如何隐式使用Target生成包含的文件?

时间:2010-12-02 18:38:55

标签: msbuild

我天生就是一个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}}元素后,需要发生

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">