C++ msbuild:在命令行中设置特定的预处理器#define

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/166474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:24:43  来源:igfitidea点击:

msbuild: set a specific preprocessor #define in the command line

c++visual-studiomsbuild

提问by acemtp

In a C++ file, I have a code like this:

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

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

I want to set this ACTIVE define to 1 with the msbuild command line.

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

It tried this but it doesn't work:

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

msbuild /p:DefineConstants="ACTIVATE=1"

Any idea?

任何的想法?

采纳答案by acemtp

The answer is : YOU CANNOT

答案是:你不能

回答by bigh_29

I'm a little late to the party (only 4 years or so), but I just had to workaround this problem on a project, and stumbled across this question while searching for a fix. Our solution was to use an environment variable with /Ddefines in it, combined with the Additional Options box in visual studio.

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

  1. In Visual Studio, add an environment variable macro, $(ExternalCompilerOptions), to the Additional Options under project options->C/C++->Command Line (remember both Debug and Release configs)
  2. Set the environment variable prior to calling msbuild. Use the /Dcompiler option to define your macros
  1. 在 Visual Studio 中,将环境变量宏 , 添加$(ExternalCompilerOptions)到项目选项->C/C++->命令行下的附加选项(记住调试和发布配置)
  2. 在调用 msbuild 之前设置环境变量。使用/D编译器选项来定义您的宏
    c:\> set ExternalCompilerOptions=/DFOO /DBAR 
    c:\> msbuild

Item #1 ends up looking like this in the vcxproj file:

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

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

This works for me with VS 2010. We drive msbuild from various build scripts, so the environment variable ugliness is hidden a bit. Note that I have not tested if this works when you need to set the define to specific value ( /DACTIVATE=1). I think it would work, but I'm concerned about having multiple '='s in there.

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

H^2

H^2

回答by Mac

C++ projects (and solutions) are not (yet ?) integrated in the MSBuild environment. As part of the build process, the VCBuild taskis called, which is just a wrapper around vcbuild.exe.

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

You could :

你可以 :

  • create a specific configuration for your solution where ACTIVATE=1would be defined, and compile it with devenv.exe(with the /ProjectConfigswitch).
  • create your own target file to wrap your own call to the VCBuild task(see the Override parameter)...
  • use vcbuild.exe instead of msbuild.exe.(vcbuild.exe does not seem to have the equivalent of an Override parameter).
  • 为您的解决方案创建一个特定的配置ACTIVATE=1,并使用devenv.exe(使用/ProjectConfig开关)编译它。
  • 创建您自己的目标文件以包装您自己对VCBuild 任务的调用(请参阅 Override 参数)...
  • 使用 vcbuild.exe 而不是 msbuild.exe。(vcbuild.exe 似乎没有相当于 Override 参数)。

Note that your solution would not work for C# projects either unless you tweaked your project files a bit. For reference, here is how I would do this :

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

  • Add the following code before the call to <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />:
  • 在调用之前添加以下代码<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup Condition=" '$(MyConstants)' != '' ">
  <DefineConstants>$(DefineConstants);$(MyConstants)</DefineConstants>
</PropertyGroup>
  • Call MSBuild like this :
  • 像这样调用 MSBuild:
msbuild /p:MyConstants="ACTIVATE=1"

回答by Matt Howells

I think you want:

我想你想要:

/p:DefineConstants=ACTIVATE

回答by 4LegsDrivenCat

If you need to define some constant (not just true/false), you can do it the following way:

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

On command line:

在命令行上:

MSBuild /p:MyDefine=MyValue

In vcxproj file (in section <ClCompile>; and/or <ResourceCompile>, depending on where you need it):

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

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

Note that if you don't specify /p:MyDefine=MyValuein a call to MSBuildthen empty string will be assigned to MY_DEFINEmacro. If it's OK for you, that's it. If not, keep reading.

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

How to make a macro undefined if corresponding MSBuild parameter is not specified

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

To have MY_DEFINEmacro undefined instead of empty string, you can use the following trick:

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

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

First PreprocessorDefinitionsdefines unconditional macros. Second PreprocessorDefinitionsadditionally defines MY_DEFINEmacro when MyDefineis not empty string. You can test this by placing the following piece of code into your cpp file:

首先PreprocessorDefinitions定义无条件宏。当非空字符串时,第二个PreprocessorDefinitions另外定义MY_DEFINEMyDefine。您可以通过将以下代码段放入您的 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

and running:

并运行:

> 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.
...

回答by Jay

Use the CL environment variable to define preprocessor macros

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

Before calling MSBUILD, simply set the environment variable 'CL' with '/D' options like so:

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

set CL=/DACTIVATEto define ACTIVATE

set CL=/DACTIVATE定义激活

You can use the '#' symbol to replace '=' sign

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

set CL=/DACTIVATE#1will define ACTIVATE=1

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

Then make the call to MSBUILD

然后调用 MSBUILD

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

有关 CL 环境变量的更多文档,请访问:https: //msdn.microsoft.com/en-us/library/kezkeayy(v=vs.140).aspx

回答by Lex Sergeev

Maybe it is a bad idea to answer such old question, but recently I googled a similar problem and found this topic. I wrote a cmd script for some build system and I was succeed to find a solution. I leave it here for future generations (:

也许回答这样的老问题是个坏主意,但最近我在 google 上搜索了一个类似的问题并找到了这个话题。我为某些构建系统编写了一个 cmd 脚本,并成功找到了解决方案。我把它留给子孙后代(:

According to @acemtp's problem, my solution would look like this:

根据@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: I tried to use set CL=/DACTIVATE=1and it also worked, but the official documentationrecommends to use number sign

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

回答by Bruce Ikin

I needed to do this too - needed to be able to build two different versions of my app and wanted to be able to script the build using VCBUILD. VCBUILD does have the /override command line switch, but I am not sure it can be used to modify #define symbols that can then be tested using #if conditional compilation.

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

The solution I cam up with was to write a simple utility to create a header file that #defined the symbol based on the state of an environment variable and run the utility from a pre-build step. Prior to each execution of the VCBUILD step the script sets the environment variable and "touches" a file in the app to ensure that the prebuild step is executed.

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

Yes, it is an ugly hack, but it was the best I could come up with!

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

回答by stijn

For VS2010 and up, see my answer herefor a solution that requires no modification of the original project file.

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

回答by Anthony

As @bigh_29 has mentioned, using environment variables to define or undefine a preprocessor.

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

What he suggested the way to undefine a preprocessor is actually /UACTIVATE.

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

This way, any preprocessor matching ACTIVATE will be negated and compiler wouldn't go through your #if ACTIVATE #endif enclosure.

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

回答by Robert

It should probably be:

大概应该是:

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