我天生就是一个make(1)家伙。我想要做的是相当于这个make片段:
FILES = generated.cs
app.exe : $(FILES)
csc -out:$@ $(FILES)
generated.cs :
echo "// generated file" > $@
也就是说,$(FILES)
包含一个文件列表,其中一些文件可能由Makefile中的其他目标生成。这只是工作。
我想和MSBuild做同样的事情。不幸的是,我的尝试失败了:
<Target Name="BuildGenerated"
Outputs="Generated.cs"
>
<WriteLinesToFile
File="Generated.cs"
Lines="// generated file"
Overwrite="True"
/>
</Target>
<ItemGroup>
<Compile Include="Generated.cs" />
</ItemGroup>
也就是说,使用<Compile/>
来包含生成的文件并使MSBuild推断出由于Generated.cs
不存在,它应该找到一些<Target/>
,它将生成该文件,然后执行它
看起来像这样做的唯一方法是添加预构建步骤,但这似乎是一个黑客。预构建步骤是唯一的方法吗?或者是否有某种方法可以使MSBuild像大脑一样行动?
更新1 :作为参考,这将是使其工作所需的预构建咒语,并且(再次)这是我宁愿避免的事情:
<PropertyGroup>
<CompileDependsOn>
BuildGenerated;$(CompileDependsOn)
</CompileDependsOn>
</PropertyGroup>
在定义<Import Project="..." />
的{{1}}元素后,需要发生。
答案 0 :(得分:2)
问题是您的文件是生成的文件,而MsBuild只解析一次项目和属性组(在构建开始时)。因此,当MsBuild尝试包含generated.cs文件时,它尚未创建,而且MsBuild根本不包含任何内容。
这样做的正确方法是在BuildGenerated目标中执行include部分,这将导致它被动态评估。
<Target Name="BuildGenerated"
Outputs="Generated.cs"
>
<WriteLinesToFile
File="Generated.cs"
Lines="// generated file"
Overwrite="True"
/>
<ItemGroup>
<Compile Include="Generated.cs" />
</ItemGroup>
</Target>
我在回答此问题时提供了更多信息:Bin folder not being copied with MSBuild, Teamcity
编辑
对不起,我没有正确读出您的问题。在您的makefile中,在app.exe目标(默认值)中,您明确地调用您的generated.cs目标。您可以使用MsBuild执行相同操作。
默认情况下,MsBuild搜索Build目标(makefile中的'all'),如果您的主目标是“app.exe”,则必须使用以下选项之一调用BuildGenerated目标:
<Target Name="app.exe" DependsOnTargets="BuildGenerated>
<!-- Stuff here -->
</Target>
或
<Target Name="app.exe">
<CallTarget Targets="BuildGenerated"/>
<!-- Stuff here -->
</Target>
如果您没有设置默认目标,可以通过命令行使用/ t参数或在项目声明中执行:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="app.exe">