Сторонние исходники и установка

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

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. Не устанавливать. Собрать всё в каком-то подкаталоге и запускать оттуда.
    • Много лишних файлов
    • Не очень понятно как читать man

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

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

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

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

    • Кто за вас бкдет подгружать разделяемые библиотеки из /opt/название-приложения/lib? Никто. Надо разбираться с $LD_LIBRARY_PATH

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

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

  3. /!\ так делать не надо /!\ Установить руками в соответствующие каталоги (/usr/bin/ для бинарников, /usr/lib64 для библиотек и т. д.)

    • А если там файлы из пакетов лежали?
    • А как потом удалять?
    • Админ увидит — руки оторвёт…
    • Вариант предыдущего — /usr/local/… вместо /usr — ненамного лучше

      • В случае linux там мало что лежит
      • Всё остальное так же плохо
  4. Сформировать пакет

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

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

Вывод:

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

Установка

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

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

Замечание 1: чисто теоретически для gettext есть специальный m4-модуль: Tutorial на эту тему

Замечание 2: вместо этого в лекциях мы использовали очень неполноценную конструкцию, которая приравнивала единственный имеющийся .mo-файл к просто данным pkgdata_DATA=ahello.mo. Конструкция эта неполноценна, потому что несколько переводов надо раскладывать в несколько разных каталогов.

Д/З

  1. Взять решение Д/З с локализацией и обеспечить в нём
    1. Сборку и установку в произвольный каталог (для autotools — с помощью --prefix), содержащий стандартные подкаталоги

      • Убедиться, что установленное таком образом приложение находит файлы с переводами в подкаталогах этого каталога
    2. Сборку по стандартной схеме (как минимум, /usr/bin/ для бинарников и /usr/share/locale/ru/LC_MESSAGES/ для русских переводов) и установку в произвольный подкаталог (вот оттуда оно может и не работать). В случае make это делается переменой DESTDIR самого make.

      • Убеждаться в этом не обязательно, но собранная таким образом программа должна находить перевод в /usr/share/locale/ru/LC_MESSAGES/…

  2. Полученный код, очищенный от генератов, поместить в подкаталог 13_PatchInstall отчётного git-репозитория

LecturesCMC/LinuxApplicationDevelopment2020/13_PatchInstall (последним исправлял пользователь FrBrGeorge 2020-12-08 23:35:19)