Just moozing

Before you can check your notes, you must make them…

Cross compile in Debian

with 9 comments

As mentioned earlier, I have a new wireless router and I decided that the time was right to do some cross compilation.

Cross compilation is the act of compiling a program on one kind of computer (the host) and using the binaries on a different machine with a different architecture (the target). It has the big advantage, that the host may have a lot of processing power, RAM and temporary disk space while the target may be very small (like a router or other embedded device).

I was told to “just add -march=xxx to gcc and it should work..”. It turned out to be untrue, hence this blog post.

The host

The host system runs a standard Debian Squeeze installation. Cpuinfo looks like this:

 # cat /proc/cpuinfo
processor    : 0
vendor_id    : GenuineIntel
cpu family    : 15
model        : 2
model name    : Intel(R) Pentium(R) 4 CPU 2.80GHz
stepping    : 9
cpu MHz        : 2798.650
[snip]

It is a 2.8 GHz intel processor (on both processors), SATA disks and 3 Gb of memory.

Target

Target is my Linksys Wrt160nl wireless router.

# cat /proc/cpuinfo
system type        : Atheros AR9130 rev 2
machine            : Linksys WRT160NL
processor        : 0
cpu model        : MIPS 24Kc V7.4
BogoMIPS        : 266.24
wait instruction    : yes
microsecond timers    : yes
tlb_entries        : 16
extra interrupt vector    : yes
hardware watchpoint    : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
ASEs implemented    : mips16
shadow register sets    : 1
core            : 0
VCED exceptions        : not available
VCEI exceptions        : not available

The target is a Mips 24kc with 30 Mb of RAM and something like 8 Mb of flash. Converting from BogoMIPS to Mhz is not trivial, but here it is reported as being a 400 Mhz processor.

I am surprised of how different the cpuinfo information is on the two systems. It seems that the information is highly dependant on the architecture – “stepping” is apparently not a concept used for mips.

Anyway, it should be obvious why I want to do cross compilation.

Configuring the host

The first thing to check is the gcc compiler.

# gcc -dumpmachine
i486-linux-gnu

This tells us why the “-march” thing is not working. Gcc on my standard Debian Squeeze is able to build for intel architechtures only. It makes sense to only be able to build for the curren host architechture. Cross compilation is not that common.

To do cross compilation the Debian way, we use emdebian. They have made cross compilation toolchains. I started following this page. It turned out to be a bad idea, but it gave me some pointers. The “problem” is that they are working hard on making an easy system for handling cross compilation. Currently apt-cross is out as of Squeeze and dpkg-cross are to be used for now, but (as I understand it) they are being phased out and merged with apr, xapt and dpkg.

We need to add emdebian to sources.list

deb http://www.emdebian.org/debian/ squeeze main
apt-get update
apt-get install emdebian-archive-keyring

The nice people at emdebian.org has made a complete mips toolchain. Adapting from here, I install the packages

# apt-get install linux-libc-dev-mips-cross libc6-mips-cross libc6-dev-mips-cross binutils-mips-linux-gnu gcc-4.4-mips-linux-gnu g++-4.4-mips-linux-gnu

This install the gcc compiler and some support libraries.

# mips-linux-gnu-gcc -dumpmachine
mips-linux-gnu

I now have a gcc compiler that is able to compile for the mips platform. Next step is to make a “Hello world” program, build it and copy it to the router to test the cross compilation for real.

Hello world

I start here for the hello world program.

me@host:~$ gcc hallo.c
me@host:~$ ./a.out
Hello world

Now for the cross compilation

me@host:~$ mips-linux-gnu-gcc hallo.c
me@host:~$ ./a.out
-bash: ./a.out: cannot execute binary file
me@host:~$ scp a.out root@192.168.2.1:/tmp/
a.out                                         100% 5741     5.6KB/s   00:00
me@host:~$slogin root@192.168.2.1

BusyBox v1.15.3 (2010-07-10 11:43:31 PDT) built-in shell (ash)
Enter 'help' for a list of built-in commands.

 _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
 |__| W I R E L E S S   F R E E D O M
 Backfire (10.03.1-rc3, r22796) --------------------
 * 1/3 shot Kahlua    In a shot glass, layer Kahlua
 * 1/3 shot Bailey's  on the bottom, then Bailey's,
 * 1/3 shot Vodka     then Vodka.
 ---------------------------------------------------
root@Target:~# /tmp/a.out
-ash: /tmp/a.out: not found

First the compilation succeeded and the resulting binary was not runable on the intel machine. Next I copied the binary to the Linksys router, and tried to execute it. It failed.

The “not found” found is related to a shared library that fails to load. Rebuilding with “-muclibc” library,

</pre>
me@host:~$ mips-linux-gnu-gcc -muclibc hallo.c
me@host:~$ scp a.out root@192.168.2.1:/tmp/
a.out                                         100% 5757     5.6KB/s   00:00
me@host:~$ slogin root@192.168.2.1

[snip]
root@target:~# /tmp/a.out
/tmp/a.out: can't load library 'libc.so.6'

The executable runs, except for some sort of issue related to a named shared libraries. I will work on that next time.

Advertisements

Written by moozing

April 5, 2011 at 09:00

Posted in Tech

Tagged with , ,

9 Responses

Subscribe to comments with RSS.

  1. libc.so.6 is the embedded libc library, which openwrt does not have. Instead, it is using the uclibc library, which uses the name libc.so.0. Although you are correctly using the -muclibc parameter, you do not have libc.so.0 in your /usr/mips-linux-gnu/lib directory, so presumably it is falling back on libc.so.6 instead. AFAIK the emdebian toolchain does not currently have a deb package which provides uclibc (it is listed on their TODO at http://wiki.debian.org/EmdebianToolchain ), if you’ve found a workaround, please post.

    vaft

    December 21, 2011 at 22:56

    • I’m also looking for some help with this libc.so problem. Something new now ?

      Required_name

      July 1, 2012 at 11:57

      • I got sidetracked after this post, so I have not looked at in more details.

        Now, when I look at it, it seems odd to use the Debian toolchain to compile the programs for openwrt. My guess is that using openwrt feeds, would be a fairly simple and robust way of doing it.

        moozing

        July 1, 2012 at 13:41

  2. I’m pretty sure it IS odd. However that’s a beautiful hacker way to do what I wanted to do. 🙂
    And it seemed to me enough to compile some code without installing a lot of source code files with svn.
    Now it compiles well but I’m quite sure that what I wanted to see was “Hello world !” instead of some “Segmentation fault” response. 😀
    Nevertheless, it’s not the right place to post about OpenWRT feeds. So, thanks a lot for this article and for the http://wiki.openwrt.org/doc/devel/feeds link, you did a great job !

    Required_name

    July 2, 2012 at 16:28

    • Thanks for the kind words. It is good to know that people actually read what you write 🙂

      moozing

      July 18, 2012 at 23:20

  3. Just what i’ve benn searching, ty man !

    Jorge Segundo Rojas

    May 10, 2013 at 16:38


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: