【问题标题】:How do I generate included files using cmake?如何使用 cmake 生成包含的文件?
【发布时间】:2015-09-21 19:07:18
【问题描述】:

我有一个工具可以生成包含定义和声明的文件。这些文件需要包含在其他源文件或头文件中 - 它们不能独立使用。

显而易见的事情是使用自定义命令来生成它们。执行此操作的我的 CMakeLists.txt 如下。我目前正在将它与 GNU makefile 生成器一起使用。

project(test_didl)
cmake_minimum_required(VERSION 3.0)

add_custom_command(
  OUTPUT test_didl_structs.h test_didl_structs.c
  COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/didl.py --decls=test_didl_structs.h --defs=test_didl_structs.c ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/didl.py ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
  MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py)

add_executable(test_didl test_didl.c)
target_include_directories(test_didl PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(test_didl shared_lib)

test_didl.c 很简单:

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "test_didl_structs.h"
#include "test_didl_structs.c"

int main(void) {
}

但是在第一次构建时,make 会尝试构建 test_didl.c,这当然会失败,因为 test_didl_structs.* 还没有生成。自然,在第一次成功构建test_didl.c之前,依赖信息是未知的,所以make也不知道先运行python命令。

我尝试了自定义目标,但这并不好,因为假定自定义目标总是脏的。这意味着在每次构建时都会重新编译 C 文件并链接 EXE。这种方法无法扩展。

我最终的解决方案是将输出 .h 文件作为可执行文件的输入:

add_executable(test_didl test_didl.c test_didl_structs.h)

.h 文件输入被视为依赖项,但不会对 makefile 生成器做任何有趣的事情。 (我目前对其他生成器不感兴趣。)

这样可行,但感觉有点难看。它实际上并没有明确说明需要首先运行自定义命令,尽管实际上这似乎发生了。不过,我不太确定如何(但我还没有跟上阅读 CMake 生成的 Makefile 的速度)。

这是它应该如何工作的吗?还是我应该做一些更整洁的事情?

(我想,我想象的类似于 Visual Studio 预构建步骤,因为它被认为在正常依赖检查之前在每个构建上运行。但我希望这个预构建步骤具有依赖检查,因此如果其输入比其输出旧,则跳过它。)

【问题讨论】:

    标签: c cmake makefile code-generation


    【解决方案1】:

    我的最终解决方案是将输出 .h 文件作为可执行文件的输入。

    这种方式是正确的。

    它实际上声明,构建可执行文件取决于给定文件,并且,如果该文件是某些add_custom_command() 的输出,则此命令将在构建可执行文件之前执行 .


    另一种方法是使用execute_process()configuration 阶段生成所需的标头。在这种情况下,无需将头文件添加为add_executable() 的源:CMake 具有自动检测编译依赖项的概念,因此test_didl 将在test_didl_structs.h 重新生成后重新构建。

    execute_process(COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/didl.py --decls=test_didl_structs.h --defs=test_didl_structs.c ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py)
    # ...
    add_executable(test_didl test_didl.c)
    

    这种方法的缺点是您需要在更改 .py 文件后手动重新运行配置阶段。另请参阅 question 并回答它。 另一个问题是头文件将被更新每次配置运行。

    【讨论】:

      【解决方案2】:

      您可以尝试告诉 cmake 您正在使用外部源,请参阅有关 set_source_files_properties 的文档,请参阅此 past post

      【讨论】:

        猜你喜欢
        • 2015-01-27
        • 1970-01-01
        • 1970-01-01
        • 2020-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-03
        • 1970-01-01
        相关资源
        最近更新 更多