Search code examples
c++ubuntucmakelibraries

Framework manage libraries


I have a framework which depends on multiple third party libraries. I would like to share my framework easily. For example the user needs only my includes and add my lib to use my framework, and not all the dependencies.

I use CMake to create my libs, but I am still trying to understand how it works.

The hierarchy of the project

test
├── CMakeLists.txt
├── libA
│   ├── CMakeLists.txt
│   ├── libA.cpp
│   ├── libA.hpp
├── libB
│   ├── CMakeLists.txt
│   ├── libB.cpp
│   ├── libB.hpp
└── test
    ├── CMakeLists.txt
    └── main.cpp

The libB depends on the libA, and I would like to add only the libB to make the project works.

The content of the main CMakeLists.txt located in test/:

cmake_minimum_required (VERSION 2.8.11)
project (C CXX)
include(CheckCXXCompilerFlag)

add_subdirectory("libA")
add_subdirectory("libB")
add_subdirectory("test")

The content of the main CMakeLists.txt located in test/libA:

cmake_minimum_required (VERSION 2.8.11)
project (A CXX)
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++14")
file(GLOB SOURCES "*.cpp")
add_library(A STATIC ${SOURCES})

The content of the main CMakeLists.txt located in test/libB:

cmake_minimum_required (VERSION 2.8.11)
project (B CXX)
include(CheckCXXCompilerFlag)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++14")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-static")

include_directories("../libA")
link_directories("../libA")
file(GLOB SOURCES "*.cpp")

add_library(B STATIC ${SOURCES})
target_link_libraries(B A)

The content of the main CMakeLists.txt located in test/test:

cmake_minimum_required (VERSION 2.8.11)
project (C CXX)
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++14")

include_directories(../libA)
include_directories(../libB)

link_directories(../build/libB)
link_directories(../build/libA)

add_executable(C main.cpp)

target_link_libraries(C B)

If I run the main CMake all works fine, the standalone is well generated. But if I want to create only the exe by going into test/test and running "cmake . && make", I have an undefined reference to addL(int, int). To make it works I have to add target_link_libraries(C A) at the end of the CMakeLists. Is it normal? Is it possible to add only the main library without its dependencies?


Solution

  • Command invocation

    target_link_libraries(C B)
    

    have different meanings in your use-cases.

    In "all" use-case 'B' is (previously) defined as a CMake target, so CMake knows location of the library (link_directories is not used in that case), and automatically propagates all dependencies of library 'B' to executable 'C'.

    In "test-only" use case there is no CMake target named 'B', so it is just transformed to linker option -lB. Linker searches appropriate library file under link directories (link_directories is needed in that case). But information about 'B' dependencies is lost, so automatic linking with A isn't performed.


    Your project may provide a standalone CMake script which can be included by a user of your library. The script should define all needed dependencies. Common "types" of such scripts are FindXXX.cmake and XXXConfig.cmake, which can be included via find_package(XXX) command.