如何使用cmake生成包含的文件?

时间:2015-07-03 23:30:27

标签: c cmake makefile code-generation

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

显而易见的事情是使用自定义命令来生成它们。我的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预构建步骤,因为在正常的依赖性检查之前,它被考虑在每个构建上运行。但是我想要这个预构建步骤以进行依赖性检查,以便在输入比其输出旧时跳过它。)

2 个答案:

答案 0 :(得分:1)

  

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

这种方式是正确的。

它实际上表明,在给定文件上构建可执行文件取决于,如果该文件对某些add_custom_command()是OUTPUT,则此命令将在之前执行建立可执行文件。

另一种方法是使用configurationexecute_process()阶段生成所需的标头。在这种情况下,不需要添加头文件作为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并回答它。 另一个问题是每次运行配置时都会更新头文件。

答案 1 :(得分:0)

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