微信公众号:Nginx源码分析
关注可了解更多的Nginx
知识。任何问题或建议,请公众号留言;
关注公众号,有趣有内涵的文章第一时间送达!
内容简介
本文分析auto/lib
相关脚本的功能。
从脚本名称我们也能够知道,这部分是和第三方库相关的。比如pcre
库,openssl
, perl
等。
我们首先看一下这个目录中的各个脚本的作用。如下图:
auto/lib/conf脚本
这个脚本就在configure
中被调用。负责auto/lib
下的所有第三方库的配置工作。
脚本内容
if [ $USE_PCRE = YES -o $PCRE != NONE ]; then
. auto/lib/pcre/conf
else
if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option or you have to enable the PCRE support.
END
exit 1
fi
fi
if [ $USE_OPENSSL = YES ]; then
. auto/lib/openssl/conf
fi
if [ $USE_ZLIB = YES ]; then
. auto/lib/zlib/conf
fi
if [ $USE_LIBXSLT != NO ]; then
. auto/lib/libxslt/conf
fi
if [ $USE_LIBGD != NO ]; then
. auto/lib/libgd/conf
fi
if [ $USE_PERL != NO ]; then
. auto/lib/perl/conf
fi
if [ $USE_GEOIP != NO ]; then
. auto/lib/geoip/conf
fi
if [ $NGX_GOOGLE_PERFTOOLS = YES ]; then
. auto/lib/google-perftools/conf
fi
if [ $NGX_LIBATOMIC != NO ]; then
. auto/lib/libatomic/conf
fi
脚本分析
我们观察一下这个脚本,会发现所有的功能处理方法都是类似的。先判断是否使用了某个功能,如果使用了,就调用对应的auto/lib
脚本。
我们以pcre
为例分析auto/lib/conf
的作用。
在auto/lib/conf
的最上面就是对pcre
的处理。
if [ $USE_PCRE = YES -o $PCRE != NONE ]; then
. auto/lib/pcre/conf
else
if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option or you have to enable the PCRE support.
END
exit 1
fi
fi
这部分脚本首先会判断USE_PCRE
和PCRE
的值,这两个变量的值都是是在auto/option
中进行设置的。
默认情况下,这两个变量的值如下:
USE_PCRE=NO
PCRE=NONE
通过执行configure
脚本时传递--with-pcre=*) PCRE="$value"
参数可以设置这两个变量的值。其中USE_PCRE
表示是否使用pcre
库。PCRE
表示pcre
库所在的目录。
--without-pcre) USE_PCRE=DISABLED ;;
--with-pcre) USE_PCRE=YES ;;
--with-pcre=*) PCRE="$value" ;;
如果我们没有设置pcre
,但是使用了http_rewrite
功能,那么在执行./cofigure
脚本的时候就会报错,如下:
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option or you have to enable the PCRE support.
这是我们在编译nginx
的时候经常遇到的错误,就是上面所说的原因造成的。
注意:我们在
./configure
的时候可能并没有指定--with-pcre
,但是默认情况下还是会编译pcre
的。因为默认情况下HTTP_REWRITE = YES
,在执行auto/modules
脚本(后面分析)的时候,会根据HTTP_REWRITE
来设置USE_PCRE
的值。
pcre脚本
下面我们看一下auto/lib/pcre/conf
脚本主要干了什么工作。
先看一下脚本内容:
if [ $PCRE != NONE ]; then
CORE_INCS="$CORE_INCS $PCRE"
case "$NGX_CC_NAME" in
msvc | owc | bcc)
have=NGX_PCRE . auto/have
have=PCRE_STATIC . auto/have
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
LINK_DEPS="$LINK_DEPS $PCRE/pcre.lib"
CORE_LIBS="$CORE_LIBS $PCRE/pcre.lib"
;;
icc)
have=NGX_PCRE . auto/have
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
echo $ngx_n "checking for PCRE library ...$ngx_c"
if [ -f $PCRE/pcre.h ]; then
ngx_pcre_ver=`grep PCRE_MAJOR $PCRE/pcre.h \
| sed -e 's/^.*PCRE_MAJOR.* \(.*\)$/\1/'`
else if [ -f $PCRE/configure.in ]; then
ngx_pcre_ver=`grep PCRE_MAJOR= $PCRE/configure.in \
| sed -e 's/^.*=\(.*\)$/\1/'`
else
ngx_pcre_ver=`grep pcre_major, $PCRE/configure.ac \
| sed -e 's/^.*pcre_major,.*\[\(.*\)\].*$/\1/'`
fi
fi
echo " $ngx_pcre_ver major version found"
# to allow -ipo optimization we link with the *.o but not library
case "$ngx_pcre_ver" in
4|5)
CORE_LIBS="$CORE_LIBS $PCRE/pcre.o"
;;
6)
CORE_LIBS="$CORE_LIBS $PCRE/pcre_chartables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_compile.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_exec.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_fullinfo.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_globals.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_tables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_try_flipped.o"
;;
*)
CORE_LIBS="$CORE_LIBS $PCRE/pcre_chartables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_compile.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_exec.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_fullinfo.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_globals.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_tables.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_try_flipped.o"
CORE_LIBS="$CORE_LIBS $PCRE/pcre_newline.o"
;;
esac
;;
*)
have=NGX_PCRE . auto/have
if [ "$NGX_PLATFORM" = win32 ]; then
have=PCRE_STATIC . auto/have
fi
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a"
;;
esac
if [ $PCRE_JIT = YES ]; then
have=NGX_HAVE_PCRE_JIT . auto/have
PCRE_CONF_OPT="$PCRE_CONF_OPT --enable-jit"
fi
else
if [ "$NGX_PLATFORM" != win32 ]; then
PCRE=NO
ngx_feature="PCRE library"
ngx_feature_name="NGX_PCRE"
ngx_feature_run=no
ngx_feature_incs="#include <pcre.h>"
ngx_feature_path=
ngx_feature_libs="-lpcre"
ngx_feature_test="pcre *re;
re = pcre_compile(NULL, 0, NULL, 0, NULL);
if (re == NULL) return 1"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="PCRE library in /usr/local/"
ngx_feature_path="/usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lpcre"
else
ngx_feature_libs="-L/usr/local/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# RedHat RPM, Solaris package
ngx_feature="PCRE library in /usr/include/pcre/"
ngx_feature_path="/usr/include/pcre"
ngx_feature_libs="-lpcre"
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="PCRE library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lpcre"
else
ngx_feature_libs="-L/usr/pkg/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="PCRE library in /opt/local/"
ngx_feature_path="/opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lpcre"
else
ngx_feature_libs="-L/opt/local/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_INCS="$CORE_INCS $ngx_feature_path"
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
PCRE=YES
fi
if [ $PCRE = YES ]; then
ngx_feature="PCRE JIT support"
ngx_feature_name="NGX_HAVE_PCRE_JIT"
ngx_feature_test="int jit = 0;
pcre_free_study(NULL);
pcre_config(PCRE_CONFIG_JIT, &jit);
if (jit != 1) return 1;"
. auto/feature
if [ $ngx_found = yes ]; then
PCRE_JIT=YES
fi
fi
fi
if [ $PCRE != YES ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
END
exit 1
fi
fi
脚本分析
从脚本的整体内容上来看,auto/lib/pcre/conf
是一个if-else
结构,分别处理PCRE
变量为空和非空的情况。
如果在configre
的时候通过--with-pcre
选项指定了pcre
的库文件路径,那么执行if
部分,否则执行else
部分,二者的处理逻辑基本相同。下面我们详细分析这两种情况。
1).
指定pcre
路径
if [ $PCRE != NONE ]; then
CORE_INCS="$CORE_INCS $PCRE"
case "$NGX_CC_NAME" in
*)
have=NGX_PCRE . auto/have
if [ "$NGX_PLATFORM" = win32 ]; then
have=PCRE_STATIC . auto/have
fi
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a"
;;
esac
if [ $PCRE_JIT = YES ]; then
have=NGX_HAVE_PCRE_JIT . auto/have
PCRE_CONF_OPT="$PCRE_CONF_OPT --enable-jit"
fi
else # 没有设置 PCRE 变量
这部分整体就是一个case
语句,根据NGX_CC_NAME
的值执行不同的处理逻辑。这个变量我们在之前的分析auto/cc
的时候说过,它表示的是当前使用的编译器。我使用的是gcc
,所以执行的是default
部分。所以我把那些执行不到的case
分支删了,只保留了default
部分。
这部分代码就是设置一些编译时候要用到的变量,根据configre
时设置的pcre
源文件以及库文件的路径,设置到编译选项中,等到最后生成Makefile
的时候使用。
注意:这里并没有判断
pcre
是否存在,因为没有必要,既然你在执行configure
的时候已经手动指定了pcre
的路径,那么nginx
就认为它是存在的,如果不存在,那么在最后编译的时候会报错。这点和下面我们要分析的else
部分不同。
然后又通过PCRE_CONF_OPT
参数设置pcre
即时编译相关功能,在编译pcre
的时候会使用。
2).
未指定pcre
路径
else
if [ "$NGX_PLATFORM" != win32 ]; then
PCRE=NO
ngx_feature="PCRE library"
ngx_feature_name="NGX_PCRE"
ngx_feature_run=no
ngx_feature_incs="#include <pcre.h>"
ngx_feature_path=
ngx_feature_libs="-lpcre"
ngx_feature_test="pcre *re;
re = pcre_compile(NULL, 0, NULL, 0, NULL);
if (re == NULL) return 1"
. auto/feature
if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="PCRE library in /usr/local/"
ngx_feature_path="/usr/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lpcre"
else
ngx_feature_libs="-L/usr/local/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# RedHat RPM, Solaris package
ngx_feature="PCRE library in /usr/include/pcre/"
ngx_feature_path="/usr/include/pcre"
ngx_feature_libs="-lpcre"
. auto/feature
fi
if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="PCRE library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lpcre"
else
ngx_feature_libs="-L/usr/pkg/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="PCRE library in /opt/local/"
ngx_feature_path="/opt/local/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lpcre"
else
ngx_feature_libs="-L/opt/local/lib -lpcre"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_INCS="$CORE_INCS $ngx_feature_path"
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
PCRE=YES
fi
if [ $PCRE = YES ]; then
ngx_feature="PCRE JIT support"
ngx_feature_name="NGX_HAVE_PCRE_JIT"
ngx_feature_test="int jit = 0;
pcre_free_study(NULL);
pcre_config(PCRE_CONFIG_JIT, &jit);
if (jit != 1) return 1;"
. auto/feature
if [ $ngx_found = yes ]; then
PCRE_JIT=YES
fi
fi
fi
if [ $PCRE != YES ]; then
cat << END
$0: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
END
exit 1
fi
fi
这一部分是在没有设置pcre
的时候执行。nginx
会通过auto/feature
脚本测试当前操作系统是否支持pcre
功能。
这一部分脚本虽然比较多,但是功能特别单一。
首先默认pcre
安装在了标准路径
中。这里的标准路径
指的是编译器默认查找头文件以及库文件的路径。
如果没有找到,那么依次从
/usr/include/pcre
,
/usr/pkg/include
, /opt/local/include
路径中查找,如果在任何一个路径中找到pcre
都算成功。
找到PCRE
之后,会进一步的测试PCRE_JIT
功能。
如果经过上面的步骤之后,还是没有找到pcre
,那么就会输出错误提示,如下:
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
整个脚本分析结束。
总结
我们在本文中详细的分析了auto/lib/
目录下的脚本。
这一部分的脚本主要是为了nginx
使用到的第三方库进行便已测试。我只对pcre
库的内容进行了分析。其他的大家可以自行分析。
后面的文章我们会接着分析nginx
的源码,敬请期待。顺便关注我的个公众号(Nginx源码分析
)。