CreateCollatedSymbolicLink( Bam.Core.Module sourceModule, Bam.Core.TokenizedString sourcePath, CollatedFile reference, Bam.Core.TokenizedString subDirectory) { if (null == reference) { throw new Bam.Core.Exception("Collating a symbolic link requires a collated file as reference"); } var copySymlinkModule = Bam.Core.Module.Create <CollatedSymbolicLink>(preInitCallback: module => { module.Macros["CopyDir"] = GenerateSymbolicLinkCopyDestination( module, reference.GeneratedPaths[CollatedObject.Key], subDirectory); }); this.Requires(copySymlinkModule); copySymlinkModule.SourceModule = sourceModule; copySymlinkModule.SourcePath = sourcePath; copySymlinkModule.Reference = reference; copySymlinkModule.SubDirectory = subDirectory; return(copySymlinkModule); }
Include <DependentModule>( Bam.Core.PathKey key, string subDirectory, CollatedObject reference) where DependentModule : Bam.Core.Module, new() { var dependent = Bam.Core.Graph.Instance.FindReferencedModule <DependentModule>(); this.Requires(dependent); this.Requires(dependent.Tool); var strippedInitialRef = this.RefMap[reference]; var subDir = Bam.Core.TokenizedString.CreateVerbatim(subDirectory); var copyFileModule = Bam.Core.Module.Create <CollatedFile>(preInitCallback: module => { Bam.Core.TokenizedString referenceFilePath = strippedInitialRef.GeneratedPaths[this.ReferenceKey]; this.RegisterGeneratedFile(Key, module.CreateTokenizedString("@dir($(0))", dependent.GeneratedPaths[key])); module.Macros["CopyDir"] = Collation.GenerateFileCopyDestination( module, referenceFilePath, subDir, this.GeneratedPaths[Key]); }); this.Requires(copyFileModule); copyFileModule.SourceModule = dependent; copyFileModule.SourcePath = dependent.GeneratedPaths[key]; copyFileModule.Reference = strippedInitialRef as CollatedFile; copyFileModule.SubDirectory = subDir; return(copyFileModule); }
CreateCollatedSymbolicLink( Bam.Core.Module sourceModule, Bam.Core.TokenizedString sourcePath, CollatedFile reference, Bam.Core.TokenizedString subDirectory) { if (null == reference) { throw new Bam.Core.Exception("Collating a symbolic link requires a collated file as reference"); } var copySymlinkModule = Bam.Core.Module.Create <CollatedSymbolicLink>(preInitCallback: module => { module.Macros["CopyDir"] = GenerateSymbolicLinkCopyDestination( module, reference.GeneratedPaths[CollatedObject.Key], subDirectory); }); this.Requires(copySymlinkModule); if (null != reference.SourceModule && null != sourceModule && reference.SourceModule != sourceModule) // in case a different key from the same module is published { // ensuring that non-Native builders set up order-only dependencies for additional published only modules reference.SourceModule.Requires(sourceModule); } copySymlinkModule.SourceModule = sourceModule; copySymlinkModule.SourcePath = sourcePath; copySymlinkModule.Reference = reference; copySymlinkModule.SubDirectory = subDirectory; return(copySymlinkModule); }
CreateCollatedFile( Bam.Core.Module sourceModule, Bam.Core.TokenizedString sourcePath, CollatedFile reference, Bam.Core.TokenizedString subDirectory) { var copyFileModule = Bam.Core.Module.Create <CollatedFile>(preInitCallback: module => { Bam.Core.TokenizedString referenceFilePath = null; if (null != reference) { referenceFilePath = reference.GeneratedPaths[CollatedObject.Key]; } else { if (!this.GeneratedPaths.ContainsKey(Key)) { this.RegisterGeneratedFile(Key, module.CreateTokenizedString("@dir($(0))", sourcePath)); } } module.Macros["CopyDir"] = GenerateFileCopyDestination( module, referenceFilePath, subDirectory, this.GeneratedPaths[Key]); }); this.Requires(copyFileModule); copyFileModule.SourceModule = sourceModule; copyFileModule.SourcePath = sourcePath; copyFileModule.Reference = reference; copyFileModule.SubDirectory = subDirectory; return(copyFileModule); }
IncludeDirectory( Bam.Core.TokenizedString parameterizedPath, string subdir, CollatedFile reference) { return(this.CreateCollatedDirectory(null, parameterizedPath, reference, Bam.Core.TokenizedString.CreateVerbatim(subdir))); }
GenerateFileCopyDestination( Bam.Core.Module module, Bam.Core.TokenizedString referenceFilePath, Bam.Core.TokenizedString subDirectory, Bam.Core.TokenizedString unReferencedRoot) { if (referenceFilePath != null) { if (null != subDirectory) { return(module.CreateTokenizedString("@normalize(@dir($(0))/$(1)/)", referenceFilePath, subDirectory)); } else { return(module.CreateTokenizedString("@normalize(@dir($(0))/)", referenceFilePath)); } } else { if (null != subDirectory) { return(module.CreateTokenizedString("@normalize($(0)/$(1)/)", unReferencedRoot, subDirectory)); } else { return(module.CreateTokenizedString("@normalize($(0)/)", unReferencedRoot)); } } }
CreateInternal( string tokenizedString, Module macroSource, bool verbatim, TokenizedStringArray positionalTokens, EFlags flags) { if (null == tokenizedString) { return(null); } // strings can be created during the multithreaded phase lock (Cache) { if (0 == (flags & EFlags.NoCache)) { var search = Cache.Where((ts) => { // first check the simple states for equivalence if (ts.OriginalString == tokenizedString && ts.ModuleWithMacros == macroSource && ts.Verbatim == verbatim) { // and then check the positional tokens, if they exist var samePosTokenCount = ((null != positionalTokens) && (positionalTokens.Count() == ts.PositionalTokens.Count())) || ((null == positionalTokens) && (0 == ts.PositionalTokens.Count())); if (!samePosTokenCount) { return(false); } for (int i = 0; i < ts.PositionalTokens.Count(); ++i) { // because positional tokens are TokenizedStrings, they will refer to the same object if (ts.PositionalTokens[i] != positionalTokens[i]) { return(false); } } return(true); } else { return(false); } }); var foundTS = search.FirstOrDefault(); if (null != foundTS) { ++foundTS.RefCount; return(foundTS); } } var newTS = new TokenizedString(tokenizedString, macroSource, verbatim, positionalTokens, flags); Cache.Add(newTS); return(newTS); } }
Aliased( TokenizedString alias) { if (this.IsAliased) { throw new Exception("TokenizedString is already aliased"); } this.Alias = alias; ++alias.RefCount; }
RegisterGeneratedFile( PathKey key, TokenizedString path) { if (this.GeneratedPaths.ContainsKey(key)) { Log.DebugMessage("Key '{0}' already exists", key); return; } this.GeneratedPaths.Add(key, path); }
CreateTokenizedString( string format, params TokenizedString[] argv) { if (0 == argv.Length) { return(TokenizedString.Create(format, this)); } var positionalTokens = new TokenizedStringArray(argv); return(TokenizedString.Create(format, this, positionalTokens)); }
IncludeFile( Bam.Core.TokenizedString parameterizedFilePath, string subdir) { var copyFileModule = this.CreateCollatedFile( this, parameterizedFilePath, null, Bam.Core.TokenizedString.CreateVerbatim(subdir)); return(copyFileModule); }
SetPublishingDirectory( string original, params Bam.Core.TokenizedString[] positional) { if (null == this.publishingDirectory) { this.publishingDirectory = this.CreateTokenizedString(original, positional); } else { this.publishingDirectory.Set(original, positional); } }
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); }
FindReferencedModule <T>() where T : Module, new() { if (null == this.BuildEnvironmentInternal) { var message = new System.Text.StringBuilder(); message.AppendLine("Unable to find a module either within a patch or after the build has started."); message.AppendLine("If called within a patch function, please modify the calling code to invoke this call within the module's Init method."); message.AppendLine("If it must called elsewhere, please use the overloaded version accepting an Environment argument."); throw new Exception(message.ToString()); } var referencedModules = this.ReferencedModules[this.BuildEnvironmentInternal]; var matchedModule = referencedModules.FirstOrDefault(item => item.GetType() == typeof(T)); if (null != matchedModule) { return(matchedModule as T); } this.CommonModuleType.Push(typeof(T)); try { var newModule = Module.Create <T>(preInitCallback: module => { if (null != module) { referencedModules.Add(module); } }); return(newModule); } catch (UnableToBuildModuleException) { // remove the failed to create module from the referenced list // and also any modules and strings created in its Init function, potentially // of child module types var moduleTypeToRemove = this.CommonModuleType.Peek(); TokenizedString.RemoveEncapsulatedStrings(moduleTypeToRemove); Module.RemoveEncapsulatedModules(moduleTypeToRemove); referencedModules.Remove(referencedModules.First(item => item.GetType() == typeof(T))); var moduleEnvList = this.Modules[this.BuildEnvironmentInternal]; moduleEnvList.Remove(moduleEnvList.First(item => item.GetType() == typeof(T))); throw; } finally { this.CommonModuleType.Pop(); } }
GenerateSymbolicLinkCopyDestination( Bam.Core.Module module, Bam.Core.TokenizedString referenceFilePath, Bam.Core.TokenizedString subDirectory) { if (null != subDirectory) { return(module.CreateTokenizedString("@normalize(@dir($(0))/$(1)/)", referenceFilePath, subDirectory)); } else { return(module.CreateTokenizedString("@normalize(@dir($(0))/)", referenceFilePath)); } }
AssignLinkTarget( TokenizedString path = null) { #if __MonoCS__ if (path == null) { var symlink = new Mono.Unix.UnixSymbolicLinkInfo(this.SourcePath.Parse()); this.Macros["LinkTarget"] = Bam.Core.TokenizedString.CreateVerbatim(symlink.ContentsPath); } else { this.Macros["LinkTarget"] = path; } #else throw new System.NotSupportedException("Unable to get symbolic link target on Windows"); #endif }
CreateCollatedFile( Bam.Core.Module sourceModule, Bam.Core.TokenizedString sourcePath, CollatedFile reference, Bam.Core.TokenizedString subDirectory) { var copyFileModule = Bam.Core.Module.Create <CollatedFile>(preInitCallback: module => { Bam.Core.TokenizedString referenceFilePath = null; if (null != reference) { referenceFilePath = reference.GeneratedPaths[CollatedObject.Key]; } else { if (!this.GeneratedPaths.ContainsKey(Key)) { this.RegisterGeneratedFile(Key, module.CreateTokenizedString("@dir($(0))", sourcePath)); } } module.Macros["CopyDir"] = GenerateFileCopyDestination( module, referenceFilePath, subDirectory, this.GeneratedPaths[Key]); }); this.Requires(copyFileModule); if (null != reference && null != reference.SourceModule && null != sourceModule && reference.SourceModule != sourceModule) // in case a different key (e.g. import library) is published from the same module { // ensuring that non-Native builders set up order-only dependencies for additional published only modules reference.SourceModule.Requires(sourceModule); } copyFileModule.SourceModule = sourceModule; copyFileModule.SourcePath = sourcePath; copyFileModule.Reference = reference; copyFileModule.SubDirectory = subDirectory; return(copyFileModule); }
Init( Bam.Core.Module parent) { base.Init(parent); if (this.BuildEnvironment.Platform.Includes(Bam.Core.EPlatform.Windows)) { this.Tool = Bam.Core.Graph.Instance.FindReferencedModule <ZipWin>(); } else { this.Tool = Bam.Core.Graph.Instance.FindReferencedModule <ZipPosix>(); } this.RegisterGeneratedFile( Key, this.CreateTokenizedString("$(packagebuilddir)/$(moduleoutputdir)/$(zipoutputbasename).zip") ); this.InputPath = this.Macros["pathtozip"]; }
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))); }
CopyPDB( CollatedObject collatedFile, System.Collections.Generic.Dictionary <CollatedObject, Bam.Core.Module> referenceMap) { var copyPDBModule = Bam.Core.Module.Create <CollatedFile>(preInitCallback: module => { Bam.Core.TokenizedString referenceFilePath = null; if (collatedFile.Reference != null) { if (!referenceMap.ContainsKey(collatedFile.Reference)) { throw new Bam.Core.Exception("Unable to find CollatedFile reference to {0} in the reference map", collatedFile.Reference.SourceModule.ToString()); } var newRef = referenceMap[collatedFile.Reference]; referenceFilePath = newRef.GeneratedPaths[CollatedObject.Key]; } module.Macros["CopyDir"] = Collation.GenerateFileCopyDestination( this, referenceFilePath, collatedFile.SubDirectory, this.GeneratedPaths[Key]); }); this.DependsOn(copyPDBModule); copyPDBModule.SourceModule = collatedFile.SourceModule; // TODO: there has not been a check whether this is a valid path or not (i.e. were debug symbols enabled for link?) copyPDBModule.SourcePath = collatedFile.SourceModule.GeneratedPaths[C.ConsoleApplication.PDBKey]; copyPDBModule.SubDirectory = collatedFile.SubDirectory; // since PDBs aren't guaranteed to exist as it depends on build settings, allow missing files to go through copyPDBModule.FailWhenSourceDoesNotExist = false; if (collatedFile.Reference == null) { referenceMap.Add(collatedFile, copyPDBModule); } }
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); }
IncludeFile( Bam.Core.TokenizedString parameterizedFilePath, string subdir, CollatedFile reference, bool isExecutable = false) { var copyFileModule = this.CreateCollatedFile( null, parameterizedFilePath, reference, Bam.Core.TokenizedString.CreateVerbatim(subdir)); if (isExecutable) { if (this.IsReferenceAWindowedApp(reference)) { this.AddOSXChangeIDNameForBinary(copyFileModule); } } return(copyFileModule); }
GenerateDirectoryCopyDestination( Bam.Core.Module module, Bam.Core.TokenizedString referenceFilePath, Bam.Core.TokenizedString subDirectory, Bam.Core.TokenizedString sourcePath) { // Windows XCOPY requires the directory name to be added to the destination, while Posix cp does not if (null != subDirectory) { if (module.BuildEnvironment.Platform.Includes(Bam.Core.EPlatform.Windows)) { return(module.CreateTokenizedString("@normalize(@dir($(0))/$(1)/@ifnotempty($(CopiedFilename),$(CopiedFilename),@filename($(2)))/)", referenceFilePath, subDirectory, sourcePath)); } else { return(module.CreateTokenizedString("@normalize(@dir($(0))/$(1)/@ifnotempty($(CopiedFilename),$(CopiedFilename),))", referenceFilePath, subDirectory)); } } else { if (module.BuildEnvironment.Platform.Includes(Bam.Core.EPlatform.Windows)) { return(module.CreateTokenizedString("@normalize(@dir($(0))/@ifnotempty($(CopiedFilename),$(CopiedFilename),@filename($(1)))/)", referenceFilePath, sourcePath)); } else { return(module.CreateTokenizedString("@normalize(@dir($(0))/@ifnotempty($(CopiedFilename),$(CopiedFilename),))", referenceFilePath)); } } }
CreateCollatedDirectory( Bam.Core.Module sourceModule, Bam.Core.TokenizedString sourcePath, CollatedFile reference, Bam.Core.TokenizedString subDirectory) { if (null == reference) { throw new Bam.Core.Exception("Collating a directory requires a collated file as reference"); } // copying a directory must not have a trailing slash on the source directory path // otherwise the leafname ends up being duplicated var fixedSourcePath = this.CreateTokenizedString("@removetrailingseparator($(0))", sourcePath); var copyDirectoryModule = Bam.Core.Module.Create <CollatedDirectory>(preInitCallback: module => { module.Macros["CopyDir"] = GenerateDirectoryCopyDestination( module, reference.GeneratedPaths[CollatedObject.Key], subDirectory, fixedSourcePath); }); this.Requires(copyDirectoryModule); if (null != reference.SourceModule && null != sourceModule && reference.SourceModule != sourceModule) // in case a different key from the same module is published { // ensuring that non-Native builders set up order-only dependencies for additional published only modules reference.SourceModule.Requires(sourceModule); } copyDirectoryModule.SourceModule = sourceModule; copyDirectoryModule.SourcePath = fixedSourcePath; copyDirectoryModule.Reference = reference; copyDirectoryModule.SubDirectory = subDirectory; return(copyDirectoryModule); }
CloneFile( CollatedObject collatedFile, System.Collections.Generic.Dictionary <CollatedObject, Bam.Core.Module> referenceMap) { var clonedFile = Bam.Core.Module.Create <CollatedFile>(preInitCallback: module => { Bam.Core.TokenizedString referenceFilePath = null; if (collatedFile.Reference != null) { if (!referenceMap.ContainsKey(collatedFile.Reference)) { throw new Bam.Core.Exception("Unable to find CollatedFile reference to {0} in the reference map", collatedFile.Reference.SourceModule.ToString()); } var newRef = referenceMap[collatedFile.Reference]; // the PathKey depends on whether the reference came straight as a clone, or after being stripped referenceFilePath = newRef.GeneratedPaths[this.ReferenceKey]; } module.Macros["CopyDir"] = Collation.GenerateFileCopyDestination( this, referenceFilePath, collatedFile.SubDirectory, this.GeneratedPaths[Key]); }); this.DependsOn(clonedFile); clonedFile.SourceModule = collatedFile; clonedFile.SourcePath = collatedFile.GeneratedPaths[CollatedObject.Key]; clonedFile.SubDirectory = collatedFile.SubDirectory; if (collatedFile.Reference == null) { referenceMap.Add(collatedFile, clonedFile); this.ReferenceKey = CollatedObject.Key; } }
Display() { Log.Info("\nBuildAMation Statistics"); Log.Info("Memory Usage"); Log.Info("Peak working set size : {0:N2}MB", BytesToMegaBytes(System.Diagnostics.Process.GetCurrentProcess().PeakWorkingSet64)); Log.Info("Peak virtual size : {0:N2}MB", BytesToMegaBytes(System.Diagnostics.Process.GetCurrentProcess().PeakVirtualMemorySize64)); Log.Info("GC total memory : {0:N2}MB (after GC, {1:N2}MB)", BytesToMegaBytes(System.GC.GetTotalMemory(false)), BytesToMegaBytes(System.GC.GetTotalMemory(true))); Log.Info("\nObject counts"); Log.Info("Tokenized strings : {0} ({1} unshared)", TokenizedString.Count, TokenizedString.UnsharedCount); TokenizedString.DumpCache(); Log.Info("Modules : {0}", Module.Count); Log.Info("\nModule creation times"); foreach (var env in Graph.Instance.BuildEnvironments) { var encapsulatingModules = Graph.Instance.EncapsulatingModules(env); Log.Info("Configuration {0} has {1} named/encapsulating modules, with the following creation times (ms):", env.Configuration.ToString(), encapsulatingModules.Count); foreach (var module in encapsulatingModules.OrderByDescending(item => item.CreationTime)) { Log.Info("\t{0}\t{1}", module, module.CreationTime.TotalMilliseconds); } } TimingProfileUtilities.DumpProfiles(); }
CreateInternal( string tokenizedString, Module macroSource, bool verbatim, TokenizedStringArray positionalTokens, EFlags flags) { if (null == tokenizedString) { return null; } // strings can be created during the multithreaded phase lock (Cache) { if (0 == (flags & EFlags.NoCache)) { var search = Cache.Where((ts) => { // first check the simple states for equivalence if (ts.OriginalString == tokenizedString && ts.ModuleWithMacros == macroSource && ts.Verbatim == verbatim) { // and then check the positional tokens, if they exist var samePosTokenCount = ((null != positionalTokens) && (positionalTokens.Count() == ts.PositionalTokens.Count())) || ((null == positionalTokens) && (0 == ts.PositionalTokens.Count())); if (!samePosTokenCount) { return false; } for (int i = 0; i < ts.PositionalTokens.Count(); ++i) { // because positional tokens are TokenizedStrings, they will refer to the same object if (ts.PositionalTokens[i] != positionalTokens[i]) { return false; } } return true; } else { return false; } }); var foundTS = search.FirstOrDefault(); if (null != foundTS) { ++foundTS.RefCount; return foundTS; } } var newTS = new TokenizedString(tokenizedString, macroSource, verbatim, positionalTokens, flags); Cache.Add(newTS); return newTS; } }
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); }
public CollatedObject() { this.RealSourcePath = this.MakePlaceholderPath(); this.Macros.Add("CopiedFilename", this.MakePlaceholderPath()); }
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); }
MakePlaceholderPath() { return(TokenizedString.CreateUncached(string.Empty, this)); }
Aliased( TokenizedString alias) { if (this.IsAliased) { throw new Exception("TokenizedString is already aliased"); } this.Alias = alias; ++alias.RefCount; }
public CollatedObject() { this.RealSourcePath = this.MakePlaceholderPath(); this.Macros.Add("CopiedFilename", this.MakePlaceholderPath()); }
Execute( Array <Environment> environments, System.Reflection.Assembly packageAssembly = null) { PrintVersion(); if (0 == environments.Count) { throw new Exception("No build configurations were specified"); } var graph = Graph.Instance; if (null != packageAssembly) { PackageUtilities.IdentifyAllPackages(); graph.ScriptAssembly = packageAssembly; graph.ScriptAssemblyPathname = packageAssembly.Location; } else { PackageUtilities.CompilePackageAssembly(); PackageUtilities.LoadPackageAssembly(); } var packageMetaDataProfile = new TimeProfile(ETimingProfiles.PackageMetaData); packageMetaDataProfile.StartProfile(); // validate that there is at most one local policy // if test mode is enabled, then the '.tests' sub-namespaces are also checked { var localPolicies = graph.ScriptAssembly.GetTypes().Where(t => typeof(ISitePolicy).IsAssignableFrom(t)); var includeTests = CommandLineProcessor.Evaluate(new Options.UseTests()); if (!includeTests) { localPolicies = localPolicies.Where(item => !item.Namespace.EndsWith(".tests")); } var numLocalPolicies = localPolicies.Count(); if (numLocalPolicies > 0) { if (numLocalPolicies > 1) { var message = new System.Text.StringBuilder(); message.AppendLine("Too many site policies exist in the package assembly:"); foreach (var policy in localPolicies) { message.AppendFormat("\t{0}", policy.ToString()); message.AppendLine(); } throw new Exception(message.ToString()); } Settings.LocalPolicy = System.Activator.CreateInstance(localPolicies.First()) as ISitePolicy; } } // find a product definition { var productDefinitions = graph.ScriptAssembly.GetTypes().Where(t => typeof(IProductDefinition).IsAssignableFrom(t)); var numProductDefinitions = productDefinitions.Count(); if (numProductDefinitions > 0) { if (numProductDefinitions > 1) { var message = new System.Text.StringBuilder(); message.AppendLine("Too many product definitions exist in the package assembly:"); foreach (var def in productDefinitions) { message.AppendFormat("\t{0}", def.ToString()); message.AppendLine(); } throw new Exception(message.ToString()); } graph.ProductDefinition = System.Activator.CreateInstance(productDefinitions.First()) as IProductDefinition; } } // get the metadata from the build mode package var metaName = System.String.Format("{0}Builder.{0}Meta", graph.Mode); var metaDataType = graph.ScriptAssembly.GetType(metaName); if (null == metaDataType) { throw new Exception("No build mode {0} meta data type {1}", graph.Mode, metaName); } if (!typeof(IBuildModeMetaData).IsAssignableFrom(metaDataType)) { throw new Exception("Build mode package meta data type {0} does not implement the interface {1}", metaDataType.ToString(), typeof(IBuildModeMetaData).ToString()); } graph.BuildModeMetaData = System.Activator.CreateInstance(metaDataType) as IBuildModeMetaData; // packages can have meta data - instantiate where they exist foreach (var package in graph.Packages) { var ns = package.Name; var metaType = graph.ScriptAssembly.GetTypes().FirstOrDefault(item => item.Namespace == ns && typeof(PackageMetaData).IsAssignableFrom(item)); if (null == metaType) { continue; } try { package.MetaData = System.Activator.CreateInstance(metaType) as PackageMetaData; } catch (Exception exception) { throw exception; } catch (System.Reflection.TargetInvocationException exception) { throw new Exception(exception, "Failed to create package metadata"); } } packageMetaDataProfile.StopProfile(); var topLevelNamespace = graph.MasterPackage.Name; var findBuildableModulesProfile = new TimeProfile(ETimingProfiles.IdentifyBuildableModules); findBuildableModulesProfile.StartProfile(); // Phase 1: Instantiate all modules in the namespace of the package in which the tool was invoked Log.Detail("Creating modules"); foreach (var env in environments) { graph.CreateTopLevelModules(graph.ScriptAssembly, env, topLevelNamespace); } findBuildableModulesProfile.StopProfile(); var populateGraphProfile = new TimeProfile(ETimingProfiles.PopulateGraph); populateGraphProfile.StartProfile(); // Phase 2: Graph now has a linear list of modules; create a dependency graph // NB: all those modules with 0 dependees are the top-level modules // NB: default settings have already been defined here // not only does this generate the dependency graph, but also creates the default settings for each module, and completes them graph.SortDependencies(); populateGraphProfile.StopProfile(); // TODO: make validation optional, if it starts showing on profiles var validateGraphProfile = new TimeProfile(ETimingProfiles.ValidateGraph); validateGraphProfile.StartProfile(); graph.Validate(); validateGraphProfile.StopProfile(); // Phase 3: (Create default settings, and ) apply patches (build + shared) to each module // NB: some builders can use the patch directly for child objects, so this may be dependent upon the builder // Toolchains for modules need to be set here, as they might append macros into each module in order to evaluate paths // TODO: a parallel thread can be spawned here, that can check whether command lines have changed // the Settings object can be inspected, and a hash generated. This hash can be written to disk, and compared. // If a 'verbose' mode is enabled, then more work can be done to figure out what has changed. This would also require // serializing the binary Settings object var createPatchesProfile = new TimeProfile(ETimingProfiles.CreatePatches); createPatchesProfile.StartProfile(); graph.ApplySettingsPatches(); createPatchesProfile.StopProfile(); // expand paths after patching settings, because some of the patches may contain tokenized strings // TODO: a thread can be spawned, to check for whether files were in date or not, which will // be ready in time for graph execution var parseStringsProfile = new TimeProfile(ETimingProfiles.ParseTokenizedStrings); parseStringsProfile.StartProfile(); TokenizedString.ParseAll(); parseStringsProfile.StopProfile(); if (CommandLineProcessor.Evaluate(new Options.ViewDependencyGraph())) { // must come after all strings are parsed, in order to display useful paths graph.Dump(); } // Phase 4: Execute dependency graph // N.B. all paths (including those with macros) have been delayed expansion until now var graphExecutionProfile = new TimeProfile(ETimingProfiles.GraphExecution); graphExecutionProfile.StartProfile(); var executor = new Executor(); executor.Run(); graphExecutionProfile.StopProfile(); }