MSBuild:用于 VS2010 中本机 C++ 项目的 Custom.After.Microsoft.Common.targets

2021-12-14 00:00:00 native msbuild c++ visual-studio-2010

我已经阅读了关于Custom.Before.Microsoft.Common.targets"和Custom.After.Microsoft.Common.targets"的使用,以便在每个项目构建之前/之后执行自定义目标,我会喜欢使用这种技术来在我们的 TeamCity 构建服务器上构建时更改版本信息.

I've read about the use of "Custom.Before.Microsoft.Common.targets" and "Custom.After.Microsoft.Common.targets" in order to execute a custom target before/after every project build and I would like to use this technique in order to change version info while building on our TeamCity build server.

问题是,虽然它适用于 C# 项目,但它似乎不适用于本机 C++ 项目.

The problem is that although it works for C# projects, it doesn't seem to work for native C++ projects.

在 Microsoft.Cpp.targets 文件中进行一些挖掘后,我发现对于本机 C++ 项目,这似乎是通过设置 $(ForceImportBeforeCppTargets) 和 $(ForceImportAfterCppTargets) 来实现的.

After some digging around in the Microsoft.Cpp.targets file I found out that for native C++ projects this seems to be implemented through setting $(ForceImportBeforeCppTargets) and $(ForceImportAfterCppTargets).

不过,我似乎无法在网络上找到有关本机 C++ 应用程序的这项技术的一条信息,所以我在问我是否在寻找正确的方向.

I can't seem to find a single piece of information on the web about this technique for native C++ apps though, so I'm asking if I'm looking in the right direction or not.

感谢任何帮助.

推荐答案

对于 VC++ 项目来说有点不同.您可以在项目开始或结束时定义要导入的文件.要使用此方法,您需要为属性 ForceImportBeforeCppTargetsForceImportAfterCppTargets 定义值.例如,如果您希望在项目的开头包含一个文件,您可以在命令行中传递该值.例如,我刚刚创建了一个名为 CppTets??01 的虚拟 VC++ 项目.然后我创建了下面的两个示例文件.

For VC++ projects it is a bit different. You define a file to be imported either at the beginning or at the end of the project. To use this approach you need to define values for the properties ForceImportBeforeCppTargets or ForceImportAfterCppTargets. For example if you want a file to be included at the beginning of the project you can pass in the value at the command line. For example I just created a dummy VC++ project named CppTets01. Then I created the two sample files below.

Before.proj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">


  <Target Name="CustomTargetInBefore" AfterTargets="Build">
    <Message Text="From CustomTargetInBefore" Importance="high"/>
  </Target>

</Project>

After.proj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Target Name="CustomTargetInAfter" AfterTargets="Build">
    <Message Text="From CustomTargetInAfter" Importance="high"/>
  </Target>

</Project>

然后我执行了以下命令:

Then I executed the following command:

msbuild CppTest01.vcxproj 
    /p:ForceImportBeforeCppTargets="C:Temp\_NETThrowAwayCppTest01CppTest01Before.proj";
    ForceImportAfterCppTargets="C:Temp\_NETThrowAwayCppTest01CppTest01After.proj"

结果是C:Temp_NETThrowAwayCppTest01CppTest01>msbuild CppTest01.vcxproj/p:ForceImportBeforeCppTargets="C:Temp_NETThrowAwayCppTest01CppTest01Before.proj";ForceImportAfterCppTargets="C:Temp_NETThrowAwayCppTest01CppTest01After.proj"

The result was C:Temp_NETThrowAwayCppTest01CppTest01>msbuild CppTest01.vcxproj /p:ForceImportBeforeCppTargets="C:Temp_NETThrowAwayCppTest01C ppTest01Before.proj";ForceImportAfterCppTargets="C:Temp_NETThrowAwayCppTest01CppTest01After.proj"

Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 10/18/2010 8:32:55 AM.
Project "C:Temp\_NETThrowAwayCppTest01CppTest01CppTest01.vcxproj" on node 1 (default targets).
InitializeBuildStatus:
  Creating "DebugCppTest01.unsuccessfulbuild" because "AlwaysCreate" was specified.
