Разработка и сборка пакетов

Я хочу создать пакет для Fedora. Что мне следует знать?

См. здесь и здесь.

Как собрать RPM пакет в mock?

См. здесь.

Как добавить свой пакет в репозиторий Fedora и стать мейнтейнером?

См. здесь.

Что такое Koji?

Fedora Koji - это автоматизированная среда для сборки пакетов для Fedora.

Хочу внести свои правки в пакет и пересобрать его для личных нужд. Как проще это сделать?

Установим утилиты fedpkg и mock:

sudo dnf install fedpkg mock

Скачаем исходники необходимого пакета foo-bar:

fedpkg clone -a foo-bar

Перейдём в каталог с загруженными исходниками и переключимся на ветку для конкретной версии Fedora (если нужна версия из Rawhide - следует использовать master):

cd foo-bar
fedpkg switch-branch f29

Внесём свои правки, сделаем коммит в репозиторий:

git add -A
git commit -m "Description of our changes."

Запустим автоматическую сборку в mock:

fedpkg mockbuild

Как создать tarball с исходниками из Git репозитория?

Если проект по какой-либо причине не поставляет готовые тарболы и отсутствует возможность их скачать напрямую с хостинга VCS, можно создать их из Git.

Клонируем репозиторий источника:

git clone https://example.org/foo-bar.git

Создадим архив с исходниками:

git archive --format=tar --prefix=foo-bar-1.0.0/ HEAD | gzip > ~/rpmbuild/SOURCES/foo-bar-1.0.0.tar.gz

Здесь HEAD - указатель на актуальный коммит (вместо этого можно использовать SHA1 хеш любого коммита, а также имя тега или ветки), foo-bar - название проекта, а 1.0.0 - его версия.

Как переопределить пакет в Koji репозитория RPM Fusion?

Создание build override для репозитория f29-free:

koji-rpmfusion tag f29-free-override foo-bar-1.0-1.fc29

Удаление build override для репозитория f29-free:

koji-rpmfusion untag f29-free-override foo-bar-1.0-1.fc29

Как настроить Git для работы с почтовым сервисом Gmail?

Для того, чтобы использовать функцию git send-mail с почтовым сервисом Gmail, необходимо:

  1. включить двухфакторную аутентификацию в настройках Google аккаунта;
  2. в настройках безопасности почтового ящика Gmail разрешить использование «небезопасных приложений» (под небезопасными Google понимает любые, не поддерживающие OAuth2);
  3. там же включить доступ к почте посредством POP3 или IMAP (это активирует также и необходимый для нас протокол SMTP);
  4. в настройках безопасности сгенерировать новый пароль для приложения;
  5. указать в файле ~/.gitconfig параметры почтового сервиса;
  6. когда будет запрошен пароль, ввести созданный ранее пароль приложения.

Пример файла ~/.gitconfig для работы с почтовым сервисом Gmail:

[sendemail]
    smtpEncryption = tls
    smtpServer = smtp.gmail.com
    smtpUser = yourname@gmail.com
    smtpServerPort = 587

Правильно ли использовать dlopen для загрузки динамических библиотек в приложении?

Для загрузки динамических библиотек в приложении использовать dlopen допускается, но мы настоятельно рекомендуем избегать этого и использовать полноценную линковку по следующим причинам:

  1. в каждом дистрибутиве GNU/Linux именование библиотек, особенно если у них нет чётко установленной апстримом SOVERSION константы, ложится на плечи мейнтейнеров. К примеру есть популярная libcurl. Во всех дистрибутивах она линкуется с openssl и называется libcurl.so, а в Debian и Ubuntu была переименована в libcurl-gnutls.so из-за линковки с gnutls;
  2. нет никакой гарантии, что загрузится именно необходимая версия библиотеки, имеющая необходимую функцию, а отсутствии оной приложение будет аварийно завершено с ошибкой сегментирования;
  3. если существует несколько версий библиотеки с разными SOVERSION, необходимо самостоятельно их искать на диске и подгружать с рядом хаков ибо имя libfoo.so без указанной SOVERSION в большинстве дистрибутивов представляет собой символическую ссылку и доступен лишь после установки соответствующего development пакета. Соответственно на машинах обычных пользователей он отсутствует;
  4. о библиотеках, подгружаемых динамически, не в курсе LD, а следовательно он не сможет при загрузке образа приложения подгрузить их в память;
  5. в случае корректной линковки LD перед запуском приложения осуществит автоматический поиск необходимых экспортируемых функций во всех указанных библиотеках. При их отсутствии приложение не будет запущено;
  6. при сборке пакета динамически подгружаемые через dlopen библиотеки не будут определены и прописаны в качестве зависимостей пакета, что может вызвать проблемы у пользователей и падение приложения;

