| Index: visual_studio/NativeClientVSAddIn/NaCl.Build.CPPTasks/NaClCompile.cs
|
| diff --git a/visual_studio/NativeClientVSAddIn/NaCl.Build.CPPTasks/NaClCompile.cs b/visual_studio/NativeClientVSAddIn/NaCl.Build.CPPTasks/NaClCompile.cs
|
| index 272353f6ba38eb256f5b9d58575193318ba59699..fc9f9253986ce3861a7a1b6f4597b197c89fc98a 100644
|
| --- a/visual_studio/NativeClientVSAddIn/NaCl.Build.CPPTasks/NaClCompile.cs
|
| +++ b/visual_studio/NativeClientVSAddIn/NaCl.Build.CPPTasks/NaClCompile.cs
|
| @@ -1,4 +1,4 @@
|
| -
|
| +
|
| using System;
|
| using System.Collections.Generic;
|
| using System.Text;
|
| @@ -6,8 +6,11 @@ using System.Collections;
|
| using System.IO;
|
| using System.Reflection;
|
| using System.Resources;
|
| +using System.Windows.Forms;
|
| using Microsoft.Build.Framework;
|
| +using Microsoft.Win32;
|
| using Microsoft.Build.Utilities;
|
| +using System.Collections.Specialized;
|
|
|
| using System.Diagnostics;
|
|
|
| @@ -39,11 +42,26 @@ namespace NaCl.Build.CPPTasks
|
| public string NaCLCompilerPath { get; set; }
|
|
|
| [Required]
|
| - public string OutputCommandLine { get; set; }
|
| + public bool OutputCommandLine { get; set; }
|
| +
|
| + public int ProcessorNumber { get; set; }
|
| +
|
| + public bool MultiProcessorCompilation { get; set; }
|
|
|
| [Required]
|
| public string TrackerLogDirectory { get; set; }
|
|
|
| + protected override StringDictionary EnvironmentOverride
|
| + {
|
| + get {
|
| + string show = OutputCommandLine ? "1" : "0";
|
| + string cores = Convert.ToString(ProcessorNumber);
|
| + return new StringDictionary() {
|
| + {"NACL_GCC_CORES", cores},
|
| + {"NACL_GCC_SHOW_COMMANDS", show }
|
| + };
|
| + }
|
| + }
|
|
|
| protected override string GenerateFullPathToTool() { return ToolName; }
|
|
|
| @@ -51,7 +69,7 @@ namespace NaCl.Build.CPPTasks
|
| : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", Assembly.GetExecutingAssembly()))
|
| {
|
| this.pathToLog = string.Empty;
|
| - this.EnvironmentVariables = new string []{"CYGWIN=nodosfilewarning", "LC_CTYPE=C"};
|
| + this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning", "LC_CTYPE=C" };
|
| }
|
|
|
| protected IDictionary<string, string> GenerateCommandLinesFromTlog()
|
| @@ -68,7 +86,7 @@ namespace NaCl.Build.CPPTasks
|
| if (lineStr.Length == 0 ||
|
| (lineStr[0] == '^' && lineStr.Length == 1))
|
| {
|
| - Log.LogMessage(MessageImportance.High, "Invalid line in command tlog");
|
| + Log.LogError("Invalid line in command tlog");
|
| break;
|
| }
|
| else if (lineStr[0] == '^')
|
| @@ -87,7 +105,21 @@ namespace NaCl.Build.CPPTasks
|
|
|
| protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
|
| {
|
| - base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(singleLine), messageImportance);
|
| + base.LogEventsFromTextOutput(GCCUtilities.ConvertGCCOutput(singleLine), messageImportance);
|
| + }
|
| +
|
| + static string GetObjectFile(ITaskItem source)
|
| + {
|
| + string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectFileName"));
|
| + // cl.exe will accept a folder name as the ObjectFileName in which case
|
| + // the objectfile is created as <ObjectFileName>/<basename>.obj. Here
|
| + // we mimic this behaviour.
|
| + if ((File.GetAttributes(objectFilePath) & FileAttributes.Directory) != 0)
|
| + {
|
| + objectFilePath = Path.Combine(objectFilePath, Path.GetFileName(source.ItemSpec));
|
| + objectFilePath = Path.ChangeExtension(objectFilePath, ".obj");
|
| + }
|
| + return objectFilePath;
|
| }
|
|
|
| private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTrackedOutputFiles outputs)
|
| @@ -106,8 +138,7 @@ namespace NaCl.Build.CPPTasks
|
| foreach (ITaskItem source in compiledSources)
|
| {
|
| string sourcePath = Path.GetFullPath(source.ItemSpec).ToUpperInvariant();
|
| -
|
| - string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectFileName"));
|
| + string objectFilePath = GetObjectFile(source);
|
| string depFilePath = Path.ChangeExtension(objectFilePath, ".d");
|
|
|
| try
|
| @@ -167,8 +198,8 @@ namespace NaCl.Build.CPPTasks
|
| trackedFiles.RemoveEntriesForSource(sourceItem);
|
|
|
| //add entry with updated information
|
| - trackedFiles.AddComputedOutputForSourceRoot( Path.GetFullPath(sourceItem.ItemSpec).ToUpperInvariant(),
|
| - Path.GetFullPath(sourceItem.GetMetadata("ObjectFileName")).ToUpperInvariant());
|
| + trackedFiles.AddComputedOutputForSourceRoot(Path.GetFullPath(sourceItem.ItemSpec).ToUpperInvariant(),
|
| + Path.GetFullPath(GetObjectFile(sourceItem)).ToUpperInvariant());
|
| }
|
|
|
| //output tlog
|
| @@ -203,14 +234,12 @@ namespace NaCl.Build.CPPTasks
|
| }
|
| }
|
|
|
| - protected string GenerateCommandLineFromProps(ITaskItem sourceFile)
|
| + protected string GenerateCommandLineFromProps(ITaskItem sourceFile, bool fullOutputName=false)
|
| {
|
| StringBuilder commandLine = new StringBuilder(GCCUtilities.s_CommandLineLength);
|
|
|
| if (sourceFile != null)
|
| {
|
| - string sourcePath = GCCUtilities.Convert_Path_Windows_To_Posix(sourceFile.ToString());
|
| -
|
| // Remove rtti items as they are not relevant in C compilation and will produce warnings
|
| if (SourceIsC(sourceFile.ToString()))
|
| {
|
| @@ -219,10 +248,9 @@ namespace NaCl.Build.CPPTasks
|
| }
|
|
|
| //build command line from components and add required switches
|
| - string props = m_XamlParser.Parse(sourceFile);
|
| + string props = m_XamlParser.Parse(sourceFile, fullOutputName);
|
| commandLine.Append(props);
|
| commandLine.Append(" -MD -c ");
|
| - commandLine.Append("\"" + sourcePath + "\"");
|
| }
|
|
|
| return commandLine.ToString();
|
| @@ -272,20 +300,68 @@ namespace NaCl.Build.CPPTasks
|
|
|
| private int Compile(string pathToTool)
|
| {
|
| + // If multiprocess complication is enabled (not the VS default)
|
| + // and the number of processors to use is not 1, then use the
|
| + // compiler_wrapper python script to run multiple instances of
|
| + // gcc
|
| + if (MultiProcessorCompilation && ProcessorNumber != 1)
|
| + {
|
| +
|
| + string envvar = (string)Registry.GetValue("HKEY_CURRENT_USER\\Environment", "PATH", "");
|
| + List<string> pathList = new List<string>(envvar.Split(';'));
|
| + envvar = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment", "PATH", "");
|
| + pathList.AddRange(new List<string>(envvar.Split(';')));
|
| + string pythonExe = null;
|
| + foreach (string path in pathList)
|
| + {
|
| + string testPath = Path.Combine(path, "python.bat");
|
| + if (File.Exists(testPath))
|
| + {
|
| + pythonExe = testPath;
|
| + break;
|
| + }
|
| + testPath = Path.Combine(path, "python.exe");
|
| + if (File.Exists(testPath))
|
| + {
|
| + pythonExe = testPath;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (pythonExe == null)
|
| + {
|
| + MessageBox.Show("Multi-processor Compilation with NaCl requires that python available in the PATH.\n" +
|
| + "Please disable Multi-processor Compilation in the project properties or add python " +
|
| + "to the your PATH\n" +
|
| + "Falling back to serial compilation.\n");
|
| + }
|
| + else
|
| + {
|
| + return CompileParallel(pathToTool, pythonExe);
|
| + }
|
| + }
|
| + return CompileSerial(pathToTool);
|
| + }
|
| +
|
| + private int CompileSerial(string pathToTool)
|
| + {
|
| int returnCode = 0;
|
|
|
| - foreach (ITaskItem sourceFileItem in CompileSourceList)
|
| + foreach (ITaskItem sourceItem in CompileSourceList)
|
| {
|
| try
|
| {
|
| - string commandLine = GenerateCommandLineFromProps(sourceFileItem);
|
| + string commandLine = GenerateCommandLineFromProps(sourceItem, true);
|
| + commandLine += "\"" + GCCUtilities.ConvertPathWindowsToPosix(sourceItem.ToString()) + "\"";
|
|
|
| - base.Log.LogMessageFromText(Path.GetFileName(sourceFileItem.ToString()), MessageImportance.High);
|
| -
|
| - if (OutputCommandLine == "true")
|
| + if (OutputCommandLine)
|
| {
|
| string logMessage = pathToTool + " " + commandLine;
|
| - Log.LogMessageFromText(logMessage, MessageImportance.High);
|
| + Log.LogMessage(logMessage);
|
| + }
|
| + else
|
| + {
|
| + base.Log.LogMessage(Path.GetFileName(sourceItem.ToString()));
|
| }
|
|
|
|
|
| @@ -306,6 +382,62 @@ namespace NaCl.Build.CPPTasks
|
| return returnCode;
|
| }
|
|
|
| + private int CompileParallel(string pathToTool, string pythonExe)
|
| + {
|
| + int returnCode = 0;
|
| +
|
| + // Compute sources that can be compiled together.
|
| + Dictionary<string, List<ITaskItem>> srcGroups =
|
| + new Dictionary<string, List<ITaskItem>>();
|
| +
|
| + foreach (ITaskItem sourceItem in CompileSourceList)
|
| + {
|
| + string commandLine = GenerateCommandLineFromProps(sourceItem);
|
| + if (srcGroups.ContainsKey(commandLine))
|
| + {
|
| + srcGroups[commandLine].Add(sourceItem);
|
| + }
|
| + else
|
| + {
|
| + srcGroups.Add(commandLine, new List<ITaskItem> {sourceItem});
|
| + }
|
| + }
|
| +
|
| + string pythonScript = Path.GetDirectoryName(Path.GetDirectoryName(PropertiesFile));
|
| + pythonScript = Path.Combine(pythonScript, "compiler_wrapper.py");
|
| +
|
| + foreach (KeyValuePair<string, List<ITaskItem>> entry in srcGroups)
|
| + {
|
| + string commandLine = entry.Key;
|
| + string cmd = "\"" + pathToTool + "\" " + commandLine + "--";
|
| + List<ITaskItem> sources = entry.Value;
|
| +
|
| + foreach (ITaskItem sourceItem in sources)
|
| + {
|
| + string src = GCCUtilities.ConvertPathWindowsToPosix(sourceItem.ToString());
|
| + cmd += " \"" + src + "\"";
|
| + }
|
| +
|
| + try
|
| + {
|
| + // compile this group of sources
|
| + returnCode = base.ExecuteTool(pythonExe, cmd, "\"" + pythonScript + "\"");
|
| + }
|
| + catch (Exception e)
|
| + {
|
| + Log.LogMessage("compiler exception: {0}", e);
|
| + returnCode = base.ExitCode;
|
| + }
|
| +
|
| + //abort if an error was encountered
|
| + if (returnCode != 0)
|
| + break;
|
| + }
|
| +
|
| + Log.LogMessage(MessageImportance.Low, "compiler returned: {0}", returnCode);
|
| + return returnCode;
|
| + }
|
| +
|
| protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
|
| {
|
| if (File.Exists(pathToTool) == false)
|
| @@ -343,7 +475,7 @@ namespace NaCl.Build.CPPTasks
|
| if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking == false)
|
| {
|
| this.CompileSourceList = this.Sources;
|
| - if ((this.CompileSourceList == null) || (this.CompileSourceList.Length == 0))
|
| + if (this.CompileSourceList == null || this.CompileSourceList.Length == 0)
|
| {
|
| this.SkippedExecution = true;
|
| }
|
|
|