public static void PrintBuildResults(BuildOptions options, BuildResults buildResults) { Console.WriteLine("==================================================="); Console.WriteLine("BuildResults.Action = {0}", buildResults.Action); Console.WriteLine("BuildResults.Success = {0}", buildResults.Success); Console.WriteLine("BuildResults.TranslationCount = {0}", buildResults.TranslationCount); Console.WriteLine("BuildResults.UpToDateCount = {0}", buildResults.UpToDateCount); Console.WriteLine("BuildResults.UpdateImplicitInputsCount = {0}", buildResults.UpdateImplicitInputsCount); Console.WriteLine("BuildOptions.FileDecider.FStatCount= {0}", options.FileDecider.FStatCount); TimeSpan executionTime = buildResults.ExecuteEndTime - buildResults.ExecuteStartTime; Console.WriteLine("# ExecutionTime = {0}", executionTime); }
public void GetInputsAndOutputsForTargets( BuildOptions buildOptions, IEnumerable<string> targetPaths, out HashSet<string> inputs, out HashSet<string> outputs) { inputs = new HashSet<string>(); outputs = new HashSet<string>(); BuildProcess buildProcess = CreateBuildProcess(buildOptions, targetPaths); buildProcess.GetInputsAndOutputs(m_buildFiles.Values, inputs, outputs); }
/// Returns all files that are not generated by this BuildGraph. /// This may be a very large collection. public ICollection<string> GetInputFilePaths(BuildOptions buildOptions) { ComputeDependencies(buildOptions); if (!m_dependenciesValid) { return null; } var inputs = new HashSet<string>(); foreach (BuildFile buildFile in m_buildFiles.Values) { if (!IsBuildFileGenerated(buildFile)) { inputs.Add(buildFile.Path); } } return inputs; }
public static void DoTest() { var buildGraph = new BuildGraph(); Directory.CreateDirectory(buildFileDir); string windowsSdkDir = @"C:\Program Files\Microsoft SDKs\Windows\v6.0A"; var cc_a = CompileOne(buildGraph, "a.cpp"); var cc_b = CompileOne(buildGraph, "b.cpp"); var cc_c = CompileOne(buildGraph, "c.cpp"); var cc_main = CompileOne(buildGraph, "main.cpp"); string kernel32Lib = Path.Combine(windowsSdkDir, @"Lib\kernel32.lib"); // NOTE: linker order matters; the linker translation respects that var link = LinkExecutable( buildGraph, "main.exe", cc_a.Params.ObjectPath, cc_b.Params.ObjectPath, cc_c.Params.ObjectPath, cc_main.Params.ObjectPath, kernel32Lib); var generateHeader = new GenerateHeader( buildGraph, "generated.h", compileDir, buildFileDir); BuildOptions buildOptions = new BuildOptions(); buildOptions.ContinueOnError = false; buildOptions.FileDecider = new FileSizeDateDecider(); buildOptions.MaxConcurrency = 6; string[] targets = { link.Params.OutputFilePath }; BuildResults cleanBuildResults = buildGraph.Execute(BuildAction.Build, buildOptions, targets, true); TestHelpers.PrintBuildResults(buildOptions, cleanBuildResults); BuildResults incrementalBuildResults = buildGraph.Execute(BuildAction.Build, buildOptions, targets, true); TestHelpers.PrintBuildResults(buildOptions, incrementalBuildResults); bool doClean = true; if (doClean) { BuildResults cleanResults = buildGraph.Execute(BuildAction.Clean, buildOptions, targets, true); TestHelpers.PrintBuildResults(buildOptions, cleanResults); } }
///----------------------------------------------------------------- /// Public interface public BuildProcess( BuildGraph buildGraph, BuildAction buildAction, BuildOptions buildOptions, BuildResults buildResults, IEnumerable<BuildNode> buildNodes, bool processDependencies) { m_buildGraph = buildGraph; m_buildAction = buildAction; m_buildOptions = buildOptions; m_buildResults = buildResults; bool initialized = InitializeBuildProcess(buildNodes, processDependencies); if (!initialized) { throw new InvalidOperationException("Failed to initialize BuildProcess."); } }
//-- Public interface /// Execute the specified action on targets. /// This is how you kick off a Build. public BuildResults Execute( BuildAction action, BuildOptions buildOptions, IEnumerable<string> targetPaths, bool processDependencies) { Trace.TraceInformation("Execute {0}", action); Trace.TraceInformation("-----------"); // TODO: trace targets BuildResults buildResults = new BuildResults(); buildResults.Action = action; buildResults.ExecuteStartTime = DateTime.Now; buildResults.Success = UntimedExecute( action, buildOptions, targetPaths, processDependencies, buildResults); buildResults.ExecuteEndTime = DateTime.Now; return buildResults; }
private bool UntimedExecute( BuildAction action, BuildOptions buildOptions, IEnumerable<string> targetPaths, bool processDependencies, BuildResults buildResults) { TimedComputeDependencies(buildResults, buildOptions); if (!m_dependenciesValid) { return false; } HashSet<BuildFile> targets = GetBuildFilesForPaths(targetPaths); HashSet<BuildNode> buildNodes = GetBuildNodesForFiles(targets); if (buildNodes == null) { return false; } BuildProcess buildProcess = new BuildProcess( this, action, buildOptions, buildResults, buildNodes, processDependencies); bool result = buildProcess.Run(); return result; }
private void TimedComputeDependencies(BuildResults buildResults, BuildOptions buildOptions) { buildResults.ComputeDependenciesStartTime = DateTime.Now; ComputeDependencies(buildOptions); buildResults.DependenciesValid = m_dependenciesValid; buildResults.ComputeDependenciesEndTime = DateTime.Now; }
/// This function determines all BuildNodes' dependencies. /// Consumers are cleared here, to be decided later by the /// specific targets required of a BuildProcess. /// Call this after all Translations have been added. private void ComputeDependencies(BuildOptions buildOptions) { if (m_dependenciesComputed) { return; } m_dependenciesComputed = true; m_dependenciesValid = true; // Clear m_buildFiles, so that we only use the most recent // inputs and outputs from each BuildTranslation. m_buildFiles.Clear(); Regex moduleNameRegex; if (String.IsNullOrEmpty(buildOptions.ModuleNameRegex)) { moduleNameRegex = new Regex(".*"); } else { moduleNameRegex = new Regex(buildOptions.ModuleNameRegex); } // Clear stale dependency information, and update each BuildNode's IOs. foreach (BuildTranslation translation in m_translations) { translation.BuildNode.Reset(); bool moduleNameMatches = moduleNameRegex.IsMatch(translation.ModuleName); if (!moduleNameMatches) { // Do not update BuildNode; this means this translation will // not participate in the build at all. continue; } if (translation.DepsCacheFilePath == null) { Trace.TraceError("Translation {0} has null DepsCachePath.", translation.BuildFileBaseName); return; } // Update *current* explicit inputs and outputs. translation.UpdateExplicitIO(); // Load *previous* implicit inputs and outputs (for incremental building). // TODO: parallelize deps cache file loading, or else we are I/O bound here // depsCache file opened for exclusive access here. We could also roll UpdateExplicitIO() // into the parallel initialization, since each BuildNode is independent. QRDirectory.EnsureDirectoryExistsForFile(translation.DepsCacheFilePath); using (FileStream depsCacheFileStream = new FileStream(translation.DepsCacheFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { string prevDepsCacheFileContents = QRFileStream.ReadAllText(depsCacheFileStream); DependencyCache.LoadImplicitInputs(prevDepsCacheFileContents, translation.ImplicitInputs); } } // Ensure existence of all BuildFile objects and BuildFile.BuildNode correctness. foreach (BuildTranslation translation in m_translations) { m_dependenciesValid &= AddOutputDependencies(translation, translation.ExplicitOutputs); } // Establish BuildNode<->BuildNode dependencies based on inputs. foreach (BuildTranslation translation in m_translations) { AddInputDependencies(translation, translation.ExplicitInputs); AddInputDependencies(translation, translation.ImplicitInputs); } // Establish consumers by reflecting the dependencies. foreach (BuildTranslation translation in m_translations) { foreach (BuildNode dependency in translation.BuildNode.Dependencies) { dependency.Consumers.Add(translation.BuildNode); } } }
internal BuildProcess CreateBuildProcess( BuildOptions buildOptions, IEnumerable<string> targetPaths) { ComputeDependencies(buildOptions); if (!m_dependenciesValid) { return null; } HashSet<BuildFile> targets = GetBuildFilesForPaths(targetPaths); HashSet<BuildNode> buildNodes = GetBuildNodesForFiles(targets); if (buildNodes == null) { return null; } BuildResults buildResults = new BuildResults(); BuildProcess buildProcess = new BuildProcess( this, BuildAction.Build /* don't care */, buildOptions, buildResults /* don't care */, buildNodes, true /* processDependencies */); return buildProcess; }
public static void TestCppCompileLink() { var buildGraph = new BuildGraph(); Directory.CreateDirectory(buildFileDir); var cc_test02 = CompileOne(buildGraph, "test02.cpp"); var cc_foo = CompileOne(buildGraph, "foo.cpp"); var cc_groo = CompileOne(buildGraph, "groo.cpp"); var cc_qoo = CompileOne(buildGraph, "qoo.cpp"); var cc_yoo = CompileOne(buildGraph, "yoo.cpp"); var cc_aoo = CompileOne(buildGraph, "aoo.cpp"); var cc_boo = CompileOne(buildGraph, "boo.cpp"); var cc_coo = CompileOne(buildGraph, "coo.cpp"); var cc_doo = CompileOne(buildGraph, "doo.cpp"); var linkerParams = new MsvcLinkerParams(); linkerParams.VcBinDir = vcBinDir; linkerParams.ToolChain = toolChain; linkerParams.CompileDir = compileDir; linkerParams.BuildFileDir = buildFileDir; linkerParams.Inputs.Add(cc_aoo.Params.ObjectPath); linkerParams.Inputs.Add(cc_boo.Params.ObjectPath); linkerParams.Inputs.Add(cc_coo.Params.ObjectPath); linkerParams.Inputs.Add(cc_doo.Params.ObjectPath); linkerParams.Inputs.Add(cc_foo.Params.ObjectPath); linkerParams.Inputs.Add(cc_groo.Params.ObjectPath); linkerParams.Inputs.Add(cc_qoo.Params.ObjectPath); linkerParams.Inputs.Add(cc_test02.Params.ObjectPath); linkerParams.Inputs.Add(cc_yoo.Params.ObjectPath); linkerParams.OutputFilePath = "result.exe"; var link = new MsvcLink(buildGraph, linkerParams); BuildOptions buildOptions = new BuildOptions(); buildOptions.ContinueOnError = false; buildOptions.FileDecider = new FileSizeDateDecider(); buildOptions.MaxConcurrency = 6; string[] targets = { link.Params.OutputFilePath }; BuildResults cleanBuildResults = buildGraph.Execute(BuildAction.Build, buildOptions, targets, true); TestHelpers.PrintBuildResults(buildOptions, cleanBuildResults); BuildResults incrementalBuildResults = buildGraph.Execute(BuildAction.Build, buildOptions, targets, true); TestHelpers.PrintBuildResults(buildOptions, incrementalBuildResults); bool doClean = true; if (doClean) { BuildResults cleanResults = buildGraph.Execute(BuildAction.Clean, buildOptions, targets, true); TestHelpers.PrintBuildResults(buildOptions, cleanResults); } }
static void TestSingleNodeGraph() { var buildGraph = new BuildGraph(); var ccp = new MsvcCompileParams(); ccp.VcBinDir = @"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin"; ccp.ToolChain = MsvcToolChain.ToolsX86TargetX86; ccp.CompileDir = @"K:\work\code\cpp\0002_test"; ccp.SourceFile = @"test02.cpp"; ccp.Compile = true; ccp.DebugInfoFormat = MsvcDebugInfoFormat.Normal; var cc = new MsvcCompile(buildGraph, ccp); BuildOptions buildOptions = new BuildOptions(); buildOptions.ContinueOnError = false; buildOptions.FileDecider = new FileSizeDateDecider(); buildOptions.MaxConcurrency = 1; string[] targets = { @"K:\work\code\cpp\0002_test\test02.obj" }; BuildResults buildResults = buildGraph.Execute(BuildAction.Build, buildOptions, targets, true); Console.WriteLine("BuildResults.Success = {0}", buildResults.Success); Console.WriteLine("BuildResults.TranslationCount = {0}", buildResults.TranslationCount); Console.WriteLine("BuildResults.UpToDateCount = {0}", buildResults.UpToDateCount); }
static void TestDependencyChain() { var buildGraph = new BuildGraph(); string testDir = @"K:\work\code\C#\QRBuild\Tests\A"; string intDir = Path.Combine(testDir, "int"); string a = Path.Combine(testDir, "a"); string b = Path.Combine(testDir, "b"); string c = Path.Combine(testDir, "c"); string d = Path.Combine(testDir, "d"); if (!File.Exists(a)) { File.WriteAllText(a, "a"); } var fcB = new FileCopy(buildGraph, a, b, intDir); var fcC = new FileCopy(buildGraph, b, c, intDir); var fcD = new FileCopy(buildGraph, c, d, intDir); BuildOptions buildOptions = new BuildOptions(); buildOptions.ContinueOnError = false; buildOptions.FileDecider = new FileSizeDateDecider(); buildOptions.MaxConcurrency = 1; string[] targets = { d }; BuildResults buildResults = buildGraph.Execute(BuildAction.Build, buildOptions, targets, true); Console.WriteLine("BuildResults.Success = {0}", buildResults.Success); Console.WriteLine("BuildResults.TranslationCount = {0}", buildResults.TranslationCount); Console.WriteLine("BuildResults.UpToDateCount = {0}", buildResults.UpToDateCount); //QRFile.Delete(a, b, c, d); }