| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 using System; | 4 using System; |
| 5 using System.Collections.Generic; | 5 using System.Collections.Generic; |
| 6 using System.Text; | 6 using System.Text; |
| 7 using System.Collections; | 7 using System.Collections; |
| 8 using System.IO; | 8 using System.IO; |
| 9 using System.Reflection; | 9 using System.Reflection; |
| 10 using System.Resources; | 10 using System.Resources; |
| 11 using System.Windows.Forms; | 11 using System.Windows.Forms; |
| 12 using Microsoft.Build.Framework; | 12 using Microsoft.Build.Framework; |
| 13 using Microsoft.Win32; | 13 using Microsoft.Win32; |
| 14 using Microsoft.Build.Utilities; | 14 using Microsoft.Build.Utilities; |
| 15 using System.Collections.Specialized; | 15 using System.Collections.Specialized; |
| 16 | 16 |
| 17 using System.Diagnostics; | 17 using System.Diagnostics; |
| 18 | 18 |
| 19 namespace NaCl.Build.CPPTasks | 19 namespace NaCl.Build.CPPTasks |
| 20 { | 20 { |
| 21 public class NaClCompile : NaClToolTask | 21 public class NaClCompile : NaClToolTask |
| 22 { | 22 { |
| 23 [Required] | 23 [Required] |
| 24 public string PropertiesFile { get; set; } | |
| 25 | |
| 26 [Required] | |
| 27 public string NaCLCompilerPath { get; set; } | 24 public string NaCLCompilerPath { get; set; } |
| 28 | 25 |
| 29 public int ProcessorNumber { get; set; } | 26 public int ProcessorNumber { get; set; } |
| 30 | 27 |
| 31 public bool MultiProcessorCompilation { get; set; } | 28 public bool MultiProcessorCompilation { get; set; } |
| 32 | 29 |
| 33 [Required] | 30 [Required] |
| 34 public string ConfigurationType { get; set; } | 31 public string ConfigurationType { get; set; } |
| 35 | 32 |
| 36 [Obsolete] | 33 [Obsolete] |
| 37 protected override StringDictionary EnvironmentOverride | 34 protected override StringDictionary EnvironmentOverride |
| 38 { | 35 { |
| 39 get { | 36 get { |
| 40 string show = OutputCommandLine ? "1" : "0"; | 37 string show = OutputCommandLine ? "1" : "0"; |
| 41 string cores = Convert.ToString(ProcessorNumber); | 38 string cores = Convert.ToString(ProcessorNumber); |
| 42 return new StringDictionary() { | 39 return new StringDictionary() { |
| 43 {"NACL_GCC_CORES", cores}, | 40 {"NACL_GCC_CORES", cores}, |
| 44 {"NACL_GCC_SHOW_COMMANDS", show } | 41 {"NACL_GCC_SHOW_COMMANDS", show } |
| 45 }; | 42 }; |
| 46 } | 43 } |
| 47 } | 44 } |
| 48 | 45 |
| 49 public NaClCompile() | 46 public NaClCompile() |
| 50 : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources
", Assembly.GetExecutingAssembly())) | 47 : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources
", Assembly.GetExecutingAssembly())) |
| 51 { | 48 { |
| 52 this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning"
, "LC_CTYPE=C" }; | 49 this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning"
, "LC_CTYPE=C" }; |
| 53 } | 50 } |
| 54 | 51 |
| 55 protected IDictionary<string, string> GenerateCommandLinesFromTlog() | |
| 56 { | |
| 57 IDictionary<string, string> cmdLineDictionary = new Dictionary<strin
g, string>(StringComparer.OrdinalIgnoreCase); | |
| 58 string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath"); | |
| 59 if (File.Exists(tlogFilename)) | |
| 60 { | |
| 61 using (StreamReader reader = File.OpenText(tlogFilename)) | |
| 62 { | |
| 63 string filename = string.Empty; | |
| 64 for (string lineStr = reader.ReadLine(); lineStr != null; li
neStr = reader.ReadLine()) | |
| 65 { | |
| 66 if (lineStr.Length == 0 || | |
| 67 (lineStr[0] == '^' && lineStr.Length == 1)) | |
| 68 { | |
| 69 Log.LogError("Invalid line in command tlog"); | |
| 70 break; | |
| 71 } | |
| 72 else if (lineStr[0] == '^') | |
| 73 { | |
| 74 filename = lineStr.Substring(1); | |
| 75 } | |
| 76 else | |
| 77 { | |
| 78 cmdLineDictionary[filename] = lineStr; | |
| 79 } | |
| 80 } | |
| 81 } | |
| 82 } | |
| 83 return cmdLineDictionary; | |
| 84 } | |
| 85 | |
| 86 protected override void LogEventsFromTextOutput(string singleLine, Messa
geImportance messageImportance) | 52 protected override void LogEventsFromTextOutput(string singleLine, Messa
geImportance messageImportance) |
| 87 { | 53 { |
| 88 base.LogEventsFromTextOutput(GCCUtilities.ConvertGCCOutput(singleLin
e), messageImportance); | 54 base.LogEventsFromTextOutput(GCCUtilities.ConvertGCCOutput(singleLin
e), messageImportance); |
| 89 } | 55 } |
| 90 | 56 |
| 91 static string GetObjectFile(ITaskItem source) | 57 static string GetObjectFile(ITaskItem source) |
| 92 { | 58 { |
| 93 string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectF
ileName")); | 59 string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectF
ileName")); |
| 94 // cl.exe will accept a folder name as the ObjectFileName in which c
ase | 60 // cl.exe will accept a folder name as the ObjectFileName in which c
ase |
| 95 // the objectfile is created as <ObjectFileName>/<basename>.obj. He
re | 61 // the objectfile is created as <ObjectFileName>/<basename>.obj. He
re |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 { | 102 { |
| 137 //source itself not required | 103 //source itself not required |
| 138 if (filename == sourcePath) | 104 if (filename == sourcePath) |
| 139 continue; | 105 continue; |
| 140 | 106 |
| 141 if (File.Exists(filename) == false) | 107 if (File.Exists(filename) == false) |
| 142 { | 108 { |
| 143 Log.LogMessage(MessageImportance.High, "File
" + sourcePath + " is missing dependency " + filename); | 109 Log.LogMessage(MessageImportance.High, "File
" + sourcePath + " is missing dependency " + filename); |
| 144 } | 110 } |
| 145 | 111 |
| 146 writer.WriteLine(filename); | 112 string fname = filename.ToUpperInvariant(); |
| 113 fname = Path.GetFullPath(fname); |
| 114 writer.WriteLine(fname); |
| 147 } | 115 } |
| 148 | 116 |
| 149 //remove d file | 117 //remove d file |
| 150 try | 118 try |
| 151 { | 119 { |
| 152 File.Delete(depFilePath); | 120 File.Delete(depFilePath); |
| 153 } | 121 } |
| 154 finally | 122 finally |
| 155 { | 123 { |
| 156 | 124 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 181 trackedFiles.AddComputedOutputForSourceRoot(Path.GetFullPath(sou
rceItem.ItemSpec).ToUpperInvariant(), | 149 trackedFiles.AddComputedOutputForSourceRoot(Path.GetFullPath(sou
rceItem.ItemSpec).ToUpperInvariant(), |
| 182 Path.GetFullPath(Get
ObjectFile(sourceItem)).ToUpperInvariant()); | 150 Path.GetFullPath(Get
ObjectFile(sourceItem)).ToUpperInvariant()); |
| 183 } | 151 } |
| 184 | 152 |
| 185 //output tlog | 153 //output tlog |
| 186 trackedFiles.SaveTlog(); | 154 trackedFiles.SaveTlog(); |
| 187 | 155 |
| 188 return trackedFiles; | 156 return trackedFiles; |
| 189 } | 157 } |
| 190 | 158 |
| 159 protected override string TLogCommandForSource(ITaskItem source) |
| 160 { |
| 161 return GenerateCommandLineForSource(source) + " " + source.GetMetada
ta("FullPath").ToUpperInvariant(); |
| 162 } |
| 163 |
| 191 protected override void OutputCommandTLog(ITaskItem[] compiledSources) | 164 protected override void OutputCommandTLog(ITaskItem[] compiledSources) |
| 192 { | 165 { |
| 193 IDictionary<string, string> commandLines = GenerateCommandLinesFromT
log(); | 166 IDictionary<string, string> commandLines = GenerateCommandLinesFromT
log(); |
| 194 | 167 |
| 195 // | 168 // |
| 196 if (compiledSources != null) | 169 if (compiledSources != null) |
| 197 { | 170 { |
| 198 foreach (ITaskItem source in compiledSources) | 171 foreach (ITaskItem source in compiledSources) |
| 199 { | 172 { |
| 200 string rmSource = FileTracker.FormatRootingMarker(source); | 173 string rmSource = FileTracker.FormatRootingMarker(source); |
| 201 commandLines[rmSource] = GenerateCommandLineFromProps(source
) + " " + source.GetMetadata("FullPath").ToUpperInvariant(); | 174 commandLines[rmSource] = TLogCommandForSource(source); |
| 202 } | 175 } |
| 203 } | 176 } |
| 204 | 177 |
| 205 //write tlog | 178 //write tlog |
| 206 using (StreamWriter writer = new StreamWriter(this.TLogCommandFile.G
etMetadata("FullPath"), false, Encoding.Unicode)) | 179 using (StreamWriter writer = new StreamWriter(this.TLogCommandFile.G
etMetadata("FullPath"), false, Encoding.Unicode)) |
| 207 { | 180 { |
| 208 foreach (KeyValuePair<string, string> p in commandLines) | 181 foreach (KeyValuePair<string, string> p in commandLines) |
| 209 { | 182 { |
| 210 string keyLine = "^" + p.Key; | 183 string keyLine = "^" + p.Key; |
| 211 writer.WriteLine(keyLine); | 184 writer.WriteLine(keyLine); |
| 212 writer.WriteLine(p.Value); | 185 writer.WriteLine(p.Value); |
| 213 } | 186 } |
| 214 } | 187 } |
| 215 } | 188 } |
| 216 | 189 |
| 217 protected string GenerateCommandLineFromProps(ITaskItem sourceFile, | 190 protected string GenerateCommandLineForSource(ITaskItem sourceFile, |
| 218 bool fullOutputName=false) | 191 bool fullOutputName=false) |
| 219 { | 192 { |
| 220 StringBuilder commandLine = new StringBuilder(GCCUtilities.s_Command
LineLength); | 193 StringBuilder commandLine = new StringBuilder(GCCUtilities.s_Command
LineLength); |
| 221 | 194 |
| 222 if (sourceFile != null) | 195 //build command line from components and add required switches |
| 196 string props = xamlParser.Parse(sourceFile, fullOutputName); |
| 197 commandLine.Append(props); |
| 198 commandLine.Append(" -c"); |
| 199 |
| 200 // Remove rtti items as they are not relevant in C compilation and w
ill |
| 201 // produce warnings |
| 202 if (SourceIsC(sourceFile.ToString())) |
| 223 { | 203 { |
| 224 //build command line from components and add required switches | 204 commandLine.Replace("-fno-rtti", ""); |
| 225 string props = xamlParser.Parse(sourceFile, fullOutputName); | 205 commandLine.Replace("-frtti", ""); |
| 226 commandLine.Append(props); | 206 } |
| 227 commandLine.Append(" -c "); | |
| 228 | 207 |
| 229 // Remove rtti items as they are not relevant in C compilation a
nd will | 208 if (ConfigurationType == "DynamicLibrary") |
| 230 // produce warnings | 209 { |
| 231 if (SourceIsC(sourceFile.ToString())) | 210 commandLine.Append(" -fPIC"); |
| 232 { | |
| 233 commandLine.Replace("-fno-rtti", ""); | |
| 234 commandLine.Replace("-frtti", ""); | |
| 235 } | |
| 236 | |
| 237 if (ConfigurationType == "DynamicLibrary") | |
| 238 { | |
| 239 commandLine.Append(" -fPIC "); | |
| 240 } | |
| 241 } | 211 } |
| 242 | 212 |
| 243 return commandLine.ToString(); | 213 return commandLine.ToString(); |
| 244 } | 214 } |
| 245 | 215 |
| 246 protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSources
FromTracking, | |
| 247 List<ITaskItem> outOfDateSourcesFromCommandLineChanges) | |
| 248 { | |
| 249 List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSources
FromTracking); | |
| 250 | |
| 251 foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges) | |
| 252 { | |
| 253 if (!mergedSources.Contains(item)) | |
| 254 { | |
| 255 mergedSources.Add(item); | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 return mergedSources.ToArray(); | |
| 260 } | |
| 261 | |
| 262 private int Compile(string pathToTool) | 216 private int Compile(string pathToTool) |
| 263 { | 217 { |
| 264 if (Platform.Equals("pnacl", StringComparison.OrdinalIgnoreCase)) | 218 if (Platform.Equals("pnacl", StringComparison.OrdinalIgnoreCase)) |
| 265 { | 219 { |
| 266 if (!SDKUtilities.FindPython()) | 220 if (!SDKUtilities.FindPython()) |
| 267 { | 221 { |
| 268 Log.LogError("PNaCl compilation requires python in your exec
utable path."); | 222 Log.LogError("PNaCl compilation requires python in your exec
utable path."); |
| 269 return -1; | 223 return -1; |
| 270 } | 224 } |
| 271 | 225 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 return CompileSerial(pathToTool); | 263 return CompileSerial(pathToTool); |
| 310 } | 264 } |
| 311 | 265 |
| 312 private int CompileSerial(string pathToTool) | 266 private int CompileSerial(string pathToTool) |
| 313 { | 267 { |
| 314 int returnCode = 0; | 268 int returnCode = 0; |
| 315 foreach (ITaskItem sourceItem in CompileSourceList) | 269 foreach (ITaskItem sourceItem in CompileSourceList) |
| 316 { | 270 { |
| 317 try | 271 try |
| 318 { | 272 { |
| 319 string commandLine = GenerateCommandLineFromProps(sourceItem
, true); | 273 string commandLine = GenerateCommandLineForSource(sourceItem
, true); |
| 320 commandLine += GCCUtilities.ConvertPathWindowsToPosix(source
Item.ToString()); | 274 commandLine += " " + GCCUtilities.ConvertPathWindowsToPosix(
sourceItem.ToString()); |
| 321 | 275 |
| 322 if (OutputCommandLine) | 276 if (OutputCommandLine) |
| 323 { | 277 { |
| 324 string logMessage = pathToTool + " " + commandLine; | 278 string logMessage = pathToTool + " " + commandLine; |
| 325 Log.LogMessage(logMessage); | 279 Log.LogMessage(logMessage); |
| 326 } | 280 } |
| 327 else | 281 else |
| 328 { | 282 { |
| 329 base.Log.LogMessage(Path.GetFileName(sourceItem.ToString
())); | 283 base.Log.LogMessage(Path.GetFileName(sourceItem.ToString
())); |
| 330 } | 284 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 349 private int CompileParallel(string pathToTool) | 303 private int CompileParallel(string pathToTool) |
| 350 { | 304 { |
| 351 int returnCode = 0; | 305 int returnCode = 0; |
| 352 | 306 |
| 353 // Compute sources that can be compiled together. | 307 // Compute sources that can be compiled together. |
| 354 Dictionary<string, List<ITaskItem>> srcGroups = | 308 Dictionary<string, List<ITaskItem>> srcGroups = |
| 355 new Dictionary<string, List<ITaskItem>>(); | 309 new Dictionary<string, List<ITaskItem>>(); |
| 356 | 310 |
| 357 foreach (ITaskItem sourceItem in CompileSourceList) | 311 foreach (ITaskItem sourceItem in CompileSourceList) |
| 358 { | 312 { |
| 359 string commandLine = GenerateCommandLineFromProps(sourceItem); | 313 string commandLine = GenerateCommandLineForSource(sourceItem); |
| 360 if (srcGroups.ContainsKey(commandLine)) | 314 if (srcGroups.ContainsKey(commandLine)) |
| 361 { | 315 { |
| 362 srcGroups[commandLine].Add(sourceItem); | 316 srcGroups[commandLine].Add(sourceItem); |
| 363 } | 317 } |
| 364 else | 318 else |
| 365 { | 319 { |
| 366 srcGroups.Add(commandLine, new List<ITaskItem> {sourceItem})
; | 320 srcGroups.Add(commandLine, new List<ITaskItem> {sourceItem})
; |
| 367 } | 321 } |
| 368 } | 322 } |
| 369 | 323 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 { | 370 { |
| 417 returnCode = Compile(pathToTool); | 371 returnCode = Compile(pathToTool); |
| 418 } | 372 } |
| 419 finally | 373 finally |
| 420 { | 374 { |
| 421 | 375 |
| 422 } | 376 } |
| 423 return returnCode; | 377 return returnCode; |
| 424 } | 378 } |
| 425 | 379 |
| 426 protected void CalcSourcesToCompile() | 380 protected override string GenerateResponseFileCommands() |
| 427 { | 381 { |
| 428 //check if full recompile is required otherwise perform incremental | 382 return ""; |
| 429 if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking
== false) | |
| 430 { | |
| 431 this.CompileSourceList = this.Sources; | |
| 432 return; | |
| 433 } | |
| 434 | |
| 435 //retrieve list of sources out of date due to command line changes | |
| 436 List<ITaskItem> outOfDateSourcesFromCommandLine = GetOutOfDateSource
sFromCmdLineChanges(); | |
| 437 | |
| 438 //retrieve sources out of date due to tracking | |
| 439 CanonicalTrackedOutputFiles trackedOutputFiles = new CanonicalTracke
dOutputFiles(this, this.TLogWriteFiles); | |
| 440 this.TrackedInputFiles = new CanonicalTrackedInputFiles(this, | |
| 441 this.TLogRea
dFiles, | |
| 442 this.Sources
, | |
| 443 this.Exclude
dInputPaths, | |
| 444 trackedOutpu
tFiles, | |
| 445 true, | |
| 446 false); | |
| 447 ITaskItem[] outOfDateSourcesFromTracking = this.TrackedInputFiles.Co
mputeSourcesNeedingCompilation(); | |
| 448 | |
| 449 //merge out of date lists | |
| 450 CompileSourceList = MergeOutOfDateSources(outOfDateSourcesFromTracki
ng, outOfDateSourcesFromCommandLine); | |
| 451 | |
| 452 if (this.CompileSourceList.Length == 0) | |
| 453 { | |
| 454 this.SkippedExecution = true; | |
| 455 return; | |
| 456 } | |
| 457 | |
| 458 //remove sources to compile from tracked file list | |
| 459 this.TrackedInputFiles.RemoveEntriesForSource(this.CompileSourceList
); | |
| 460 trackedOutputFiles.RemoveEntriesForSource(this.CompileSourceList); | |
| 461 this.TrackedInputFiles.SaveTlog(); | |
| 462 trackedOutputFiles.SaveTlog(); | |
| 463 } | 383 } |
| 464 | 384 |
| 465 protected bool SourceIsC(string sourceFilename) | 385 protected bool SourceIsC(string sourceFilename) |
| 466 { | 386 { |
| 467 string fileExt = Path.GetExtension(sourceFilename.ToString()); | 387 string fileExt = Path.GetExtension(sourceFilename.ToString()); |
| 468 | 388 |
| 469 if (fileExt == ".c") | 389 if (fileExt == ".c") |
| 470 return true; | 390 return true; |
| 471 else | 391 else |
| 472 return false; | 392 return false; |
| 473 } | 393 } |
| 474 | 394 |
| 475 public override bool Execute() | 395 protected override string CommandTLogFilename |
| 476 { | |
| 477 bool returnResult = false; | |
| 478 | |
| 479 try | |
| 480 { | |
| 481 xamlParser = new XamlParser(PropertiesFile); | |
| 482 if (!Setup()) | |
| 483 return false; | |
| 484 CalcSourcesToCompile(); | |
| 485 returnResult = base.Execute(); | |
| 486 } | |
| 487 finally | |
| 488 { | |
| 489 | |
| 490 } | |
| 491 | |
| 492 return returnResult; | |
| 493 } | |
| 494 | |
| 495 protected List<ITaskItem> GetOutOfDateSourcesFromCmdLineChanges() | |
| 496 { | |
| 497 //get dictionary of source + command lines | |
| 498 IDictionary<string, string> dictionary = this.GenerateCommandLinesFr
omTlog(); | |
| 499 List<ITaskItem> outOfDateSources = new List<ITaskItem>(); | |
| 500 | |
| 501 //add sources to out of date list if the tlog dictionary string do n
ot match the generated command line string | |
| 502 StringBuilder currentCommandLine = new StringBuilder(GCCUtilities.s_
CommandLineLength); | |
| 503 foreach (ITaskItem sourceItem in Sources) | |
| 504 { | |
| 505 currentCommandLine.Length = 0; | |
| 506 | |
| 507 currentCommandLine.Append(GenerateCommandLineFromProps(sourceIte
m)); | |
| 508 currentCommandLine.Append(" "); | |
| 509 currentCommandLine.Append(sourceItem.GetMetadata("FullPath").ToU
pperInvariant()); | |
| 510 | |
| 511 string tlogCommandLine = null; | |
| 512 if (dictionary.TryGetValue(FileTracker.FormatRootingMarker(sourc
eItem), out tlogCommandLine)) | |
| 513 { | |
| 514 if ((tlogCommandLine == null) || !currentCommandLine.ToStrin
g().Equals(tlogCommandLine, StringComparison.Ordinal)) | |
| 515 { | |
| 516 outOfDateSources.Add(sourceItem); | |
| 517 } | |
| 518 } | |
| 519 else | |
| 520 { | |
| 521 outOfDateSources.Add(sourceItem); | |
| 522 } | |
| 523 } | |
| 524 return outOfDateSources; | |
| 525 } | |
| 526 | |
| 527 [Output] | |
| 528 public ITaskItem[] CompileSourceList | |
| 529 { | 396 { |
| 530 get | 397 get |
| 531 { | 398 { |
| 532 return this.compileSourceList; | 399 return BaseTool() + ".compile.command.1.tlog"; |
| 533 } | |
| 534 set | |
| 535 { | |
| 536 this.compileSourceList = value; | |
| 537 } | 400 } |
| 538 } | 401 } |
| 539 | 402 |
| 403 protected override string[] ReadTLogFilenames |
| 404 { |
| 405 get |
| 406 { |
| 407 return new string[] { BaseTool() + ".compile.read.1.tlog" }; |
| 408 } |
| 409 } |
| 410 |
| 411 protected override string WriteTLogFilename |
| 412 { |
| 413 get |
| 414 { |
| 415 return BaseTool() + ".compile.write.1.tlog"; |
| 416 } |
| 417 } |
| 418 |
| 540 protected override string ToolName | 419 protected override string ToolName |
| 541 { | 420 { |
| 542 get | 421 get |
| 543 { | 422 { |
| 544 return NaCLCompilerPath; | 423 return NaCLCompilerPath; |
| 545 } | 424 } |
| 546 } | 425 } |
| 547 | 426 |
| 548 } | 427 } |
| 549 } | 428 } |
| OLD | NEW |