Ubuntu logo

Packaging Guide

8. Спільні бібліотеки

Спільні бібліотеки — це скомпільований код, призначений для спільного використання декількома різними проґрамами. Вони розповсюджуються у вигляді файлів .so в /usr/lib/.

Бібліотеки експортують символи у скомпільованому вигляді: функції, кляси та змінні. В кожної бібліотеки також є назва SONAME, що включає номер її версії, але який не обов’язково збігається з офіційним номером релізу. Проґрами компілюються з конкретним SONAME бібліотеки. Так, якщо якийсь з символів бібліотеки був вилучений або змінений – небхідно змінити версію з тим, щоб усі залежні від бібліотеки пакунки були перекомпільовані з використанням нової версії. Зазвичай версії встановлюються у джерелі, й ми використовуємо ті ж номери версій для двійкових пакунків, що називаються “номер ABI”, але у випадку, якщо джерело не використовує притомної версійності, творці пакунків можуть використовувати окрему, традиційнішу нумерацію.

Бібліотеки зазвичай розповсюджуються апстрімом у вигляді окремих випусків. Інколи вони розповсюджуються, як частина проґрами. У останньому випадку вони можуть бути включені у двійковий пакунок разом з проґрамою (це зветься bundling), якщо Ви не припускаєте використання цих бібліотек іншими проґрамами, але частіше їх усе ж слід виділяти у окремі двійкові пакунки.

Самі бібліотеки поміщаються у двійковий пакунок з іменем libfoo1, де foo — ім’я бібліотеки, а 1 — версія з SONAME. Файли розробки з пакунку, такі як заголовкові файли, необхідні для компілювання проґрам з бібліотекою, поміщаються у пакунок з іменем libfoo-dev.

8.1. Приклад

У якості прикладу ми використовуємо libnova:

$ bzr branch ubuntu:trusty/libnova
$ sudo apt-get install libnova-dev

Щоб знайти SONAME бібліотеки, виконайте:

$ readelf -a /usr/lib/libnova-0.12.so.2 | grep SONAME

SONAME у даному випадку libnova-0.12.so.2, що відповідає імені файлу (як правило, але не завжди). Тут апстрім помістив номер версії з апстріму, як частину SONAME, й задав ABI-версію 2. Імена бібліотекових пакунків повинні слідувати SONAME бібліотеки, яку вони містять. Двійковий бібліотековий пакунок зветься libnova-0.12-2, де libnova-0.12 — ім’я бібліотеки, а 2 — наш ABI-номер.

Якщо автори з апстріму внесли несумісні зміни у свою бібліотеку, вони повинні змінити номер версії SONAME, а ми повинні перейменувати нашу бібліотеку. Будь-які інші пакунки, що використовують наш бібліотековий пакунок, потрібно буде перекомпілювати з новою версією, це зветься переходом (transition) й потребує певних зусиль. Потрібно сподіватися, наш ABI-номер продовжить відповідати SONAME апстріму, але інколи вони вносять несумісності без зміни їх номеру версії, а нам потрібно змінити наш.

Поглянувши на debian/libnova-0.12-2.instal, ми побачимо, що він включає у себе два файли:

usr/lib/libnova-0.12.so.2
usr/lib/libnova-0.12.so.2.0.0

Другий рядок — справжня бібліотека, з повним номером версії. Перше — символьне посилання, що вказує на справжню бібліотеку. Проґрами, що використовують бібліотеку, как правило, будуть користуватися символічним посиланням.

libnova-dev.install містить усі файли, необхідні для компілювання проґрами з даною бібліотекою. Заголовкові файли, бінарник конфігурації, файл libtool’a .la, а також libnova.so – ще один симлінк на бібліотеку, створюваний з тим, щоб проґрами могли компілюватися поза залежністю від старшого номеру версії (при цьому, скомпільваний застосунок все одно буде залежати від версії).

.la-файли libtool’у потрібні на деяких не-Linux системах з обмеженою підтримкою бібліотек, але на системах Debian часто створюють більше проблем, ніж вирішують. Мета Debian відмовитися від .la-файлів сьогодні вельми актуальна, й Ви можете допомогти з вирішенням цього завдання.

8.2. Статичні бібліотеки

Пакунок -dev також містить usr/lib/libnova.a. Це статична бібліотека, альтернатива спільній бібліотеці. Будь-яка проґрама, скомпільована зі статичною бібліотекою, містить її код безпосередньо у собі. Це дозволяє не бентежитися про двійкову сумісність бібліотеки. Втім це також значить, що будь-які помилки, у тому числі вразливості у безпеці, не будуть виправлені за рахунок оновлення бібліотеки, поки проґрама не буде перекомпільована. З цієї причини використовувати проґрами з статичними бібліотеками не радимо.

8.3. Символьні файли

Коли додаток компілюється з бібліотекою, механізм shlibs додасть до пакунку залежність від цієї бібліотеки. Саме тому більшість проґрам містять Depends: ${shlibs:Depends} у файлі debian/control. Це замінюється переліком залежних бібліотек при білді. Втім shlibs може лише вказувати залежність від старшої ABI-версії , 2 у нашому прикладі з libnova, тож якщо нові символи будуть додані у майбутній libnova 2.1 – застосунок буде запускатися й зі старішою версією libnova ABI 2.0, що призведе до аварійного завершення.

Щоб точніше вказувати залежності від бібліотек, ми створили файл .symbols, який перераховує усі символи бібліотеки й версії, у яких вони з’явилися.

libnova не має символьного файлу, тож ми можемо створити його. Почніть з компілювання пакунку:

$ bzr builddeb -- -nc

Опція -nc вказує не вилучати збірочні файли після завершення компілювання. Перейдіть у каталог збірки й виконайте dpkg-gensymbols для пакунку бібліотеки:

$ cd ../build-area/libnova-0.12.2/
$ dpkg-gensymbols -plibnova-0.12-2 > symbols.diff

Це створить diff-файл, який Ви зможете застосувати самостійно:

$ patch -p0 < symbols.diff

Це створить файл з іменем вигляду dpkg-gensymbolsnY_WWI, у якому будуть перераховані усі символи. Він також вказує поточну версію пакунку. Версію пакунку можна прибрати з файлу, оскільки нові символи зазвичай додаються не з новою версією пакунку, а розробниками початкової бібліотеки.

$ sed -i s,-0ubuntu2,, dpkg-gensymbolsnY_WWI

Тепер перемістіть файл туди, де він має знаходитися, зафіксуйте зміни та виконайте тестову збірку:

$ mv dpkg-gensymbolsnY_WWI ../../libnova/debian/libnova-0.12-2.symbols
$ cd ../../libnova
$ bzr add debian/libnova-0.12-2.symbols
$ bzr commit -m "add symbols file"
$ bzr builddeb

Якщо компілювання виконується успішно, значить символьний файл не містить вад. З виходом наступної апстрім-версії libnova Вам доведеться знову запустити dpkg-gensymbols, щоб створити diff для оновлення символьного файлу.

8.4. Символьні файли бібліотек C++

В мови C++ більш суворі стандарти на двійкову сумісність, ніж у C. Команда Debian Qt/KDE підтримує деякі скрипти, які допоможуть подолати це: сторінка Робота з файлами symbols дає опис принципів їх використання.

8.5. Матеріяли для подальшого читання

Стаття Junichi Uekawa Пакункування бібліотек для Debian розглядає це питання детальніше.