§2023-09-20

-mkinitcpioをGentooに移植してみる話

 2021/05/11 00:26 

・はじめに

今日、ほとんどのGNU/Linuxディストリビューションでinitramfsが使われています。

カーネルを新しいバージョンに上げたりするたびに新しいinitramfsを作成するわけですが、Gentoo LinuxではWikiを確認したところ公式がサポートしてるinitramfs作成ツールはgenkernelとdracutの2種のみのようです。

ここで、Arch Linuxには便利なinitfamfs作成ツールであるmkinitcpioが存在しているのでこれをGentoo Linuxでも使いたいと思います。

・Portageを使う理由

幸いmkinitcpioは簡単なシェルスクリプトから構成されているためArch Linuxのサイトからパッケージを取ってきて解凍してルートディレクトリにコピーするだけですぐ使えます。 しかしこの方法ではアンインストールする際に面倒なのでGentoo Linuxのパッケージ管理システムであるPortageで管理できるようにします。

そのために今回は/usr/local配下にローカルリポジトリを作成して、そこに自分で書いたebuildファイルを保存します。 こうすると他のパッケージ同様emergeでインストール/アンインストールが可能になるので非常に楽になるはずです。

mkinitcpio及びその依存関係で必要なmkinitcpio-busyboxを移植します。

・参考資料

mkinitcpio - ArchWiki https://wiki.archlinux.jp/index.php/Mkinitcpio

Arch Linux - mkinitcpio 30-1 https://archlinux.org/packages/core/any/mkinitcpio/

Arch Linux - mkinitcpio-busybox 1.32.1-3 (x86_64) https://archlinux.org/packages/core/x86_64/mkinitcpio-busybox/

Gentoo Ebuild 執筆基本ガイド - Gentoo Wiki https://wiki.gentoo.org/wiki/Basic_guide_to_write_Gentoo_Ebuilds/ja

ハンドブック:パート/Portage/カスタムツリー - Gentoo Wiki https://wiki.gentoo.org/wiki/Handbook:Parts/Portage/CustomTree/ja

ebuild リポジトリ - Gentoo Wiki https://wiki.gentoo.org/wiki/Ebuild_repository/ja

書ける!ebuild - Brackets Salad https://omasanori.github.io/blog/2016/12/08/writing-ebuild-crash-course/

・実際の操作

¶1.ローカルリポジトリ用Portageツリーの作成

今回移植するmkinitcpioはgenkernelやdracutに倣ってsys-kernelグループに配属します。 /usr/local配下にローカルリポジトリ用のportageディレクトリを作成し、その配下にsys-kernelディレクトリを作成します。さらにその配下にmkinitcpioとmkinitcpio-busyboxの2つのディレクトリを作成します。 また、mkinitcpio-busybox配下にfilesディレクトリも作成しておきます。

# ls /usr/local/
bin  lib  lib64  sbin
(chroot) hc4Gentoo / # mkdir -vp /usr/local/portage/sys-kernel/{mkinitcpio,mkinitcpio-busybox}
mkdir: created directory '/usr/local/portage'
mkdir: created directory '/usr/local/portage/sys-kernel'
mkdir: created directory '/usr/local/portage/sys-kernel/mkinitcpio'
mkdir: created directory '/usr/local/portage/sys-kernel/mkinitcpio-busybox'

# mkdir -vp /usr/local/portage/sys-kernel/{mkinitcpio,mkinitcpio-busybox}
# mkdir -v /usr/local/portage/sys-kernel/mkinitcpio-busybox/files
mkdir: created directory '/usr/local/portage/sys-kernel/mkinitcpio-busybox/files'

¶2.ローカルリポジトリの登録

ローカルリポジトリをPortageに登録すべく /etc/portage/repos.conf配下にローカルリポジトリの設定ファイル(localrepo.conf)をこんな感じで作成します。

nano /etc/portage/repos.conf/localrepo.conf

[localrepo]
location = /usr/local/portage

masters = gentoo

¶3.ebuildファイルとパッチの作成

¶3-1.mkinitcpioのebuildファイル作成

現在(2021-05-10)、mkinitcpioの最新バージョンは30なので、バージョン30のものとarch linuxのgitで管理されている開発版のものの合わせて2つのebuildファイルを作成します。

まずはバージョン30のebuildを以下のように作成します。

nano /usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-30.ebuild

# Copyright 2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=7

inherit bash-completion-r1 linux-info systemd toolchain-funcs

DESCRIPTION="Modular initramfs image creation utility"
HOMEPAGE="https://git.archlinux.org/mkinitcpio.git/"
SRC_URI="https://git.archlinux.org/mkinitcpio.git/snapshot/mkinitcpio-30.tar.gz"

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="amd64 ~x86 arm64"

