arm linux 移植 Nginx


--- title: arm linux 移植 Nginx date: 2020-06-22 08:04:19 categories: tags: - Linux - arm - nginx - porting ---

背景

Nginx 在一些基於web的嵌入式產品上能夠使用,所以本人也介紹一下有關的支持。

本人的有關博客:《Windows 編譯安裝 nginx 服務器 + rtmp 模塊》、《Ubuntu 編譯安裝 nginx》、《Arm-Linux 移植 Nginx
Host平台   :Ubuntu 16.04
Arm平台   :3531d

rcre     : 8.30

zlib     :1.2.11

openssl   : 1.0.2t

nginx    : 1.17.6 (本文完全適用於 1.15版本的 nginx)

arm-gcc   :4.9.4

注意:

  • 這個和以往的交叉編譯不一樣,nginx的交叉編譯依賴的庫都是源碼包,而不是最終的結果。
  • 由於nginx在嵌入式下的支持不是很好,所以在配置編譯之前,需要手動修改工程中的某些項目。

主機准備

##
#    Copyright By Schips, All Rights Reserved
#    https://gitee.com/schips/

#    File Name:  make.sh
#    Created  :  Fri 22 Nov 2019 11:49:30 AM CST

##
#!/bin/sh
BASE=`pwd`
BUILD_HOST=arm-linux
ZLIB=zlib-1.2.11
OPENSSL=openssl-1.0.2t
PCRE=pcre-8.30
NGINX=nginx-1.17.6
FIN_INSTALL=/usr/${NGINX}

make_dirs() {
    cd ${BASE}
    mkdir  compressed  install  source -p

}

tget () { #try wget
    filename=`basename $1`
    echo "Downloading [${filename}]..."
    if [ ! -f ${filename} ];then
        wget $1
    fi

    echo "[OK] Downloaded [${filename}] "
}

download_package () {
    cd ${BASE}/compressed
    #下載包
    tget https://www.zlib.net/${ZLIB}.tar.gz
    tget https://www.openssl.org/source/${OPENSSL}.tar.gz
    # 注意地址
    tget https://jaist.dl.sourceforge.net/project/pcre/pcre/8.30/${PCRE}.tar.bz2
    tget http://mirrors.sohu.com/nginx/${NGINX}.tar.gz
}

tar_package () {
    cd ${BASE}/compressed
    ls * > /tmp/list.txt
    for TAR in `cat /tmp/list.txt`
    do
        tar -xf $TAR -C  ../source
    done
    rm -rf /tmp/list.txt
}


pre_configure_nginx () {
    cd ${BASE}/source/${NGINX}
    # auto/cc/name
    sed -r -i "/ngx_feature_run=yes/ s/.*/\tngx_feature_run=no/g" auto/cc/name
    sed -r -i "/exit 1/ s/.*//1" auto/cc/name

    # auto/types/sizeof
    sed -r -i "/ngx_size=`$NGX_AUTOTEST`/ s/.*/\tngx_size=4/g" auto/types/sizeof
    #
    sed -r -i "/PCRE_CONF_OPT=/ s/.*/PCRE_CONF_OPT=--host=${BUILD_HOST}/g" auto/options
}


configure_nginx () {
    cd ${BASE}/source/${NGINX}
    BUILD=`pwd`
    ./configure \
    --builddir=${BUILD} \
    --prefix=${FIN_INSTALL} \
    --with-http_mp4_module \
    --with-http_ssl_module \
    --without-http_upstream_zone_module \
    --with-openssl-opt=os/compiler:${BUILD_HOST}-gcc \
    --with-cc=${BUILD_HOST}-gcc \
    --with-cpp=${BUILD_HOST}-g++ \
    --with-ld-opt=-lpthread \
    --with-cc-opt='-D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64' \
    --with-pcre=${BASE}/source/${PCRE} \
    --with-openssl=${BASE}/source/${OPENSSL} \
    --with-zlib=${BASE}/source/${ZLIB} \
    --with-http_v2_module && echo "${FIN_INSTALL} with ${BUILD_HOST}" > ccinfo
}

