这段时间,我一直忙于将 Rainbond 源码构建模块移植到 Arm64/aarch64 架构中。这一源码构建模块可以将指定代码仓库中包含的源码,拉取构建成为容器镜像,在各种容器平台中运行。目前支持的源码类型包括:Java(Maven、Gradle、jar、war)、Nodejs(前端Vue、后端项目)、Golang、Python、PHP、.NetCore、静态Html。

Rainbond源码构建简介

Rainbond 源码构建模块由 builderrunner 两个子模块组成。

builder 负责将源码进行编译,并打包成为 Heroku 风格的 slug.tgz 包。slug.tgz 包中会包含编译完成的产物(比如jar包、二进制等),以及编译产物运行所需要的基础环境(比如 jdk、tomcat、nginx、apache)。

runner 负责提供 slug.tgz 包运行的基础环境。这是一个通用的基础环境,不必再区分语言,无论何种语言生成的 slug.tgz 包都适用。

为何要编译Nginx

Nginx 是静态Html 、 Nodejs前端项目运行所使用的默认 Web-Server。builder 会在这两种语言编译完成后,前往 Rainbond 专用的云端对象存储中拉取 Nginx 安装包。这种预编译的安装包,Nginx 官方只会提供 x86_64 版本。

在源码构建模块移植到 Arm64/aarch64 架构的过程中,我不可避免的要自己重新编译 Arm 架构可用的 Nginx 预编译安装包。

为何要进行静态编译

最开始,我是希望走一些捷径,Nginx 的核心是要有一个可执行二进制文件,那么我是否可以从别处得到这种可执行文件。

Nginx 官方虽不提供我直接需要的 Arm64 预编译安装包,但是却为各大操作系统发行版提供 Arm64 环境下的安装源。对于 builder 所使用的 Ubuntu:14.04 操作系统而言,可以通过 apt install nginx 的方式安装。然后我就可以得到我想要的可执行文件了。但是下面两个问题的出现,阻断了这条思路。

  • Ubuntu:14.04 源提供的 Nginx 版本过低。
  • 使用更高版本的 Ubuntu:18.04 安装的 Nginx 版本可以满足我的要求,但是提取到的可执行文件在 Ubuntu:14.04 无法运行,缺少必要的库文件。

此时我意识到,由源安装而来的 Nginx 是动态编译版本,apt 等包管理工具会自动处理所需的依赖,然而我并不想要一点点尝试我所缺少的库都由哪些包安装,这很耗神。

我希望这个可执行文件可以像 golang 语言编译出的二进制文件一样,将所有需要的库都编译到二进制中去,从而免除对操作系统的要求。理论上,这种方式得到的二进制在运行效率上也会更高。

简单的查询后,我了解到,我所需要的,是进行静态编译。

准备工作

阅读 Nginx 官方提供的 源码编译文档 了解到,我至少需要以下依赖需要处理:

  • PCRE(Perl Compatible Regular Expressions):基于 Perl 的正则表达式函数库,Nginx 的 Core 、Rewrite 模块需要它。pcre-8.44.tar.gz

  • zlib:小而美的压缩库,Nginx 的 Gzip 模块需要它。zlib-1.2.11.tar.gz

  • OpenSSL:用于安全通信的工具包,非常著名,Nginx 所有和安全通信相关的模块都需要它,比如Https。openssl-1.1.1l.tar.gz

我已经把它们的安装包上传到 Rainbond 官方对象存储上,读者若有需求,可以点击下载。

进行编译的硬件环境,是位于拥有 M1 芯片的 MacBookPro 笔记本 ,利用 Docker Desktop 启动的 ubuntu:1404 容器。容器中预装了 gccmake 软件包。

编译过程

解压所有的依赖软件包,以及 Nginx 的源码包,所有源码包都位于同级目录下:

# 解压已经下载好的依赖软件包
$ tar xzf pcre-8.44.tar.gz
$ tar xzf zlib-1.2.11.tar.gz
$ tar xzf openssl-1.1.1l.tar.gz
# 下载并解压 nginx stable 源码包
$ wget https://nginx.org/download/nginx-1.18.0.tar.gz
$ tar zxf nginx-1.18.0.tar.gz
$ cd nginx-1.18.0

执行 configure ,并指定静态编译参数:

$ ./configure \
--with-cc-opt='-static -static-libgcc' \
--with-ld-opt=-static \
--prefix=/app/nginx \
--with-http_ssl_module \
--with-openssl=../openssl-1.1.1l \
--with-pcre=../pcre-8.44 \
--with-zlib=../zlib-1.2.11

开始执行编译:

$ make && make install

打包编译出来的 Nginx 目录即可:

$ tar czf nginx-1.18.0-arm64.tar.gz /app/nginx

验证

查看编译后产生的可执行文件,会发现该二进制文件的编译类型为静态类型,这样的文件,可以在 arm64 架构下的任意 Linux 环境下运行。

$ file /usr/local/nginx/sbin/nginx
/usr/local/nginx/sbin/nginx: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=66e5740a16bdfe6bc2f04c5371fd706ae7ca5395, not stripped