DEPEND="
                app-arch/bzip2
                app-arch/gzip
                app-arch/libarchive
                app-arch/lzop
                app-arch/lz4
                app-arch/xz-utils
                app-arch/zstd
                app-shells/bash
                sys-apps/coreutils
                sys-apps/diffutils
                sys-apps/findutils
                sys-apps/gawk
                sys-apps/grep
                sys-apps/kmod
                sys-apps/systemd
                >=sys-apps/util-linux-2.23
                >=sys-kernel/mkinitcpio-busybox-1.19.4-r2
"
DEPEND="${DEPEND}"

開発版のものをバージョン9999として以下のように作成します。

nano /usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-9999.ebuild

# Copyright 2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=7

inherit bash-completion-r1 git-r3 linux-info systemd toolchain-funcs

DESCRIPTION="Modular initramfs image creation utility"
HOMEPAGE="https://git.archlinux.org/mkinitcpio.git/"
EGIT_REPO_URI="https://git.archlinux.org/mkinitcpio.git"

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="amd64 ~x86 arm64"

DEPEND="
                app-arch/bzip2
                app-arch/gzip
                app-arch/libarchive
                app-arch/lzop
                app-arch/lz4
                app-arch/xz-utils
                app-arch/zstd
                app-shells/bash
                sys-apps/coreutils
                sys-apps/diffutils
                sys-apps/findutils
                sys-apps/gawk
                sys-apps/grep
                sys-apps/kmod
                sys-apps/systemd
                >=sys-apps/util-linux-2.23
                >=sys-kernel/mkinitcpio-busybox-1.19.4-r2
"
DEPEND="${DEPEND}"

¶3-2.mkinitcpio-busyboxのebuildとパッチ用シェルスクリプトの作成

mkinitcpio-busybox用のパッチをダウンロードするシェルスクリプトを作ります。

nano /usr/local/portage/sys-kernel/mkinitcpio-busybox/files/patchs-download.sh

#!/bin/bash
curl -o /usr/local/portage/sys-kernel/mkinitcpio-busybox/files//0001-ash-fix-unset_var-pattern-repl.patch https://git.archlinux.org/svntogit/packages.git/plain/trunk/0001-ash-fix-unset_var-pattern-repl.patch?h=packages/mkinitcpio-busybox

curl -o /usr/local/portage/sys-kernel/mkinitcpio-busybox/files/0002-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch https://git.archlinux.org/svntogit/packages.git/plain/trunk/0002-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch?h=packages/mkinitcpio-busybox

curl -o /usr/local/portage/sys-kernel/mkinitcpio-busybox/files/config https://git.archlinux.org/svntogit/packages.git/plain/trunk/config?h=packages/mkinitcpio-busybox

ebuild ./mkinitcpio-busybox-*.ebuild manifest

作ったシェルスクリプトに実行権限をつけます。

 # chmod u+x /usr/local/portage/sys-kernel/mkinitcpio-busybox/files/patchs-download.sh

mkinitcpio-busyboxのバージョン1.32.1-r3を以下のように作成します。

# Copyright 2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=7

inherit flag-o-matic savedconfig systemd toolchain-funcs

DESCRIPTION="Base initramfs tools"
HOMEPAGE="https://archlinux.org/packages/core/x86_64/mkinitcpio-busybox/"
SRC_URI="https://busybox.net/downloads/busybox-1.32.1.tar.bz2"

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="amd64 ~x86 arm64"

DEPEND="
                sys-libs/glibc
                sys-libs/libxcrypt
"
RDEPEND="${DEPEND}"

S=${WORKDIR}/busybox-1.32.1

src_prepare() {
                default
                PATCHES=(
                        "${FILESDIR}/0001-ash-fix-unset_var-pattern-repl.patch"
                        "${FILESDIR}/0002-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch"
                )
                cp -v "${FILESDIR}/config" "${S}/.config" || die "Please rerun /usr/local/portage/sys-kernel/mkinitcpio-busybox/files/patchs-download.sh"
}

src_compile() {
                export KCONFIG_NOTIMESTAMP=1
                emake || die "emake failed"
}

src_install() {
                mkdir -vp "${D}/usr/lib/initcpio/"
                cp -v "${S}/busybox" "${D}/usr/lib/initcpio/busybox"
}

¶4.Manifest(メタデータ)の作成

ebuildファイルを書き終えたらメタデータファイルであるManifestというファイルを作成します。 Manifestファイルにはソースコードの入ったtarballなどのチェックサムが保存してあるみたいです。

