Kernelnotes

Материал из ALT Linux Wiki
Внимание! Использование своего ядра с дистрибутивами ALT Linux не поддерживается как техподдержкой ООО «Альт Линукс», так и силами сообщества. Созданные в багтрекере ошибки, относящиеся к самосборным ядрам будут закрыты как NOTABUG.


Small-pyramides.png
Архивная информация.
Описываемые в этой статье вещи больше не используются и оставлены только для обратной совместимости.


Внимание! Настоящая инструкция устарела и описывает положение вещей примерно на 2009 год.


Freesource-logo.png Blue Glass Arrow.svg MediaWiki logo.png
Эта страница была перемещена с freesource.info.
Эта страница наверняка требует чистки и улучшения — смело правьте разметку и ссылки.
Просьба по окончанию убрать этот шаблон со страницы.


Эта страница не описывает, как собирать ядра с kernel.org, но как собирать ядра из репозиториев ALT Linux.

См. тж. Kernel/build for dummies.

Последняя информация о том, как правильно собирать ядро

Последняя информация о том, как правильно собирать ядро, находится в пакете kernel-build-tools в файле README.ru.koi8; его посмотреть можно в git-репозитории пакета, например, тут (ссылка со временем устареет): README.ru.koi8

Зачем может быть нужно собирать своё ядро?

  • Вы разработчик ядра.
  • Вам нужно ядро, собранное каким-то особым способом (например, со включенной экспериментальной опцией), и ядра в ALT Linux не собраны таким образом.
  • Вы пытаетесь отладить проблему в ядре ALT Linux и в багтракере, списке рассылки или техподдержке вам подсказали, что для этого нужно собрать ядро специальным способом
  • У вас есть устройство, не поддерживаемое ядрами ALT Linux (только изредка! Очень часто достаточно просто собрать свой модуль к ядру, см. ниже).

Почему обычно не нужно собирать своё ядро?

  • Это скучное занятие.
  • Если вам нужен специальный драйвер, то достаточно собрать модуль к уже имеющемуся ядру.
  • Распространённые мифы про сборку ядра ложны:
    • Сборка ядра — простое дело
      Современный PC — достаточно сложное устройство, и правильный выбор опций компиляции — нетривиальное занятие.
      Дистрибутивные ядра оптимизированы под «средний» компьютер, пересборка увеличивает производительность
      Не подтверждается тестами. Чаще наоборот: неправильно собранное ядро замедляет систему.
      Сборка ядра — обязательное дело любого линуксоида
      Нет©
      Ненужные драйвера тормозят и занимают память
      Ненужные драйвера лежат на диске в виде модулей и не загружаются в память.
      Ядро с драйверами, вкомпилированными внутрь, работает быстрее
      Не подтверждается тестами. Загрузка модулей занимает несколько секунд при старте компьютера, дальнейшее использование идентично по скорости вкомпилированным драйверам. (а для тех применений, где отсутствие лишнего просмотра таблицы действительно существенно — всяко требуется специалист, не судящий по глупым сказкам)

Предупреждение

Статья частично протухла. vsu@ советует читать доки в kernel-build-tools.

Собираем новое ядро

Будем для примера собирать ядро версии 2.6.23. Вам понадобится хорошая быстрая машина, с быстрым процессором, и большим объемом ОЗУ[1]. Для ускорения сборки можно использовать ccache, установив для этого переменные:

$ export LC_ALL=C
$ export GCC_USE_CCACHE=1

Подготовительный этап

I

У ALT Linux разработана своя среда (kernel-build-tools) для сборки ядер. Основным мантейнером этой среды является vsu; по состоянию на декабрь 2009 последние правки публиковал aspsk:

$ git clone git://git.altlinux.org/people/vsu/packages/kernel-build-tools
$ cd kernel-build-tools
$ ls
$ git remote add aspsk git://git.altlinux.org/people/aspsk/packages/kernel-build-tools
$ git remote update
$ git branch -r


Как видно, среда состоит из набора скриптов.


II

Репозиторий c ядром должен находиться в директории kernel.

Забираем ядро, например, у vsu или lakostis:

$ git clone git://git.altlinux.org/people/vsu/packages/kernel-image-2.6.18 kernel

или

