GCC Spec Files

来源:互联网 发布:mac 汉仪 启功体下载 编辑:程序博客网 时间:2024/04/28 15:54
 
Open source 常見的 toolchain,就非 gcc 和 binutils 系列莫屬。然而,商業公司提供的 toolchain,往往必需安裝在特定目錄,這總是惹惱有潔癖者,如我。然而,若將 toolchain 任意搬動位置,則會曝露 gcc 的一個缺陷,gcc 找不到其它幅程式或 library 。這是因為 gcc 假設 library 和 toolchain 會安裝在固定位置,於是在 build toolchain 時,就將這些路徑設定死。於是,對於不想重新 build toolchain,或只拿到 binary 的 user 而言,就必需使用 -nostdlib 這個參數,然後加上一堆 -I 和 -L 參數,使 gcc 能正確的找到 library 。

另外,一些 toolchain ,因為平台的因素,無法使用 gcc 預設好的參數內容。於是要強迫使用者必需下一堆固定的參數,例如: Android 就在其 build system 裡,為 gcc 設定一堆和平台相關的參數,像是 -mthumb。於是,若使用該 toolchain 自行開發軟體,就誓必要找出這些參數,並正確的設定為 gcc 的參數。這完全是一堆苦工。其實,只要作 toolchain 的人多用點心,使用 toolchain 其實可以不用這麼累。

sysroot

一般而言,gcc 會到 /usr/lib 和 /usr/include 下找 library 、 header files 和其它一些 start files 、 end files。當我們在 build gcc 設定 --prefix=/path/to/xxx ,則 gcc 安裝到 /path/to/xxx ,也在該目錄下的 lib/ 和 include/ 找 library 和 header 。旦,若裝 gcc 移到其它目錄時, gcc 會找不到這些 library 。這時,我們可以在呼叫 gcc 時,給予 --sysrooot=/new/path/to/xxx 參數。如此,gcc 就會改以 /new/path/to/xxx 為參考目錄,去搜尋所需的幅程式和 library 等。

然而,要注意的是, ld 必需要能 support --sysroot。這必需在 configure binutils 時,給予 --sysroot=xxx 參數。xxx 可以是任意目錄,不一定是實際安裝的位置。這個參數的主要目的是使 ld 啟動 --sysroot 的功能。

Spec File

--sysroot 解決了一部分問題,但有更大部分的問題是 toolchain 往往要你設定一些固定參數。例如,你會需要設定一些 header file 的目錄,並且設定一些平台有關的參數。這些設定往往又臭又長,很容易出錯。其實,這些參數可以寫在 spec file 裡,使用者就不用一再的重復指定這些參數。例如,以下是我為Android 設定的 spec file 的內容

#!raw%rename cc1_android old_cc1_android%rename cc1plus_android old_cc1plus_android*android_root:%R/../../../../../*android_product:generic*ccflags:%{!march=:-march=armv5te} %{!mtune=:-mtune=xscale} -mthumb \-fno-strict-aliasing -finline-limit=64 -mthumb-interwork \-fno-short-enums \-D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5TE__ \-isystem %(android_root)bionic/libc/arch-arm/include/ \-isystem %(android_root)bionic/libc/include \-isystem %(android_root)bionic/libstdc++/include \-isystem %(android_root)bionic/libc/kernel/common \-isystem %(android_root)bionic/libc/kernel/arch-arm \-isystem %(android_root)bionic/libm/include \-isystem %(android_root)bionic/libm/include/arch/arm \-isystem %(android_root)bionic/libthread_db/include \-include %(android_root)system/core/include/arch/linux-arm/AndroidConfig.h \-isystem %(android_root)system/core/include/arch/linux-arm/*cc1_android:%(old_cc1_android) %(ccflags)*cc1plus_android:%(old_cc1plus_android) %(ccflags)

像 Android 的 header files 就散置在一堆目錄,於是 build system 就指定了一堆參數。如果你自己寫個小程式,又不使用 Android 的 build system 時,就必需自己指定這些參數。於是,有人寫了一個 perl 的小程式,作為 gcc 的 wrapper ,幫你指定一些參數。其實不用這麼麻煩,只需像上例一樣,設定一個 spec file ,在執行 gcc 時加上一個參數就能自動套用這些參數

  • gcc -specs myandroid.specs

spec file 設計的很有彈性,可以對參數列的內容進行修改,也可以加入條件性的參數。像上例 {!march=:...} 就是指定,當參數列沒有指定 -march= 的參數時,就在 cc1 的參數例加入 -march=armv5te。另外我還指定了一些巨集和 -system 指定一些 header file 的路徑。而這些路徑是相對於 %R ,也就是 --sysroot 所指定的路。例如 --sysroot=/my/path/to/the/kkk/ ,則 %(android_root)bionic/libm/include/arch/arm 就會對應到 /my/path/to/th/kkk/../../../../../bionic/libm/include/arch/arm 。

更進一步

--sysroot 的預設內容,其實是可以設定成相對於 gcc 本身的位置。在 configure 時,若

configure --with-sysroot='${exec_prefix}/xxx'

則編譯出來的 gcc ,其 sysroot 就會相對於其執行路徑。如此 user 甚至不必再手動指定 --sysroot 。

結論

有了 spec files ,我們只需設定 -specs 和 --sysroot 兩個參數就能解決所有的問題。其實在建 toolchain 時,應該再多花一點時間,幫 user 作好 spec files 。這樣的 toolchain 才方便使用。關於 spec file 更詳細的內容,請參考Spec Files

原创粉丝点击