代码之家  ›  专栏  ›  技术社区  ›  Nathaniel

CMake静态库依赖项不与ExternalProject_Add一起传播

  •  6
  • Nathaniel  · 技术社区  · 10 年前

    我目前正在尝试让一个可执行文件与它需要的所有依赖项正确链接。

    以下是依赖项的示例结构:

    exe -> libA -> libB
    

    exe libA 有自己的存储库。 exe文件 拉入 libA语言 类似于:

    add_executable(exe ${sources})
    
    ExternalProject_Add(
        libA
        GIT_REPOSITORY http://some/git/url/libA.git
        ...
    )
    
    target_include_directories(exe PRIVATE ${libA_includes})
    target_link_libraries(exe ${libA_libs}/libA.a)
    
    add_dependencies(exe libA)
    

    libA语言 拉入 libB 以类似的方式:

    add_library(libA STATIC ${sources})
    
    ExternalProject_Add(
        libB
        URL http://some/artifact/repo/libB.tgz
        ...
    )
    
    target_include_directories(libA PRIVATE ${libB_includes})
    target_link_libraries(libA ${libB_libs}/libB.a)
    
    add_dependencies(libA libB)
    

    我可以建造 libA语言 好的,还有一个测试可执行文件 利比亚银行 。然而,当我尝试构建 exe文件 ,它只与 libA语言 但不是 利比亚银行 。我如何让CMake知道 libA语言 利比亚银行 不应该通过ExternalProject丢失?

    编辑:

    我创建了一些依赖关系图,希望能阐明我想要的:

    实际值:

    exe actual libA actual

    我的期望:

    expected

    如有任何帮助,将不胜感激。谢谢

    编辑2:

    我最终使用了以下解决方案:

    在libA的CMakeLists.txt(其中 ${MODULE_NAME} 是libA中某个模块的名称):

    export(TARGETS ${MODULE_NAME}
           NAMESPACE "${CMAKE_PROJECT_NAME}-"
           APPEND FILE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-targets.cmake)
    

    在exe的CMakeLists.txt中:

    ExternalProject_Add(
        libA ...
    )
    
    ExternalProject_Get_Property(libA source_dir)
    ExternalProject_Get_Property(libA binary_dir)
    
    target_include_directories(${PROJECT_NAME} PRIVATE ${source_dir})
    
    set(LIBA_TARGETS_FILE ${binary_dir}/libA-targets.cmake)
    if(EXISTS ${LIBA_TARGETS_FILE})
        include(${LIBA_TARGETS_FILE})
        target_link_libraries(${MODULE_NAME} libA-module_in_liba)
    endif()
    
    add_dependencies(${MODULE_NAME} libA)
    

    注意:这现在需要使用两次运行 cmake 如下所示:

    mkdir build; cd build
    cmake .. # initial configuration
    make # download the external projects
    cmake .. # be able to include targets cmake file from external projects
    make # this should now link everything properly
    
    1 回复  |  直到 10 年前
        1
  •  6
  •   metropolision daniel.wirtz    10 年前

    据我所知,使用一次配置运行和ExternalProject功能无法实现您想要的目标。你似乎在使用 ${libA_libs}/libA.a ,这当然没有任何进一步的信息。由于项目libA和libB可能来自完全不同的供应商,因此在配置时无法从主项目中得知libA甚至包含一个链接依赖libB(这也是在libA中构建的)。

    我将假设你想使用传递链接的(相当自然的)思想。 根据您是否自己开发libA/libB,有不同的选项。我将解释“最干净”的做法。缺点是这也需要修改libA项目cmake。[如果无法做到这一点,则需要手动将libB.a添加为硬编码的链接库;即解决传递性问题。抱歉!]

    传递链接的关键是您需要导入实际的 目标 由CMake-in创建 libA ,然后正确地具有 target_link_libraries 信息到libB,一切都会正常工作。的目标配置 libA语言 可以使用 INSTALL (.. EXPORT )cmake中的功能,然后允许您使用 find_package(LIBA CONFIG) .然后,您的exe CMakeLists.txt应该如下所示

    find_package(LIBA CONFIG QUIET)
    if (NOT LIBA_FOUND)
        AddExternalProject(libA .....)
        return
    else()
        add_executable(exe ${sources})
        target_link_libraries(exe <libA-target-name>)
    

    这将在链接时包含libB,并设置正确的包含路径(如果在 target_include_directories(libA PUBLIC ${LIBA_INCDIR} ..)

    关键问题是在 相同的配置运行 当然,无法生成findpackage将设置的所有内容,因为尚未编译/安装任何内容。外部项目背后的想法是,你告诉它把东西放在哪里,这样你就知道应该在哪里找到东西,但不幸的是,这永远不会包括像链接库这样的可传递的东西。

    有(一如既往)更快、更脏的解决方案,然而,通过CONFIG模式下的find_package将包模块化并将其作为目标提供的“新”cmake方式是将cmake感知项目相互包含的最佳且简单的方式。