cmake: настройка нескольких проектов и зависимостей между ними

Мне нужна помощь с написанием хорошего CMakeLists.txt для проектов C ++.

Я искал ответ, но я нашел что-нибудь.
Это структура моих проектов:

MainProj
|  ProjLib/
|  |  include/
|  |  |  proj_lib.h
|  |  src/
|  |  |  proj_lib.cc
|  |  CMakeLists.txt
|  ProjExec/
|  |  include/
|  |  |  proj_exec.h
|  |  src/
|  |  |  proj_exec.cc
|  |  CMakeLists.txt
|  CMakeLists.txt

MainProj CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(MainProj CXX)

# enable C and C++ language
enable_language(C CXX)

# Add sub-directories
add_subdirectory(ProjLib)
add_subdirectory(ProjExec)

ProjLib CMakeLists.txt

set (PROJLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
set (PROJLIB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)

set(PROJLIB_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/src/proj_lib.cc
)

include_directories("${PROJLIB_SOURCE_DIR}")
include_directories("${PROJLIB_INCLUDE_DIR}")

add_library(ProjLib SHARED ${PROJLIB_SRCS} ${PROJLIB_INCLUDE_DIR})

target_include_directories (ProjLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

ProjExec CMakeLists.txt

set (PROJEXEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set (PROJEXEC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)

set(PROJEXEC_SRCS
${PROJEXEC_SOURCE_DIR}/proj_exec.cc
)

include_directories("${PROJEXEC_SOURCE_DIR}")
include_directories("${PROJEXEC_INCLUDE_DIR}")

add_executable(ProjExec ${PROJEXEC_SRCS})

target_link_libraries (ProjExec LINK_PUBLIC ProjLib)

proj_exec.cc

#include "proj_lib.h"...

И он не нашел proj_lib.h в файле proj_exec.cc.
Если мне нужны дополнительные записи в каком-то cmake?

Любая помощь будет оценена. 🙂

7

Решение

Вам нужно использовать цели CMake и их свойства:

MainProj / CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
project(MainProj)

# Add sub-directories
add_subdirectory(ProjLib)
add_subdirectory(ProjExec)

ProjLib / CMakeLists.txt

add_library(ProjLib SHARED src/proj_lib.cc)
target_include_directories(ProjLib PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)

ProjExec / CMakeLists.txt

add_executable(ProjExec src/proj_exec.cc)
target_include_directories(ProjExec PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(ProjExec ProjLib)

target_link_libraries гарантирует, что при построении цели соответствующие каталоги PUBLIC и INTERFACE будут использоваться соответствующим образом.

14

Другие решения

Ваш шаблон проекта cmake выглядит хорошо и автономно. Во-первых, я собираюсь предположить, GAITPARAMS_SRCS должен был быть PROJEXEC_SRCS который в настоящее время указывает на proj_exec.cc содержит метод main (). (Если вы собираетесь управлять списком SRCS, будьте осторожны, чтобы не добавлять исходные файлы вверху списка, add_executable ожидает, что основная функция будет в первой записи)

Во-вторых, проблема в вашем ProjLib/CMakeLists.txt, Попробуйте заменить ваш target_include_directories позвоните с этим:

target_include_directories (ProjLib PUBLIC ${PROJLIB_INCLUDE_DIR})

Это распространит информацию о включаемом каталоге в ProjExec, когда target_link_libraries Команда применяется. Если вы не хотите этого делать, я думаю, вы можете получить доступ через #include <include/ProjLib.h> но это просто сбивает с толку. Я рекомендую добавить еще одну папку в папку include (названную точно так же, как и в папке cmake) и добавить в нее свои заголовки. Как это:

MainProj
|  ProjLib/
|  |  include/
|  |  |  ProjLib/
|  |  |  |  proj_lib.h
|  |  src/
|  |  |  proj_lib.cc
|  |  CMakeLists.txt

Это позволяет вам включать заголовки с именем Foldername (не говоря уже о предотвращении конфликта имен). Как это:

#include <ProjLib/proj_lib.h>

И настроить ваши файлы CMakeLists.txt в соответствии с шаблоном.

1

Все перечисленные ниже действительны, но лучший вариант объясняется в ответ Rubenvb.


У вас есть как минимум 3 варианта:

1) Добавьте следующую строку в ProjExec / CMakeLists.txt:

 target_include_directories (ProjExec PUBLIC ${CMAKE_SOURCE_DIR}/ProjLib/include)

2) Вы можете расширить видимость переменной PROJLIB_INCLUDE_DIR, добавив CACHE INTERNAL ключевые слова

 set(PROJLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "")

и затем используйте его в ProjExec / CMakeLists.txt:

 target_include_directories (ProjExec PUBLIC ${PROJLIB_INCLUDE_DIR})

Увидеть Как установить глобальную переменную в функции для cmake?
Конечно, ProjLib должен быть первым в add_subdirectory последовательность в основном файле CMakeLists.txt.

3) Я не мог проверить это. Если вы используете CMakeLists.txt в ProjLib, используйте эту строку:

 target_include_directories (ProjLib PUBLIC ${PROJLIB_INCLUDE_DIR})

Затем в CMakeLists.txt ProjExec вы можете извлечь свойство INTERFACE_INCLUDE_DIRECTORIESи используйте это:

 get_target_property(ProjLib PROJLIB_INCLUDE_DIR INTERFACE_INCLUDE_DIRECTORIES) #Do not use anymore CACHE INTERNAL (Point 2)
target_include_directories (ProjExec PUBLIC ${PROJLIB_INCLUDE_DIR}) #or PRIVATE

Эти 2 строки можно сжать в одну, используя CMake-генератор-выражение (Непроверенные):

target_include_directories (ProjExec PUBLIC $<TARGET_PROPERTY:ProjLib,INTERFACE_INCLUDE_DIRECTORIES>) #or PRIVATE

Смотрите также target_include_directories а также get_target_property.


Другие заметки:

  • Либо использовать include_directories или же target_include_directories, не оба.
  • Обычно вам не нужно иметь исходный каталог в качестве включаемого каталога, то есть вы можете удалить include_directories("${PROJLIB_SOURCE_DIR}") а также include_directories("${PROJEXEC_SOURCE_DIR}")
-1
По вопросам рекламы [email protected]