Zephyr RTOS 開發記錄: Mac OSX 下 SDK 編譯

Zephyr RTOS 開發記錄: 基本環境建立 一文中提到了我們如何安裝 Zephyr SDK 到 Linux 系統來進行開發,那如果我想要在 Mac OSX 上面開發要怎麼辦呢?

由於 Zephyr SDK 目前僅提供 Linux 的版本,因此在 Mac OSX 中我們必須自己透過 crosstool-ng 去編譯我們自己的 SDK。

安裝依賴的相關套件

第一步要做的,當然就是安裝相關套件啦,這點我們直接透過 homebrew 來安裝

coldnew@MacOSX ~ $ brew install gettext qemu help2man mpfr gmp coreutils wget

接下來我們要安裝 GNU 的 grep 命令來替代系統內建的 grep 命令

coldnew@MacOSX ~ $ brew tap homebrew/dupes
coldnew@MacOSX ~ $ brew install grep --default-names

接著,安裝我們需要用的程式: crosstool-ng

coldnew@MacOSX ~ $ brew install crosstool-ng

建立編譯環境

安裝好 crosstool-ng 後,我們需要建立一個 Case Sensitive 的 HFS+ 硬碟來讓 MacOSX 可以順利編譯,以下為我建立這顆硬碟所用的命令 (佔 10G 的硬碟空間)

hdiutil create -volname CrossToolNG -type SPARSE \
        -fs 'Case-sensitive Journaled HFS+' \
        -size 10g CrossToolNG.sparseimage

完成後,打開 CrossToolNG.sparseimage 這個映像檔,他會被掛載到 /Volumes/CrossToolNG

coldnew@MacOSX ~ $ open CrossToolNG.sparseimage

接著我們就切換到 /Volumes/CrossToolNG 來準備進行我們的編譯,順便建立一個 src 資料夾讓 crosstool-ng 存放他下載的原始碼

coldnew@MacOSX ~ $ cd /Volumes/CrossToolNG && mkdir src

我們先複製 Zephyr 裡面提供的設定檔到當前目錄

coldnew@MacOSX /Volumes/CrossToolNG $ cp ${ZEPHYR_BASE}/scripts/cross_compiler/x86.config .config

如果你有什麼設定要修正的話,可以使用 ct-ng menuconfig 來進行修改

coldnew@MacOSX /Volumes/CrossToolNG $ ct-ng menuconfig

另外,在進行編譯前要確認以下幾個設定是否和你編譯目錄 (/Volumes/CrossToolNG) 一致

CT_LOCAL_TARBALLS_DIR="/Volumes/CrossToolNG/src"
# CT_SAVE_TARBALLS is not set
CT_WORK_DIR="${CT_TOP_DIR}/.build"
CT_PREFIX_DIR="/Volumes/CrossToolNG/x-tools/${CT_TARGET}"
CT_INSTALL_DIR="${CT_PREFIX_DIR}"

都確認沒問題後,就開始我們的編譯吧 gogogo ~

coldnew@MacOSX /Volumes/CrossToolNG $ ct-ng build

接著你可以去泡杯咖啡或出去走走,編譯工具鍊 (toolchain) 很花時間的

設定編譯環境

完成編譯我們要的工具鍊 (toolchain) 後,我們可以在 /Volumes/CrossToolNG 看到以下的資料夾,其中 x-tools 就是我們編譯出來的結果

coldnew@MacOSX /Volumes/CrossToolNG $ tree -L 1.
. <b>
├── build.log <g>
├── config -> /usr/local/Cellar/crosstool-ng/1.22.0/lib/crosstool-ng-1.22.0/config <lb>
├── config.gen <b>
├── src <b>
└── x-tools <b>

4 directories, 1 file

最後,在你的 ~/.zephyrrc 設定這些環境變數就可以去嘗試編譯你的 Zephyr kernel 看看囉 ~

coldnew@MacOSX ~ $ vim ~/.zephyrrc

