Приложение A. Углублённое пакетирование

# Приложение A. Углублённое пакетирование

The rewrite of this tutorial document with updated contents and more practical examples is available as Guide for Debian Maintainers. Please use this new tutorial as the primary tutorial document.

Here are some hints and pointers for advanced packaging topics that you are most likely to deal with. You are strongly advised to read all the references suggested here.

Вам может потребоваться вручную отредактировать шаблонные файлы пакета, сгенерированные командой dh_make, чтобы подогнать их под темы, затронутые в этой главе. Новая команда debmake больше подходит к этим темам.

## A.1. Общие библиотеки

Перед пакетированием общих библиотек прочтите следующие основные документы:

- руководство по политике Debian, раздел 8 «Общие библиотеки»

- руководство по политике Debian, раздел 9.1.1 «Структура файловой системы

- руководство по политике Debian, раздел 10.2 «Библиотеки»

Вот упрощённое представление, для начала:

- Общие библиотеки — это объектные файлы в формате ELF, в которых содержится скомпилированный код.

- Общие библиотеки распространяются в виде файлов `*.so` (не в файлах `*.a` или `*.la`).

- Главным образом, общие библиотеки нужны для совместного использования общего кода в исполняемых файлах посредством механизма ld.

- Иногда общие библиотеки используются в качестве подключаемых модулей исполняемых файлов посредством механизма dlopen.

- Shared libraries export symbols, which represent compiled objects such as variables, functions, and classes; and enable access to them from the linked executables.

- SONAME общей библиотеки `lib`foo`.so`.`1`: `objdump -p lib`foo`.so.`1` | grep SONAME` [87]

- SONAME общей библиотеки обычно совпадает с именем файла библиотеки (но не всегда).

- SONAME общих библиотек, которые скомпонованы с ``/usr/bin/foo``: `objdump -p `/usr/bin/foo` | grep NEEDED` [88]

- `lib`foo``1``: библиотечный пакет общей библиотеки `lib`foo`.so.`1`` с ABI-версией SONAME, равной `1`.[89]

- Пакетные сценарии сопровождающего для библиотеки должны вызывать ldconfig для создания необходимых символьных ссылок для SONAME при определённых условиях.[90]

- `lib`foo``1`-dbg`: the debugging symbols package that contains the debugging symbols for the shared library package `lib`foo``1``.

- `lib`foo`-dev`: the development package that contains the header files etc. for the shared library `lib`foo`.so.`1``.[91]

- Debian packages should not contain `*.la` Libtool archive files in general.[92]

- Debian packages should not use RPATH in general.[93]

- Несмотря на некоторое устаревание и статус вторичности, следующая ссылка тоже может быть полезна Debian Library Packaging Guide.

## A.2. Управление `debian/`пакет`.symbols`

When you package a shared library, you should create a `debian/`package`.symbols` file to manage the minimal version associated with each symbol for backward-compatible ABI changes under the same SONAME of the library for the same shared library package name.[94] You should read the following primary references in detail:

- Смотрите руководство по политике Debian, раздел 8.6.3 «Система символов»[95]

- dh_makeshlibs(1)

- dpkg-gensymbols(1)

- dpkg-shlibdeps(1)

- deb-symbols(5)

Here is a rough example of how to create the `libfoo1` package from the upstream version `1.3` with the proper `debian/libfoo1.symbols` file:

- Подготовьте основу исходного дерева из авторского файла `libfoo-1.3.tar.gz`.

  - Если пакетирование `libfoo1` производится впервые, создайте пустой файл `debian/libfoo1.symbols`.

  - Если была упакована предыдущая авторская версия `1.2` в пакет `libfoo1` с соответствующим файлом `debian/libfoo1.symbols` в пакете с исходным кодом, то используйте его и сейчас.

  - If the previous upstream version `1.2` was not packaged with `debian/libfoo1.symbols`, create it as the `symbols` file from all available binary packages of the same shared library package name containing the same SONAME of the library, for example, versions `1.1-1` and `1.2-1`. [96]

        $ dpkg-deb -x libfoo1_1.1-1.deb libfoo1_1.1-1
        $ dpkg-deb -x libfoo1_1.2-1.deb libfoo1_1.2-1
        $ : > symbols
        $ dpkg-gensymbols -v1.1 -plibfoo1 -Plibfoo1_1.1-1 -Osymbols
        $ dpkg-gensymbols -v1.2 -plibfoo1 -Plibfoo1_1.2-1 -Osymbols

