Библиотеки и сторонние исходники

TODO «Установка» не влезает — перенести

Libtool

libtool — инструмент для кроссплатформенной сборки и тестирования библиотек.

Пример:

А теперь с Libtool:

Особенности:

Версионирование библиотек

Базовая статья

Попробуем добавить -version-info 8:3:1


Это копипаста аналогичного материала прошлых лет; возможно, её надо отредактировать

Использование сторонних исходников:

Patch / diff

Рассмотрим ситуацию, когда сторонние исходники используются, но нужно их немного поправить:

Цикл обновления / внесения изменений:

  1. Первоначальный импорт исходников
    1. Адаптация к вашим нуждам
    2. Оформление серии патчей (см. ниже)

    3. Релиз
  2. Отныне и навеки
    1. Обновление апстримной версии
    2. Применение патчей к обновлённой версии
    3. Адаптация отвалившихся патчей
    4. Релиз

Утилита diffпострочное сравнение и демонстрация изменений двух текстов

   1 #include <stdio.h>
   2 #include <sys/types.h>
   3 #include <sys/stat.h>
   4 #include <fcntl.h>
   5 #include <ctype.h>
   6 
   7 /* open()->fopen() wrapper */
   8 static FILE *ffopen(const char *pathname, const char *mode, int flags)
   9 {
  10   int m;
  11 
  12   switch(tolower(mode[0])+(mode[1]=='+')) {
  13     case 'b': /* "a+" */
  14     case 'a': m = O_WRONLY | O_CREAT | O_APPEND; break;
  15     case 'r': m = O_RDONLY; break;
  16     case 's': m = O_RDWR; break; /* "r+" */
  17     case 'x': /* "w+" */
  18     case 'w': m = O_WRONLY | O_CREAT | O_TRUNC; break;
  19     default: m = O_RDONLY; break;
  20   }
  21 
  22   int fd = open(pathname, flags, m);
  23   return fd<0? NULL: fdopen(fd, mode);
  24 }
  25 
  26 int main(int argc, char *argv[]) {
  27         FILE *fp;
  28 
  29         fp = ffopen(argv[1], "r", O_NOFOLLOW);
  30         if(fp == NULL) {
  31           perror(argv[1]);
  32           return 1;
  33         }
  34 
  35         return 0;
  36 }

   1 #include <stdio.h>
   2 #include <sys/types.h>
   3 #include <sys/stat.h>
   4 #include <fcntl.h>
   5 #include <ctype.h>
   6 
   7 /* open()->fopen() wrapper */
   8 static FILE *ffopen(const char *pathname, const char *mode, int flags)
   9 {
  10   int m;
  11 
  12   /* Simulate fopen flags */
  13   switch(tolower(mode[0])+(mode[1]=='+')) {
  14     case 'a': m = O_WRONLY | O_CREAT | O_APPEND; break;
  15     case 'b': /* "a+" */
  16     case 'r': m = O_RDONLY; break;
  17     case 's': m = O_RDWR; break; /* "r+" */
  18     case 'x': /* "w+" */
  19     case 'w': m = O_WRONLY | O_CREAT | O_TRUNC; break;
  20     default: m = O_RDONLY; break;
  21   }
  22 
  23   int fd = open(pathname, flags, m);
  24   return fd<0? NULL: fdopen(fd, mode);
  25 }
  26 
  27 int main(int argc, char *argv[]) {
  28         FILE *fp;
  29 
  30         fp = ffopen(argv[1], "r", O_NOFOLLOW);
  31         if(fp == NULL) {
  32           perror(argv[1]);
  33           return 1;
  34         }
  35 
  36         return 0;
  37 }

Утилита patch умеет применять результат diff к исходному файлу, при этом получается целевой файл

Что гораздо важнее, patch умеет находить перемещение контекста и даже определять приблизительное совпадение контекста:

В случае, когда какие-то блоки применяются, а какие-то — нет, patch создаёт reject-файл — патч, содержащий только неприложившиеся блоки.

Использование git

Сочетание git и patch

Если никакого git-репозитория нет, всё равно удобно использовать git:

Установка

Есть много способов установить ПО под Linux:

  1. Не устанавливать. Собрать всё в каком-то подкаталоге и запускать оттуда.
    • {o} Просто собрать!

    • Много лишних файлов
    • Не очень понятно как читать man

    • Скорее всего, не будет работать, если мы не сделаем cd этот каталог

    • Надо разбираться с $LD_LIBRARY_PATH

  2. Вариант: собирать один большой статический бинарник со всем, так делает Qt

    • Требует программного решения (данные-«ресурсы»)
    • Требует статической компоновки с большинством библиотек
    • {o} можно запускать его откуда угодно

  3. Установить в специальный отдельный подкаталог системы все нужные файлы
    • Как правило, это /opt/название-приложения

    • Требует прав root

    • Надо разбираться с $LD_LIBRARY_PATH

    • Скорее всего, не будет работать, если мы не сделаем cd этот каталог; но тогда надо отличать два вида файлов

      • RO — те, что установлены в /opt/название-приложения

      • RW — те, которые образуются в процессе работы приложения (например, локальные конфиги в $HOME/.config/название-приложения).

    • Само приложение придётся запускать /opt/название-приложения/bin/название-приложения (или как-то так), либо для каждого добавлять /opt/название-очередного-приложения/bin/ в $PATH

    • {o} Удаление такого приложения — просто удаление каталога /opt/название-приложения

  4. «Крибле! Крабле! Бумс!», оно же «configure - make - make install»
    • Требует прав root
    • Приедет по умолчанию в /usr/local/*, особо никому не мешает, /usr/local/lib можно добавить один раз в системный ld.so.cache, а /usr/local/bin/ — в $PATH

      • Вариант: configure --prefx=/usr — можно попортить систему

    • Проблема деинсталляции
  5. Сформировать пакет / AppImage / Snap / …

    • Установка, удаление
    • Интеграция с системой или, наоборот, изоляция
    • Надо уметь собирать пакеты ☹
    • Если вы не майнтейнер пакета в определённом сообществе, а апстрим, придётся собирать много разных пакетов, что ли??

  6. ( /!\ за это вам уготованы мучения в аду /!\ ) Использовать самописный «инсталлятор»

Вывод:

Поддержка установки в automake

Установка

В gettext поддерживается цель install и монжество её подцелей

Как узнать параметры установки внутри самой программы?

Установка неотслеживаемых файлов

Например, картинок, сопроводительных текстов и т. п. ( /!\ проверить, docdir ли):

   1 install-data-local:
   2         mkdir -p $(DESTDIR)/$(docdir)
   3         cp -a html $(DESTDIR)/$(docdir)

Д/З

В этот раз задания нет — сборка библиотеки будет в следующем Д/З

LecturesCMC/LinuxApplicationDevelopment2022/10_LibrariesPatch (последним исправлял пользователь FrBrGeorge 2022-11-28 12:44:25)