因为工作需要在嵌入式mips平台上使用nginx做缓存。所以需要将nginx移植到mips平台上。移植过程还是相当简单的。下面给出移植步骤:
1.下载官方的源码包,并解压,准备好交叉编译环境;
2.编写配置脚本config.sh,脚本的主要功能如下:
a.设置交叉编译工具的路径
b.对根据自身的需要对nginx做裁减
下面给出config.sh的样例:
#!/bin/bash
export CC=mips-unknown-linux-uclibc-gcc
export CXX=mips-unknown-linux-uclibc-g++
export SYSROOT="/home/command/crosstool/usr/mips-unknown-linux-uclibc/sysroot"
#export CFLAGS="--sysroot=${SYSROOT}"
./configure \
--prefix=./cmd \
--conf-path=./conf/nginx.conf \
--error-log-path=./err_log \
--user=admin \
--group=root \
--with-select_module \
--with-poll_module \
--without-http_gzip_module \
--without-http_ssi_module \
--without-http_userid_module \
--without-http_access_module \
--without-http_auth_basic_module \
--without-http_autoindex_module \
--without-http_geo_module \
--without-http_map_module \
--without-http_split_clients_module \
--without-http_referer_module \
--without-http_rewrite_module \
--without-http_proxy_module \
--without-http_fastcgi_module \
--without-http_uwsgi_module \
--without-http_scgi_module \
--without-http_empty_gif_module \
--without-http_browser_module \
--without-http_upstream_hash_module \
--without-http_upstream_ip_hash_module \
--without-http_upstream_least_conn_module \
--without-http_upstream_keepalive_module \
--without-http_upstream_zone_module \
--with-cc=mips-unknown-linux-uclibc-gcc \
--with-cc-opt="--sysroot=/home/command/crosstool/usr/mips-unknown-linux-uclibc/sysroot" \
--without-pcre
****************************************************************************************************************
先解释 一下configure的错用,configure主要是在编译前检测本地的编译环境是否准备好,编译工具是否正常工作,相关的依赖库时候已安装等等。
由于nginx的configure脚本会自动检测当前平台的系统版本,然后根据系统版本进行相关的配置,所以这一步,我们会遇到几个错误,下面我会一一列举出来,并给出解决方法:
a.报错“checking for C compiler ... found but is not working”
原因:这个错误出现的原因是由于在执行configure时,会使用我们在config.sh里面配置的编译工具链去编一段测试程序,然后执行编译后的可执行文件。由于我们这里是交叉编译,编译的程序不能再编译的机器上执行,所以这里执行编译后的可执行程序肯定会出错,这回导致configure程序不通过。所以我们需要修改configure的脚本,使其不对编译后的可执行会文件做执行检查。
解决方法:修改源码根目录下面的auto/feature文件,找到下面的代码:
if [ -x $NGX_AUTOTEST ]; then
case "$ngx_feature_run" in
yes)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
else
echo " found but is not working"
fi
;;
我们见对编译后的可执行文件做执行检查的部分注释掉(行首加上#),修改后的如下(其它部分保持不变):
if [ -x $NGX_AUTOTEST ]; then
case "$ngx_feature_run" in
yes)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
#if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
if test -n "$ngx_feature_name"; then
have=$ngx_have_feature . auto/have
fi
#else
# echo " found but is not working"
#fi
;;
修改源码根目录下面的auto/cc/name文件找到如下部分:
if [ "$NGX_PLATFORM" != win32 ]; then
ngx_feature="C compiler"
ngx_feature_name=
ngx_feature_run=yes
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=
修改后的如下:
if [ "$NGX_PLATFORM" != win32 ]; then
ngx_feature="C compiler"
ngx_feature_name=
ngx_feature_run=
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=
=====================================================================
b. 报错”./configure: error: can not detect int size“
原因:这个报错是由于执行configure时会去执行一段代码检测当前机器上int占用多少个字节,由于我们是交叉编译,所以肯定不能正常检测。
解决方法:修改源码根目录下面的auto/types/sizeof文件,找到如下代码处:
if [ -x $NGX_AUTOTEST ]; then
ngx_size=`$NGX_AUTOTEST`
echo " $ngx_size bytes"
fi
由于我们这里不能执行代码区检测,所以我们就直接将检测的size写死(根据自己的平台来写,我的mips平台上int占用4字节),修改后如下:
if [ -x $NGX_AUTOTEST ]; then
#ngx_size=`$NGX_AUTOTEST`
ngx_size=4
echo " $ngx_size bytes"
fi
4.到这里config.sh是执行通过了。执行make命令编译源码。很快会出现如下错误:
src/os/unix/ngx_errno.c: In function ‘ngx_strerror’:
src/os/unix/ngx_errno.c:37:43: error: expected expression before ‘)’ token
src/os/unix/ngx_errno.c: In function ‘ngx_strerror_init’:
src/os/unix/ngx_errno.c:58:24: error: invalid type argument of unary ‘*’ (have ‘unsigned int’)
src/os/unix/ngx_errno.c:65:37: error: expected expression before ‘;’ token
objs/Makefile:603: recipe for target 'objs/src/os/unix/ngx_errno.o' failed
原因:这个错误出现的原因是由于在configure阶段会检测当前系统的类型(linux, unix,win32 等等),然后根据系统类型去检测当前系统的errno的最大值,并设置环境变量NGX_SYS_NERR这个环境变量为这个最大值。由于我们是交叉编译,所以这个errno的最大值是检测不到的,所以NGX_SYS_NERR就是空的,放到代码里面去肯定是会出错的。
解决方法:修改configure是检测的系统类型为我们真实的类型(我这里是mips),并且根据平台将errno的最大值写死。
修改configure文件,找到如下部分将其注释掉并添加我们平台的定义:
NGX_SYSTEM=`uname -s 2>/dev/null`
NGX_RELEASE=`uname -r 2>/dev/null`
NGX_MACHINE=`uname -m 2>/dev/null`
修改后的部分如下:
#NGX_SYSTEM=`uname -s 2>/dev/null`
#NGX_RELEASE=`uname -r 2>/dev/null`
#NGX_MACHINE=`uname -m 2>/dev/null`
NGX_SYSTEM=Linux
NGX_RELEASE=3.4.11-rt19
NGX_MACHINE=mips
除此之外我们还需要修改设置NGX_SYS_NERR这边变量的地方,将其设置为我们平台对应的值(我这里的mips平台的值是47),找到auto/feature的如下部分:
#ifndef $ngx_feature_name
#define $ngx_feature_name `$NGX_AUTOTEST`
#endif
修改后部分的如下:
#ifndef $ngx_feature_name
//#define $ngx_feature_name `$NGX_AUTOTEST`
#define $ngx_feature_name 47
#endif
到这里基本就完了,依次执行make clean; make; make install就可以了。
生成可执行文件以及库文件在源码和config.sh文件里面配置的prefix环境变量的值一致,我这里是源码根目录下面的cmd文件下面。
版权所有,转载请说明出处,谢谢!