Библиотека общего доступа 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.


когда вы настраиваете свою среду сборки, вы должны подумать о следующих трех темах (помимо других, но для этого обсуждения / ответа я сократил его до трех, которые, как я чувствую, актуальны здесь):

  1. Dependecies / Соединение
  2. развертывание
  3. команды

"Сильной Связью"

я подумал о 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 файлы.

ссылки