Inheritance: ProcessResult
        public async Task<bool> Build(IConsole console, IProject project, string label = "", IEnumerable<string> defines = null)
		{
            if(!ValidateToolchainExecutables(console))
            {
                return false;
            }

			console.Clear();

            var result = await PreBuild(console, project);

            console.WriteLine("Starting Build...");
            
			terminateBuild = !result;

			SetFileCount(project as IStandardProject);
			buildCount = 0;

			var compiledProjects = new List<CompileResult>();

            List<Definition> injectedDefines = new List<Definition>();

            if (defines != null)
            {
                foreach (var define in defines)
                {
                    var injectableDefinition = new Definition() { Global = true, Value = define };
                    (project as IStandardProject).Defines.Add(injectableDefinition);
                    injectedDefines.Add(injectableDefinition);
                }
            }       

			if (!terminateBuild)
			{
				await CompileProject(console, project as IStandardProject, project as IStandardProject, compiledProjects);

				if (!terminateBuild)
				{
					await WaitForCompileJobs();

					foreach (var compiledReference in compiledProjects)
					{
						result = compiledReference.ExitCode == 0;

						if (!result)
						{
							break;
						}
					}

					if (result)
					{
						var linkedReferences = new CompileResult();
						linkedReferences.Project = project as IStandardProject;

						foreach (var compiledProject in compiledProjects)
						{
							if (compiledProject.Project.Location != project.Location)
							{
								var linkResult = Link(console, project as IStandardProject, compiledProject, linkedReferences);
                            }
							else
							{
								// if (linkedReferences.Count > 0)
								{
									linkedReferences.ObjectLocations = compiledProject.ObjectLocations;
									linkedReferences.NumberOfObjectsCompiled = compiledProject.NumberOfObjectsCompiled;
									var linkResult = Link(console, project as IStandardProject, linkedReferences, linkedReferences, label);
                                    result = await PostBuild(console, project, linkResult);
								}
							}

							if (linkedReferences.ExitCode != 0)
							{
								result = false;
								break;
							}
						}
					}

					ClearBuildFlags(project as IStandardProject);
				}
			}

			console.WriteLine();

			if (terminateBuild)
			{
				result = false;
			}

			if (result)
			{
				console.WriteLine("Build Successful");
			}
			else
			{
				console.WriteLine("Build Failed");
			}

            foreach(var define in injectedDefines)
            {
                (project as IStandardProject).Defines.Remove(define);
            }

            project.Save();

			return result;
		}
		private LinkResult Link(IConsole console, IStandardProject superProject, CompileResult compileResult,
			CompileResult linkResults, string label = "")
		{
			var binDirectory = compileResult.Project.GetBinDirectory(superProject);

			if (!Directory.Exists(binDirectory))
			{
				Directory.CreateDirectory(binDirectory);
			}

			var outputLocation = binDirectory;

			var executable = Path.Combine(outputLocation, compileResult.Project.Name);

			if (!string.IsNullOrEmpty(label))
			{
				executable += string.Format("-{0}", label);
			}

			if (compileResult.Project.Type == ProjectType.StaticLibrary)
			{
				executable = Path.Combine(outputLocation, "lib" + compileResult.Project.Name);
				executable += StaticLibraryExtension;
			}
			else
			{
				executable += ExecutableExtension;
			}

			if (!Directory.Exists(outputLocation))
			{
				Directory.CreateDirectory(outputLocation);
			}

			var link = false;
			foreach (var objectFile in compileResult.ObjectLocations)
			{
				if (System.IO.File.GetLastWriteTime(objectFile) > System.IO.File.GetLastWriteTime(executable))
				{
					link = true;
					break;
				}
			}

			if (!link)
			{
				foreach (var library in compileResult.LibraryLocations)
				{
					if (System.IO.File.GetLastWriteTime(library) > System.IO.File.GetLastWriteTime(executable))
					{
						link = true;
						break;
					}
				}
			}

			var linkResult = new LinkResult {Executable = executable};

			if (link)
			{
				console.OverWrite(string.Format("[LL]    [{0}]", compileResult.Project.Name));
				linkResult = Link(console, superProject, compileResult.Project, compileResult, executable);
			}

			if (linkResult.ExitCode == 0)
			{
				if (compileResult.Project.Type == ProjectType.StaticLibrary)
				{
                    if (compileResult.ObjectLocations.Count > 0)  // This is where we have a libray with just headers.
                    {
                        linkResults.LibraryLocations.Add(executable);
                    }
				}
				else
				{
					superProject.Executable = superProject.Location.MakeRelativePath(linkResult.Executable).ToAvalonPath();
					superProject.Save();
					console.WriteLine();
					Size(console, compileResult.Project, linkResult);
					linkResults.ExecutableLocations.Add(executable);
				}
			}
			else if (linkResults.ExitCode == 0)
			{
				linkResults.ExitCode = linkResult.ExitCode;
			}

            return linkResult;
		}
		private async Task CompileProject(IConsole console, IStandardProject superProject, IStandardProject project,
			List<CompileResult> results = null)
		{
			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);
								}
							}
						}
					}
				}
			}
		}
		public override LinkResult Link(IConsole console, IStandardProject superProject, IStandardProject project,
			CompileResult assemblies, string outputDirectory)
		{
			var result = new LinkResult();

			var startInfo = new ProcessStartInfo();

			startInfo.FileName = Path.Combine(BaseDirectory, "GCC\\bin", "arm-none-eabi-gcc.exe");

			if (project.Type == ProjectType.StaticLibrary)
			{
				startInfo.FileName = Path.Combine(BaseDirectory, "GCC\\bin", "arm-none-eabi-ar.exe");
			}

			startInfo.WorkingDirectory = project.Solution.CurrentDirectory;

			if (Path.IsPathRooted(startInfo.FileName) && !System.IO.File.Exists(startInfo.FileName))
			{
				result.ExitCode = -1;
				console.WriteLine("Unable to find linker executable (" + startInfo.FileName + ") Check project compiler settings.");
				return result;
			}

			// GenerateLinkerScript(project);

			var objectArguments = string.Empty;
			foreach (var obj in assemblies.ObjectLocations)
			{
				objectArguments += obj + " ";
			}

			var libs = string.Empty;
			foreach (var lib in assemblies.LibraryLocations)
			{
				libs += lib + " ";
			}

			if (!Directory.Exists(outputDirectory))
			{
				Directory.CreateDirectory(outputDirectory);
			}

			var outputName = Path.GetFileNameWithoutExtension(project.Location) + ".elf";

			if (project.Type == ProjectType.StaticLibrary)
			{
				outputName = "lib" + Path.GetFileNameWithoutExtension(project.Name) + ".a";
			}

			var executable = Path.Combine(outputDirectory, outputName);

			var linkedLibraries = string.Empty;

			foreach (var libraryPath in project.StaticLibraries)
			{
				var relativePath = project.CurrentDirectory;

				var libName = Path.GetFileNameWithoutExtension(libraryPath).Substring(3);

				linkedLibraries += string.Format(" -L\"{0}\" -l{1} ", relativePath, libName);
			}

			foreach (var lib in project.BuiltinLibraries)
			{
				linkedLibraries += string.Format("-l{0} ", lib);
			}


			// Hide console window
			startInfo.UseShellExecute = false;
			startInfo.RedirectStandardOutput = true;
			startInfo.RedirectStandardError = true;
			startInfo.RedirectStandardInput = true;
			startInfo.CreateNoWindow = true;

			startInfo.Arguments = string.Format("{0} -o{1} {2} -Wl,--start-group {3} {4} -Wl,--end-group",
				GetLinkerArguments(superProject, project), executable, objectArguments, linkedLibraries, libs);

			if (project.Type == ProjectType.StaticLibrary)
			{
				startInfo.Arguments = string.Format("rvs {0} {1}", executable, objectArguments);
			}

			//console.WriteLine(Path.GetFileNameWithoutExtension(startInfo.FileName) + " " + startInfo.Arguments);
			//console.WriteLine ("[LL] - " + startInfo.Arguments);

			using (var process = Process.Start(startInfo))
			{
				process.OutputDataReceived += (sender, e) =>
				{
					//console.WriteLine(e.Data);
				};

				process.ErrorDataReceived += (sender, e) =>
				{
					if (e.Data != null && !e.Data.Contains("creating"))
					{
						console.WriteLine(e.Data);
					}
				};

				process.BeginOutputReadLine();

				process.BeginErrorReadLine();

				process.WaitForExit();

				result.ExitCode = process.ExitCode;

				if (result.ExitCode == 0)
				{
					result.Executable = executable;
				}
			}

			return result;
		}
		public abstract LinkResult Link(IConsole console, IStandardProject superProject, IStandardProject project,
			CompileResult assemblies, string outputPath);
