Набор CMake утилит для обеспечения работы с зависимостями проекта.
- CMake >= 3.10
- git
- python3 (опционально для git hooks)
- Скопировать и подключить файл bastard_setup.cmake:
cmake_minimum_required(VERSION 3.10)
include(cmake/bastard_setup.cmake)
bastard_setup()
project(${BASTARD_PACKAGE_NAME})
- Запустить cmake
cd build && cmake ..
Начнется инициализация проекта. Пакетный менеджер будет выгружен в каталог .deps как обычная зависимость. Далее по описанию из bastard.toml будут выгружены зависимости пакета и сгенерированы цели для сборки.
Инициализация проекта начинается после вызова функции bastard_setup(), поэтому любые глобальные специфические опции (например CMAKE_POSITION_INDEPENDENT_CODE) должны назначаться выше.
-
[package]
name: str
Имя пакета (уникально в рамках сборки)authors: list[str]
Список авторовautogen-defines: bool
Автогенерация defines из опций (с префиксом)version: str
Версия пакетаlang: str
Язык по-умолчанию для всех целей пакетаc90|c99|c++98|c++11|c++14|c++17|c++20
system: [str]
Общая спецификация платформы (обычно Unix | Windows | Generic)processor: [str]
Общая спецификация процессора (экв. CMAKE_SYSTEM_PROCESSOR)
-
[dependencies] Базовые зависимости
<package>: str
Имя зависимой библиотекиgit: str
Ссылка на репозиторийtag: str
Конкретный тегbranch: str
Конкретная веткаrev: str
Конкретный хэш коммитаlinks: list[str]
Указание нескольких библиотек для линковкиpath: str
Путь к локальной зависимости проектаinterface: str
Путь к директории с исходниками для генерации целиsystem: [str]
Спецификация платформы для зависимостиprocessor: [str]
Спецификация процессора для зависимости
-
[dev-dependencies] Зависимости для разработки
- Аналогично секции
[dependencies]
- Аналогично секции
-
[sys-dependencies] Системные зависимости
<package>: str
Имя системного пакета (например Thread, Boost)components: list[str]
Список компонентов для find_package()links: list[str]
Список библиотек для линковки
-
[lib] Описание цели библиотеки
name: str
Имя цели библиотекиlang: str
Используемый язык (см. package.lang)type: str
Тип библиотекиstatic|shared|interface
include: [str]
Маска для включения файлов относительно каталога libexclude: [str]
Маска для исключения файлов относительно каталога lib
-
[[bin]] Описание цели/целей бинарника
name: str
Имя цели (или путь к каталогу по-умолчанию, если не определен path)path: str
Путь к файлу/директории для сборкиlang: str
Используемый язык (см. package.lang)include: [str]
Маска для включения файлов относительно каталога libexclude: [str]
Маска для исключения файлов относительно каталога libinclude
иexclude
относительноbin/name
либоbin
директорииconsole: bool
Является ли приложение консольным (по-умолчанию true)
-
[[test]] Описание цели/целей бинарника для тестирования
- Аналогично [bin]
-
[[example]] Описание цели/целей бинарника для примеров
- Аналогично [bin]
-
[options] Описание cmake переменных для целей
<package> = { <name>=<value> }
-
[defines.<public|private>] Описание defines для целей
<package> = { <name>=<value> }
По-умолчанию если секции [lib]
[[bin]]
не указаны, то принимается legacy соглашение, когда все зависимости должны подключаются вручную в CMakeLists.txt. Для legacy режима возможно использовать любую структуру проекта, однако функциональность bastard ограничивается только выгрузкой зависимостей и настройкой опций. Если следовать соглашению по структуре проекта, то конфигурирование пакета будет происходить автоматически.
Под конфигурированием в данном случае понимается:
- Генерация lib цели
- Генерация bin целей
- Линковка lib ко всем bin
- Настройка доступа к заголовочным файлам
- Подключение и линковка системных пакетов
- Генерация и настройка тестов из папки tests
- Генерация файла версии version.h
- [future] Генерация и настройка примеров из папки examples
- [future] Генерация и настройка бенчмарков из папки benchs
Структура пакета с библиотекой:
-- cmake
-- include/
---- mylib/
------ mylib.h
-- lib/
---- mylib.cpp
-- bastard.toml
-- CMakeLists.txt
Структура пакета с бинарниками:
-- cmake
-- bin
---- app1/
------ main.cpp
---- app2/
------ main.cpp
-- bastard.toml
-- CMakeLists.txt
Структура пакета с библиотекой и бинарниками:
-- cmake
-- bin
---- app1/
------ main.cpp
---- app2/
------ main.cpp
-- include/
---- mylib/
------ mylib.h
-- lib/
---- mylib.cpp
-- bastard.toml
-- CMakeLists.txt
Также допускается не использовать подкаталоги вида <include/package_name>
и <bin/app_name>
(а только include и bin). Это бывает удобно при сборке плагинов или одиночных приложений.
Все бинарники автоматически линкуются с единственной библиотекой пакета (как это сделано в cargo). Иметь в пакете более одной библиотеки можно только через добавление локальной зависимости (опять же, которая будет линковаться к главной библиотеке)
Зависимости только с заголовочными файлами можно подключать через атрибут interface = "/path/include"
. В таком случае будет создана цель интерфейсной библиотеки. Использование атрибута допустимо только для git зависимостей.
По умолчанию в качестве исходников подгружаются все файлы (по маске) из каталогов lib, bin, bin/name, include, include/name:
lib/*.cpp, lib/*.hpp, lib/*.c, lib/*.h, lib/*.ui, lib/*.qrc
bin/*.cpp, bin/*.hpp, bin/*.c, bin/*.h, bin/*.ui, bin/*.qrc
include/*.hpp, include/*.h
Для детальной настройки целей [[bin]]
и [lib]
можно использовать опции include
и exclude
. Разрешение имен для файлов происходит относительно целевых каталогов целей. Для цели [lib]
нельзя настроить фильтрацию каталога include
.
Для разделения функционала под разные платформы можно пользоваться описанием локальных зависимостей и системы:
[dependencies.boost_timer]
path = "specific/boost_timer"
system = ["Unix", "Windows"]
processor = "x86_64"
[dependencies.soft_timer]
path = "specific/soft_timer"
system = "Generic"
processor = ["TMS320C6414", "TMS320C5509A"]
В данном случае все файлы из каталога specific/boost_timer
будут добавлены к сборке базовой цели для платформ Windows или Unix (процессоры x86_64). Для случая Generic платформы (процессоры TMS320C6414 или TMS320C5509A) используются файлы specific/soft_timer
- Значения из
system
аналогичны проверке cmake флагов WIN32 и UNIX (для Windows и Unix соотв.), прочие значения проверяются на соответствие CMAKE_SYSTEM_NAME - Значения из
processor
полностью соответствуют CMAKE_SYSTEM_PROCESSOR из тулчейна
ВАЖНО: Нужно быть осторожным, при описании пересекающихся целей (модули с общими интерфейсами)
При указании версии пакета (в секции package) будет автоматически сгенерирован файл ${build_path}/include/${package_name}/version.h
:
#ifndef __MYPACKAGE_VERSION_GUARD__
#define __MYPACKAGE_VERSION_GUARD__
#define MYPACKAGE_VERSION "1.2.3"
#define MYPACKAGE_VERSION_MAJOR (1)
#define MYPACKAGE_VERSION_MINOR (2)
#define MYPACKAGE_VERSION_PATCH (3)
#define MYPACKAGE_GIT_COMMIT "23498f"
#endif
Подключить файл к проекту (публичная область видимости):
#include <package_name/version.h>
При конфигурировании менеджер автоматически размещает в каталоге .git/hooks/
скрипты вспомогательных хуков (но только при условии отсутствия пользовательских).
При изменении version в toml файле генерируется post-commit хук, который автоматически добавит тег вида "vX.X.X" при каждом коммите. Поэтому важно периодически использовать команду git push --tags
для обновления тегов на сервере.
При наличии в корне проекта файла правил .clang-format
, перед каждым коммитом будет вызван pre-commit хук. Для каждого staged файла с расширениями cpp, hpp, h, c, cxx, hxx
вызывается clang-format и результат сравнивается с исходным. Если код не форматирован - коммит сделать нельзя. Чтобы обойти это ограничение - можно использовать файл .clang-format-ignore
по аналогии с .gitignore
.
ВАЖНО: правила и файлы берутся из staged состояния, локальные правки не влияют на результат.
- При первом запуске cmake зависимости обновляются автоматически
- Без доступа к сети можно разместить зависимости в каталог .deps вручную
- Версии при генерации lock файла берутся из .deps зависимостей
- Для обновления зависимостей необходимо удалить пакет из .deps, удалить .lock и перезапустить cmake (в клиенте для этого будет отдельная функция)
- Имеет смысл добавлять bastard.lock под версионирование
- Описывайте в секции [dev-dependencies] зависимости для разработки
- Для пакетов библиотек лучше использовать конкретные версии зависимостей (tag)
- После выгрузки все зависимости используются как локальные (каталог .deps)
- Для сборки без доступа к репозиториям (на другой системе) удалите старый build
- Многострочные атрибуты для toml временно не поодеживаются (пишите в одну строку)
- SVN не поддерживается (и никогда не будет)
- В любой непонятной ситуации удаляй build/.deps/bastard.lock