如何忽略相应 csproj 文件中命令行上给出的 属性 值?
How to ignore the property value given on the command line from within the respective csproj file?
我们的 TFS 构建控制器将同一解决方案中的所有项目构建到同一共享 bin 目录中,因为 TFS 构建工作流将 OutDir
参数传递给负责构建解决方案的 msbuild 命令。
我有一个项目,我想在其中抑制此行为并让它构建到标准相对 bin\Debug
或 bin\Release
目录中。
但我找不到如何操作。实际上,请观察以下简单的 msbuild 脚本:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutDir>$(MSBuildThisFileDirectory)bin$(Configuration)</OutDir>
</PropertyGroup>
<Target Name="Build">
<Message Text="$(OutDir)" Importance="High"/>
</Target>
</Project>
现在,我是运行它:
PS C:\> msbuild ..csproj /p:OutDir=XoXo /nologo
Build started 11/13/2015 9:50:57 PM.
Project "C:.csproj" on node 1 (default targets).
Build:
XoXo
Done Building Project "C:.csproj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
PS C:\>
注意它显示 XoXo,忽略我从内部覆盖它的尝试。
那么,有可能吗?
这是一种典型的 RTFM 情况,但仍然很有趣。请参阅 MSBuild Properties in particular the part on Global Properties 的文档以及如何使属性不被前者覆盖:
MSBuild lets you set properties on the command line by using the /property (or /p) switch. These global property values override property values that are set in the project file. This includes environment properties, but does not include reserved properties, which cannot be changed.
Global properties can also be set or modified for child projects in a multi-project build by using the Properties attribute of the MSBuild task
If you specify a property by using the TreatAsLocalProperty attribute
in a project tag, that global property value doesn't override the
property value that's set in the project file.
它还链接到 Project 元素文档,该文档基本上重复相同的信息,并表示属性中的多个属性应该用分号分隔。
简而言之,适用于您案例的代码:
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
TreatAsLocalProperty="OutDir">
请注意,这将完全禁止从项目外部更改 OutDir。一个更可配置的替代解决方案可能是有一个小的存根项目,您可以构建 TFS 而不是主项目。在该项目中,您可以决定是将 OutDir 传递给实际项目还是覆盖它,例如通过导入可能已定义或未定义的文件或基于环境变量等来获取值。这给出了基本思想:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Try import if this file exists, it should supply the value for CustomOutDir-->
<Import Project="$(MSBuildThisFileDirectory)customoutdir.props" Condition="Exists('$(MSBuildThisFileDirectory)customoutdir.props')"/>
<PropertyGroup>
<!-- Default value for CustomOutDir if not set elsewhere -->
<CustomOutDir Condition="'$(CustomOutDir)' == ''">$(MSBuildThisFileDirectory)bin$(Configuration)</CustomOutDir>
<!-- ApplyCustomOutDir specifies whether or not to apply CustomOutDir -->
<ActualOutDir Condition="'$(ApplyCustomOutDir)' == 'True'">$(CustomOutDir)</ActualOutDir>
<ActualOutDir Condition="'$(ApplyCustomOutDir)' != 'True'">$(OutDir)</ActualOutDir>
</PropertyGroup>
<Target Name="Build">
<MSBuild Projects="$(MasterProject)" Properties="OutDir=$(ActualOutDir)"/>
</Target>
</Project>
并且应该通过传递需要的属性来调用
msbuild stub.targets /p:MasterProject=/path/to/main.vcxproj;ApplyCustomOutDir=True
(我从未使用过TFS,所以获取属性传递的方式可能不同)
我们的 TFS 构建控制器将同一解决方案中的所有项目构建到同一共享 bin 目录中,因为 TFS 构建工作流将 OutDir
参数传递给负责构建解决方案的 msbuild 命令。
我有一个项目,我想在其中抑制此行为并让它构建到标准相对 bin\Debug
或 bin\Release
目录中。
但我找不到如何操作。实际上,请观察以下简单的 msbuild 脚本:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutDir>$(MSBuildThisFileDirectory)bin$(Configuration)</OutDir>
</PropertyGroup>
<Target Name="Build">
<Message Text="$(OutDir)" Importance="High"/>
</Target>
</Project>
现在,我是运行它:
PS C:\> msbuild ..csproj /p:OutDir=XoXo /nologo
Build started 11/13/2015 9:50:57 PM.
Project "C:.csproj" on node 1 (default targets).
Build:
XoXo
Done Building Project "C:.csproj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
PS C:\>
注意它显示 XoXo,忽略我从内部覆盖它的尝试。
那么,有可能吗?
这是一种典型的 RTFM 情况,但仍然很有趣。请参阅 MSBuild Properties in particular the part on Global Properties 的文档以及如何使属性不被前者覆盖:
MSBuild lets you set properties on the command line by using the /property (or /p) switch. These global property values override property values that are set in the project file. This includes environment properties, but does not include reserved properties, which cannot be changed.
Global properties can also be set or modified for child projects in a multi-project build by using the Properties attribute of the MSBuild task
If you specify a property by using the TreatAsLocalProperty attribute in a project tag, that global property value doesn't override the property value that's set in the project file.
它还链接到 Project 元素文档,该文档基本上重复相同的信息,并表示属性中的多个属性应该用分号分隔。
简而言之,适用于您案例的代码:
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
TreatAsLocalProperty="OutDir">
请注意,这将完全禁止从项目外部更改 OutDir。一个更可配置的替代解决方案可能是有一个小的存根项目,您可以构建 TFS 而不是主项目。在该项目中,您可以决定是将 OutDir 传递给实际项目还是覆盖它,例如通过导入可能已定义或未定义的文件或基于环境变量等来获取值。这给出了基本思想:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Try import if this file exists, it should supply the value for CustomOutDir-->
<Import Project="$(MSBuildThisFileDirectory)customoutdir.props" Condition="Exists('$(MSBuildThisFileDirectory)customoutdir.props')"/>
<PropertyGroup>
<!-- Default value for CustomOutDir if not set elsewhere -->
<CustomOutDir Condition="'$(CustomOutDir)' == ''">$(MSBuildThisFileDirectory)bin$(Configuration)</CustomOutDir>
<!-- ApplyCustomOutDir specifies whether or not to apply CustomOutDir -->
<ActualOutDir Condition="'$(ApplyCustomOutDir)' == 'True'">$(CustomOutDir)</ActualOutDir>
<ActualOutDir Condition="'$(ApplyCustomOutDir)' != 'True'">$(OutDir)</ActualOutDir>
</PropertyGroup>
<Target Name="Build">
<MSBuild Projects="$(MasterProject)" Properties="OutDir=$(ActualOutDir)"/>
</Target>
</Project>
并且应该通过传递需要的属性来调用
msbuild stub.targets /p:MasterProject=/path/to/main.vcxproj;ApplyCustomOutDir=True
(我从未使用过TFS,所以获取属性传递的方式可能不同)