构建c/c++项目时添加宏定义

有时候我们希望在构建时能够在命令行添加一些宏定义,改变程序行为。一个典型应用示例是代码里通过检查是否定义了 DEBUG 宏,来决定是否输出调试信息。编译器一般提供命令行选项支持这种做法,例如使用 gcc 时可以在命令行添加 -D 选项,定义一些宏:

gcc -DDEBUG=1 a.c

不过,大型项目一般都需要自动化构建工具,如 GNU Autotools 或者 CMake。使用它们后,我们无法直接修改编译命令,但它们提供了替代方案。对于 Autotools,它可以识别 CPPFLAGS 等环境变量,从而我们可以在命令行上添加宏定义,例如:

CPPFLAGS="-DDEBUG=1" ./configure

此外,我们还可以先 export CPPFLAGS="-DDEBUG=1" ,再用 ./configure 命令。注意这里 CPPFLAGS 的 CPP 指的是 C 预处理器 (C Preprocessor),不是 C++,其中只应该设置 -I 、 -D 、 -U 等影响预处理器的选项。Autotools 支持 CFLAGS、 CXXFLAGS 、 LDFLAGS 环境变量,分别用来指定 C 编译链接时、C++ 编译链接时、以及仅在链接时有效的选项。

目前许多项目已经使用 CMake 来构建。CMake 支持 CFLAGS 、 CXXFLAGS 、LDFLAGS 等,但遗憾的是唯独不支持 CPPFLAGS 。也就是说,CMake 会无视CPPFLAGS 环境变量的值。Aron Xu 为此报了一个 BUG ,不过因为没人志愿去做,所以一直没有修复。许多人可能会以为,可以用类似 cmake .. -DVAR=VALUE 的方式来添加宏定义,但这是 无效 的。这样一来,如果想在命令行上指定宏定义,只能复用CFLAGS 或者 CXXFLAGS 变量。这基本可以工作,因为一般情况下预处理和编译是同一个命令进行的。

CMake 中标准的添加宏定义方法是使用 ADD_DEFINITIONS(-DMACRO) (参考 文档 ),不过这需要修改 CMakeLists.txt 文件。如果想要在命令行上定制宏的开关或取值,那么可以像 这里 一样,定义一个 CMake 选项:

OPTION(DEFINE_MACRO "Option description" ON) # Enabled by default

然后做一个条件判断:

IF(DEFINE_MACRO)
    ADD_DEFINITIONS(-DMACRO)
ENDIF(DEFINE_MACRO)

之后,就可以用 cmake -DDEFINE_MACRO=OFF .. 调整宏的开关或取值了。

最后值得一提的是,如果代码里已经有了宏定义语句,那么通过命令行修改其取值是 不可能 的。编译器会警告宏被重复定义,而且生效的是源文件中的定义。想要重新定义,只能随后 #undef 再 #define 。这将不得不通过修改代码来实现。

你可能感兴趣的:(c/c++)