导出导入的库

时间:2015-06-22 18:33:54

标签: cmake

我有projectA,我正在导入一个库:

add_library(foo STATIC IMPORTED)
set_property(TARGET foo PROPERTY IMPORTED_LOCATION /path/to/foo.a)

然后我在项目的几个地方使用foo,一切正常。

我希望导出一个在此项目中构建的库,以便在另一个具有完全断开连接的CMake配置的项目中使用。我有:

...
target_link_libraries(thislib foo)
export(TARGETS thislib FILE /path/to/thislib.cmake)

导入projectB也需要foo(因为导入的库需要它),并且抱怨它cannot find -lfoo。我尝试将其添加到export命令,但后来我得到了:

CMake Error at thislib/CMakeLists.txt:37 (export):
  export given target "foo" which is not built by this project.

我只想将我在本地使用的相同配置导出到另一个(导入)项目。我不想明确地告诉projectB关于foo。有没有办法实现这个目标?

3 个答案:

答案 0 :(得分:2)

我没有找到问题的实际解决方案,但我发布了自己的解决方法以供将来参考。

我意识到导出中会发出foo依赖 。它只是没有路径。由于我还没有弄清楚如何让cmake随之导出路径,因此我将export命令恢复为上述问题中显示的命令(没有foo)。

然后我回到导入foo的原始位置,移除了add_libraryset_property,将其替换为:

set(foo /path/to/foo.a)

然后将target_link_libraries更改为:

target_link_libraries(thislib ${foo})

换句话说,它不仅仅是一个真正的导入库,而是一个原始的库路径。这确实被正确写入导出文件并允许projectB链接。

答案 1 :(得分:0)

你需要

  1. 从构建地点{到foo
  2. 导出foolibs.cmake
  3. 而不是直接使用/path/to/thislib.cmake(由export(TARGETS thislib...生成的导出文件创建另一个,thislib-and-deps.cmake包括:{/ p>

    include(<...>/foolibs.cmake)
    include(${CMAKE_CURRENT_LIST_DIR}/thislib.cmake)
    

答案 2 :(得分:0)

我也找不到理想的方法来做到这一点。但这是我现在使用的解决方法。这是额外的工作,而不是干,但我认为它实现了正确的事情。

想象一下,lib B取决于第三方库AA要么定义了查找模块,要么我们可以为它实现自定义查找模块。两者都可行。假设我们已经写了FindA.cmake并存储在${CMAKE_SOURCE_DIR}/cmake中。另外,假设您运行cmake生成B的构建系统时,提供A_ROOT来帮助cmake找到A

然后在B的顶级CMakeLists.txt我们需要:

# Use FindA.cmake, defined in the cmake/ directory.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
find_package(A REQUIRED)

# ... (define the B target here)...

# Copy the config file to the build dir
configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY)

# Copy A's find module (skip this step if FindA is not custom).
configure_file(cmake/FindA.cmake cmake/FindA.cmake COPYONLY)

# Create the target export.
export(EXPORT BTargets
    FILE ${CMAKE_BINARY_DIR}/cmake/BTargets.cmake
    NAMESPACE B::
    )

# Register B so cmake can find B's config file.
export(PACKAGE B)

现在在cmake/BConfig.cmake

# Get the exported find module onto the module path.
# This step is unnecessary if the find module is part of cmake.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")

# Store the root so that find_package will work.
# You may have to store other variables here, too, but
# the principle is just more of the same.
set(A_ROOT @A_ROOT@) # **Could optionally cache this.
find_package(A MODULE REQUIRED)

# The usual one-liner for a config file.
include("${CMAKE_CURRENT_LIST_DIR}/BTargets.cmake")

为了将解决方案带回家,让我们看一下第二个例子,Rocket这次使用Boost,它已经定义了一个查找模块。

CMakeLists.txt

option(Boost_USE_MULTITHREADED ON)
option(Boost_USE_STATIC_LIBS OFF)
find_package(Boost REQUIRED COMPONENTS filesystem program_options)

add_library(Rocket rocket.cpp)
target_link_libraries(Rocket
    PUBLIC Boost::filesystem
    PRIVATE Boost::program_options
    )

configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY)

export(EXPORT RocketTargets 
    FILE ${CMAKE_BINARY_DIR}/RocketTargets.cmake
    NAMESPACE Rocket::
    )
export(PACKAGE Rocket)

然后cmake/RocketConfig.cmake会:

set(BOOST_ROOT @BOOST_ROOT@ CACHE PATH "In case boost was relocated.")
set(Boost_USE_MULTITHREADED @Boost_USE_MULTITHREADED@)
set(Boost_USE_STATIC LIBS @Boost_USE_STATIC_LIBS@)
find_package(Boost REQUIRED COMPONENTS filesystem program_options)

include("${CMAKE_CURRENT_LIST_DIR}/RocketTargets.cmake")

所以是的。打字似乎太多了。似乎cmake应该能够从export中的CMakeLists.txt语句生成所有代码。但这种策略似乎达到了目标。

另外,我还没有测试过,但我怀疑,如果你的传递依赖使用CONFIG而不是MODULE find_package,那么它应该很容易也可以在配置文件中添加CMAKE_PREFIX_PATH