擁抱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上,可以方便運行了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章