Gentoo Install Battle Clang edition
初めに
私は現在Gentoo LinuxのデフォルトのコンパイラをClangにして使っています。
今回は、ClangをブートストラップしてGentooをインストールする過程を書きたいと思います。
公式のインストールガイドにある情報や、Gentooに特有でない知識などの説明は省くことが多いです。ご了承ください。
インストールメディアの準備
arch-chroot
genfstab
-
mirrorselect
を使えるので、今回はMinimal Installation CDを使います。
近くのミラーからダウンロードします。
ディスクの準備
パーティショニング
- サイズを
+2G
のように相対的に指定できる -
w
を実行し、確認に答えて初めてディスクに変更が書き込まれる
ので、gdisk
がおすすめです。
gdisk /dev/sda
例として、以下のようなレイアウトを使います。
デバイスパス | マウントポイント | ファイルシステム | 概要 |
---|---|---|---|
/dev/sda1 |
/boot |
vfat | EFI システム パーティション(ESP) |
/dev/sda2 |
なし | swap | スワップパーティション |
/dev/sda3 |
/ |
btrfs | ルートパーティション |
フォーマット
mkfs.fat -F 32 /dev/sda1
スワップパーティションを初期化します。
mkswap /dev/sda2
BTRFSを使います。
mkfs.btrfs /dev/sda3
マウント
ルートパーティションをマウントします。zstd
を使った透過的自動圧縮を有効化します。
mount -o compress=zstd /dev/sda3 /mnt/gentoo
ブートパーティションもマウントします。
mount --mkdir /dev/sda1 /mnt/gentoo/boot
スワップパーティションを有効化します。
swapon /dev/sda2
stageファイルのダウンロード
プロファイルは
- amd64
- OpenRC
- nomultilib
です。
OpenRCを使うかsystemdを使うかは好みです。慣れていないならsystemdで良いと思います。
Wineなどの32-bitのサポートが必要なソフトウェアを使いたい場合はmultilibを使ってください。
事前にカレントディレクトリを/mnt/gentoo
にしておきます。
cd /mnt/gentoo
wget
を使います。
wget https://url/to/mirror/releases/amd64/autobuilds/<release>/stage3-amd64-nomultilib-openrc-<release>.tar.xz
<release>は日付になっています。適宜置き換えてください。
stageファイルを展開します。
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner
コンパイルオプションの設定
make.conf
を編集します。この時点ではvi
とnano
が使えたはずですが、chroot
先ではnano
しか入っていないです。
nano /mnt/gentoo/etc/portage/make.conf
COMMON_FLAGS="-O2 -pipe -march=native"
MAKEOPTS="-j12 -l12"
PORTAGE_SCHEDULING_POLICY="idle"
EMERGE_DEFAULT_OPTS="--jobs=12 --load-average=12 --keep-going --quiet-build --with-bdeps=y --complete-graph=y"
12は自分の環境に合わせて置き換えてください。
PORTAGE_SCHEDULING_POLICY
このオプションをidle
に設定すると、Portageプロセスの優先度が非常に低くなるので、
裏でPortageを走らせながら他の作業をするときに、画面のカクつきなどの違和感が減ります。
EMERGE_DEFAULT_OPTS
emerge
コマンドにデフォルトで渡されるオプションです。
--keep-going
あるパッケージのビルドに失敗したときでも可能ならばビルドを継続します。
GCCだとあまり失敗することはないですがClangだとときどき失敗するのであった方が良いです。
--quiet-build
ビルドログを表示させないようにします。エラーが起きたら表示されます。
less /var/tmp/portage/category/package/temp/build.log
でログを読めます。
--with-bdeps=y
パッケージのビルドだけに必要なパッケージも保持します。
--complete-graph=y
依存関係について深く考慮させます。
依存関係の計算にかかる時間がかなり長くなります。
ミラーの設定
mirrorselect
を使います。
mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf
chroot
DNS情報をコピーします。
cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
fstabを生成します。
genfstab -U /mnt/gentoo >> /mnt/gentoo/etc/fstab
chrootします。
arch-chroot /mnt/gentoo
source /etc/profile
Portageの設定
Gentoo ebuild repositoryの設定
repos.conf
ディレクトリを作成します。
mkdir --parents --verbose /etc/portage/repos.conf
Portageに付属しているファイルをコピーします。
cp /usr/share/portage/config/repos.conf /etc/portage/repos.conf/gentoo.conf
Repositoryの同期
Gentoo ebuild repositoryのスナップショットをインストールします。
emerge-webrsync
ニュースがあれば必ず読みましょう。
eselect news list
eselect news read
プロファイルの選択
現在のプロファイルを表示します。
eselect profile show
これが正しくなければ、
eselect profile list
eselect profile set 2
などとして適切なプロファイルを選んでください。
システムのアップグレード
emerge --ask --verbose --update --deep --newuse @world
短縮形:
emerge -avuDN @world
Clangのブートストラップ
おそらく一番時間がかかります。
USE変数の設定
まずUSE変数を設定します。
USE="-clang -llvm"
これを設定しなかったときはsys-libs/llvm-libunwind
のインストールに失敗しました。
Clang toolchainのビルド(一回目)
GCCでClangをインストールします。
emerge --ask --verbose clang llvm compiler-rt llvm-libunwind lld
かなり時間がかかります。お茶でも飲んで休憩しましょう。
ClangでClangをインストールするための設定
Gentooではパッケージ毎にコンパイルオプションを設定できます。
それを使って先程インストールしたClangでClang自身をビルドするための設定をします。
まず/etc/portage/env
ディレクトリを作ります。
mkdir /etc/portage/env
そして以下のようなファイルを作成します。
COMMON_FLAGS="-O2 -pipe -march=native -flto=thin"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS} -stdlib=libstdc++"
LDFLAGS="-stdlib=libstdc++ -fuse-ld=lld -rtlib=compiler-rt -unwindlib=libunwind -Wl,-O2 -Wl,--as-needed"
CC="clang"
CXX="clang++"
LD="ld.lld"
AR="llvm-ar"
NM="llvm-nm"
RANLIB="llvm-ranlib"
STRIP="llvm-strip"
OBJCOPY="llvm-objcopy"
OBJDUMP="llvm-objdump"
-flto=thin
ThinLTOを有効化します。
ビルド時間は長くなります。
-stdlib=libstdc++
LLVM製のlibc++ではなくGNU製のlibstdc++を使います。
両者のABIに互換性がなく、システムが壊れる可能性があるためです。
-fuse-ld=lld
GNU製のbfd
ではなくLLVMのlld
を使います。こちらの方が速いです。
-rtlib=compiler-rt
ランタイムライブラリにLLVMのcompiler-rtを使います。
-unwindlib=libunwind
LLVMのlibunwindを使います。
また、make.conf
を編集し、USE変数を変更します。
USE="clang llvm default-compiler-rt default-lld llvm-libunwind -default-libcxx"
次に、package.env/compiler-clang
を作成し、上記の設定を必要なパッケージに適用します。
mkdir /etc/portage/package.env
sys-devel/llvm compiler-clang
sys-libs/libcxx compiler-clang
sys-libs/libcxxabi compiler-clang
sys-libs/compiler-rt compiler-clang
sys-libs/compiler-rt-sanitizers compiler-clang
sys-libs/llvm-libunwind compiler-clang
sys-devel/lld compiler-clang
sys-devel/clang compiler-clang
Clang toolchainのビルド(二回目)
emerge --ask --verbose clang llvm libcxx libcxxabi compiler-rt llvm-libunwind lld
設定が上手くいっていればこれらのパッケージはClangでコンパイルされるはずです。
これも時間がかかります。コーヒーでも飲んで休憩しましょう。
Clangをデフォルトのコンパイラとして使うための設定
make.conf
を編集します。と言っても、先程env/compiler-clang
に書いた内容を持ってくるだけです。
COMMON_FLAGS="-O2 -pipe -march=native -flto=thin"
CXXFLAGS="${COMMON_FLAGS} -stdlib=libstdc++"
LDFLAGS="-stdlib=libstdc++ -fuse-ld=lld -rtlib=compiler-rt -unwindlib=libunwind -Wl,-O2 -Wl,--as-needed"
CC="clang"
CXX="clang++"
LD="ld.lld"
AR="llvm-ar"
NM="llvm-nm"
RANLIB="llvm-ranlib"
STRIP="llvm-strip"
OBJCOPY="llvm-objcopy"
OBJDUMP="llvm-objdump"
フォールバック環境の設定
多くのパッケージはClangでコンパイルできますが、失敗するものもあります。
そういった場合にGCCを使うことができるように設定します。
env/compiler-gcc
を作成します。
COMMON_FLAGS="-O2 -pipe -march=native"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
LDFLAGS="-fuse-ld=bfd -Wl,-O2 -Wl,--as-needed"
CC="gcc"
CXX="g++"
LD="ld.bfd"
AR="gcc-ar"
NM="gcc-nm"
RANLIB="gcc-ranlib"
STRIP="strip"
OBJCOPY="objcopy"
OBJDUMP="objdump"
Clangで失敗したパッケージはpackage.env/compiler-gcc
に書いていけば良いです。
私の環境で失敗したパッケージを載せておきます。perlのライブラリが多いです。
media-libs/alsa-lib compiler-gcc
dev-perl/Socket6 compiler-gcc
dev-perl/Net-SSLeay compiler-gcc
dev-perl/Clone compiler-gcc
perl-core/Compress-Raw-Zlib compiler-gcc
dev-perl/HTML-Parser compiler-gcc
dev-perl/XML-Parser compiler-gcc
app-i18n/libskk compiler-gcc
dev-perl/Sub-Name compiler-gcc
ここでシステムをアップグレードします。
emerge -avuDN @world
make.conf
の設定
USE
USE="clang llvm default-compiler-rt default-lld llvm-libunwind -default-libcxx X wayland opengl vulkan elogind dbus jpeg gtk pulseaudio pipewire -qt -gnome -kde -branding -bluetooth"
自分の環境に合わせて設定してください。
CPU_FLAGS
app-portage/cpuid2cpuflags
をインストールします。
emerge --ask --verbose --oneshot cpuid2cpuflags
出力をpackage.use/00cpu-flags
にリダイレクトします。
echo "*/* $(cpuid2cpuflags) > /etc/portage/package.use/00cpu-flags
VIDEO_CARDS
私はIntelのGPUを使っているので
VIDEO_CARDS="intel"
としました。
ACCEPT_LICENSE
基本的には
ACCEPT_LICENSE="-* @FREE"
として、自由でないライセンスのソフトウェアをインストールするときに
package.license
以下に
sys-kernel/linux-firmware @BINARY-REDISTRIBUTABLE
sys-firmware/intel-microcode intel-ucode
とするのが面倒ですが良いと思います。
GRUB_PLATFORMS
amd64でUEFIなら
GRUB_PLATFORMS="efi-64"
タイムゾーンの設定
日本に住んでいるなら
echo "Asia/Tokyo" > /etc/timezone
emerge --config sys-libs/timezone-data
です。
ロケールの設定
/etc/locale.gen
のen_US.UTF-8
とja_JP.UTF-8
をアンコメントします。
en_US.UTF-8
ja_JP.UTF-8
ロケールを生成します。
locale-gen
この時点ではen_US.UTF-8
を選択してください。
eselect locale list
eselect locale set 4
ここで環境をリロードします。
env-update && source /etc/profile
ファームウェアのインストール
emerge --ask --verbose linux-firmware
AMD製のCPUであればsys-kernel/linux-firmware
にマイクロコードが入っています。
IntelのCPUなら別途マイクロコードをインストールしてください。
emerge --ask --verbose intel-microcode
ライセンスのエラーが出たら、package.license
を設定してください。
installkernelのインストール
2024年2月26日から、ソースからカーネルをインストールする場合は明示的にsys-kernel/installkernel
をインストールする必要があります。
emerge --ask --verbose installkernel
カーネルのインストール
完全手動でやります。
カーネルのソースをインストールします。慣れていないならsys-kernel/gentoo-sources
が良いと思います。
emerge --ask --verbose gentoo-sources
カーネルを選択します。
eselect kernel list
eselect kernel set 1
ソースがあるディレクトリに移動します。
cd /usr/src/linux
TUIで設定できます。
make menuconfig
完全に環境によるのでconfigについては省略します。
https://wiki.gentoo.org/wiki/Handbook:AMD64/Full/Installation/ja#.E5.88.A5.E3.81.AE.E6.96.B9.E6.B3.95:_.E3.83.9E.E3.83.8B.E3.83.A5.E3.82.A2.E3.83.AB.E8.A8.AD.E5.AE.9A を見てください。
configが終わったら、コンパイルします。ここでもClangを使えます。
make LLVM=1 LLVM_IAS=1 KFLAGS="-O2 -pipe -march" -j12 && make modules_install
LLVM=1は
CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \
OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \
HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld
と同じです。
-j12についてはMAKEOPTS
と同じです。
カーネルのconfigに書いていなければここで
- LTOなし
- FullLTO
- ThinLTO
のどれかを選択します。
ThinLTOにします。
終わったらインストールします。
make install
initramfsのビルド
sys-kernel/dracut
をインストールします。
emerge --ask -verbose dracut
initramfsをビルドします。
dracut --kver=6.6.21-gentoo
--kver
は適宜置き換えてください。
ネットワークの設定
ホストネームを設定します。
echo your_hostname > /etc/hostname
ここではnet-misc/dhcpcd
をインストールします。自分の環境に合わせて設定してください。
emerge --ask --verbose dhcpcd
起動時に自動的にスタートするようにします。
rc-update add dhcpcd default
hosts
ファイルを設定します。
127.0.0.1 your_hostname.homenetwork your_hostname localhost
システムの設定
パスワードを設定します。
passwd
OpenRCの設定をします。
私は以下をアンコメントしています。
rc_parallel="YES"
rc_logger="YES"
rc_send_sighup="YES"
rc_timeout_stopsec="10"
rc_send_sigkill="YES"
rc_parallel="YES"
可能ならサービスを並列起動します。
rc_logger="YES"
起動時のログを有効化します。デフォルトでは/var/log/rc.log
に出力されます。
rc_send_sighup="YES"
stopsigとsigcontの直後にcgroupのプロセスにsighupを送ります。
rc_timeout_stopsec="10"
sigcontとsighupを送った後に、cgroupのプロセスにsigkillを送るまでの遅延時間です。単位は秒です。
rc_send_sigkill="YES"
cgroupのプロセスにsigkillを送ります。
キーボードの設定をします。US配列なら変えなくても動くと思います。
JIS配列なら
keymap="jp106"
とします。
/bin/sh
はデフォルトではbash
へのシンボリックリンクになっています。ここではdash
に変更します。
echo "app-alternatives/sh -bash dash" > /etc/portage/package.use/sh
emerge --ask --verbose --oneshot app-alternatives/sh
ロガーのインストール
とりあえず動かしたいならapp-admin/sysklogd
が良いと思います。
emerge --ask --verbose sysklogd
起動時に自動でスタートさせます。
rc-update add sysklogd default
cronデーモンのインストール
色々ありますがsys-process/cronie
を使います。
emerge --ask --verbose cronie
rc-update add cronie default
時刻同期の設定
net-misc/chrony
をインストールします。
emerge --ask --verbose chrony
/etc/chrony/chrony.conf
に設定を書きます。
server ntp1.jst.mfeed.ad.jp
rc-update add chronyd default
ファイルシステムツールのインストール
使っているファイルシステムのものをインストールします。
sys-fs/e2fsprogs
(ext4)は既にインストールされているはずです。
ここではsys-fs/btrfs-progs
(btrfs)とsys-fs/dosfstools
(vfat)をインストールします。
emerge --ask --verbose btrfs-progs
emerge --ask --verbose dosfstools
ブートローダのインストール
GRUBを使います。
emerge --ask --verbose grub
grub-install --target=x86_64-efi --efi-directory=/boot --removal
基本的にはこれで問題ないはずです。
grub-mkconfig -o /boot/grub/grub.cfg
再起動
上手くいったことを願って再起動します。
まずchroot環境を出ます。
exit
パーティションをアンマウントします。
umount -R /mnt/gentoo
再起動します。
reboot
長くなったのでインストール後の環境構築は別の記事で書きたいと思います。
Discussion