Библиотека общего доступа CMake с несколькими исполняемыми файлами
мой проект содержит несколько исполняемых файлов с общим кодом. Я хотел бы поместить общий код в статическую библиотеку, на которую могут ссылаться исполняемые файлы. (Общий код довольно мал, и я предпочитаю не иметь дело с общими библиотеками).
дерево источника выглядит примерно так это:
- CMakeLists.txt
- общий
- CMakeLists.txt
- src
- включить
- приложения app1
- src
- CMakeLists.txt
- приложения app2
- src
- CMakeLists.txt
app1 и app2 оба зависят от кода в общий.
этот общий код очень специфичен для приложения и никогда не будет использоваться другим проектом вне этого дерева каталогов. По этой причине я бы предпочел не устанавливать библиотеку в каком-либо глобальном месте.
CMakeLists верхнего уровня.txt-файл просто добавляет подкаталоги:
project(toplevel)
cmake_minimum_required(VERSION 3.1)
add_subdirectory(common)
add_subdirectory(app1)
add_subdirectory(app2)
CMakeLists общей библиотеки.txt-файл создает статическую библиотеку и устанавливает каталоги:
add_library(common STATIC common.cpp)
target_include_directories(common PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include")
и файл для исполняемые файлы выглядят следующим образом:
project(app1)
cmake_minimum_required(VERSION 3.1)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} common)
теперь мой вопрос. Если я запускаю CMake из каталога проектов верхнего уровня, я могу создать app1 и app2, и они успешно строятся. Однако, если я хочу построить один из этих проектов (например, запустив CMake из app1) вместо построения из каталога верхнего уровня, я получаю ошибку, потому что common/include
не добавляется в путь поиска заголовка.
Я понимаю, почему это происходит. В CMakeLists ничего нет.формат txt файл для app1 или app2, который" тянет " общий. Это делается только на высшем уровне.
есть ли способ обойти это, или это поведение обычно считается приемлемым? Что - то в моей настройке не оптимально? Я просто думаю, что было бы неплохо иметь возможность создавать проекты индивидуально, а не с верхнего уровня в случае, если мы начнем разрабатывать все больше и больше исполняемых файлов, которые используют эту общую библиотеку, но, возможно, это то, что меня не должно беспокоить о.
2 ответов
вы должны использовать project()
команда в подкаталогах, только если этот подпроект предназначен для создания как автономного, так и в составе проекта верхнего уровня. Например, это относится к LLVM и Clang: Clang можно компилировать отдельно, но когда система сборки LLVM обнаруживает источник Clang, она также включает в себя его цели.
в вашем случае вам не нужно подпроекты. Компилировать только app1
или app2
объектом make app1
/make app2
в проектах build dir.
когда вы настраиваете свою среду сборки, вы должны подумать о следующих трех темах (помимо других, но для этого обсуждения / ответа я сократил его до трех, которые, как я чувствую, актуальны здесь):
- Dependecies / Соединение
- развертывание
- команды
"Сильной Связью"
я подумал о add_subdirectory()
команда как поддерживающ "сильное соединение" и Ваше текущая настройка неявно поддерживает:
- часто меняется
common
библиотека - одно развертывание (процесс и время) для всех ваших приложений
- одна команда, работающая на полной исходной базе
- IDE покажет все это в одном решении
- вы создаете одну среду сборки для всего
"Свободная Связь"
если вы хотите больше "свободная связь" вы можете использовать внешние скрипты на других языках или использовать CMake ExternalProject_Add()
макрос. Поэтому, если вы установите common
библиотека (возможно, даже включая "двоичную доставку") и каждый app
в качестве отдельного проекта вы поддерживаете:
- менее часто меняется
common
библиотека- вероятно, с собственными циклами выпуска
- независимый цикл разработки / развертывания для каждое приложение
- команда различных разработчиков, работающих над каждым
app
смесь
Итак, как вы можете видеть есть много вещей, чтобы рассмотреть, и CMake может дать вам поддержку для всех видов подходов. Учитывая, что ваш проект может быть на ранних стадиях, вы, вероятно, идете смешанным подходом (не сразу де-сцепление common
библиотека):
CMakeLists.txt
project(toplevel)
cmake_minimum_required(VERSION 3.1)
include(ExternalProject)
ExternalProject_Add(
app1
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/app1"
PREFIX app1
INSTALL_COMMAND ""
)
ExternalProject_Add(
app2
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/app2"
PREFIX app2
INSTALL_COMMAND ""
)
app1 / CMakeLists.txt
project(app1)
cmake_minimum_required(VERSION 3.1)
add_subdirectory(../common common)
add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} common)
это фактически создаст три среды сборки. Один непосредственно в вашем двоичном выходном каталоге и по одному в app1
и app2
суб-каталоги.
и в таких подходах вы можете подумать об общей цепочке инструментов CMake файлы.
ссылки