mkinitcpio-busyboxのManifestファイルは先ほど作ったシェルスクリプトを実行すれば作成されます。

(chroot) hc4Gentoo / # mkdir  /usr/local/portage/metadata/
(chroot) hc4Gentoo / # nano  /usr/local/portage/metadata/layout.conf
(chroot) hc4Gentoo / # cat /usr/local/portage/metadata/layout.conf
masters = gentoo

# ebuild /usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-30.ebuild manifest
# ebuild /usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-9999.ebuild manifest
# /usr/local/portage/sys-kernel/mkinitcpio-busybox/files/patchs-download.sh
(chroot) hc4Gentoo / # ebuild /usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-9999.ebuild manifest
>>> Creating Manifest for /usr/local/portage/sys-kernel/mkinitcpio
(chroot) hc4Gentoo / # /usr/local/portage/sys-kernel/mkinitcpio-busybox/files/patchs-download.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   162  100   162    0     0     28      0  0:00:05  0:00:05 --:--:--    43
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   162  100   162    0     0     28      0  0:00:05  0:00:05 --:--:--    43
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   162  100   162    0     0    224      0 --:--:-- --:--:-- --:--:--   224
Appending / to PORTDIR_OVERLAY...
!!! Repository 'x-' is missing masters attribute in '/metadata/layout.conf'
!!! Set 'masters = gentoo' in this file for future compatibility
ebuild: /mkinitcpio-busybox-*.ebuild: does not exist

(chroot) hc4Gentoo / # ebuild /usr/local/portage/sys-kernel/mkinitcpio-busybox/mkinitcpio-busybox-1.32.1-r3.ebuild manifest
>>> Downloading 'http://distfiles.gentoo.org/distfiles/0d/busybox-1.32.1.tar.bz2'
--2023-09-20 06:57:46--  http://distfiles.gentoo.org/distfiles/0d/busybox-1.32.1.tar.bz2
Resolving distfiles.gentoo.org... 89.187.187.19, 89.187.187.15, 89.187.187.11, ...
Connecting to distfiles.gentoo.org|89.187.187.19|:80... connected.
HTTP request sent, awaiting response... 404 Not Found
2023-09-20 06:57:48 ERROR 404: Not Found.

>>> Downloading 'https://busybox.net/downloads/busybox-1.32.1.tar.bz2'
--2023-09-20 06:57:48--  https://busybox.net/downloads/busybox-1.32.1.tar.bz2
Resolving busybox.net... 140.211.167.122
Connecting to busybox.net|140.211.167.122|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2444679 (2.3M) [application/x-bzip2]
Saving to: ‘/var/cache/distfiles/busybox-1.32.1.tar.bz2.__download__’

/var/cache/distfiles/busybox-1.32.1.tar.bz2.__download__             100%[====================================================================================================================================================================>]   2.33M  2.19MB/s    in 1.1s    

2023-09-20 06:57:50 (2.19 MB/s) - ‘/var/cache/distfiles/busybox-1.32.1.tar.bz2.__download__’ saved [2444679/2444679]

>>> Creating Manifest for /usr/local/portage/sys-kernel/mkinitcpio-busybox

para;5.インストール

# emerge -av mkinitcpio mkinitcpio-busybox

(chroot) hc4Gentoo / # eix sys-kernel/mkinitcpio
cannot open database file /var/cache/eix/portage.eix for reading
Did you forget to create it with "eix-update"?
(chroot) hc4Gentoo / # eix-update
Reading Portage settings...
Building database (/var/cache/eix/portage.eix)...
[0] "gentoo" /var/db/repos/gentoo/ (cache: metadata-md5-or-flat)
     Reading category 167|167 (100) Finished             
