private async Task CompileProject(IConsole console, IStandardProject superProject, IStandardProject project, List <CompileResult> results = null) { if (project == superProject) { superProject.ToolChain?.ProvisionSettings(project); } if (project.Type == ProjectType.Executable && superProject != project) { await Build(console, project); } else { if (!terminateBuild) { if (results == null) { results = new List <CompileResult>(); } foreach (var reference in project.References) { var standardReference = reference as IStandardProject; if (standardReference != null) { await CompileProject(console, superProject, standardReference, results); } } var outputDirectory = project.GetOutputDirectory(superProject); if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } var doWork = false; lock (resultLock) { if (!project.IsBuilding) { project.IsBuilding = true; doWork = true; } } if (doWork) { var objDirectory = project.GetObjectDirectory(superProject); if (!Directory.Exists(objDirectory)) { Directory.CreateDirectory(objDirectory); } var compileResults = new CompileResult(); compileResults.Project = project; results.Add(compileResults); var tasks = new List <Task>(); var numLocalTasks = 0; var sourceFiles = project.SourceFiles.ToList(); foreach (var file in sourceFiles) { if (terminateBuild) { break; } if (SupportsFile(file)) { var outputName = Path.GetFileNameWithoutExtension(file.Location) + ".o"; var dependencyFile = Path.Combine(objDirectory, Path.GetFileNameWithoutExtension(file.Location) + ".d"); var objectFile = Path.Combine(objDirectory, outputName); var dependencyChanged = false; if (System.IO.File.Exists(dependencyFile)) { var dependencies = new List <string>(); dependencies.AddRange(ProjectExtensions.GetDependencies(dependencyFile)); foreach (var dependency in dependencies) { if (!System.IO.File.Exists(dependency) || System.IO.File.GetLastWriteTime(dependency) > System.IO.File.GetLastWriteTime(objectFile)) { dependencyChanged = true; break; } } } if (dependencyChanged || !System.IO.File.Exists(objectFile)) { while (numTasks >= Jobs) { Thread.Yield(); } lock (resultLock) { numLocalTasks++; numTasks++; console.OverWrite(string.Format("[CC {0}/{1}] [{2}] {3}", ++buildCount, fileCount, project.Name, Path.GetFileName(file.Location))); } new Thread(() => { var compileResult = Compile(console, superProject, project, file, objectFile); lock (resultLock) { if (compileResults.ExitCode == 0 && compileResult.ExitCode != 0) { terminateBuild = true; compileResults.ExitCode = compileResult.ExitCode; } else { compileResults.ObjectLocations.Add(objectFile); compileResults.NumberOfObjectsCompiled++; } numTasks--; numLocalTasks--; } }).Start(); } else { buildCount++; compileResults.ObjectLocations.Add(objectFile); } } } } } } }
private async Task CompileProject(IConsole console, IStandardProject superProject, IStandardProject project, List <CompileResult> results = null) { if (project.Type == ProjectType.Executable && superProject != project) { if (project.ToolChain == null) { terminateBuild = true; console.WriteLine($"Project: {project.Name} does not have a toolchain set."); } await project.ToolChain?.Build(console, project); } else { if (!terminateBuild) { if (results == null) { results = new List <CompileResult>(); } foreach (var reference in project.References) { var standardReference = reference as IStandardProject; if (standardReference != null) { await CompileProject(console, superProject, standardReference, results); } } var outputDirectory = project.GetOutputDirectory(superProject); if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } var doWork = false; lock (resultLock) { if (!project.IsBuilding) { project.IsBuilding = true; doWork = true; } } if (doWork) { var objDirectory = project.GetObjectDirectory(superProject); if (!Directory.Exists(objDirectory)) { Directory.CreateDirectory(objDirectory); } var compileResults = new CompileResult(); compileResults.Project = project; results.Add(compileResults); var tasks = new List <Task>(); var sourceFiles = project.SourceFiles.ToList(); _statusBar?.SetText($"Building Project: {project.Name}"); foreach (var file in sourceFiles) { if (terminateBuild) { break; } if (SupportsFile(file)) { var outputName = Path.ChangeExtension(file.Name, ".o"); var objectPath = Path.Combine(objDirectory, project.CurrentDirectory.MakeRelativePath(file.CurrentDirectory)); var objectFile = Path.Combine(objectPath, outputName); var dependencyFile = Path.ChangeExtension(objectFile, ".d"); if (!Directory.Exists(objectPath)) { Directory.CreateDirectory(objectPath); } var dependencyChanged = false; if (System.IO.File.Exists(dependencyFile)) { var dependencies = new List <string>(); dependencies.Add(file.Location); dependencies.AddRange(ProjectExtensions.GetDependencies(dependencyFile)); foreach (var dependency in dependencies) { if (!System.IO.File.Exists(dependency) || System.IO.File.GetLastWriteTime(dependency) > System.IO.File.GetLastWriteTime(objectFile)) { dependencyChanged = true; break; } } } if (dependencyChanged || !System.IO.File.Exists(objectFile)) { while (numTasks >= Jobs) { Thread.Sleep(10); } lock (resultLock) { if (terminateBuild) { break; } numTasks++; } Task.Run(() => { var stringBuilderConsole = new StringBuilderConsole(); var compileResult = Compile(stringBuilderConsole, superProject, project, file, objectFile); lock (resultLock) { if (compileResults.ExitCode == 0 && compileResult.ExitCode != 0) { terminateBuild = true; compileResults.ExitCode = compileResult.ExitCode; } else { compileResults.ObjectLocations.Add(objectFile); compileResults.NumberOfObjectsCompiled++; } numTasks--; } console.OverWrite($"[CC {++buildCount}/{fileCount}] [{project.Name}] {file.Project.Location.MakeRelativePath(file.Location)}"); var output = stringBuilderConsole.GetOutput(); if (!string.IsNullOrEmpty(output)) { console.WriteLine(output); } }).GetAwaiter(); } else { buildCount++; compileResults.ObjectLocations.Add(objectFile); } } } _statusBar?.ClearText(); } } } }