我们的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 .\1.csproj /p:OutDir=XoXo /nologo
Build started 11/13/2015 9:50:57 PM.
Project "C:\1.csproj" on node 1 (default targets).
Build:
XoXo
Done Building Project "C:\1.csproj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
PS C:\>
请注意,它显示 XoXo ,忽略了我从内部覆盖它的尝试。
那么,有可能吗?
答案 0 :(得分:2)
这是一个经典的RTFM情况,但仍然很有趣。请参阅MSBuild Properties的文档,特别是Global Properties上的部分以及如何使属性不被前者覆盖:
MSBuild允许您使用/ property(或/ p)开关在命令行上设置属性。这些全局属性值覆盖在项目文件中设置的属性值。这包括环境属性,但不包括无法更改的保留属性。
也可以使用MSBuild任务的Properties属性为多项目构建中的子项目设置或修改全局属性
如果使用 TreatAsLocalProperty 属性指定属性 在项目标记中,该全局属性值不会覆盖 在项目文件中设置的属性值。
它还链接到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>
应该通过传递像
这样的neede属性来调用msbuild stub.targets /p:MasterProject=/path/to/main.vcxproj;ApplyCustomOutDir=True
(我从未使用过TFS,因此传递属性的方式可能会有所不同)