Exemple #6
0
        public async Task <bool> Build(IConsole console, IProject project, string label = "", IEnumerable <string> defines = null)
        {
            if (!ValidateToolchainExecutables(console))
            {
                return(false);
            }

            console.Clear();

            var result = await PreBuild(console, project);

            console.WriteLine("Starting Build...");

            terminateBuild = !result;

            SetFileCount(project as IStandardProject);
            buildCount = 0;

            var compiledProjects = new List <CompileResult>();

            List <Definition> injectedDefines = new List <Definition>();

            if (defines != null)
            {
                foreach (var define in defines)
                {
                    var injectableDefinition = new Definition()
                    {
                        Global = true, Value = define
                    };
                    (project as IStandardProject).Defines.Add(injectableDefinition);
                    injectedDefines.Add(injectableDefinition);
                }
            }

            if (!terminateBuild)
            {
                await CompileProject(console, project as IStandardProject, project as IStandardProject, compiledProjects);

                if (!terminateBuild)
                {
                    await WaitForCompileJobs();

                    foreach (var compiledReference in compiledProjects)
                    {
                        result = compiledReference.ExitCode == 0;

                        if (!result)
                        {
                            break;
                        }
                    }

                    if (result)
                    {
                        var linkedReferences = new CompileResult();
                        linkedReferences.Project = project as IStandardProject;

                        foreach (var compiledProject in compiledProjects)
                        {
                            if (compiledProject.Project.Location != project.Location)
                            {
                                var linkResult = Link(console, project as IStandardProject, compiledProject, linkedReferences);
                            }
                            else
                            {
                                // if (linkedReferences.Count > 0)
                                {
                                    linkedReferences.ObjectLocations         = compiledProject.ObjectLocations;
                                    linkedReferences.NumberOfObjectsCompiled = compiledProject.NumberOfObjectsCompiled;
                                    var linkResult = Link(console, project as IStandardProject, linkedReferences, linkedReferences, label);
                                    result = await PostBuild(console, project, linkResult);
                                }
                            }

                            if (linkedReferences.ExitCode != 0)
                            {
                                result = false;
                                break;
                            }
                        }
                    }

                    ClearBuildFlags(project as IStandardProject);
                }
            }

            console.WriteLine();

            if (terminateBuild)
            {
                result = false;
            }

            if (result)
            {
                console.WriteLine("Build Successful");
            }
            else
            {
                console.WriteLine("Build Failed");
            }

            foreach (var define in injectedDefines)
            {
                (project as IStandardProject).Defines.Remove(define);
            }

            project.Save();

            return(result);
        }
		public override CompileResult Compile(IConsole console, IStandardProject superProject, IStandardProject project,
			ISourceFile file, string outputFile)
		{
			var result = new CompileResult();

			if (Path.GetExtension(file.FilePath) == ".cs")
			{
				CompileCS(console, superProject, project, file, outputFile);

				TransformMSIL(console, superProject, project, file, outputFile);

				CompileLLVMIR(console, superProject, project, file, outputFile + ".bc", outputFile);
			}
			else if (Path.GetExtension(file.FilePath) == ".cpp" || Path.GetExtension(file.FilePath) == ".c")
			{
				var startInfo = new ProcessStartInfo();

				if (file.Extension == ".cpp")
				{
					startInfo.FileName = Path.Combine(BaseDirectory, "GCC\\bin", "arm-none-eabi-g++.exe");
				}
				else
				{
					startInfo.FileName = Path.Combine(BaseDirectory, "GCC\\bin", "arm-none-eabi-gcc.exe");
				}


				startInfo.WorkingDirectory = project.Solution.CurrentDirectory;

				if (Path.IsPathRooted(startInfo.FileName) && !System.IO.File.Exists(startInfo.FileName))
				{
					result.ExitCode = -1;
					console.WriteLine("Unable to find compiler (" + startInfo.FileName + ") Please check project compiler settings.");
				}
				else
				{
					var fileArguments = string.Empty;

					if (file.Extension == ".cpp")
					{
						fileArguments = "-x c++ -std=c++14 -fno-use-cxa-atexit";
					}

					startInfo.Arguments = string.Format("{0} {1} {2} -o{3} -MMD -MP", GetCompilerArguments(superProject, project, file),
						fileArguments, file.Location, outputFile);

					// Hide console window
					startInfo.UseShellExecute = false;
					startInfo.RedirectStandardOutput = true;
					startInfo.RedirectStandardError = true;
					startInfo.CreateNoWindow = true;

					//console.WriteLine (Path.GetFileNameWithoutExtension(startInfo.FileName) + " " + startInfo.Arguments);

					using (var process = Process.Start(startInfo))
					{
						process.OutputDataReceived += (sender, e) => { console.WriteLine(e.Data); };

						process.ErrorDataReceived += (sender, e) =>
						{
							if (e.Data != null)
							{
								console.WriteLine();
								console.WriteLine(e.Data);
							}
						};

						process.BeginOutputReadLine();

						process.BeginErrorReadLine();

						process.WaitForExit();

						result.ExitCode = process.ExitCode;
					}
				}
			}

			return result;
		}
