使用CMake运行预构建步骤的最佳实践



假设您有一个存储库,其中有一个文件夹(命名为dataset(,其中包含几个.csv文件和一个python脚本(命名为csvcut.py(,该脚本获取数据集中的所有.csv并生成相应的.h文件。

这些.h文件包含在一些.cpp文件中,用于构建用于测试的可执行文件(add_executable(testlib...(。

假设您使用add_custom_target(test_pattern...创建一个运行csvcut.py的目标(名为test_pattern(,并使用add_dependencies(testlib test_pattern)在构建testlib之前运行脚本。

这是可行的,但如果:会更好

  • 只有当数据集文件夹中的文件或脚本本身发生更改时(而不是.cpp发生更改时(,才运行脚本
  • .h文件是在构建文件夹(即build/tests/dataset/(的子文件夹中生成的,并包含在.cpp文件中,如so#include <tests/dataset/generated.h>

您对进行这些改进/优化有什么建议吗?

谢谢,Alberto

这需要多个步骤,但都可以用标准CMake处理。首先,我们将使用add_custom_command来实际生成文件。我还添加了一个自定义目标,但只是因为我不知道如何让INTERFACE库在没有它的情况下工作

add_custom_command(
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/include/foo.h"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/gen.py"
DEPENDS
gen.py
foo.h.in
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include"
)
add_custom_target(gen_files
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/foo.h"
)

在我的例子中,gen.py只是抛出一个基本的头文件,但这并不重要。列出你需要的任何文件作为输出,你的csv文件应该在DEPENDS下(对我来说,foo.h.in试图模拟这一点(。

由于您只提到生成头文件,所以我创建了一个依赖于gen_files目标的INTERFACE库。我还添加了适当的include目录。

add_library(foo INTERFACE)
target_include_directories(foo
INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/include"
)
add_dependencies(foo
gen_files
)

如果构建STATIC/SHARED库,我可以在源和依赖项工作时直接添加生成的文件,但INTERFACE库需要额外的目标(即使我尝试在add_dependencies下列出文件(。既然你已经有了一个自定义目标,我想这不会是一个大问题。

最后,我有一个链接到foo的可执行文件。

add_executable(main
main.c
)
target_link_libraries(main
PRIVATE
foo
)

演示:

$ make clean 
$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  include  Makefile
$ make
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[ 66%] Building C object CMakeFiles/main.dir/main.c.o
[100%] Linking C executable main
[100%] Built target main
$ make clean
$ make main
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[ 66%] Building C object CMakeFiles/main.dir/main.c.o
[100%] Linking C executable main
[100%] Built target main
$ make
[ 33%] Built target gen_files
[100%] Built target main
$ touch ../foo.h.in 
$ make
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[100%] Built target main
$ touch ../gen.py 
$ make
[ 33%] Generating include/foo.h
[ 33%] Built target gen_files
[100%] Built target main
$ ls include/
foo.h

如果输入(foo.h.in(或生成脚本(gen.py(发生更改,则重建目标。

最新更新