Создание deb-пакета для самых маленьких. Из простого проекта с разделяемыми библиотеками

от автора

На просторах интернета уже имеются всевозможные туториалы, описывающие пошагово процесс создания deb-пакета. Однако у меня возникла потребность собрать пакет из проекта с разделяемыми библиотеками, и я решил поделиться тут своим опытом

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

Описание проекта, для которого будет создаваться deb-пакет

Назовем проект poop. Он будет имитировать авторизацию в каком-нибудь сервисе, а именно проверять наличие паролей для двух пользователей и не совпадают ли они.

Начальная структура проекта

-> /poop |-> Makefile |-> /src |-> input_check.h |-> input_check.c |-> login.c |-> login.h |-> input_check.c

Исходники

input_check.h

#ifndef INPUT_CHECK_H #define INPUT_CHECK_H    int check_input(int argc);  #endif

input_check.c

#include <stdio.h>    int check_input(int argc) { int ret = argc; switch (ret) { case 1: printf("[%s] The poop app. "    "Tap TAB to make app dumb\npoop [random string]\n",    __FUNCTION__); ret = 0; break; case 2: break; default: printf("[%s] WTF?!\npoop [random string]\n", __FUNCTION__); ret = -1; break; } return ret; }

login.h

#ifndef LOGIN_H #define LOGIN_H    int check_login(const char* login_to_check);    #endif

login.c

#include <stdio.h> #include <string.h>    #define TYPE_1 "user_1" #define TYPE_2 "user_2"  int check_login(const char* login_to_check) { int ret = 0; if(login_to_check != NULL) { if ((strcmp(login_to_check, TYPE_1) == 0) ||  (strcmp(login_to_check, TYPE_2) == 0)) { printf("%s\n", login_to_check); } else { printf("[%s]: Логин не определен\n",  __FUNCTION__); ret = -2; } } else { printf("[%s] Пусто!\n",  __FUNCTION__); ret = -3; } return ret; }

main.c

#include <stdio.h> #include "input_check.h" #include "login.h"  int main(int argc, char **argv) { int ret = check_input(argc); if (0 < ret) ret = check_login(argv[1]); return ret; }

Makefile

# target to create first shared library libpoopl0gin.so: src/login.c gcc src/login.c -o libpoopl0gin.so -shared -fPIC    # target to create second shared library libpoopinputch3ck.so: src/input_check.c gcc src/input_check.c -o libpoopinputch3ck.so -shared -fPIC    main.o: src/main.c gcc -c src/main.c    all: libpoopl0gin.so libpoopinputch3ck.so main.o gcc main.o -I/src libpoopl0gin.so libpoopinputch3ck.so -o poop.out    clean: rm -rf *.so rm -rf *.o*

Сборка производится командой make all

Подготовка проекта и сборка пакета

Разделим всю работу по созданию пакета на несколько этапов:

0. Обзор зависимостей;
1. Создание манифеста;
2. Перемещение файлов;
3. Создание скрипта установки;
4. Сборка и проверка пакета.

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

sudo apt install dpkg-dev devscripts equivs

А вот теперь уже приступим

Когда понял, что предстоит читать этот лонгрид

Когда понял, что предстоит читать этот лонгрид

0. Обзор зависимостей

Наши собранные библиотеки имеют собственные зависимости, поэтому их нужно посмотреть. Делается это командой objdump:

~/poop$ objdump -p ./libpoopl0gin.so | grep NEEDED   NEEDED               libc.so.6 ~/poop$ objdump -p ./libpoopinputch3ck.so | grep NEEDED   NEEDED               libc.so.6  # В нашем случае программе необходима только libc.  # Смотрим, в каком пакете она находится: ~/poop$ dpkg -S libc.so.6 libc6:amd64: /lib/x86_64-linux-gnu/libc.so.6

1. Создание манифеста

Создаем папку:

~/poop$ mkdir -p package/DEBIAN

Затем файл манифеста

~/poop$ vi package/DEBIAN/control

И наполняем следующим содержимым:

Package: poop Version: 1.0 Section: uncrown Priority: optional Depends: libc6 Architecture: amd64 Essential: no Installed-Size: 16 # значение из результата команды du -k ./poop.out Maintainer: doob.poop <peep@doob.poop> Description: Check random login from random user

