【问题标题】:CMake: relink when linked package is rebuiltCMake:重建链接包时重新链接
【发布时间】:2014-07-01 20:23:20
【问题描述】:

如果已经有人问过这个问题,我深表歉意,但我无法在网上找到正确的方法来让这件事发挥作用。

我有一个 cmake 项目 Foo,它依赖于另一个 cmake 项目 Bar。目标:每当重新安装 Bar 时(只更改库,而不是标题),然后 Foo 应该重新链接(当然不重建)。

所以,在项目 Foo (只有一个目标,一个可执行文件)的顶层文件夹中的 CMakeLists.txt 中,我有 cmake 命令

FIND_PACKAGE(Bar REQUIRED)

在配置时正确地找到了项目 Bar。在我创建目标的部分,我有

LINK_DIRECTORIES (${BAR_LIBRARY_DIRS} )
ADD_EXECUTABLE(foo.exe main.cpp)
TARGET_LINK_LIBRARIES(foo.exe ${BAR_LIBRARIES})

里面的两个变量是在BarConfig.cmake中定义的,也是FIND_PACKAGE(Bar)要找的那个,只包含以下指令

SET(BAR_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/../../../include")
SET(BAR_LIBRARY_DIRS "${CMAKE_CURRENT_LIST_DIR}/../../../lib")
SET(BAR_LIBRARIES bar)

我在屏幕上打印了这些变量,它们包含您希望它们包含的内容(/path/to/folder/include、/path/to/folder/lib 和 bar)。

所以,我在某处读到 cmake 无法向未指定完整路径的库添加依赖项。应该写

TARGET_LINK_LIBRARIES (foo.exe full-path-to-bar-libraries)

在这种情况下,它可以工作。但这并不令人满意。首先,导致路径可以改变。但是你可以从一个变量中读取它,你可能会说。真的。但是,第二,即使在这种情况下,如果项目 Bar 包含许多未知的库,则必须费力地创建正确的字符串以添加到那里...

但是,我还读到如果该库也使用 cmake 构建和安装,它应该会自动运行。事实上,我还有另一个项目对,A 依赖于 B,都是用 cmake 构建的。在这种情况下,依赖是有效的。不幸的是,项目 B 是巨大的,并且定义了大量的 cmake 宏,我无法确定它设置正确变量的部分。

您是否知道每次重新安装库 Bar 时如何让 Foo 重新链接(而不重建)?我想避免使用完整路径。

谢谢

编辑:更清楚一点:如果库 Bar 设置了一个变量 BAR_LIBRARIES 包含其所有库的完整路径,那么 TARGET_LINK_LIBRARIES 将起作用。但是,BAR_LIBRARIES 很可能包含“bar”,而不是“/some/path/libbar.a”。鉴于 LINK_DIRECTORIES 提供的目录和 TARGET_LINK_LIBRARIES 提供的库名称,我希望 cmake 能够将这两部分放在一起。例如。如果 BAR_LIBRARY_DIRS 包含 '/folder1/;/folder2/' 并且 BAR_LIBRARIES 包含 'bar1;bar2',我希望 cmake 建立对 libbar1.a 和 libbar2.a 的依赖关系,可在以下任一位置找到:

  1. /folder1/libbar1.a
  2. /folder2/libbar1.a
  3. /folder1/libbar2.a
  4. /folder2/libbar2.a

如果自上次链接以来已创建依赖项的任何依赖项发生更改,则重新链接。

【问题讨论】:

    标签: c++ linker cmake


    【解决方案1】:

    并且仅包含以下说明

    您不需要手动设置所有这些变量,只需使用CMakePackageConfigHelpers 模块:

    configure_package_config_file(
        "./FooConfig.cmake.in"
        "${foo_config}"
        INSTALL_DESTINATION ${CONFIG_INSTALL_DESTINATION}
        PATH_VARS CONFIG_INSTALL_DESTINATION
    )
    
    install(
        FILES "${foo_config}"
        DESTINATION ${CONFIG_INSTALL_DESTINATION}
    )
    

    并安装目标:

    install(
        TARGETS foo DESTINATION ${LIB_INSTALL_DESTINATION} EXPORT FooTargets
    )
    install(
        EXPORT FooTargets NAMESPACE Foo:: DESTINATION ${CONFIG_INSTALL_DESTINATION}
    )
    

    在其他项目中的使用:

    find_package(Foo CONFIG REQUIRED)
    target_link_libraries(boo Foo::foo)
    

    就是这样。像魅力一样工作(Makefile 生成器example):

    > cmake -HFoo -B_builds/Foo -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="`pwd`/_install"
    > cmake --build _builds/Foo/ --target install
    > cmake -HBoo -B_builds/Boo -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="`pwd`/_install" -DCMAKE_VERBOSE_MAKEFILE=ON
    > cmake --build _builds/Boo
    

    再一次(检查没有重新链接):

    > cmake --build _builds/Boo
    

    修改目标Foo并重新安装:

    > echo "void some(){}" >> Foo/foo.cpp
    > cmake --build _builds/Foo/ --target install
    

    现在构建Boo

    > cmake --build _builds/Boo
    ...
    Linking CXX executable boo.exe
    ...
    

    重新链接!

    【讨论】:

    • 感谢您的回复。我按照您发布的链接中的示例进行操作,但无法获取重新链接的代码。
    • cmake版本为2.8.10.1。内核是Linux版本2.6.32(gcc版本4.4.7 20120313(Red Hat 4.4.7-4)(GCC))
    • 谢谢,我会尽快尝试一下。只是......我在哪里可以找到它?
    猜你喜欢
    • 2019-09-20
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多