2016-11-08 81 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>