3.3.2 利用configure脚本将定制的模块加入到Nginx中

在1.6节提到的configure执行流程中,其中有两行脚本负责将第三方模块加入到Nginx中,如下所示。


.auto/modules

.auto/make


下面完整地解释一下configure脚本是如何与3.3.1节中提到的config文件配合起来把定制的第三方模块加入到Nginx中的。

在执行configure—add-module=PATH命令时,PATH就是第三方模块所在的路径。在configure中,通过auto/options脚本设置了NGX_ADDONS变量:


—add-module=*)NGX_ADDONS="$NGX_ADDONS$value";


在configure命令执行到auto/modules脚本时,将在生成的ngx_modules.c文件中加入定制的第三方模块。


if test-n"$NGX_ADDONS";then

echo configuring additional modules

for ngx_addon_dir in$NGX_ADDONS

do

echo"adding module in$ngx_addon_dir"

if test-f$ngx_addon_dir/config;then

在这里执行自定义的config脚本

.$ngx_addon_dir/config

echo"+$ngx_addon_name was configured"

else

echo"$0:error:no$ngx_addon_dir/config was found"

exit 1

fi

done

fi


可以看到,$NGX_ADDONS可以包含多个目录,对于每个目录,如果其中存在config文件就会执行,也就是说,在config中重新定义的变量都会生效。之后,auto/modules脚本开始创建ngx_modules.c文件,这个文件的关键点就是定义了ngx_module_t*ngx_modules[]数组,这个数组存储了Nginx中的所有模块。Nginx在初始化、处理请求时,都会循环访问ngx_modules数组,确定该用哪一个模块来处理。下面来看一下auto/modules是如何生成数组的,代码如下所示:


modules="$CORE_MODULES$EVENT_MODULES"

if[$USE_OPENSSL=YES];then

modules="$modules$OPENSSL_MODULE"

CORE_DEPS="$CORE_DEPS$OPENSSL_DEPS"

CORE_SRCS="$CORE_SRCS$OPENSSL_SRCS"

fi

if[$HTTP=YES];then

modules="$modules$HTTP_MODULES$HTTP_FILTER_MODULES\

$HTTP_HEADERS_FILTER_MODULE\

$HTTP_AUX_FILTER_MODULES\

$HTTP_COPY_FILTER_MODULE\

$HTTP_RANGE_BODY_FILTER_MODULE\

$HTTP_NOT_MODIFIED_FILTER_MODULE"

NGX_ADDON_DEPS="$NGX_ADDON_DEPS\$(HTTP_DEPS)"

fi


首先,auto/modules会按顺序生成modules变量。注意,这里的$HTTP_MODULES等已经在config文件中重定义了。这时,modules变量是包含所有模块的。然后,开始生成ngx_modules.c文件:


cat<<END>$NGX_MODULES_C

include<ngx_config.h>

include<ngx_core.h>

$NGX_PRAGMA

END

for mod in$modules

do

echo"extern ngx_module_t$mod;">>$NGX_MODULES_C

done

echo

>>$NGX_MODULES_C

echo'ngx_module_t*ngx_modules[]={'

>>$NGX_MODULES_C

for mod in$modules

do

向ngx_modules数组里添加Nginx模块

echo"

&$mod,"

>>$NGX_MODULES_C

done

cat<<END

>>$NGX_MODULES_C

NULL

};

END


这样就已经确定了Nginx在运行时会调用自定义的模块,而auto/make脚本负责把相关模块编译进Nginx。

在Makefile中生成编译第三方模块的源代码如下:


if test-n"$NGX_ADDON_SRCS";then

ngx_cc="\$(CC)$ngx_compile_opt\$(CFLAGS)$ngx_use_pch\$(ALL_INCS)"

for ngx_src in$NGX_ADDON_SRCS

do

ngx_obj="addon/basename\dirname$ngx_src\"

ngx_obj=echo$ngx_obj/\basename$ngx_src\

|sed-e"s/\//$ngx_regex_dirsep/g"

ngx_obj=echo$ngx_obj\

|sed-e

"s#^\(.*.\)cpp\$#$ngx_objs_dir\1$ngx_objext#g"\

-e

"s#^\(.*.\)cc\$#$ngx_objs_dir\1$ngx_objext#g"\

-e

"s#^\(.*.\)c\$#$ngx_objs_dir\1$ngx_objext#g"\

-e

"s#^\(.*.\)S\$#$ngx_objs_dir\1$ngx_objext#g"

ngx_src=echo$ngx_src|sed-e"s/\//$ngx_regex_dirsep/g"

cat<<END

>>$NGX_MAKEFILE

$ngx_obj:\$(ADDON_DEPS)$ngx_cont$ngx_src

$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX

END

done

fi


下面这段代码用于将各个模块的目标文件设置到ngx_obj变量中,紧接着会生成Makefile里的链接代码,并将所有的目标文件、库文件链接成二进制程序。


for ngx_src in$NGX_ADDON_SRCS

do

ngx_obj="addon/basename\dirname$ngx_src\"

test-d$NGX_OBJS/$ngx_obj||mkdir-p$NGX_OBJS/$ngx_obj

ngx_obj=echo$ngx_obj/\basename$ngx_src\

|sed-e"s/\//$ngx_regex_dirsep/g"

ngx_all_srcs="$ngx_all_srcs$ngx_obj"

done

……

cat<<END

>>$NGX_MAKEFILE

$NGX_OBJS${ngx_dirsep}nginx${ngx_binext}:

$ngx_deps$ngx_spacer\$(LINK)

${ngx_long_start}${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link

$ngx_rcc

${ngx_long_end}

END


综上可知,第三方模块就是这样嵌入到Nginx程序中的。