[TOOLS] 13 分鐘閱讀OraCore 編輯部

Gentoo 核心設定把 menuconfig 變流程

我把 Gentoo kernel 設定整理成可重複流程,從 menuconfig、模組重建到 installkernel,都能照著做。

分享 LinkedIn
Gentoo 核心設定把 menuconfig 變流程

我把 Gentoo kernel 設定理成可重複流程,從 menuconfig、模組重建到 installkernel,都能照著做。

我在 Gentoo 上玩 kernel 夠久了,早就知道它最煩的不是 compile。compile 很單純,真正會讓人火大的是:這個 driver 到底要 built-in、module,還是根本別碰?外部模組有沒有一起顧到?我是不是又把 boot chain 弄成一坨,六小時後還講不清楚自己改了什麼?最惱人的就是這種「看起來都對,實際上很容易出事」的設定。Gentoo Wiki 的 Kernel/Configuration 這頁,剛好把這堆雜訊整理成我能直接拿來用的流程。

這次拆的來源就是這頁,外加它連到的 KernelKernel/Gentoo Kernel Configuration Guideinstallkernel。我不是在自己發明一套新宗教,我只是把它們串成一個比較不會踩雷的工作法。

別把 kernel config 當一次性儀式

訂閱 AI 趨勢週報

每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。

不會寄垃圾信,隨時可取消。

“The kernel offers several user facing tools with which to configure itself.”

白話一點就是:Gentoo 不押寶單一入口,它給你多種配置工具,重點是你要知道每個工具適合幹嘛。頁面列了 make configmake menuconfigmake nconfigmake xconfigmake gconfigmake oldconfigmake olddefconfig。看起來很多,但本質上就三種:互動編修、升級沿用、重置重來。

Gentoo 核心設定把 menuconfig 變流程

我以前也傻傻用 make config,它很誠實,會一題一題問你。問題是你只要中途發現前面漏掉一個選項,就得一路翻回去重走。這不是工作流,這是體力活。我不想每次都像在補考。

實操上,我現在會這樣分:日常改設定用 make menuconfig;從已知可用的 .config 升級時,用 make olddefconfig 讓新預設吃進來但不要一直打斷我;真的要整個重洗,就用 make defconfig。另外,動手前先備份目前的 .config,這不是保守,這是避免自己把自己逼進角落。

  • menuconfig:日常互動修改
  • olddefconfig:升級時少問廢話
  • defconfig:要重來就直接重來

看懂符號,不然你根本沒看懂 menu

這頁花篇幅解釋 menu UI,這不是廢話,這是救命。它把符號講得很清楚:方括號代表 built-in toggle,尖括號代表 built-in 或 module 的選擇,花括號代表被依賴關係鎖住的狀態,還有那些被別的選項固定住的項目。標籤像 (NEW)(EXPERIMENTAL)(DEPRECATED)(OBSOLETE) 也都不是裝飾品。

翻譯一下就是:你不能只看顏色、縮排、或名字像不像你熟悉的東西。[*]<M> 差很多。前者是直接進 kernel image,後者是變成可載入模組。這個差別會影響開機、救援、還有你能不能在不重編整顆 kernel 的情況下把問題救回來。

我之前就踩過一次,某台機器的 storage 支援被我做成 module,結果早期開機路徑需要它先活著,偏偏我又沒把依賴顧完整。那台機器不是直接炸掉,而是一直表現得很有個性:有時候能開、有時候卡住、有時候像在故意考我記不記得自己改了什麼。這種不穩定最煩,因為它不會馬上告訴你錯在哪。

實操寫法很簡單:在 menuconfig 裡,別憑感覺猜。每個選項只問一件事:它是不是必須在 modules 載入前就存在?如果是,就 built-in;如果不是,module 通常比較好回頭。看到 experimental 或 deprecated,先停一下,不要讓好奇心直接接手。

  • [*] = built in
  • <M> = module
  • (NEW)(EXPERIMENTAL) 要多看一眼

先搜尋,再慢慢翻,不要用肉眼賭運氣

Gentoo 這頁特別提到 menuconfig 裡面的 / 搜尋。這種小功能很常被忽略,但它其實超有用。搜尋結果會列出 symbol 名稱、目前狀態、所在位置,還有 dependency chain。頁面用 HCIBTUSB 當例子,直接跳到 Bluetooth USB support,整個路徑一清二楚。

