我有一个奇怪的解决方案,我需要一个项目在另一个项目中"编译"文件。
编译器(这里显示一个最小的例子)如下(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 + "nn" + DateTime.Now);
generatedFileNames.Add(outputFileName);
}
this.OutputFiles = generatedFileNames.Select(name => new TaskItem(name)).ToArray();
return true;
}
}
如您所见,它只大写输入文件的内容。
这是A项目——"编译器"库。
项目B,目前主要的应用程序,有一个文件"loremm .txt"需要"编译"成"loremm .res.txt",并作为EmbeddedResource放在b.c exe/b.c dll中。
在b.s csproj中我添加了以下内容:
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);InvokeMyCompile</CoreCompileDependsOn>
</PropertyGroup>
<UsingTask TaskName="MyCompiler.MyCompileTask" AssemblyFile="$(MSBuildProjectDirectory)..MyCompilerbin$(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=""$(MSBuildBinPath)MSBuild.exe" /t:MyCompile "$(ProjectDir)$(ProjectFileName)"" />
</Target>
(2层目标和显式的msbuild.exe调用是另一个问题的解决方案。事实上,这个例子的大部分内容都是从Q.那里偷来的。
最重要的部分工作,即当我更改loremm .txt并构建loremm .res.txt时,loremm .res.txt会重新生成。
然而:
- 当loremm .res.txt被物理删除时,构建不做任何事情(说它是最新的),直到我在vs中实际刷新项目,所以MSBuild不"知道"loremm .res.txt实际上需要构建项目。
- 更重要的是,当我改变项目A中的任何东西时,项目B会重新编译,但不会重新运行编译loremm .txt -> loremm .res.txt。所以MSBuild并不"知道"转换依赖于另一个项目。
如何在csproj文件中声明这些依赖关系?
附加问题:如何将输出文件(loremm .res.txt)标记为生成的EmbeddedResource,因此我不必在VS中跟踪它,但它仍然放入程序集?
•当loremm .res.txt被物理删除时,构建不做任何事情(说它是最新的),直到我在vs中实际刷新项目。因此,MSBuild不"知道"loremm .res.txt实际上需要构建项目。
我创建了一个演示并在我这边重现了您的问题,您可以使用msbuild命令行来避免它。
•更重要的是,当我更改项目A中的任何内容时,项目B会重新编译,但不会重新运行编译loremm .txt -> loremm .res.txt。因此MSBuild并不"知道"转换依赖于另一个项目。
由于自定义任务引用了DLL文件,当更改项目A中的任何内容时,您需要重新构建项目以生成更新的DLL文件。
附加问题:如何将输出文件(loremm .res.txt)标记为生成的EmbeddedResource,因此我不必在VS中跟踪它,但它仍然放入程序集?
您可以在BeforeBuild目标中添加自定义ItemGroup来实现它。
<Target Name="BeforeBuild" DependsOnTargets="MyCompile">
<ItemGroup>
<Content Include="lorem.res.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Target>