8月 292014
 

有时候我们希望在构建时能够在命令行添加一些宏定义,改变程序行为。一个典型应用示例是代码里通过检查是否定义了 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 支持 CFLAGSCXXFLAGSLDFLAGS 环境变量,分别用来指定 C 编译链接时、C++ 编译链接时、以及仅在链接时有效的选项。

目前许多项目已经使用 CMake 来构建。CMake 支持 CFLAGSCXXFLAGSLDFLAGS 等,但遗憾的是唯独不支持 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。这将不得不通过修改代码来实现。

1月 232012
 

有一本书叫 "Open Sources: Voices from the Open Source Revolution", 是一些开源界人士写的散文的集合,内容涉及社区精神、GNU 和 FSF、Linux 历史、 商业模式等等。我曾经在图书馆借阅出过一个影印版。 它在清华图书馆的逸夫馆外文图书借阅区,索书号是 TP31 FO61 2003

后来发现,书中文章都可以在 Oreilly 网站上看到,如这里是简介。

借助于 Gooogle,各篇文章也可以通过搜索得到。如想看 Larry Wall 有关 Perl 的 文章,使用如下去搜索即可:

perl site:http://oreilly.com/catalog/opensources/book/

然后你就可以发现,链接是 http://oreilly.com/catalog/opensources/book/larry.html