CMake项目结构:如何正确地将库合并在一起并将它们包含在多个可执行文件中

Posted

技术标签:

【中文标题】CMake项目结构:如何正确地将库合并在一起并将它们包含在多个可执行文件中【英文标题】:CMake Project Structure: How do I properly merge libraries together and include them in multiple executables 【发布时间】:2019-07-24 20:09:07 【问题描述】:

我正在构建一个 C 项目,目前我对如何正确链接库有点迷茫。

总结一下:我将有 3 个具有多个可执行文件的项目。这些项目将使用具有多个目录(子库)的库中的代码。我在包含目录中包含项目的所有包含。而且我也会有一个用于 src 和 lib 的测试目录。

如何链接位于单独目录中的库?

有没有办法可以将所有这些库合并到一个主库中,所以我只需链接一个库?

结构如下:

Project:
   |-- bin   
   |-- build   
   |-- src     
   |   |-- Project 1   
   |   |      |-- Project1a.c
   |   |      |-- Project1b.c
   |   |      |-- cmakelists.txt
   |   |-- Project 2
   |   |      |--Project2.c
   |   |-- Project 3
   |   |      |--Project3.c
   |   |-- cmakelists.txt
   |
   |-- lib 
   |    |--Crypto_Lib
   |    |      |-- Crypto.c
   |    |      |-- cmakelists.txt
   |    |--Communications_Lib
   |    |      |-- Communications.c
   |    |      |-- cmakelists.txt
   |    |--Error_Lib
   |    |      |-- Error.c
   |    |      |-- cmakelists.txt
   |    |--cmakelists.txt
   |
   |-- include
   |    |--src
   |    |   |-- Project 1
   |    |   |     |-- Project1a.h
   |    |   |     |-- Project1b.h
   |    |   |-- Project 2
   |    |   |     |-- Project2.h
   |    |   |-- Project 3
   |    |         |-- Project3.h    
   |    |--lib
   |    |  |--Hash 
   |    |  |    |-- Crypto.h
   |    |  |--Communications
   |    |  |    |-- Communications.h
   |    |  |--Error
   |    |  |    |-- Error.h
   |
   |-- test
   |    |--src (etc...)
   |    |--lib (etc...)
   |    |--cmakelists.txt
   |
   |--cmakelists.txt

我目前拥有的 CMAKES:

~/CMakeLists.txt

    add_subdirectory(lib)
    add_subdirectory(src)
    add_subdirectory(test)

~/lib/CMakeLists.txt

    #To access the header file
    include_directories($CMAKE_SOURCE_DIR/includes/lib)   

    add_subdirectory(communications)
    add_subdirectory(crypto)
    add_subdirectory(error)

~/src/CMakeLists.txt

    #To access the header file
    include_directories($CMAKE_SOURCE_DIR/includes/src)   

    add_subdirectory(project_one)
    add_subdirectory(project_two)
    add_subdirectory(project_three)

~/lib/communications/CMakeLists.txt

    add_library(Comm_Lib STATIC communications.c)

~/lib/crypto/CMakeLists.txt

    add_library(Crypto _Lib STATIC crypto.c)

~/lib/error/CMakeLists.txt

    add_library(Error_Lib STATIC error.c)

~/src/project_one/CMakeLists.txt

    add_executable(Project_1A Project_1a.c)
    add_executable(Project_1B Project_1B.c)

    #target_link_library(Project_1A Full_Library) Would like to be able to join all libraries together

~/src/project_two/CMakeLists.txt

    add_executable(Project_Three Project_two.c)

~/src/project_one/CMakeLists.txt

    add_executable(Project_Three Project_three.c)

~/test/CMakeLists.txt

    add_subdirectory(lib_test)
    add_subdirectory(src_test)  

    **Haven’t gotten any deeper in the test CMakeLists.txt

我知道我还没有使用过 link_libraries,我只是想找出解决这个问题的最佳方法。

感谢您的帮助!

【问题讨论】:

【参考方案1】:

您几乎明白了:您可以将可执行文件与其他目录中定义的库链接起来。没有问题。

add_executable(Project_1A Project_1a.c)
add_executable(Project_1B Project_1B.c)

target_link_library(Project_1A PUBLIC Full_Library)

但是,我建议您只链接到您直接使用的库的部分:

add_executable(Project_1A Project_1a.c)
add_executable(Project_1B Project_1B.c)

# Project_1A only use crypto directly in it's code
target_link_library(Project_1A PUBLIC Crypto_Lib) 

# Project_1B use comm and error directly in it's code
target_link_library(Project_1B PUBLIC Comm_Lib Error_Lib) 

然后,不要使用include_directories 函数,而是使用target_include_directories。可以选择添加包含目录作为使用要求。该要求将传播到使用此要求的其他库:

target_include_directories(Comm_Lib INTERFACE $CMAKE_CURRENT_SOURCE_DIR)

使用上面的那一行,任何链接到Comm_Lib 的人都会将通信库目录作为包含路径。

如果你真的把这三个库聚合在一起,Full_Library可以这样定义:

add_library(Full_Library INTERFACE)

target_link_libraries(Full_Library INTERFACE Comm_Lib Crypto_Lib Error_Lib)
target_include_directories(Full_Library INTERFACE common/include/dir)

【讨论】:

在 Project_1 的 cmakelist.txt 中,我尝试为 Project_1A 添加 Comm Library,但是当我将communications.h 添加到 project_1a.c 时,它说我找不到该文件。我错过了什么吗?另外,包括 PUBLIC 的原因是什么?谢谢! 另外,假设我还有一个在其他库中使用的库(实用程序)。如何将它们包含在其他库中? @AlexErling 如果您需要包含目录并使用特定库,则必须将其添加为接口包含目录。让我编辑 好的,谢谢您的信息。最后一个问题是,我将目标包含在哪些 Cmake 中?在我的示例中,是 ~/src/Cmakelist.txt,还是库将使用的任何 cmake?我假设我需要为我添加的每个库都这样做? @AlexErling 你可以添加一个包含包含目录的纯接口库:add_library(common INTERFACE) 并添加包含目录target_include_directory(common INTERFACE your/include/dir)

以上是关于CMake项目结构:如何正确地将库合并在一起并将它们包含在多个可执行文件中的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将库模块依赖项添加到 Flutter Plugin 的 Android 文件夹? [关闭]

如何使用自制软件、cMake 和 cLion 将库添加到 C++ 项目

如何将多个文件列表与 CMake 合并在一起?

如何从 firestore 两个集合中获取数据并将所有数据合并在一起

如何正确地将多个合并还原为远程主控

将库链接到 cmake 项目中的所有目标