Exemple #8
0
        private LinkResult Link(IConsole console, IStandardProject superProject, CompileResult compileResult,
                                CompileResult linkResults, string label = "")
        {
            var binDirectory = compileResult.Project.GetBinDirectory(superProject);

            if (!Directory.Exists(binDirectory))
            {
                Directory.CreateDirectory(binDirectory);
            }

            var outputLocation = binDirectory;

            var executable = Path.Combine(outputLocation, compileResult.Project.Name);

            if (!string.IsNullOrEmpty(label))
            {
                executable += string.Format("-{0}", label);
            }

            if (compileResult.Project.Type == ProjectType.StaticLibrary)
            {
                executable  = Path.Combine(outputLocation, "lib" + compileResult.Project.Name);
                executable += StaticLibraryExtension;
            }
            else
            {
                executable += ExecutableExtension;
            }

            if (!Directory.Exists(outputLocation))
            {
                Directory.CreateDirectory(outputLocation);
            }

            var link = false;

            foreach (var objectFile in compileResult.ObjectLocations)
            {
                if (System.IO.File.GetLastWriteTime(objectFile) > System.IO.File.GetLastWriteTime(executable))
                {
                    link = true;
                    break;
                }
            }

            if (!link)
            {
                foreach (var library in compileResult.LibraryLocations)
                {
                    if (System.IO.File.GetLastWriteTime(library) > System.IO.File.GetLastWriteTime(executable))
                    {
                        link = true;
                        break;
                    }
                }
            }

            var linkResult = new LinkResult {
                Executable = executable
            };

            if (link)
            {
                console.OverWrite(string.Format("[LL]    [{0}]", compileResult.Project.Name));
                linkResult = Link(console, superProject, compileResult.Project, compileResult, executable);
            }

            if (linkResult.ExitCode == 0)
            {
                if (compileResult.Project.Type == ProjectType.StaticLibrary)
                {
                    if (compileResult.ObjectLocations.Count > 0)  // This is where we have a libray with just headers.
                    {
                        linkResults.LibraryLocations.Add(executable);
                    }
                }
                else
                {
                    superProject.Executable = superProject.Location.MakeRelativePath(linkResult.Executable).ToAvalonPath();
                    superProject.Save();
                    console.WriteLine();
                    Size(console, compileResult.Project, linkResult);
                    linkResults.ExecutableLocations.Add(executable);
                }
            }
            else if (linkResults.ExitCode == 0)
            {
                linkResults.ExitCode = linkResult.ExitCode;
            }

            return(linkResult);
        }