- Make trial builds of the source tree with tools such as debuild and pdebuild. (If this fails due to missing symbols etc., there were some backward-incompatible ABI changes that require you to bump the shared library package name to something like `libfoo1a` and you should start over again.)

      $ cd libfoo-1.3
      $ debuild
      ...
      dpkg-gensymbols: warning: some new symbols appeared in the symbols file: ...
       see diff output below
      --- debian/libfoo1.symbols (libfoo1_1.3-1_amd64)
      +++ dpkg-gensymbolsFE5gzx        2012-11-11 02:24:53.609667389 +0900
      @@ -127,6 +127,7 @@
        foo_get_name@Base 1.1
        foo_get_longname@Base 1.2
        foo_get_type@Base 1.1
      + foo_get_longtype@Base 1.3-1
        foo_get_symbol@Base 1.1
        foo_get_rank@Base 1.1
        foo_new@Base 1.1
      ...

- If you see the diff printed by the dpkg-gensymbols as above, extract the proper updated `symbols` file from the generated binary package of the shared library. [97]

      $ cd ..
      $ dpkg-deb -R  libfoo1_1.3_amd64.deb libfoo1-tmp
      $ sed -e 's/1\.3-1/1\.3/' libfoo1-tmp/DEBIAN/symbols \
              >libfoo-1.3/debian/libfoo1.symbols

- Соберите выпускаемые пакеты с помощью таких инструментов как debuild и pdebuild.

      $ cd libfoo-1.3
      $ debuild -- clean
      $ debuild
      ...

В дополнение к вышеупомянутым примерам мы должны проверить дальнейшую совместимость ABI и, если понадобится, увеличить версии некоторых символов вручную. [98]

Несмотря на статус вторичности, вики Debian UsingSymbolsFiles и содержащиеся на ней ссылки могут быть полезными.

## A.3. Мультиархитектурность

Свойство мультиархитектурности, появившееся в Debian wheezy, встраивает поддержку кросс-платформенной установки двоичных пакетов (а именно `i386`<->`amd64`, но есть и другие комбинации) в `dpkg` и `apt`. Подробная информация приведена в следующих документах:

- вики Ubuntu MultiarchSpec (авторский документ)

- вики Debian Multiarch/Implementation (ситуация в Debian)

При установке общих библиотек в путях используются триплеты, например `i386-linux-gnu` и `x86_64-linux-gnu`. Актуальный триплет динамически задаётся в переменной `$(DEB_HOST_MULTIARCH)` с помощью dpkg-architecture(1) при каждой сборке. Например, путь установки мультиархитектурных библиотек изменяется следующим образом:[99]

Старый путь | мультиархитектурный путь для i386 | мультиархитектурный путь для amd64
--- | --- | ---
`/lib/` | `/lib/i386-linux-gnu/` | `/lib/x86_64-linux-gnu/`
`/usr/lib/` | `/usr/lib/i386-linux-gnu/` | `/usr/lib/x86_64-linux-gnu/`

Here are some typical multiarch package split scenario examples for the following:

- библиотека с исходным кодом `lib`foo`-1.tar.gz`

- инструмент с исходным кодом ``bar`-1.tar.gz`, написанный на компилируемом языке

- инструмент с исходным кодом ``baz`-1.tar.gz`, написанный на интерпретируемом языке

Пакет | Архитектура: | Мультиархитектурность: | Содержимое пакета
--- | --- | --- | ---
`lib`foo``1`` | любая | такая же | общая библиотека, одновременная установка
`lib`foo``1`-dbg` | любая | такая же | отладочные символы общей библиотеки, одновременная установка
`lib`foo`-dev` | любая | такая же | заголовочные файлы общей библиотеки, одновременная установка
`lib`foo`-tools` | любая | сторонняя | программы поддержки времени выполнения, не одновременная установка
`lib`foo`-doc` | все | сторонняя | файлы документации общей библиотеки
``bar`` | любая | сторонняя | скомпилированные файлы программы, одновременная установка
``bar`-doc` | все | сторонняя | файлы документации программы
``baz`` | все | сторонняя | интерпретируемые файлы программы

Заметим, что пакет для разработчика должен содержать символьную ссылку на соответствующую общую библиотеку без номера версии. Пример: `/usr/lib/x86_64-linux-gnu/libfoo.so` -> `libfoo.so.1`

## A.4. Сборка пакета с общей библиотекой

You can build a Debian library package enabling multiarch support using dh(1) as follows:

- Обновите `debian/control`.

  - Add `Build-Depends: debhelper (>=10)` for the source package section.

  - Добавьте `Pre-Depends: ${misc:Pre-Depends}` для каждого двоичного пакета с общей библиотекой.

  - Добавьте строку `Multi-Arch:` в раздел каждого двоичного пакета.

- Set `debian/compat` to "10".

- Измените путь с обычного `/usr/lib/` на мультиархитектурный `/usr/lib/$(DEB_HOST_MULTIARCH)/` во всех сценариях пакета.

  - Call `DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)` in `debian/rules` to set the `DEB_HOST_MULTIARCH` variable first.

  - Замените `/usr/lib/` на `/usr/lib/$(DEB_HOST_MULTIARCH)/` в `debian/rules`.

  - If `./configure` is used in part of the `override_dh_auto_configure` target in `debian/rules`, make sure to replace it with `dh_auto_configure --` . [100]

  - Замените все появления `/usr/lib/` на `/usr/lib/*/` в файлах `debian/`foo`.install`.

  - Generate files like `debian/`foo`.links` from `debian/`foo`.links.in` dynamically by adding a script to the `override_dh_auto_configure` target in `debian/rules`.

        override_dh_auto_configure:
                dh_auto_configure
                sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
                        debian/foo.links.in > debian/foo.links

