27

在 C++ 文件中,我有这样的代码:

#if ACTIVATE
#   pragma message( "Activated" )
#else
#   pragma message( "Not Activated")
#endif

我想使用 msbuild 命令行将此 ACTIVE 定义设置为 1。

它尝试了这个,但它不起作用:

msbuild /p:DefineConstants="ACTIVATE=1"

任何的想法?

4

11 回答 11

32

我参加聚会有点晚了(只有 4 年左右),但我只需要在一个项目中解决这个问题,并在寻找解决方案时偶然发现了这个问题。我们的解决方案是使用带有/D定义的环境变量,并结合 Visual Studio 中的“附加选项”框。

  1. 在 Visual Studio 中,将环境变量宏 , 添加$(ExternalCompilerOptions)到项目选项->C/C++->命令行下的附加选项(记住调试和发布配置)
  2. 在调用 msbuild 之前设置环境变量。使用/D编译器选项来定义你的宏
    c:\> set ExternalCompilerOptions=/DFOO /DBAR 
    c:\> msbuild

项目 #1 在 vcxproj 文件中最终看起来像这样:

    <ClCompile>
      <AdditionalOptions>$(ExternalCompilerOptions) ... </AdditionalOptions>
    </ClCompile>

这适用于 VS 2010。我们从各种构建脚本驱动 msbuild,因此环境变量 ugliness 被隐藏了一点。/DACTIVATE=1请注意,当您需要将定义设置为特定值 ( )时,我没有测试这是否有效。我认为它会起作用,但我担心那里有多个'='。

H^2

于 2013-01-07T23:51:08.660 回答
12

C++ 项目(和解决方案)尚未(还?)集成到 MSBuild 环境中。作为构建过程的一部分,将调用VCBuild 任务,它只是vcbuild.exe的包装器。

你可以 :

  • 为您的解决方案创建一个特定的配置ACTIVATE=1,并使用devenv.exe(使用/ProjectConfig开关)对其进行编译。
  • 创建您自己的目标文件以包装您自己对VCBuild 任务的调用(请参阅 Override 参数)...
  • 使用 vcbuild.exe 而不是 msbuild.exe。(vcbuild.exe 似乎没有等效的 Override 参数)。

请注意,除非您稍微调整项目文件,否则您的解决方案也不适用于 C# 项目。作为参考,我将这样做:

  • 在调用之前添加以下代码<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup Condition=" '$(MyConstants)' != '' ">
  <DefineConstants>$(DefineConstants);$(MyConstants)</DefineConstants>
</属性组>
  • 像这样调用 MSBuild:
msbuild /p:MyConstants="ACTIVATE=1"
于 2008-10-03T12:22:52.557 回答
9

我想你想要:

/p:DefineConstants=ACTIVATE
于 2008-10-03T12:03:28.413 回答
7

如果您需要定义一些常量(不仅仅是true/ false),您可以通过以下方式进行:

在命令行上:

MSBuild /p:MyDefine=MyValue

在 vcxproj 文件中(在<ClCompile>; 和/或部分<ResourceCompile>,取决于您需要它的位置):

<PreprocessorDefinitions>MY_DEFINE=$(MyDefine);$(PreprocessorDefinitions)</PreprocessorDefinitions>

请注意,如果您未/p:MyDefine=MyValue在调用中指定,MSBuild则空字符串将分配给MY_DEFINE宏。如果你觉得没问题,就是这样。如果没有,请继续阅读。

如果未指定相应的 MSBuild 参数,如何使宏未定义

要使MY_DEFINE宏未定义而不是空字符串,您可以使用以下技巧:

<ClCompile>
  ....
  <PreprocessorDefinitions>_DEBUG;_CONSOLE;OTHER_UNCONDITIONAL_MACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(MyDefine)'!=''">MY_DEFINE=$(MyDefine);%(PreprocessorDefinitions)</PreprocessorDefinitions>
  ....