Exemple #9
0
        private async Task CompileProject(IConsole console, IStandardProject superProject, IStandardProject project,
                                          List <CompileResult> results = null)
        {
            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);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #10
0
 public abstract LinkResult Link(IConsole console, IStandardProject superProject, IStandardProject project,
                                 CompileResult assemblies, string outputPath);
        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();

                        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);
                                }
                            }
                        }
                    }
                }
            }
        }
        public async Task <bool> BuildAsync(IConsole console, IProject project, string label = "", IEnumerable <string> defines = null)
        {
            try
            {
                if (!await InstallAsync(console, project))
                {
                    console.WriteLine("Failed: Unable to install or initialise toolchain.");
                    return(false);
                }
            }
            catch (Exception e)
            {
                console.WriteLine("Failed: Unable to install or initialise toolchain. Due to an unexpected error.");
                console.WriteLine();

                console.WriteLine(e.Message);
                console.WriteLine(e.StackTrace);
            }

            console.Clear();
            IoC.Get <IErrorList>().Remove(this);

            console.WriteLine("Starting Build...");
            console.WriteLine();

            if (!ValidateToolchainExecutables(console))
            {
                console.WriteLine("Failed: Unable to find toolchain executables.");
                return(false);
            }

            await BeforeBuild(console, project);

            var preBuildCommands  = (project as IStandardProject).PreBuildCommands;
            var postBuildCommands = (project as IStandardProject).PostBuildCommands;

            bool result = true;

            if (preBuildCommands.Count > 0)
            {
                console.WriteLine("Pre-Build Commands:");

                result = ExecuteCommands(console, project, preBuildCommands);
            }

            terminateBuild = !result;

            SetFileCount(project as IStandardProject);
            buildCount = 0;

            var compiledProjects = new List <CompileResult>();

            List <Definition> injectedDefines = new List <Definition>();

            if (defines != null)
            {
                foreach (var define in defines)
                {
                    var injectableDefinition = new Definition()
                    {
                        Global = true, Value = define
                    };
                    (project as IStandardProject).Defines.Add(injectableDefinition);
                    injectedDefines.Add(injectableDefinition);
                }
            }

            if (!terminateBuild)
            {
                await CompileProject(console, project as IStandardProject, project as IStandardProject, compiledProjects);

                if (!terminateBuild)
                {
                    await WaitForCompileJobs();

                    foreach (var compiledReference in compiledProjects)
                    {
                        result = compiledReference.ExitCode == 0;

                        if (!result)
                        {
                            break;
                        }
                    }

                    if (result)
                    {
                        var linkedReferences = new CompileResult
                        {
                            Project = project as IStandardProject
                        };

                        foreach (var compiledProject in compiledProjects)
                        {
                            if (compiledProject.Project.Location != project.Location)
                            {
                                var linkResult = Link(console, project as IStandardProject, compiledProject, linkedReferences);
                            }
                            else
                            {
                                linkedReferences.ObjectLocations         = compiledProject.ObjectLocations;
                                linkedReferences.NumberOfObjectsCompiled = compiledProject.NumberOfObjectsCompiled;
                                var linkResult = Link(console, project as IStandardProject, linkedReferences, linkedReferences, label);

                                console.WriteLine();

                                if (postBuildCommands.Count > 0)
                                {
                                    console.WriteLine("Post-Build Commands:");
                                    bool succeess = ExecuteCommands(console, project, postBuildCommands);

                                    if (!succeess)
                                    {
                                        result = false;
                                        break;
                                    }
                                }
                            }

                            if (linkedReferences.ExitCode != 0)
                            {
                                result = false;
                                break;
                            }
                        }
                    }

                    ClearBuildFlags(project as IStandardProject);
                }
            }

            console.WriteLine();

            if (terminateBuild)
            {
                result = false;
            }

            if (result)
            {
                console.WriteLine("Build Successful");
            }
            else
            {
                console.WriteLine("Build Failed");
            }

            foreach (var define in injectedDefines)
            {
                (project as IStandardProject).Defines.Remove(define);
            }

            project.Save();

            return(result);
        }
		public override LinkResult Link(IConsole console, IStandardProject superProject, IStandardProject project,
			CompileResult assemblies, string outputPath)
		{
			var settings = GetSettings(superProject);
			var result = new LinkResult();

			var startInfo = new ProcessStartInfo();

			startInfo.FileName = Path.Combine(BaseDirectory, "arm-none-eabi-gcc" + Platform.ExecutableExtension);

			if (project.Type == ProjectType.StaticLibrary)
			{
				startInfo.FileName = Path.Combine(BaseDirectory, "arm-none-eabi-ar" + Platform.ExecutableExtension);
			}

			startInfo.WorkingDirectory = project.Solution.CurrentDirectory;

			if (!File.Exists(startInfo.FileName))
			{
				result.ExitCode = -1;
				console.WriteLine("Unable to find linker executable (" + startInfo.FileName + ") Check project compiler settings.");
				return result;
			}

			var objectArguments = string.Empty;
			foreach (var obj in assemblies.ObjectLocations)
			{
				objectArguments += obj + " ";
			}

			var libs = string.Empty;
			foreach (var lib in assemblies.LibraryLocations)
			{
				libs += lib + " ";
			}

			var outputDir = Path.GetDirectoryName(outputPath);

			if (!Directory.Exists(outputDir))
			{
				Directory.CreateDirectory(outputDir);
			}

			var outputName = Path.GetFileNameWithoutExtension(outputPath) + ExecutableExtension;

			if (project.Type == ProjectType.StaticLibrary)
			{
				outputName = Path.GetFileNameWithoutExtension(outputPath) + StaticLibraryExtension;
			}
			else
			{
				GenerateLinkerScript(superProject);
			}

			var executable = Path.Combine(outputDir, outputName);

			var linkedLibraries = string.Empty;

			foreach (var libraryPath in project.StaticLibraries)
			{
				var relativePath = Path.GetDirectoryName(libraryPath);

				var libName = Path.GetFileNameWithoutExtension(libraryPath).Substring(3);

				linkedLibraries += string.Format("-L\"{0}\" -l{1} ", relativePath, libName);
			}

			foreach (var lib in project.BuiltinLibraries)
			{
				linkedLibraries += string.Format("-l{0} ", lib);
			}


			// TODO linked libraries won't make it in on nano... Please fix -L directory placement in compile string.
			switch (settings.LinkSettings.Library)
			{
				case LibraryType.NanoCLib:
					linkedLibraries += "-lm -lc_nano -lsupc++_nano -lstdc++_nano ";
					break;

				case LibraryType.BaseCLib:
					linkedLibraries += "-lm -lc -lstdc++ -lsupc++ ";
					break;

				case LibraryType.SemiHosting:
					linkedLibraries += "-lm -lgcc -lc -lrdimon ";
					break;

				case LibraryType.Retarget:
					linkedLibraries += "-lm -lc -lnosys -lstdc++ -lsupc++ ";
					break;
			}

			// Hide console window
			startInfo.UseShellExecute = false;
			startInfo.RedirectStandardOutput = true;
			startInfo.RedirectStandardError = true;
			startInfo.RedirectStandardInput = true;
			startInfo.CreateNoWindow = true;

			if (project.Type == ProjectType.StaticLibrary)
			{
				startInfo.Arguments = string.Format("rvs {0} {1}", executable, objectArguments);
			}
			else
			{
				startInfo.Arguments = string.Format("{0} -o{1} {2} -Wl,--start-group {3} {4} -Wl,--end-group",
					GetLinkerArguments(project), executable, objectArguments, linkedLibraries, libs);
			}

			//console.WriteLine(Path.GetFileNameWithoutExtension(startInfo.FileName) + " " + startInfo.Arguments);
			//console.WriteLine ("[LL] - " + startInfo.Arguments);

			using (var process = Process.Start(startInfo))
			{
				process.OutputDataReceived += (sender, e) =>
				{
					//console.WriteLine(e.Data);
				};

				process.ErrorDataReceived += (sender, e) =>
				{
					if (e.Data != null && !e.Data.Contains("creating"))
					{
						console.WriteLine(e.Data);
					}
				};

				process.BeginOutputReadLine();

				process.BeginErrorReadLine();

				process.WaitForExit();

				result.ExitCode = process.ExitCode;

				if (result.ExitCode == 0)
				{
					result.Executable = executable;
				}
			}

			return result;
		}
		public override CompileResult Compile(IConsole console, IStandardProject superProject, IStandardProject project,
			ISourceFile file, string outputFile)
		{
			var result = new CompileResult();

			var startInfo = new ProcessStartInfo();

			if (file.Language == Language.Cpp)
			{
				startInfo.FileName = Path.Combine(BaseDirectory, "arm-none-eabi-g++" + Platform.ExecutableExtension);
			}
			else
			{
				startInfo.FileName = Path.Combine(BaseDirectory, "arm-none-eabi-gcc" + Platform.ExecutableExtension);
			}


			startInfo.WorkingDirectory = file.CurrentDirectory;

			if (!File.Exists(startInfo.FileName))
			{
				result.ExitCode = -1;
				console.WriteLine("Unable to find compiler (" + startInfo.FileName + ") Please check project compiler settings.");
			}
			else
			{
				var fileArguments = string.Empty;

				if (file.Language == Language.Cpp)
				{
					fileArguments = "-x c++ -fno-use-cxa-atexit";
				}

				startInfo.Arguments = string.Format("{0} {1} {2} -o{3} -MMD -MP", fileArguments,
					GetCompilerArguments(superProject, project, file), file.Location, outputFile);

				// Hide console window
				startInfo.UseShellExecute = false;
				startInfo.RedirectStandardOutput = true;
				startInfo.RedirectStandardError = true;
				startInfo.CreateNoWindow = true;

				//console.WriteLine (Path.GetFileNameWithoutExtension(startInfo.FileName) + " " + startInfo.Arguments);

				using (var process = Process.Start(startInfo))
				{
					process.OutputDataReceived += (sender, e) => { console.WriteLine(e.Data); };

					process.ErrorDataReceived += (sender, e) =>
					{
						if (e.Data != null)
						{
							console.WriteLine();
							console.WriteLine(e.Data);
						}
					};

					process.BeginOutputReadLine();

					process.BeginErrorReadLine();

					process.WaitForExit();

					result.ExitCode = process.ExitCode;
				}
			}

			return result;
		}