Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Side by Side Diff: visual_studio/NativeClientVSAddIn/NaCl.Build.CPPTasks/NaClCompile.cs

Issue 11044024: Implement multi-core builds in MSVS (Closed) Base URL: http://nativeclient-sdk.googlecode.com/svn/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1  1
2 using System; 2 using System;
3 using System.Collections.Generic; 3 using System.Collections.Generic;
4 using System.Text; 4 using System.Text;
5 using System.Collections; 5 using System.Collections;
6 using System.IO; 6 using System.IO;
7 using System.Reflection; 7 using System.Reflection;
8 using System.Resources; 8 using System.Resources;
9 using System.Windows.Forms;
9 using Microsoft.Build.Framework; 10 using Microsoft.Build.Framework;
11 using Microsoft.Win32;
10 using Microsoft.Build.Utilities; 12 using Microsoft.Build.Utilities;
13 using System.Collections.Specialized;
11 14
12 using System.Diagnostics; 15 using System.Diagnostics;
13 16
14 namespace NaCl.Build.CPPTasks 17 namespace NaCl.Build.CPPTasks
15 { 18 {
16 public class NaClCompile : ToolTask 19 public class NaClCompile : ToolTask
17 { 20 {
18 private XamlParser m_XamlParser; 21 private XamlParser m_XamlParser;
19 private ITaskItem[] excludedInputPaths; 22 private ITaskItem[] excludedInputPaths;
20 private ITaskItem[] tlogReadFiles; 23 private ITaskItem[] tlogReadFiles;
(...skipping 11 matching lines...) Expand all
32 [Required] 35 [Required]
33 public string PropertiesFile { get; set; } 36 public string PropertiesFile { get; set; }
34 37
35 [Required] 38 [Required]
36 public ITaskItem[] Sources { get; set; } 39 public ITaskItem[] Sources { get; set; }
37 40
38 [Required] 41 [Required]
39 public string NaCLCompilerPath { get; set; } 42 public string NaCLCompilerPath { get; set; }
40 43
41 [Required] 44 [Required]
42 public string OutputCommandLine { get; set; } 45 public bool OutputCommandLine { get; set; }
46
47 public int ProcessorNumber { get; set; }
48
49 public bool MultiProcessorCompilation { get; set; }
43 50
44 [Required] 51 [Required]
45 public string TrackerLogDirectory { get; set; } 52 public string TrackerLogDirectory { get; set; }
46 53
54 protected override StringDictionary EnvironmentOverride
55 {
56 get {
57 string show = OutputCommandLine ? "1" : "0";
58 string cores = Convert.ToString(ProcessorNumber);
59 return new StringDictionary() {
60 {"NACL_GCC_CORES", cores},
61 {"NACL_GCC_SHOW_COMMANDS", show }
62 };
63 }
64 }
47 65
48 protected override string GenerateFullPathToTool() { return ToolName; } 66 protected override string GenerateFullPathToTool() { return ToolName; }
49 67
50 public NaClCompile() 68 public NaClCompile()
51 : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources ", Assembly.GetExecutingAssembly())) 69 : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources ", Assembly.GetExecutingAssembly()))
52 { 70 {
53 this.pathToLog = string.Empty; 71 this.pathToLog = string.Empty;
54 this.EnvironmentVariables = new string []{"CYGWIN=nodosfilewarning", "LC_CTYPE=C"}; 72 this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning" , "LC_CTYPE=C" };
55 } 73 }
56 74
57 protected IDictionary<string, string> GenerateCommandLinesFromTlog() 75 protected IDictionary<string, string> GenerateCommandLinesFromTlog()
58 { 76 {
59 IDictionary<string, string> cmdLineDictionary = new Dictionary<strin g, string>(StringComparer.OrdinalIgnoreCase); 77 IDictionary<string, string> cmdLineDictionary = new Dictionary<strin g, string>(StringComparer.OrdinalIgnoreCase);
60 string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath"); 78 string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath");
61 if (File.Exists(tlogFilename)) 79 if (File.Exists(tlogFilename))
62 { 80 {
63 using (StreamReader reader = File.OpenText(tlogFilename)) 81 using (StreamReader reader = File.OpenText(tlogFilename))
64 { 82 {
65 string filename = string.Empty; 83 string filename = string.Empty;
66 for (string lineStr = reader.ReadLine(); lineStr != null; li neStr = reader.ReadLine()) 84 for (string lineStr = reader.ReadLine(); lineStr != null; li neStr = reader.ReadLine())
67 { 85 {
68 if (lineStr.Length == 0 || 86 if (lineStr.Length == 0 ||
69 (lineStr[0] == '^' && lineStr.Length == 1)) 87 (lineStr[0] == '^' && lineStr.Length == 1))
70 { 88 {
71 Log.LogMessage(MessageImportance.High, "Invalid line in command tlog"); 89 Log.LogError("Invalid line in command tlog");
72 break; 90 break;
73 } 91 }
74 else if (lineStr[0] == '^') 92 else if (lineStr[0] == '^')
75 { 93 {
76 filename = lineStr.Substring(1); 94 filename = lineStr.Substring(1);
77 } 95 }
78 else 96 else
79 { 97 {
80 cmdLineDictionary[filename] = lineStr; 98 cmdLineDictionary[filename] = lineStr;
81 } 99 }
82 } 100 }
83 } 101 }
84 } 102 }
85 return cmdLineDictionary; 103 return cmdLineDictionary;
86 } 104 }
87 105
88 protected override void LogEventsFromTextOutput(string singleLine, Messa geImportance messageImportance) 106 protected override void LogEventsFromTextOutput(string singleLine, Messa geImportance messageImportance)
89 { 107 {
90 base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(s ingleLine), messageImportance); 108 base.LogEventsFromTextOutput(GCCUtilities.ConvertGCCOutput(singleLin e), messageImportance);
109 }
110
111 static string GetObjectFile(ITaskItem source)
112 {
113 string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectF ileName"));
114 // cl.exe will accept a folder name as the ObjectFileName in which c ase
115 // the objectfile is created as <ObjectFileName>/<basename>.obj. He re
116 // we mimic this behaviour.
117 if ((File.GetAttributes(objectFilePath) & FileAttributes.Directory) != 0)
118 {
119 objectFilePath = Path.Combine(objectFilePath, Path.GetFileName(s ource.ItemSpec));
120 objectFilePath = Path.ChangeExtension(objectFilePath, ".obj");
121 }
122 return objectFilePath;
91 } 123 }
92 124
93 private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTra ckedOutputFiles outputs) 125 private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTra ckedOutputFiles outputs)
94 { 126 {
95 string trackerPath = Path.GetFullPath(TlogDirectory + ReadTLogFilena mes[0]); 127 string trackerPath = Path.GetFullPath(TlogDirectory + ReadTLogFilena mes[0]);
96 128
97 //save tlog for sources not compiled during this execution 129 //save tlog for sources not compiled during this execution
98 TaskItem readTrackerItem = new TaskItem(trackerPath); 130 TaskItem readTrackerItem = new TaskItem(trackerPath);
99 CanonicalTrackedInputFiles files = new CanonicalTrackedInputFiles(ne w TaskItem[] { readTrackerItem }, Sources, outputs, false, false); 131 CanonicalTrackedInputFiles files = new CanonicalTrackedInputFiles(ne w TaskItem[] { readTrackerItem }, Sources, outputs, false, false);
100 files.RemoveEntriesForSource(compiledSources); 132 files.RemoveEntriesForSource(compiledSources);
101 files.SaveTlog(); 133 files.SaveTlog();
102 134
103 //add tlog information for compiled sources 135 //add tlog information for compiled sources
104 using (StreamWriter writer = new StreamWriter(trackerPath, true, Enc oding.Unicode)) 136 using (StreamWriter writer = new StreamWriter(trackerPath, true, Enc oding.Unicode))
105 { 137 {
106 foreach (ITaskItem source in compiledSources) 138 foreach (ITaskItem source in compiledSources)
107 { 139 {
108 string sourcePath = Path.GetFullPath(source.ItemSpec).ToUppe rInvariant(); 140 string sourcePath = Path.GetFullPath(source.ItemSpec).ToUppe rInvariant();
109 141 string objectFilePath = GetObjectFile(source);
110 string objectFilePath = Path.GetFullPath(source.GetMetadata( "ObjectFileName"));
111 string depFilePath = Path.ChangeExtension(objectFilePath, ". d"); 142 string depFilePath = Path.ChangeExtension(objectFilePath, ". d");
112 143
113 try 144 try
114 { 145 {
115 if (File.Exists(depFilePath) == false) 146 if (File.Exists(depFilePath) == false)
116 { 147 {
117 Log.LogMessage(MessageImportance.High, depFilePath + " not found"); 148 Log.LogMessage(MessageImportance.High, depFilePath + " not found");
118 } 149 }
119 else 150 else
120 { 151 {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 string path = Path.Combine(TlogDirectory, WriteTLogFilename); 191 string path = Path.Combine(TlogDirectory, WriteTLogFilename);
161 TaskItem item = new TaskItem(path); 192 TaskItem item = new TaskItem(path);
162 CanonicalTrackedOutputFiles trackedFiles = new CanonicalTrackedOutpu tFiles(new TaskItem[] { item }); 193 CanonicalTrackedOutputFiles trackedFiles = new CanonicalTrackedOutpu tFiles(new TaskItem[] { item });
163 194
164 foreach (ITaskItem sourceItem in compiledSources) 195 foreach (ITaskItem sourceItem in compiledSources)
165 { 196 {
166 //remove this entry associated with compiled source which is abo ut to be recomputed 197 //remove this entry associated with compiled source which is abo ut to be recomputed
167 trackedFiles.RemoveEntriesForSource(sourceItem); 198 trackedFiles.RemoveEntriesForSource(sourceItem);
168 199
169 //add entry with updated information 200 //add entry with updated information
170 trackedFiles.AddComputedOutputForSourceRoot( Path.GetFullPath(so urceItem.ItemSpec).ToUpperInvariant(), 201 trackedFiles.AddComputedOutputForSourceRoot(Path.GetFullPath(sou rceItem.ItemSpec).ToUpperInvariant(),
171 Path.GetFullPath(so urceItem.GetMetadata("ObjectFileName")).ToUpperInvariant()); 202 Path.GetFullPath(Get ObjectFile(sourceItem)).ToUpperInvariant());
172 } 203 }
173 204
174 //output tlog 205 //output tlog
175 trackedFiles.SaveTlog(); 206 trackedFiles.SaveTlog();
176 207
177 return trackedFiles; 208 return trackedFiles;
178 } 209 }
179 210
180 private void OutputCommandTrackerLog(ITaskItem[] compiledSources) 211 private void OutputCommandTrackerLog(ITaskItem[] compiledSources)
181 { 212 {
(...skipping 14 matching lines...) Expand all
196 { 227 {
197 foreach (KeyValuePair<string, string> p in commandLines) 228 foreach (KeyValuePair<string, string> p in commandLines)
198 { 229 {
199 string keyLine = "^" + p.Key; 230 string keyLine = "^" + p.Key;
200 writer.WriteLine(keyLine); 231 writer.WriteLine(keyLine);
201 writer.WriteLine(p.Value); 232 writer.WriteLine(p.Value);
202 } 233 }
203 } 234 }
204 } 235 }
205 236
206 protected string GenerateCommandLineFromProps(ITaskItem sourceFile) 237 protected string GenerateCommandLineFromProps(ITaskItem sourceFile, bool fullOutputName=false)
207 { 238 {
208 StringBuilder commandLine = new StringBuilder(GCCUtilities.s_Command LineLength); 239 StringBuilder commandLine = new StringBuilder(GCCUtilities.s_Command LineLength);
209 240
210 if (sourceFile != null) 241 if (sourceFile != null)
211 { 242 {
212 string sourcePath = GCCUtilities.Convert_Path_Windows_To_Posix(s ourceFile.ToString());
213
214 // Remove rtti items as they are not relevant in C compilation a nd will produce warnings 243 // Remove rtti items as they are not relevant in C compilation a nd will produce warnings
215 if (SourceIsC(sourceFile.ToString())) 244 if (SourceIsC(sourceFile.ToString()))
216 { 245 {
217 commandLine.Replace("-fno-rtti", ""); 246 commandLine.Replace("-fno-rtti", "");
218 commandLine.Replace("-frtti", ""); 247 commandLine.Replace("-frtti", "");
219 } 248 }
220 249
221 //build command line from components and add required switches 250 //build command line from components and add required switches
222 string props = m_XamlParser.Parse(sourceFile); 251 string props = m_XamlParser.Parse(sourceFile, fullOutputName);
223 commandLine.Append(props); 252 commandLine.Append(props);
224 commandLine.Append(" -MD -c "); 253 commandLine.Append(" -MD -c ");
225 commandLine.Append("\"" + sourcePath + "\"");
226 } 254 }
227 255
228 return commandLine.ToString(); 256 return commandLine.ToString();
229 } 257 }
230 258
231 protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSources FromTracking, List<ITaskItem> outOfDateSourcesFromCommandLineChanges) 259 protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSources FromTracking, List<ITaskItem> outOfDateSourcesFromCommandLineChanges)
232 { 260 {
233 List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSources FromTracking); 261 List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSources FromTracking);
234 262
235 foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges) 263 foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges)
(...skipping 29 matching lines...) Expand all
265 return true; 293 return true;
266 } 294 }
267 else 295 else
268 { 296 {
269 return false; 297 return false;
270 } 298 }
271 } 299 }
272 300
273 private int Compile(string pathToTool) 301 private int Compile(string pathToTool)
274 { 302 {
303 // If multiprocess complication is enabled (not the VS default)
304 // and the number of processors to use is not 1, then use the
305 // compiler_wrapper python script to run multiple instances of
306 // gcc
307 if (MultiProcessorCompilation && ProcessorNumber != 1)
308 {
309
310 string envvar = (string)Registry.GetValue("HKEY_CURRENT_USER\\En vironment", "PATH", "");
311 List<string> pathList = new List<string>(envvar.Split(';'));
312 envvar = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\System\\ CurrentControlSet\\Control\\Session Manager\\Environment", "PATH", "");
313 pathList.AddRange(new List<string>(envvar.Split(';')));
314 string pythonExe = null;
315 foreach (string path in pathList)
316 {
317 string testPath = Path.Combine(path, "python.bat");
318 if (File.Exists(testPath))
319 {
320 pythonExe = testPath;
321 break;
322 }
323 testPath = Path.Combine(path, "python.exe");
324 if (File.Exists(testPath))
325 {
326 pythonExe = testPath;
327 break;
328 }
329 }
330
331 if (pythonExe == null)
332 {
333 MessageBox.Show("Multi-processor Compilation with NaCl requi res that python available in the PATH.\n" +
334 "Please disable Multi-processor Compilation in the project properties or add python " +
335 "to the your PATH\n" +
336 "Falling back to serial compilation.\n");
337 }
338 else
339 {
340 return CompileParallel(pathToTool, pythonExe);
341 }
342 }
343 return CompileSerial(pathToTool);
344 }
345
346 private int CompileSerial(string pathToTool)
347 {
275 int returnCode = 0; 348 int returnCode = 0;
276 349
277 foreach (ITaskItem sourceFileItem in CompileSourceList) 350 foreach (ITaskItem sourceItem in CompileSourceList)
278 { 351 {
279 try 352 try
280 { 353 {
281 string commandLine = GenerateCommandLineFromProps(sourceFile Item); 354 string commandLine = GenerateCommandLineFromProps(sourceItem , true);
355 commandLine += "\"" + GCCUtilities.ConvertPathWindowsToPosix (sourceItem.ToString()) + "\"";
282 356
283 base.Log.LogMessageFromText(Path.GetFileName(sourceFileItem. ToString()), MessageImportance.High); 357 if (OutputCommandLine)
284
285 if (OutputCommandLine == "true")
286 { 358 {
287 string logMessage = pathToTool + " " + commandLine; 359 string logMessage = pathToTool + " " + commandLine;
288 Log.LogMessageFromText(logMessage, MessageImportance.Hig h); 360 Log.LogMessage(logMessage);
361 }
362 else
363 {
364 base.Log.LogMessage(Path.GetFileName(sourceItem.ToString ()));
289 } 365 }
290 366
291 367
292 // compile 368 // compile
293 returnCode = base.ExecuteTool(pathToTool, commandLine, strin g.Empty); 369 returnCode = base.ExecuteTool(pathToTool, commandLine, strin g.Empty);
294 } 370 }
295 catch (Exception) 371 catch (Exception)
296 { 372 {
297 returnCode = base.ExitCode; 373 returnCode = base.ExitCode;
298 } 374 }
299 375
300 //abort if an error was encountered 376 //abort if an error was encountered
301 if (returnCode != 0) 377 if (returnCode != 0)
302 { 378 {
303 return returnCode; 379 return returnCode;
304 } 380 }
305 } 381 }
306 return returnCode; 382 return returnCode;
307 } 383 }
308 384
385 private int CompileParallel(string pathToTool, string pythonExe)
386 {
387 int returnCode = 0;
388
389 // Compute sources that can be compiled together.
390 Dictionary<string, List<ITaskItem>> srcGroups =
391 new Dictionary<string, List<ITaskItem>>();
392
393 foreach (ITaskItem sourceItem in CompileSourceList)
394 {
395 string commandLine = GenerateCommandLineFromProps(sourceItem);
396 if (srcGroups.ContainsKey(commandLine))
397 {
398 srcGroups[commandLine].Add(sourceItem);
399 }
400 else
401 {
402 srcGroups.Add(commandLine, new List<ITaskItem> {sourceItem}) ;
403 }
404 }
405
406 string pythonScript = Path.GetDirectoryName(Path.GetDirectoryName(Pr opertiesFile));
407 pythonScript = Path.Combine(pythonScript, "compiler_wrapper.py");
408
409 foreach (KeyValuePair<string, List<ITaskItem>> entry in srcGroups)
410 {
411 string commandLine = entry.Key;
412 string cmd = "\"" + pathToTool + "\" " + commandLine + "--";
413 List<ITaskItem> sources = entry.Value;
414
415 foreach (ITaskItem sourceItem in sources)
416 {
417 string src = GCCUtilities.ConvertPathWindowsToPosix(sourceIt em.ToString());
418 cmd += " \"" + src + "\"";
419 }
420
421 try
422 {
423 // compile this group of sources
424 returnCode = base.ExecuteTool(pythonExe, cmd, "\"" + pythonS cript + "\"");
425 }
426 catch (Exception e)
427 {
428 Log.LogMessage("compiler exception: {0}", e);
429 returnCode = base.ExitCode;
430 }
431
432 //abort if an error was encountered
433 if (returnCode != 0)
434 break;
435 }
436
437 Log.LogMessage(MessageImportance.Low, "compiler returned: {0}", retu rnCode);
438 return returnCode;
439 }
440
309 protected override int ExecuteTool(string pathToTool, string responseFil eCommands, string commandLineCommands) 441 protected override int ExecuteTool(string pathToTool, string responseFil eCommands, string commandLineCommands)
310 { 442 {
311 if (File.Exists(pathToTool) == false) 443 if (File.Exists(pathToTool) == false)
312 { 444 {
313 base.Log.LogMessageFromText("Unable to find NaCL compiler: " + p athToTool, MessageImportance.High); 445 base.Log.LogMessageFromText("Unable to find NaCL compiler: " + p athToTool, MessageImportance.High);
314 return -1; 446 return -1;
315 } 447 }
316 448
317 int returnCode = -1; 449 int returnCode = -1;
318 450
(...skipping 17 matching lines...) Expand all
336 { 468 {
337 if (this.TrackFileAccess || this.MinimalRebuildFromTracking) 469 if (this.TrackFileAccess || this.MinimalRebuildFromTracking)
338 { 470 {
339 this.SetTrackerLogPaths(); 471 this.SetTrackerLogPaths();
340 } 472 }
341 473
342 //check if full recompile is required otherwise perform incremental 474 //check if full recompile is required otherwise perform incremental
343 if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking == false) 475 if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking == false)
344 { 476 {
345 this.CompileSourceList = this.Sources; 477 this.CompileSourceList = this.Sources;
346 if ((this.CompileSourceList == null) || (this.CompileSourceList. Length == 0)) 478 if (this.CompileSourceList == null || this.CompileSourceList.Len gth == 0)
347 { 479 {
348 this.SkippedExecution = true; 480 this.SkippedExecution = true;
349 } 481 }
350 } 482 }
351 else 483 else
352 { 484 {
353 //retrieve list of sources out of date due to command line chang es 485 //retrieve list of sources out of date due to command line chang es
354 List<ITaskItem> outOfDateSourcesFromCommandLineChanges = this.Ge tOutOfDateSourcesFromCommandLineChanges(); 486 List<ITaskItem> outOfDateSourcesFromCommandLineChanges = this.Ge tOutOfDateSourcesFromCommandLineChanges();
355 487
356 //retrieve sources out of date due to tracking 488 //retrieve sources out of date due to tracking
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 767
636 protected override Encoding ResponseFileEncoding 768 protected override Encoding ResponseFileEncoding
637 { 769 {
638 get 770 get
639 { 771 {
640 return Encoding.ASCII; 772 return Encoding.ASCII;
641 } 773 }
642 } 774 }
643 } 775 }
644 } 776 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698