$ git clone git://git.altlinux.org/people/lakostis/packages/kernel-image-2.6.22 kernel

Добавляем репозиторий, содержащий новую версию ядра (для git-remote может потребоваться поставить пакет perl-GIT):

$ git remote add linux-2.6.23 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.23.y.git

В master ветку этого репозитория Линус помещает обновления для ядер серии 2.6.23 (например 2.6.23.1, 2.6.23.2…). В нашем репозитории будет создана ветка linux-2.6.23/master, которая будет отслеживать обновления для ванильного ядра 2.6.23.

Загрузим с репозитория linux-2.6.23 исходный код ядра.

$ git fetch linux-2.6.23

Теперь в нашем репозитории ветка linux-2.6.23/master содержит ядро 2.6.23 с обновлениями. Убедимся:

$ git-log --pretty=short -n 1 linux-2.6.23/master
commit 4367388f04eea72e78347dc9b299698bf4275f92
Author: Greg Kroah-Hartman <gregkh@suse.de>

    Linux 2.6.23.1

Собираем пакет kernel-source-2.6.23-1.0.0-alt1.noarch.rpm

Как видно, данный пакет не зависит от архитектуры. Внутри пакета содержиться только файл с иходными кодами ванильного ядра: /usr/src/kernel/sources/kernel-source-2.6.23.tar.bz2

Заметьте, что данный пакет содержит исходный код ядра версии 2.6.23, а не 2.6.23.1. Собрать этот пакет не составит труда. Достаточно:

$ git checkout -b kernel-source origin/kernel-source # создадим ветки на основе ветки того, кого мы скопировали
$ git pull -s ours . tag v2.6.23 # иначе будет ругаться gear
$ vim kernel-source.spec # увеличиваем версию
$ add_changelog kernel-source.spec

В ответ на ругань add_changelog что версия пакета не изменилась, можно добавить к alt1 точку: 'alt1.', потом удалить. Версия пакета не изменяется, а изменяется имя пакета.

$ vim .gear/rules  # обновить версию ядра в файле (тег)
$ gear-update-tag -a -c
$ git add .gear/rules kernel-source.spec
$ git commit -m "kernel-source-2.6.23 1.0.0-alt1"

Осталось собрать сам пакет с помощью gear в hasher:

$ gear --hasher -- hsh
или
$ gear --hasher -- hsh --apt-config=$HOME/apt/apt.conf.sisyphus.x86_64.hasher $HOME/hasher

Замечания вида:

warning: Macro %kernel_srcdir not found
warning: Macro %kernel_srcdir not found
warning: Macro %kernel_src not found

на результат не влияют, там BuildRequires(pre) не хватает. После сборки этот пакет будет находится в репозитории hasher-a.

Собираем пакет kernel-image-std-smp-2.6.23-alt1.i586.rpm

Собственно этот пакет содержит само ядро + стандартные модули поставляемые с ядром.

Несколько слов о структуре репозитория. На мой взгляд следует различать ветки:

  • kernel-source — цель этой ветки создать пакет с исходниками ванильного ядра 2.6.23 (мы использовали эту ветку на предыдущем шаге).
  • начинающиеся с feat-*-* fix-*-* . Каждая такая ветка содержит ванильное ядро + какое-то одно исправление, дополнение, патч.

Имя ветки сообщает, какое конкретное дополнение она несет.

  • fix-stable — содержит ванильное ядро с последними исправлениями 2.6.23.1.
  • kernel-image-std-smp — содержит пропатчиное ядро. эту ветку мержутся ветки fix-stable, feat-*-*, fix-*-*, fix-stable

Цель ветки kernel-image-std-smp создать мега патч-бомбу который накладывается на ванильное ядро 2.6.23, скомпилировать бинарное ядро, собрать пакет.

Файл branches-to-merge используется скриптом merge-all-branches. Может возникнуть вопрос: «Зачем мержить ветки которые указаны в branches-to-merge, если они уже в замерженыы в ветку kernel-image-std-smp ?» Ответ: Периодически в этих ветках появляется что-то новое, вот скрипт и проверяет, что появилось. Ещё возможен вариант вида branch-* скрипт merge-all-branches проверяет, есть ли что-то новое, если нет — ничего не делает, если есть — спрашивает, надо ли это мержить.

