宿主機操作系統為ubuntu 16.04。交叉編譯需要用到的軟件包為
openssl-OpenSSL_1_1_0i.tar.gz
pcre-8.42.tar.gz
nginx-1.14.0.tar.gz
暫時還沒有把zlib加上
一、注意openssl和pcre只需要把源碼解壓縮,不需要單獨交叉編譯!
開始的時候不知道,傻傻的把這兩個庫弄半天把它們編譯過去了。誰知道nginx的--with-pcre和--with-openssl選項,指定的是這兩個庫源代碼的路徑,并非安裝路徑!nginx的編譯系統只會從/usr、/usr/local等少數幾個目錄查找是否有預編譯的pcre、zlib、openssl等庫。對于交叉編譯,直接把交叉編譯后的pcre等安裝在/usr、/usr/local顯然不合適,因此需要使用--with-pcre和--with-openssl指定源代碼的位置
二、交叉編譯nginx
在x64 linux上面編譯非常簡單的nginx,沒想到在交叉編譯的時候巨多坑。下面一個configure是編譯成功的配置
./configure --with-http_ssl_module --with-cc=arm-hisiv400-linux-gcc --with-cpp=arm-hisiv400-linux-cpp --with-pcre=/home/src/pcre-8.42 --with-openssl=/home/src/openssl-OpenSSL_1_1_0i --without-http_gzip_module --without-http_upstream_zone_module
踩坑一,configure的時候報錯
checking for C compiler ... found but is not working
./configure: error: C compiler arm-hisiv400-linux-gcc is not found
這是因為nginx編譯的時候除了檢查cc是否存在,還需要執行編譯后的程序。很明顯交叉編譯的程序無法執行。解決辦法
vi auto/cc/name
ngx_feature="C compiler"
ngx_feature_name=
ngx_feature_run=yes
==> ngx_feature_run=no
踩坑二,configure的時候報錯
checking for int size ...objs/autotest: 1: objs/autotest: Syntax error: word unexpected (expecting ")")
bytes
./configure: error: can not detect int size
同樣也是因為cc編譯后的程序無法本地執行導致。解決辦法
vi auto/types/sizeof
ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
==> ngx_test="gcc $CC_TEST_FLAGS $CC_AUX_FLAG \
if [ -x $NGX_AUTOTEST ]; then
ngx_size=`$NGX_AUTOTEST`
==> ngx_size=4
需要注意,ngx_size=4是目標機器為32位情況時的設值。如果是64位,要改為8
踩坑三,make的時候報錯
cd /home/src/pcre-8.42
&& if [ -f Makefile ]; then make distclean; fi
&& CC="arm-hisiv400-linux-gcc" CFLAGS="--host=arm-hisiv400-linux -pipe"
./configure --disable-shared
...
configure: error: in `/home/src/pcre-8.42':
configure: error: C compiler cannot create executables
這是因為編譯pcre的時候,nginx沒有正確設置交叉編譯鏈。解決
vi auto/options
PCRE_CONF_OPT=
==> PCRE_CONF_OPT=--host=arm-hisiv400-linux
踩坑四,make的時候報錯
src/core/ngx_rwlock.c:125:2: error: #error ngx_atomic_cmp_set() is not defined!
報錯的地方,nginx的源碼是這樣的
#if (NGX_HTTP_UPSTREAM_ZONE || NGX_STREAM_UPSTREAM_ZONE)
#error ngx_atomic_cmp_set() is not defined!
#endif
解決辦法,在configure的時候加上--without-http_upstream_zone_module和--without-stream_upstream_zone_module
踩坑五,make的時候報錯
src/os/unix/ngx_errno.c: In function ‘ngx_strerror’:
src/os/unix/ngx_errno.c:37:31: error: ‘NGX_SYS_NERR’ undeclared (first use in this function)
msg = ((ngx_uint_t) err < NGX_SYS_NERR) ? &ngx_sys_errlist[err]:
出錯的原因仍然是因為交叉編譯程序無法本地運行,導致NGX_SYS_NERR宏沒有賦值。解決辦法,手動編輯 objs/ngx_auto_config.h,加上
#ifndef NGX_SYS_NERR
#define NGX_SYS_NERR 132
#endif
踩坑六,make的時候報錯
/home/src/openssl-OpenSSL_1_1_0i/.openssl/lib/libssl.a: error adding symbols: File format not recognized
collect2: error: ld returned 1 exit status
objs/Makefile:236: recipe for target 'objs/nginx' failed
這是SSL編譯的時候調用了x86的gcc,而非交叉編譯gcc導致的。解決辦法
vi auto/lib/openssl/make
&& ./config --prefix=$ngx_prefix no-shared no-threads $OPENSSL_OPT \
改為
&& ./Configure --prefix=$ngx_prefix no-shared no-threads --cross-compile-prefix=arm-hisiv400-linux- linux-generic32 \
踩坑七,make的時候報錯
objs/src/core/ngx_cycle.o: In function 'ngx_init_cycle':
/home/src/nginx-1.14.0/src/core/ngx_cycle.c:476: undefined reference to 'ngx_shm_alloc'
/home/src/nginx-1.14.0/src/core/ngx_cycle.c:685: undefined reference to 'ngx_shm_free'
解決辦法
vi objs/ngx_auto_config.h
#ifndef NGX_HAVE_SYSVSHM
#define NGX_HAVE_SYSVSHM 1
#endif