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程序中的。