Вопрос или проблема
У меня есть один исходный пакет верхнего уровня, использующий cmake, и я хотел бы упаковать его как два двоичных пакета Debian.
$ tree proj
proj/
├── app1.c
├── app2.c
└── CMakeLists.txt
Исходный CMakeLists.txt
уже написан с учетом этого. Они используют аргумент COMPONENTS команды install
$ cat proj/CMakeLists.txt
include(GnuInstallDirs)
add_executable(app1 app1.c)
install(
TARGETS app1
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT app1)
add_executable(app2 app2.c)
install(
TARGETS app2
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT app2)
Чтобы собрать/установить локально, это довольно просто:
$ mkdir build && cd build
$ cmake ../proj -DCMAKE_INSTALL_PREFIX=/usr/local # Настройка
$ cmake --build . # Сборка
$ cmake -DCOMPONENT=app1 -P cmake_install.cmake # Установить компонент app1
$ cmake -DCOMPONENT=app2 -P cmake_install.cmake # Установить компонент app2
Но как бы вы создали файл debian/rules
для этого?
Стандартный файл debhelper debain/rules
может выглядеть так (система сборки автоматически распознает cmake на более новых уровнях совместимости).
%:
dh $@ # --buildsystem=cmake <-- более старые уровни совместимости могут нуждаться в этом
Это эффективно запустит make install DESTDIR=debian/tmp
. Но это помещает все в одно место назначения, заставляя вас вручную писать файлы debian/*.install
, чтобы разделить его на части (см. dh_install(1)). Это обычный способ превращения монолитного исходника cmake в несколько двоичных файлов, и есть хорошее руководство по этому вопросу в руководстве Debian здесь.
Однако, верхний уровень уже сделал эту работу, определив установки COMPONENT.
Чтобы воспользоваться этим, переопределите свой собственный рецепт установки, чтобы указать ассоциацию пакета/компонента:
include /usr/share/dpkg/architecture.mk
%:
dh $@
override_dh_auto_install:
sed -i -е 's/\-P/\-DCOMPONENT\=app1\ \-P/g' obj-$(DEB_HOST_MULTIARCH)/Makefile
dh_auto_install --destdir=debian/app1
sed -i -е 's/\-DCOMPONENT\=app1/\-DCOMPONENT\=app2/g' obj-$(DEB_HOST_MULTIARCH)/Makefile
dh_auto_install --destdir=debian/app2
Корень debian/<binary_package_name>
представляет /
в этом двоичном пакете.
Я немного разочарован командами sed
. Я надеялся сделать это, передавая -- -DCOMPONENT=app1
в каталог dh_auto_install. Вместо этого эти команды редактируют файл Makefile, сгенерированный cmake. Это решение предполагает, что вы используете make
, и что единственная строка -P
будет в ваших командах установки (что, похоже, имеет место для проектов, которые я проверял до сих пор). Я рад принять правки к этому ответу с лучшим решением.
Примечание: компания Kitware (разработчик cmake) работает над новым расширением debhelper dh-cmake, которое, по-видимому, упростит это. Однако, на момент выпуска Debian 10 (buster) оно еще недоступно.
Спустя годы я вернулся к этому с лучшим ответом: dh-cmake
сейчас доступен и работает хорошо. Установите пакет Debian dh-cmake
.
В приведенном выше примере я добавил dh-cmake
, dh-cmake-compat (= 1)
и dh-sequence-cmake
в качестве зависимостей для сборки. Этого достаточно, чтобы задействовать dh-cmake
в процессе сборки.
debian/control
:
Source: proj
Maintainer: Stewart <[email protected]>
Build-Depends:
debhelper-compat (= 13),
dh-cmake,
dh-cmake-compat (= 1),
dh-sequence-cmake
Package: proj-app1
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Package: proj-app2
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Далее нам нужно сопоставить компоненты cmake с пакетами. Сделайте это, перечислив каждый компонент в соответствующем <package>.cmake-components
.
debian/proj-app1.cmake-components
:
app1
debian/proj-app2.cmake-components
:
app2
Нет необходимости поддерживать debian/<package>.install
, переопределять что-либо в debian/rules
или изменять CMakeLists.txt
верхнего уровня. debian/rules
может оставаться таким же простым:
#!/usr/bin/make -f
%:
dh $@
Ответ или решение
Вопрос о том, как упаковать CMake компоненты в Debian, является актуальной темой для многих разработчиков, стремящихся оптимизировать свою работу с пакетами. Основной задачей является создание двух бинарных пакетов Debian из одного источника CMake, где в исходниках уже использованы аргументы COMPONENTS для установки.
Предпосылки
Ваша проектная структура и CMakeLists.txt настроены так, чтобы компоненты могли устанавливаться отдельно:
proj/
├── app1.c
├── app2.c
└── CMakeLists.txt
CMakeLists.txt содержит установки, разделенные по компонентам "app1" и "app2":
add_executable(app1 app1.c)
install(
TARGETS app1
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT app1)
add_executable(app2 app2.c)
install(
TARGETS app2
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT app2)
Создание файла debian/rules
Стандартный файл debian/rules для debhelper может выглядеть следующим образом:
%:
dh $@
Тем не менее, для работы с установленными COMPONENTS, потребуется специфический подход для ассоциации компонентов с пакетами. Используйте следующие шаги для этого:
-
Использование dh-cmake: Убедитесь, что у вас установлены
dh-cmake
,dh-cmake-compat (= 1)
иdh-sequence-cmake
. Эти инструменты помогут в процессе создания пакетов. -
Правка debian/control:
Source: proj Maintainer: Ваше Имя <[email protected]> Build-Depends: debhelper-compat (= 13), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake Package: proj-app1 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Package: proj-app2 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}
-
Создание файлов для компонентов: Ассоциируйте компоненты с пакетами, создав соответствующие файлы:
-
debian/proj-app1.cmake-components
содержит:app1
-
debian/proj-app2.cmake-components
содержит:app2
-
Заключение
С внедрением dh-cmake
, процесс разделения компонентов CMake на разные пакеты становится автоматизированным и удобным. Ваша структура debian/rules может оставаться минималистичной, поскольку большая часть механики обрабатывается за вас.
Подход, описанный выше, позволяет эффективно управлять процессом упаковки, сокращая ручную работу и минимизируя вероятность ошибок. Мы рекомендуем регулярно проверять новые возможности и обновления в инструментах упаковки Debian для поддержания вашего процесса на современном уровне.