marcman
marcman

Reputation: 3383

CMake: Linking a static library from a subdirectory to an executable in another subdirectory

I have a project that uses both my own code and external code that needs to be compiled. My file tree is as follows.

PROJECT_ROOT
 |--CMakeLists.txt
 |--src
     |--CMakeLists.txt
     |--B1.cpp
     |--B1.h
     |--B2.cpp
     |--B2.h
     |
     |--ext
     |   |--CMakeLists.txt
     |   |--outside_module
     |   |   |--CMakeLists.txt
     |   |   |--A1.h
     |   |   |--A1.cpp
     |
     |--exe
         |--CMakeLists.txt
         |--runnerA.cpp
         |--runnerB.cpp

I have pasted the structure of my CMakeList.txt files below. The problem that I am having is that my runnerA executable gives me a bunch of undefined reference errors to symbols defined in A1.h and A1.cpp. For some reason, however, CMake is unable to find my library A when trying to link to the executable runnerA.

I included the rest of the code, because it compiled just fine. I am able to build executable runnerB with no problem. I have deduced that runnerB works because the source files are in my src folder, which is a parent to my exe folder, and thus the B library scope includes exe.

How can I let CMake know where to find my A library, so that it can find it when linking it to runnerA in src/exe?


PROJECT_ROOT

cmake_minimum_required(VERSION 2.8)
project(MyProject)

add_subdirectory(src)

PROJECT_ROOT/src

find_package(Module REQUIRED)

# CREATE LIBRARIES
add_library(
    B
    B1.cpp B1.h
    B2.cpp B2.h
)

# GROUP LIBRARIES TOGETHER
set(
    B_LIBS
    B
    ${Module_LIBS}
)


# INCLUDE DIRECTORIES
set(
    B_INCLUDES
    .
    ${Module_INCLUDE_DIRS}
)

# ASSIGN INCLUDES TO LIBRARY
target_include_directories(
    B PUBLIC
    ${B_INCLUDES}
)


add_subdirectory(ext)
add_subdirectory(exe)

PROJECT_ROOT/src/ext

add_subdirectory(outside_module)

PROJECT_ROOT/src/ext/outside_module

find_package(Boost COMPONENTS
    filesystem
    system
    log
    thread
    REQUIRED)

# ADD DEFINITIONS
add_definitions(-DBOOST_LOG_DYN_LINK) # Necessary to compile A with log shared libraries (instead of static)

# DEFINE LIBRARY
add_library(
    A
    A1.cpp A2.h
)

# LINK LIBRARIES
set(
    A_LIBS
    A
    ${Boost_FILESYSTEM_LIBRARY}
    ${Boost_LOG_LIBRARY}
    ${Boost_SYSTEM_LIBRARY}
    ${Boost_THREAD_LIBRARY}
)

# INCLUDE DIRECTORIES
set(
    A_INCLUDES
    ${Boost_INCLUDE_DIRS}
)

PROJECT_ROOT/src/exe

# DEFINE EXECUTABLES
add_executable(runnerB runnerB.cpp)
add_executable(runnerA runnerA.cpp)


##################
# LINK LIBRARIES
##################
target_link_libraries(
    runnerB
    ${B_LIBS}
)

target_link_libraries(
    runnerA
    ${A_LIBS}
)

target_include_directories(
    runnerA PUBLIC
    ${A_INCLUDES}
)

# INSTALLATION
install(TARGETS runnerB DESTINATION bin/)
install(TARGETS runnerA DESTINATION bin/)

Upvotes: 4

Views: 4509

Answers (1)

arrowd
arrowd

Reputation: 34391

Right, you set that ${A_LIBS} variable in nested CMakeLists.txt. The solution is to use set() command with PARENT_SCOPE or CACHE keyword.

Upvotes: 2

Related Questions