public override bool Execute() { List <ITaskItem> computed = new List <ITaskItem>(); foreach (ITaskItem source in Sources) { bool skip = true; Log.LogMessage(MessageImportance.Low, string.Format("Computing dependencies for {0}", source.GetMetadata("Identity"))); var sourceInfo = new FileInfo(source.GetMetadata("FullPath")); if (!sourceInfo.Exists) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because source: {0} doesn't exists", source.GetMetadata("Identity"))); skip = false; } var generatedItems = GeneratedItems(source); FileInfo generatedInfo = null; FileInfo dependInfo = null; // // Check if the Slice compiler is older than the source file // var sliceCompiler = new FileInfo(Path.Combine(IceToolsPath, ToolName)); if (skip) { foreach (ITaskItem item in generatedItems) { generatedInfo = new FileInfo(item.GetMetadata("FullPath")); if (generatedInfo.Exists && sliceCompiler.LastWriteTime.ToFileTime() > generatedInfo.LastWriteTime.ToFileTime()) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because target: {0} is older than Slice compiler: {1}", TaskUtil.MakeRelative(WorkingDirectory, generatedInfo.FullName), ToolName)); skip = false; break; } } } XmlDocument dependsDoc = new XmlDocument(); if (skip) { dependInfo = new FileInfo(Path.Combine(WorkingDirectory, source.GetMetadata("OutputDir"), string.Format("SliceCompile.{0}.d", Path.GetFileNameWithoutExtension(sourceInfo.Name)))); // // Check that the depdend file exists // if (!dependInfo.Exists) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because depend file: {0} doesn't exists", TaskUtil.MakeRelative(WorkingDirectory, dependInfo.FullName))); skip = false; } // // Check that the depend file is older than the corresponding Slice source // else if (sourceInfo.LastWriteTime.ToFileTime() > dependInfo.LastWriteTime.ToFileTime()) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because source: {0} is older than depend file {1}", source.GetMetadata("Identity"), TaskUtil.MakeRelative(WorkingDirectory, dependInfo.FullName))); skip = false; } else { try { dependsDoc.Load(dependInfo.FullName); } catch (XmlException) { try { File.Delete(dependInfo.FullName); } catch (IOException) { } Log.LogMessage(MessageImportance.Low, string.Format("Build required because depend file: {0} has some invalid data", TaskUtil.MakeRelative(WorkingDirectory, dependInfo.FullName))); skip = false; } } } if (skip) { foreach (ITaskItem item in generatedItems) { generatedInfo = new FileInfo(item.GetMetadata("FullPath")); // // Check that the generated file exists // if (!generatedInfo.Exists) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because generated: {0} doesn't exists", TaskUtil.MakeRelative(WorkingDirectory, generatedInfo.FullName))); skip = false; break; } // // Check that the generated file is older than the corresponding Slice source // else if (sourceInfo.LastWriteTime.ToFileTime() > generatedInfo.LastWriteTime.ToFileTime()) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because source: {0} is older than target {1}", source.GetMetadata("Identity"), TaskUtil.MakeRelative(WorkingDirectory, generatedInfo.FullName))); skip = false; break; } } } if (skip) { XmlNodeList options = dependsDoc.DocumentElement.SelectNodes( string.Format("/dependencies/source[@name='{0}']/options/child::node()", source.GetMetadata("Identity"))); if (options != null) { var newOptions = GetOptions(source); var oldOptions = options.Cast <XmlNode>().Select(node => new { node.Name, node.InnerXml }).ToDictionary(t => t.Name, t => t.InnerXml); if (newOptions.Except(oldOptions).Any() || oldOptions.Except(newOptions).Any()) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because source: {0} build options change", source.GetMetadata("Identity"))); skip = false; } } } if (skip) { XmlNodeList depends = dependsDoc.DocumentElement.SelectNodes( string.Format("/dependencies/source[@name='{0}']/dependsOn", source.GetMetadata("Identity"))); if (depends != null) { var inputs = new List <string>(); foreach (XmlNode depend in depends) { string path = depend.Attributes["name"].Value; FileInfo dependencyInfo = new FileInfo(path); if (!dependencyInfo.Exists) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because dependency: {0} doesn't exists", TaskUtil.MakeRelative(WorkingDirectory, dependencyInfo.FullName))); skip = false; break; } else if (dependencyInfo.LastWriteTime > generatedInfo.LastWriteTime) { Log.LogMessage(MessageImportance.Low, string.Format("Build required because source: {0} is older than target: {1}", source.GetMetadata("Identity"), TaskUtil.MakeRelative(WorkingDirectory, dependencyInfo.FullName))); skip = false; break; } inputs.Add(Path.GetFullPath(depend.Attributes["name"].Value).ToUpper()); } inputs.Add(source.GetMetadata("FullPath").ToUpper()); inputs.Add(sliceCompiler.FullName.ToUpper()); var outputs = GeneratedItems(source).Select(item => item.GetMetadata("FullPath").ToUpper()); source.SetMetadata("Outputs", string.Join(";", outputs)); source.SetMetadata("Inputs", string.Join(";", inputs)); } } if (skip) { string message = string.Format("Skipping {0} -> ", source.GetMetadata("Identity")); message += generatedItems[0].GetMetadata("Identity"); if (generatedItems.Length > 1) { message += " and "; message += generatedItems[1].GetMetadata("Identity"); message += " are "; } else { message += " is "; } message += "up to date"; Log.LogMessage(MessageImportance.Normal, message); } ITaskItem computedSource = new TaskItem(source.ItemSpec); source.CopyMetadataTo(computedSource); computedSource.SetMetadata("BuildRequired", skip ? "False" : "True"); computedSource.SetMetadata("OutputDir", computedSource.GetMetadata("OutputDir").TrimEnd('\\')); computed.Add(computedSource); } ComputedSources = computed.ToArray(); return(true); }
protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) { int status = base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); if (status == 0) { TraceGenerated(); // // Recompue dependencies // string output = ""; string error = ""; status = TaskUtil.RunCommand(WorkingDirectory, pathToTool, commandLineCommands + " --depend-xml", ref output, ref error); if (status == 0) { List <ITaskItem> computed = new List <ITaskItem>(); XmlDocument dependsDoc = new XmlDocument(); dependsDoc.LoadXml(output); foreach (ITaskItem source in Sources) { var inputs = new List <string>(); var depends = dependsDoc.DocumentElement.SelectNodes( string.Format("/dependencies/source[@name='{0}']/dependsOn", source.GetMetadata("Identity"))); if (depends != null) { foreach (XmlNode depend in depends) { inputs.Add(depend.Attributes["name"].Value); } } // // Save the dependencies for each source to a dependency file // // Foo.ice -> $(OutputDir)/SliceCompile.Foo.d // var doc = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XElement("dependencies", new XElement("source", new XAttribute("name", source.GetMetadata("Identity")), inputs.Select(path => new XElement("dependsOn", new XAttribute("name", path))), new XElement("options", GetOptions().Select(e => new XElement(e.Key, e.Value)))))); doc.Save(Path.Combine(OutputDir, string.Format("SliceCompile.{0}.d", source.GetMetadata("Filename")))); // // Update the Inputs and Outputs metadata of the output sources, // these info will be use to write the TLog files // inputs = inputs.Select(path => Path.GetFullPath(path)).ToList(); inputs.Add(source.GetMetadata("FullPath").ToUpper()); inputs.Add(Path.GetFullPath(pathToTool).ToUpper()); ITaskItem computedSource = new TaskItem(source.ItemSpec); source.CopyMetadataTo(computedSource); var outputs = GeneratedItems(source).Select((item) => item.GetMetadata("FullPath").ToUpper()); computedSource.SetMetadata("Outputs", string.Join(";", outputs)); computedSource.SetMetadata("Inputs", string.Join(";", inputs)); computed.Add(computedSource); } ComputedSources = computed.ToArray(); } } return(status); }