c++ - cmake add_dependency、add_custom_command 和 add_custom_target 不能一起工作

标签 c++ cmake dependencies cmake-custom-command add-custom-target

我一直在尝试获得简单的用例,即让 cmake 使用脚本生成一些文件,然后从这些生成的文件中构建一个可执行文件。在花了几个小时阅读文档和各种堆栈溢出答案之后,似乎一切都应该如此安排,但 cmake 拒绝配置项目。

这个想法是通过以下步骤完成事情:

  1. 在配置期间,会使用正确的路径生成generate_files.sh
  2. 在构建期间,首先构建目标 gen,然后构建目标 test

步骤 1 已正确执行,但步骤 2 未正确执行。 Cmake 提示找不到目标 test 的源文件,尽管它应该先构建 gen 然后再找到源代码。

我做错了什么?

目录结构:

.
├── build
├── CMakeLists.txt
├── config
│   └── generate_files.sh.in
├── extern
│   ├── CMakeLists.txt
│   └── gen
├── scripts
└── src
    ├── CMakeLists.txt
    └── main.cpp

顶级 CMakeLists:

cmake_minimum_required(VERSION 3.13)
project(test VERSION 0.1.0.0)

add_subdirectory(src)
add_subdirectory(extern)

configure_file("${CMAKE_SOURCE_DIR}/config/generate_files.sh.in" "${CMAKE_SOURCE_DIR}/scripts/generate_files.sh")

src/CMakeLists:

add_executable(test main.cpp)

外部/CMakeLists:

set(generated_sources
    ${CMAKE_CURRENT_SOURCE_DIR}/gen/generated.h
    ${CMAKE_CURRENT_SOURCE_DIR}/gen/generated_1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/gen/generated_2.cpp
    )

set(generated_directories
    ${CMAKE_CURRENT_SOURCE_DIR}/gen)

add_custom_command(
    OUTPUT ${generated_sources}
    COMMAND "${CMAKE_SOURCE_DIR}/scripts/generate_files.sh"
    )

add_custom_target(gen
    DEPENDS ${generated_sources}
    )

add_dependencies(test gen)

target_sources(test
    PRIVATE
        ${generated_sources}
)

target_include_directories(test
    PRIVATE
        ${generated_directories}
)

config/generate_files.sh.in:

#! /bin/bash

echo " const int get_trouble_code();
const int get_higher_trouble_code();" > ${CMAKE_SOURCE_DIR}/extern/gen/generated.h
echo " #include \"generated.h\"
const int get_trouble_code(){return 1;}" > ${CMAKE_SOURCE_DIR}/extern/gen/generated_1.cpp
echo " #include \"generated.h\"
const int get_higher_trouble_code(){return 1+1;}" > ${CMAKE_SOURCE_DIR}/extern/gen/generated_2.cpp

src/main.cpp:

#include "generated.h"

int main()
{
  get_trouble_code();
  get_higher_trouble_code();

  return 0;
}

编辑:我找到了一种让它发挥作用的方法,但现在我更困惑了。将生成的文件添加为库而不是自定义目标似乎可以解决问题。对 extern/CMakeLists 的以下更改有效,但有人可以解释原因吗? :

set(generated_sources
    ${CMAKE_CURRENT_SOURCE_DIR}/gen/generated.h
    ${CMAKE_CURRENT_SOURCE_DIR}/gen/generated_1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/gen/generated_2.cpp
    )

set(generated_directories
    ${CMAKE_CURRENT_SOURCE_DIR}/gen)

add_custom_command(
    OUTPUT ${generated_sources}
    COMMAND "${CMAKE_SOURCE_DIR}/scripts/generate_files.sh"
    )

#comment out this stuff
#add_custom_target(gen
#   DEPENDS ${generated_sources}
#    )
#
#add_dependencies(test gen)
#
#target_sources(test
#    PRIVATE
#        ${generated_sources}
#)

#add as library instead
add_library(gen ${generated_sources})
target_link_libraries(test PRIVATE gen)

target_include_directories(test
    PRIVATE
        ${generated_directories}
)

最佳答案

CMake complains that the source files for target test aren't found ...

这是因为源文件不存在,其GENERATED属性未设置。

通常,add_custom_command 为其 OUTPUT 中列出的所有文件设置 GENERATED 属性。但在 CMake 3.20 之前,该属性位于目录本地:

  • add_custom_command 是从 extern/CMakeLists.txt 调用的,但是
  • target test 在创建目标的顶级 CMakeLists.txt 中评估其源。 (无论在哪里调用 target_sources)。

在 CMake 3.20 中,GENERATED 属性变为全局(要使用此功能,您的项目应该具有相应的 cmake_minimum_required)。

如果无法更新 CMake,那么您可以在顶级 CMakeLists.txt手动设置 GENERATED 属性。 (这会损害您的 CMakeLists.txt 的局部性。因此最好更新 CMake。)

从技术上讲,您会触发 that bugreport 中发布的问题.

关于c++ - cmake add_dependency、add_custom_command 和 add_custom_target 不能一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75502630/

相关文章:

python - OpenVINO:如何使用推理引擎构建 OpenCV 以启用从模型优化器加载模型

javascript - TypeScript 库的存储库应该包含 JS 版本吗?

node.js - npm 通过 package.json 中的依赖项安装私有(private) github 存储库

c++ - 运算符 '==' 错误

cmake - Clion/Cmake 和 Eigen 错误

CMake find_library 找不到库

c# - 当前文件夹中的 .dll 出现 DllNotFoundException

c++ - 这种内存使用优化技术在 union 的情况下是否可行?

c++ - 在 AVI、H.264 文件中查找关键帧

c++ - 在定义之前显式实例化模板函数