【问题标题】:How to define a C++ preprocessor macro through the command line with CMake?如何使用 CMake 通过命令行定义 C++ 预处理器宏?
【发布时间】:2022-01-01 11:01:22
【问题描述】:

我尝试在 CMake 的命令行中设置预处理器宏。我试过了:

set generator="Visual Studio 8 2005"
set params=-D MY_MACRO=1
cmake.exe -G %generator% %params% ..\some_project

但它既没有在我编译时定义,也根本无法在 CMake 生成的文件中找到名称 MY_MACRO,除了 CMakeCache.txt 它以以下形式存在:

MY_MACRO:UNINITIALIZED=1

我该怎么做?

【问题讨论】:

  • 如果你现在解决了这个问题,我会对解决方案感兴趣
  • @ybungalobill:不能从命令行注入宏,只能修改 CMakeLists.txt 中定义的现有宏。此外,set params=-D MY_MACRO=1 应该是 set params=-DMY_MACRO=1
  • @TimMeyer:是的,请看下面我的回答。
  • @ybungalobill 我在 7 年前就感兴趣了 ;) 感谢您提供答案,我相信它会帮助许多其他人。

标签: c++ cmake


【解决方案1】:

试试这个:-D CMAKE_CXX_FLAGS=/DMY_MACRO=1

【讨论】:

  • 它确实有效。它会覆盖CMAKE_CXX_FLAGS 的值。我试过-D CMAKE_CXX_FLAGS="/DMY_MACRO=1 ${CMAKE_CXX_FLAGS}"${CMAKE_CXX_FLAGS} 没有得到扩展。有谁知道如何解决这个问题?
  • 命令行中的双引号字符串将被 bash 扩展。由于您没有名为 CMAKE_CXX_FLAGS 的环境变量,因此 bash 在 cmake 看到它之前将其扩展为“”。请改用单引号。
  • @Tolli 似乎也不起作用。它可以防止 bash 扩展变量,但 cmake 也不会扩展它。它将文字值/DMY_MACRO=1 ${CMAKE_CXX_FLAGS} 直接传递给编译器。
  • @Tolli:我没有在 bash 上运行它。并非所有世界都是 bash。
  • ` -DCMAKE_CXX_FLAGS:="-D_GLIBCXX_USE_CXX11_ABI=0 -DTSI_OPENSSL_ALPN_SUPPORT=0"` 似乎对我有用
【解决方案2】:

除非你有充分的理由,否则你应该使用ADD_DEFINITIONS(<name>=<value>[, ...])

只需将以下行添加到您的 CMakeLists.txt:

ADD_DEFINITIONS("MY_MACRO=1")

CMake 会处理开关的语法(-D<name>=<value>/D<name>=<value>)。

【讨论】:

  • 修改 CMakeLists.txt 不算作命令行解决方案。是的,我有充分的理由不这样做。我必须自动化构建过程,而且我不应该更改源代码。
  • 对不起,空间不足;我想添加一个命令行解决方案,但它并不是您想要的。尽管如此,从命令行执行它只会让你的一天变得痛苦,相信我。
  • 有时命令行比 gui 应用程序更有用,有时则不然。我真的不认为你可以说这会让你的一天变得痛苦,因为这真的取决于情况、用户的技能和个人喜好。
【解决方案3】:

一个不错的选择是定义一个 cmake 选项:

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

后跟一个条件:

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

然后您可以通过命令行使用 cmake 使用 -D 标志打开/关闭该选项。示例:

cmake -DDEFINE_MACRO=OFF ..

为确保编译器正确接收定义,您可以在详细模式下调用 make 并检查是否定义了宏:

make VERBOSE=1

这也是一个很好的解决方案,因为make 将在任何 cmake 选项更改时重新编译您的代码。

【讨论】:

  • 这需要修改 CMakeLists,所以它不是解决方案 (-1)。
  • @YakovGalka 不完全正确,他建议事先更改 CmakeLists.txt,以便可以在后续构建中定义/取消定义宏。同意它不提供最大的灵活性,但对于大多数用例来说,这是人们需要的。
  • 可以使用add_compile_definitions 代替add_definitions。见define preprocessor macro through cmake
【解决方案4】:

这个问题背后的动机是批量构建 3rd 方库,这就是我想避免修改 CMakeLists 的原因。多年后,即使我不再需要它,我发现它很容易通过 CMake 外部的手段来实现:

  • 像往常一样调用 CMake,没有特殊标志。

  • 然后:

    • 使用 MSVC: 编译器读取 CL 环境变量以获取额外的命令行参数。所以

        set CL=/DMY_MACRO=1 %CL%
      

      然后调用 MSBuild 来完成它的工作。

    • 使用 Makefile: 生成的 makefile 使用 CFLAGSCXX_FLAGS 变量,就像预期的 makefile 一样。所以构建可以通过

        make CXX_FLAGS=-DMY_MACRO=1
      

      或者通过设置相应的环境变量。

【讨论】:

  • 这是命令行构建的一个很好的解决方法,但我也希望用户能够使用 IDE 打开生成的解决方案文件,在这种情况下这将不起作用。遗憾的是,即使在 2020 年,也没有办法添加到 CMAKE_CXX_FLAGS 而不是指定(覆盖)它们。
  • 偶然发现这个问题后,我发现cmake -E env CXXFLAGS="-DMY_MACRO" cmake SourcePath在我的情况下有效(src:stackoverflow.com/a/44357387/1666181)。不确定这是否也会完全覆盖。
猜你喜欢
  • 2012-02-19
  • 2021-12-29
  • 2016-12-14
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多