虽然我已经完成了一些多平台(例如嵌入式与主机运行时环境)CMake“项目”,但我有一个看似简单的用例,但我不太明白。我所知道的典型 CMake 用法是这样的:
mkdir <build-dir>
cd <build-dir>
cmake -DCMAKE_TOOLCHAIN_FILE=../srcs/cmake/toolchain.cmake ../srcs
make
我在这里设置一个构建目录,移动到它,运行 cmake 来设置一个“makefile 构建系统”(即一组 Makefile 和帮助文件),然后构建东西。这一切都很好,花花公子。
为了清楚我的问题,考虑一个简单的程序:
#include <stdio.h>
int main(int, char**)
{
#if defined(CFG_TEST)
printf("Test configuration.\n");
// or #pragma message "Test configuration."
#else
printf("Normal configuration.\n");
// or #pragma message "Normal configuration."
#endif
return 0;
}
这里的想法是我希望能够在以下内容之间切换: gcc demo.c -o 演示 和 gcc -DCFG_TEST 演示.c -o 演示
换句话说,CMake 生成 Makefile,当我运行它们时(通过
make
),我怎样才能将一个简单的 #define
传递给 C/C++ 编译器而不必重新运行 CMake?这有意义吗?
如果这不可行或不利于 CMake 哲学,那么通过命令行执行等效 CMake 的最简单方法是什么?换句话说,我该如何处理像
cmake -DCFG_TEST ...
这样的东西,并导致将 -DCFG_TEST
传递给编译器?
我将从你的最后一个问题开始:
如果这不可行或不利于 CMake 理念,那么在 cmake 命令行执行等效操作的最简单方法是什么?换句话说,我如何处理 cmake
之类的东西,并导致将-DCFG_TEST ...
传递给编译器?-DCFG_TEST
跳出框框思考little位。 CMake 是一个构建系统generator。配置 CMake 后,可以很容易地生成任意数量的构建系统。您可以生成两个构建系统:一个用于“正常”模式,一个用于“测试”模式:
cmake -S srcs -B build_normal
cmake -S srcs -B build_test -DCMAKE_CXX_FLAGS="-DCFG_TEST"
我会说这是在 CMake 中做事的一种非常“惯用”的方式。权衡成本是两个构建系统及其工件的磁盘空间成本,但好处是能够将它们并排放置:您可以使用一个,然后快速使用另一个,而无需切换标志和重建。
话虽这么说,回答你最初的问题,
如何在不重新运行 CMake 的情况下将简单的#define 传递给 C/C++ 编译器?这有意义吗?
我不确定您的要求是否可行 - 至少使用
Unix Makefiles
生成器并且无需构建修改后的 CMake 可执行文件。
编写Makefiles时,可以指定变量,像
$(foo)
一样使用它们。据我所知,CMake 生成的 Makefile 没有任何供用户使用并插入编译命令的“自由浮动”变量。
例如,我在我的机器上生成了一个 Unix Makefiles 构建系统的一个非常小的 CMake 项目在其目标生成的
CMakeFiles/example.dir/build.make
文件中有一行,如下所示:
/usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /.../test.cpp -o CMakeFiles/example.dir/test.cpp.s
并且标志生成到目标的
CMakeFiles/example.dir/flags.make
中,如下所示:
CXX_DEFINES = ...
CXX_INCLUDES = ...
CXX_FLAGS = ...
CMAKE_CXX_FLAGS
, target_compile_options
, target_compile_definitions
, etc.
所以当调用生成的构建系统时,按照How to pass macro definition from "make" command line arguments (-D) to C source code?,你可以在技术上做这样的事情:
make CXX_FLAGS=-DCFG_TEST
cmake --build
命令文档了解“--
”的含义):
cmake --build <build_dir> -- CXX_FLAGS=-DCFG_TEST
但这会覆盖你告诉 CMake 为
CXX_FLAGS
Makefile 变量生成的任何值,所以如果你真的想这样做,你需要复制 CXX_FLAGS
的完整生成值,然后覆盖它带有粘贴的命令行加上您想要添加的任何内容以避免遗漏任何内容。
如果您想插入自己的 Makefile 变量“槽”而不是覆盖生成的变量,例如
CXX_DEFINES
,CXX_INCLUDES, and
CXX_FLAGS, I'm pretty sure you'd need to build and install a modified version of CMake. The relevant file to modify would be
cmMakefileTargetGenerator::WriteObjectRuleFiles` 在Source/cmMakefileTargetGenerator.cxx.
如果您决定可以修改已配置的构建系统的变量缓存并在重建之前重新生成它(老实说,这可能根本不是什么大问题(就花费的时间而言),具体取决于您项目的具体情况) ,您可以使用 CMake 缓存编辑工具,如
ccmake
或 cmake-gui
,然后运行配置命令,然后调用构建系统。或者查看是否有从命令行编辑缓存变量的安全方法?(TL; DR 您也可以使用-D
参数)。您要么编辑 CMAKE_CXX_FLAGS
变量或类似变量,要么编辑您自己定义的变量,然后将其用作编译定义,如 target_compile_definitions(<target_name> <visibility> "<name_of_your_cache_variable>=${<name_of_your_cache_variable>}")
.