Как получить полный список установленных переменных окружения в текущем терминале?

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

env

Как получить полный список установленных переменных для запущенного процесса?

Получение списка установленных переменных окружения для запущенных процессов:

cat /proc/$PID/environ

Здесь $PID - PID процесса, информацию о котором необходимо получить.

Как задать переменную окружения?

Вариант 1. Запуск процесса с заданной переменной окружения:

FOO=BAR /usr/bin/foo-bar

Вариант 2. Экспорт переменной окружения в запущенном терминале и дальнейший запуск приложения:

export FOO=BAR
/usr/bin/foo-bar

Вариант 3. Модификация директивы Exec= в ярлыке запуска приложения:

env FOO=BAR /usr/bin/foo-bar

Как правильно настроить Git для работы?

Сначала укажем своё имя и адрес электронной почты:

git config --global user.name "Your Name"
git config --global user.email email@example.org

Установим предпочитаемый текстовый редактор для работы с коммитами:

git config --global core.editor vim

Я хочу внести правки в проект. Как правильно отправить их в апстрим?

Если проект хостится на одном из популярных сервисов (GitHub, BitBucket или GitLab), сначала войдём в свой аккаунт (при осутствии создадим) и сделаем форк репозитория.

Осуществим базовую настройку Git клиента если это ещё не было сделано ранее.

Клонируем наш форк:

git clone git@github.com:YOURNAME/foo-bar.git

Создадим ветку new_feature для наших изменений (для каждого крупного изменения следует создавать отдельную ветку и ни в коем случае не коммитить в master):

git checkout -b new_feature

Внесём свои правки в проект, затем осуществим их фиксацию:

git add -A
git commit -s

В появившемся текстовом редакторе укажем подробное описание всех наших изменений на английском языке. Несмотря на то, что параметр -s является опциональным, большинство проектов требуют его использования для автоматического создания подписи вида:

Signed-off-by: Your Name <email@example.org>

Многие проекты обновляются слишком быстро, поэтому потребуется осуществить синхронизацию наших изменений с актуальной веткой апстрима. Для этого подключим к нашем форку оригинальный репозиторий:

git remote add upstream https://github.com/foo/foo-bar.git

Скачаем актуальные изменения и выполним rebase основной ветки нашего форка с апстримом:

git fetch upstream
git checkout master
git merge upstream/master

Осуществим rebase ветки с нашими изменениями с основной:

git checkout new_feature
git rebase master

Отправим наши изменения на сервер:

git push -u origin new_feature

Создадим новый Pull Request.

Как скомпилировать простую программу на языке C++ из консоли?

Установим компилятор GCC-C++ (G++) и ряд вспомогательных компонентов:

sudo dnf install gcc-c++ rpm-build

Создадим простейший пример helloworld.cpp:

#include <iostream>

