拥抱Android:编译nginx搭建移动平台

Android编译系列篇:

1 - Python

2 - NodeJS

3 - Nginx

4 - MariaDB


编译好的版本 android (>6), arm, nginx-1.10.2: https://github.com/dna2github/dna2oslab/releases

再起:Nginx-1.10.2

初遇Nginx-1.9.5那回,把nginx编译一遍,然后将build log抓出来分析处理,才手动编译好。

看了:http://tiebing.blogspot.jp/2014/09/cross-compile-nginx-for-arm.html

对啊,用local的configure生成好一切东西,改改生成的文件,再编译就方便许多,过程也干净许多。

编译脚本:https://github.com/dna2github/dna2oslab/blob/master/android/build/nginx-1.10.2-pie.sh

比较繁琐的还是处理glob,把它干掉;然后还有crypt函数没有,直接用openssl里的DES_crypt充当。

这样一来session cache问题解决了,basic auth和gzip也可以用了。


初遇:Nginx-1.9.5

不知不觉已经开始写拥抱Android的第三篇文章了,这次是nginx 1.9.5。

虽然过程很山寨,但是效果还不错,至少在Android上能跑起来。

程序员作为手机党出去旅游可以给大家提供wifi和娱乐服务啦!去国外旅游,买个十几天无限流量,开个热点,开个斗地主或者三国杀什么的,和大家玩得不及乐乎!

脚本可以从github上获得:https://github.com/dna2github/dna2oslab/tree/master/android/build

先放个模拟器运行成功图(http和https):

(1)运行http的效果图

(2)运行https的效果图

其实还编译了mail和stream(http v2)的模块,结合以前的python与nodejs,前端服务器和后端wsgi~

这次的编译没有走寻常路线,因为发现nginx的编译脚本略坑。

当然,首先是想走普通路线的,运行一下,首先它会一堆check,这么我完全没有办法cross compile啊,第一步就会test gcc报gcc编出来的东西不能运行。显然的,arm代码何以横行intel。

读了下编译脚本,写得挺结构化,就是不太好去掉每次check feature完都要运行程序test的部分,其实是懒。

然后就想,nginx代码也不多,直接写脚本一个文件一个文件编译吧。

于是找了台linux,裸编译./configure --prefix=xxx $WANTED_MODULES && make | tee build.log得到一个build日志。

这下好办了,不过日志有几万行呢,这么多!

只是nginx强制使用openssl和pcre的source code然后编译一遍,我这有现成的啊!

于是删除所有openssl和pcre的编译过程,发现nginx的编译过程就2100多行,基本每3行编译一个o文件。

把include改成shell变量的形式写,一下子log清晰了很多,处理好了就成了一个sh。

开始编译,./droid-nginx.sh

当头棒是ngx_auto_headers.h没有,找找代码,是configure生成的,没关系,我们只要把nginx编译出来,所以这个直接从linux上编译好的nginx的objs文件夹拿来用吧。

包括ngx_auto_headers.h, ngx_auto_config.h和ngx_modules.c三个文件都需要。

一开始报的错就是glob.h没有,查了查这是什么。文件搜索的库函数,我们需要么?

再看看是哪里用了,最后就是在读取conf的时候,如果你给了include一个不明确的文件,它就执行搜索。直接干掉。于是grep "glob" nginx-1.9.5/src -r,把所有glob有关的申明和调用全部删除。当然src/core/ngx_conf_file.c下面关于glob的部分删除就删除了,那个通过include读conf的函数别删除了,把里面后半部分注释掉,写个返回错误就好了,这样nginx还可以在conf文件里使用include加载具体文件,比如conf/mime.types。

crypt.h这个头文件也没有,这会影响basic_auth模块,所以这个模块以后再研究,先把nginx编译出来再说。直接干掉too。

后面的事情就好办了,什么没有加什么,Linux Cross Reference是个好伙伴。

列举下sed需要的映射:

所有 in_port_t 改 uint16_t

SO_REUSEPORT 改 0x2000

AT_EMPTY_PATH 改 0x2000

O_PATH 改 0x1000000

IOV_MAX 改 1024

SOCK_NONBLOCK 改 0x0080

然后有一些东西Android上没有的,直接注释掉:

比如http_degration和http_gzip的模块依赖有问题,先干掉。比如ACCEPT4, POSIX_FADVIS, EPOLLRDHUP没有, 通通在ngx_auto_conf.h里干掉!

于是程序最终很开心地走到了最后。

下面遇到一个文件是libssl.a各种函数未定义,弄到最后原来是libcrypto.a和libssl.a的位置不能反,libssl.a在前面!

这里就把nginx用hack的方式编译完了。

能用么?

adb push nginx /data/local/tmp

adb shell

# cd /data/local/tmp

# mkdir client_body_temp conf fastcgi_temp html logs proxy_temp sbin scgi_temp uwsgi_temp

# mv nginx sbin/

然后再把conf文件夹里的东西全部adb push到/data/local/tmp/conf里,跑起!

nginx: [emerg] getpwnam("nginx") failed (2: No such file or directory)

挂了。说没有nginx这个用户。

太离谱了,直接气冲冲地跑去src/core/nginx.c找getpwnam算账。把它们连带grp的函数全部干掉,uid 1000, gid 1000,再编译一遍。

nginx: [alert] could not open error log file: open() "/usr/local/nginx/logs/error.log" failed (2: No such file or directory)

2015/11/09 12:27:53 [emerg] 787#0: open() "/usr/local/nginx/conf/nginx.conf" failed (2: No such file or directory)

又报错,哪里设置了prefix,经查办,ngx_auto_conf.h里有,把prefix设置为空字符串"",这回编译再运行,好了一切成功了。

先写个index.html: echo '<html><body><h1>hello world</h1></body></html>' > html/index.html

打开模拟器的浏览器,输入http://127.0.0.1/ (模拟器已经root,所以可以用80,不然还是8080吧)

hello world

出现了!

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout cert.key -out cert.crt

然后修改下nginx.conf,把https server配置上,第一个是session cache会有问题,先不管,估计是注释了crypt.h的原因,统统干掉。

再sbin/nginx运行,打开浏览器输入https://127.0.0.1,系统提示自签名证书,继续,页面加载成功

hello world

至此,nginx编译完成。

下一篇文章,我可能会带大家一起编译mariadb(先赞下它的模块化,编译脚本输出也很清晰);

或者尝试如何信手拈来,达到我要python或nodejs的入口,还有nginx的入口,写一个Java App结合JNI技术将所有东西连起来。这样写的app就有python和node支持,可以不用都往internal scard上装,直接把py或js文件放sdcard上,可以方便运行了。

发布了51 篇原创文章 · 获赞 37 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/prog_6103/article/details/49744633