export XTOOLS_TOOLCHAIN_PATH=/Volumes/CrossToolNG/x-tools
export ZEPHYR_SDK_INSTALL_DIR=${XTOOLS_TOOLCHAIN_PATH}
export ZEPHYR_GCC_VARIANT=xtools

可能會遇到的錯誤

在 Mac OSX 下編譯非 Apple 官方的東西常常會出現一堆奇怪的錯誤,有時是因為 XCode 的改動,有時是因為你透過 homebrew 安裝了其他命令和 Mac OSX 內建的有衝突。

下面紀錄我在這次編譯遇到的錯誤:

stat: cannot read file system information for '%Lp'

如果你遇到了這個問題,哪很有可能是因為你的系統同時也裝了 GNU coreutils 導致 crosstool-ng 調用的命令是 GNU 的 stat 命令,而不是系統內建的 stat 命令。

[INFO ]  Performing some trivial sanity checks
[INFO ]  Build started 20160229.010627
[INFO ]  Building environment variables
[EXTRA]  Preparing working directories
[00:01] / stat: cannot read file system information for '%Lp': No such file or directory
[ERROR]
[ERROR]  >>
[ERROR]  >>  Build failed in step '(top-level)'
[ERROR]  >>
[ERROR]  >>  Error happened in: CT_DoForceRmdir[scripts/functions@460]
[ERROR]  >>        called from: main[scripts/crosstool-NG.sh@238]
[ERROR]  >>
[ERROR]  >>  For more info on this error, look at the file: 'build.log'
[ERROR]  >>  There is a list of known issues, some with workarounds, in:
[ERROR]  >>      '/usr/local/Cellar/crosstool-ng/1.22.0/share/doc/crosstool-ng/crosstool-ng-1.22.0/B - Known issues.txt'
[ERROR]
[ERROR]  (elapsed: 0:00.70)
[00:01] / make: *** [build] Error 1

我們可以透過 which 命令去檢查是否真的用到 GNU coreutilsstat 命令

coldnew@MacOSX ~ $ which stat
/usr/local/opt/coreutils/libexec/gnubin/stat

我自己由於不常用 stat 命令,所以選擇移除已經編譯好的 stat 連結,改用系統內建的 stat

coldnew@MacOSX ~ $ rm /usr/local/opt/coreutils/libexec/gnubin/stat

crosstool-ng 要找的 stat 則是在 /usr/bin

coldnew@MacOSX ~ $ which stat
/usr/bin/stat

ld: library not found for -lcrt0.o

Zephyr 提供的 .config 有打開靜態連結 (static link) 相關的設定,於是你會遇到這樣的狀況,解法參考 issue #31 移除 static link 相關設定。

[INFO ]  Performing some trivial sanity checks
[INFO ]  Build started 20160229.011000
[INFO ]  Building environment variables
[EXTRA]  Preparing working directories
[ERROR]    clang: error: linker command failed with exit code 1 (use -v to see invocation)
[ERROR]
[ERROR]  >>
[ERROR]  >>  Build failed in step 'Checking that gcc can compile a trivial statically linked program (CT_WANTS_STATIC_LINK)'
[ERROR]  >>        called in step '(top-level)'
[ERROR]  >>
[ERROR]  >>  Error happened in: CT_DoExecLog[scripts/functions@216]
[ERROR]  >>        called from: main[scripts/crosstool-NG.sh@554]
[ERROR]  >>
[ERROR]  >>  For more info on this error, look at the file: 'build.log'
[ERROR]  >>  There is a list of known issues, some with workarounds, in:
[ERROR]  >>      '/usr/local/Cellar/crosstool-ng/1.22.0/share/doc/crosstool-ng/crosstool-ng-1.22.0/B - Known issues.txt'
[ERROR]
[ERROR]  (elapsed: 0:03.48)
[00:05] / make: *** [build] Error 1

我自己是將 .config 裡面這兩個靜態連結 (static link) 相關的函式庫設定為取消後就可以正常編譯囉~

CT_WANTS_STATIC_LINK=n
CT_CC_GCC_STATIC_LIBSTDCXX=n