pre_make_nginx () {
    cd ${BASE}/source/${NGINX}

    # 屏蔽nginx 的configure信息
    HEAD_FILE=`find . -name "ngx_auto_config.h"`
    DEL_LINE=`sed -n "/NGX_CONFIGURE/="  ${HEAD_FILE}`
        sed -i "${DEL_LINE}d" ${HEAD_FILE}
    echo "#undef NGX_CONFIGURE " >> ${HEAD_FILE}
    echo "#define NGX_CONFIGURE \"./configure\"" >> ${HEAD_FILE}
    
    echo "#ifndef NGX_SYS_NERR" >> ${HEAD_FILE}
    echo "#define NGX_SYS_NERR 132" >> ${HEAD_FILE}
    echo "#endif" >> ${HEAD_FILE}

    echo "#ifndef NGX_HAVE_SYSVSHM" >> ${HEAD_FILE}
    echo "#define NGX_HAVE_SYSVSHM 1" >> ${HEAD_FILE}
    echo "#endif" >> ${HEAD_FILE}

    # 刪除makefile 多余的幾行

        DEL_LINE=`sed -n "/build\:/="  Makefile  | awk 'END {print}'`
    # 因為是有 2 行,刪除以后文件會發生變化
        sed -i "${DEL_LINE}d" Makefile
        sed -i "${DEL_LINE}d" Makefile

        DEL_LINE=`sed -n "/install\:/="  Makefile  | awk 'END {print}'`
        sed -i "${DEL_LINE}d" Makefile
        sed -i "${DEL_LINE}d" Makefile

        DEL_LINE=`sed -n "/modules\:/="  Makefile  | awk 'END {print}'`
        sed -i "${DEL_LINE}d" Makefile
        sed -i "${DEL_LINE}d" Makefile

}

make_nginx () {
    cd ${BASE}/source/${NGINX}
    make -j4 && sudo make install && sudo mv ccinfo ${FIN_INSTALL}/ccinfo
    cp ${FIN_INSTALL} ${BASE}/install/ -vr
    sudo rm ${FIN_INSTALL} -r
}
sudo ls
make_dirs
download_package
tar_package
pre_configure_nginx
configure_nginx
pre_make_nginx
make_nginx

這樣應該就沒有什么問題了。

arm板子准備

整個目錄 拷貝 到板子,具體以prefix指定的路徑為准上

添加nginx有關庫和運行路徑環境變量

完成nginx.conf的配置…(此步驟省略)

/usr/nginx/sbin/nginx -c /usr/nginx/conf/nginx.conf -p usr/nginx #啟動nginx

編譯nginx時指定外部模塊

第三方模塊下載地址:https://www.nginx.com/resources/wiki/modules/index.html

使第三方模塊的生效方法: ./configure --add-module=模塊的路徑

例如:

/configure --prefix=/usr/local/nginx-1.4.1 \  
 --with-http_stub_status_module \  
 --with-http_ssl_module --with-http_realip_module \  
 --with-http_image_filter_module \  
 --add-module=../ngx_pagespeed-master  

附錄:移植NGINX的中間過程

為了讓讀者能夠搞清楚腳本中各命令的意義,本人保留了下文,以作為手動修改的參考依據。

nginx根目錄下, 執行此腳本,再一步步排查錯誤。

    cd ${BASE}/source/${NGINX}
    echo ${BASE}/source/${NGINX}
    BUILD=`pwd`
    ./configure \
    --builddir=${BUILD} \
    --prefix=${BASE}/install/nginx \
    --with-http_mp4_module \
    --with-http_ssl_module \
    --without-http_upstream_zone_module \
    --with-openssl-opt=os/compiler:${BUILD_HOST}-gcc \
    --with-cc=${BUILD_HOST}-gcc \
    --with-cpp=${BUILD_HOST}-g++ \
    --with-ld-opt=-lpthread \
    --with-cc-opt='-D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64' \
    --with-pcre=${BASE}/source/${PCRE} \
    --with-openssl=${BASE}/source/${OPENSSL} \
    --with-zlib=${BASE}/source/${ZLIB} \
    --with-http_v2_module

