Kernelnotes
Эта страница не описывает, как собирать ядра с 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
Ссылки
Примечания
- ↑ Athlon 64 X2 Dual Core 3800+ и 1GB ОЗУ, по субьективной оценке, не очень быстро работают