我在 .csproj 中有这样的部分:
<Target Name="Date" BeforeTargets="BeforeBuild">
<WriteLinesToFile File="$(IntermediateOutputPath)BuildInfo.gen.cs"
Lines="...."/>
</Target>
<ItemGroup>
<Compile Include="$(IntermediateOutputPath)BuildInfo.gen.cs"
Condition="Exists('$(IntermediateOutputPath)BuildInfo.gen.cs')"/>
</ItemGroup>
IntermediateOutputPath
如期解决,一切都很好。但由于整个路径在我的 .csproj 中重复了 3 次,我想清理它并提出自定义变量:
<PropertyGroup>
<BuildInfoPath>$(IntermediateOutputPath)BuildInfo.gen.cs</BuildInfoPath>
</PropertyGroup>
<Target Name="Date" BeforeTargets="BeforeBuild">
<WriteLinesToFile File="$(BuildInfoPath)" Lines="...."/>
</Target>
<ItemGroup>
<Compile Include="$(BuildInfoPath)"
Condition="Exists('$(BuildInfoPath)')"/>
</ItemGroup>
我的变量已解析,但其内容不完全正确 - 我的效果就像
IntermediateOutputPath
是一个空字符串。
那么我如何定义自己的变量引用
IntermediateOutputPath
?
我已经发现,如果我将变量定义包装在
Target
中,它将部分起作用 - 即上面所示的 Target
部分将获得正确的变量,但反过来对于 ItemGroup
我的变量会是空的。
MSBuild 有两个阶段:评估和执行。请参阅“MSBuild 如何构建项目”。 “顶层”的
ItemGroup
和 PropertyGroup
元素(即 Project
文档根元素的直接子元素)在评估阶段进行评估。 ItemGroup
中的 PropertyGroup
和
Target
元素在执行阶段进行评估。
我假设这是一个 SDK 风格的项目。在后台,根据 SDK 类型导入一组文件。有些文件是在 .csproj 项目文件内容之前导入的,有些文件是在 .csproj 项目文件内容之后导入的。
IntermediateOutputPath
属性是在评估阶段定义的,但在 .csproj 内容之后导入的文件中定义。
在评估阶段的项目文件内容中,该属性尚未定义,并且在定义之前使用该属性会产生一个空字符串 - 正如您所观察到的。
在 SDK 样式项目中,仅在目标中使用
IntermediateOutputPath
属性。
您仍然可以定义自己的属性和依赖于
IntermediateOutputPath
的项目,但您需要将定义包装在目标中,并确保在使用值之前执行定义,例如:
<Target Name="DefineBuildInfoPath">
<PropertyGroup>
<BuildInfoPath>$(IntermediateOutputPath)BuildInfo.gen.cs</BuildInfoPath>
</PropertyGroup>
</Target>
<Target Name="Date" BeforeTargets="BeforeBuild" DependsOnTargets="DefineBuildInfoPath">
<WriteLinesToFile File="$(BuildInfoPath)" Lines="...."/>
</Target>
<Target Name="AddBuildInfoToCompile" BeforeTargets="BeforeCompile" DependsOnTargets="Date;DefineBuildInfoPath">
<ItemGroup>
<Compile Include="$(BuildInfoPath)" Condition="Exists('$(BuildInfoPath)')"/>
</ItemGroup>
</Target>