В моем случае, накатывать 2.6.23 поверх пропатченого 2.6.18, бесмысленно, иначе там всё развалится. Придётся делать по сути rebase всех веток с патчами, и подцеплять к старой истории в самом конце. При сборке 2.6.23 лучше создать новые ветки fix-stable, kernel-image-std-smp, …

A

Cоздадим ветку fix-stable. Задача этой ветки содержать последние официальные исправления для ядра от Linus Torvalds:

$ git checkout -b fix-stable linux-2.6.23/master

При будущих обновлениях можно поступать одним из следующим способов: 1. Из tracking branch:

$ git fetch linux-2.6.23
$ git pull . linux-2.6.23/master

2. Загрузить обновления непосредственно из репозитория Linus-а:

$ git pull git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.23.y.git

B

Создадим ветку kernel-image-std-smp на основе тега v2.6.23. Задача этой ветки содержать код ядра со всеми приложеными патчами. То есть в эту ветку мержатся остальные ветки feat-*-* fix-*-*.

$git checkout -b kernel-image-std-smp v2.6.23

Заберем из старой ветки vsu/kernel-image-std-smp файлы: kernel-image.spec config-i586 config-x86_64 branches-to-merge .gear/rules modules.build

Для каждого вышеперечисленного файла выполним:

$ git ls-tree vsu/kernel-image-std-smp
$ git cat-file blob 'sha1' >kernel-image.spec
$ git add -f kernel-image.spec config-i586 config-x86_64 branches-to-merge .gear/rules modules.build

флаг -f указывает добавить .gear/rules, даже если он занесен в .gitignore

C

Создадим ветки feat-*-* и fix-*-*. Например создадим ветку добавляющую поддержку файловой системы unioinfs.

$ git checkout -b feat-fs-unionfs v2.6.23

Патч можно наложить в ручную (patch -p1 < .....) или же средствами git. Что будет более правильно, и облегчит добавление файлов в index, если патч затрагивает слишком много файлов:

$ git apply --index --whitespace=nowarn unionfs.patch

Отличие от patch в том, что git apply рассматривает любой fuzz как ошибку. Ещё особенность в том, что по умолчанию, если есть хотя бы одна ошибка, патч не применяется вообще. Можно добавить — -reject, чтобы создавались *.rej, как с обычным patch. Кстати, такой внешний патч может иметь смысл совать в отдельную ветку, растущую прямо из той версии ядра, для которой предназначен патч а потом уже мержить. Дело в том, что 3way merge зачастую работает надёжнее, чем наложение патча на изменившуюся версию изменения из патча иногда могут молча улетать в другой участок с похожим содержимым.

$ git commit -m "Add unionfs 2.1.8 support"

Ничего страшного не будет если самому создать сам ветку git checkout -b fix-xxx, а потом добавить коммит из ветки vsu/fix-xxx с помощью git cherry-pick. vsu так же делал большей части этих веток. То есть получается мы крадем коммиты vsu с помощью cherry-pick. Единственная неприятность от cherry-pick — если эти коммиты появятся в нескольких местах, потом, возможно, придётся что-то мержить руками. Если изменения точно совпадают, git merge происходит автоматически, если с одной стороны есть ещё какие-то изменения сверху, может вылезти конфликт на ровном месте.

Если Linus Torvalds добавил в официальное ядро присутвовавшие у нас исправления то можно сделать в ветке fix-stable:

$ git pull -s ours fix-xxx

этот фиктивный мерж проходит всегда автоматом, а потом git уже просто не смотрит внутрь этой ветки.

В итоге у меня получились следующие ветки :

feat-core- -rt
feat-core-bootsplash
feat-evms
feat-evms-nodm
feat-fs-squashfs
feat-fs-unionfs
fix-core- -init
fix-core- -syslog
fix-stable
kernel-image-std-smp
kernel-source
master

D

Мержим все исправления в ветку kernel-image-std-smp, исправляем конфликты.

$ git pull . feat-fs-unionfs

E

В ветке kernel-image-std-smp, создадим новый конфиг на базе старого:

$ cp config-i586 .config
$ make oldconig

