在 C++ 文件中,我有这样的代码:
#if ACTIVATE
# pragma message( "Activated" )
#else
# pragma message( "Not Activated")
#endif
我想使用 msbuild 命令行将此 ACTIVE 定义设置为 1。
它尝试了这个,但它不起作用:
msbuild /p:DefineConstants="ACTIVATE=1"
任何的想法?
在 C++ 文件中,我有这样的代码:
#if ACTIVATE
# pragma message( "Activated" )
#else
# pragma message( "Not Activated")
#endif
我想使用 msbuild 命令行将此 ACTIVE 定义设置为 1。
它尝试了这个,但它不起作用:
msbuild /p:DefineConstants="ACTIVATE=1"
任何的想法?
我参加聚会有点晚了(只有 4 年左右),但我只需要在一个项目中解决这个问题,并在寻找解决方案时偶然发现了这个问题。我们的解决方案是使用带有/D
定义的环境变量,并结合 Visual Studio 中的“附加选项”框。
$(ExternalCompilerOptions)
到项目选项->C/C++->命令行下的附加选项(记住调试和发布配置)/D
编译器选项来定义你的宏 c:\> set ExternalCompilerOptions=/DFOO /DBAR
c:\> msbuild
项目 #1 在 vcxproj 文件中最终看起来像这样:
<ClCompile>
<AdditionalOptions>$(ExternalCompilerOptions) ... </AdditionalOptions>
</ClCompile>
这适用于 VS 2010。我们从各种构建脚本驱动 msbuild,因此环境变量 ugliness 被隐藏了一点。/DACTIVATE=1
请注意,当您需要将定义设置为特定值 ( )时,我没有测试这是否有效。我认为它会起作用,但我担心那里有多个'='。
H^2
C++ 项目(和解决方案)尚未(还?)集成到 MSBuild 环境中。作为构建过程的一部分,将调用VCBuild 任务,它只是vcbuild.exe的包装器。
你可以 :
ACTIVATE=1
,并使用devenv.exe(使用/ProjectConfig开关)对其进行编译。请注意,除非您稍微调整项目文件,否则您的解决方案也不适用于 C# 项目。作为参考,我将这样做:
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
:<PropertyGroup Condition=" '$(MyConstants)' != '' "> <DefineConstants>$(DefineConstants);$(MyConstants)</DefineConstants> </属性组>
msbuild /p:MyConstants="ACTIVATE=1"
我想你想要:
/p:DefineConstants=ACTIVATE
如果您需要定义一些常量(不仅仅是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.
...
使用 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
回答这么老的问题也许是个坏主意,但最近我用谷歌搜索了一个类似的问题,发现了这个话题。我为一些构建系统编写了一个 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
,它也有效,但官方文档建议使用数字符号
我也需要这样做——需要能够构建我的应用程序的两个不同版本,并希望能够使用 VCBUILD 编写构建脚本。VCBUILD 确实有 /override 命令行开关,但我不确定它是否可用于修改 #define 符号,然后可以使用 #if 条件编译对其进行测试。
我想出的解决方案是编写一个简单的实用程序来创建一个头文件,该文件根据环境变量的状态#defined 符号并从预构建步骤运行该实用程序。在每次执行 VCBUILD 步骤之前,脚本会设置环境变量并“接触”应用程序中的文件以确保执行预构建步骤。
是的,这是一个丑陋的黑客,但这是我能想到的最好的!
对于 VS2010 及更高版本,请在此处查看我的答案,以获取不需要修改原始项目文件的解决方案。
正如@bigh_29 所提到的,使用环境变量来定义或取消定义预处理器。
他建议取消定义预处理器的方法实际上是/U ACTIVATE。
这样,任何匹配 ACTIVATE 的预处理器都将被否定,并且编译器不会通过您的 #if ACTIVATE #endif 附件。
应该是:
#ifdef ACTIVATE
# pragma message( "Activated" )
#else
# pragma message( "Not Activated")
#endif
答案是:你不能