Проверьте, что пакет с общей библиотекой содержит только ожидаемые файлы и что ваши пакеты -dev ещё работают.

All files installed simultaneously as the multiarch package to the same file path should have exactly the same file content. You must be careful of differences generated by the data byte order and by the compression algorithm.

## A.5. Родной пакет Debian

Если пакет сопровождается только для Debian или, возможно, предназначен только для локального использования, то файлы `debian/*` можно хранить прямо его в исходном коде. Есть два способа его пакетирования.

You can make the upstream tarball by excluding the `debian/*` files and package it as a non-native Debian package as in Раздел 2.1, «Порядок сборки пакета Debian». This is the normal way, which some people encourage using.

Альтернативный способ сборки родного пакета Debian:

- создание родного пакета Debian с исходным кодом в формате `3.0 (native)`, состоящем из одного сжатого файла tar, в который включены все файлы

  - ``пакет`_`версия`.tar.gz`
  - ``пакет`_`версия`.dsc`

- сборка двоичных пакетов Debian из родного пакета Debian с исходным кодом

  - ``пакет`_`версия`_`архитектура`.deb`

For example, if you have source files in `~/mypackage-1.0` without the `debian/*` files, you can create a native Debian package by issuing the dh_make command as follows:

    $ cd ~/mypackage-1.0
    $ dh_make --native

Then the `debian` directory and its contents are created just like in Раздел 2.8, «Начальный неродной пакет Debian». This does not create a tarball, since this is a native Debian package. But that is the only difference. The rest of the packaging activities are practically the same.

После выполнения команды dpkg-buildpackage, вы увидите следующие файлы в родительском каталоге:

- `mypackage_1.0.tar.gz`

  Это сжатый архив tar с исходным кодом, созданный из каталога `mypackage-1.0` командой dpkg-source (его суффикс не `orig.tar.gz`).

- `mypackage_1.0.dsc`

  This is a summary of the contents of the source code, as in the non-native Debian package. (There is no Debian revision.)

- `mypackage_1.0_i386.deb`

  This is your completed binary package, as in the non-native Debian package. (There is no Debian revision.)

- `mypackage_1.0_i386.changes`

  Содержит описание всех изменений, сделанных в текущей версии пакета, такой же как для неродного пакета Debian (в имени нет редакции Debian).

[87] Либо: `readelf -d lib`foo`.so.`1` | grep SONAME`

[88] Либо: `readelf -d lib`foo`.so.`1` | grep NEEDED`

[89] Смотрите руководство по политике Debian, раздел 8.1 «Общие библиотеки времени выполнения».

[90] Смотрите руководство по политике Debian, раздел 8.1.1 «ldconfig».

[91] Смотрите руководство по политике Debian, раздел 8.3 «Статические библиотеки» и руководство по политике Debian, раздел 8.4 «Файлы для разработки».

[92] Смотрите Debian wiki ReleaseGoals/LAFileRemoval.

[93] Смотрите вики Debian RpathIssue.

[94] При обратно несовместимых изменениях ABI обычно требуется обновить SONAME библиотеки и поменять имя пакета общей библиотеки на новое.

[95] Вместо указанного для библиотек C++ и в других случаях, где слежение за отдельными символами слишком сложно, прочтите руководство по политике Debian, раздел 8.6.4 «Система shlibs».

[96] Все предыдущие версии пакетов Debian доступны по http://snapshot.debian.org/. Для облегчения переноса пакета в старые выпуски часть, отвечающая за версию Debian, отбрасывается: `1.1` << `1.1-1~bpo70+1` << `1.1-1` и `1.2` << `1.2-1~bpo70+1` << `1.2-1`

[97] Для облегчения переноса пакета в старые выпуски часть, отвечающая за версию Debian, отбрасывается: `1.3` << `1.3-1~bpo70+1` << `1.3-1`

[98] Смотрите руководство по политике Debian, раздел 8.6.2 «Изменения ABI общей библиотеки».

[99] Old special purpose library paths such as `/lib32/` and `/lib64/` are not used anymore.

[100] Или же вы можете добавить параметры `--libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)` и `--libexecdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)` в `./configure`. Заметим, что в `--libexecdir` задаётся путь по умолчанию для установки исполняемых программ, запускаемых другими программами, а не пользователями. Значение Autotools по умолчанию равно `/usr/libexec/`, но значение Debian по умолчанию равно `/usr/lib/`.

Глава 9. Отправка пакета |  |