简体   繁体   中英

CMake Project Structure: How do I properly merge libraries together and include them in multiple executables

I am building a C Project and I'm currently a little lost on how to properly link in the libraries.

To summarize: I will have 3 projects that will have multiple executables. The projects will be using code from a library that will have multiple directories (sub-libraries). I have all the includes for the project in an includes directory. And I also will have a testing directory for the src and the lib as well.

How do I link in a library thats in a separate directory?

Is there a way to I can merge all these libraries into one main library, so I only have to link a single library?

The structure looks like this:

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 I currently have:

~/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

I know I haven't used link_libraries yet, I'm just trying to figure out the best way to go about this.

Thanks for any help!

You almost got it: you can link your executables with the libraries defined in other directories. There is no problem with that.

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

target_link_library(Project_1A PUBLIC Full_Library)

However, I would suggest you link only to the parts of the library you are using directly:

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) 

Then instead of using the include_directories function, use the target_include_directories . There's an option to add the include directory as a usage requirement. That requirement will be propagated to other libraries which use this one:

target_include_directories(Comm_Lib INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

With that line above, anyone who links to Comm_Lib will have the communication library directory as include path.

If you really and to aggregate the three library together, Full_Library can be defined like this:

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM