Wednesday, October 21, 2015

Cross compiling libs3 for Raspberry Pi

Recently I had a need to upload files from Raspberry Pi to Amazon S3 bucket. There are at least two ways to do this: uploading through REST API and using libs3 C library. The REST API approach requires HMAC-SHA1 signature authentication. Calculating the signature is not trivial considering the various rules in constructing the signature payload. So I chose to go with libs3 approach to achieve the goal. This post explains how I cross compiled libs3 for Raspberry Pi/armhf.

Getting Source

The libs3 source is hosted in Github in the repository https://github.com/bji/libs3. Clone the repository and make sure it is accessible from our build environment.

Getting Dependencies

We need header and library files of libcurl and libxml2 to build libs3. We also need library files of zlib and liblzma while building host application that uses libs3.

The easy way to get these files is to get your OS distribution packages of these libraries and extract the required files. My Raspberry Pi 2 runs Raspbian OS created from Debian Wheezy. So I downloaded Wheezy packages of these libraries for "armhf" architecture from here and extracted the files as explained here.

The hard way is to get source of all these libraries and cross compiling them for Raspberry Pi then using the resultant libraries. It is a time consuming and unnecessary exercise as the required files are readily available in the OS distribution packages. So I didn't choose to go in this way.

The libs3 can be built as static and shared library. The default build configuration builds both version. When you build libs3 static library you need the .a files from these dependencies and when you build shared library you need the .so files.

Build Environment 

Get your Raspberry Pi cross compiling environment ready as explained here. Copy the dependencies header files(i.e. "curl" and "libxml" directories) into "$HOME/raspberrypi/rootfs/usr/include". Copy the dependencies library files into "$HOME/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf".

Building The Library

Navigate to the libs3 source directory and issue the below commands to build libs3 library.

$ make CC=arm-linux-gnueabihf-gcc CURL_LIBS=$HOME/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf/libcurl.a CURL_CFLAGS=-I/opt/raspberrypi/rootfs/usr/include LIBXML2_LIBS=/$HOME/raspberrypi/rootfs/usr/lib/arm-linux-gnueabihf/libxml2.a LIBXML2_CFLAGS=-I$HOME/raspberrypi/rootfs/usr/include -f GNUmakefile

It is enough to specify the include directory "-I/opt/raspberrypi/rootfs/usr/include" once either in CURL_CFLAGS or LIBXML2_CFLAGS but if we didn't specify in both it will attempt to invoke the programs "curl-config" or "xml2-config" which we don't have.

After successfully building the library, the libs3 static and shared libraries will be available under "build/lib" directory of libs3 source directory. The directory "inc" under libs3 source directory contains the corresponding libs3 header files. Now we can either point our application build system to consume libs3 from here or copy the header and library files into the corresponding directories of "$HOME/raspberrypi/rootfs/usr" to consume them automatically via the pi.cmake toolchain file. Make sure you link zlib and lzma libraries with your application when you consume libs3, otherwise the linking process will fail with undefined symbol error.

I hope the information helps you, thanks for reading.