提示:

checking for OS
 + Linux 4.15.0-65-generic x86_64
checking for C compiler ... found but is not working

./configure: error: C compiler arm-hisiv500-linux-gcc is not found

make: *** No rule to make target 'build', needed by 'default'.  Stop.

解決方法:

 修改 auto/cc/name

   ngx_feature_run=yes 👉 ngx_feature_run=no

   exit 1 👉 刪掉或者注釋

再次運行

./configure: error: can not detect int size

解決方法:

 vi auto/types/sizeof
 ngx_test中的 $CC 👉 gcc
 ngx_size=`$NGX_AUTOTEST` 👉  ngx_size=4

配置通過以后, 就可以開始make

checking whether we are cross compiling... configure: error: in `nginx-1.15.2/pcre-8.30':
configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details
Makefile:1282: recipe for target 'pcre-8.30/Makefile' failed
make: *** [pcre-8.30/Makefile] Error 1

解決方法

vi auto/options
 根據情況改成自己的交叉編譯工具鏈
PCRE_CONF_OPT= 👉 PCRE_CONF_OPT=-–host=arm-hisiv600-linux

修改以后重新運行 ./make.sh以后再 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]:
                               ^
src/os/unix/ngx_errno.c:37:31: note: each undeclared identifier is reported only once for each function it appears in
src/os/unix/ngx_errno.c: In function ‘ngx_strerror_init’:
src/os/unix/ngx_errno.c:58:11: error: ‘NGX_SYS_NERR’ undeclared (first use in this function)
     len = NGX_SYS_NERR * sizeof(ngx_str_t);
           ^
Makefile:693: recipe for target '/home/schips/arm/nginx/source/nginx-1.15.2/src/os/unix/ngx_errno.o' failed
make: *** [/home/linkpi/arm/nginx/source/nginx-1.15.2/src/os/unix/ngx_errno.o] Error 1
解決方法: 
    添加以下3行到 ngx_auto_config.h 中 (根據有關的源碼可知, 這個宏和操作系統識別的錯誤個數有關)
  # ngx_auto_config.h 文件的位置和 $OBJ 變量有關
  

    #ifndef NGX_SYS_NERR
    #define NGX_SYS_NERR 132
    #endif

  // 注意: NGX_SYS_NERR不是在src里面的,而是編譯的時候根據操作系統的不同而生成的不內容
  // 為了穩定,我們參考host端的結果,使用132作為值。

繼續make

nginx-1.15.2/src/core/ngx_cycle.o: In function `ngx_init_cycle':
nginx-1.15.2/src/core/ngx_cycle.c:476: undefined reference to `ngx_shm_alloc'
nginx-1.15.2/src/core/ngx_cycle.c:685: undefined reference to `ngx_shm_free'
nginx-1.15.2/src/event/ngx_event.o: In function `ngx_event_module_init':
nginx-1.15.2/src/event/ngx_event.c:546: undefined reference to `ngx_shm_alloc'
collect2: error: ld returned 1 exit status
Makefile:247: recipe for target 'nginx-1.15.2/nginx' failed
make: *** [nginx-1.15.2/nginx] Error 1

解決方法:

由於,ngx_shm_free ngx_shm_alloc 這幾個函數被條件宏NGX_HAVE_MAP_ANON,NGX_HAVE_SYSVSHM NGX_HAVE_MAP_DEVZERO,
3者選1,而nginx 的交叉編譯不夠友好,所以需要我們手動添加。

找到 ngx_auto_config.h  

添加以下3行

