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

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

Issue 10831030: NaCl settings and completed install scripts. (Closed) Base URL: https://nativeclient-sdk.googlecode.com/svn/trunk/src
Patch Set: Created 8 years, 4 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
(Empty)
1 
2 using System;
3 using System.Collections.Generic;
4 using System.Text;
5 using System.Collections;
6 using System.IO;
7 using System.Reflection;
8 using System.Resources;
9 using Microsoft.Build.Framework;
10 using Microsoft.Build.Utilities;
11
12 using System.Diagnostics;
13
14 namespace NaCl.Build.CPPTasks
15 {
16 public class NaClCompile : ToolTask
17 {
18 private XamlParser m_XamlParser;
19 private ITaskItem[] excludedInputPaths;
20 private ITaskItem[] tlogReadFiles;
21 private ITaskItem tlogCommandFile;
22 private ITaskItem[] tlogWriteFiles;
23 private CanonicalTrackedInputFiles trackedInputFiles;
24 private bool skippedExecution;
25 private ITaskItem[] compileSourceList;
26 public bool BuildingInIDE { get; set; }
27 private string m_toolname;
28 private bool trackFileAccess;
29 private bool minimalRebuildFromTracking;
30 private string pathToLog;
31
32 [Required]
33 public string PropertiesFile { get; set; }
34
35 [Required]
36 public ITaskItem[] Sources { get; set; }
37
38 [Required]
39 public string NaCLCompilerPath { get; set; }
40
41 [Required]
42 public string OutputCommandLine { get; set; }
43
44 [Required]
45 public string TrackerLogDirectory { get; set; }
46
47
48 protected override string GenerateFullPathToTool() { return ToolName; }
49
50 public NaClCompile()
51 : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources ", Assembly.GetExecutingAssembly()))
52 {
53 this.pathToLog = string.Empty;
54 }
55
56 protected IDictionary<string, string> GenerateCommandLinesFromTlog()
57 {
58 IDictionary<string, string> cmdLineDictionary = new Dictionary<strin g, string>(StringComparer.OrdinalIgnoreCase);
59 string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath");
60 if (File.Exists(tlogFilename))
61 {
62 using (StreamReader reader = File.OpenText(tlogFilename))
63 {
64 string filename = string.Empty;
65 for (string lineStr = reader.ReadLine(); lineStr != null; li neStr = reader.ReadLine())
66 {
67 if (lineStr.Length == 0 ||
68 (lineStr[0] == '^' && lineStr.Length == 1))
69 {
70 Log.LogMessage(MessageImportance.High, "Invalid line in command tlog");
71 break;
72 }
73 else if (lineStr[0] == '^')
74 {
75 filename = lineStr.Substring(1);
76 }
77 else
78 {
79 cmdLineDictionary[filename] = lineStr;
80 }
81 }
82 }
83 }
84 return cmdLineDictionary;
85 }
86
87 protected override void LogEventsFromTextOutput(string singleLine, Messa geImportance messageImportance)
88 {
89 base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(s ingleLine), messageImportance);
90 }
91
92 private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTra ckedOutputFiles outputs)
93 {
94 string trackerPath = Path.GetFullPath(TlogDirectory + ReadTLogFilena mes[0]);
95
96 //save tlog for sources not compiled during this execution
97 TaskItem readTrackerItem = new TaskItem(trackerPath);
98 CanonicalTrackedInputFiles files = new CanonicalTrackedInputFiles(ne w TaskItem[] { readTrackerItem }, Sources, outputs, false, false);
99 files.RemoveEntriesForSource(compiledSources);
100 files.SaveTlog();
101
102 //add tlog information for compiled sources
103 using (StreamWriter writer = new StreamWriter(trackerPath, true, Enc oding.Unicode))
104 {
105 foreach (ITaskItem source in compiledSources)
106 {
107 string sourcePath = Path.GetFullPath(source.ItemSpec).ToUppe rInvariant();
108
109 string objectFilePath = Path.GetFullPath(source.GetMetadata( "ObjectFileName"));
110 string depFilePath = Path.ChangeExtension(objectFilePath, ". d");
111
112 try
113 {
114 if (File.Exists(depFilePath) == false)
115 {
116 Log.LogMessage(MessageImportance.High, depFilePath + " not found");
117 }
118 else
119 {
120 writer.WriteLine("^" + sourcePath);
121 DependencyParser parser = new DependencyParser(depFi lePath);
122
123 foreach (string filename in parser.Dependencies)
124 {
125 //source itself not required
126 if (filename == sourcePath)
127 continue;
128
129 if (File.Exists(filename) == false)
130 {
131 Log.LogMessage(MessageImportance.High, "File " + sourcePath + " is missing dependency " + filename);
132 }
133
134 writer.WriteLine(filename);
135 }
136
137 //remove d file
138 try
139 {
140 File.Delete(depFilePath);
141 }
142 finally
143 {
144
145 }
146 }
147
148 }
149 catch (Exception)
150 {
151 Log.LogError("Failed to update " + readTrackerItem + " f or " + sourcePath);
152 }
153 }
154 }
155 }
156
157 private CanonicalTrackedOutputFiles OutputWriteTrackerLog(ITaskItem[] co mpiledSources)
158 {
159 string path = Path.Combine(TlogDirectory, WriteTLogFilename);
160 TaskItem item = new TaskItem(path);
161 CanonicalTrackedOutputFiles trackedFiles = new CanonicalTrackedOutpu tFiles(new TaskItem[] { item });
162
163 foreach (ITaskItem sourceItem in compiledSources)
164 {
165 //remove this entry associated with compiled source which is abo ut to be recomputed
166 trackedFiles.RemoveEntriesForSource(sourceItem);
167
168 //add entry with updated information
169 trackedFiles.AddComputedOutputForSourceRoot( Path.GetFullPath(so urceItem.ItemSpec).ToUpperInvariant(),
170 Path.GetFullPath(so urceItem.GetMetadata("ObjectFileName")).ToUpperInvariant());
171 }
172
173 //output tlog
174 trackedFiles.SaveTlog();
175
176 return trackedFiles;
177 }
178
179 private void OutputCommandTrackerLog(ITaskItem[] compiledSources)
180 {
181 IDictionary<string, string> commandLines = GenerateCommandLinesFromT log();
182
183 //
184 if (compiledSources != null)
185 {
186 foreach (ITaskItem source in compiledSources)
187 {
188 string rmSource = FileTracker.FormatRootingMarker(source);
189 commandLines[rmSource] = GenerateCommandLineFromProps(source ) + " " + source.GetMetadata("FullPath").ToUpperInvariant();
190 }
191 }
192
193 //write tlog
194 using (StreamWriter writer = new StreamWriter(this.TLogCommandFile.G etMetadata("FullPath"), false, Encoding.Unicode))
195 {
196 foreach (KeyValuePair<string, string> p in commandLines)
197 {
198 string keyLine = "^" + p.Key;
199 writer.WriteLine(keyLine);
200 writer.WriteLine(p.Value);
201 }
202 }
203 }
204
205 protected string GenerateCommandLineFromProps(ITaskItem sourceFile)
206 {
207 StringBuilder commandLine = new StringBuilder(GCCUtilities.s_Command LineLength);
208
209 if (sourceFile != null)
210 {
211 string sourcePath = GCCUtilities.Convert_Path_Windows_To_Posix(s ourceFile.ToString());
212
213 // Remove rtti items as they are not relevant in C compilation a nd will produce warnings
214 if (SourceIsC(sourceFile.ToString()))
215 {
216 commandLine.Replace("-fno-rtti", "");
217 commandLine.Replace("-frtti", "");
218 }
219
220 //build command line from components and add required switches
221 string props = m_XamlParser.Parse(sourceFile);
222 commandLine.Append(props);
223 commandLine.Append(" -MD -c ");
224 commandLine.Append(sourcePath);
225
226 }
227
228 return commandLine.ToString();
229 }
230
231 protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSources FromTracking, List<ITaskItem> outOfDateSourcesFromCommandLineChanges)
232 {
233 List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSources FromTracking);
234
235 foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges)
236 {
237 if (!mergedSources.Contains(item))
238 {
239 mergedSources.Add(item);
240 }
241 }
242
243 return mergedSources.ToArray();
244 }
245
246 protected bool ForcedRebuildRequired()
247 {
248 string tlogCommandPath = null;
249
250 try
251 {
252 tlogCommandPath = this.TLogCommandFile.GetMetadata("FullPath");
253 }
254 catch (Exception exception)
255 {
256 if (exception is InvalidOperationException || exception is NullR eferenceException)
257 return true;
258 else
259 throw;
260 }
261
262 //if command tlog file does not exist then force rebuild is required
263 if (File.Exists(tlogCommandPath) == false)
264 {
265 return true;
266 }
267 else
268 {
269 return false;
270 }
271 }
272
273 private int Compile(string pathToTool)
274 {
275 int returnCode = 0;
276
277 foreach (ITaskItem sourceFileItem in CompileSourceList)
278 {
279 try
280 {
281 string commandLine = GenerateCommandLineFromProps(sourceFile Item);
282
283 base.Log.LogMessageFromText(Path.GetFileName(sourceFileItem. ToString()), MessageImportance.High);
284
285 if (OutputCommandLine == "true")
286 {
287 string logMessage = pathToTool + " " + commandLine;
288 Log.LogMessageFromText(logMessage, MessageImportance.Hig h);
289 }
290
291
292 // compile
293 returnCode = base.ExecuteTool(pathToTool, commandLine, strin g.Empty);
294 }
295 catch (Exception)
296 {
297 returnCode = base.ExitCode;
298 }
299
300 //abort if an error was encountered
301 if (returnCode != 0)
302 {
303 return returnCode;
304 }
305 }
306 return returnCode;
307 }
308
309 protected override int ExecuteTool(string pathToTool, string responseFil eCommands, string commandLineCommands)
310 {
311 if (File.Exists(pathToTool) == false)
312 {
313 base.Log.LogMessageFromText("Unable to find NaCL compiler: " + p athToTool, MessageImportance.High);
314 return -1;
315 }
316
317 int returnCode = -1;
318
319 try
320 {
321 returnCode = Compile(pathToTool);
322 }
323 finally
324 {
325
326 }
327 return returnCode;
328 }
329
330 protected override bool SkipTaskExecution()
331 {
332 return this.skippedExecution;
333 }
334
335 protected void CalcSourcesToCompile()
336 {
337 if (this.TrackFileAccess || this.MinimalRebuildFromTracking)
338 {
339 this.SetTrackerLogPaths();
340 }
341
342 //check if full recompile is required otherwise perform incremental
343 if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking == false)
344 {
345 this.CompileSourceList = this.Sources;
346 if ((this.CompileSourceList == null) || (this.CompileSourceList. Length == 0))
347 {
348 this.SkippedExecution = true;
349 }
350 }
351 else
352 {
353 //retrieve list of sources out of date due to command line chang es
354 List<ITaskItem> outOfDateSourcesFromCommandLineChanges = this.Ge tOutOfDateSourcesFromCommandLineChanges();
355
356 //retrieve sources out of date due to tracking
357 CanonicalTrackedOutputFiles trackedOutputFiles = new CanonicalTr ackedOutputFiles(this, this.TLogWriteFiles);
358 this.TrackedInputFiles = new CanonicalTrackedInputFiles(this, th is.TLogReadFiles, this.Sources, this.ExcludedInputPaths, trackedOutputFiles, tru e, false);
359 ITaskItem[] outOfDateSourcesFromTracking = this.TrackedInputFile s.ComputeSourcesNeedingCompilation();
360
361 //merge out of date lists
362 this.CompileSourceList = this.MergeOutOfDateSources(outOfDateSou rcesFromTracking, outOfDateSourcesFromCommandLineChanges);
363
364 if (this.CompileSourceList.Length == 0)
365 {
366 this.SkippedExecution = true;
367 }
368 else
369 {
370 //remove sources to compile from tracked file list
371 this.TrackedInputFiles.RemoveEntriesForSource(this.CompileSo urceList);
372 trackedOutputFiles.RemoveEntriesForSource(this.CompileSource List);
373 this.TrackedInputFiles.SaveTlog();
374 trackedOutputFiles.SaveTlog();
375
376 this.SkippedExecution = false;
377 }
378 }
379 }
380
381 protected bool SourceIsC(string sourceFilename)
382 {
383 string fileExt = Path.GetExtension(sourceFilename.ToString());
384
385 if (fileExt == ".c")
386 return true;
387 else
388 return false;
389 }
390
391 public override bool Execute()
392 {
393 bool returnResult = false;
394
395 try
396 {
397 m_XamlParser = new XamlParser(PropertiesFile);
398 m_toolname = Path.GetFileNameWithoutExtension(ToolName);
399 ValidateParameters();
400 CalcSourcesToCompile();
401
402 returnResult = base.Execute();
403
404 // Update tracker log files if execution occurred
405 //if (this.skippedExecution == false)
406 {
407 CanonicalTrackedOutputFiles outputs = OutputWriteTrackerLog( CompileSourceList);
408 ConstructReadTLog(CompileSourceList, outputs);
409 OutputCommandTrackerLog(CompileSourceList);
410 }
411 }
412 finally
413 {
414
415 }
416
417 return returnResult;
418 }
419
420 protected List<ITaskItem> GetOutOfDateSourcesFromCommandLineChanges()
421 {
422 //get dictionary of source + command lines
423 IDictionary<string, string> dictionary = this.GenerateCommandLinesFr omTlog();
424 List<ITaskItem> outOfDateSources = new List<ITaskItem>();
425
426 //add sources to out of date list if the tlog dictionary string do n ot match the generated command line string
427 StringBuilder currentCommandLine = new StringBuilder(GCCUtilities.s_ CommandLineLength);
428 foreach (ITaskItem sourceItem in Sources)
429 {
430 currentCommandLine.Length = 0;
431
432 currentCommandLine.Append(GenerateCommandLineFromProps(sourceIte m));
433 currentCommandLine.Append(" ");
434 currentCommandLine.Append(sourceItem.GetMetadata("FullPath").ToU pperInvariant());
435
436 string tlogCommandLine = null;
437 if (dictionary.TryGetValue(FileTracker.FormatRootingMarker(sourc eItem), out tlogCommandLine))
438 {
439 if ((tlogCommandLine == null) || !currentCommandLine.ToStrin g().Equals(tlogCommandLine, StringComparison.Ordinal))
440 {
441 outOfDateSources.Add(sourceItem);
442 }
443 }
444 else
445 {
446 outOfDateSources.Add(sourceItem);
447 }
448 }
449 return outOfDateSources;
450 }
451
452 protected virtual void SetTrackerLogPaths()
453 {
454 if (this.TLogCommandFile == null)
455 {
456 string commandFile = Path.Combine(this.TlogDirectory, this.Comma ndTLogFilename);
457 this.TLogCommandFile = new TaskItem(commandFile);
458 }
459
460 if (this.TLogReadFiles == null)
461 {
462 this.TLogReadFiles = new ITaskItem[this.ReadTLogFilenames.Length ];
463 for (int n = 0; n < this.ReadTLogFilenames.Length; n++)
464 {
465 string readFile = Path.Combine(this.TlogDirectory, this.Read TLogFilenames[n]);
466 this.TLogReadFiles[n] = new TaskItem(readFile);
467 }
468 }
469
470 if (this.TLogWriteFiles == null)
471 {
472 this.TLogWriteFiles = new ITaskItem[1];
473 string writeFile = Path.Combine(this.TlogDirectory, this.WriteTL ogFilename);
474 this.TLogWriteFiles[0] = new TaskItem(writeFile);
475 }
476 }
477
478
479 //props
480 protected string CommandTLogFilename
481 {
482 get
483 {
484 return m_toolname + ".compile.command.1.tlog";
485 }
486 }
487
488 protected string[] ReadTLogFilenames
489 {
490 get
491 {
492 return new string[] { m_toolname + ".compile.read.1.tlog" };
493 }
494 }
495
496 [Output]
497 public bool SkippedExecution
498 {
499 get
500 {
501 return this.skippedExecution;
502 }
503 set
504 {
505 this.skippedExecution = value;
506 }
507 }
508
509 public ITaskItem TLogCommandFile
510 {
511 get
512 {
513 return this.tlogCommandFile;
514 }
515 set
516 {
517 this.tlogCommandFile = value;
518 }
519 }
520
521 protected string TlogDirectory
522 {
523 get
524 {
525 if (this.TrackerLogDirectory != null)
526 {
527 return this.TrackerLogDirectory;
528 }
529 return string.Empty;
530 }
531 }
532
533 public bool MinimalRebuildFromTracking
534 {
535 get
536 {
537 return this.minimalRebuildFromTracking;
538 }
539 set
540 {
541 this.minimalRebuildFromTracking = value;
542 }
543 }
544
545
546 public ITaskItem[] TLogReadFiles
547 {
548 get
549 {
550 return this.tlogReadFiles;
551 }
552 set
553 {
554 this.tlogReadFiles = value;
555 }
556 }
557
558 public ITaskItem[] ExcludedInputPaths
559 {
560 get
561 {
562 return this.excludedInputPaths;
563 }
564 set
565 {
566 this.excludedInputPaths = value;
567 }
568 }
569
570
571 public ITaskItem[] TLogWriteFiles
572 {
573 get
574 {
575 return this.tlogWriteFiles;
576 }
577 set
578 {
579 this.tlogWriteFiles = value;
580 }
581 }
582
583 protected string WriteTLogFilename
584 {
585 get
586 {
587 return m_toolname + ".compile.write.1.tlog";
588 }
589 }
590
591 public bool TrackFileAccess
592 {
593 get
594 {
595 return this.trackFileAccess;
596 }
597 set
598 {
599 this.trackFileAccess = value;
600 }
601 }
602
603 protected CanonicalTrackedInputFiles TrackedInputFiles
604 {
605 get
606 {
607 return this.trackedInputFiles;
608 }
609 set
610 {
611 this.trackedInputFiles = value;
612 }
613 }
614
615 [Output]
616 public ITaskItem[] CompileSourceList
617 {
618 get
619 {
620 return this.compileSourceList;
621 }
622 set
623 {
624 this.compileSourceList = value;
625 }
626 }
627
628 protected override string ToolName
629 {
630 get
631 {
632 return NaCLCompilerPath;
633 }
634 }
635
636 protected override Encoding ResponseFileEncoding
637 {
638 get
639 {
640 return Encoding.ASCII;
641 }
642 }
643 }
644 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698