📌 置頂: 請把任何比你弱勢的用路人當作你的至親對待。跟前車保持安全車距 (2秒以上)。

Debug f9-kernel make config 的 ncurses 按鈕顏色問題

In

,

Tags:



by

Linux kernel 與 f9-kernel 按鈕

今天要講的是修改 f9-kernel menu config 下排按鈕顏色跑掉的問題。

會發現這個問題是因為把 f9-kernel clone 下來想要編譯,在要做 config 的時候發現這個問題。可以從上圖左邊看到 Linux kernel 的 make menuconfig 下排的 button 是有對比顏色的 (<Select> tag active 是黃色的、<Exit> tag 是紅色的),上圖右邊 f9-kernel make config 的部份則是灰色的而已。

這個 bug 花了 3 小時解完,實在是因為我是新手才會遇到這樣的問題。下面會紀錄我這次的 debug 步驟,以及遇到這種情況可以怎麼解的步驟,寄望後人不要為了這種鳥問題而被困住 3 小時。

 

0. Linux kernel 好像也有這個東西…

Linux kernel 也有相對應於 f9-kernel make config 的 make menuconfig,了解這件事情之後,我先strace make menuconfig看發生什麼事情,之後轉用ltrace make menuconfig觀察。不過沒有觀察到什麼有用的東西。

1. 找尋 make config實際發生的事情

第一步先找尋 make config 實際發生的事情,點開 topdir 的 Makefile 來看,唉,跟任何大一點的 C project 的 Makefile 一樣,根本就讓人看不懂。

轉頭去看 Documentation 下的 build-system.txt 才了解到,Makefile process 時,相關的檔案其實都被放置在 mk/ 底下,其中 brief explaination 的部份介紹到 generic.mk 是處理 Make config 的部份。詢著線索往下看到 generic.mk,結果發現跟絕大多數大一點的 C project 的 Makefile 一樣,根本就讓人看不懂 (其實好懂一點了)。

2. generic.mk 之後,發生什麼事情?

憑藉著我薄弱的 make 知識,細看一下其實還是看的懂怎麼呼叫到 config 的部份,是在最下面這邊:

但是問題來了,$(out_host) 到底是什麼鬼東西,從全部檔案搜尋發現是定義在最上層 Makefile 的部份,是 output directory 有關 host build 的路徑,指向 build/host

好啦,找到 build/host ,可是裏面卻只有一個 mconf 執行檔外加沒什麼關係的 c files,問題變成該怎麼找到 mconf 原始碼呢?

幸好有 fzf ,回到 topdir 輸入 mconf.c ,原來是在 external/kconfig/mconf.c 這個路徑裏面呢。

fzf

3. 顏色設定錯誤?

翻查了一下,顏色定義在 lxdialog/util.c 裏面,對照 Linux kernel 與 f9-kernel 的並無差異。 (崩潰)

4. mconf.c 如何運作

這邊其實是花最多時間的部份,先去查了 kernel menuconfig 的背景知識之後,了解到有 ncurses、lxdialog 這兩者的參與,同時 kconfig 就是 kernel 中負責 config 相關的元件。

接著就是 trace code,先從 mconf.c 開始 tracing,執行路徑是 main -> conf -> dialog_menu,中間有去 diff kernel 跟 f9-kernel 在 kconfig 資料夾裏面的檔案有沒有不同。而 dialog_menu 定義在 menubox.c 當中,把其中的 code 逐一註解之後,鎖定到這塊 code:

這段 code 就是實際上 dialog_menu 在渲染 menu 時候用到的部份,流程看 code 就知道,先抓大小、渲染陰影、畫出 dialog、畫出匡線、menu、items …etc ,從上面開始註解掉發現是在這段出問題:

wbkgdset 的用途是調整背景顏色,如果把 wbkgdset 註解掉,那這樣下面的按鈕就會正常的顯示出顏色,問題是 menu background 就會是黑色,不優。

wbkgdset comment, but background color will be black
wbkgdset comment, but background color will be black

這下好了,是 wbkgdset 出問題嗎?翻找同時也有用到 wbkgdset 的 textbox.c,人家硬是沒有問題啊啊啊啊啊啊啊啊啊 (回音 * 100)

textbox button was fine
textbox button was fine

5. lxdialog 出問題?

嘗試把 kernel lxdialog 直接複製到 f9-kernel 裏面,結果完全不能用,裏面有些部份 f9-kernel 改的很多,git blame 一下才發現原來是因為 f9-kernel 的 kconfig 是從 olibc 的 kconfig 抽取出來使用的。裏面有個檔案讓人很害怕,寫著:

> BIG.FAT.WARNING

This is NOT the official version of dialog. This version has been
significantly modified from the original. It is for use by the Linux
kernel configuration script. Please do not bother Savio Lam with
questions about this program.

有點要崩潰了……

6. git bisect?

途中 git bisect 了一下,可是實在沒什麼用,一開始就是錯的了,沒有好過。

7. 到底編譯的給的 Flags 是什麼?

現在排除 mconf.c 的問題,lxdialog 看起來也是好的,唯一關鍵的 wbkgdset 在 textbox 跟 Linux kernel 都可以執行。

這到底是什麼狀況啊啊啊啊。

因為剛剛把 kernel 的檔案全部 copy 到 f9-kernel,發現有 .textbox.o.cmd 這樣的檔案,裏面有編譯執行的指令

cmd_scripts/kconfig/lxdialog/menubox.o := gcc -Wp,-MD,scripts/kconfig/lxdialog/.menubox.o.d -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89 -D_GNU_SOURCE -DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1 -DLOCALE -c -o scripts/kconfig/lxdialog/menubox.o scripts/kconfig/lxdialog/menubox.c

埃呀,感覺跟 f9-kernel 的不一樣耶,看到 -DCURSES_LOC 的部份,趕緊來 grep 一下。

原來在 check-lxdialog.sh 裏面啊。

8. check-lxdialog.sh

這個檔案可以檢查 ldflags、ccflags 等參數,我以為就這樣而已,跟編譯沒有關係。後來才發現到,Makefile 有用到這個 sh,而且裏面的 echo 是會拿去編譯用的 (上面 Makefile 沒有 -DCURSES_LOC 就應該要有警覺了)。

回頭看了一下,跟 kernel 差了一點,kernel 不知道為何有多加 -DNCURSES_WIDECHAR=1,我到之後才知道這就是關鍵……

9. 如何加上 cflags?

反正高大上的 Makefile 妳一定看不到 CFLAGS 或是 LDFLAGS 直接露出,所以又想直接用 gcc 編譯看看 (失敗)、學 ncurses helloworld (失敗)、總之就是很失敗,花了很多時間…。

10. git log check-lxdialog.sh

到這邊才找到跟這個 macro 可能有關 (也只會跟 -DNCURSES_WIDECHAR 有關了,幾乎一模一樣的狀況下只有編譯條件不一樣而已),回頭去 git log check-lxdialog.sh,還真的找到問題咧。

vanilla kernel commit: be8af2d54a66911693eddc556e4f7a866670082b,說明使用 pkg-config 來設定 ccflags 的部份,就是在這個 commit 把 -DNCURSES_WIDECHAR=1 加上去的。
於是我把 ccflags 跟 ldflags 的部份複製到 f9-kernel 裏,重新make config一次。

after fixed check-lxdialog.sh

God,終於修正成功,原因是編譯的 macro 不同!

後記

花了3、4個小時解這個問題,送了 PR 上去,打包收工。

反省一下,應該要更理解 make 的運作,同時 git log 搜尋以前有沒有發生過相同的問題。

 


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.