Cross-Compiling C & C++ Programs: Part 3 – C Programming with Libraries
We’re continuing our series on cross-compiling programs for the Omega2. A couple weeks ago, we covered how to cross-compile a hello world C program. This week, we’ll be showing you how to cross-compile more complex C programs that make use of external libraries!
In this example, we will write and cross compile a program that will read and print the input value on a user-specified GPIO once a second for 20 seconds. Our program will use the
ugpio library to interact with the GPIOs. See our c-cross-compile-example repo on GitHub for the code.
You may ask, why do I need to cross-compile this program when I already know how to compile C programs on my Omega?
Well, as a space saving measure, header files for libraries that are not regularly part of the C standard library are not included on the Omega’s filesystem. So we are not be able to compile programs that make use of external libraries directly on the Omega, the compiler would complain that it can’t filnd the
ugpio/ugpio.h header file.
However, the Omega’s filesystem does include shared object files of many external libraries, including
/usr/lib on your Omega). This means that compiled programs that use these libraries can be executed on the Omega, if they have been previously cross compiled on a system that has all of the required header files and shared object files.
Cross Compilation Process
Head to your
omega2-source Docker container and let’s dive in! Go to the
/root directory and we’ll start by cloning the repo that has the C code:
Now that you have all of the code, you’ll notice that there’s a
makefile as well as a
xCompile.sh script. The
makefile is fairly standard as far as makefiles go, it’s the
xCompile.sh script that makes all of the cross compilation magic happen. It’s responsible for invoking the makefile in such a way that:
- The compilers are set to the cross-compilers created by the LEDE build system
- The compilation and linking flags are set to allow compilation of programs that use external libraries
Since we love to write code that’s reusable, the script takes two arguments:
- The location of the LEDE build system (so it knows where to look for the cross-compiler and the header files & static object files for any external libraries)
- The names of any libraries that are used by the program
So, the script should be called like this:
sh xCompile.sh -buildroot ‹PATH TO BUILD SYSTEM› -lib ‹REQUIRED LIBRARY›
A Small but Important Note
We keep mentioning that the program will use the
ugpio library. In order for this to be possible, the library must first be compiled by LEDE build system.
If you’re using our
omega2-source Docker image or building based on our
source GitHub repo, you’re all good as it’s selected for compilation by default.
If not, you’ll have to run
make menuconfig in the build system to select the
libugpio package to be compiled and then compile it by running
Back to Cross Compiling
Ok, let’s run our cross compilation script. If you’re following along in the
omega2-source Docker container, the following command is what you should run:
sh xCompile.sh -buildroot /root/source/ -lib ugpio
As you can see from the output, we now have a
gpioRead executable file. Let’s take a closer look at this file:
compile-example# file gpioRead gpioRead: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked, interpreter /lib/ld-musl-mipsel-sf.so.1, not stripped
Success! It’s a MIPS executable!
Getting the Program to the Omega
To get this program onto your Omega, transfer the
gpioRead binary executable file to
https://transfer.sh/ and then download it on your Omega.
curl --upload-file ./gpioRead https://transfer.sh/gpioRead
It will upload the file and output a link you can use to download the file.
Now switch over to your Omega and we’ll download the executable using the
root@Omega-F16B:~# wget https://transfer.sh/MVr7R/
gpioRead --2017-10-10 15:48:25-- https://transfer.sh/MVr7R/ gpioRead Resolving transfer.sh... 220.127.116.11, 2001:bc8:4700:2000::4423 Connecting to transfer.sh|18.104.22.168|:443.. . connected. HTTP request sent, awaiting response... 200 OK Length: 9804 (9.6K)  Saving to: 'gpioRead' gpioRead 100%[===== ============================== ============================== === ============================== =================>] 9.57K --.- KB/s in 0.005s 2017-10-10 15:48:27 (1.79 MB/s) - 'gpioRead' saved [9804/9804]
One last step, we’ll need to change the downloaded file’s permissions to make it executable:
chmod +x gpioRead
Another Small but Important Note
gpioRead executable was compiled with the
ugpio library dynamically linked. So, when the
gpioReadprogram executes, it will be looking for the
libugpio shared object when it needs to execute code from the library.
What that means is that for the
gpioRead program to run properly, your Omega needs to have the
libugpio package installed. If you’re using an Onion firmware, you’re all good since it comes with
libugpio by default. If not, you’ll have to use
opkg to install it.
Running the Program
Back to the show: you’re all set to run your cross-compiled program! Select the GPIO that you would like to read and let’s run the program:
root@Omega-F16B:~# ./gpioRead 1 > setting to input > begin reading GPIO1 > Read GPIO1: value '1' > Read GPIO1: value '1' > Read GPIO1: value '0'
It will read the input value on the specified GPIO 20 times in a row and display it on the command line.
Try running a jumper wire from your GPIO to GND, starting the program, and then moving it from GND to 3.3V after a while.
You’ve Made It!
So now you’ve successfully cross compiled your second program, one that has a
makefile and uses an external library! Now, it’s your turn to make some awesome projects and share them with us! Try using some of the C Libraries we’ve made! Happy Hacking!
Thanks for reading & have a great week!
Have you seen the Omega2S, the smaller and surface-mount version of the Omega2 for high volume commercial and industrial OEMs? See our Omega2S page for more details!
Let us know what kind of stuff you would like to see featured on 2-Bullet Tuesday! Send a tweet to @OnionIoT with your suggestions!
P.S. We can still hardly believe it! The Omega2 family is now available on SparkFun!