如何支持 CMake 中 Makefile 的构建时变量?

2023-11-30

虽然我已经完成了一些多平台(例如嵌入式与主机运行时环境)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 演示.c -o 演示 和 gcc -DCFG_TEST demo.c -o 演示

换句话说,CMake 生成 Makefile,当我运行它们时(通过make),我怎样才能通过一个简单的#define无需重新运行 CMake 即可进入 C/C++ 编译器?这还有道理吗?

如果这不可行或不利于 CMake 理念,那么通过命令行执行等效 CMake 的最简单方法是什么?换句话说,我该如何处理类似的事情cmake -DCFG_TEST ...并取得通过的结果-DCFG_TEST给编译器?


我将从你的最后一个问题开始:

如果这不可行或不利于 CMake 理念,那么在 cmake 命令行中执行等效操作的最简单方法是什么?换句话说,我该如何处理像 cmake 这样的东西-DCFG_TEST ...并取得通过的结果-DCFG_TEST给编译器?

Think a little有点在盒子外面。 CMake 是一个构建系统发电机。配置 CMake 后,就可以很容易地生成所需数量的构建系统。您可以生成两个构建系统:一个用于“正常”模式,另一个用于“测试”模式:

cmake -S srcs -B build_normal
cmake -S srcs -B build_test -DCMAKE_CXX_FLAGS="-DCFG_TEST"

要将其作为宏传递给编译器,请使用add_compile_definitions or target_compile_definitions. Ex.

target_compile_definitions(my_target PUBLIC "CFG_TEST=${CFG_TEST}")

我想说这是在 CMake 中做事的一种非常“惯用”的方式。权衡成本是两个构建系统及其工件的磁盘空间成本,但好处是能够并排使用它们:您可以使用一个,然后快速使用另一个,而无需切换标志并重新配置 +重建。


话虽如此,为了回答你最初的问题,

如何将简单的 #define 传递到 C/C++ 编译器而无需重新运行 CMake?这还有道理吗?

我不确定你所要求的是否可能 - 至少与Unix Makefiles生成器,并且无需构建修改后的 CMake 可执行文件。

