CMake:导入目标的链接顺序不正确

时间:2018-12-27 09:27:43

标签: cmake

我有以下情况:

  • 我将两个预构建的库导入到我的项目(libAlibB
  • libB依赖于libA
  • 可执行文件同时依赖于libAlibB

但是,我的link.txt中的相对链接顺序不正确

/usr/bin/c++     CMakeFiles/bin.dir/main.cpp.o  -o bin ../libA.a ../libB.a

我希望libA.a会在libB.a之后列出。 CMakeLists.txt看起来与以下几行相似

cmake_minimum_required(VERSION 3.13)
project(cmake_test)
set(lib_dir ${CMAKE_CURRENT_SOURCE_DIR})

add_library(MY::libA IMPORTED INTERFACE)
set_target_properties(MY::libA PROPERTIES INTERFACE_LINK_LIBRARIES "${lib_dir}/libA.a")

add_library(MY::libB IMPORTED INTERFACE)
set_target_properties(MY::libB PROPERTIES INTERFACE_LINK_LIBRARIES "MY::libA;${lib_dir}/libB.a")

add_executable(bin ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
target_link_libraries(bin PUBLIC MY::libB MY::libA)

在下面我对解决问题的尝试的描述中。有的没有成功,有的却成功,但有一些修改使代码对生产环境无用。

成功尝试:

  • 删除binlibA的依赖(即用target_link_libraries(bin PUBLIC MY::libB)替换最后一行。这可行,但是我不能删除真实代码中的依赖关系。
  • 将目标类型IMPORTED INTERFACE替换为IMPORTED STATIC。使用IMPORTED_LOCATION代替INTERFACE_LINK_LIBRARIES,并使用target_link_libraries表示libBlibA的依赖性。在这种情况下,link.txt产生:[...] -o bin ../libA.a ../libB.a ../libA.a。恢复libB的目标类型后,链接顺序再次崩溃。但是,在生产环境中,柯南创建的目标之一为IMPORTED INTERFACE

尝试不成功(与上述行为相同):

  • 为每个库创建一个单独的IMPORTED目标(使用IMPORTED_LOCATION)并将它们分组在INTERFACE目标中
  • 在代码上加上ADD_DEPENDENCIES
  • 从第9行的libA中删除INTERFACE_LINK_LIBRARIES,而改用target_link_libraries(MY::libB INTERFACE MY::libA)。结果相同。

使用INTERFACES作为构建块显示相同失败的示例代码

cmake_minimum_required(VERSION 3.13)
project(cmake_test)
set(lib_dir ${CMAKE_CURRENT_SOURCE_DIR})

# libA
add_library(MY::libA_file1 IMPORTED STATIC)
set_target_properties(MY::libA_file1 PROPERTIES IMPORTED_LOCATION "${lib_dir}/libA.a")

add_library(libA INTERFACE)
target_link_libraries(libA INTERFACE MY::libA_file1)

# libB
add_library(MY::libB_file1 IMPORTED STATIC)
set_target_properties(MY::libB_file1 PROPERTIES IMPORTED_LOCATION "${lib_dir}/libB.a")

add_library(libB INTERFACE)
target_link_libraries(libB INTERFACE MY::libB_file1 libA)


add_executable(bin ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
target_link_libraries(bin PUBLIC libA libB)

1 个答案:

答案 0 :(得分:1)

您错误地将 INTERFACE_LINK_LIBRARIES 属性视为库目标的“内容”,该属性是通过target_link_libraries调用排序的。

使用

target_link_libraries(MY::libB INTERFACE MY::libA)

您在库目标MY::libBMY::libA之间设置了链接依赖关系。也就是说,MY::libB目标的“内容”应该在链接命令行中的MY::libA目标的“内容”之前。

但是 INTERFACE_LINK_LIBRARIES 属性不是是库目标的“内容”!这只是附加的链接依赖性。

相反, IMPORTED_LOCATION (对于非 INTERFACE IMPORTED 目标)是库的“内容”,并且{{1} }会影响其顺序。

似乎您无法使用 INTERFACE 库目标为库添加链接依赖关系。为此,您应该使用 IMPORTED 库目标:

target_link_libraries