ClCompile:
  All outputs are up-to-date.
  All outputs are up-to-date.
ManifestResourceCompile:
  All outputs are up-to-date.
Link:
  All outputs are up-to-date.
Manifest:
  All outputs are up-to-date.
FinalizeBuildStatus:
  Deleting file "DebugCppTest01.unsuccessfulbuild".
  Touching "DebugCppTest01.lastbuildstate".
CustomTargetInBefore:
  From CustomTargetInBefore
CustomTargetInAfter:
  From CustomTargetInAfter
Done Building Project "C:Temp\_NETThrowAwayCppTest01CppTest01CppTest01.vcxproj" (default targets).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.21

从输出中可以看出,目标已成功注入到构建过程中.如果您想将其与 Custom.Before.Microsoft.Common.targetsCustom.Before.Microsoft.Common.targets 联系起来,那么您应该知道那里使用的技术有点不同.特别是如果您创建这些文件,它们会自动导入到每个 C#/VB.NET 项目中.在这种情况下,您必须设置此属性.你真的有两个选择:

As you can see from the output the targets were successfully injected into the build process. If you want to relate this back to Custom.Before.Microsoft.Common.targets and Custom.Before.Microsoft.Common.targets then you should know that the technique used there is a bit different. Specifically if you create those files they are automatically imported into every C#/VB.NET project. In this case you have to set this property. You really have two options here:

  1. 您可以将此属性设置为环境变量
  2. 您可以使用另一种技术,ImportBefore &VC++特有的ImportAfter

对于#1,让我解释一下.在 MSBuild 中,当您使用语法 $(PropName) 访问属性时,如果名称为 PropName 的属性不存在,MSBuild 将在环境变量中查找是否存在这样的值,如果存在,则返回该值.因此,如果您有一个构建服务器,您希望在其中为每个 VC++ 构建包含一个文件,那么只需将这些属性创建为环境变量.现在是另一种技术.

For #1 let me explain a bit. In MSBuild when you access a property with the syntax $(PropName) then if a property with the name PropName doesn't exist MSBuild will look up in the environment variables to see if such a value exists, if it does then that value is returned. So if you have a build server in which you want to include a file for each VC++ build, then just create those properties as environment variables. Now for the other technique.

ImportBefore/ImportAfter在 VC++ 中引入了一个新概念.在 Microsoft.Cpp.Win32.targets 中,您可以看到 .targets 文件顶部的声明.

ImportBefore/ImportAfter In VC++ a new concept is introduced. In Microsoft.Cpp.Win32.targets you can see the declaration at the top of the .targets file.

<Import Project="$(VCTargetsPath)PlatformsWin32ImportBefore*.targets" 
Condition="Exists('$(VCTargetsPath)PlatformsWin32ImportBefore')" />

然后有一个朝向底部

<Import Project="$(VCTargetsPath)PlatformsWin32ImportAfter*.targets" 
Condition="Exists('$(VCTargetsPath)PlatformsWin32ImportAfter')" />

其他目标平台也存在类似的导入声明.查看 %ProgramFiles32%MSBuildMicrosoft.Cppv4.0Platforms 中的文件以了解具体名称.

A similar import declaration exists for the other target platforms as well. Take a look at the files at %ProgramFiles32%MSBuildMicrosoft.Cppv4.0Platforms for the specific names.

如果您想要导入文件,则使用此技术只需创建一个以 .targets 结尾的文件并将其放入适当的文件夹中.这样做的好处是它将被导入到该平台的每个 VC++ 构建中,并且您可以创建许多不同的文件.缺点是您必须将它们放在那些特定的文件夹中.这是两种技术之间的主要区别.使用第一种技术,您可以通过属性指定文件位置,它不会自动包含在每个构建中,但对于第二种方法,您不能更改位置

With this technique if you want a file to be imported then simply create a file that ends with .targets and place it into the appropriate folder. The advantage of this is that it will be imported into every VC++ build for that platform, and that you can create many different files. The drawback is that you have to place them in those specific folders. That's the main difference between both techniques. With this first technique you can specify the file location via property and its not automatically included for every build, but for the second approach it is but you cannot change the location

相关文章