При обработке make oldconfig, следует учитывать тот факт, что при наличии возможности скомпилировать некую часть ядра в виде модуля, следует ее выбрать. Чаще всего модули не компилируются непосредственно в ядро, но бывают исключения.

Проверяем все ли впорядке:

$ make menuconfig

Опцию CONFIG_LOCALVERSION_AUTO следует отключить.

$ cp .config config-i586
$ vim kernel-image.spec .gear/rules
$ add_changelog kernel-image.spec
$ gear-update-tag -acv
$ git add config-i586 kernel-image.spec .gear/rules
$ git commit

F

Собираем ядро

$ ./buildkernel-hsh --hsh-workdir=/home/stanv/hasher std-smp
или
$ ./buildkernel-hsh --hsh-options=--apt-config=/home/stanv/apt/apt.conf.sisyphus.x86_64 --hsh-workdir=/build/stanv/hasher/ std-smp
или
$ time ./buildkernel-hsh --target=x86_64 --hsh-workdir=/home/stanv/hasher --hsh-options='--apt-config=/home/stanv/apt/apt.conf.sisyphus.x86_64 --repo=/home/stanv/tmp/repo-2.6.23 --target=x86_64' wks

Сборка дополнительных модулей

См. статью Сборка модулей ядра.

A

Каждый пакет, несущий дополнительный модуль собирается на основе шаблона. Шаблоны для всех дополнительных модулей раньше можно было загрузить с CVS:

$ cvs -d cvs.alt:/cvs/kernel checkout -d modules kernel/modules
или
$ cvs -d anoncvs@anoncvs.altlinux.org:/cvs/kernel co -d modules kernel/modules

Теперь шаблоны для модулей находятся в репозиториях kernel-modules у мантейнеров.

B

Например, при сборке пакета kernel-modules-nvidia-std-smp-100.14.19-alt3.132631.1.i586.rpm будет использован шаблон modules/nvidia/kernel-modules-nvidia.spec и пакет kernel-source-nvidia-1001419-100.14.19-alt39.i586.rpm.

Пакет kernel-source-nvidia-1001419-100.14.19-alt39.i586.rpm берем из Sisyphus.

Пакеты kernel-source-* собираются как обычно. У кого-то лежит в гите, у кого-то старым дедовским способом. Получается что мантейниры модулей предлагают только kernel-source-%modulename, а сам бинарный модуль собирает vsu. Пакеты с бинарными модулями нужно собирать с каждым обновлением ядра. Если kernel-source-modulename плохо собран, тогда vsu выполняет двойную работу, либо забивает на этот модуль.

Undeground

то есть, rpm-build-kernel — для BuildRequires, kernel-build-tools — скрипты для использования мантейнерами

pull . сейчас можно менять на merge что лучше cherry-pick или pull ? это в древних версиях git merge не предназначался для вызова руками зависит от ситуации… если в ветке куча коммитов, которые в свежей версии уже есть, merge с большой вероятностью не пройдёт автоматически если это патчи, которые не вошли в новую версию, вероятно, лучше сделать merge а я сделал cherry :( кстати, в подобном случае может иметь смысл сначала сделать merge новой версии в эту ветку хотя это зависит от того, что в дальнейшем предполагается делать с этими изменениями если нужно получить патчи для свежего апстрима, придётся делать rebase если это какие-то изменения, которые апстриму нафиг не нужны, может быть проще смержить свежую версию апстрима туда и разгрести конфликты кстати, в самом свежем git сделали поддержку revert и cherry-pick для merge… указывается, с каким родителем делать дифф, который потом откатывается или применяется A->B ы :(то есть cherry-pick может забирвать все коммиты, между A и B ? нет… это git rebase умеет только он портит исходный бранч а в чем тогда новая фишка ? cherry-pick и revert — это почти одно и то же, различаются тем, в какую сторону применяется патч патч генерируется между указанным коммитом и его родителем если это merge, нужно указать, какой из родительских коммитов нужно брать вот эту опцию и добавили то есть, если сделать cherry-pick для merge, получится один мегапатч со всеми изменениями вообще это полезно для revert

Ссылки

Примечания

  1. Athlon 64 X2 Dual Core 3800+ и 1GB ОЗУ, по субьективной оценке, не очень быстро работают