Home > Blockchain >  CMake: Properly setting up a multi-directory project with a library and executable project
CMake: Properly setting up a multi-directory project with a library and executable project

Time:08-20

I'm struggling with properly setting up my CMake project. I've been trying to fix this error for the past 2 days. I'm currently learning CMake so please, pardon a "nooby" question.

I have a library, let's call it "InternalLibrary" and an executable project, called "App". InternalLibrary uses a static library, let's call it "ExternalLibrary". Since I want to actively test InternalLibrary while developing it, I setup a multi-directory project.

Here's how directory structure looks like:

Root
├───App
│   └───src/
└───InternalLibrary
    ├───include/
    ├───Libs/
    │   └───ExternalLibrary/
    │       ├───include/
    │       └───lib/
    └───src/

Here's root's CMakeLists.txt:

cmake_minimum_required(VERSION 3.12)
project(LibraryProject)
add_subdirectory(InternalLibrary)
add_subdirectory(App)

InternalLibrary's CMakeLists.txt:

cmake_minimum_required(VERSION 3.12)
project(InternalLibrary)

set(CMAKE_CXX_STANDARD 17)

add_library(InternalLibrary STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/internallibrary.cpp)

target_include_directories(InternalLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Libs/ExternalLibrary/include)
target_include_directories(InternalLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(InternalLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Libs/ExternalLibrary/lib/ExternalLibrary)

App's CMakeLists.txt:

cmake_minimum_required(VERSION 3.12)
project(App)

set(CMAKE_CXX_STANDARD 17)

add_executable(App ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)
target_link_libraries(App InternalLibrary)

And as you can see, because InternalLibrary uses ExternalLibrary, when compiling there's an error:

No rule to make target 'DIRECTORY/Root/InternalLibrary/Libs/ExternalLibrary/lib/ExternalLibrary', needed by 'App/App.exe'.  Stop.

There's no error when compiling InternalLibrary alone, so there's probably some thing I need to add in my App's CMakeLists.txt to tell CMake to include that ExternalLibrary used by InternalLibrary.

CodePudding user response:

The parameters passed to the target_link_library command as any parameter other than the first one can be:

  • A library target name
  • A full path to a library file
  • A plain library name
  • [other stuff for different use cases]

Given the parameter you're passing in

target_link_libraries(InternalLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Libs/ExternalLibrary/lib/ExternalLibrary)

you're closest to the "a full path to a library file" case, but ExternalLibrary is not the name of the library, at least not for any common library type I know of. Possible file names could be e.g. (depending on the lib type and OS)

  • libExternalLibrary.so
  • libExternalLibrary.a
  • ExternalLibrary.lib

You could use the appropriate file name here.

# may need to be adjusted depending on the exact lib file name
target_link_libraries(InternalLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Libs/ExternalLibrary/lib/libExternalLibrary.so)

Alternatively you could specify a link directory and use the "A plain library name" option:

# add directory to search for libs
target_link_directories(InternalLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Libs/ExternalLibrary/lib)

# would find e.g. libExtenalLibrary.so in .../Libs/ExternalLibrary/lib
target_link_libraries(InternalLibrary PUBLIC ExternalLibrary)
  • Related