Gentoo 核心設定把 menuconfig 變流程

也就是說,你不用記住每個 submenu 的路徑。你只要知道 driver 或 subsystem 名稱,直接搜尋,然後順著依賴往下看就好。kernel config 其實大部分時間都在處理依賴,只是它披著 UI 外衣,看起來很像在選功能。

我以前很常犯一個蠢事:明明有搜尋,卻硬是靠翻菜單找東西,像在逛百貨公司。結果找到選項後改了三個相關設定,還是不知道為什麼能動。搜尋把流程變成手術刀,不是逛街。它也讓 help text 變得更有價值,因為你是在正確的位置看正確的說明。

實操上,我會先用 driver 名稱或 subsystem 名稱搜尋,再順著依賴鏈看它到底要求什麼。只要它依賴 USBNET,就別假裝沒看到。搜尋結果不是答案本身,它是地圖。你要自己走路。

這裡我也會搭配 Kconfig 文件Hardware detection,以及 upstream kernel tree:kernel.org。有時候你真的得回 upstream 看 symbol 到底在講什麼,不然只看 distro 文檔很容易半懂不懂。

Gentoo 的 common settings 是底線,不是偷懶捷徑

頁面提到 CONFIG_GENTOO_LINUX,這個選項在 sys-kernel/gentoo-sources 和一些 Kernel Project 維護的 kernels 裡可用。重點不是名字,而是它會幫你選一組 Gentoo 常見安裝需要的基本選項,像 tmpfsdevtmpfs 這些跟 /dev 管理有關的東西。

翻譯一下就是:Gentoo 給你一個合理底線,避免你每次都忘掉那些很無聊、但又絕對不能漏的設定。它不是替你做決策,它只是先把通用前提鋪好,讓你把腦力留給真正跟硬體有關的部分。

我其實滿喜歡這種設計,因為它承認現實:沒有人想每次都重選一遍所有通用 kernel knob。那不叫精緻,那叫重複勞動。把基礎盤先固定住,才有空去處理 storage、input、network、graphics、virtualization,還有那些只有你那台機器才會碰到的怪東西。

實操上,如果你用的是 Gentoo sources,就先確認這個 helper config 在不在,然後把 help text 看完。把它當 baseline 用,但不要假設它已經涵蓋所有 edge case。它不會。

  • 適合當 Gentoo 基本盤
  • 不是硬體細節的替代品
  • help text 先看再說

工具鏈別亂混,不然錯得很像玄學

這頁有一句我很認同的警告:不要混用 GNU binutils 和 LLVM binutils。它甚至直接舉例:make CC=gcc LD=ld.lld AR=llvm-ar 這種組合不行,因為 LLVM 的 arld 跟 GCC 那套不相容。這種話我希望更多 build doc 都能直接講白,不要假裝工具鏈都能隨便拼。

也就是說,kernel build 看的不是你以為自己選了哪個 compiler 而已,它看的是整組工具鏈。你要走 LLVM,就整套都走 LLVM;你要走 GCC + GNU binutils,就乖乖待在那條路。混著來,失敗通常會看起來像隨機,其實只是你自己配出來的。

我遇過最煩的那種 build error,就是看起來像 source code 問題,結果翻半天發現是前面某次實驗留下一組半換不換的 toolchain 設定。kernel build system 很彈性,彈性到你可以很精準地傷害自己。

實操寫法:先決定工具鏈策略,再開始 build。如果你要 LLVM,最簡單就是照頁面建議用 make LLVM=1。如果你還要額外 optimization flags,就明白寫出來,不要把一堆看不懂的變數塞進命令列。你如果不知道某個環境變數在幹嘛,先別抄。

我也會搭配 Clang/LLVM in the kernel docs 看 upstream 說法,然後對照 Gentoo 上實際裝了什麼。distro 預設跟你手上的 compiler/ binutils 狀態,常常不是同一回事。

build、install、驗證要當成同一條線

設定完之後,頁面把流程講得很直白:用 make -j$(nproc) 編譯、用 make modules_install 安裝模組、用 make install 安裝 kernel。這些看起來很基本,但真正會出問題的是它們之間的銜接。模組預設會進 /lib/modules,除非你改 MODLIB。而 kernel install 其實是透過 /sbin/installkernel,也就是 sys-kernel/installkernel 這條路。