int main(int argc, char *argv[], char *env[])
{
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

Скомпилируем и слинкуем его:

g++ $(rpm -E %{optflags}) -fPIC helloworld.cpp -o helloworld $(rpm -E %{build_ldflags}) -lstdc++

Здесь g++ - запускающий файл файл компилятора, helloworld.cpp - файл с исходным кодом (если их несколько, то разделяются пробелом), helloworld - имя результирующего бинарника, -lstdc++ - указание компоновщику на необходимость линковки со стандартной библиотекой C++.

Корректные флаги компиляции и компоновки вставляются автоматически из соответствующих макросов RPM.

Запустим результат сборки:

./helloworld

Если всё сделано верно, то увидим сообщение Hello, World! в консоли.

Приложение падает. Как мне его отладить?

Для начала рекомендуется (хотя и не обязательно) установить отладочную информацию для данного пакета:

sudo dnf debuginfo-install foo-bar

После завершения процесса отладки символы можно снова удалить.

Чтобы получить бэктрейс падения, нужно выполнить в терминале:

gdb /usr/bin/foo-bar 2>&1 | tee ~/backtrace.log

Далее в интерактивной консоли отладчика ввести: handle SIGPIPE nostop noprint и затем run, дождаться сегфолта и выполнить bt full для получения бэктрейса. Теперь можно прописать quit для выхода из режима отладки.

Далее получившийся файл ~/backtrace.log следует загрузить на любой сервис размещения текстовых файлов.

Также рекомендуется ещё сделать трассировку приложения до момента падения:

strace -o ~/trace.log /usr/bin/foo-bar

Полученный файл ~/trace.log также следует загрузить на сервис.

Безопасно ли использовать LD_PRELOAD для загрузки сторонних библиотек?

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

Создадим и скомпилируем простой пример example.c:

#include <stdio.h>

static __attribute__((constructor (200))) void bar()
{
    printf("%s", "Method bar() was called.\n");
}

static __attribute__((constructor (150))) void foo()
{
    printf("%s", "Method foo() was called.\n");
}

Данный метод содержит сразу два суперглобальных конструктора с указанием приоритетов. Чем ниже приоритет, тем скорее данный метод будет исполнен.

Скомпилируем и слинкуем наш пример:

gcc -shared $(rpm -E %{optflags}) -fPIC example.c -o example.so $(rpm -E %{build_ldflags}) -lc

Внедрим нашу библиотеку в известный доверенный процесс, например whoami:

LD_PRELOAD=./example.so whoami

Оба суперглобальных метода будут немедленно исполнены с правами запускаемого приложения и изменят его вывод:

Method foo() was called.
Method bar() was called.
user1

Разумеется, вместо безобидных вызовов функции printf() может находиться абсолютно любой код, в т.ч. вредоносный.

Как можно активировать LTO оптимизации при сборке пакета?

Для активации LTO оптимизаций необходимо и достаточно передать параметр -flto как для компилятора (CFLAGS и/или CXXFLAGS), так и для компоновщика.

Самый простой способ сделать это - переопределение значений стандартных макросов внутри SPEC файла:

%global optflags %{optflags} -flto
%global build_ldflags %{build_ldflags} -flto

Если в проекте применяются статические библиотеки (в т.ч. для внутренних целей), то также необходимо переопределить ряд переменных окружения внутри секции %build:

export AR=%{_bindir}/gcc-ar
export RANLIB=%{_bindir}/gcc-ranlib
export NM=%{_bindir}/gcc-nm

Если используется система сборки cmake, то помимо этого придётся патчить манифест CMakeLists.txt, т.к. он в настоящее время не поддерживает загрузку переопределённых значений:

set(CMAKE_AR "/usr/bin/gcc-ar")
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
set(CMAKE_NM "/usr/bin/gcc-nm")

В противном случае появится ошибка plugin needed to handle lto object.

Как вывести список установленных пакетов, от которых никто не зависит?

В настоящее время данная функциональность отсутствует в dnf «из коробки», поэтому напишем и скомпилируем небольшую программу на языке C, реализующую это средствами библиотеки libsolv.

Установим компилятор и необходимые для сборки библиотеки:

sudo dnf install gcc libsolv-devel

Создадим файл rpm-unneeded.c с исходным текстом программы:

#include <solv/pool.h>
#include <solv/poolarch.h>
#include <solv/repo_rpmdb.h>
#include <solv/solver.h>

int main(void)
{
    Pool *pool;
    Repo *rpmdb;
    Solver *solver;
    Queue q;

    pool = pool_create();
    pool_setarch(pool, NULL);
    pool_set_flag(pool, POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS, 1);

    rpmdb = repo_create(pool, "@system");
    repo_add_rpmdb(rpmdb, NULL, 0);
    pool->installed = rpmdb;

    solver = solver_create(pool);
    solver_set_flag(solver, SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES, 1);
    solver_set_flag(solver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
    solver_set_flag(solver, SOLVER_FLAG_YUM_OBSOLETES, 1);

    queue_init(&q);
    solver_solve(solver, &q);
    solver_get_unneeded(solver, &q, 1);

    for (int i = 0; i < q.count; i++)
    {
        printf("%s\n", pool_solvid2str(pool, q.elements[i]));
    }

    queue_free(&q);
    pool_free(pool);

    return 0;
}

Скомпилируем и слинкуем приложение:

gcc $(rpm -E %{optflags}) -fPIC rpm-unneeded.c -o rpm-unneeded $(rpm -E %{build_ldflags}) -lsolv -lsolvext

Запустим приложение ./rpm-unneeded и получим список установленных пакетов, от которых никто не зависит.

Можно ли использовать cpack для сборки пакетов для GNU/Linux?

Нет, использовать cpack категорически не рекомендуется по следующим причинам:

  • создаёт RPM и DEB пакеты в виде архивов;
  • не добавляет метаданные в создаваемые пакеты;
  • не прописывает зависимости от библиотек и других пакетов;
  • не экспортирует provides;
  • не обрабатывает mime-типы;
  • не добавляет обязательные скриптлеты;
  • не соблюдает гайдлайны дистрибутивов.

Вместо cpack следует собирать нативные пакеты.

Приложение собрано со старой версией библиотеки. Как заставить его работать?

Если приложение было собрано со старой версией библиотеки foo-bar, которой уже нет в репозиториях и его требуется запустить, существует два способа:

  1. LD_PRELOAD - небезопасный - библиотека (или библиотеки) напрямую инъектируется в процесс средствами интерпретатора динамических библиотек LD до его непосредственного запуска;
  2. LD_LIBRARY_PATH - более безопасный - список каталогов, в которых интерпретатор динамических библиотек LD ищет соответствующие so, расширяется на указанные пользователем значения.

Рассмотрим второй способ с переопределением переменной окружения LD_LIBRARY_PATH.

Скачаем RPM пакет foo-bar необходимой версии из любого источника (лучшим вариантом будет конечно же репозитории старых версий Fedora), распакуем его например в ~/lib/foo-bar и извлечём необходимые динамические библиотеки (.so файлы).

Создадим shell-скрипт run-foo.sh для запуска бинарника:

#!/usr/bin/sh
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/lib/foo-bar
/path/to/binary/foo

Здесь foo - имя бинарника, который требуется запустить, а /path/to/binary - каталог, в котором он находится. В качестве разделителя путей LD_LIBRARY_PATH применяется двоеточие. Закрывающий слэш не ставится.

Установим скрипту разрешение не запуск и запустим его:

chmod +x run-foo.sh
./run-foo.sh

Если всё сделано верно, приложение успешно стартует.

Проекты под какими лицензиями допускается распространять в репозиториях?

См. здесь.

В каком порядке запускаются процессы через канал (пайп)?

Если запускается несколько процессов с передачей данных через канал (пайп; pipe), то все они стартуют одновременно, затем начинает выполняться первый, а остальные уходят в состояние ожидания ввода.

Можно ли использовать собственные флаги компиляции при сборке пакета?

Для любых официальных сборок следует использовать исключительно стандартные для дистрибутива флаги, предоставляемые макросами %{optflags} (флаги компилятора) и %{build_ldflags} (флаги компоновки).

Какую IDE использовать для разработки на C++ в Fedora?

Мы рекомендуем Qt Creator, которая одинаково хорошо подходит как для разработки на C++ (с Qt и без него), так и чистого C.

Установим данную IDE, а также компилятор C++ и ряд необходимых библиотек и средств для сборки проектов:

sudo dnf install gcc gcc-c++ qt-creator qt5-qtbase-devel cmake

При необходимости установим также документацию Qt и готовые примеры стандартных приложений:

sudo dnf install qt5-qtbase-doc qt5-qtbase-examples qt-creator-doc

В Qt Creator отсутствует документация. Как исправить?

Если Qt Creator при попытке загрузить документацию выдаёт ошибку Error loading: qthelp://org.qt-project.qtcreator.472/doc/index.html, выберем пункт меню Tools - Options - Help - Documentation - Add, затем вручную добавим следующие файлы:

/usr/share/doc/qt5/qmake.qch
/usr/share/doc/qt5/qtconcurrent.qch
/usr/share/doc/qt5/qtcore.qch
/usr/share/doc/qt5/qtdbus.qch
/usr/share/doc/qt5/qtgui.qch
/usr/share/doc/qt5/qtnetwork.qch
/usr/share/doc/qt5/qtnetworkauth.qch
/usr/share/doc/qt5/qtopengl.qch
/usr/share/doc/qt5/qtplatformheaders.qch
/usr/share/doc/qt5/qtprintsupport.qch
/usr/share/doc/qt5/qtsql.qch
/usr/share/doc/qt5/qttestlib.qch
/usr/share/doc/qt5/qtwidgets.qch
/usr/share/doc/qt5/qtxml.qch
/usr/share/doc/qt5/qtxmlpatterns.qch
/usr/share/doc/qtcreator/qtcreator.qch
/usr/share/doc/qtcreator/qtcreator-dev.qch

Изменения вступят в силу после перезапуска IDE.

В Qt Creator отсутствуют компиляторы. Как исправить?

Если Qt Creator не смог самостоятельно обнаружить установленный в системе фреймворк Qt, а также компилятор, то необходимо добавить их самостоятельно.

Для этого войдём в настройки IDE, затем сначала добавим компилятор GCC /usr/bin/gcc, а затем тулчейн Qt - /usr/bin/qmake-qt5. После этого на вкладке Kits создадим новый набор из данных компонентов.

Сохраним изменения в настройках и добавим созданный Kit к своему проекту.

Какую IDE использовать для разработки на Python в Fedora?

Мы рекомендуем PyCharm Community Edition.

Подключим COPR репозиторий:

sudo dnf copr enable phracek/PyCharm

Установим IDE:

sudo dnf install pycharm-community pycharm-community-jre

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

sudo dnf install pycharm-community-plugins

Как получить информацию о содержимом образа бинарной прошивки?

Для работы с образами прошивок можно использовать утилиту binwalk. Установим её:

sudo dnf install binwalk

Произведём анализ файла и получим результат:

binwalk foo-bar.bin

Как автоматически скачать исходники, прописанные в SPEC-файле?

Установим необходимые утилиты:

sudo dnf install rpm-build rpmdevtools

Создадим базовую иерархию каталогов для rpmbuild:

rpmdev-setuptree

Скачаем исходники, прописанные в SPEC-файле foo-bar.spec:

spectool -g -R foo-bar.spec

Как автоматически инкрементировать релиз в SPEC-файле?

Установим необходимый для работы пакет:

sudo dnf install rpmdevtools

Инкрементируем релиз SPEC-файла (директива Release) с автоматическим созданием новой строки в %changelog:

rpmdev-bumpspec -c "Updated to latest snapshot."

Как загрузить изменения во всех вложенных репозиториях из данного каталога?

Если Git репозитории были клонированы в общий каталог ~/foo-bar, то загрузим изменения в каждом из вложенных проектов при помощи find и bash:

find ~/foo-bar -maxdepth 1 ! -path . -type d -exec bash -c "pushd '{}' ; git pull ; popd" \;

Как создать пустую ветку в Git без общей истории?

Создадим новую пустую ветку foo-bar от текущего HEAD:

git checkout --orphan foo-bar

Создадим удалим всё проиндексированное содержимое данной ветки:

git reset --hard

Можно ли перенести каталоги сборки и кэшей mock на другой диск?

Система автоматической сборки пакетов mock занимает огромное количество места в корневом разделе, поэтому многие мейнтейнеры хотели бы перенести её на другой диск. Штатно это сделать не представляется возможным ибо значения каталогов по умолчанию /var/cache/mock и /var/lib/mock жёстко прописаны внутри приложения и не подлежат изменению со стороны пользователя, поэтому воспользуемся символическими ссылками.

Создадим на другом накопителе (его файловая система должна поддерживать права доступа Unix) базовый каталог для mock:

cd /media/foo-bar
sudo mkdir mock
sudo chown root:mock mock
sudo chmod 42775 mock

Переместим содержимое текущих рабочих каталогов mock:

sudo mv /var/cache/mock /media/foo-bar/mock/cache
sudo mv /var/lib/mock /media/foo-bar/mock/lib

Создадим символические ссылки на старом месте:

sudo ln -s /media/foo-bar/mock/cache/mock /var/cache/mock
sudo ln -s /media/foo-bar/mock/lib/mock /var/lib/mock

Зададим контекст SELinux по умолчанию для нового хранилища:

sudo semanage fcontext -a -t mock_cache_t "/media/foo-bar/mock/cache(/.*)?"
sudo semanage fcontext -a -t mock_var_lib_t "/media/foo-bar/mock/lib(/.*)?"

Сбросим контекст SELinux для всех рабочих каталогов:

sudo restorecon -Rv /var/cache/mock
sudo restorecon -Rv /var/lib/mock
sudo restorecon -Rv /media/foo-bar/mock/cache
sudo restorecon -Rv /media/foo-bar/mock/lib

Здесь /media/foo-bar - точка монтирования нового накопителя, на котором будут располагаться кэши mock.

Внимание! Раздел назначения должен использовать флаги монтирования по умолчанию defaults. В противном случае не будут выполнены скриптлеты и сборка не завершится успешно.

Как включить отображение текущей ветки Git в Bash?

Модуль интеграции с Bash входит в состав пакета Git. Добавим в приветствие Bash следующую строку:

export PS1='[\u@\h \W$(declare -F __git_ps1 &>/dev/null && __git_ps1 " (%s)")]\$ '

В качестве опциональных параметров поддерживаются GIT_PS1_SHOWDIRTYSTATE (показывать наличие незакреплённых изменений внутри каталога) и GIT_PS1_SHOWUNTRACKEDFILES (учитывать, либо нет не отслеживаемые системой контроля версий файлы):

export GIT_PS1_SHOWDIRTYSTATE=true
export GIT_PS1_SHOWUNTRACKEDFILES=true

Изменения вступят в силу при следующем запуске оболочки.

Как создать унифицированный патч изменений между двумя файлами?

Для создания патча нам необходимо две версии файла: оригинальная и текущая.

Создадим унифицрованный патч с разностью между файлами foo-bar.txt.orig (оригинальный) и foo-bar.txt (текущий):

diff -Naur foo-bar.txt.orig foo-bar.txt > result.patch

Результат будет сохранён в файле result.patch.

Как создать унифицированный патч изменений между двумя каталогами?

Создадим унифицрованный патч с разностью между каталогами foo-bar_orig (оригинальный) и foo-bar (текущий):

diff -Naur foo-bar_orig foo-bar > result.patch

Результат будет сохранён в файле result.patch.

Как применить унифицированный патч?

Проверим возможность применения патча foo-bar.patch без внесения каких-либо изменений:

patch -p0 --dry-run -i foo-bar.patch

Применим патч:

patch -p0 -i foo-bar.patch

Параметром -p задаётся количество каталогов, которые будут отброшены при поиске файлов, указанных внутри унифицированного патча.

Как откатить наложенный унифицированный патч?

Проверим возможность отката патча foo-bar.patch без внесения каких-либо изменений:

patch -p0 -R --dry-run -i foo-bar.patch

Откатитим внесённые изменения:

patch -p0 -R -i foo-bar.patch

Параметром -p задаётся количество каталогов, которые будут отброшены при поиске файлов, указанных внутри унифицированного патча.

Как создать унифицированный патч между двумя коммитами?

Создадим патч между двумя коммитами AAA и BBB:

git diff AAA BBB > result.patch

Создадим патч коммитом CCC и текущим рабочей рабочей версией:

git diff CCC > result.patch

Здесь AAA, BBB и CCC - хеши коммитов в Git репозитории.

Как экспортировать Git коммит для отправки по электронной почте?

В Git имеется встроенное средство экспорта коммитов для их дальнейшей отправки по электронной почте.

Экспортируем один коммит:

git format-patch -1

Экспортируем сразу 3 коммита:

git format-patch -3

Как авторизоваться в инфраструктуре Fedora?

Для авторизации мы должны использовать вход в домен посредством Kerberos:

kinit foo-bar@FEDORAPROJECT.ORG

Здесь foo-bar - логин в FAS. Имя домена должно быть указано строго в верхнем регистре.

Также для некоторых операций необходимо загрузить публичный ключ SSH в FAS аккаунт.

Как запросить создание пакета в репозитории?

Сразу после завершения процедуры package review, мейнтейнер должен запросить создание пакета в репозиториях Fedora.

Установим утилиту fedpkg

sudo dnf install fedpkg

Получим новый токен в Pagure, который будет использоваться утилитой fedpkg для создания заявки. Для этого перейдём в раздел Settings - API Keys - Create new key, затем в списке доступных разрешений (ACLs) установим флажок только около опции Create a new ticket и нажмём кнопку Add.

Создадим файл конфигурации fedpkg:

mkdir -p ~/.config/rpkg
touch ~/.config/rpkg/fedpkg.conf

Загрузим созданный файл ~/.config/rpkg/fedpkg.conf в любом текстовом редакторе и добавим:

[fedpkg.pagure]
token = XXXXXXXXXX

Здесь XXXXXXXXXX - полученный от Pagure токен.

Запросим создание нового пакета в репозитории, а также веток для всех поддерживаемых релизов Fedora:

fedpkg request-repo --namespace rpms --monitor monitoring foo-bar YYYYYY
fedpkg request-branch --namespace rpms --repo foo-bar --all-releases

Здесь foo-bar - имя пакета, а YYYYYY - номер заявки в Red Hat BugZilla с успешно завершённым package review.

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

После создания пакета осуществим вход в инфраструктуру Fedora, затем скачаем репозиторий пакета из Fedora SCM, содержащий SPEC файл и набор патчей (при необходимости), а также прочие службные файлы:

fedpkg clone foo-bar
cd foo-bar

Самым простым способом загрузки является импорт готового SRPM файла, поэтому выполним именно эту процедуру:

fedpkg switch-branch master
fedpkg import /путь/к/foo-bar-1.0-1.fc30.src.rpm

Проверим внесённые изменения и если всё верно, жмём Q для выхода. Зафиксируем наши изменения:

git commit -m "Initial import."

При необходимости внесём изменения и в ветки поддерживаемых релизов Fedora:

fedpkg switch-branch f30
git merge master

Отправим изменения на сервер:

git push

Как осуществить сборку пакета для публикации в репозиториях?

После загрузки файлов с исходными кодами пакета, осуществим вход в инфраструктуру Fedora, а затем приступим к непосредственно сборке в Fedora Koji:

cd foo-bar
fedpkg switch-branch master
fedpkg build

При необходимости соберём и для других поддерживаемых релизов Fedora:

fedpkg switch-branch f30
fedpkg build

Как осуществить тестовую сборку пакета для определённой архитектуры?

Осуществим вход в инфраструктуру Fedora.

Выполним стандартную scratch-сборку для всех поддерживаемых данным выпуском архитектур:

cd foo-bar
fedpkg switch-branch master
fedpkg build --scratch

Выполним scratch-сборку только для указанных архитектур:

cd foo-bar
fedpkg switch-branch master
fedpkg scratch-build --arches x86_64 aarch64

Как выложить собранный пакет в репозитории?

По окончании сборки мы можем воспользоваться Fedora Bodhi и выложить обновление в репозитории.

Сначала все обновления попадают в тестовые репозитории Fedora (updates-testing) и лишь после получения положительной кармы от других участников сообщества (уровень задаётся мейнтейнером, но не может быть меньше 1), либо по истечении 7 дней, оно может попасть в стабильные (updates) и будет доставлено конечным пользователям.

Заполним стандартную, хорошо документированную форму, затем нажмём кнопку Submit.

Что разрешается хранить в COPR репозиториях?

В COPR разрешается распространять всё то же, что и в основных репозиториях Fedora. Сборка и публикация запатентованного и проприетарного программного обеспечения в пользовательских оверлеях не допускается.

Что такое linux-vdso.so.1 и почему она загружена в каждый процесс?

Библиотека linux-vdso.so.1 не является обычной динамической библиотекой. Это виртуальный динамически разделяемый объект (VDSO), который отображается на адресное пространство каждого запущенного процесса ядром Linux и представляет собой интерфейс для осуществления быстрых системных вызовов.

Данный объект можно обнаружить в выводе ldd для любого бинарного ELF-файла, но без прямого пути, т.к. он не является реальным файлом.

Как определить зависимости конкретного бинарника?

Для определения зависимостей любых ELF-файлов, воспользуемся утилитой ldd.

Определим зависимости динамически разделяемой библиотеки:

ldd /path/to/shared/library.so.1

Определим зависимости исполняемого файла:

ldd /path/to/application

Если библиотека была найдена в системе, наряду с именем будет указан абсолютный путь к её файлу на диске, а также адрес предполагаемой загрузки.

Исключение составляют виртуальные объекты, для которых будет указан лишь адрес, без пути.

Как изменить адрес Git репозитория после его переезда?

Получим список подключённых удалённых ресурсов текущего Git репозитория:

git remote -v

Изменим апстрим для origin:

git remote set-url origin https://github.com/foo-bar/new_repo.git

После этого команды Git, отвечающие за работу с удалёнными ресурсами, git pull, git fetch, git push, начнут использовать новый апстрим.

Можно ли перенести стандартный каталог сборки rpmbuild?

Да, это возможно. Откроем файл ~/.rpmmacros в любом текстовом редаторе, найдём строку:

%_topdir %(echo $HOME)/rpmbuild

Заменим её на следующую:

%_topdir /media/foo-bar/rpmbuild

Здесь /media/foo-bar - новый каталог размещения базовой иерархии rpmbuild.

Сохраним изменения, которые вступят в силу немеденно.

Как определить какие лицензии используются в проекте?

Установим утилиту licensecheck:

sudo dnf install licensecheck

Запустим проверку проекта:

licensecheck --recursive --merge-licenses --no-verbose /path/to/foo-bar > ~/results.txt

Здесь /path/to/foo-bar - путь к распакованным исходникам проекта, а ~/results.txt - имя файла, в котором будут сохранены результаты проверки.

Как загрузить в gdb отладчик coredump падения?

GDB позволяет не только отлаживать приложения напрямую, но и загружать coredump падений.

Установим утилиту lz4 для распаковки сжатых файлов с дампами:

sudo dnf install lz4

Распакуем coredump:

unlz4 /path/to/coredump.lz4

Воспользуемся описанным выше способом получения backtrace падения, но слегка модифицируем команду запуска отладчика:

gdb /usr/bin/foo-bar /path/to/coredump 2>&1 | tee ~/backtrace.log

Здесь /usr/bin/foo-bar - путь к отлаживаемому приложению, /path/to/coredump - coredump падения (версия приложения и дампа, снятого с него, должны обязательно совпадать), а ~/backtrace.log - файл, в котором будет сохранён трейс падения.