“config-style”cmake find_package 在父范围中不可用

sve*_*evs 2 cmake

我有以下结构

project_root/
    CMakeLists.txt     (A)
    ext/
        CMakeLists.txt (B)
    apps/
        CMakeLists.txt (C)
Run Code Online (Sandbox Code Playgroud)

仅当添加这个新的“配置样式”库时,设置似乎才是根本问题。

TL;DR:当find_package(foo)(B) 中定义foo::foo为库时,如何foo::foo在父范围中提供该库,以便它target_link_libraries(tgt foo)适用于 (A) 和 (C)?

  1. 列表 (A) 定义了我的项目的选项,例如要编译支持哪些驱动程序。
  2. add_subdirectory(ext)发生,并找到所需的外部库。add_subdirectory它们是和的混合物find_package。列表 (B) 填充额外包含目录、库和编译时定义的列表,使它们可供 (A)(以及随后的 (C))使用

    set(MYPROJ_EXTRA_INC_DIRS "${MYPROJ_EXTRA_INC_DIRS}" PARENT_SCOPE)
    set(MYPROJ_EXTRA_LIBS     "${MYPROJ_EXTRA_LIBS}"     PARENT_SCOPE)
    set(MYPROJ_EXTRA_DEFINES  "${MYPROJ_EXTRA_DEFINES}"  PARENT_SCOPE)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 列表(A)现在添加了我的库,包括这些额外的目录,添加这些额外的定义,最终

    target_link_libraries(${MYPROJ_LIB_NAME} ${MYPROJ_EXTRA_LIBS})
    
    Run Code Online (Sandbox Code Playgroud)
  4. 当请求构建应用程序时,add_subdirectory(apps)列表 (C) 会定义一个简单的宏,该宏使用指定的依赖项创建可执行文件。相关部分

    target_link_libraries(${appName} ${MYPROJ_LIB_NAME} ${MYPROJ_EXTRA_LIBS})
    
    Run Code Online (Sandbox Code Playgroud)

长期以来,这种方法一直运作良好但是,我添加了对使用配置样式find_package定义的新库的支持,但我不知道如何正确使用它。

将此新库称为依赖项foo。它最终定义了一个单一的foo_LIBRARY,即foo::foo. 我的理解是我需要这样做target_link_libraries(tgt foo),它适用于我的图书馆的列表(A)。但是,它不适用于应用程序,并且在宏中我必须find_package(foo)对每个可执行文件再次执行此操作。

有没有一种方法可以使用现有的方法(list(APPEND MYPROJ_EXTRA_LIBS <something>))而不需要find_package每次都运行?

我已经用尽了所有合理的选项,要么得到-lfoo未定义的选项(如果我只是foo像我认为应该的那样附加到列表中),要么find_package()缺少 IMPORTED 或 ALIAS 目标。又名,因为find_package(foo)发生在 (B),当我们达到 (C) 时,该目标不可用。我尝试创建一个 ALIAS,但错误是无法为 IMPORTED 库创建相当于 ALIAS 的内容。

Tsy*_*rev 6

调用结果find_packageCONFIGMODULE)旨在在同一目录或以下目录中使用。您很幸运,只需将变量传播到PARENT_SCOPEfind_package即可使父级可以使用结果。

add_subdirectory(ext)发生,并找到所需的外部库。

而不是ext/CMakeLists.txt包含在add_subdirectory创建 CMake 文件(例如external.cmake)中以通过include. 因为include命令不会引入新变量的范围,所以它的find_package调用适用于 mainCMakeLists.txt

许多现有项目在文件中处理它们的依赖关系include


另一种方法是通过创建INTERFACEfind_package库目标将调用结果从子目录传播到父目录,该目标本身使用这些结果:

add_library(MyLibExtra INTERFACE)
target_link_libraries(MyLibExtra INTERFACE ${MYPROJ_EXTRA_LIBS})
target_include_directories(MyLibExtra INTERFACE ${MYPROJ_EXTRA_INC_DIRS})
target_compile_definitions(MyLibExtra INTERFACE ${MYPROJ_EXTRA_DEFINES})
Run Code Online (Sandbox Code Playgroud)