Это минимальный набор параметров в файле манифеста. Вот их значение:

  • Package — имя пакета;

  • Version — версия программы в пакете, будет использована при обновлении пакета;

  • Section — категория пакета, позволяет определить зачем он нужен;

  • Priority — важность пакета, для новых пакетов, которые ни с чем не конфликтуют обычно прописывают optional, кроме того доступны значения required, important или standard;

  • Depends — от каких пакетов зависит ваш пакет, он не может быть установлен, пока не установлены эти пакеты;

  • Recommends — необязательные пакеты, но тем не менее они обычно устанавливаются по умолчанию в apt;

  • Conflicts — пакет не будет установлен, пока в системе присутствуют перечисленные здесь пакеты;

  • Architecture — архитектура системы, в которой можно установить этот пакет, доступные значения: i386, amd64, all, последнее означает, что архитектура не имеет значения;

  • Installed-Size — общий размер программы после установки;

  • Maintainer — указывает кто собрал этот пакет и кто отвечает за его поддержку;

  • Description — краткое описание пакета.

2. Перемещение файлов

Создаем папку usr/bin и поместить туда исполняемый файл программы:

~/poop$ mkdir -p package/usr/bin ~/poop$ cp ./poop.out package/usr/bin

Создаем папку usr/lib для наших разделяемых библиотек

~/poop$ mkdir -p package/usr/lib ~/poop$ cp ./libpoop* package/usr/lib

3. Создание скрипта установки

Несмотря на то, что система установки пакетов очень мощная и позволяет делать многое, некоторые вещи всё же сделать нельзя. Для решения этой проблемы была предусмотрена возможность выполнять скрипты перед установкой пакета и после. Аналогично это работает для удаления пакета — перед и после. Эти скрипты называются preinst, postinst, prerm и postrm. Каждый файл просто содержит набор скриптов, которые надо выполнить. Например:

~/poop$ vi package/DEBIAN/postinst  #!/bin/bash echo "Hello from poop installed"

Разработчики Debian не рекомендуют использовать эти скрипты без крайней надобности, поскольку они дают вам полный контроль над системой пользователя и вы можете случайно что-то повредить. Обычно эти скрипты используются для того чтобы задавать пользователям вопросы и на основе этого генерировать конфигурационные файлы.

4. Сборка и проверка пакета

Осталось собрать настроенный пакет:

~/poop$ dpkg-deb --build ./package

После завершения сборки устанавливаем его с помощью apt:

~/poop$ sudo apt install ~/package.deb Reading package lists... Done Building dependency tree... Done Reading state information... Done Note, selecting 'poop' instead of './package.deb' The following NEW packages will be installed:   poop 0 upgraded, 1 newly installed, 0 to remove and 8 not upgraded. Need to get 0 B/4 454 B of archives. After this operation, 16,4 kB of additional disk space will be used. Get:1 /home/user/Projects/poop/package.deb poop amd64 1.0 [4 454 B] Selecting previously unselected package poop. (Reading database ... 281406 files and directories currently installed.) Preparing to unpack .../user/Projects/poop/package.deb ... Unpacking poop (1.0) ... Setting up poop (1.0) ... Hello from poop installed

Теперь проект можно запустить:

~/poop$ poop.out user [check_login]: Логин не определен

Конечная структура проекта

-> /poop |-> Makefile |-> /src |-> input_check.h |-> input_check.c |-> login.c |-> login.h |-> input_check.c |-> /package |-> /DEBIAN |-> /usr |-> /bin |-> poop.out |-> /lib |-> libpoopinputch3ck.so |-> libpoopl0gin.so

Как видно из структуры выше, добавилась папка package, в которой находятся все поддиректории и файлы, необходимые для успешной сборки deb-пакета простенького проекта

Для простоты проверки всего вышего сказанного, можно клонировать с Github уже готовый настроенный проект.

Так выглядит deb-пакет по мнению Kandinsky

Так выглядит deb-пакет по мнению Kandinsky

Буду рад ответить на вопросы и предложения.

Полезные ссылки и материалы по теме:

Создание deb пакетов

Описание процесса сборки пакета deb


ссылка на оригинал статьи https://habr.com/ru/articles/786958/