Cross-compile nginx for armhf

I needed to cross-compile a modern nginx for armhf for the Eurotech Reliagate 10-11 hardware we use for Om7Sense. Thankfully I came across this handy blog post. Building on that, here is how I cross-compiled 1.9.3 with SSL and rewrite support for a Linux box based on Yocto 1.6 without having to deal with the SDK.

Decide where to create your buildroot

For me it was in ~/arm.

export BUILDROOT = ~/arm
mkdir $BUILDROOT

Get a toolchain

Get https://releases.linaro.org/14.04/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.bz2

Unpack to /opt or so and add the bin subfolder to your path.

Get and compile pcre

wget “ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.38.tar.gz
./configure –enable-shared=no –prefix=$BUILDROOT  –host=arm-linux-gnueabihf
make
make install

Get and compile libssl (I used 1.0.0m for this)

wget “https://www.openssl.org/source/old/1.0.0/openssl-1.0.0m.tar.gz
./Configure -DOPENSSL_NO_HEARTBEATS –openssldir=$BUILDROOT shared os/compiler:arm-linux-gnueabihf-gcc
make
make install

Make install might fail because it cannot install the documentation. Just delete the install_docs target from the install target in the Makefile.

Get and compile nginx (tested with 1.9.3)

First we configure it for the host system because the configure system is not made for cross compiling (inspired by http://tiebing.blogspot.de/2014/09/cross-compile-nginx-for-arm.html)

./configure –with-pcre –prefix=/opt/nginx  –with-http_ssl_module –without-http_gzip_module –without-http_ssi_module –without-http_userid_module –without-http_autoindex_module –without-http_geo_module –without-http_fastcgi_module –without-http_uwsgi_module –without-http_scgi_module  –without-http_memcached_module –without-http_empty_gif_module –without-http_browser_module –without-mail_pop3_module –without-mail_imap_module –without-mail_smtp_module

Afterwards replace top part of objs/Makefile with this:

CC =    arm-linux-gnueabihf-gcc
CFLAGS =  -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g
CFLAGS += -I~/arm/openssl-1.0.0k/include/ -I/opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux/arm-linux-gnueabihf/libc/usr/include/ -I~/arm/include
CPP =   cc -E
LINK =  $(CC) -L~/arm/lib

Then edit objs/ngx_auto_config.h. If your target platform cannot do SO_REUSE_ADDR (mine couldn’t) delete this block:

#ifndef NGX_HAVE_REUSEPORT
#define NGX_HAVE_REUSEPORT  1
#endif

Since I was cross-compiling from a 64-bit box for arm32 all the auto-detected sizes for integers and so on where wrong. If you get compile errors about missing precision you need to do this: Delete the whole block between #ifndef NGX_PTR_SIZE and the #endif after #NGX_MAX_TIME_T_VALUE. Replace with this:

#ifndef NGX_PTR_SIZE
#define NGX_PTR_SIZE
4
#endif
#ifndef NGX_SIG_ATOMIC_T_SIZE
#define NGX_SIG_ATOMIC_T_SIZE
4
#endif
#ifndef NGX_HAVE_LITTLE_ENDIAN
#define NGX_HAVE_LITTLE_ENDIAN
1
#endif
#ifndef NGX_MAX_SIZE_T_VALUE
#define NGX_MAX_SIZE_T_VALUE  2147483647L
#endif
#ifndef NGX_SIZE_T_LEN
#define NGX_SIZE_T_LEN  (sizeof(
"-2147483648"
) -
1
)
#endif
#ifndef NGX_MAX_OFF_T_VALUE
#define NGX_MAX_OFF_T_VALUE  2147483647L
#endif
#ifndef NGX_OFF_T_LEN
#define NGX_OFF_T_LEN  (sizeof(
"-2147483648"
) -
1
)
#endif
#ifndef NGX_TIME_T_SIZE
#define NGX_TIME_T_SIZE
4
#endif
#ifndef NGX_TIME_T_LEN
#define NGX_TIME_T_LEN  (sizeof(
"-2147483648"
) -
1
)
#endif
#ifndef NGX_MAX_TIME_T_VALUE
#define NGX_MAX_TIME_T_VALUE  2147483647L
#endif

Then run make. The binary will be in obj/nginx and needs to be stripped to shrink its size:

arm-linux-gnueabihf-strip objs/nginx