[1] "" /usr/local/portage (cache: parse|ebuild*3.0.24#metadata-md5#metadata-flat#assign)
     Reading category 146|167 ( 87): sys-kernel...!!! Repository 'localrepo' is missing masters attribute in '/usr/local/portage/metadata/layout.conf'
!!! Set 'masters = gentoo' in this file for future compatibility
!!! Repository 'localrepo' is missing masters attribute in '/usr/local/portage/metadata/layout.conf'
!!! Set 'masters = gentoo' in this file for future compatibility
 * ERROR: sys-kernel/mkinitcpio-30:: failed (depend phase):
 *   toolchain-funcs: EAPI 0 not supported
 * 
 * Call stack:
 *                   ebuild.sh, line 628:  Called source '/usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-30.ebuild'
 *        mkinitcpio-30.ebuild, line   4:  Called inherit 'bash-completion-r1' 'linux-info' 'systemd' 'toolchain-funcs'
 *                   ebuild.sh, line 308:  Called __qa_source '/var/db/repos/gentoo/eclass/bash-completion-r1.eclass'
 *                   ebuild.sh, line 123:  Called source '/var/db/repos/gentoo/eclass/bash-completion-r1.eclass'
 *   bash-completion-r1.eclass, line  29:  Called inherit 'toolchain-funcs'
 *                   ebuild.sh, line 308:  Called __qa_source '/var/db/repos/gentoo/eclass/toolchain-funcs.eclass'
 *                   ebuild.sh, line 123:  Called source '/var/db/repos/gentoo/eclass/toolchain-funcs.eclass'
 *      toolchain-funcs.eclass, line  18:  Called die
 * The specific snippet of code:
 *      *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
 * 
 * If you need support, post the output of `emerge --info '=sys-kernel/mkinitcpio-30::'`,
 * the complete build log and the output of `emerge -pqv '=sys-kernel/mkinitcpio-30::'`.
 * Working directory: '/usr/lib/python3.11/site-packages'
 * S: '/mkinitcpio-30'

ebuild failed with status 1
     Reading category 146|167 ( 87): sys-kernel...
cannot properly execute /usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-30.ebuild
     Reading category 167|167 (100) Finished      
Applying masks...
Calculating hash tables...
Writing database file /var/cache/eix/portage.eix...
Database contains 18907 packages in 167 categories
 # eix sys-kernel/mkinitcpio
* sys-kernel/mkinitcpio [1]
     Available versions:  30 9999*l
     Homepage:            https://git.archlinux.org/mkinitcpio.git/
     Description:         Modular initramfs image creation utility

* sys-kernel/mkinitcpio-busybox [1]
     Available versions:  1.32.1-r3 {savedconfig}
     Homepage:            https://archlinux.org/packages/core/x86_64/mkinitcpio-busybox/
     Description:         Base initramfs tools

[1] /usr/local/portage

Found 2 matches
 # emerge -av mkinitcpio mkinitcpio-busybox
!!! Repository 'localrepo' is missing masters attribute in '/usr/local/portage/metadata/layout.conf'
!!! Set 'masters = gentoo' in this file for future compatibility

 * IMPORTANT: 12 news items need reading for repository 'gentoo'.
 * Use eselect news read to view new items.


These are the packages that would be merged, in order:

Calculating dependencies \ * Manifest not found for '/usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-9999.ebuild'
 * Manifest not found for '/usr/local/portage/sys-kernel/mkinitcpio/mkinitcpio-30.ebuild'
... done!
Dependency resolution took 5.93 s.


!!! All ebuilds that could satisfy "mkinitcpio" have been masked.
!!! One of the following masked packages is required to complete your request:
- sys-kernel/mkinitcpio-9999::localrepo (masked by: corruption)
- sys-kernel/mkinitcpio-30::localrepo (masked by: corruption)

For more information, see the MASKED PACKAGES section in the emerge
man page or refer to the Gentoo Handbook.

6.実行結果の確認

必要な設定ファイルが無いのでエラーを吐いてますが一応動作してます。

Gentoo-Titan ~ # mkinitcpio 
==> Starting dry run: 5.12.0-zen1
  -> Running build hook: [base]
==> ERROR: Hook 'udev' cannot be found
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
==> WARNING: Possibly missing firmware for module: xhci_pci
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Dry run complete, use -g IMAGE to generate a real image

7.インストールされたファイルの確認

Portageでしっかり管理されてるのでインストールされたファイルもバッチリ確認できます。

Gentoo-Titan ~ # equery files mkinitcpio

Gentoo-Titan ~ # equery files mkinitcpio-busybox

・おわりに

なんやかんやマジメにebuildを書いたのは恥ずかしながら初めてです(笑) emergeの出力もそこそこエラーを吐いてる感じですがなんとかインストールできたので良しとします。

今回の移植で一番難儀したのは開発版バージョンのebuild(mkinitcpio-9999.ebuild)の作成でした。 ebuildのinheritの欄(=eclassを設定する項目)にgit-r3を追加しないでいたのでgitを用いたソースコードのクローンができずインストールされなかった時は焦りました… 別のパッケージのebuildを見まくった結果、gitを使う時はeclassの欄にgit-r3を追加しないといけないと気が付き事なきを得ました。 eclassを上手く設定できればさらにうまくebuildを書けそうな気がします…

丁寧で複雑なebuildを書くGentoo Linuxの開発者の方々には改めて頭が上がらないです。

次回はmkinitcpioを使えるものにすべく、mkinitcpioの設定ファイルをサクっと作ります。