2016-11-08 80 views
3

我有一個奇怪的解決方案,我需要其中一個項目來「編譯」另一個文件。MSBuild自定義任務取決於另一個項目

編譯器(在這裏呈現出最小的例子)如下(MSBuild的自定義任務):

public class MyCompileTask : Task 
{ 
    [Required] 
    public ITaskItem[] InputFiles { get; set; } 

    [Output] 
    public ITaskItem[] OutputFiles { get; set; } 

    public override bool Execute() 
    { 
     var generatedFileNames = new List<string>(); 

     foreach (var inputFile in this.InputFiles) 
     { 
      var inputFileName = inputFile.ItemSpec; 
      var outputFileName = Path.ChangeExtension(inputFileName, ".res.txt"); 

      var source = File.ReadAllText(inputFileName); 
      var compiled = source.ToUpper(); 
      File.WriteAllText(outputFileName, compiled + "\n\n" + DateTime.Now); 

      generatedFileNames.Add(outputFileName); 
     } 

     this.OutputFiles = generatedFileNames.Select(name => new TaskItem(name)).ToArray(); 

     return true; 
    } 
} 

正如你看到的,它只是將轉換爲大寫輸入文件的內容。

這是項目A - 「編譯器」庫。

項目B,現在是主應用程序,需要將文件「lorem.txt」「編譯」爲「lorem.res.txt」,並將其作爲EmbeddedResource放在B.exe/B.dll中。

在B.csproj添加以下:

<PropertyGroup> 
<CoreCompileDependsOn>$(CoreCompileDependsOn);InvokeMyCompile</CoreCompileDependsOn> 
</PropertyGroup> 
<UsingTask TaskName="MyCompiler.MyCompileTask" AssemblyFile="$(MSBuildProjectDirectory)\..\MyCompiler\bin\$(Configuration)\MyCompiler.dll" /> 
<Target Name="MyCompile" Inputs="lorem.txt" Outputs="lorem.res.txt"> 
    <MyCompileTask InputFiles="lorem.txt"> 
    <Output TaskParameter="OutputFiles" PropertyName="OutputFiles" /> 
    </MyCompileTask> 
</Target> 
<Target Name="InvokeMyCompile" Inputs="lorem.txt" Outputs="lorem.res.txt"> 
    <Exec Command="&quot;$(MSBuildBinPath)\MSBuild.exe&quot; /t:MyCompile &quot;$(ProjectDir)$(ProjectFileName)&quot;" /> 
</Target> 

(該2層中的目標,並明確msbuild.exe調用是一種變通方法to another problem事實上,許多本實施例的從是Q被盜)

最重要的部分工作,即當我更改lorem.txt和生成時,lorem.res.txt得到重新生成。

但是:

  • 當lorem.res.txt物理刪除,建造什麼也不做(說,這是先進的日期),直到我真正刷新VS.項目所以,MSBuild不會「知道」實際需要lorem.res.txt來構建項目。
  • 更重要的是,當我更改項目A中的任何內容時,項目B將重新編譯但不會重新運行編譯lorem.txt - > lorem.res.txt。所以MSBuild不知道轉換依賴於另一個項目。

我該如何在csproj文件中聲明這些依賴關係?

紅利問題:如何將輸出文件(lorem.res.txt)標記爲生成的EmbeddedResource,因此我不必在VS中跟蹤它,但它仍然會放入程序集中?

+0

將MyCompiler.dll添加到輸入可能會處理最後一個點。而不是使用CoreCompileDependsOn,您可以嘗試將* BeforeTargets =「Build」*添加到目標,以便執行不依賴於可能的其他機制來決定項目是否爲最新版本。 – stijn

+0

你是什麼意思關於「我怎樣才能在csproj文件中聲明這些依賴關係?」 –

+0

你是否解決了這個問題,如果問題依然存在,請隨時告訴我。 –

回答

0

•當lorem.res.txt被物理刪除時,構建什麼都不做(說它是最新的),直到我實際刷新VS中的項目。所以,MSBuild不會「知道」實際需要lorem.res.txt來構建項目。

我創建一個演示並在我的身邊重現您的問題,您可以使用msbuild命令行來避免它。

•更重要的是,當我更改項目A中的任何內容時,項目B將重新編譯但不會重新運行編譯lorem.txt - > lorem.res.txt。所以MSBuild不知道轉換依賴於另一個項目。

由於自定義任務引用了DLL文件,因此在更改項目A中的任何內容時,需要重新生成項目以生成較新的DLL文件。

紅利問題:如何標記輸出文件(lorem.res。txt)作爲一個生成的EmbeddedResource,所以我不必在VS中跟蹤它,但它仍然被放入程序集?

您可以在BeforeBuild目標中添加自定義的ItemGroup來實現它。

<Target Name="BeforeBuild" DependsOnTargets="MyCompile"> 
    <ItemGroup> 
     <Content Include="lorem.res.txt"> 
     <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 
     </Content> 
    </ItemGroup> 
    </Target>