#1 2011-12-14 15:02:04
[Tomato USB(泰迪熊)] 交叉編譯器的使用
在網路上有諸多程式, 原始碼是C語言. 要將程式用於機器上, 得事先編譯為機器能懂的二進位執行檔. 以微軟的術語來說, 就是.exe, .com的執行檔. 若未編譯, 只能看的到, 吃不著.
為何使用交叉編譯器? 在原生機器(Router)上面編譯, 相容性最好, 但機器的CPU太慢, RAM太少, 導致編譯費時, 一覺醒來, 可能還沒編譯好. 所以使用x86, amd64的PC, 藉PC的高速運算, 將C原始碼交叉編譯為目標機器(Router)的執行檔.
泰迪熊放在捷克的原始碼, tomato-ND-USBmod是K24, tomato-RT, tomato-RT-N是K26. 因泰迪熊原始碼支援USB, 依泰迪熊原始碼所衍生的土司超人等諸多版本, 也是使用相同的交叉編譯器. 而泰迪熊的交叉編譯器來源, 可能是Lly. 若PC是64位元, 可使用Lly釋出的x86_64 Toolchain.
編譯原始碼前, 先準備編譯平台GNU/Linux.(廢話!) 不論是安裝在虛擬機器, 或是另一顆硬碟都行. 選用自己喜歡的Linux發行版本, 安裝必要套件, 營造編譯平台. 安裝的必要套件可參考Lly wiki, 或twtomato相關的.rar檔案. 套件名稱依Linux發行版本的不同, 或許會有些微差異. 所以得自己熟悉套件管理程式, 搜尋, 安裝套件.
安裝git套件, 參考這篇, 透過git下載原始碼. 先決定要使用哪個衍生版本, 再下載正確的分支. 下載完畢後, 您可嘗試編譯韌體, 順道測試編譯平台相關套件是否安裝妥當. 編譯韌體不是本文重點, 略過不提.
git下載的原始碼, 內含交叉編譯器. 以K26來說:
$ ll ~/Tomato/tomato-RT/tools/brcm/K26/hndtools-mipsel-uclibc-4.2.4/
total 44
drwxr-xr-x 2 abel abel 4096 Jun 3 2011 bin/
drwxr-xr-x 17 abel abel 4096 Jun 3 2011 include/
drwxr-xr-x 2 abel abel 4096 Jun 3 2011 info/
-rw-r--r-- 1 abel abel 93 Jun 3 2011 info.mk
drwxr-xr-x 5 abel abel 4096 Jun 3 2011 lib/
drwxr-xr-x 3 abel abel 4096 Jun 3 2011 libexec/
drwxr-xr-x 4 abel abel 4096 Jun 3 2011 man/
lrwxrwxrwx 1 abel abel 19 Jun 3 2011 mipsel-linux -> mipsel-linux-uclibc/
drwxr-xr-x 4 abel abel 4096 Jun 3 2011 mipsel-linux-uclibc/
drwxr-xr-x 4 abel abel 4096 Jun 3 2011 share/
drwxr-xr-x 2 abel abel 4096 Jun 3 2011 stamp/
drwxr-xr-x 2 abel abel 4096 Jun 3 2011 target-utils/
bin目錄內有mipsel開頭的gcc等執行檔與連結, 這些就是在PC上交叉編譯要用到的執行檔. gcc版本是4.2.4, uClibc呢? 查lib目錄, uClibc版本是0.9.30.1. 所以, 若使用Lly釋出的Cross Toolchain, 要選擇對應正確的版本.
好, 先來交叉編譯試試, 建立自信心. 取最簡單的CPU與RAM效能測試的原始碼openwrt_cpu_bench_v06.c來開刀. 使用文字編輯器, 貼上原始碼, 注意斷行, 存檔為openwrt_cpu_bench_v06.c
編譯:
$ ~/Tomato/tomato-RT/tools/brcm/K26/hndtools-mipsel-uclibc-4.2.4/bin/mipsel-linux-gcc -o cpubench openwrt_cpu_bench_v06.c
檢查:
$ file cpubench
cpubench: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
將編譯後的cpubench上傳(FTP, SCP等)到Router, 變更檔案屬性為可執行, 測試:
# chmod +x cpubench
# ./cpubench
如果看到效能測試結果, 恭喜, 搞定第一步了.
參考Tomato Utilities, 交叉編譯是經由script來執行. 以微軟的術語來說, 就是批次檔.bat. 那也來參照測試.
$ nano build.sh
#!/bin/sh
export PATH=$HOME/Tomato/tomato-RT/tools/brcm/K26/hndtools-mipsel-uclibc-4.2.4/bin:$PATH
mipsel-linux-gcc -o cpubench openwrt_cpu_bench_v06.c
$ chmod u+x build.sh
$ ./build.sh
經由指定環境變數$PATH, 可省事不少. script入門, 請參考網中人, 鳥哥. 理解script後, 您可能高呼: 阿母, 我出運了! 還沒啦, 繼續吃鐵牛運功散吧.
交叉編譯前, 先決定編譯後的程式放在目標平台(Router)哪個目錄.
# echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/home/root:/mmc/sbin:/mmc/bin:/mmc/usr/sbin:/mmc/usr/bin:/opt/sbin:/opt/bin:/opt/usr/sbin:/opt/usr/bin:
/bin, /usr, /sbin, 唯讀, 想都別想. /home/root, 記憶體, 關機後, 程式就不見蛋了. 所以只能放在USB HD等, 掛載到對應的目錄. JFFS? 行, 但得想想有多少空間可存放程式.
在PC的Linux創建目標平台的目錄架構. 假設您編譯後的程式, 預計放在/opt/usr/bin內, 也就是將/opt/usr當成根目錄.
$ mkdir -p ~/Work/opt/usr
$ su
# cd /opt
# ln -s /home/使用者/Work/opt/usr usr
為何這樣搞?
1. 因為編譯後的程式, 一般都放在/usr/local等相關目錄, 參考後面的configure說明.
2. 目標平台的/usr/local是唯讀, 無法寫入, 也不是預計放置程式的目錄.
3. 藉由指定--prefix=/opt/usr, make install會將編譯後的執行檔, 函式庫, 說明等, 放在/opt/usr.
4. 若用root編譯, 權限太高, 迷糊手賤時, 會誤刪系統檔案, 搞垮整個PC的Linux.
或許您會說, 那我建個/opt/usr目錄, 允許使用者有權限寫入就好了. 行, 當然可以, 電腦是您的, 可摔可踢, 任君自由.
同理, 若預計放在目標平台的/jffs, 也是依自己的方式操作.
接著就是找原始碼. 先選套小型的工具程式, 就Wget好了. Wget原始碼在何處? 在Google找到原始碼網站, 下載, 沒問題. 但另有一個簡便的方法, 就是查看Linux套件資訊. 以Optware來說,
# ipkg-opt info wget
Package: wget
Version: 1.12-2
Conflicts: wget-ssl
Status: unknown ok not-installed
Section: net
Architecture: mipsel
maintainer: NSLU2 Linux
MD5Sum: 3ad0feecfc0198045068159e238b6d83
Size: 186025
Filename: wget_1.12-2_mipsel.ipk
Source: http://ftp.gnu.org/pub/gnu/wget/wget-1.12.tar.gz
Description: A network utility to retrieve files from the Web
Source就告訴您來源了. GNU在國網中心或學術網路都有鏡射, SourceForge國網中心也有鏡射, 就不必捨近求遠了. 當然, 也可由PC的Linux, 透過套件管理程式查詢相關資訊.
如何下載? 說這些太囉唆了, 照樣略過不提. 解壓縮後的原始碼, 必先參閱README, INSTALL等說明, 裡面會告訴你許多密技. 甚麼? 英文看不懂! 別哭爹喊娘了, 您還沒到編譯錯誤的頭痛階段呢! 這點小事, 聰明的您應該知道翻譯工具吧. 如果這也不知道, 我勸您趁早收手, 天冷, 較早睡, 較有眠.
$ ./configure -h
`configure' configures wget 1.13.4 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
-q, --quiet, --silent do not print `checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for `--cache-file=config.cache'
-n, --no-create do not create output files
--srcdir=DIR find the sources in DIR [configure dir or `..']
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, `make install' will install all the files in
`/usr/local/bin', `/usr/local/lib' etc. You can specify
an installation prefix other than `/usr/local' using `--prefix',
for instance `--prefix=$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/wget]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]
Program names:
--program-prefix=PREFIX prepend PREFIX to installed program names
--program-suffix=SUFFIX append SUFFIX to installed program names
--program-transform-name=PROGRAM run sed PROGRAM on installed program names
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-opie disable support for opie or s/key FTP login
--disable-digest disable support for HTTP digest authorization
--disable-ntlm disable support for NTLM authorization
--disable-debug disable support for debugging output
--disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors
--disable-largefile omit support for large files
--enable-threads={posix|solaris|pth|win32}
specify multithreading API
--disable-threads build without multithread safety
--disable-nls do not use Native Language Support
--disable-rpath do not hardcode runtime library paths
--disable-ipv6 disable IPv6 support
--disable-iri disable IDN/IRIs support
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-ssl disable SSL autodetection
--with-ssl={gnutls,openssl} specify the SSL backend. GNU TLS is the default.
--with-gnu-ld assume the C compiler uses GNU ld default=no
--with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
--without-libiconv-prefix don't search for libiconv in includedir and libdir
--with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib
--without-libintl-prefix don't search for libintl in includedir and libdir
--with-libpth-prefix[=DIR] search for libpth in DIR/include and DIR/lib
--without-libpth-prefix don't search for libpth in includedir and libdir
--with-libssl-prefix[=DIR] search for libssl in DIR/include and DIR/lib
--without-libssl-prefix don't search for libssl in includedir and libdir
--with-libgnutls-prefix[=DIR] search for libgnutls in DIR/include and DIR/lib
--without-libgnutls-prefix don't search for libgnutls in includedir and libdir
--with-libidn=DIR Support IDN/IRIs (needs GNU Libidn)
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory
CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to .
因為不打算使用SSL, 所以改良後的script如下:
$ nano build.sh
#!/bin/sh
Name=wget
Ver=1.13.4
export PATH=$HOME/Tomato/tomato-RT/tools/brcm/K26/hndtools-mipsel-uclibc-4.2.4/bin:$PATH
export CC=mipsel-linux-gcc
export CPP=mipsel-linux-cpp
cd $Name-$Ver
make distclean
./configure \
--host=mipsel-linux \
--target=mipsel-linux \
--prefix=/opt/usr \
--without-ssl
[ $? -eq 0 ] && make && make install
如果您問到CFLAGS, CPPFLAGS等, 有何作用? 這難以三言兩語道盡, 請自行man或info gcc, ld等.
如果您注意之前編譯的cpubench, MIPS32 version 1 (SYSV), 這表示是MIPS R1/R2的機種可吃. 若要編譯為MIPS R2專用的呢?
$ man gcc
MIPS Options -EL -EB -march=arch -mtune=arch -mips1 -mips2 -mips3 -mips4
-mips32 -mips32r2 -mips64 -mips64r2 -mips16 -mno-mips16 -mflip-mips16
...
有答案了吧! 當然, 進階還可微調相關參數, 可參考泰迪熊或Rodney的Tomato Utilities是怎麼玩的.
如果您的PC是多核心CPU, make可加入-j參數. 詳情請man make.
開工, 編譯.
$ ./build.sh
啪拉啪拉跑一堆訊息出來. 若有興趣, 可將螢幕輸出導向檔案存檔, 慢慢研究. 參考網中人, 鳥哥的教學.
如果編譯沒出錯, /opt/usr/bin/wget就是執行檔了. 除執行檔外, 還有相關的說明文件. 使用tree指令查看整個編譯結果.
$ tree /opt/usr/
/opt/usr/
├── bin
│ └── wget
├── etc
│ └── wgetrc
└── share
├── info
│ └── wget.info
└── man
├── man1
│ └── wget.1
└── whatis
6 directories, 5 files
至此, 我建議您將整個/opt/usr目錄打包壓縮, 省去日後再編譯的時間.
$ mkdir ~/Done
$ cd /opt/usr
$ tar -czf ~/Done/wget-1.13.4.tar.gz *
同樣的, 上傳到目標平台, 測試結果.
日後多編譯幾套程式後, 您就會知道如何調整script. 而因程式是放在USB HD等儲存空間, 也就暫時先不管縮小程式體積與最佳化等. 有興趣者, 可研讀gcc相關文件. 更進一步就是改良原始碼, 回饋社群了...
收工!
離線
#2 2015-11-18 13:31:53
Re: [Tomato USB(泰迪熊)] 交叉編譯器的使用
關於 搭建編譯環境 這邊有一篇 供入門者參考 "從零開始學習OpenWrt:刷機 + 使用 + 編譯教程"http://upsangel.com/openwrt/openwrt-beginner-guide/
離線
相關討論主題
主題 | 回覆 | 點閱 | 最後發表 |
---|---|---|---|
置頂 |
33 | 85118 | 2024-10-23 08:28:27 作者 huiduo |
置頂 |
1625 | 3031799 | 2024-04-28 12:35:05 作者 s87311 |
|
155 | 348185 | 2022-12-08 17:08:17 作者 dir868l |
置頂 |
54 | 207407 | 2022-09-15 12:25:01 作者 chiachu |
|
222 | 502870 | 2022-09-14 14:54:52 作者 chiachu |