文章

交叉编译Nginx到Android Arm

Nginx Cross Compile For Android Arm

主机环境

  • OS: Windows 11
  • 使用Docker Ubuntu容器完成交叉编译过程

准备工作

  • 源代码下载
  • 源代码压缩包都下载好后放在一个合适的目录下,这里演示将上述压缩包统一先放在了B:\temp source,即我在我电脑的可用磁盘B盘的根目录下创建了一个temp source文件夹,然后将下载好的压缩包全部拷贝到了这个文件夹
    • temp source 下就有一下压缩包
      • nginx-1.26.2.tar.gz
      • pcre-8.45.zip
      • zlib-1.3.1.tar.gz
      • openssl-openssl-3.3.2.tar.gz
      • android-ndk-r27-linux.zip
    • image-20240925212645734
  • Docker 容器准备

    • Docker Desktop下载: Docker: Accelerated Container Application Development

    • 将一下的Dockerfile内容拷贝到本地,命名文件为Dockerfile

      • Dockerfile:

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        
        # 使用官方ubuntu作为父镜像
        FROM ubuntu:latest
              
        # 设置镜像维护者信息
        LABEL maintainer="Zpekii" description="预安装各种工具,用于做集成工作的ubuntu镜像"
              
        # 预安装工具
        RUN apt update && apt install -y \
                vim \
                nano \
                curl    \
                wget \
                git     \
                rsync \
                unzip \
                build-essential \
                && rm -rf /var/lib/apt/lists/*
              
        # 指定挂载卷
        VOLUME ["/data"]
              
        # 默认执行命令
        CMD ["/bin/bash"]
        
    • 执行 docker pull ubuntu:latest 拉取最新ubuntu镜像

      • 1
        
        docker pull ubuntu:latest
        
    • Dockerfile所在目录下执行docker build -t ubuntu:ci .进行创建自定义镜像

      • 1
        
        docker build -t ubuntu:ci .
        
    • 在源代码压缩包存放的文件夹下运行CMD命令行窗口

      • 执行docker run --rm -it --name temp -v ".\:/mnt" ubuntu:ci bash 创建容器

        • 1
          
          docker run --rm -it --name temp -v ".\:/mnt" ubuntu:ci bash
          
        • 如果创建成功则就会直接进入到容器中,(root@XXXX:/#

          image-20240925213421935

    • 执行cd /mnt进入挂载的本地电脑目录中,

      • 1
        
        cd /mnt
        
    • 执行mkdir -p /var/data/src创建存放解压后的源代码

    • 解压源代码

      • 执行tar -xzvf ./nginx-1.26.2.tar.gz -C /var/data/src解压Nginx源代码至指定目录(/var/data/src)

        • 1
          
          tar -xzvf ./nginx-1.26.2.tar.gz -C /var/data/src
          
      • 执行tar -xzvf ./openssl-openssl-3.3.2.tar.gz -C /var/data/src解压openssl

        • 1
          
          tar -xzvf ./openssl-openssl-3.3.2.tar.gz -C /var/data/src
          
      • 执行tar -xzvf ./zlib-1.3.1.tar.gz -C /var/data/src解压zlib

        • 1
          
          tar -xzvf ./zlib-1.3.1.tar.gz -C /var/data/src
          
      • 执行unzip ./android-ndk-r27-linux.zip -d /var/data/src 解压android ndk

        • 1
          
          unzip ./android-ndk-r27-linux.zip -d /var/data/src
          
      • 执行unzip ./pcre-8.45.zip -d /var/data/src解压 pcre

        • 1
          
          unzip ./pcre-8.45.zip -d /var/data/src
          

交叉编译Nginx源代码

设置环境变量

  • 执行到这一步仍保持在/mnt目录下

  • 执行cd /var/data/src进入接下来的工作目录

    • 1
      
      cd /var/data/src
      
  • 执行ls查看当前各源代码文件夹

    • 1
      
      ls
      
    • image-20240925214547210
  • 执行export NDK=/var/data/src/android-ndk-r27设置NDK环境变量(注: 需要根据实际解压后的源代码文件夹名进行设置!

    • 1
      
      export NDK=/var/data/src/android-ndk-r27
      
  • 执行 export TOOLCHAINS=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin 设置NDK工具链环境变量,便于后面的环境变量设置

    • 1
      
      export TOOLCHAINS=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin
      
  • 执行export CC=$TOOLCHAINS/armv7a-linux-androideabi34-clang设置C语言编译器(C Compiler)环境变量

    • Arm 32:

      • 1
        
        export CC=$TOOLCHAINS/armv7a-linux-androideabi34-clang
        
    • Arm 64:

      • 1
        
        export CC=$TOOLCHAINS/aarch64-linux-android34-clang
        
  • 执行export CPP=$TOOLCHAINS/armv7a-linux-androideabi34-clang++设置C++编译器环境变量

    • Arm 32:

      • 1
        
        export CPP=$TOOLCHAINS/armv7a-linux-androideabi34-clang++
        
    • Arm 64:

      • 1
        
        export CPP=$TOOLCHAINS/aarch64-linux-android34-clang++
        
  • 执行export ZLIB=/var/data/src/zlib-1.3.1设置压缩库环境变量

    • 1
      
      export ZLIB=/var/data/src/zlib-1.3.1
      
  • 执行export NGINX_PATH=/data/data/com.example.www/nginx/nginx设置nginx保存路径(这里是设置成在安卓中可访问和执行命令的目录),其中com.example.www为包名需要自行设定和安卓应用包名一致

    • 1
      
      export NGINX_PATH=/data/data/com.example.www/nginx/nginx
      
  • 一条指令设置所有环境变量

    • Arm 32位:

      • 1
        2
        3
        4
        5
        6
        
        export NDK=/var/data/src/android-ndk-r27 \
        export TOOLCHAINS=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin \
        export CC=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi34-clang \
        export CPP=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi34-clang++ \
        export ZLIB=/var/data/src/zlib-1.3.1 \
        export NGINX_PATH=/data/data/com.example.www/nginx/nginx
        
      • Arm 64位

        • 1
          2
          3
          4
          5
          6
          
          export NDK=/var/data/src/android-ndk-r27 \
          export TOOLCHAINS=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin \
          export CC=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android34-clang \
          export CPP=/var/data/src/android-ndk-r27/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android34-clang++ \
          export ZLIB=/var/data/src/zlib-1.3.1 \
          export NGINX_PATH=/data/data/com.example.www/nginx/nginx
          

设置Nginx交叉编译配置

  • 执行cd nginx-1.26.2进入Nginx源代码目录(注: 需要根据实际解压后的源代码文件夹名进行设置!

    • 1
      
      cd nginx-1.26.2
      
  • 修改部分文件内容,以确保之后可以正常进行配置

    • 执行nano ./auto/cc/name使用nano文本编辑工具修改./auto/cc/name文件

      • 修改ngx_feature_run值为no

        • 1
          2
          
          ngx_feature_run=yes
          修改为==> ngx_feature=no
          
        • image-20240925221523432
      • 修改完成按下快捷键Ctrl+X,然后按下y键确认修改,最后按回车键返回命令行

    • 执行nano ./auto/types/sizeof修改./auto/types/sizeof文件

      • 设置ngx_size值为4

        • 1
          2
          
          ngx_size=
          修改为==>ngx_size=4
          
        • image-20240925221458453
      • 如果是arm64则修改为8

      • 注释掉原来的ngx_size=$NGX_AUTOTEST ,然后写上ngx_size=4

        • 1
          2
          
          ngx_size=`$NGX_AUTOTEST`
          修改为==> ngx_size=4
          
        • image-20240925221434072
      • 如果是arm64则修改为8

      • 修改ngx_test

        • 1
          2
          3
          4
          
          ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
                    -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
          修改为==> ngx_test="gcc $CC_TEST_FLAGS $CC_AUX_FLAGS \
                    -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
          
        • image-20240925222338113
    • 执行nano ./auto/options修改

      • Ctrl+W快捷键进行搜索PCRE_CONF_OPT
      • 设置PCRE_CONF_OPT值为--host=arm-linux-androideabi
      • image-20240925221931174
  • 然后执行以下指令

    • 1
      
      ./configure --crossbuild=android-arm --prefix=$NGINX_PATH --with-http_ssl_module --with-cc=$CC --with-cpp=$CPP --with-pcre=/var/data/src/pcre-8.45 --with-openssl=/var/data/src/openssl-openssl-3.3.2 --with-zlib=$ZLIB --without-http_gzip_module --without-http_upstream_zone_module --without-stream_upstream_zone_module --with-ld-opt="-pie -fPIE" --with-cc-opt="-Wno-sign-compare -pie -fPIE -fPIC" --without-http_userid_module
      
    • 执行成功截图

      • image-20240925222525673

修改部分Nginx配置文件使编译成功

  • 执行nano ./objs/Makefile修改Makefile

  • 1
    
    nano ./objs/Makefile
    
    • 移除Werror
      • image-20240925222803630
    • Crtl+W搜索./config --prefix=/var/data/src/openssl-openssl-3.3.2/.openssl no-shared no-threads

      • 添加no-asm参数
        • image-20240925222959137
    • Ctrl+X加输入y加回车退出编辑,返回命令行

    • 执行nano ./objs/ngx_auto_config.h在最后添加以下代码

    • 1
      
      nano ./objs/ngx_auto_config.h
      
      • 1
        2
        3
        4
        5
        6
        7
        
        #ifndef NGX_SYS_NERR
        #define NGX_SYS_NERR  132
        #endif
              
        #ifndef NGX_HAVE_SYSVSHM
        #define NGX_HAVE_SYSVSHM 1
        #endif
        

        image-20240925223410627

  • 执行nano ./src/os/unix/ngx_user.c修改Nginx源代码文件src/os/unix/ngx_user.c

    • 引入头文件#include <openssl/des.h>

      • image-20240925224311840
    • 修改调用,Ctrl+W搜索value = crypt((char *) key, (char *) salt);

      • 1
        2
        
        value = crypt((char *) key, (char *) salt);
        修改为==> value = DES_crypt((char *) key, (char *) salt);
        

        image-20240925224531595

  • 执行nano ./src/os/unix/ngx_linux_config.hcrypt.h引入注释
    • image-20240925225104289

执行make进行编译nginx

1
make
  • 执行成功截图

image-20240925225145726

执行make install进行安装

  • 1
    
    make install
    

image-20240925225225996

Nginx安装路径在/data/data/com.example.www/nginx/nginx(如果没有设置--prefix=$NGINX_PATH参数的话,安装路径默认在/usr/local/nginx),至此就成功完成Nginx的交叉编译Android Arm架构版本,可执行cp -r /data/data/com.example.www/nginx/nginx /mnt将nginx拷贝到主机文件系统

参考

本文由作者按照 CC BY 4.0 进行授权