如何配置 CMake 目标或命令来预处理 C 文件?

Posted

技术标签:

【中文标题】如何配置 CMake 目标或命令来预处理 C 文件?【英文标题】:How to configure CMake target or command to preprocess C file? 【发布时间】:2012-07-08 12:54:33 【问题描述】:

我最初在CMake 邮件列表中问过这个问题:How to configure target or command to preprocess C file?

我正在将基于 GNU Autotools 的构建配置移植到 CMake,我必须处理 C 预处理以生成文件。

预处理器的输入是 SQL 文件,其中使用了 C 预处理器 指令,例如 #include "another.sql" 等。

目前,Makefile 使用以下规则生成纯 SQL 文件作为输出:

myfile.sql: myfile.sql.in.c
    cpp -I../common $< | grep -v '^#' > $@

因此,myfile.sql 是构建过程的产品之一,类似于共享库或可执行文件。

我应该使用什么 CMake 工具来达到同样的效果?

我不清楚我应该使用add_custom_commandadd_custom_target 还是两者兼而有之。

显然,我正在寻找一种至少可以与 GNU GCCVisual Studio 工具集一起使用的可移植解决方案。我想我必须定义特定于平台的自定义命令,一个用于cpp 预处理器,一个用于cl.exe /P

或者,CMake 是否为 C 预处理器提供任何类型的抽象?

我扫描了档案,但我只发现了基于 make 功能的 fortran 文件或解决方案的预处理:make myfile.i 所以,这不是我想要的。

更新:Added answer 基于 CMake 邮件列表中的 solution received from Petr Kmoch。

【问题讨论】:

【参考方案1】:

我通过复制解决方案received from Petr Kmoch 的重要部分来回答自己的问题,作为对我在邮件列表中的帖子的回复。

首先,使用add_custom_command(带有 OUTPUT 签名的版本)创建一个自定义命令来实际执行预处理。

例如:

add_custom_command(
  OUTPUT myfile.sql
  COMMAND "$CMAKE_C_COMPILER" -E myfile.sql.in -I ../common
  MAIN_DEPENDENCY myfile.sql.in
  COMMENT "Preprocessing myfile.sql.in"
  VERBATIM)

二、配置命令触发器:

如果命令输出文件(myfile.sql)在另一个目标中使用,添加为源 文件添加到add_libraryadd_executable,在这些命令中指定它就足够了。 CMake 会发现它是一个依赖项,并根据需要运行自定义命令。

如果命令输出文件是未用作依赖项的最终输出 任何其他目标,然后使用add_custom_target添加自定义目标来驱动命令

例如:

add_custom_target(
  ProcessSQL ALL
  DEPENDS myfile.sql
  COMMENT "Preprocessing SQL files"
  VERBATIM)

致谢:Petr Kmoch

【讨论】:

请注意,cpp 从来都不是用来预处理通用文件的。 @LtWorf 你是对的。我只需要使用 PostGIS 项目中的现有解决方案。 @mloskot 我的解决方案有个小问题:预处理器的输出没有保存在任何地方。我可以在控制台上看到输出,但无法保存预处理器结果。你有什么主意吗?非常感谢您的帮助。 @sandromark78 尝试将 -o myfile.sql 作为 C 预处理器的额外参数【参考方案2】:

要利用 CMake 的 make myfile.i 功能,您可以这样做:

add_library(sql_cpp_target EXCLUDE_FROM_ALL myfile.sql.in.c)

现在运行make myfile.sql.in.c.i 将为您生成预处理源,使用定义的CMAKE_C_FLAGS。可能可以更改预处理文件的输出名称和目录。

无论如何,您需要将这些 make 调用包装到 add_custom_target(ALL ...) 中,以使 CMake 在构建期间运行它们。

在目标定义中使用 CMAKE_MAKE_PROGRAM 变量。

如果你想从构建工具中抽象出来,你可以调用 cmake 本身来为你构建一个目标。定义自定义目标时使用$CMAKE_COMMAND --build $CMAKE_BINARY_DIR --target targetname


或者,您可以只运行指定编译器的add_custom_command() 来预处理文件并将它们放在适当的位置。但这似乎不太灵活,IMO。

【讨论】:

+1 虽然您的回答是片面的,也不是真正深入的解释,但谢谢。 我想知道您为什么选择手动完成所有操作的替代方式。 因为,我不能假设将使用“make”作为最终构建器。自定义命令提供抽象程度,使其可跨具体构建器移植。 (当然,'"$CMAKE_C_COMPILER" -E' 是 GCC 特有的,但这只是一个示例。) 您可以使用 cmake --build --target 从构建工具中抽象出来。 更新答案会很好,但对我来说,评论也有效。接受。谢谢

以上是关于如何配置 CMake 目标或命令来预处理 C 文件?的主要内容,如果未能解决你的问题,请参考以下文章

CMake基础教程(30)CMake构建系统概览

CMake基础教程(30)CMake构建系统概览

cmake 怎么配置才能生成预编译文件和汇编文件

cmake - 如何根据谁使用它来定义目标库的符号

如何知道 CMake 找到的库版本?

如何强制 CMake 链接到系统库而不是同名目标