"配置风格" cmake find_package在父范围内不可用

时间:2018-02-12 00:26:29

标签: cmake

我有以下结构

project_root/
    CMakeLists.txt     (A)
    ext/
        CMakeLists.txt (B)
    apps/
        CMakeLists.txt (C)

设置似乎是根本问题,只有在添加这个新的" config-style"库。

TL; DR:当(B)中的find_package(foo)foo::foo定义为库时,如何在父作用域中使foo::foo可用,以便{{1}将适用于(A)和(C)?

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

    find_package
  3. List(A)现在添加我的库,包括这些额外的目录,添加这些额外的定义,最终

    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)
    
  4. 当请求构建应用程序时,target_link_libraries(${MYPROJ_LIB_NAME} ${MYPROJ_EXTRA_LIBS}) 发生,列表(C)定义一个使用指定依赖项创建可执行文件的简单宏。相关部分

    add_subdirectory(apps)
  5. 很长一段时间以来一直很好用。但是,我添加了对使用config-style find_package定义的新库的支持,而我无法弄清楚如何正确使用它。

    调用此新库依赖项target_link_libraries(${appName} ${MYPROJ_LIB_NAME} ${MYPROJ_EXTRA_LIBS}) 。它最终定义了一个foo foo_LIBRARY。我的理解是我需要做foo::foo,它在我的库的列表(A)中工作。但是,它不适用于应用程序,并且在宏中我必须为每个可执行文件再次执行target_link_libraries(tgt foo)

    有没有办法使用每次都需要运行find_package(foo)的现有方法(list(APPEND MYPROJ_EXTRA_LIBS <something>))?

    我已经用尽了所有合理的选项,并且未定义find_package(如果我只是将-lfoo添加到列表中,就像我认为的那样),或{{1 IMPORTED或ALIAS目标缺少。}自foo发生在(B)以来,当我们达到(C)时,该目标不可用。我尝试制作一个ALIAS,但错误是相当于ALIAS的东西无法创建到IMPORTED库。

1 个答案:

答案 0 :(得分:3)

find_package调用的结果( CONFIG MODULE )旨在用于同一目录或以下目录。您很幸运,将变量简单地传播到 PARENT_SCOPE 会使父项可以使用find_package的结果。

  

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

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

许多现有项目处理include文件中的依赖项。

另一种方法是通过创建本身使用这些结果的 INTERFACE 库目标,将find_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})