CMake: как лучше всего построить несколько (необязательных) подпроектов?

представьте себе общий проект с несколькими компонентами:

  • basic
  • io
  • web
  • app-a
  • app-b
  • app-c

теперь, скажем, web зависит от io, который зависит от basic, и все эти вещи находятся в одном РЕПО и имеют CMakeLists.txt для создания их как общих библиотек.

как мне настроить, чтобы я мог создавать три приложения, если каждое из них является необязательным и может не присутствовать во время сборки?

одна идея состоит в том, чтобы иметь пустой каталог "apps" в главном РЕПО, и мы можем клонировать любые репозитории приложений, которые мы хотим в это. Наши основные CMakeLists.txt файл может использовать GLOB, чтобы найти все каталоги приложений и построить их (не зная заранее, сколько их будет). Проблемы с этим подходом включают в себя:

  • по-видимому, CMake не re-glob, когда вы просто говорите make, поэтому, если вы добавляете новое приложение, вы должны запустить cmake снова.
  • он накладывает определенную структуру на человека, выполняющего сборку.
  • не очевидно, как можно сделать два клона одного приложения и построить их отдельно против одной сборки библиотеки.

общая концепция похожа на традиционный рекурсивный проект CMake, но где модули более низкого уровня не обязательно заранее знают, какие модули более высокого уровня будут их использовать. Тем не менее, я не хочу требовать от пользователя установки нижнего уровня библиотеки в фиксированном месте (например,/usr/local/lib). Однако я хочу, чтобы один вызов make чтобы заметить измененные зависимости по всему проекту, так что если я создаю приложение, но изменил одну из библиотек низкого уровня, все будет перекомпилироваться соответствующим образом.

6 ответов


моей первой мыслью было использовать CMake импорт/экспорт элемент характеристика.

есть CMakeLists.txt для basic, io и web и один CMakeLists.txt, который ссылается на эти. Затем вы можете использовать CMake экспорт функция для экспорта этих целей и проектов приложений может тогда импорт цели CMake.

при создании проекта библиотеки сначала проекты приложений должны быть в состоянии найти скомпилированные библиотеки автоматически (без необходимости установки библиотек в /usr/local/lib) в противном случае всегда можно настроить правильную переменную CMake для указания правильного каталога.

делая это таким образом make в проекте приложения не сделать make в проект библиотеки, вам придется позаботиться об этом самостоятельно.


есть несколько CMakeLists.формат txt.

многие проекты с открытым исходным кодом принимают эту оценку (LibOpenJPEG, LibPNG, poppler и т. д.). Взгляните на их CMakeLists.txt, чтобы узнать, как они это сделали.

в основном позволяет просто переключать функции по мере необходимости.


Я вижу два дополнительных подхода. Один из них-просто иметь базовые, io и web-подмодули каждого приложения. Да, существует дублирование кода и потерянное дисковое пространство, но это очень просто реализовать и гарантирует, что различные настройки компилятора для каждого приложения не будут мешать друг другу в общих библиотеках. Я полагаю, что это заставляет библиотеки больше не делиться, но, возможно, это не должно быть большой проблемой в 2011 году. ОЗУ и диск стали дешевле, но инженерное время имеет нет, и разделение источников, пожалуй, более компактен, чем делить двоичные файлы.

другой подход состоит в том, чтобы иметь макет, указанный в вопросе, и иметь CMakeLists.txt-файлы в каждом подкаталоге. В CMakeLists.txt-файлы в basic, io и web генерируют автономные общие библиотеки. В CMakeLists.txt-файлы в каждом каталоге приложений извлекают в каждой общей библиотеке с помощью команды add_subdirectory (). Затем вы можете удалить все каталоги библиотек и любое приложение(ы), которое вы хотели и инициировать сборку из каждого каталога приложений.


Я закончил тем, что я изложил в своем вопросе, который должен проверить в пустом каталоге (содержащем a .файл gitignore, который игнорирует все) и скажите CMake GLOB любые каталоги (которые помещаются туда пользователем). Тогда я могу просто сказать cmake myrootdir, и он находит все различные компоненты. Это работает более или менее нормально. У этого есть некоторые побочные недостатки, такие как то, что некоторые сторонние инструменты, такие как BuildBot, ожидают более традиционной структуры проекта, которая делает интеграция других инструментов с такого рода расположением немного больше работы.


можно использовать ADD_SUBDIRECTORY для этого!

https://cmake.org/cmake/help/v3.11/command/add_subdirectory.html


на CMake BASIS инструмент предоставляет утилиты, где вы можете создавать независимые модули проекта и выборочно включать и отключать их с помощью команды ccmake.

полное раскрытие информации: я разработчик проекта.