</ClCompile>

首先PreprocessorDefinitions定义无条件宏。第二个在非空字符串时PreprocessorDefinitions另外定义MY_DEFINE宏。MyDefine您可以通过将以下代码放入您的 cpp 文件来对此进行测试:

#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)

#ifndef MY_DEFINE
#pragma message("MY_DEFINE is not defined.")
#else
#pragma message("MY_DEFINE is defined to: [" STRINGIZE(MY_DEFINE) "]")
#endif

并运行:

> MSBuild SandBox.sln /p:Configuration=Debug /p:MyDefine=test /t:Rebuild
...
MY_DEFINE is defined to: [test]
...

> MSBuild SandBox.sln /p:Configuration=Debug /p:MyDefine= /t:Rebuild
...
MY_DEFINE is not defined.
...

> MSBuild SandBox.sln /p:Configuration=Debug /t:Rebuild
...
MY_DEFINE is not defined.
...
于 2013-04-01T15:23:24.127 回答
6

使用 CL 环境变量定义预处理器宏

在调用 MSBUILD 之前,只需使用 '/D' 选项设置环境变量 'CL',如下所示:

set CL=/DACTIVATE定义激活

您可以使用“#”符号替换“=”符号

set CL=/DACTIVATE#1将定义 ACTIVATE=1

然后拨打 MSBUILD

More documentation on the CL Environment Variables can be found at: https://msdn.microsoft.com/en-us/library/kezkeayy(v=vs.140).aspx

于 2018-04-03T12:45:38.303 回答
0

回答这么老的问题也许是个坏主意,但最近我用谷歌搜索了一个类似的问题,发现了这个话题。我为一些构建系统编写了一个 cmd 脚本,我成功地找到了解决方案。我把它留在这里留给后代(:

根据@acemtp 的问题,我的解决方案如下所示:

@echo off

:: it is considered that Visual Studio tools are in the PATH
if "%1"=="USE_ACTIVATE_MACRO" (
    :: if parameter USE_ACTIVATE_MACRO is passed to script
    :: the macro ACTIVATE will be defined for the project
    set CL=/DACTIVATE#1
)
call msbuild /t:Rebuild /p:Configuration=Release

UPD:我尝试使用set CL=/DACTIVATE=1,它也有效,但官方文档建议使用数字符号

于 2018-03-05T17:01:10.733 回答
-1

我也需要这样做——需要能够构建我的应用程序的两个不同版本,并希望能够使用 VCBUILD 编写构建脚本。VCBUILD 确实有 /override 命令行开关,但我不确定它是否可用于修改 #define 符号,然后可以使用 #if 条件编译对其进行测试。

我想出的解决方案是编写一个简单的实用程序来创建一个头文件,该文件根据环境变量的状态#defined 符号并从预构建步骤运行该实用程序。在每次执行 VCBUILD 步骤之前,脚本会设置环境变量并“接触”应用程序中的文件以确保执行预构建步骤。

是的,这是一个丑陋的黑客,但这是我能想到的最好的!

于 2009-02-20T00:04:26.410 回答
-1

对于 VS2010 及更高版本,请在此处查看我的答案,以获取不需要修改原始项目文件的解决方案。

于 2013-07-03T11:25:00.677 回答
-1

正如@bigh_29 所提到的,使用环境变量来定义或取消定义预处理器。

他建议取消定义预处理器的方法实际上是/U ACTIVATE。

这样,任何匹配 ACTIVATE 的预处理器都将被否定,并且编译器不会通过您的 #if ACTIVATE #endif 附件。

于 2017-08-23T10:23:20.653 回答
-2

应该是:

#ifdef ACTIVATE
#   pragma message( "Activated" )
#else
#   pragma message( "Not Activated")
#endif
于 2008-10-03T12:07:15.333 回答
-5

答案是:你不能

于 2008-10-07T10:48:53.913 回答