Friday, June 1, 2018

More Cross Compiling for MIPS32

So in previous posts I could not successfully pull off building my own toolchain to cross compile on MIPS32.

I decided to try and do a simple cross compile using the OpenWRT toolchain.

Let me review the steps for this:

  1. Download OpenWRT by doing a git clone on the OpenWRT project
  2. Select your target architecture using the "make menuconfig" command at the top directory of the OpenWRT project
  3. Invoke the build and monitor results to ensure build compiled correctly
The complexity of OpenWRT, and reverse-engineering what it is doing, starts here.

Here is the output directory structure...
....or at least what is written out to MY system when I did the build). 

As you can see, I decided to name my configuration with a name that corresponded to the OEM router I used to build the image (handy if you install OpenWRT on multiple OEM routers).

So let's start talking now about why this is confusing.

1. You might expect the toolchain to be in the toolchain directory. 

And it is, but it's not. The stuff to build the toolchain is in the toolchain folder....
.
...but the output of the build is not in this directory.

It is probably in the build_dir folder then, right? WRONG.


The build_dir folder is where the build is kicked off from. But once that happens, everything is written out to the staging_dir

So let's go and take a look at that directory.


There are a few directories listed, so we will do some investigation and hunt for some binaries. A quick find command shows that indeed, there are some bin directories we can look at.

It turns out that the top level bin directory has the generated executables. 

So when OpenWRT builds the toolchain, it writes it into the staging directory for the specific target that was configured in the initial "make menuconfig".

So the next step then, is to make sure that these can be used to build some code on the target device (MIPS32 in our case).


A simple testcompiler.c file is all that is needed:
#include <stdio.h>

int main()
{
   printf("Testing MIPS32 Compiler!\n");
}

Next we will set up a simple Makefile to compile this simple source (we could do it on command line of course also).

all: testcompiler.o

testcompiler.o : testcompiler.c
      ${CC} testcompiler.c -o testcompiler -static -march=mips32

Next, we need to ensure that the proper compiler gets used, and we can do this by using an environment file before we kick off the build with the "make" command.


Now there are a couple of ways to test this binary, but the first and most simple thing to do is to inspect it using the file command, which indeed will confirm whether the binary was built for MIPS32.


Good. It is. So we can now do one of two things: 
  1. Copy it to the target and run it
  2. Run the binary through an emulator
Emulators can be tricky to install and set up. The one most commonly used for Linux x86_64 architectures is QEMU. 

NOTE: I tried to install and use this but got a bunch of errors. So, using QEMU was not as simple as I thought it would be. Something for later. 

So, I copied it over to the target and it ran just fine.

Now this process is as simple as it gets. When you get into dependent libraries and packages, building, as well as running, on cross compiled architectures can get quite a bit trickier.

And I do plan to do some more sophisticated cross compiling, so I will write more on that as I do that.

No comments:

Fixing Clustering and Disk Issues on an N+1 Morpheus CMP Cluster

I had performed an upgrade on Morpheus which I thought was fairly successful. I had some issues doing this upgrade on CentOS 7 because it wa...