Arm64架构下静态编译Nginx的更多相关文章

  1. Arm64架构下编译便携Python

    这段时间,我一直忙于将 Rainbond 源码构建模块移植到 Arm64/aarch64 架构中.对于 Python 项目而言,可以直接通过源代码编译成为可运行在各种容器平台之上的容器镜像.这个过程不 ...

  2. ARM64架构下,OpenJDK的官方Docker镜像为何没有8版本

    为什么需要ARM64架构的OpenJDK8的Docker镜像 对现有的Java应用,之前一直运行在x86处理器环境下,编译和运行都是JDK8,如今在树莓派的Docker环境运行(也可能是其他ARM环境 ...

  3. Linux下静态编译Qt

    Qt采用编译的方式安装的时候,配置中默认的编译方式是动态编译的,但是有时候你编写的程序要发布出去,带很多动态库文件是很繁琐的,此时就需要静态编译你的程序,Qt要实现静态编译必须库文件也是静态编译的,所 ...

  4. Linux/Ubuntu下 静态编译Qt程序

    一般情况下,我们用Qt编译出来的程序是要依赖于系统Qt库的,也就是这个程序移到别的没有安装Qt库的系统上是不能使用的.会提示缺少……库文件之类的错误.这就是动态编译的结果. 但是如果我们想编译一个程序 ...

  5. Linux下静态编译Qt程序

    一般情况下,我们用Qt编译出来的程序是要依赖于系统Qt库的,也就是这个程序移到别的没有安装Qt库的系统上是不能使用的.会提示缺少……库文件之类的错误.这就是动态编译的结果. 但是如果我们想编译一个程序 ...

  6. Win7下静态编译QT5.12源码

    官方参考文档:https://doc.qt.io/qt-5/build-sources.html CSDN博客:https://blog.csdn.net/GG_SiMiDa/article/deta ...

  7. Windows下静态编译Qt4

    既然是静态编译,那就要编译出来的程序不信赖于任何dll文件.首先下载qt-win-opensource-4.7.4-mingw.exe: http://get.qt.nokia.com/qt/sour ...

  8. Qt5.5.0在Windows下静态编译(修改参数以后才能支持XP)good

    测试系统环境: windows 7 编译软件环境: vs2013 + QT5.5.0 [源码地址:http://download.qt.io/official_releases/qt/5.5/5.5. ...

  9. Qt5.5.0在Linux下静态编译(加上-fontconfig编译项才能显示中文) good

    测试系统环境:Ubuntu12.04 (32bit/64bit)编译软件环境:QT5.5.0   本文章主要介绍Linux下QT静态编译环境的搭建,以及如何编译我们的程序board_driver. 1 ...

随机推荐

  1. Spring Boot 热启动插件

    1. maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId ...

  2. C语言中宏定义#define 、 typedef 和枚举类型

    替换时机 #define :预编译阶段简单替换,编译阶段展开源程序(1.词法扩展==程序生成期间的字符串替换 2.语义扩展==生成特定指令) 枚举常量:编译阶段确定其值 内联函数:编译阶段插入代码 t ...

  3. 【php安全】 register_argc_argv 造成的漏洞分析

    对register_argc_argv的分析 简介 使用 cli模式下,不论是否开始register_argc_argv,都可以获取命令行或者说外部参数 web模式下,只有开启了register_ar ...

  4. 转 Android应用开发必备的20条技能

    https://blog.csdn.net/u012269126/article/details/52433237 有些andorid开发人员感觉很迷茫,接下来该去看系统源码还是继续做应用,但是感觉每 ...

  5. 【Linux】【Services】【SaaS】Docker+kubernetes(12. 部署prometheus/grafana/Influxdb实现监控)

    1.简介 1.1. 官方网站: promethos:https://prometheus.io/ grafana:https://grafana.com/ 1.2. 架构图 2. 环境 2.1. 机器 ...

  6. jquery:iframe里面的元素怎样触发父窗口元素的事件?

    例如父窗口定义了一个事件. top: $(dom1).bind('topEvent', function(){}); 那么iframe里面的元素怎样触发父窗口dom1的事件呢?这样吗? $(dom1, ...

  7. 4、Redis基础

    redis性能 1.关于测试性能 官方自带的测试性能的工具 redis-benchmark 压力测试工具 #进行压力测试.需求:测试:100个并发连接,100000个请求 #redis-benchma ...

  8. WPF将窗口置于桌面下方(可用于动态桌面)

    WPF将窗口置于桌面下方(可用于动态桌面) 先来看一下效果: 界面元素很简单,就一个Button按钮,然后写个定时器,定时更新Button按钮中的内容为当前时间,下面来介绍下原理,和界面组成. 窗口介 ...

  9. ciscn_2019_es_7

    这是我第一次见到srop的用法的题目,于是在此记录方便以后的复习 拿到程序例行检查 将程序放入ida中 可以看到栈的大小是0x10,却可以显示出0x30的内容,所以我们可以通过这个溢出泄露出/bin/ ...

  10. 2020 NUPCTF pwn题目

    去年的一场比赛,今年来把去年不会做的题目来看一下,只在buu找到三道题,剩下两道好像是内核题,算了,估计找到也不会做. npuctf_2020_level2 bss段上的格式化字符串漏洞的利用. 程序 ...