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
msbuild: set a specific preprocessor #define in the command line
提问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 /D
defines in it, combined with the Additional Options box in visual studio.
我参加聚会有点晚了(只有 4 年左右),但我只需要在一个项目中解决这个问题,并在寻找修复程序时偶然发现了这个问题。我们的解决方案是使用一个带有/D
定义的环境变量,并结合 Visual Studio 中的附加选项框。
- 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) - Set the environment variable prior to calling msbuild. Use the
/D
compiler option to define your macros
- 在 Visual Studio 中,将环境变量宏 , 添加
$(ExternalCompilerOptions)
到项目选项->C/C++->命令行下的附加选项(记住调试和发布配置) - 在调用 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=1
would 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=MyValue
in a call to MSBuild
then empty string will be assigned to MY_DEFINE
macro. 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_DEFINE
macro 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 PreprocessorDefinitions
defines unconditional macros. Second PreprocessorDefinitions
additionally defines MY_DEFINE
macro when MyDefine
is not empty string. You can test this by placing the following piece of code into your cpp file:
首先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
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=/DACTIVATE
to define ACTIVATE
set CL=/DACTIVATE
定义激活
You can use the '#' symbol to replace '=' sign
您可以使用“#”符号替换“=”符号
set CL=/DACTIVATE#1
will 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=1
and 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
回答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