cmake-command target_source 踩坑

target_source BASE_DIRS和FILES的联动

FILES选项

An optional list of files to add to the file set. Each file must be in one of the base directories, or a subdirectory of one of the base directories.

cmake文档中说明FILES选项列出的文件必须是相对于base directories的,即BASE_DIRS

BASE_DIRS

An optional list of base directories of the file set. Any relative path is treated as relative to the current source directory (i.e. CMAKE_CURRENT_SOURCE_DIR). If no BASE_DIRS are specified when the file set is first created, the value of CMAKE_CURRENT_SOURCE_DIR is added.

文档说明在如果不给出该选项则默认值为CMAKE_CURRENT_SOURCE_DIR

note: 如果是相对路径,依然是相对于CMAKE_CURRENT_SOURCE_DIR

遇到的问题

configure_file(config.h.in config.h @ONLY)

add_executable(Main main.cpp)

target_sources(
    Main
    PRIVATE
    FILE_SET HEADERS
    #BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR}
    FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h
)

configure_file的output的文件是相对于CMAKE_CURRENT_BINARY_DIR的,所以我在上面的代码里写得是FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h

Path to the output file or directory. A relative path is treated with respect to the value of CMAKE_CURRENT_BINARY_DIR. If the path names an existing directory the output file is placed in that directory with the same file name as the input file. If the path contains non-existent directories, they are created.

这就造成了一个问题,上面的cmake代码是搜索不到config.h

fatal error: config.h: No such file or directory
    1 | #include "config.h"

原因

Target properties related to include directories are also modified by target_sources(FILE_SET) as follows:

INCLUDE_DIRECTORIES
If the TYPE is HEADERS, and the scope of the file set is PRIVATE or PUBLIC, all of the BASE_DIRS of the file set are wrapped in $<BUILD_INTERFACE> and appended to this property.

INTERFACE_INCLUDE_DIRECTORIES
If the TYPE is HEADERS, and the scope of the file set is INTERFACE or PUBLIC, all of the BASE_DIRS of the file set are wrapped in $<BUILD_INTERFACE> and appended to this property.

target_source会通过BASE_DIRS选项追加INCLUDE_DIRECTORIESINTERFACE_INCLUDE_DIRECTORIES。上方的代码将BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR}注释掉,就会造成INCLUDE_DIRECTORIES默认为CMAKE_CURRENT_SOURCE_DIR,而CMAKE_CURRENT_BINARY_DIR是不在搜索范围内的。

通过以下代码打印一下

include(CMakePrintHelpers)

cmake_print_properties(
    TARGETS Main
    PROPERTIES INCLUDE_DIRECTORIES
)
  1. BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR}
 Properties for TARGET Main:
   Main.INCLUDE_DIRECTORIES = "$<BUILD_INTERFACE:/home/xxx/CMake/cookbook/second_chapter/recipe_05/build>"
  1. BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR}
 Properties for TARGET Main:
   Main.INCLUDE_DIRECTORIES = "$<BUILD_INTERFACE:/home/xxx/CMake/cookbook/second_chapter/recipe_05/build>"
posted @ 2026-07-12 15:33  杨忆州  阅读(2)  评论(0)    收藏  举报