编写Makefile时,您可以指定变量并像这样使用它们$(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.

因此,当调用生成的构建系统时,请执行以下操作如何将宏定义从“make”命令行参数(-D)传递到C源代码?,从技术上来说你可以做这样的事情:

make CXX_FLAGS=-DCFG_TEST

or (see the cmake --build命令文档为了什么 ”--“ 方法):

cmake --build <build_dir> -- CXX_FLAGS=-DCFG_TEST

但这将覆盖您告诉 CMake 为生成的任何值CXX_FLAGSMakefile 变量,所以如果你真的想这样做,你需要复制完整生成的值CXX_FLAGS然后在命令行上使用它的粘贴以及您想要添加的任何内容覆盖它,以避免丢失任何内容。

如果您想插入自己的 Makefile 变量“槽”而不是覆盖生成的变量,例如CXX_DEFINES, CXX_INCLUDES, and CXX_FLAGS,我很确定您需要构建并安装 CMake 的修改版本。要修改的相关文件是cmMakefileTargetGenerator::WriteObjectRuleFiles in the 源/cmMakefileTargetGenerator.cxx.

如果您决定修改已配置的构建系统的变量缓存并在重建之前重新生成它(老实说,这可能根本不是什么大问题(就所花费的时间而言),具体取决于项目的具体情况),您可以使用 CMake 缓存编辑工具,例如ccmake or cmake-gui,然后运行配置命令,然后调用构建系统。或者看有没有一种安全的方法可以从命令行编辑缓存变量?(TL;DR 您也可以使用-D争论)。您要么正在编辑CMAKE_CXX_FLAGS变量或类似变量,或者您自己定义的变量,然后用作编译定义,例如target_compile_definitions(<target_name> <visibility> "<name_of_your_cache_variable>=${<name_of_your_cache_variable>}").

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何支持 CMake 中 Makefile 的构建时变量? 的相关文章

  • 动态加载库和共享全局符号

    由于我在动态加载的库中观察到全局变量的一些奇怪行为 因此我编写了以下测试 首先我们需要一个静态链接库 头文件test hpp ifndef BASE HPP define BASE HPP include
  • 使用 CMake 在 iOS 中使用另一个 STATIC 库创建一个 STATIC 库

    我有一个 libfooi a 的集合 libfoo1 a libfoo2 a libfoo3 a 使用工厂 带有静态代码 有一个公共接口来创建 C 对象 使用 CMake 我选择其中之一 并创建一个链接它并添加所有内容的 libfooWra
  • 如何将新的 Visual Studio 2017 cmake 功能与 gitlab CI 运行程序结合使用

    我以直接的方式为 Linux 设置了 gitlab ci runner cmake make make test 大致如下 variables GIT SUBMODULE STRATEGY recursive stages build te
  • 控制 make 命令的输出不那么冗长,不要回显每个命令

    目前 我正在使用 Makefile 来跟踪项目的所有依赖项和编译 问题是make只是输出它正在执行的所有操作 这使得很难发现 甚至读取 更重要的信息 例如编译器警告 有没有办法控制终端上显示哪些信息 我知道有一个 s沉默的选项make 但这
  • 如何在Linux上构建GLFW3项目?

    我已经使用 cmake 和 make 编译了 glfw3 和包含的示例 没有出现任何问题 开始编写我的第一个项目 作为 opengl 和 glfw 的新手 并且对 C 和 CMake 没有经验 我正在努力理解示例构建文件 甚至要链接哪些库和
  • 如何告诉 CMake 将构建文件放在哪里?

    我想告诉 CMake 将文件和文件夹输出到不同的文件夹而不是当前文件夹 我在下面讨论的是 CMake 生成的文件 文件 CMakeCache txt 目录 CMakeFiles 文件 生成文件 目录 bin 文件 cmake install
  • 如何指定CMAKE外部项目的编译器?

    我使用ExternalProject Add 包含一个外部项目 我想要的是能够做到 cmake DCMAKE CXX COMPILER
  • CMake - 未定义参考

    我正在尝试将 gtest 包含到我的项目中 问题是我在 GTest 中收到未定义的引用错误 我正在尝试在 Gtest 中测试 Node 类 在节点的构造函数中 我使用类记录器 尽管我已将库记录器添加到 gtest target 中 但我仍然
  • VS 2010 和 CMake:“rc”未被识别为内部或外部命令

    我正在尝试使用 VS 2010 和 CMake 在 Windows 10 Home 上构建一个项目 我收到以下错误 zutil c lib nologo out zlib lib adler32 obj compress obj crc32
  • Makefile:没有规则来制作目标

    我正在关注本指南makefile http www cs colby edu maxwell courses tutorials maketutor 但我根本不理解最后一个例子 并且我无法让我的 makefile 工作 因为我收到了错误ma
  • CMake:如何更改单个目标的编译器

    我有使用交叉编译器的嵌入式项目 我想介绍一下Google测试 用原生GCC编译器编译 另外使用 CTC 编译器构建一些单元测试目标 Briefly 我有 3 个不同的目标并用 3 个不同的编译器编译它们 如何表达它CMakeLists tx
  • CMake、Exe找不到DLL

    所以我尝试在 Windows 上使用 cmake 设置一个项目 这就是我的项目结构 游戏引擎 git build include source testing CMakeLists txt 这个想法是 source 目录包含 GameEng
  • Windows 上 gnu make 的 libintl3 和 libiconv2 在哪里,需要在 MinGW 上用 ruby​​ 编译 vim

    我正在尝试为 Windows 运行 gnu make 但它无法运行 因为libint3 dll没找到 果然 http gnuwin32 sourceforge net packages make htm http gnuwin32 sour
  • 是否可以让 cmake 构建文件(CMakeLists.txt)不在 CLion 的根目录中

    是否可以让 cmake 构建文件 CMakeLists txt 不在 CLion 的根目录中 我目前正在开发的项目中 cmake 构建文件不在 CLion 项目的根目录中 在 out Debug 目录中 我希望 CLion 打开该项目的根目
  • 从 makefile 内部传递命令行参数

    我有一个 makefile 我试图从中调用一个可执行文件 该可执行文件需要 5 个参数 我如何从 makefile 传递这些参数 这样做不起作用 run exe arg1 somevalue arg2 somevalue arg3 some
  • 使用 CLion IDE 运行 Opengl 程序 [重复]

    这个问题在这里已经有答案了 我知道这个问题已经被问过 但提供的解决方案确实对我不起作用 我想通过 CLion IDE 运行我的 OpenGL 程序 我可以通过 Ubuntu 中的终端运行相同的程序 gcc progname c lglut
  • 是否可以在 Mac OS X 上构建 FreeGLUT?

    我正在做一些关于 OpenGL 的教程 http www arcsynthesis org gltut Basics Tutorial 2001 html那个使用FreeGLUT http freeglut sourceforge net
  • CMake GUI:指定 Windows 的库路径

    我正在编译一个基于 CMake 的项目 具体来说是 SOCI 它依赖于 SQLite 这是Windows 没有可供项目研究的标准路径 因此它找不到SQLite 我在配置时得到这个 SQLite3 not found some librari
  • 生成带有完整路径的 gcc 依赖项

    我有一个简单的项目 看起来像这样 build file1 o one file1 o file2 o depend Makefile src file1 cpp one file1 cpp file2 cpp Makefile 是这样的 G
  • 找不到包“gdk-pixbuf-2.0”

    我正在尝试在 Amazon Linux 发行版实例上构建 librsvg 我已经通过 yum 安装了大部分依赖项 其中一些在实例上启用的默认 yum 存储库中不可用 因此必须从头开始构建它们 我已经走了很远 但还停留在最后一点 跑步时sud

随机推荐