如何将PreProcessorDefinitions设置为msbuild任务的任务

时间:2013-02-28 17:05:03

标签: msbuild

以下内容来自常规的VS2010 C ++项目。

    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>

如果我编辑PreprocessorDefinitions,我可以设置预处理器使用的定义。我可以通过#ifdef等在我的代码中看到这个。

但是,如果我使用以下

  <Target Name="NormalBuild" Condition=" '$(_InvalidConfigurationWarning)' != 'true' " DependsOnTargets="_DetermineManagedStateFromCL;CustomBeforeBuild;$(BuildDependsOn)" Returns="@(ManagedTargetPath)">
    <ItemGroup>
        <ManagedTargetPath Include="$(TargetPath)" Condition="'$(ManagedAssembly)' == 'true'" />
    </ItemGroup>
      <Message Text="PreprocessorDefinitions: $(PreprocessorDefinitions)" Importance="High" />
  </Target>

  <Target Name="TestBuild" Returns="@(ManagedTargetPath)">
    <MSBuild Projects="demo.vcxproj" Targets="NormalBuild" Properties="PreprocessorDefinitions=THISGETSSETBUTDOESNOTHING"/>
  </Target>

我还可以通过消息看到PreprocessorDefinitions包含我通过Properties="PreprocessorDefinitions=THISGETSSETBUTDOESNOTHING"设置的值,但我无法使用#ifdef等控制我的构建。 如果我使用常规设置并尝试使用PreprocessorDefinitions输出<Message Text="PreprocessorDefinitions: $(PreprocessorDefinitions)",则该字段实际上是空白的,并且不包含预期的<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>,尽管我可以使用其中任何一个键来控制我的构建使用#ifdef

  1. 为什么?
  2. 如何通过任务Properties元素传递VS2010 C ++项目的PreprocessorDefinitions?

3 个答案:

答案 0 :(得分:32)

这可以在不修改原始项目的情况下完成:在Microsoft.Cpp.Targets中完成的第一件事,通常是在普通C ++项目中导入的最后一件事,是检查是否有一个名为{{1的属性如果是这样,请导入它。

因此,假设您要将ForceImportBeforeCppTargets添加到预处理器定义中,您可以像这样创建文件'override.props'(完全自动化使用ADDITIONAL任务来创建文件):

WritelinesToFile

并致电

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

  <ItemDefinitionGroup>
    <ClCompile>
      <PreprocessorDefinitions>%(PreprocessorDefinitions);ADDITIONAL</PreprocessorDefinitions>
    </ClCompile>
  </ItemDefinitionGroup>

</Project>

或来自

的命令行
<MSBuild Projects="demo.vcxproj" 
         Properties="ForceImportBeforeCppTargets=override.props"/>

注意作为richb在注释中指出,只有在msbuild的查找规则可以找到override.props时,上述方法才有效。要确保始终找到它,只需指定完整路径。

答案 1 :(得分:8)

如果不修改demo.vcxproj,则无法执行此操作,因为您需要访问PreprocessorDefinitions的{​​{1}},而CLCompile不是PropertyGroup,因此无法访问 <ClCompile> .... <PreprocessorDefinitions>$(MyMacro);%(PreprocessorDefinitions)</PreprocessorDefinitions> </ClCompile> 通过MSBuild命令行传递。

您可以通过项目属性 - &gt;修改GUI中的预处理器定义。配置属性 - &gt; C / C ++ - &gt;预处理器,或直接编辑XML:

  <Target Name="TestBuild" Returns="@(ManagedTargetPath)">
    <MSBuild Projects="demo.vcxproj" Targets="NormalBuild" Properties="MyMacro=THISGETSSETBUTDOESNOTHING"/>
  </Target>

在您的MSBuild项目中:

  MSBuild demo.vcxproj /p:MyMacro=THISGETSSETBUTDOESNOTHING

这相当于将MSBuild.exe作为:

运行
{{1}}

答案 2 :(得分:1)

基于@Kevin答案,您需要在PropertySheet中定义用户定义的宏。然后创建一个引用用户定义宏的预处理器。现在,您可以在代码中使用新的预处理器值。最后,对于构建,您可以使用/p标志更改用户定义的宏的值。 在这里,我定义了一个用户定义的值,例如mymacro和一个预处理器值,例如VAL。 现在,您只需使用/p:mymacro="\"some thing new\""编译项目即可。

#include <iostream>


int main() {
    std::cout << VAL << std::endl;

    getchar();
}

yourproject.vcxproj

<ClCompile>
  ...
  <PreprocessorDefinitions>VAL=$(mymacro);%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>

msbuild yourproject.vcxproj /p:mymacro="\"some thing new\""