ISharedObjectSymbolicLinkPolicy.Symlink( SharedObjectSymbolicLink sender, Bam.Core.ExecutionContext context, Bam.Core.PreBuiltTool tool, ConsoleApplication target) { var meta = new MakeFileBuilder.MakeFileMeta(sender); var rule = meta.AddRule(); // since this is not a referenced type, need to specify a variable name for the MakeFile var variableName = new System.Text.StringBuilder(); variableName.Append(target.GetType().Name); // this is what it's building the symlink for variableName.Append("_"); variableName.Append(sender.Macros["SymlinkUsage"].ToString()); // intended usage rule.AddTarget(sender.GeneratedPaths[SharedObjectSymbolicLink.Key], variableName: variableName.ToString()); rule.AddPrerequisite(target, C.ConsoleApplication.Key); var commandLineArgs = new Bam.Core.StringArray(); commandLineArgs.Add("-s"); commandLineArgs.Add("-f"); var command = new System.Text.StringBuilder(); command.AppendFormat("{0} {1} $(notdir $<) $@ {2}", CommandLineProcessor.Processor.StringifyTool(tool), commandLineArgs.ToString(' '), CommandLineProcessor.Processor.TerminatingArgs(tool)); rule.AddShellCommand(command.ToString()); }
ISharedObjectSymbolicLinkPolicy.Symlink( SharedObjectSymbolicLink sender, Bam.Core.ExecutionContext context, Bam.Core.PreBuiltTool tool, ConsoleApplication target) { var commandLine = new Bam.Core.StringArray(); commandLine.Add("-s"); commandLine.Add("-f"); var sourceFile = sender.CreateTokenizedString("@filename($(0))", target.GeneratedPaths[ConsoleApplication.Key]); lock (sourceFile) { if (!sourceFile.IsParsed) { sourceFile.Parse(); } } commandLine.Add(sourceFile.ToStringQuoteIfNecessary()); var destination = sender.CreateTokenizedString("@dir($(0))/$(1)", target.GeneratedPaths[ConsoleApplication.Key], target.Macros[sender.Macros["SymlinkUsage"].ToString()]); lock (destination) { if (!destination.IsParsed) { destination.Parse(); } } commandLine.Add(destination.ToStringQuoteIfNecessary()); CommandLineProcessor.Processor.Execute(context, tool, commandLine); }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (null != this.Policy) { this.Policy.CreateTarBall(this, context, this.Tool as Bam.Core.ICommandLineTool, this.InputFiles.ScriptPath, this.GeneratedPaths[Key]); } }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (null == this.Policy) { return; } this.Policy.CreateBundle(this, context, this.TheSourceModule.GeneratedPaths[CollatedObject.Key], this.GeneratedPaths[Key]); }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (null == this.Policy) { return; } this.Policy.Strip(this, context, this.sourceModule.GeneratedPaths[this.sourcePathKey], this.GeneratedPaths[Key]); }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (null == this.Policy) { return; } this.Policy.ObjCopy(this, context, this.TheSourceModule.GeneratedPaths[this.SourceKey], this.GeneratedPaths[Key]); }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (null == this.Policy) { return; } this.Policy.Collate(this, context); }
ExecuteInternal( ExecutionContext context) { foreach (var framework in this.Frameworks) { this.Policy.InstallName( this, context, framework.SourceModule.Macros["IDName"], framework.Macros["IDName"]); } }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (this.IsPrebuilt) { return; } var source = FlattenHierarchicalFileList(this.sourceModules).ToReadOnlyCollection(); var headers = FlattenHierarchicalFileList(this.headerModules).ToReadOnlyCollection(); var linked = this.linkedModules.ToReadOnlyCollection(); var executable = this.GeneratedPaths[Key]; this.Policy.Link(this, context, executable, source, headers, linked, null); }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (null == this.Policy) { return; } this.Policy.Zip( this, context, this.GeneratedPaths[Key], this.InputPath ); }
ISharedObjectSymbolicLinkPolicy.Symlink( ConsoleApplication sender, Bam.Core.ExecutionContext context, Bam.Core.PreBuiltTool tool, Bam.Core.TokenizedString linkname, Bam.Core.TokenizedString target) { var commandLine = new Bam.Core.StringArray(); commandLine.Add("-s"); commandLine.Add("-f"); commandLine.Add(sender.CreateTokenizedString("@filename($(0))", target).Parse()); commandLine.Add(sender.CreateTokenizedString("@dir($(0))/$(1)", target, linkname).Parse()); CommandLineProcessor.Processor.Execute(context, tool, commandLine); }
ExecuteInternal( Bam.Core.ExecutionContext context) { if (this.IsPrebuilt && !((this.headerModules.Count > 0) && Bam.Core.Graph.Instance.BuildModeMetaData.CanCreatePrebuiltProjectForAssociatedFiles)) { return; } var source = FlattenHierarchicalFileList(this.sourceModules).ToReadOnlyCollection(); var headers = FlattenHierarchicalFileList(this.headerModules).ToReadOnlyCollection(); // some linkers require a specific order of libraries in order to resolve symbols // so that if an existing library is later referenced, it needs to be moved later var linked = OrderLibrariesWithDecreasingDependencies(this.linkedModules); var executable = this.GeneratedPaths[Key]; this.Policy.Link(this, context, executable, source, headers, linked); }
ExecuteInternal( Bam.Core.ExecutionContext context) { var path = this.ScriptPath.Parse(); var dir = System.IO.Path.GetDirectoryName(path); if (!System.IO.Directory.Exists(dir)) { System.IO.Directory.CreateDirectory(dir); } using (var scriptWriter = new System.IO.StreamWriter(path)) { foreach (var dep in this.Files) { var filePath = dep.Key.GeneratedPaths[dep.Value].ToString(); var fileDir = System.IO.Path.GetDirectoryName(filePath); // TODO: this should probably be a setting if (this.BuildEnvironment.Platform.Includes(Bam.Core.EPlatform.OSX)) { scriptWriter.WriteLine("-C"); scriptWriter.WriteLine(fileDir); } else { scriptWriter.WriteLine("-C{0}", fileDir); } scriptWriter.WriteLine(System.IO.Path.GetFileName(filePath)); } foreach (var dep in this.Paths) { var fileDir = dep.Key.GeneratedPaths[dep.Value].ToString(); if (this.BuildEnvironment.Platform.Includes(Bam.Core.EPlatform.OSX)) { scriptWriter.WriteLine("-C"); scriptWriter.WriteLine(fileDir); } else { scriptWriter.WriteLine("-C{0}", fileDir); } scriptWriter.WriteLine("."); } } }
ExecuteInternal( ExecutionContext context) { var framework = this.CopiedFileModule.SourceModule as C.OSXFramework; if (null == framework) { throw new Bam.Core.Exception("Updating the ID name only works on an external framework"); } // TODO: although this is standard for an application bundle, should the '../Frameworks' be actually taken // from the subdirectory of the copied framework? this.CopiedFileModule.Macros["IDName"] = this.CopiedFileModule.CreateTokenizedString("@executable_path/../Frameworks/$(0)", framework.Macros["FrameworkLibraryPath"]); this.Policy.InstallName( this, context, null, this.CopiedFileModule.Macros["IDName"]); }
ISharedObjectSymbolicLinkPolicy.Symlink( ConsoleApplication sender, Bam.Core.ExecutionContext context, Bam.Core.PreBuiltTool tool, Bam.Core.TokenizedString linkname, Bam.Core.TokenizedString target) { var makeMeta = sender.MetaData as MakeFileBuilder.MakeFileMeta; var rule = makeMeta.Rules[0]; var commandLineArgs = new Bam.Core.StringArray(); commandLineArgs.Add("-s"); commandLineArgs.Add("-f"); rule.AddShellCommand(System.String.Format(@"{0} {1} $(notdir $@) $(dir $@)/{2} {3}", CommandLineProcessor.Processor.StringifyTool(tool), commandLineArgs.ToString(' '), linkname.Parse(), CommandLineProcessor.Processor.TerminatingArgs(tool))); }
ILinkingPolicy.Link( ConsoleApplication sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executablePath, System.Collections.ObjectModel.ReadOnlyCollection<Bam.Core.Module> objectFiles, System.Collections.ObjectModel.ReadOnlyCollection<Bam.Core.Module> headers, System.Collections.ObjectModel.ReadOnlyCollection<Bam.Core.Module> libraries, System.Collections.ObjectModel.ReadOnlyCollection<Bam.Core.Module> frameworks) { // any libraries added prior to here, need to be moved to the end // they are external dependencies, and thus all built modules (to be added now) may have // a dependency on them (and not vice versa) var linker = sender.Settings as C.ICommonLinkerSettings; var externalLibs = linker.Libraries; linker.Libraries = new Bam.Core.StringArray(); foreach (var library in libraries) { (sender.Tool as C.LinkerTool).ProcessLibraryDependency(sender as CModule, library as CModule); } linker.Libraries.AddRange(externalLibs); var executableDir = System.IO.Path.GetDirectoryName(executablePath.ToString()); if (!System.IO.Directory.Exists(executableDir)) { System.IO.Directory.CreateDirectory(executableDir); } var commandLine = new Bam.Core.StringArray(); // first object files foreach (var input in objectFiles) { commandLine.Add(input.GeneratedPaths[C.ObjectFile.Key].ToString()); } // then all options (sender.Settings as CommandLineProcessor.IConvertToCommandLine).Convert(commandLine); CommandLineProcessor.Processor.Execute(context, sender.Tool as Bam.Core.ICommandLineTool, commandLine); }
Run() { Log.Detail("Running build"); // TODO: should the rank collections be sorted, so that modules with fewest dependencies are first? var graph = Graph.Instance; var metaDataType = graph.BuildModeMetaData.GetType(); var useEvaluation = CheckIfModulesNeedRebuilding(metaDataType); var explainRebuild = CommandLineProcessor.Evaluate(new Options.ExplainBuildReason()); var immediateOutput = CommandLineProcessor.Evaluate(new Options.ImmediateOutput()); ExecutePreBuild(metaDataType); if (!System.IO.Directory.Exists(graph.BuildRoot)) { System.IO.Directory.CreateDirectory(graph.BuildRoot); } var threadCount = CommandLineProcessor.Evaluate(new Options.MultiThreaded()); if (0 == threadCount) { threadCount = System.Environment.ProcessorCount; } System.Exception abortException = null; if (threadCount > 1) { var cancellationSource = new System.Threading.CancellationTokenSource(); var cancellationToken = cancellationSource.Token; // LongRunning is absolutely necessary in order to achieve paralleism var creationOpts = System.Threading.Tasks.TaskCreationOptions.LongRunning; var continuationOpts = System.Threading.Tasks.TaskContinuationOptions.LongRunning; var scheduler = new LimitedConcurrencyLevelTaskScheduler(threadCount); var factory = new System.Threading.Tasks.TaskFactory( cancellationToken, creationOpts, continuationOpts, scheduler); var tasks = new Array<System.Threading.Tasks.Task>(); foreach (var rank in graph.Reverse()) { foreach (var module in rank) { var context = new ExecutionContext(useEvaluation, explainRebuild, immediateOutput); var task = factory.StartNew(() => { if (cancellationToken.IsCancellationRequested) { return; } var depTasks = new Array<System.Threading.Tasks.Task>(); foreach (var dep in module.Dependents) { if (null == dep.ExecutionTask) { continue; } depTasks.Add(dep.ExecutionTask); } foreach (var dep in module.Requirements) { if (null == dep.ExecutionTask) { continue; } depTasks.Add(dep.ExecutionTask); } System.Threading.Tasks.Task.WaitAll(depTasks.ToArray()); if (cancellationToken.IsCancellationRequested) { return; } try { (module as IModuleExecution).Execute(context); } catch (Exception ex) { abortException = ex; cancellationSource.Cancel(); } finally { if (context.OutputStringBuilder != null && context.OutputStringBuilder.Length > 0) { Log.Info(context.OutputStringBuilder.ToString()); } if (context.ErrorStringBuilder != null && context.ErrorStringBuilder.Length > 0) { Log.Info(context.ErrorStringBuilder.ToString()); } } }); tasks.Add(task); module.ExecutionTask = task; } } try { System.Threading.Tasks.Task.WaitAll(tasks.ToArray()); } catch (System.AggregateException exception) { if (!(exception.InnerException is System.Threading.Tasks.TaskCanceledException)) { throw new Exception(exception, "Error during threaded build"); } } } else { foreach (var rank in graph.Reverse()) { if (null != abortException) { break; } foreach (IModuleExecution module in rank) { var context = new ExecutionContext(useEvaluation, explainRebuild, immediateOutput); try { module.Execute(context); } catch (Exception ex) { abortException = ex; break; } finally { if (context.OutputStringBuilder != null && context.OutputStringBuilder.Length > 0) { Log.Info(context.OutputStringBuilder.ToString()); } if (context.ErrorStringBuilder != null && context.ErrorStringBuilder.Length > 0) { Log.Info(context.ErrorStringBuilder.ToString()); } } } } } if (null != abortException) { throw new Exception(abortException, "Error during {0}threaded build", (threadCount > 1) ? string.Empty : "non-"); } ExecutePostBuild(metaDataType); }
ILinkingPolicy.Link( ConsoleApplication sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executablePath, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> objectFiles, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> headers, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> libraries, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> frameworks) { // any libraries added prior to here, need to be moved to the end // they are external dependencies, and thus all built modules (to be added now) may have // a dependency on them (and not vice versa) var linker = sender.Settings as C.ICommonLinkerSettings; var externalLibs = linker.Libraries; linker.Libraries = new Bam.Core.StringArray(); foreach (var library in libraries) { (sender.Tool as C.LinkerTool).ProcessLibraryDependency(sender as CModule, library as CModule); } linker.Libraries.AddRange(externalLibs); var commandLineArgs = new Bam.Core.StringArray(); (sender.Settings as CommandLineProcessor.IConvertToCommandLine).Convert(commandLineArgs); var meta = new MakeFileBuilder.MakeFileMeta(sender); var rule = meta.AddRule(); rule.AddTarget(executablePath); foreach (var module in objectFiles) { rule.AddPrerequisite(module, C.ObjectFile.Key); } foreach (var module in libraries) { if (module is StaticLibrary) { rule.AddPrerequisite(module, C.StaticLibrary.Key); } else if (module is IDynamicLibrary) { if (module.BuildEnvironment.Platform.Includes(Bam.Core.EPlatform.Windows)) { rule.AddPrerequisite(module, C.DynamicLibrary.ImportLibraryKey); } else { rule.AddPrerequisite(module, C.DynamicLibrary.Key); } } else if (module is CSDKModule) { continue; } else if (module is OSXFramework) { continue; } else { throw new Bam.Core.Exception("Unknown module library type: {0}", module.GetType()); } } var tool = sender.Tool as Bam.Core.ICommandLineTool; var commands = new System.Text.StringBuilder(); commands.AppendFormat("{0} $^ {1} {2}", CommandLineProcessor.Processor.StringifyTool(tool), commandLineArgs.ToString(' '), CommandLineProcessor.Processor.TerminatingArgs(tool)); rule.AddShellCommand(commands.ToString()); var executableDir = System.IO.Path.GetDirectoryName(executablePath.ToString()); meta.CommonMetaData.Directories.AddUnique(executableDir); meta.CommonMetaData.ExtendEnvironmentVariables(tool.EnvironmentVariables); }
ExecuteInternal( ExecutionContext context);
ExecuteInternal( Bam.Core.ExecutionContext context) { }
ExecuteInternal( ExecutionContext context) { this.Policy.Change(this, context, this.Source, this.NewRPath); }
ILinkingPolicy.Link( ConsoleApplication sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executablePath, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> objectFiles, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> headers, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> libraries) { if (0 == objectFiles.Count) { if (headers.Count > 0) { this.CreateHeaderOnlyLibrary(sender, headers); } return; } var solution = Bam.Core.Graph.Instance.MetaData as VSSolutionBuilder.VSSolution; var project = solution.EnsureProjectExists(sender); var config = project.GetConfiguration(sender); config.SetType((sender is IDynamicLibrary) ? VSSolutionBuilder.VSProjectConfiguration.EType.DynamicLibrary : VSSolutionBuilder.VSProjectConfiguration.EType.Application); config.SetOutputPath(executablePath); config.EnableIntermediatePath(); foreach (var header in headers) { config.AddHeaderFile(header as HeaderFile); } var compilerGroup = config.GetSettingsGroup(VSSolutionBuilder.VSSettingsGroup.ESettingsGroup.Compiler); var realObjectFiles = objectFiles.Where(item => !((item is WinResource) || (item is AssembledObjectFile))); if (realObjectFiles.Any()) { var vsConvertParameterTypes = new Bam.Core.TypeArray { typeof(Bam.Core.Module), typeof(VSSolutionBuilder.VSSettingsGroup), typeof(string) }; var sharedSettings = C.SettingsBase.SharedSettings( realObjectFiles, typeof(VisualCCommon.VSSolutionImplementation), typeof(VisualStudioProcessor.IConvertToProject), vsConvertParameterTypes); (sharedSettings as VisualStudioProcessor.IConvertToProject).Convert(sender, compilerGroup); foreach (var objFile in realObjectFiles) { var deltaSettings = (objFile.Settings as C.SettingsBase).CreateDeltaSettings(sharedSettings, objFile); config.AddSourceFile(objFile, deltaSettings); } // now handle the other object file types // TODO: if there were many resource files, this could also have a common settings group? Not sure if VS supports this // and it's not as likely to have many resource files, as it would have many source files var resourceObjectFiles = objectFiles.Where(item => item is WinResource); foreach (var resObj in resourceObjectFiles) { config.AddResourceFile(resObj as WinResource, resObj.Settings); } var assembledObjectFiles = objectFiles.Where(item => item is AssembledObjectFile); foreach (var asmObj in assembledObjectFiles) { config.AddAssemblyFile(asmObj as AssembledObjectFile); } } else { (objectFiles[0].Settings as VisualStudioProcessor.IConvertToProject).Convert(sender, compilerGroup); foreach (var objFile in objectFiles) { config.AddSourceFile(objFile, null); } } foreach (var input in libraries) { if ((null != input.MetaData) && VSSolutionBuilder.VSProject.IsBuildable(input)) { if ((input is C.StaticLibrary) || (input is C.IDynamicLibrary)) { config.LinkAgainstProject(solution.EnsureProjectExists(input)); } else if ((input is C.CSDKModule) || (input is C.HeaderLibrary)) { continue; } else if (input is OSXFramework) { throw new Bam.Core.Exception("Frameworks are not supported on Windows: {0}", input.ToString()); } else { throw new Bam.Core.Exception("Don't know how to handle this buildable library module, {0}", input.ToString()); } } else { if (input is C.StaticLibrary) { // TODO: probably a simplification of the DLL codepath throw new System.NotImplementedException(); } else if (input is C.IDynamicLibrary) { // TODO: this might be able to shift out of the conditional (sender.Tool as C.LinkerTool).ProcessLibraryDependency(sender as CModule, input as CModule); } else if ((input is C.CSDKModule) || (input is C.HeaderLibrary)) { continue; } else if (input is OSXFramework) { throw new Bam.Core.Exception("Frameworks are not supported on Windows: {0}", input.ToString()); } else { throw new Bam.Core.Exception("Don't know how to handle this prebuilt library module, {0}", input.ToString()); } } } var linkerGroup = config.GetSettingsGroup(VSSolutionBuilder.VSSettingsGroup.ESettingsGroup.Linker); (sender.Settings as VisualStudioProcessor.IConvertToProject).Convert(sender, linkerGroup); // order only dependencies foreach (var required in sender.Requirements) { if (null == required.MetaData) { continue; } var requiredProject = required.MetaData as VSSolutionBuilder.VSProject; if (null != requiredProject) { config.RequiresProject(requiredProject); } } // any non-C module projects should be order-only dependencies foreach (var dependent in sender.Dependents) { if (null == dependent.MetaData) { continue; } if (dependent is C.CModule) { continue; } var dependentProject = dependent.MetaData as VSSolutionBuilder.VSProject; if (null != dependentProject) { config.RequiresProject(dependentProject); } } }
ExecuteInternal( Bam.Core.ExecutionContext context) { this.Policy.Collate(this, context); }
ILinkingPolicy.Link( ConsoleApplication sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executablePath, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> objectFiles, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> headers, System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> libraries) { // any libraries added prior to here, need to be moved to the end // they are external dependencies, and thus all built modules (to be added now) may have // a dependency on them (and not vice versa) var linker = sender.Settings as C.ICommonLinkerSettings; var externalLibs = linker.Libraries; linker.Libraries = new Bam.Core.StringArray(); foreach (var library in libraries) { (sender.Tool as C.LinkerTool).ProcessLibraryDependency(sender as CModule, library as CModule); } linker.Libraries.AddRange(externalLibs); var commandLineArgs = new Bam.Core.StringArray(); (sender.Settings as CommandLineProcessor.IConvertToCommandLine).Convert(commandLineArgs); var meta = new MakeFileBuilder.MakeFileMeta(sender); var rule = meta.AddRule(); rule.AddTarget(executablePath); string objExt = null; // try to get the object file extension from a compiled source file foreach (var module in objectFiles) { if (null == objExt) { objExt = module.Tool.Macros["objext"].ToString(); } if (!(module as C.ObjectFileBase).PerformCompilation) { continue; } rule.AddPrerequisite(module, C.ObjectFile.Key); } foreach (var module in libraries) { if (module is StaticLibrary) { rule.AddPrerequisite(module, C.StaticLibrary.Key); } else if (module is IDynamicLibrary) { var dynLib = module as IDynamicLibrary; if (dynLib.LinkerNameSymbolicLink != null) { var linkerNameSymLink = dynLib.LinkerNameSymbolicLink; rule.AddPrerequisite(linkerNameSymLink, C.SharedObjectSymbolicLink.Key); } else { rule.AddPrerequisite(module, C.DynamicLibrary.Key); } } else if (module is CSDKModule) { continue; } else if (module is OSXFramework) { continue; } else if (module is HeaderLibrary) { continue; } else { throw new Bam.Core.Exception("Unknown module library type: {0}", module.GetType()); } } var tool = sender.Tool as Bam.Core.ICommandLineTool; var commands = new System.Text.StringBuilder(); // if there were no object files, you probably intended to use all prerequisites anyway var filter = (null != objExt) ? System.String.Format("$(filter %{0},$^)", objExt) : "$^"; commands.AppendFormat("{0} {1} {2} {3}", CommandLineProcessor.Processor.StringifyTool(tool), filter, commandLineArgs.ToString(' '), CommandLineProcessor.Processor.TerminatingArgs(tool)); rule.AddShellCommand(commands.ToString()); var executableDir = System.IO.Path.GetDirectoryName(executablePath.ToString()); meta.CommonMetaData.AddDirectory(executableDir); meta.CommonMetaData.ExtendEnvironmentVariables(tool.EnvironmentVariables); }