Linux cross-compile dengan crosstool-ng
Pada artikel ini, saya coba menuliskan langkah-langkah membuat toolchain untuk cross compile program Linux. Os yang dipakai Debian Jessie, tentu saja applicable untuk selain Debian, sedangkan toolchain yang dipakai menggunakan crosstool-ng.
Sebelum ke how-to, ada baiknya dituliskan sedikit penjelasan tentang hal-hal yang berkaitan dengan cross-compile.
Architecture
Setiap CPU (Central Processing Unit) dibuat menurut architecture tertentu, dan setiap architecture berbeda dalam mengeksekusi program [1]. Beberapa contoh cpu architecture yang banyak dipakai diantaranya ada architecture x86, ini merupakan cpu 32 bit yang banyak dipakai di komputer desktop, laptop, serta server. Kemudian ada x86_64, prosesor architecture x86 versi 64 bit. Produk dari Intel dan AMD banyak dipakai untuk dua architecture tersebut.
Kemudian ada architecture ARM, dan seperti x86, ARM adalah 32 bit sedangkan ARM64 untuk yang 64 bit. Prosesor ARM banyak dipakai di system embed dan handheld seperti smartphone, sebagian besar smartphone yang ada saat ini menggunakan cpu ARM.
Selain x86 dan ARM, ada processor architecture yang terkenal di embedded system yaitu MIPS. MIPS banyak dipakai di sistem embed untuk jaringan seperti router dan switch. Beberapa router dan switch seperti Cisco, Ubiquiti dan MikroTik menggunakan MIPS.
Endianness
Setiap cpu, cara mengatur susunan byte (byte order) dalam memory berbeda-beda dan dikelompokkan menjadi dua bagian, little endian dan big endian [2]. Little dan big endian tidak ada pengaruhnya untuk data di memory yang besarnya hanya satu byte (8 bit), bedanya adalah ketika data di memory merupakan multiple byte atau lebih dari satu byte. Big endian (big-end) menyusun dan menginterpretasikan bahwa byte pertama atau byte paling awal adalah byte terbesar, sedangkan litte endian (little-end) sebaliknya.
Contoh untuk tipe data short integer yang besarnya 2 byte. Artinya ada 2 lokasi memory (satu blok memory besarnya 1 byte / 8 bit) yang apabila data dari dua lokasi memory itu dijumlahkan akan membentuk satu data short integer. Byte pertama berisi 0x12 atau 18 dalam desimal, byte kedua berisi 0x34 atau 52 dalam desimal.
Big endian mengartikan byte pertama adalah yang terbesar sehingga kalkulasinya adalah
18 x (2 ^ 8) + 52 = 4660
Sedangkan little endian mengartikan bahwa byte terakhir adalah yang terbesar, pertama yang terkecil, sehingga:
18 + 52 x (2 ^ 8) = 13798
Dari sini terlihat, kalau salah mengartikan endianness, maka hasil program pun akan salah.
Compiled language
Ada dua tipe program yang ada di komputer, yaitu tipe interpreted dan compiled. Program yang termasuk dalam tipe interpreted language tidak perlu di-compile dan biasanya disebut bahasa scripting, beberapa contoh ada bahasa Python, Perl, PHP, dsb.
Berbeda dengan interpreted language, bahasa tipe compiled language harus di-compile sebelum bisa dieksekusi atau dijalankan. Yang termasuk kategori ini diantaranya bahasa C, C++, Pascal, dsb. Program compiled biasanya berjalan lebih cepat daripada tipe interpreted language.
Proses kompilasi adalah proses menerjemahkan bahasa pemrograman yang dipahami manusia kedalam bahasa yang dipahami oleh cpu, program untuk meng-compile program disebut compiler. Berbeda dengan bahasa interpreted yang cukup sekali ditulis dan bisa berjalan di cpu apapun, bahasa compiled harus menyesuaikan tipe cpu yang dipakai.
Cross compile
Dalam proses compile program, ada tiga tipe cpu yang dipakai.
Build
, Build host adalah cpu dimana compiler dibuat.Host
, Host merupakan cpu dimana compiler akan digunakan untuk meng-compile program.Target
, Target merupakan cpu dimana program yang sudah di-compile akan berjalan.
Biasanya, untuk compile di komputer x86 dan yang semisalnya, build, host, dan target adalah komputer yang sama. Artinya compiler dibuat di komputer tersebut, kemudian compiler dijalankan di komputer tersebut untuk meng-compile program, dan program yang sudah di-compile akan berjalan di komputer itu.
Sedangkan untuk system embed, prosesnya berbeda. embedded system biasanya dibuat dengan sangat efisien dan resource yang terbatas. Contohnya beberapa jenis router SOHO yang mempunyai prosesor MIPS dengan speed hanya 400 MHz, memory 32 MB, dan storage 64MB. Dengan resource seperti ini tentu saja tidak mungkin kompilasi program dilakukan di router tersebut.
Proses cross-compile adalah proses meng-compile program dengan target cpu arhitecture yang berbeda. Misalnya, program di-compile di mesin Intel x86 seperti laptop atau komputer desktop, tapi program hasil kompilasi akan digunakan di cpu MIPS seperti router. Tools atau program-program yang digunakan untuk melakukan cross-compile disebut toolchain.
Toolchain dibentuk dengan beberapa program, diataranya:
binutils
, Program untuk memanage program binary, contohnya ld sebagai linker.gcc
, koleksi compiler yang dibuat oleh GNU.C library
untuk embedded system biasanya menggunakan uclibc meskipun ada juga yang menggunakan glibc.
Proses membuat toolchain merupakan proses yang sangat kompleks dan memerlukan usaha trial and error yang tidak mudah [3]. Thanks to FOSS community, kita tidak perlu melalui proses yang rumit itu. Salah satunya crosstool-ng, tool ini melakukan proses otomasi membuat toolchain seperti patching, compiling, dan linking. Dengan crosstool-ng kita bisa dengan mudah tinggal menjalankan script, memberikan input dan setelah proses selesai, toolchain sudah jadi dan siap digunakan untuk meng-compile program.
Crosstool-ng
Sebelum proses building, kita perlu mengetahui beberapa parameter untuk crosstool-ng, diantaranya cpu architecture, endianness, c library yang dipakai. Untuk case saya beberapa waktu lalu, cpu architecture MIPS 64 bit, c library menggunakan GNU libc versi 2, dan big endian.
Untuk mencari endianness, ketik lscpu di terminal:
Architecture: mips64
Byte Order: Big Endian
CPU(s): 2
On-line CPU(s) list: 0,1
Thread(s) per core: 1
Core(s) per socket: 1
Socket(s): 2
L1d cache: 32K
L1i cache: 37K
L2 cache: 1024K
Output dari Byte Order adalah Big Endian.
Pada beberapa system, command lscpu tidak ada sehingga menggunakan cara lain untuk mengetahui endianness
$ ## Big endian output 0
$ echo -n I | od -to2 | awk 'FNR==1{ print substr($2,6,1)}'
$ 0
$
$ ## Output 1 untuk little endian
$ echo -n I | od -to2 | awk 'FNR==1{ print substr($2,6,1)}'
$ 1
Untuk mengetahui cpu architecture dan OS, contoh output untuk notebook saya yang 32 bit
uname -a
Linux DEATH-STAR 3.16.0-4-686-pae #1 SMP Debian 3.16.7-ckt20-1+deb8u1 (2015-12-14) i686 GNU/Linux
Setelah parameter diketahui, berikutnya ke proses build.
Untuk Debian dan sejenisnya, pastikan paket build-essential sudah terinstall
dpkg -l | grep build-essential
# jika belum terinstall
apt-get install build-essential
Download crosstool-ng, versi terakhir saat artikel ini ditulis adalah 1.22
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2
Extract tarball dan compile crosstool-ng
tar -xvjf crosstool-ng-1.22.0.tar.bz2
cd crosstool-ng-1.22
./configure --prefix=/usr/local
make
# dengan user root
make install
crosstool-ng sudah terinstall di /usr/local. Selanjutnya buat direktori untuk toolchain. Direktori untuk toolchain dalam contoh ini dinamai crosstool dengan subdirektori build untuk proses build dan subdirektori target untuk toolchain yang sudah siap digunakan.
mkdir -p ~/crosstool/{build,target}
cd ~/crosstool/build
ct-ng list-samples
Dari output sample, yang paling mendekati adalah mipsel-unknown-linux-gnu. mipsel-unknown-linux-gnu adalah contoh konfigurasi untuk target mips little endian dengan c library gnu libc. Karena target dalam kasus ini berbeda, target endianness big endian, maka konfigurasi perlu disesuaikan dengan ct-ng menuconfig
ct-ng show-mipsel-unknown-linux-gnu
ct-ng mipsel-unknown-linux-gnu
ct-ng menuconfig
Di bagian paths and misc options, sesuaikan target direktori sesuai dengan yang sudah dibuat diatas
(${HOME}/crosstool/target) Prefix directory
Di bagian Target Options, ubah endianness ke Big Endian. Pilih exit kemudian save. Setalah itu build toolchain dengan command ct-ng build
ct-ng build
Command ct-ng build akan secara otomatis mendownload tool yang diperlukan seperti binutils, gcc, libc, dsb. ct-ng build juga akan melakukan patching source code dan kemudian compile secara otomatis. Proses ini cukup lama, lebih dari 2 jam dengan prosesor Intel Atom, prosesor yang lebih tinggi seharusnya lebih cepat.
Setelah selesai, toolchain sudah ada di direktori ~/crosstool/target dan sudah bisa digunakan
export PATH=$PATH:$HOME/crosstool/target/bin
# Tes compile program
mips-unknown-linux-gnu-gcc -g -Wall program.c -o program
Program yang sudah di-compile dengan crosstool-ng tinggal di-copy ke mesin target, di-set execution bit nya dan bisa dijalankan.
Refs: