覆盖.targets文件中的一个属性

时间:2015-02-20 14:54:47

标签: visual-studio msbuild

背景:我有几个解决方案,其中包含大约300个C ++项目,其中大多数是共享的。我们正在使用Visual Studio 2013,并且有一个构建脚本,它以正确的顺序编译所有项目,确保依赖关系得到提前解决。我们的开发/工程团队通过构建脚本构建所有代码,然后尝试使用Visual Studio 2013进行调试。

问题:"构建然后调试" Visual Studio中的进程结果告诉我们项目已过期。这源于ProjectEvaluationFingerprint属性(在第39行Microsoft.CppBuild.targets中),包括输出文件中的$(SolutionDir)recommended fix from Microsoft建议从文件中删除$(SolutionDir)。由于我们的开发人员倾向于在项目之间来回切换,我不想在每个开发人员的机器上手动更改此.targets文件(并且记得在他们离开项目时将其更改回来)。我想通过显式使用.targets文件覆盖.vcxproj中的属性。

Microsoft.CppBuild.targets中的属性如下所示:

<!-- Global up-to-date check support -->
<PropertyGroup>
   <ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|$(SolutionDir)|$(ProjectEvaluationFingerprint)</ProjectEvaluationFingerprint>
</PropertyGroup>

一般来说,我一直关注微软的How to: Use the Same Target in Multiple Project Files。我创建了一个.targets文件(test.targets),其中包含以下代码(注意,TEST文本用于测试构建脚本中的属性评估以及在Visual Studio中构建项目 ):

<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
    <ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|TEST|$(ProjectEvaluationFingerprint)</ProjectEvaluationFingerprint>
</PropertyGroup>

然后我使用.vcxproj

中的以下行导入它
<Import Project="..\..\Config\VSPropertySheets\test.targets" />

project.lastbuildstate文件现在显示为:

#TargetFrameworkVersion=v4.0:PlatformToolSet=v120_xp:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit
Debug|Win32|D:\views\devbranch\Products\SLN\|Debug|Win32|TEST|

它将新的ProjectEvaluationFingerprint附加到现有的,因此它不会覆盖(我可以理解这一点,但我没有MSBuild专家)。

问题:如何使用.targets文件覆盖此属性?我需要使用replaceregexp task还是我有更简单的选择?

2 个答案:

答案 0 :(得分:3)

您可以覆盖此属性,但必须注意两件事:

  • 您想要的新设置是: <ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|TEST/ProjectEvaluationFingerprint> 请注意删除$(ProjectEvaluationFingerprint),其中包含此标记的先前值
  • 您放置导入的位置很重要:您需要将其放在项目的最后(即Microsoft.CppBuild.targets导入后)。

具体地:

  

use_custom_fingerprint.targets    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <ProjectEvaluationFingerprint>$(Configuration)|$(Platform)</ProjectEvaluationFingerprint> </PropertyGroup> </Project>

     

project.vcxproj    <Project ...> ... <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> <Import Project="use_custom_fingerprint.targets" /> </Project>

请注意,我也尝试了扩展.props,这也是一样的。

注意:导入Microsoft.CppBuild.targets.$(Platform).user.props后的新导入就足够了,必须Microsoft.CppBuild.targets之后。

免责声明:在Visual Studio 2015中尝试过

答案 1 :(得分:0)

我有同样的问题。我能够比你更进一步,但我仍然没有完整的解决方案。

您现在将旧指纹附加到没有解决方案目录的新指纹的原因是您的行

<ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|TEST|$(ProjectEvaluationFingerprint)</ProjectEvaluationFingerprint>

$(ProjectEvaluationFingerprint)

保留旧指纹,因此只需从ProjectEvaluationFingerprint的值中删除此部分,您的lastbuildstate将具有所需的值。

可悲的是,现在(至少对我而言)Visual Studio总是认为指纹是错误的,并且会在每次编译时重新链接项目,而不仅仅是在切换sln文件时。

我从道具表中删除了该行,只要解决方案目录没有更改,我就会按预期再次运行最新检查。然后我直接修改了Microsoft.CppBuild.targets,这样就可以了:即使切换解决方案目录,也不再需要“不是最新的”项目。