development.rst 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793
  1. ..
  2. SPDX-FileCopyrightText: 2018-2023 EasyCoding Team and contributors
  3. SPDX-License-Identifier: CC-BY-SA-4.0
  4. .. _development:
  5. *****************************
  6. Разработка и сборка пакетов
  7. *****************************
  8. .. index:: repository, package, packaging, rpm
  9. .. _create-package:
  10. Я хочу создать пакет для Fedora. Что мне следует знать?
  11. ============================================================
  12. См. `здесь <https://www.easycoding.org/2019/01/28/sozdayom-rpm-pakety-dlya-fedora.html>`__ и `здесь <https://www.easycoding.org/2018/06/17/pravilno-paketim-po-dlya-linux.html>`__.
  13. .. index:: package, packaging, rpm, building
  14. .. _build-package:
  15. Как собрать RPM пакет в mock?
  16. ==================================
  17. См. `здесь <https://www.easycoding.org/2017/02/22/sobiraem-rpm-pakety-dlya-fedora-v-mock.html>`__.
  18. .. index:: packaging, repository, maintainer
  19. .. _becoming-maintainer:
  20. Как добавить свой пакет в репозиторий Fedora и стать мейнтейнером?
  21. =====================================================================
  22. См. `здесь <https://www.easycoding.org/2016/06/20/dobavlyaem-paket-v-glavnyj-repozitorij-fedora.html>`__.
  23. .. index:: koji, about
  24. .. _koji-about:
  25. Что такое Koji?
  26. ===================
  27. `Fedora Koji <https://koji.fedoraproject.org/koji/>`__ -- это автоматизированная среда для сборки пакетов для Fedora.
  28. .. index:: fedpkg, package, rebuild, mock, rpm
  29. .. _fedpkg-rebuild:
  30. Хочу внести свои правки в пакет и пересобрать его для личных нужд. Как проще это сделать?
  31. ===============================================================================================
  32. Установим утилиты fedpkg и mock:
  33. .. code-block:: text
  34. sudo dnf install fedpkg mock
  35. Скачаем исходники необходимого пакета **foo-bar**:
  36. .. code-block:: text
  37. fedpkg clone -a foo-bar
  38. Перейдём в каталог с загруженными исходниками и переключимся на ветку для конкретной версии Fedora (если нужна версия из Rawhide -- следует использовать **master**):
  39. .. code-block:: text
  40. cd foo-bar
  41. fedpkg switch-branch f38
  42. Внесём свои правки, сделаем коммит в репозиторий:
  43. .. code-block:: text
  44. git add -A
  45. git commit -m "Description of our changes."
  46. Запустим автоматическую :ref:`сборку в mock <build-package>`:
  47. .. code-block:: text
  48. fedpkg mockbuild
  49. .. index:: git, tarball
  50. .. _git-tarball:
  51. Как создать tarball с исходниками из Git репозитория?
  52. =========================================================
  53. Если проект по какой-либо причине не поставляет готовые тарболы и отсутствует возможность их скачать напрямую с хостинга VCS, можно создать их из Git.
  54. Клонируем репозиторий источника:
  55. .. code-block:: text
  56. git clone https://example.org/foo-bar.git
  57. Создадим архив с исходниками:
  58. .. code-block:: text
  59. git archive --format=tar --prefix=foo-bar-1.0.0/ HEAD | gzip > ~/rpmbuild/SOURCES/foo-bar-1.0.0.tar.gz
  60. Здесь **HEAD** -- указатель на актуальный коммит (вместо этого можно использовать SHA1 хеш любого коммита, а также имя тега или ветки), **foo-bar** -- название проекта, а **1.0.0** -- его версия.
  61. .. index:: fedpkg, koji, build, rpmfusion
  62. .. _rpmfusion-override:
  63. Как переопределить пакет в Koji репозитория RPM Fusion?
  64. ===========================================================
  65. Создание build override для репозитория f38-free:
  66. .. code-block:: text
  67. koji-rpmfusion tag f38-free-override foo-bar-1.0-1.fc38
  68. Удаление build override для репозитория f38-free:
  69. .. code-block:: text
  70. koji-rpmfusion untag f38-free-override foo-bar-1.0-1.fc38
  71. .. index:: rpmfusion, koji, build, repository
  72. .. _rpmfusion-koji-regen:
  73. Как обновить кэши репозиториев Koji в RPM Fusion?
  74. =====================================================
  75. Запустим обновление кэшей репозиториев для free:
  76. .. code-block:: text
  77. koji-rpmfusion regen-repo f38-free-build --nowait
  78. Запустим обновление кэшей репозиториев для nonfree:
  79. .. code-block:: text
  80. koji-rpmfusion regen-repo f38-nonfree-build --nowait
  81. .. index:: git, gmail, mail
  82. .. _git-gmail:
  83. Как настроить Git для работы с почтовым сервисом Gmail?
  84. ===========================================================
  85. Для того, чтобы использовать функцию ``git send-mail`` с почтовым сервисом Gmail, необходимо:
  86. 1. включить двухфакторную аутентификацию в настройках Google аккаунта;
  87. 2. в настройках безопасности почтового ящика Gmail разрешить использование "небезопасных приложений" (под небезопасными Google понимает любые, не поддерживающие OAuth2);
  88. 3. там же включить доступ к почте посредством POP3 или IMAP (это активирует также и необходимый для нас протокол SMTP);
  89. 4. в настройках безопасности сгенерировать новый пароль для приложения;
  90. 5. указать в файле ``~/.gitconfig`` параметры почтового сервиса;
  91. 6. когда будет запрошен пароль, ввести созданный ранее пароль приложения.
  92. Пример файла ``~/.gitconfig`` для работы с почтовым сервисом Gmail:
  93. .. code-block:: ini
  94. [sendemail]
  95. smtpEncryption = tls
  96. smtpServer = smtp.gmail.com
  97. smtpUser = yourname@gmail.com
  98. smtpServerPort = 587
  99. .. index:: library, shared library, linker, dlopen
  100. .. _dlopen-usage:
  101. Правильно ли использовать dlopen для загрузки динамических библиотек в приложении?
  102. ======================================================================================
  103. Для загрузки динамических библиотек в приложении использовать dlopen допускается, но мы настоятельно рекомендуем избегать этого и использовать полноценную линковку по следующим причинам:
  104. 1. в каждом дистрибутиве GNU/Linux именование библиотек, особенно если у них нет чётко установленной апстримом SOVERSION константы, ложится на плечи мейнтейнеров. К примеру есть популярная libcurl. Во всех дистрибутивах она линкуется с openssl и называется libcurl.so, а в Debian и Ubuntu была переименована в libcurl-gnutls.so из-за линковки с gnutls;
  105. 2. нет никакой гарантии, что загрузится именно необходимая версия библиотеки, имеющая необходимую функцию, а отсутствии оной приложение будет аварийно завершено с ошибкой сегментирования;
  106. 3. если существует несколько версий библиотеки с разными SOVERSION, необходимо самостоятельно их искать на диске и подгружать с рядом хаков ибо имя libfoo.so без указанной SOVERSION в большинстве дистрибутивов представляет собой символическую ссылку и доступен лишь после установки соответствующего development пакета. Соответственно на машинах обычных пользователей он отсутствует;
  107. 4. о библиотеках, подгружаемых динамически, не в курсе LD, а следовательно он не сможет при загрузке образа приложения подгрузить их в память;
  108. 5. в случае корректной линковки LD перед запуском приложения осуществит автоматический поиск необходимых экспортируемых функций во всех указанных библиотеках. При их отсутствии приложение не будет запущено;
  109. 6. при сборке пакета динамически подгружаемые через dlopen библиотеки не будут определены и прописаны в качестве зависимостей пакета, что может вызвать проблемы у пользователей и падение приложения;
  110. .. index:: environment, options, env, terminal
  111. .. _env-get-term:
  112. Как получить полный список установленных переменных окружения в текущем терминале?
  113. ======================================================================================
  114. Получить список установленных :ref:`переменных окружения <env-set>` можно посредством выполнения утилиты **env**:
  115. .. code-block:: text
  116. env
  117. .. index:: environment, options, env, application
  118. .. _env-get-app:
  119. Как получить полный список установленных переменных для запущенного процесса?
  120. ================================================================================
  121. Получение списка установленных :ref:`переменных окружения <env-set>` для запущенных процессов:
  122. .. code-block:: text
  123. cat /proc/$PID/environ
  124. Здесь **$PID** -- :ref:`PID <get-pid>` процесса, информацию о котором необходимо получить.
  125. .. index:: environment, options, env
  126. .. _env-set:
  127. Как задать переменную окружения?
  128. ====================================
  129. Вариант 1. Запуск процесса с заданной переменной окружения:
  130. .. code-block:: text
  131. FOO=BAR /usr/bin/foo-bar
  132. Вариант 2. Экспорт переменной окружения в запущенном терминале и дальнейший запуск приложения:
  133. .. code-block:: text
  134. export FOO=BAR
  135. /usr/bin/foo-bar
  136. Вариант 3. Модификация директивы ``Exec=`` в ярлыке запуска приложения:
  137. .. code-block:: text
  138. Exec=env FOO=BAR /usr/bin/foo-bar
  139. .. index:: environment, options, env
  140. .. _env-unset:
  141. Как удалить переменную окружения?
  142. ====================================
  143. Вариант 1. Удаление экспортированной :ref:`переменной окружения <env-set>` при помощи команды оболочки **unset**:
  144. .. code-block:: text
  145. unset FOO
  146. Вариант 2. Удаление экспортированной переменной окружения в запущенном терминале и дальнейший запуск приложения:
  147. .. code-block:: text
  148. unset FOO
  149. /usr/bin/foo-bar
  150. Вариант 3. Модификация директивы ``Exec=`` в ярлыке запуска приложения:
  151. .. code-block:: text
  152. Exec=env -u FOO /usr/bin/foo-bar
  153. .. index:: git, vcs, configuration
  154. .. _git-configuration:
  155. Как правильно настроить Git для работы?
  156. ===========================================
  157. Сначала укажем своё имя и адрес электронной почты:
  158. .. code-block:: text
  159. git config --global user.name "Your Name"
  160. git config --global user.email email@example.org
  161. Установим :ref:`предпочитаемый текстовый редактор <editor-git>` для работы с коммитами:
  162. .. code-block:: text
  163. git config --global core.editor vim
  164. .. index:: git, vcs, pull request, push, commit
  165. .. _git-pull-request:
  166. Я хочу внести правки в проект. Как правильно отправить их в апстрим?
  167. =======================================================================
  168. Если проект хостится на одном из популярных сервисов (GitHub, BitBucket или GitLab), сначала войдём в свой аккаунт (при осутствии создадим) и сделаем форк репозитория.
  169. Осуществим :ref:`базовую настройку Git <git-configuration>` клиента если это ещё не было сделано ранее.
  170. Клонируем наш форк:
  171. .. code-block:: text
  172. git clone git@github.com:YOURNAME/foo-bar.git
  173. Создадим ветку **new_feature** для наших изменений (для каждого крупного изменения следует создавать отдельную ветку и *ни в коем случае не коммитить в master*):
  174. .. code-block:: text
  175. git checkout -b new_feature
  176. Внесём свои правки в проект, затем осуществим их фиксацию:
  177. .. code-block:: text
  178. git add -A
  179. git commit -s
  180. В появившемся :ref:`текстовом редакторе <editor-git>` укажем подробное описание всех наших изменений на английском языке. Несмотря на то, что параметр ``-s`` является опциональным, большинство проектов требуют его использования для автоматического создания подписи вида:
  181. .. code-block:: text
  182. Signed-off-by: Your Name <email@example.org>
  183. Многие проекты обновляются слишком быстро, поэтому потребуется осуществить синхронизацию наших изменений с актуальной веткой апстрима. Для этого подключим к нашем форку оригинальный репозиторий:
  184. .. code-block:: text
  185. git remote add upstream https://github.com/foo/foo-bar.git
  186. Скачаем актуальные изменения и выполним rebase основной ветки нашего форка с апстримом:
  187. .. code-block:: text
  188. git fetch upstream
  189. git checkout master
  190. git merge upstream/master
  191. Осуществим rebase ветки с нашими изменениями с основной:
  192. .. code-block:: text
  193. git checkout new_feature
  194. git rebase master
  195. Отправим наши изменения на сервер:
  196. .. code-block:: text
  197. git push -u origin new_feature
  198. Создадим новый Pull Request.
  199. .. index:: c++, cxx, application, console
  200. .. _cxx-console:
  201. Как скомпилировать простую программу на языке C++ из консоли?
  202. ================================================================
  203. Установим компилятор GCC-C++ (G++) и ряд вспомогательных компонентов:
  204. .. code-block:: text
  205. sudo dnf install gcc-c++ rpm-build
  206. Создадим простейший пример ``helloworld.cpp``:
  207. .. code-block:: c++
  208. #include <iostream>
  209. int main(int argc, char *argv[], char *env[])
  210. {
  211. std::cout << "Hello, World!" << std::endl;
  212. return 0;
  213. }
  214. Скомпилируем и слинкуем его:
  215. .. code-block:: text
  216. g++ $(rpm -E %{optflags}) -fPIC helloworld.cpp -o helloworld $(rpm -E %{build_ldflags}) -lstdc++
  217. Здесь **g++** -- запускающий файл файл компилятора, **helloworld.cpp** -- файл с исходным кодом (если их несколько, то разделяются пробелом), **helloworld** -- имя результирующего бинарника, **-lstdc++** -- указание компоновщику на необходимость линковки со стандартной библиотекой C++.
  218. Корректные флаги компиляции и компоновки вставляются автоматически из соответствующих макросов RPM.
  219. Запустим результат сборки:
  220. .. code-block:: text
  221. ./helloworld
  222. Если всё сделано верно, то увидим сообщение *Hello, World!* в консоли.
  223. .. index:: gdb, debugging, segfault, segmentation fault
  224. .. _debug-application:
  225. Приложение падает. Как мне его отладить?
  226. ===========================================
  227. Для начала рекомендуется (хотя и не обязательно) установить отладочную информацию для данного пакета:
  228. .. code-block:: text
  229. sudo dnf debuginfo-install foo-bar
  230. После завершения процесса отладки символы можно снова удалить.
  231. Чтобы получить бэктрейс падения, нужно выполнить в терминале:
  232. .. code-block:: text
  233. gdb /usr/bin/foo-bar 2>&1 | tee ~/backtrace.log
  234. Далее в интерактивной консоли отладчика ввести: ``handle SIGPIPE nostop noprint`` и затем ``run``, дождаться сегфолта и выполнить ``bt full`` для получения бэктрейса. Теперь можно прописать ``quit`` для выхода из режима отладки.
  235. Далее получившийся файл ``~/backtrace.log`` следует загрузить на любой сервис размещения текстовых файлов.
  236. Также рекомендуется ещё сделать трассировку приложения до момента падения:
  237. .. code-block:: text
  238. strace -o ~/trace.log /usr/bin/foo-bar
  239. Полученный файл ``~/trace.log`` также следует загрузить на сервис.
  240. .. index:: library, shared library, so, ld preload, security, gcc, c, ld
  241. .. _ldpreload-safety:
  242. Безопасно ли использовать LD_PRELOAD для загрузки сторонних библиотек?
  243. =========================================================================
  244. Нет, это не безопасно, т.к. существует возможность создания внутри библиотек `суперглобальных конструкторов <https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html>`__, которые будут выполняться в момент присоединения библиотеки *до запуска приложения*.
  245. Создадим и скомпилируем простой пример ``example.c``:
  246. .. code-block:: c
  247. #include <stdio.h>
  248. static __attribute__((constructor (200))) void bar()
  249. {
  250. printf("%s", "Method bar() was called.\n");
  251. }
  252. static __attribute__((constructor (150))) void foo()
  253. {
  254. printf("%s", "Method foo() was called.\n");
  255. }
  256. Данный метод содержит сразу два суперглобальных конструктора с указанием приоритетов. Чем ниже приоритет, тем скорее данный метод будет исполнен.
  257. Скомпилируем и слинкуем наш пример:
  258. .. code-block:: text
  259. gcc -shared $(rpm -E %{optflags}) -fPIC example.c -o example.so $(rpm -E %{build_ldflags}) -lc
  260. Внедрим нашу библиотеку в известный доверенный процесс, например **whoami**:
  261. .. code-block:: text
  262. LD_PRELOAD=./example.so whoami
  263. Оба суперглобальных метода будут немедленно исполнены *с правами запускаемого приложения* и изменят его вывод:
  264. .. code-block:: text
  265. Method foo() was called.
  266. Method bar() was called.
  267. user1
  268. Разумеется, вместо безобидных вызовов функции printf() может находиться абсолютно любой код, в т.ч. вредоносный.
  269. .. index:: lto, optimization, linker, compilation, gcc
  270. .. _enable-lto:
  271. Как активировать LTO-оптимизации при сборке пакета?
  272. =======================================================
  273. Актуальные релизы Fedora автоматически включают `LTO оптимизации <https://gcc.gnu.org/wiki/LinkTimeOptimization>`__ для всех собираемых пакетов.
  274. Если в проекте применяются статические библиотеки (в т.ч. для внутренних целей), то экспортируем ряд :ref:`переменных окружения <env-set>` внутри секции ``%build``:
  275. .. code-block:: text
  276. export AR=%{_bindir}/gcc-ar
  277. export RANLIB=%{_bindir}/gcc-ranlib
  278. export NM=%{_bindir}/gcc-nm
  279. В случае использования системы сборки cmake, воспользуемся штатной функцией переопределения встроенных параметров:
  280. .. code-block:: text
  281. %cmake -G Ninja \
  282. -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  283. -DCMAKE_AR=%{_bindir}/gcc-ar \
  284. -DCMAKE_RANLIB=%{_bindir}/gcc-ranlib \
  285. -DCMAKE_NM=%{_bindir}/gcc-nm \
  286. ..
  287. В противном случае появится ошибка *plugin needed to handle lto object*.
  288. .. index:: lto, optimization, linker, compilation
  289. .. _disable-lto:
  290. Как запретить LTO-оптимизации при сборке пакета?
  291. ===================================================
  292. При необходимости :ref:`LTO-оптимизации <enable-lto>` допускается отключить.
  293. Определим переменную **_lto_cflags** и установим ей пустое значение:
  294. .. code-block:: text
  295. %global _lto_cflags %{nil}
  296. .. index:: gcc, c, rpm, dependencies, package
  297. .. _rpm-unneeded:
  298. Как программно вывести список установленных пакетов, от которых никто не зависит?
  299. ====================================================================================
  300. В случае если функциональность :ref:`плагина dnf-leaves <dnf-leaves>` чем-то не устраивает, напишем и скомпилируем небольшую программу на языке C, реализующую вывод списка установленных пакетов, от которых никто не зависит, средствами библиотеки **libsolv**.
  301. Установим компилятор и необходимые для сборки библиотеки:
  302. .. code-block:: text
  303. sudo dnf install gcc libsolv-devel
  304. Создадим файл ``rpm-unneeded.c`` с исходным текстом программы:
  305. .. code-block:: c
  306. #include <solv/pool.h>
  307. #include <solv/poolarch.h>
  308. #include <solv/repo_rpmdb.h>
  309. #include <solv/solver.h>
  310. int main(void)
  311. {
  312. Pool *pool;
  313. Repo *rpmdb;
  314. Solver *solver;
  315. Queue q;
  316. pool = pool_create();
  317. pool_setarch(pool, NULL);
  318. pool_set_flag(pool, POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS, 1);
  319. rpmdb = repo_create(pool, "@system");
  320. repo_add_rpmdb(rpmdb, NULL, 0);
  321. pool->installed = rpmdb;
  322. solver = solver_create(pool);
  323. solver_set_flag(solver, SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES, 1);
  324. solver_set_flag(solver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
  325. solver_set_flag(solver, SOLVER_FLAG_YUM_OBSOLETES, 1);
  326. queue_init(&q);
  327. solver_solve(solver, &q);
  328. solver_get_unneeded(solver, &q, 1);
  329. for (int i = 0; i < q.count; i++)
  330. {
  331. printf("%s\n", pool_solvid2str(pool, q.elements[i]));
  332. }
  333. solver_free(solver);
  334. queue_free(&q);
  335. pool_free(pool);
  336. return 0;
  337. }
  338. Скомпилируем и слинкуем приложение:
  339. .. code-block:: text
  340. gcc $(rpm -E %{optflags}) -fPIC rpm-unneeded.c -o rpm-unneeded $(rpm -E %{build_ldflags}) -lsolv -lsolvext
  341. Запустим приложение ``./rpm-unneeded`` и получим результат.
  342. .. index:: cpack, cmake, rpm, deb, package
  343. .. _using-cpack:
  344. Можно ли использовать cpack для сборки пакетов для GNU/Linux?
  345. ================================================================
  346. Нет, использовать cpack категорически не рекомендуется по следующим причинам:
  347. * создаёт RPM и DEB пакеты в виде архивов;
  348. * не добавляет метаданные в создаваемые пакеты;
  349. * не прописывает зависимости от библиотек и других пакетов;
  350. * не экспортирует provides;
  351. * не обрабатывает :ref:`mime-типы <file-types>`;
  352. * не добавляет обязательные скриптлеты;
  353. * не соблюдает гайдлайны дистрибутивов.
  354. Вместо cpack следует собирать :ref:`нативные пакеты <create-package>`.
  355. .. index:: library, shared library, so, ld
  356. .. _library-path:
  357. Приложение собрано со старой версией библиотеки. Как заставить его работать?
  358. ===============================================================================
  359. Если приложение было собрано со старой версией библиотеки **foo-bar**, которой уже нет в репозиториях и его требуется запустить, существует два способа:
  360. 1. :ref:`LD_PRELOAD <ldpreload-safety>` -- небезопасный -- библиотека (или библиотеки) напрямую инъектируется в процесс средствами интерпретатора динамических библиотек LD до его непосредственного запуска;
  361. 2. LD_LIBRARY_PATH -- более безопасный -- список каталогов, в которых интерпретатор динамических библиотек LD ищет соответствующие so, расширяется на указанные пользователем значения.
  362. Рассмотрим второй способ с переопределением :ref:`переменной окружения <env-set>` ``LD_LIBRARY_PATH``.
  363. Скачаем RPM пакет **foo-bar** необходимой версии из любого источника (лучшим вариантом будет конечно же репозитории старых версий Fedora), распакуем его например в ``~/lib/foo-bar`` и извлечём необходимые динамические библиотеки (.so файлы).
  364. Создадим shell-скрипт ``run-foo.sh`` для запуска бинарника:
  365. .. code-block:: text
  366. #!/usr/bin/sh
  367. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/lib/foo-bar
  368. /path/to/binary/foo
  369. Здесь **foo** -- имя бинарника, который требуется запустить, а **/path/to/binary** -- каталог, в котором он находится. В качестве разделителя путей **LD_LIBRARY_PATH** применяется двоеточие. Закрывающий слэш не ставится.
  370. Установим скрипту разрешение не запуск и запустим его:
  371. .. code-block:: text
  372. chmod +x run-foo.sh
  373. ./run-foo.sh
  374. Если всё сделано верно, приложение успешно стартует.
  375. .. index:: fedora, license, guidelines, legal
  376. .. _fedora-licenses:
  377. Проекты под какими лицензиями допускается распространять в репозиториях?
  378. ===========================================================================
  379. См. `здесь <https://fedoraproject.org/wiki/Licensing:Main>`__.
  380. .. index:: process, bash, console, pipe
  381. .. _pipe-order:
  382. В каком порядке запускаются процессы через канал (пайп)?
  383. ===========================================================
  384. Если запускается несколько процессов с передачей данных через канал (пайп; pipe), то все они стартуют одновременно, затем начинает выполняться первый, а остальные уходят в состояние ожидания ввода.
  385. .. index:: gcc, compiler, build, flags
  386. .. _build-flags:
  387. Можно ли использовать собственные флаги компиляции при сборке пакета?
  388. ========================================================================
  389. Для любых официальных сборок следует использовать исключительно стандартные для дистрибутива флаги, предоставляемые макросами ``%{optflags}`` (флаги компилятора) и ``%{build_ldflags}`` (флаги компоновки).
  390. .. index:: gcc, c++, ide, qt creator, qt
  391. .. _cxx-ide:
  392. Какую IDE использовать для разработки на C++ в Fedora?
  393. =========================================================
  394. Мы рекомендуем Qt Creator, которая одинаково хорошо подходит как для разработки на C++ (с Qt и без него), так и чистого C.
  395. Установим данную IDE, а также компилятор C++ и ряд необходимых библиотек и средств для сборки проектов:
  396. .. code-block:: text
  397. sudo dnf install gcc gcc-c++ qt-creator qt5-qtbase-devel cmake
  398. При необходимости установим также документацию Qt и готовые примеры стандартных приложений:
  399. .. code-block:: text
  400. sudo dnf install qt5-qtbase-doc qt5-qtbase-examples qt-creator-doc
  401. .. index:: c++, ide, qt creator, qt, docs
  402. .. _qtcreator-docs:
  403. В Qt Creator отсутствует документация. Как исправить?
  404. ========================================================
  405. Если Qt Creator при попытке загрузить документацию выдаёт ошибку *Error loading: qthelp://org.qt-project.qtcreator.472/doc/index.html*, выберем пункт меню **Tools** -- **Options** -- **Help** -- **Documentation** -- **Add**, затем вручную добавим следующие файлы:
  406. .. code-block:: text
  407. /usr/share/doc/qt5/qmake.qch
  408. /usr/share/doc/qt5/qtconcurrent.qch
  409. /usr/share/doc/qt5/qtcore.qch
  410. /usr/share/doc/qt5/qtdbus.qch
  411. /usr/share/doc/qt5/qtgui.qch
  412. /usr/share/doc/qt5/qtnetwork.qch
  413. /usr/share/doc/qt5/qtnetworkauth.qch
  414. /usr/share/doc/qt5/qtopengl.qch
  415. /usr/share/doc/qt5/qtplatformheaders.qch
  416. /usr/share/doc/qt5/qtprintsupport.qch
  417. /usr/share/doc/qt5/qtsql.qch
  418. /usr/share/doc/qt5/qttestlib.qch
  419. /usr/share/doc/qt5/qtwidgets.qch
  420. /usr/share/doc/qt5/qtxml.qch
  421. /usr/share/doc/qt5/qtxmlpatterns.qch
  422. /usr/share/doc/qtcreator/qtcreator.qch
  423. /usr/share/doc/qtcreator/qtcreator-dev.qch
  424. Изменения вступят в силу после перезапуска IDE.
  425. .. index:: gcc, c++, ide, qt creator, qt
  426. .. _qtcreator-kits:
  427. В Qt Creator отсутствуют компиляторы. Как исправить?
  428. =======================================================
  429. Если Qt Creator не смог самостоятельно обнаружить установленный в системе фреймворк Qt, а также компилятор, то необходимо добавить их самостоятельно.
  430. Для этого войдём в настройки IDE, затем сначала добавим компилятор GCC ``/usr/bin/gcc``, а затем тулчейн Qt -- ``/usr/bin/qmake-qt5``. После этого на вкладке **Kits** создадим новый набор из данных компонентов.
  431. Сохраним изменения в настройках и добавим созданный Kit к своему проекту.
  432. .. index:: python, ide, pycharm
  433. .. _python-ide:
  434. Какую IDE использовать для разработки на Python в Fedora?
  435. ============================================================
  436. Мы рекомендуем PyCharm Community Edition.
  437. Подключим COPR репозиторий:
  438. .. code-block:: text
  439. sudo dnf copr enable phracek/PyCharm
  440. Установим IDE:
  441. .. code-block:: text
  442. sudo dnf install pycharm-community
  443. При необходимости установим также набор популярных плагинов:
  444. .. code-block:: text
  445. sudo dnf install pycharm-community-plugins
  446. .. index:: firmware, binwalk
  447. .. _fw-image:
  448. Как получить информацию о содержимом образа бинарной прошивки?
  449. =================================================================
  450. Для работы с образами прошивок можно использовать утилиту **binwalk**. Установим её:
  451. .. code-block:: text
  452. sudo dnf install binwalk
  453. Произведём анализ файла и получим результат:
  454. .. code-block:: text
  455. binwalk foo-bar.bin
  456. .. index:: rpmbuild, spec, sources
  457. .. _spectool:
  458. Как автоматически скачать исходники, прописанные в SPEC-файле?
  459. =================================================================
  460. Установим необходимые утилиты:
  461. .. code-block:: text
  462. sudo dnf install rpm-build rpmdevtools
  463. Создадим базовую иерархию каталогов для rpmbuild:
  464. .. code-block:: text
  465. rpmdev-setuptree
  466. Скачаем исходники, прописанные в SPEC-файле **foo-bar.spec**:
  467. .. code-block:: text
  468. spectool -g -R foo-bar.spec
  469. .. index:: spec, version, tag
  470. .. _spec-auto:
  471. Как автоматически инкрементировать релиз в SPEC-файле?
  472. ==========================================================
  473. Установим необходимый для работы пакет:
  474. .. code-block:: text
  475. sudo dnf install rpmdevtools
  476. Инкрементируем релиз SPEC-файла (директива *Release*) с автоматическим созданием новой строки в *%changelog*:
  477. .. code-block:: text
  478. rpmdev-bumpspec -c "Updated to latest snapshot."
  479. .. index:: git, pull, bash, find
  480. .. _git-multi:
  481. Как загрузить изменения во всех вложенных репозиториях из данного каталога?
  482. ==============================================================================
  483. Если Git репозитории были клонированы в общий каталог ``~/foo-bar``, то загрузим изменения в каждом из вложенных проектов при помощи **find** и **bash**:
  484. .. code-block:: text
  485. find ~/foo-bar -maxdepth 1 ! -path . -type d -exec bash -c "pushd '{}' ; git pull ; popd" \;
  486. .. index:: git, checkout, branch
  487. .. _git-empty:
  488. Как создать пустую ветку в Git без общей истории?
  489. ====================================================
  490. Создадим новую пустую ветку **foo-bar** от текущего HEAD:
  491. .. code-block:: text
  492. git checkout --orphan foo-bar
  493. Создадим удалим всё проиндексированное содержимое данной ветки:
  494. .. code-block:: text
  495. git reset --hard
  496. .. index:: mock, transfer, build, move
  497. .. _mock-move:
  498. Можно ли перенести каталоги сборки и кэшей mock на другой диск?
  499. ==================================================================
  500. Система автоматической :ref:`сборки пакетов mock <build-package>` занимает огромное количество места в корневом разделе, поэтому многие мейнтейнеры хотели бы перенести её на другой диск. Штатно это сделать не представляется возможным ибо значения каталогов по умолчанию ``/var/cache/mock`` и ``/var/lib/mock`` жёстко прописаны внутри приложения и не подлежат изменению со стороны пользователя, поэтому воспользуемся символическими ссылками.
  501. Создадим на другом накопителе (его файловая система должна поддерживать права доступа Unix) базовый каталог для mock:
  502. .. code-block:: text
  503. cd /media/foo-bar
  504. sudo mkdir mock
  505. sudo chown root:mock mock
  506. sudo chmod 4775 mock
  507. Переместим содержимое текущих рабочих каталогов mock:
  508. .. code-block:: text
  509. sudo mv /var/cache/mock /media/foo-bar/mock/cache
  510. sudo mv /var/lib/mock /media/foo-bar/mock/lib
  511. Создадим символические ссылки на старом месте:
  512. .. code-block:: text
  513. sudo ln -s /media/foo-bar/mock/cache /var/cache/mock
  514. sudo ln -s /media/foo-bar/mock/lib /var/lib/mock
  515. Зададим контекст :ref:`SELinux <selinux>` по умолчанию для нового хранилища:
  516. .. code-block:: text
  517. sudo semanage fcontext -a -t mock_cache_t "/media/foo-bar/mock/cache(/.*)?"
  518. sudo semanage fcontext -a -t mock_var_lib_t "/media/foo-bar/mock/lib(/.*)?"
  519. Сбросим контекст SELinux для всех рабочих каталогов:
  520. .. code-block:: text
  521. sudo restorecon -Rv /var/cache/mock
  522. sudo restorecon -Rv /var/lib/mock
  523. sudo restorecon -Rv /media/foo-bar/mock/cache
  524. sudo restorecon -Rv /media/foo-bar/mock/lib
  525. Здесь **/media/foo-bar** -- точка монтирования нового накопителя, на котором будут располагаться кэши mock.
  526. Внимание! Раздел назначения должен использовать флаги монтирования по умолчанию ``defaults``. В противном случае не будут выполнены скриптлеты и сборка не завершится успешно.
  527. .. index:: git, bash, branch
  528. .. _bash-git-branch:
  529. Как включить отображение текущей ветки Git в Bash?
  530. =====================================================
  531. Модуль интеграции с Bash входит в состав пакета Git. Добавим в :ref:`приветствие Bash <bash-shell>` следующую строку:
  532. .. code-block:: text
  533. export PS1='[\u@\h \W$(declare -F __git_ps1 &>/dev/null && __git_ps1 " (%s)")]\$ '
  534. В качестве опциональных параметров поддерживаются ``GIT_PS1_SHOWDIRTYSTATE`` (показывать наличие незакреплённых изменений внутри каталога) и ``GIT_PS1_SHOWUNTRACKEDFILES`` (учитывать, либо нет не отслеживаемые системой контроля версий файлы):
  535. .. code-block:: text
  536. export GIT_PS1_SHOWDIRTYSTATE=true
  537. export GIT_PS1_SHOWUNTRACKEDFILES=true
  538. Изменения вступят в силу при следующем запуске оболочки.
  539. .. index:: patch, diff, unified, file
  540. .. _patch-file:
  541. Как создать унифицированный патч изменений между двумя файлами?
  542. ==================================================================
  543. Для создания патча нам необходимо две версии файла: оригинальная и текущая.
  544. Создадим унифицрованный патч с разностью между файлами **foo-bar.txt.orig** (оригинальный) и **foo-bar.txt** (текущий):
  545. .. code-block:: text
  546. diff -Naur foo-bar.txt.orig foo-bar.txt > result.patch
  547. Результат будет сохранён в файле **result.patch**.
  548. .. index:: patch, diff, unified, file, directory
  549. .. _patch-directory:
  550. Как создать унифицированный патч изменений между двумя каталогами?
  551. =====================================================================
  552. Создадим унифицрованный патч с разностью между каталогами **foo-bar_orig** (оригинальный) и **foo-bar** (текущий):
  553. .. code-block:: text
  554. diff -Naur foo-bar_orig foo-bar > result.patch
  555. Результат будет сохранён в файле **result.patch**.
  556. .. index:: patch, diff, unified, apply
  557. .. _patch-apply:
  558. Как применить унифицированный патч?
  559. ======================================
  560. Проверим возможность применения патча **foo-bar.patch** без внесения каких-либо изменений:
  561. .. code-block:: text
  562. patch -p0 --dry-run -i foo-bar.patch
  563. Применим патч:
  564. .. code-block:: text
  565. patch -p0 -i foo-bar.patch
  566. Параметром ``-p`` задаётся количество каталогов, которые будут отброшены при поиске файлов, указанных внутри унифицированного патча.
  567. .. index:: patch, diff, unified, revert
  568. .. _patch-revert:
  569. Как откатить наложенный унифицированный патч?
  570. ================================================
  571. Проверим возможность отката патча **foo-bar.patch** без внесения каких-либо изменений:
  572. .. code-block:: text
  573. patch -p0 -R --dry-run -i foo-bar.patch
  574. Откатитим внесённые изменения:
  575. .. code-block:: text
  576. patch -p0 -R -i foo-bar.patch
  577. Параметром ``-p`` задаётся количество каталогов, которые будут отброшены при поиске файлов, указанных внутри унифицированного патча.
  578. .. index:: patch, diff, unified, git, commit
  579. .. _patch-git-create:
  580. Как создать унифицированный патч между двумя коммитами?
  581. ==========================================================
  582. Создадим патч между двумя коммитами **AAA** и **BBB**:
  583. .. code-block:: text
  584. git diff AAA BBB > result.patch
  585. Создадим патч коммитом **CCC** и текущим рабочей рабочей версией:
  586. .. code-block:: text
  587. git diff CCC > result.patch
  588. Здесь **AAA**, **BBB** и **CCC** -- хеши коммитов в Git репозитории.
  589. .. index:: patch, diff, unified, git, commit, export
  590. .. _patch-git-export:
  591. Как экспортировать Git коммит для отправки по электронной почте?
  592. ====================================================================
  593. В Git имеется встроенное средство экспорта коммитов для их дальнейшей отправки по электронной почте.
  594. Экспортируем один коммит:
  595. .. code-block:: text
  596. git format-patch -1
  597. Экспортируем сразу 3 коммита:
  598. .. code-block:: text
  599. git format-patch -3
  600. .. index:: fedora, infrastructure, authentication, kerberos, kinit
  601. .. _fedora-login:
  602. Как авторизоваться в инфраструктуре Fedora?
  603. ==============================================
  604. Для авторизации мы должны использовать вход в домен :ref:`посредством Kerberos <kerberos-auth>`:
  605. .. code-block:: text
  606. kinit foo-bar@FEDORAPROJECT.ORG
  607. Здесь **foo-bar** -- логин в FAS. Имя домена должно быть указано строго в верхнем регистре.
  608. Также для некоторых операций необходимо загрузить :ref:`публичный ключ <ssh-keygen>` SSH в `FAS аккаунт <https://admin.fedoraproject.org/accounts>`__.
  609. .. index:: fedora, infrastructure, authentication, kerberos, kinit, 2fa, otp
  610. .. _fedora-login-2fa:
  611. Как авторизоваться в инфраструктуре Fedora с поддержкой 2FA?
  612. ================================================================
  613. Для авторизации в инфраструктуре Fedora с поддержкой двухфакторной аутентификации :ref:`стандартный вход <fedora-login>` :ref:`посредством Kerberos <kerberos-auth>` работать не будет из-за возникновения ошибки *kinit: Pre-authentication failed: Invalid argument while getting initial credentials*, поэтому мы должны использовать альтернативный способ.
  614. Сгенерируем актуальный файл Kerberos Credentials Cache:
  615. .. code-block:: text
  616. kinit -n @FEDORAPROJECT.ORG -c FILE:$HOME/.cache/fedora-armor.ccache
  617. Авторизуемся в домене с указанием KCC-файла:
  618. .. code-block:: text
  619. kinit -T FILE:$HOME/.cache/fedora-armor.ccache foo-bar@FEDORAPROJECT.ORG
  620. Когда сервер запросит ввод *Enter OTP Token Value:*, укажем свой пароль и текущий код из OTP-аутентификатора по схеме **парольКОД** без пробелов и прочих знаков.
  621. Здесь **foo-bar** -- логин в FAS. Имя домена должно быть указано строго в верхнем регистре.
  622. .. index:: fedora, package, request, fedpkg
  623. .. _package-request:
  624. Как запросить создание пакета в репозитории?
  625. ===============================================
  626. Сразу после завершения :ref:`процедуры package review <becoming-maintainer>`, мейнтейнер должен запросить создание пакета в репозиториях Fedora.
  627. Установим утилиту **fedpkg**
  628. .. code-block:: text
  629. sudo dnf install fedpkg
  630. Получим `новый токен <https://pagure.io/settings>`__ в Pagure, который будет использоваться утилитой fedpkg для создания заявки. Для этого перейдём в раздел **Settings** -- **API Keys** -- **Create new key**, затем в списке доступных разрешений (**ACLs**) установим флажок только около опции **Create a new ticket** и нажмём кнопку **Add**.
  631. Создадим файл конфигурации fedpkg:
  632. .. code-block:: text
  633. mkdir -p ~/.config/rpkg
  634. touch ~/.config/rpkg/fedpkg.conf
  635. Загрузим созданный файл ``~/.config/rpkg/fedpkg.conf`` в любом текстовом редакторе и добавим:
  636. .. code-block:: ini
  637. [fedpkg.pagure]
  638. token = XXXXXXXXXX
  639. Здесь **XXXXXXXXXX** -- полученный от Pagure токен.
  640. Запросим создание нового пакета в репозитории, а также веток для всех поддерживаемых релизов Fedora:
  641. .. code-block:: text
  642. fedpkg request-repo --namespace rpms --monitor monitoring foo-bar YYYYYY
  643. fedpkg request-branch --namespace rpms --repo foo-bar --all-releases
  644. Здесь **foo-bar** -- имя пакета, а **YYYYYY** -- номер заявки в Red Hat BugZilla с успешно завершённым package review.
  645. .. index:: fedora, package, upload, fedpkg
  646. .. _fedpkg-upload:
  647. Как загрузить файлы с исходными кодами пакета в систему сборки?
  648. ==================================================================
  649. После :ref:`создания пакета <package-request>` осуществим :ref:`вход в инфраструктуру <fedora-login>` Fedora, затем скачаем репозиторий пакета из Fedora SCM, содержащий SPEC файл и набор патчей (при необходимости), а также прочие службные файлы:
  650. .. code-block:: text
  651. fedpkg clone foo-bar
  652. cd foo-bar
  653. Самым простым способом загрузки является импорт готового SRPM файла, поэтому выполним именно эту процедуру:
  654. .. code-block:: text
  655. fedpkg switch-branch master
  656. fedpkg import /путь/к/foo-bar-1.0-1.fc38.src.rpm
  657. Проверим внесённые изменения и если всё верно, жмём **Q** для выхода. Зафиксируем наши изменения:
  658. .. code-block:: text
  659. git commit -m "Initial import."
  660. При необходимости внесём изменения и в ветки поддерживаемых релизов Fedora:
  661. .. code-block:: text
  662. fedpkg switch-branch f38
  663. git merge master
  664. Отправим изменения на сервер:
  665. .. code-block:: text
  666. git push
  667. .. index:: fedora, package, build, fedpkg
  668. .. _fedpkg-build:
  669. Как осуществить сборку пакета для публикации в репозиториях?
  670. ===============================================================
  671. После :ref:`загрузки файлов с исходными кодами <fedpkg-upload>` пакета, осуществим :ref:`вход в инфраструктуру <fedora-login>` Fedora, а затем приступим к непосредственно сборке в :ref:`Fedora Koji <koji-about>`:
  672. .. code-block:: text
  673. cd foo-bar
  674. fedpkg switch-branch master
  675. fedpkg build
  676. При необходимости соберём и для других поддерживаемых релизов Fedora:
  677. .. code-block:: text
  678. fedpkg switch-branch f38
  679. fedpkg build
  680. .. index:: fedora, package, build, fedpkg, scratch
  681. .. _fedpkg-scratch:
  682. Как осуществить тестовую сборку пакета для определённой архитектуры?
  683. =======================================================================
  684. Осуществим :ref:`вход в инфраструктуру <fedora-login>` Fedora.
  685. Выполним стандартную scratch-сборку для всех поддерживаемых данным выпуском архитектур:
  686. .. code-block:: text
  687. cd foo-bar
  688. fedpkg switch-branch master
  689. fedpkg build --scratch
  690. Выполним scratch-сборку только для указанных архитектур:
  691. .. code-block:: text
  692. cd foo-bar
  693. fedpkg switch-branch master
  694. fedpkg scratch-build --arches x86_64 aarch64
  695. .. index:: fedora, package, release, publish
  696. .. _fedpkg-publish:
  697. Как выложить собранный пакет в репозитории?
  698. ==============================================
  699. По окончании :ref:`сборки <fedpkg-build>` мы можем воспользоваться `Fedora Bodhi <https://bodhi.fedoraproject.org/>`__ и `выложить обновление <https://bodhi.fedoraproject.org/updates/new>`__ в репозитории.
  700. Сначала все обновления попадают в тестовые репозитории Fedora (*updates-testing*) и лишь после получения положительной кармы от других участников сообщества (уровень задаётся мейнтейнером, но не может быть меньше 1), либо по истечении 7 дней, оно может попасть в стабильные (*updates*) и будет доставлено конечным пользователям.
  701. Заполним стандартную, хорошо документированную форму, затем нажмём кнопку **Submit**.
  702. .. index:: repository, copr, overlay
  703. .. _copr-legal:
  704. Что разрешается хранить в COPR репозиториях?
  705. ================================================
  706. В :ref:`COPR <copr>` разрешается распространять всё то же, что и в :ref:`основных репозиториях <fedora-licenses>` Fedora. Сборка и публикация запатентованного и проприетарного программного обеспечения в пользовательских оверлеях не допускается.
  707. .. index:: shared library, vdso, so, ldd
  708. .. _linux-vdso:
  709. Что такое linux-vdso.so.1 и почему она загружена в каждый процесс?
  710. =====================================================================
  711. Библиотека **linux-vdso.so.1** не является обычной динамической библиотекой. Это виртуальный динамически разделяемый объект (VDSO), который отображается на адресное пространство каждого запущенного процесса ядром Linux и представляет собой интерфейс для осуществления быстрых системных вызовов.
  712. Данный объект можно обнаружить в :ref:`выводе ldd <linux-ldd>` для любого бинарного ELF-файла, но без прямого пути, т.к. он не является реальным файлом.
  713. .. index:: shared library, elf, so, binary, ldd, ld
  714. .. _linux-ldd:
  715. Как определить зависимости конкретного бинарника?
  716. ====================================================
  717. Для определения зависимостей любых ELF-файлов, воспользуемся утилитой **ldd**.
  718. Определим зависимости динамически разделяемой библиотеки:
  719. .. code-block:: text
  720. ldd /path/to/shared/library.so.1
  721. Определим зависимости исполняемого файла:
  722. .. code-block:: text
  723. ldd /path/to/application
  724. Если библиотека была найдена в системе, наряду с именем будет указан абсолютный путь к её файлу на диске, а также адрес предполагаемой загрузки.
  725. Исключение составляют :ref:`виртуальные объекты <linux-vdso>`, для которых будет указан лишь адрес, без пути.
  726. .. index:: git, upstream, remote, origin
  727. .. _git-switch-remote:
  728. Как изменить адрес Git репозитория после его переезда?
  729. ========================================================
  730. Получим список подключённых удалённых ресурсов текущего Git репозитория:
  731. .. code-block:: text
  732. git remote -v
  733. Изменим апстрим для ``origin``:
  734. .. code-block:: text
  735. git remote set-url origin https://github.com/foo-bar/new_repo.git
  736. После этого команды Git, отвечающие за работу с удалёнными ресурсами, ``git pull``, ``git fetch``, ``git push``, начнут использовать новый апстрим.
  737. .. index:: rpmbuild, move
  738. .. _rpmbuild-move:
  739. Можно ли перенести стандартный каталог сборки rpmbuild?
  740. ==========================================================
  741. Да, это возможно. Откроем файл ``~/.rpmmacros`` в любом текстовом редаторе, найдём строку:
  742. .. code-block:: text
  743. %_topdir %(echo $HOME)/rpmbuild
  744. Заменим её на следующую:
  745. .. code-block:: text
  746. %_topdir /media/foo-bar/rpmbuild
  747. Здесь **/media/foo-bar** -- новый каталог размещения базовой иерархии rpmbuild.
  748. Сохраним изменения, которые вступят в силу немеденно.
  749. .. index:: license, checker, copyright
  750. .. _license-check:
  751. Как определить какие лицензии используются в проекте?
  752. =========================================================
  753. Установим утилиту **licensecheck**:
  754. .. code-block:: text
  755. sudo dnf install licensecheck
  756. Запустим проверку проекта:
  757. .. code-block:: text
  758. licensecheck --recursive --merge-licenses --no-verbose /path/to/foo-bar > ~/results.txt
  759. Здесь **/path/to/foo-bar** -- путь к распакованным исходникам проекта, а **~/results.txt** -- имя файла, в котором будут сохранены результаты проверки.
  760. .. index:: gdb, debugging, backtrace, coredump
  761. .. _gdb-coredump:
  762. Как загрузить в gdb отладчик coredump падения?
  763. =================================================
  764. GDB позволяет не только отлаживать приложения напрямую, но и загружать :ref:`coredump падений <codedump-info>`.
  765. Установим утилиту **lz4** для распаковки сжатых файлов с дампами:
  766. .. code-block:: text
  767. sudo dnf install lz4
  768. Распакуем coredump:
  769. .. code-block:: text
  770. unlz4 /path/to/coredump.lz4
  771. Воспользуемся :ref:`описанным выше <debug-application>` способом получения backtrace падения, но слегка модифицируем команду запуска отладчика:
  772. .. code-block:: text
  773. gdb /usr/bin/foo-bar /path/to/coredump 2>&1 | tee ~/backtrace.log
  774. Здесь **/usr/bin/foo-bar** -- путь к отлаживаемому приложению, **/path/to/coredump** -- coredump падения (версия приложения и дампа, снятого с него, должны обязательно совпадать), а **~/backtrace.log** -- файл, в котором будет сохранён трейс падения.
  775. .. index:: rpmbuild, cmake, clang, cpp, compilation
  776. .. _clang-fedora:
  777. Как собрать пакет с использованием компилятора Clang в Fedora?
  778. ===================================================================
  779. Определим переменную **toolchain** и установим ей значение **clang**:
  780. .. code-block:: text
  781. %global toolchain clang
  782. Если в проекте применяются статические библиотеки (в т.ч. для внутренних целей), то экспортируем ряд :ref:`переменных окружения <env-set>` внутри секции ``%build``:
  783. .. code-block:: text
  784. export AR=%{_bindir}/llvm-ar
  785. export RANLIB=%{_bindir}/llvm-ranlib
  786. export LINKER=%{_bindir}/llvm-ld
  787. export OBJDUMP=%{_bindir}/llvm-objdump
  788. export NM=%{_bindir}/llvm-nm
  789. В случае использования системы сборки cmake, воспользуемся штатной функцией переопределения встроенных параметров:
  790. .. code-block:: text
  791. %cmake -G Ninja \
  792. -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  793. -DCMAKE_C_COMPILER=%{_bindir}/clang \
  794. -DCMAKE_CXX_COMPILER=%{_bindir}/clang++ \
  795. -DCMAKE_AR=%{_bindir}/llvm-ar \
  796. -DCMAKE_RANLIB=%{_bindir}/llvm-ranlib \
  797. -DCMAKE_LINKER=%{_bindir}/llvm-ld \
  798. -DCMAKE_OBJDUMP=%{_bindir}/llvm-objdump \
  799. -DCMAKE_NM=%{_bindir}/llvm-nm \
  800. ..
  801. Следует :ref:`быть осторожным <qt-clang-lto>` при сборке Qt-приложений данным компилятором при использовании :ref:`LTO-оптимизаций <enable-lto>`.
  802. .. index:: clang, lto, optimization, linker, cpp
  803. .. _qt-clang-lto:
  804. Qt-приложение, собранное Clang с LTO не запускается. Что делать?
  805. =====================================================================
  806. Невозможность запуска Qt-приложений, собранных компилятором Clang с включёнными :ref:`LTO-оптимизациями <enable-lto>` -- это `известная проблема <https://bugreports.qt.io/browse/QTBUG-61710>`__, которая в настоящее время не решена.
  807. Для её решения необходимо либо отказаться от использования компилятора Clang и вернуться на GCC, либо отключить LTO-оптимизации.
  808. .. index:: linker, dependencies, ldd, library
  809. .. _using-ldd:
  810. Безопасно ли использовать LDD для проверки зависимостей бинарника?
  811. =====================================================================
  812. Нет, т.к. утилита :ref:`ldd <linux-ldd>` лишь изменяет ряд :ref:`переменных окружения <env-set>`, а затем запускает бинарник, чтобы определить все динамически загружаемые библиотеки, от которых он зависит.
  813. Внедоносный код сможет легко перехватить управление и начать выполнять свои задачи в пределах имеющихся полномочий.
  814. .. index:: git, remove, remote, tag
  815. .. _git-remove-tag:
  816. Как удалить тег во внешнем Git репозитории?
  817. ================================================
  818. Удалим локальный тег **1.0.0**:
  819. .. code-block:: text
  820. git tag -d v1.0.0
  821. Удалим удалённый тег **1.0.0** из удалённого Git репозитория:
  822. .. code-block:: text
  823. git push --delete origin v1.0.0
  824. .. index:: git, remove, remote, branch
  825. .. _git-remove-branch:
  826. Как удалить ветку во внешнем Git репозитории?
  827. =================================================
  828. Удалим удалённую ветку **foo-bar** из удалённого Git репозитория:
  829. .. code-block:: text
  830. git push --delete origin foo-bar
  831. .. index:: git, remove, tag, remote
  832. .. _git-remove-all-tags:
  833. Как удалить все теги (локальные и удалённые) в Git репозитории?
  834. ===================================================================
  835. Удалим все теги из внешнего Git репозитория:
  836. .. code-block:: text
  837. git push origin --delete $(git tag -l)
  838. Удалим все оставшиеся локальные теги:
  839. .. code-block:: text
  840. git tag -d $(git tag -l)
  841. .. index:: gcc, regression, bug report, report, bug, koji, uue, uuencode, uudecode
  842. .. _koji-extract-data:
  843. Как извлечь из Koji какие-либо данные для отправки баг-репорта?
  844. ===================================================================
  845. Т.к. :ref:`Koji <koji-about>` автоматически очищает каталог сборки по её завершении с любым статусом, единственная возможность извлечь полезные данные -- это закодировать их в формате `Uuencode <https://ru.wikipedia.org/wiki/UUE>`__ и вывести в общий журнал сборки.
  846. Добавим в :ref:`SPEC-файл пакета <create-package>` зависимость от **sharutils**:
  847. .. code-block:: text
  848. BuildRequires: sharutils
  849. Немного доработаем команду сборки (например ``%make_build``), включив в неё упаковку всех необработанных preprocessed sources в архив с кодированием в UUE, при возникновении ошибки:
  850. .. code-block:: text
  851. %make_build || (tar cf - /tmp/cc*.out | bzip2 -9 | uuencode cc.tar.bz2)
  852. Найдём в журнале ``build.log`` блок вида:
  853. .. code-block:: text
  854. begin 644 cc.tar.bz2
  855. ...
  856. ...
  857. end
  858. Извлечём и сохраним его в файл ``foo-bar.uue``.
  859. Установим утилиту **uudecode**:
  860. .. code-block:: text
  861. sudo dnf install sharutils
  862. Декодируем полезную нагрузку:
  863. .. code-block:: text
  864. uudecode foo-bar.uue
  865. Загрузим полученный архив в :ref:`баг-репорт <bug-report>`.
  866. .. index:: rpm, rpmbuild, version, package, compare
  867. .. _compare-versions:
  868. Как определить, какая из двух версий больше?
  869. ================================================
  870. Для проверки версий воспользуемся утилитой **rpmdev-vercmp**, входящей в состав пакета **rpmdevtools**.
  871. Установим его:
  872. .. code-block:: text
  873. sudo dnf install rpmdevtools
  874. Произведём проверку между **X** и **Y**:
  875. .. code-block:: text
  876. rpmdev-vercmp X Y
  877. Данную утилиту также можно использовать в различных скриптах, исходя из возвращаемых ею кодов завершения:
  878. * **0** -- версии равны;
  879. * **11** -- версия **X** больше, чем **Y**;
  880. * **12** -- версия **X** меньше, чем **Y**.
  881. .. index:: mock, cleanup, cache
  882. .. _mock-cleanup:
  883. Как очистить все кэши mock?
  884. ================================
  885. Выполним очистку сборочного каталога :ref:`mock <build-package>` для цели по умолчанию:
  886. .. code-block:: text
  887. mock --scrub=all
  888. Выполним очистку сборочного каталога, а также кэша загруженных пакетов mock для **fedora-rawhide-x86_64**:
  889. .. code-block:: text
  890. mock -r fedora-rawhide-x86_64 --scrub=all
  891. .. index:: root, permissions, library, shared library, so, ld preload, ld
  892. .. _root-check-bypass:
  893. Как обойти проверку приложением наличия прав суперпользователя?
  894. ===================================================================
  895. См. `здесь <https://www.easycoding.org/2021/08/31/obxodim-proverku-na-nalichie-prav-superpolzovatelya.html>`__.
  896. .. index:: rpm, architecture, rpmbuild, excludearch, package
  897. .. _rpmbuild-exclude-arch:
  898. Как исключить определённую архитектуру из сборки пакета?
  899. ============================================================
  900. Для исключения указанных архитектур из сборки, добавим в SPEC-файл директиву ``ExcludeArch``.
  901. В качестве примера исключим 32-битные ARM и x86:
  902. .. code-block:: text
  903. ExcludeArch: %{arm} %{ix86}
  904. .. index:: rpm, architecture, rpmbuild, exclusivearch, package
  905. .. _rpmbuild-exclusive-arch:
  906. Как собрать пакет только для определённой архитектуры?
  907. =========================================================
  908. Для выбора конкретных архитектур сборки, добавим в SPEC-файл директиву ``ExclusiveArch``.
  909. В качестве примера включим только 64-битные ARM и x86:
  910. .. code-block:: text
  911. ExcludeArch: aarch64 x86_64
  912. .. index:: rpm, rpmbuild, exclude, package, library, provides, filter
  913. .. _rpmbuild-filter-provides:
  914. Как исключить библиотеку из списка предоставляемых пакетом?
  915. ===============================================================
  916. Исключим все файлы, расположенные в каталоге **%{_libdir}/%{name}**, из автоматически генерируемого списка предоставляемых пакетом:
  917. .. code-block:: text
  918. %global __provides_exclude_from %{_libdir}/%{name}/.*
  919. При необходимости указать несколько каталогов, разделим их стандартным для `регулярного выражения PCRE <https://ru.wikipedia.org/wiki/PCRE>`__ способом:
  920. .. code-block:: text
  921. %global __provides_exclude_from %{_libdir}/%{name}/foo/.*|%{_libdir}/%{name}/bar/.*
  922. .. index:: rpm, rpmbuild, exclude, package, library, requires, filter
  923. .. _rpmbuild-filter-requires:
  924. Как исключить библиотеку из списка зависимостей пакета?
  925. ===========================================================
  926. Отключим автоматическое построение списка зависимостей пакета для ELF-объектов, расположенных в каталоге **%{_libdir}/%{name}**:
  927. .. code-block:: text
  928. %global __requires_exclude_from %{_libdir}/%{name}/.*
  929. При необходимости указать несколько каталогов, разделим их стандартным для `регулярного выражения PCRE <https://ru.wikipedia.org/wiki/PCRE>`__ способом:
  930. .. code-block:: text
  931. %global __requires_exclude_from %{_libdir}/%{name}/foo/.*|%{_libdir}/%{name}/bar/.*
  932. .. index:: rpm, rpmbuild, side-tag, koji, fedpkg, build, bodhi
  933. .. _koji-side-tags:
  934. Как собрать несколько зависящих друг от друга пакетов?
  935. ==========================================================
  936. Если раньше приходилось использовать механизм "build overrides", позволяющий вручную переопределять пакеты в сборочном репозитории, то сейчас рекомендуется для сборки двух и более пакетов применять side-теги, т.к. это более простой и безопасный способ, не создающий конфликтов и проблем с зависимостями.
  937. Мейнтейнер может запросить создание произвольного количества side-тегов и производить сборку в них по своему усмотрению.
  938. Запросим новый side-tag для F38:
  939. .. code-block:: text
  940. fedpkg request-side-tag --base-tag f38-build
  941. В выводе **fedpkg** сообщит нам уникальный идентификатор созданного репозитория, например *f38-build-side-12345*.
  942. Ждём его создания и готовности к работе:
  943. .. code-block:: text
  944. koji wait-repo f38-build-side-XXXXX
  945. Произведём сборку первого пакета **foo**:
  946. .. code-block:: text
  947. fedpkg build --target=f38-build-side-XXXXX
  948. Ожидаем его появления в теге:
  949. .. code-block:: text
  950. koji wait-repo --build=foo-1.0.0-1.fc38 f38-build-side-XXXXX
  951. Собираем все остальные пакеты тем же способом.
  952. По окончании перейдём в `Bodhi <https://bodhi.fedoraproject.org/>`__ и выберем **Create New Update** -- **Use Side Tag** для выгрузки его в основной репозиторий.
  953. .. index:: rpm, rpmbuild, koji, fedpkg, build, chain, rawhide
  954. .. _koji-chain-build:
  955. Как собрать несколько зависящих друг от друга пакетов по цепочке?
  956. ====================================================================
  957. Существует и более удобный способ -- сборки по цепочке (chain builds), доступный для :ref:`Fedora Rawhide <using-rawhide>`, либо заранее созданных :ref:`side-тегов <koji-side-tags>`.
  958. Мейнтейнер может указать произвольное количество пакетов в пределах одного задания. Koji выполнит задачу строго в указанном порядке.
  959. Внимание! Каталоги с исходниками всех участников группы должны находиться на одном уровне файловой иерархии. При сборке для side-tag, перед запуском процесса необходимо зайти в каталог каждого пакета из цепочки и при помощи команды ``fedpkg switch-branch f38`` переключиться на нужную ветку.
  960. Перейдём в каталог последнего пакета в цепочке (в данном примере это **bar**) и запустим процесс.
  961. Rawhide:
  962. .. code-block:: text
  963. cd bar
  964. fedpkg switch-branch rawhide
  965. fedpkg chain-build libfoo1 libfoo2
  966. Выделенный тег:
  967. .. code-block:: text
  968. cd bar
  969. fedpkg switch-branch f38
  970. fedpkg chain-build --target f38-build-side-XXXXX libfoo1 libfoo2
  971. Данное действие создаст следующую цепочку *libfoo1* -> *libfoo2* -> *bar*.
  972. В случае если некоторые пакеты допустимо собирать параллельно, поделим задание на подгруппы (разделителем является двоеточие).
  973. Rawhide:
  974. .. code-block:: text
  975. cd bar
  976. fedpkg switch-branch rawhide
  977. fedpkg chain-build libfoo1 : libfoo2 libfoo3 :
  978. Выделенный тег:
  979. .. code-block:: text
  980. cd bar
  981. fedpkg switch-branch f38
  982. fedpkg chain-build --target f38-build-side-XXXXX libfoo1 : libfoo2 libfoo3 :
  983. В результате появится цепочка *libfoo1* -> *libfoo2* + *libfoo3* -> *bar*.
  984. .. index:: rpm, api, abi, diff, rpmsodiff
  985. .. _rpm-check-abi:
  986. Как определить наличие изменений ABI между разными версиями пакета?
  987. ======================================================================
  988. Воспользуемся утилитой **rpmsodiff**, входящей в состав пакета **rpmdevtools**.
  989. Установим его:
  990. .. code-block:: text
  991. sudo dnf install rpmdevtools
  992. Выполним проверку `ABI-совместимости <https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9>`__ между версиями *1.1.0* и *1.0.0* пакета *foo-bar*:
  993. .. code-block:: text
  994. rpmsodiff ./foo-bar-1.1.0-1.fc38.x86_64.rpm ./foo-bar-1.0.0-1.fc38.x86_64.rpm
  995. .. index:: git, commit, cherry-pick, backport, tac, xargs
  996. .. _git-backport-commits:
  997. Как переместить набор коммитов из одной ветки Git-репозитория в другую?
  998. ==========================================================================
  999. При необходимости перенести несколько коммитов из одной ветки в другую (например, сделаны некоторые правки в ветке, которые не относятся к разрабатываемой функциональности), мы можем запросить список из N коммитов первой ветки, и выполнить **cherry-pick** во второй.
  1000. Создадим отдельный рабочий каталог ``/tmp/bar`` для ветки **bar** и перейдём в него:
  1001. .. code-block:: text
  1002. git worktree add /tmp/bar bar
  1003. pushd /tmp/bar
  1004. Произведём перемещение **10** коммитов из ветки **foo** в **bar**. Объединим данные действия в одну конвейерную команду:
  1005. .. code-block:: text
  1006. git log --format=%h -10 foo | tac | xargs git cherry-pick
  1007. При этом будет запрошен список хешей коммитов из указанной ветки, затем он будет отсортирован в обратном порядке при помощи утилиты **tac**, и результат построчно передан **git cherry-pick**, которая впоследствие и применит каждый коммит в нужную ветку.
  1008. Вернёмся назад в основной каталог Git-репозитория и произведём очистку:
  1009. .. code-block:: text
  1010. popd
  1011. git worktree remove /tmp/bar
  1012. .. index:: rpmbuild, patch, spec
  1013. .. _rpmbuild-conditional-patch:
  1014. Как применять патч при сборке пакета только при выполнении условия?
  1015. ======================================================================
  1016. Т.к. согласно гайдлайнам Fedora, все SRPM пакеты должны быть готовы к пересборке для любой поддерживаемой версии дистрибутива, мы не можем использовать условные операторы для директив *Source* и *Patch*, поэтому сначала заменим ``%autosetup`` на ``%setup -q``, а затем воспользуемся одним из описанных далее способов.
  1017. Способ 1. Ручной.
  1018. ^^^^^^^^^^^^^^^^^^^^^
  1019. Применим патчи последовательно от 1 до N:
  1020. .. code-block:: text
  1021. %prep
  1022. %setup -q
  1023. %if 0%{?fedora} && 0%{?fedora} >= 37
  1024. %patch -P1 -p1
  1025. %endif
  1026. ...
  1027. %patch -PN -p1
  1028. Способ 2. Полуавтоматический.
  1029. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  1030. Изменим нумерацию патчей в директивах **Patch** так, чтобы от **1** до **9** были патчи, которые требуется использовать при выполнении заданного условия, а с **10** -- все остальные:
  1031. .. code-block:: text
  1032. Patch1: %{name}-foo.patch
  1033. Patch10: %{name}-bar.patch
  1034. ...
  1035. PatchN: %{name}-other.patch
  1036. Сначала применим условные патчи, а затем, с использованием ``%autopatch``, все остальные, начиная с номера **10**:
  1037. .. code-block:: text
  1038. %prep
  1039. %setup -q
  1040. %if 0%{?fedora} && 0%{?fedora} >= 37
  1041. %patch -P1 -p1
  1042. %endif
  1043. %autopatch -M10 -p1
  1044. .. index:: git, commit, signature, gpg, gnupg
  1045. .. _git-commit-sign:
  1046. Как настроить автоматическую подпись Git-коммитов?
  1047. ======================================================
  1048. См. `здесь <https://www.easycoding.org/2016/04/10/vklyuchaem-avtomaticheskuyu-podpis-kommitov-v-git.html>`__.
  1049. .. index:: git, commit, date, time
  1050. .. _git-commit-datetime:
  1051. Как создать Git-коммит с указанной датой?
  1052. ==============================================
  1053. Воспользуемся опциональным параметром ``--date`` для указания произвольной даты и времени для коммита:
  1054. .. code-block:: text
  1055. git commit --date="ГГГГ-ММ-ДД ЧЧ:ММ:СС"
  1056. Внимание! Если в репозитории или глобально включена :ref:`GPG-подпись коммитов <git-commit-sign>`, то в них будет указана текущая дата и время. Решить это можно лишь изменив :ref:`настройки всей системы <set-datetime>`.