#ifndef NGX_HAVE_SYSVSHM
#define NGX_HAVE_SYSVSHM 1
#endif

make出現死循環(每次配置以后都需要執行)

nginx-1.15.2/Makefile:1374: recipe for target 'build' failed
make[650]: *** [build] Interrupt
nginx-1.15.2/Makefile:1374: recipe for target 'build' failed
make[649]: *** [build] Interrupt
nginx-1.15.2/Makefile:1374: recipe for target 'build' failed
make[648]: *** [build] Interrupt
nginx-1.15.2/Makefile:1374: recipe for target 'build' failed
make[647]: *** [build] Interrupt
nginx-1.15.2/Makefile:1374: recipe for target 'build' failed
make[646]: *** [build] Interrupt

解決方法:

刪除nginx根目錄圖中這幾行(位於1377行左右)

   7 build:
   6     $(MAKE) -f /home/schips/arm/nginx/source/nginx-1.15.2/Makefile
   5
   4 install:
   3     $(MAKE) -f /home/schips/arm/nginx/source/nginx-1.15.2/Makefile install
   2
   1 modules:
1380     $(MAKE) -f /home/schips/arm/nginx/source/nginx-1.15.2/Makefile modules

再次編譯:

由於每次配置(configure)會使ngx_auto_config.h重置。為了方便維護,我們將有關的改動做成腳本。

##
#    Copyright By Schips, All Rights Reserved
BUILD=.
./configure \
--builddir=${BUILD} \
--prefix='/home/schips/arm/nginx/install/nginx' \
--with-http_mp4_module \
--with-http_ssl_module \
--without-http_upstream_zone_module \
--with-pcre=./pcre-8.30 \
--with-openssl=./openssl-1.0.2t \
--with-zlib=./zlib-1.2.11 \
--with-cc=arm-hisiv500-linux-gcc \
--with-cpp=arm-hisiv500-linux-g++ \
--with-ld-opt=-lpthread \
--with-cc-opt='-D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64' \
--with-openssl-opt=os/compiler:arm-hisiv500-linux-gcc \
--with-http_v2_module || exit 1


echo "// schips add"               >> ngx_auto_config.h
echo "#ifndef NGX_SYS_NERR"        >> ngx_auto_config.h
echo "#define NGX_SYS_NERR 132"    >> ngx_auto_config.h
echo "#endif"                      >> ngx_auto_config.h
echo ""                            >> ngx_auto_config.h
echo "#ifndef NGX_HAVE_SYSVSHM"    >> ngx_auto_config.h
echo "#define NGX_HAVE_SYSVSHM 1"  >> ngx_auto_config.h
echo "#endif"                      >> ngx_auto_config.h
echo "Need edit Makefile" && exit 1
make CC=arm-hisiv500-linux-gcc
make install

使用已經編譯好的 openssl庫以加快編譯速度(在本文中未啟用)
--with-openssl 參數雖然可以指定 OpenSSL 路徑,但只支持 OpenSSL 的源代碼,不支持已編譯好的 OpenSSL。

每回更新 nginx 都要重新編譯 OpenSSL 肯定很麻煩,網上找到一個方案,覺得很好,記錄下來。

1.1 首先使用交叉編譯Openssl:

CC=arm-linux-gnueabi-gcc ./config no-asm shared --prefix=/app/my_lib

1.2 修改nginx的Mkaefile代碼:

把
 31#CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include"
 32#CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h"
 33#CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a"
 34#CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a"
 35#CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
 改為:
 37CORE_INCS="$CORE_INCS $OPENSSL/include"
 38CORE_DEPS="$CORE_DEPS $OPENSSL/include/openssl/ssl.h"
 39CORE_LIBS="$CORE_LIBS $OPENSSL/libssl.a"
 40CORE_LIBS="$CORE_LIBS $OPENSSL/libcrypto.a"
 41CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
 41CORE_LIBS="$CORE_LIBS $NGX_LIBDL"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM