Dockerfile example how to compile libcurl for Android inside Docker container

Update: 5 july 2015 – See updated version of dockerfile at the end of post with new NDK / SSL / clang toolchain.

If you never heard of Docker be sure to check it out as fast as possible. There are lot of publications out there. At first it looks like another virtualisation software but it is actually more like new paradigm. Someone may call it very advanced chroot, someone may call virtual containers with version control and building scripts, and so on. I like it as the idea of application-centric containers – your application can keep whole operating system as a coating and its making perfect separation from outside influence. As well you can easily reproduce production process environment at another location. It makes virtualisation easy and fun.

Libcurl in docker

Almost everything can be done inside containers now. Recently i had to recompile curl for Android as static lib using latest NDK toolchain. Its not so complicated to do on your local machine (if it is not Windows) but now there is a more clean way to do this time-wasting operation. You can go to digital ocean, create droplet with Docker and using Dockerfile from the end of this post compile it while drinking coffee.

Dockerfile is simple script to automate container image creation. In our case script will

  • setup compilation tools / utils
  • download sdk/ndk
  • create custom cross-compilation toolchain
  • download source code for libs (zlib, lib curl)
  • setup environment settings for cross compilation
  • configure and make libs
  • gather output at one folder and create the way to get compiled libs

 

So lets create it step by step:

FROM field is describing source OS image. You can specify version of ubuntu or choose something else.

As next step there is installation of compilation tools and some utils. Note that each command inside docker file produces intermediate image which is use like cache if you run your docker file again. This saves you a lot of time when you are tuning or recreating your container image with different options.

Here we download SDK / NDK using official links from Google – you can edit it to more recent versions. Also we create /Android folder and use it as WORKDIR. Any new command will run in this dir.

Extraction of NDK produces more then 4.5GB (for now). Docker aims to make containers as light as possible so watch out for free space at your storage as images can consume it pretty fast if don’t clean up them.

ENV command is setting environment variable. Note that you can’t use export command as you  do in sh scripts to set local compilation variables because every command in Dockerfile produces new image. Here we just set SDK/NDK folders.

As next step we create stand alone compilation toolchain using script from NDK. As parameters you select platform and arch. This is example is for ARM but I’m sure you will modify it with easy to make several builds for couple of arms and x86. After creation of toolchain we add it to PATH env variable.

Here we set ENV variables for cross-compilation. CC – main C compiler.

Here we download last version of ZLib (you can change the link to latest version), extract, configure and make it using –static parameter. And we doing it using newly created android toolchain. As last step we put result libz.a into /Android/output folder where we will put all the results.

The most important step – here we download curl. Configure script of curl has a lot of parameters. I don’t use SSL at the moment so i don’t need to compile OpenSSL (may be i will add it later here). The most important params here are –host=arm-linux-androideabi –target=arm-linux-androideabi as they identify cross-compilation for configuration script.

Also here we setup compilation options CFLAGS / LDFLAGS. You can tune this to your content.

Note – if something goes wrong during ./configure run you can append “|| cat config.log” to the end of line to see your errors during the building of container image.

Last step is to set ENTRYPOINT. We have to provide the result of our compilation to host OS (or we can easily make some web server and host it – but i decided to go first way).

To build container put Dockerfile into some folder on host OS and run

android/curl here is just a name i gave to new created image. The process will consume some time. You can see the list of created images using command: docker images

And we have to run container only to copy output files to host:

Key -v is mounting local ~/Android/output folder to container’s /output folder.

See whole Dockerfile:

So this small script creates all your compilation environment and does the job!

Screenshot 2014-10-28 11.56.35

As you can see if something changes this Dockerfile gives you ability to recompile your libs using different NDK or toolchain pretty fast. Now you can think how to expand this solution to make automatic building of your projects on server side (daily builds). Docker also gives some new freedom for distributed architectures. At the moment i look at CoreOs as perfect environment for containers to live in. But this is subject of separate thread.

Please report any mistakes in comments.

BONUS:

We can compile some more libs the same way – here is Libzip for Android.

UPDATE (5 July 2015) – OpenSSL + CURL using latest NDK with clang3.6 support 

I just put new Dockerfile on github which contains build section for OpenSSL library (libssl.a / lib crypto.a). So it’s pretty easy to build lib curl with SSL which supports HTTPS protocol. Also Docker file uses latest NDK with clang3.6 as building toolchain. This version is for armv7, but i’m sure it not so complicated to change it to other ARCH.

Some important lines from my current Application.mk / Android.mk files (just for example – yours might be different):

This configuration also gives ability to use C++14 on Android! 🙂