子文件夹中的各种库,如何将它们导出到父级

Various libs in subfolders, how do I export them to the parent?

本文关键字:文件夹      更新时间:2023-10-16

>我有一个这样的代码文件夹结构:

project/
  CMakeLists.txt
  src/
    project.cpp
  lib/
    libA/
      CMakeLists.txt
      src/
        libA.cpp
      include/
        libA.h
    libB/
      CMakeLists.txt
      src/
        libB.cpp
      include/
        libB.h

现在,libA是完全独立的,所以我有一个类似于这个CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project ( libA )
set ( LIBA_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE )
include_directories ( include/ )
file (GLOB LIBA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}
  src/libA.cpp
  )
add_library         ( libA STATIC ${LIBA_SOURCES} )

但是,libB取决于libA。如何导出用于链接到libBlibA.a输出路径以及相应的包含路径?

此外,如何将该数据传递给主项目的父CMakeLists.txt

我个人没有这样做过,所以这个答案可能只是一个起点,但Qt使用cmake,并且能够将所有包含目录和库依赖项绑定到每个"模块"(库)中。如果你做到了这一点,那么你就可以简单地做

add_executable(myExe ...)
target_link_libraries(myExe libB)

到主 cmake 项目中的可执行文件。

浏览Qt脚本,似乎您需要设置(对于每个库)是:

add_library(libA ...)
set_target_properties(libA PROPERTIES
    "INTERFACE_LINK_LIBRARIES" "${LIBRARIES_LIBA_DEPENDS_ON}"
    "INTERFACE_INCLUDE_DIRECTORIES" "${LIBA_INCLUDE_DIRECTORIES}"
)

然后对于 libB

add_library(libB ...)
set_target_properties(libB PROPERTIES
    "INTERFACE_LINK_LIBRARIES" "libA"
    "INTERFACE_INCLUDE_DIRECTORIES" "${LIBB_INCLUDE_DIRECTORIES}"
)

这种方法很酷的地方在于,如果操作得当,您可以根据需要将任意数量的库链接在一起,而不必担心依赖项的组合爆炸并包含目录。

@epicbrew并@NicolasHolthaus答案/评论 我只是想展示完整示例在较新版本的 CMake 中的外观,并讨论一些含义:

项目/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project( project )
add_subdirectory( lib/libB )
add_subdirectory( lib/libA )
add_executable( project src/project.cpp )
target_link_libraries( project libB )

project/lib/libA/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project( libA )
add_library( libA STATIC src/libA.cpp include/libA.h )
target_include_directories( libA PUBLIC include )

project/lib/libB/CMakeLists.txt

add_library( libB STATIC src/libB.cpp  include/libB.h )
target_include_directories( libB PUBLIC include )
target_link_libraries( libB libA )

如您所见

  1. 您需要在主CMakeLists.txt文件中知道您还需要libA .我故意反转add_subdirectory()调用,以表明使用target_link_libraries()时顺序无关紧要(有点允许目标前向声明)。
  2. 您不再需要本地include_directories()调用,它是target_include_directories()的隐式部分。
  3. 有了target_include_directories(... PUBLIC ...)这些包含路径是自我传播的。
  4. 您无需添加${CMAKE_CURRENT_SOURCE_DIR}前缀,这些是默认值。
  5. 我只是将源/头文件直接添加到 add_executable()/add_library() 调用中,以实现此示例代码的紧凑性。通常,我也会将它们放在局部变量中。
  6. libB不是独立的,但您可以更改它,例如通过将add_subdirectory( ../libA libA )添加到其CMakeLists.txt文件中。显然,您必须从主CMakeLists.txt中删除add_subdirectory( lib/libA )
  7. 如果要稍微优化 CMake 处理,则不应重复project()命令。如果您仍然希望libA自给自足,您可以在cmake_minimum_required(VERSION 3.0)/project( libA )调用周围添加if ( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )/endif()

CMake 知道你构建的所有目标,因此无需将信息导出到父级。您只需告诉 CMake libB 链接 libA 和 CMake 负责在链接器命令行上放置正确的路径。因此,只需在libB/CMakeLists中将libA指定为libB的链接依赖项.txt:

target_link_libraries(libB libA)

对于包含路径,您需要按照顶级项目/CMakeLists.txt中的以下内容在父级中设置变量:

set(LIBA_INCLUDES libA/include)
set(LIBB_INCLUDES libB/include)

然后在子项目 CMakeList.txt 文件中引用这些内容。

或者,您可以在libB/CMakeLists.txt文件中使用相对路径:

include_directories(../libA/include)