2017-02-16 6 views
0

У меня есть проект, который использует как мой собственный код, так и внешний код, который необходимо скомпилировать. Мое дерево файлов выглядит следующим образом.CMake: связать статическую библиотеку из подкаталога с исполняемым файлом в другом подкаталоге

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 

Я вставил структуру своих файлов CMakeList.txt ниже. Проблема, которую я испытываю, заключается в том, что мой исполняемый файл runnerA дает мне кучу неопределенных ссылочных ошибок для символов, определенных в A1.h и A1.cpp. По какой-то причине CMake не может найти мою библиотеку A при попытке ссылки на исполняемый файл runnerA.

Я включил остальную часть кода, потому что он скомпилирован просто отлично. Я могу создать исполняемый файл runnerB без проблем. Я пришел к выводу, что runnerB работает, потому что исходные файлы находятся в моей папке src, которая является родительским элементом моей папки exe, и поэтому область библиотеки B включает в себя exe.

Как я могу позволить CMake знать, где найти мою A библиотеку, так что он может найти его, когда связывая его с runnerA в 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/внутр

add_subdirectory(outside_module) 

PROJECT_ROOT/SRC/внутр/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/ех

# 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/) 
+0

Вам необходимо связать свой исполняемый файл с A: 'target_link_libraries (runnerA A)'. – arrowd

+0

@arrowd: Я сделал. В моем коде для параметра 'PROJECT_ROOT/src/exe'. Исправлено: – marcman

+0

@arrowd: Кроме того, я считаю, что это проблема масштаба. Как мои команды CMake работают для runnerB – marcman

ответ

0

Правильно, вы установили, что ${A_LIBS} переменный в вложен CMakeLists.txt. Решение состоит в использовании set() command с ключевым словом PARENT_SCOPE или CACHE.

+0

Что происходит, как и в моем случае, когда мне нужен «grandparent» scope? – marcman

+0

Используйте 'CACHE', это создаст запись в' CMakeCache.txt', и, следовательно, ваша переменная будет глобальной. – arrowd

+0

И не забудьте 'ФОРС' в этом случае тоже! – arrowd