翻譯一下就是:Gentoo 不是把 kernel install 當成單純複製檔案,它是 boot workflow 的一部分。如果你有用 installkernel 搭 initramfs 自動化,頁面還特別提醒:先重建外部模組,再去裝 kernel,這樣它們才會被納入 initramfs。像 NVIDIA、ZFS 這類外部模組,順序錯了就很容易出事。尤其開了 dracut USE flag 的時候,這個順序更不能亂。

我喜歡這個提醒,因為它很貼近真實故障模式。module stack 跟 kernel image 不同步,不一定會報大錯。很多時候它只是讓你 reboot 之後某些功能消失,然後你開始花整個下午追一個其實只是順序問題的 bug。

實操上,我現在會把 make modules_installmake install 看成一個動作,不是兩個獨立命令。只要你依賴 external modules,就先重建它們,再去刷新 initramfs。如果你用 dracut,就照 wiki 建議的順序走。不要賭你的 boot path 比現實更寬容。

安裝這段我也會一直開著 installkernel 頁面,因為它就是從 kernel build 接到 bootloader-ready artifacts 的那個交界點。

用 diff 看 config,才知道自己到底改了什麼

這頁最後一段我覺得最實用:把目前的 kernel config 跟預設值比對。做法很簡單,先把現有 .config 複製一份,再用 make defconfig 產生預設設定,存下來,最後用 scripts/diffconfig 去比兩份檔案。這樣你看到的是變更清單,不是面對一整坨 config 檔假裝自己有記憶力。

白話講就是:你可以開始審核自己的選擇。kernel config 會慢慢長出一堆你根本忘記為什麼存在的選項。今天為了某台機器開一個功能,六個月後你早就忘了它的背景。diff 會把這些東西攤平,讓你真的能讀懂。

我很常在整理舊 config、或升級後想知道為什麼某台機器行為不一樣時用這招。它也能幫你抓出 dependency 帶來的連鎖變化,因為一個選項真的可能悄悄改掉好幾個別的選項。頁面有明講這件事:改一個設定,可能會連動其他設定。這不是 bug,這就是 kernel config 的本性。

實操寫法:實驗前先存 working config,產生 default baseline,比對兩者,把 diff 留到測完為止。如果你不確定某個 symbol 為什麼變了,就回 menuconfig 用搜尋追它的來源和 help text。不要靠腦補。

可抄的模板

# Gentoo kernel config workflow template
# Source: https://wiki.gentoo.org/wiki/Kernel/Configuration

# 1) 進入 kernel tree
cd /usr/src/linux

# 2) 開互動設定介面
make menuconfig

# 3) 在 menuconfig 裡搜尋 symbol
# 按 /
# 例如:查 driver 或 subsystem 名稱

# 4) 編譯 kernel
make -j$(nproc)

# 5) 如果有模組,就安裝模組
make modules_install

# 6) 如果你有 external modules,且會進 initramfs
# 先重建 external modules,再安裝 kernel
# emerge --ask @module-rebuild

# 7) 透過 installkernel 安裝 kernel
make install

# 8) 升級既有 config 時,用這個
make olddefconfig

# 9) 想比較 working config 跟預設值時
cp -p .config ../.config.working
make defconfig
mv .config ../.config.default
cp -p ../.config.working .config
cd ..
/usr/src/linux/scripts/diffconfig .config.working .config.default > .config.diff

# 10) 用完清掉暫存檔
rm .config.working .config.default .config.diff

# 11) 工具鏈例子
# LLVM build:
# make LLVM=1
#
# 自訂 flags:
# make LLVM=1 KCFLAGS="-O3 -march=native -pipe"

# 12) menuconfig 記號提醒
# [*] = built in
# <M> = module
# / = search
# H = help

我如果要自己重寫一次,會把重點縮成一句話:先選一致的工具鏈,再用 menuconfig 改設定,external modules 先重建,最後用 diff 檢查自己到底動了什麼。這樣做不帥,但很穩。

這篇大部分是我根據 Gentoo Wiki 的內容整理成工作流,原始資料主要來自 Kernel/Configuration,另外參考了 KconfigLLVM build docsinstallkernel。命令與概念是衍生自原文,我的部分是把它整理成比較能直接抄走的版本。