AppendTargetNames( Bam.Core.StringArray variableNames) { foreach (var target in this.Targets) { var name = target.VariableName; if (null != name) { variableNames.AddUnique("$(" + name + ")"); } else { variableNames.AddUnique(target.Path.Parse()); } } }
Serialize() { var document = new System.Xml.XmlDocument(); var projectEl = this.CreateRootProject(document); projectEl.SetAttribute("ToolsVersion", "4.0"); // TODO: get this number from VisualC var filtersEl = document.CreateVSItemGroup(parentEl: projectEl); foreach (var filter in this.Filters) { var filterEl = document.CreateVSElement("Filter", parentEl: filtersEl); filterEl.SetAttribute("Include", filter.Key); document.CreateVSElement("UniqueIdentifier", new DeterministicGuid("VSFilter" + filter.Key).Guid.ToString("B").ToUpper(), parentEl: filterEl); var filesEl = document.CreateVSItemGroup(parentEl: projectEl); var extensions = new Bam.Core.StringArray(); foreach (var setting in filter.Value) { var path = setting.Include; var extension = System.IO.Path.GetExtension(path.Parse()).TrimStart(new[] { '.' }); extensions.AddUnique(extension); setting.Serialize(document, filesEl); } if (extensions.Count > 0) { document.CreateVSElement("Extensions", extensions.ToString(';'), parentEl: filterEl); } } return(document); }
AppendAllPrerequisiteTargetNames( Bam.Core.StringArray variableNames) { lock (this.Targets) { foreach (var target in this.Targets) { if (!target.IsPrerequisiteofAll) { continue; } var name = target.VariableName; if (null != name) { variableNames.AddUnique("$(" + name + ")"); } else { variableNames.AddUnique(target.Path.ToString()); } } } }
Serialize() { var ProjectTypeGuid = System.Guid.Parse("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"); var SolutionFolderGuid = System.Guid.Parse("2150E333-8FDC-42A3-9474-1A3956D46DE8"); var content = new System.Text.StringBuilder(); // TODO: obviously dependent on version content.AppendLine(@"Microsoft Visual Studio Solution File, Format Version 12.00"); var configs = new Bam.Core.StringArray(); foreach (var project in this.Projects) { content.AppendFormat("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", ProjectTypeGuid.ToString("B").ToUpper(), System.IO.Path.GetFileNameWithoutExtension(project.ProjectPath), project.ProjectPath, // TODO: relative to the solution file project.Guid.ToString("B").ToUpper()); content.AppendLine(); content.AppendLine("EndProject"); foreach (var config in project.Configurations) { configs.AddUnique(config.Value.FullName); } } foreach (var folder in this.SolutionFolders) { content.AppendFormat("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", SolutionFolderGuid.ToString("B").ToUpper(), folder.Key, folder.Key, folder.Value.Guid); content.AppendLine(); content.AppendLine("EndProject"); } content.AppendLine("Global"); content.AppendLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); foreach (var config in configs) { // TODO: I'm sure these are not meant to be identical, but I don't know what else to put here content.AppendFormat("\t\t{0} = {0}", config); content.AppendLine(); } content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); foreach (var project in this.Projects) { foreach (var config in project.Configurations) { var guid = project.Guid.ToString("B").ToUpper(); content.AppendFormat("\t\t{0}.{1}.ActiveCfg = {1}", guid, config.Value.FullName); content.AppendLine(); content.AppendFormat("\t\t{0}.{1}.Build.0 = {1}", guid, config.Value.FullName); content.AppendLine(); } } content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(SolutionProperties) = preSolution"); content.AppendLine("\t\tHideSolutionNode = FALSE"); content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(NestedProjects) = preSolution"); foreach (var folder in this.SolutionFolders) { foreach (var project in folder.Value.Projects) { content.AppendFormat("\t\t{0} = {1}", project.Guid.ToString("B").ToUpper(), folder.Value.Guid); content.AppendLine(); } } content.AppendLine("\tEndGlobalSection"); content.AppendLine("EndGlobal"); return(content); }
public override void Evaluate() { this.ReasonToExecute = null; var graph = Bam.Core.Graph.Instance; var factory = graph.MetaData as System.Threading.Tasks.TaskFactory; this.EvaluationTask = factory.StartNew(() => { // does the object file exist? var objectFilePath = this.GeneratedPaths[Key].Parse(); if (!System.IO.File.Exists(objectFilePath)) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.FileDoesNotExist(this.GeneratedPaths[Key]); return; } var objectFileWriteTime = System.IO.File.GetLastWriteTime(objectFilePath); // has the source file been evaluated to be rebuilt? if ((this as IRequiresSourceModule).Source.ReasonToExecute != null) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer(this.GeneratedPaths[Key], this.InputPath); return; } // is the source file newer than the object file? var sourcePath = this.InputPath.Parse(); var sourceWriteTime = System.IO.File.GetLastWriteTime(sourcePath); if (sourceWriteTime > objectFileWriteTime) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer(this.GeneratedPaths[Key], this.InputPath); return; } if (this is WinResource) { return; } // are there any headers as explicit dependencies (procedurally generated most likely), which are newer? var explicitHeadersUpdated = new Bam.Core.StringArray(); foreach (var dep in this.Dependents) { if (!(dep is HeaderFile)) { continue; } if (null == dep.ReasonToExecute) { continue; } explicitHeadersUpdated.AddUnique((dep as HeaderFile).InputPath.Parse()); } var includeSearchPaths = (this.Settings as C.ICommonCompilerSettings).IncludePaths; var filesToSearch = new System.Collections.Generic.Queue<string>(); filesToSearch.Enqueue(sourcePath); var headerPathsFound = new Bam.Core.StringArray(); while (filesToSearch.Count > 0) { var fileToSearch = filesToSearch.Dequeue(); string fileContents = null; using (System.IO.TextReader reader = new System.IO.StreamReader(fileToSearch)) { fileContents = reader.ReadToEnd(); } // never know if developers are consistent with #include "header.h" or #include <header.h> so look for both var matches = System.Text.RegularExpressions.Regex.Matches( fileContents, "^\\s*#include [\"<]([^\\s]*)[\">]", System.Text.RegularExpressions.RegexOptions.Multiline); if (0 == matches.Count) { // no #includes return; } foreach (System.Text.RegularExpressions.Match match in matches) { var headerFile = match.Groups[1].Value; bool exists = false; // search for the file on the include paths the compiler uses foreach (var includePath in includeSearchPaths) { try { var potentialPath = System.IO.Path.Combine(includePath.Parse(), headerFile); if (!System.IO.File.Exists(potentialPath)) { continue; } potentialPath = System.IO.Path.GetFullPath(potentialPath); var headerWriteTime = System.IO.File.GetLastWriteTime(potentialPath); // early out - header is newer than generated object file if (headerWriteTime > objectFileWriteTime) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer( this.GeneratedPaths[Key], Bam.Core.TokenizedString.CreateVerbatim(potentialPath)); return; } if (explicitHeadersUpdated.Contains(potentialPath)) { // found #included header in list of explicitly dependent headers that have been updated this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer( this.GeneratedPaths[Key], Bam.Core.TokenizedString.CreateVerbatim(potentialPath)); return; } if (!headerPathsFound.Contains(potentialPath)) { headerPathsFound.Add(potentialPath); filesToSearch.Enqueue(potentialPath); } exists = true; break; } catch (System.Exception ex) { Bam.Core.Log.MessageAll("IncludeDependency Exception: Cannot locate '{0}' on '{1}' due to {2}", headerFile, includePath, ex.Message); } } if (!exists) { #if false Bam.Core.Log.DebugMessage("***** Could not locate '{0}' on any include search path, included from {1}:\n{2}", match.Groups[1], fileToSearch, entry.includePaths.ToString('\n')); #endif } } } return; }); }
Serialize( string solutionPath) { var ProjectTypeGuid = System.Guid.Parse("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"); var SolutionFolderGuid = System.Guid.Parse("2150E333-8FDC-42A3-9474-1A3956D46DE8"); var content = new System.Text.StringBuilder(); var visualCMeta = Bam.Core.Graph.Instance.PackageMetaData <VisualC.MetaData>("VisualC"); content.AppendFormat(@"Microsoft Visual Studio Solution File, Format Version {0}", visualCMeta.SolutionFormatVersion); content.AppendLine(); var configs = new Bam.Core.StringArray(); foreach (var project in this.Projects) { var relativeProjectPath = Bam.Core.RelativePathUtilities.GetPath(project.ProjectPath, solutionPath); content.AppendFormat("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", ProjectTypeGuid.ToString("B").ToUpper(), System.IO.Path.GetFileNameWithoutExtension(project.ProjectPath), relativeProjectPath, project.GuidString); content.AppendLine(); content.AppendLine("EndProject"); foreach (var config in project.Configurations) { configs.AddUnique(config.Value.FullName); } } foreach (var folder in this.SolutionFolders) { var folderPath = folder.Value.Path; var folderGuid = folder.Value.GuidString; content.AppendFormat("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", SolutionFolderGuid.ToString("B").ToUpper(), folderPath, folderPath, folderGuid); content.AppendLine(); content.AppendLine("EndProject"); } content.AppendLine("Global"); content.AppendLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); foreach (var config in configs) { // TODO: I'm sure these are not meant to be identical, but I don't know what else to put here content.AppendFormat("\t\t{0} = {0}", config); content.AppendLine(); } content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); foreach (var project in this.Projects) { var guid = project.GuidString; var thisProjectConfigs = new Bam.Core.StringArray(); // write the configurations for which build steps have been defined foreach (var config in project.Configurations) { var configName = config.Value.FullName; content.AppendFormat("\t\t{0}.{1}.ActiveCfg = {1}", guid, configName); content.AppendLine(); content.AppendFormat("\t\t{0}.{1}.Build.0 = {1}", guid, configName); content.AppendLine(); thisProjectConfigs.AddUnique(configName); } // now cater for any configurations that the project does not support var unsupportedConfigs = configs.Complement(thisProjectConfigs) as Bam.Core.StringArray; foreach (var uConfig in unsupportedConfigs) { // a missing "XX.YY.Build.0" line means not configured to build // also, the remapping between config names seems a little arbitrary, but seems to work // might be related to the project not having an ProjectConfiguration for the unsupported config content.AppendFormat("\t\t{0}.{1}.ActiveCfg = {2}", guid, uConfig, thisProjectConfigs[0]); content.AppendLine(); } } content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(SolutionProperties) = preSolution"); content.AppendLine("\t\tHideSolutionNode = FALSE"); content.AppendLine("\tEndGlobalSection"); if (this.SolutionFolders.Count() > 0) { content.AppendLine("\tGlobalSection(NestedProjects) = preSolution"); foreach (var folder in this.SolutionFolders) { folder.Value.Serialize(content, 2); } content.AppendLine("\tEndGlobalSection"); } content.AppendLine("EndGlobal"); return(content); }
Evaluate() { this.ReasonToExecute = null; if (!this.PerformCompilation) { return; } var graph = Bam.Core.Graph.Instance; var factory = graph.MetaData as System.Threading.Tasks.TaskFactory; this.EvaluationTask = factory.StartNew(() => { // does the object file exist? var objectFilePath = this.GeneratedPaths[Key].Parse(); if (!System.IO.File.Exists(objectFilePath)) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.FileDoesNotExist(this.GeneratedPaths[Key]); return; } var objectFileWriteTime = System.IO.File.GetLastWriteTime(objectFilePath); // has the source file been evaluated to be rebuilt? if ((this as IRequiresSourceModule).Source.ReasonToExecute != null) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer(this.GeneratedPaths[Key], this.InputPath); return; } // is the source file newer than the object file? var sourcePath = this.InputPath.Parse(); var sourceWriteTime = System.IO.File.GetLastWriteTime(sourcePath); if (sourceWriteTime > objectFileWriteTime) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer(this.GeneratedPaths[Key], this.InputPath); return; } if (this is WinResource) { return; } // are there any headers as explicit dependencies (procedurally generated most likely), which are newer? var explicitHeadersUpdated = new Bam.Core.StringArray(); var explicitHeadersDeferred = new Bam.Core.StringArray(); foreach (var dep in this.Dependents) { if (!(dep is HeaderFile)) { continue; } if (null == dep.ReasonToExecute) { continue; } if (dep.ReasonToExecute.Reason == Bam.Core.ExecuteReasoning.EReason.InputFileIsNewer) { explicitHeadersUpdated.AddUnique((dep as HeaderFile).InputPath.Parse()); } else if (dep.ReasonToExecute.Reason == Bam.Core.ExecuteReasoning.EReason.DeferredEvaluation) { explicitHeadersDeferred.AddUnique((dep as HeaderFile).InputPath.Parse()); } } var includeSearchPaths = (this.Settings as C.ICommonCompilerSettings).IncludePaths; // implicitly search the same directory as the source path, as this is not needed to be explicitly on the include path list includeSearchPaths.AddUnique(this.CreateTokenizedString("@dir($(0))", this.InputPath)); var filesToSearch = new System.Collections.Generic.Queue <string>(); filesToSearch.Enqueue(sourcePath); var headerPathsFound = new Bam.Core.StringArray(); while (filesToSearch.Count > 0) { var fileToSearch = filesToSearch.Dequeue(); string fileContents = null; using (System.IO.TextReader reader = new System.IO.StreamReader(fileToSearch)) { fileContents = reader.ReadToEnd(); } // never know if developers are consistent with #include "header.h" or #include <header.h> so look for both // nor the amount of whitespace after #include var matches = System.Text.RegularExpressions.Regex.Matches( fileContents, "^\\s*#include\\s*[\"<]([^\\s]*)[\">]", System.Text.RegularExpressions.RegexOptions.Multiline); if (0 == matches.Count) { // no #includes return; } foreach (System.Text.RegularExpressions.Match match in matches) { var headerFile = match.Groups[1].Value; bool exists = false; // search for the file on the include paths the compiler uses foreach (var includePath in includeSearchPaths) { try { var potentialPath = System.IO.Path.Combine(includePath.Parse(), headerFile); if (!System.IO.File.Exists(potentialPath)) { continue; } potentialPath = System.IO.Path.GetFullPath(potentialPath); var headerWriteTime = System.IO.File.GetLastWriteTime(potentialPath); // early out - header is newer than generated object file if (headerWriteTime > objectFileWriteTime) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer( this.GeneratedPaths[Key], Bam.Core.TokenizedString.CreateVerbatim(potentialPath)); return; } // found #included header in list of explicitly dependent headers that have been updated if (explicitHeadersUpdated.Contains(potentialPath)) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.InputFileNewer( this.GeneratedPaths[Key], Bam.Core.TokenizedString.CreateVerbatim(potentialPath)); return; } // found #included header in list of explicitly dependent headers that require a deferred evaluation if (explicitHeadersDeferred.Contains(potentialPath)) { this.ReasonToExecute = Bam.Core.ExecuteReasoning.DeferredUntilBuild(this.GeneratedPaths[Key]); return; } if (!headerPathsFound.Contains(potentialPath)) { headerPathsFound.Add(potentialPath); filesToSearch.Enqueue(potentialPath); } exists = true; break; } catch (System.Exception ex) { Bam.Core.Log.MessageAll("IncludeDependency Exception: Cannot locate '{0}' on '{1}' due to {2}", headerFile, includePath, ex.Message); } } if (!exists) { #if false Bam.Core.Log.DebugMessage("***** Could not locate '{0}' on any include search path, included from {1}:\n{2}", match.Groups[1], fileToSearch, entry.includePaths.ToString('\n')); #endif } } } return; }); }
public System.Text.StringBuilder Serialize() { var ProjectTypeGuid = System.Guid.Parse("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"); var SolutionFolderGuid = System.Guid.Parse("2150E333-8FDC-42A3-9474-1A3956D46DE8"); var content = new System.Text.StringBuilder(); // TODO: obviously dependent on version content.AppendLine(@"Microsoft Visual Studio Solution File, Format Version 12.00"); var configs = new Bam.Core.StringArray(); foreach (var project in this.Projects) { content.AppendFormat("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", ProjectTypeGuid.ToString("B").ToUpper(), System.IO.Path.GetFileNameWithoutExtension(project.ProjectPath), project.ProjectPath, // TODO: relative to the solution file project.GuidString); content.AppendLine(); content.AppendLine("EndProject"); foreach (var config in project.Configurations) { configs.AddUnique(config.Value.FullName); } } foreach (var folder in this.SolutionFolders) { content.AppendFormat("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", SolutionFolderGuid.ToString("B").ToUpper(), folder.Key, folder.Key, folder.Value.GuidString); content.AppendLine(); content.AppendLine("EndProject"); } content.AppendLine("Global"); content.AppendLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); foreach (var config in configs) { // TODO: I'm sure these are not meant to be identical, but I don't know what else to put here content.AppendFormat("\t\t{0} = {0}", config); content.AppendLine(); } content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); foreach (var project in this.Projects) { foreach (var config in project.Configurations) { var guid = project.GuidString; content.AppendFormat("\t\t{0}.{1}.ActiveCfg = {1}", guid, config.Value.FullName); content.AppendLine(); content.AppendFormat("\t\t{0}.{1}.Build.0 = {1}", guid, config.Value.FullName); content.AppendLine(); } } content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(SolutionProperties) = preSolution"); content.AppendLine("\t\tHideSolutionNode = FALSE"); content.AppendLine("\tEndGlobalSection"); content.AppendLine("\tGlobalSection(NestedProjects) = preSolution"); foreach (var folder in this.SolutionFolders) { foreach (var nested in folder.Value.NestedEntities) { content.AppendFormat("\t\t{0} = {1}", nested.GuidString, folder.Value.GuidString); content.AppendLine(); } } content.AppendLine("\tEndGlobalSection"); content.AppendLine("EndGlobal"); return content; }
Serialize() { var document = new System.Xml.XmlDocument(); var projectEl = this.CreateRootProject(document); projectEl.SetAttribute("ToolsVersion", "4.0"); // TODO: get this number from VisualC var filtersEl = document.CreateVSItemGroup(parentEl: projectEl); foreach (var filter in this.Filters) { var filterEl = document.CreateVSElement("Filter", parentEl: filtersEl); filterEl.SetAttribute("Include", filter.Key); document.CreateVSElement("UniqueIdentifier", new DeterministicGuid("VSFilter" + filter.Key).Guid.ToString("B").ToUpper(), parentEl: filterEl); var filesEl = document.CreateVSItemGroup(parentEl: projectEl); var extensions = new Bam.Core.StringArray(); foreach (var setting in filter.Value) { var path = setting.Include; var extension = System.IO.Path.GetExtension(path.Parse()).TrimStart(new[] { '.' }); extensions.AddUnique(extension); setting.Serialize(document, filesEl); } if (extensions.Count > 0) { document.CreateVSElement("Extensions", extensions.ToString(';'), parentEl: filterEl); } } return document; }