Nginx编译配置脚本篇- 工具型脚本系列

Posted 彼方丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx编译配置脚本篇- 工具型脚本系列相关的知识,希望对你有一定的参考价值。

1、相关文章

由于学习本文需要Nginx源码及搭建相关的编译环境,且本文与前面的文章有先后呼应关系,所以建议大家按以下文章顺序阅读

2、前言

本文将介绍Nginx里面的一些工具型脚本,里面有些是内容比较简短,有些是内容比较相似的,故放在一起讲了。需要注意的是,本文并不完全按照configure文件的调用顺序来讲解各个脚本。
configure文件将在最后一篇关于Nginx脚本配置文件的文章中讲解)

3、目录

3.1、auto/have脚本文件

  • 主要功能:向自动配置头文件中添加标示有指定参数的宏定义
  • 处理变量:$have
  • 作用对象:$NGX_AUTO_CONFIG_H所表示的自动配置头文件(前文介绍过了,该值默认为objs/ngx_auto_config.h
  • 源代码如下:
cat << END >> $NGX_AUTO_CONFIG_H

#ifndef $have
#define $have  1
#endif

END
  • have变量的值为NGX_DEBUG,则运行该脚本后,objs/ngx_auto_config.h中将追加如下内容:
#ifndef NGX_DEBUG
#define NGX_DEBUG 1
#endif

3.2、auto/nohave脚本文件

  • 主要功能:向自动配置头文件中添加标示没有指定参数的宏定义
  • 处理变量:$have
  • 作用对象:$NGX_AUTO_CONFIG_H所表示的自动配置头文件(前文介绍过了,该值默认为objs/ngx_auto_config.h
  • 源代码如下:
cat << END >> $NGX_AUTO_CONFIG_H

#ifndef $have
#define $have  0
#endif

END
  • have变量的值为NGX_DEBUG,则运行该脚本后,objs/ngx_auto_config.h中将追加如下内容:
#ifndef NGX_DEBUG
#define NGX_DEBUG 0
#endif

3.3、auto/define脚本文件

  • 主要功能:向自动配置头文件中添加标示指定参数的值
  • 处理变量:$have$value
  • 作用对象:$NGX_AUTO_CONFIG_H所表示的自动配置头文件(前文介绍过了,该值默认为objs/ngx_auto_config.h
  • 源代码如下:
cat << END >> $NGX_AUTO_CONFIG_H

#ifndef $have
#define $have  $value
#endif

END
  • have变量的值为NGX_CPU_CACHE_LINEvalue变量的值为64,则运行该脚本后,objs/ngx_auto_config.h中将追加如下内容:
#ifndef NGX_CPU_CACHE_LINE
#define NGX_CPU_CACHE_LINE 64
#endif

3.4、auto/have_headers脚本文件

  • 主要功能:向自动头头文件中添加标示有指定参数的宏定义
  • 处理变量:$have
  • 作用对象:$NGX_AUTO_HEADERS_H所表示的自动头文件(前文介绍过了,该值默认为objs/ngx_auto_headers.h
  • 源代码如下:
cat << END >> $NGX_AUTO_HEADERS_H

#ifndef $have
#define $have  1
#endif

END
  • have变量的值为NGX_HAVE_UNISTD_H,则运行该脚本后,objs/ngx_auto_headers.h中将追加如下内容:
#ifndef NGX_HAVE_UNISTD_H
#define NGX_HAVE_UNISTD_H 1
#endif

3.5、auto/feature脚本文件

该文件的主要功能是测试系统环境是否支持某些操作的,如果测试了某一操作不支持,则会将错误信息输出到$NGX_AUTOCONF_ERR文件中

$NGX_AUTOCONF_ERR默认值是autoconf.err,该变量是在auto/init文件中被初始化的

接下来详细分析该文件:

3.5.1、输出检查提示信息

在《Nginx编译配置脚本篇(2)- Makefile初始化脚本auto/init》一文中我们介绍了关于ngx_nngx_c两个变量,在auto/feature中的第一句有效代码是:

echo $ngx_n "checking for $ngx_feature ...$ngx_c"

这一行代码的意思就是输出checking for $ngx_feature和换行符到$NGX_AUTOCONF_ERR文件中,以此来提示我们当前检查的操作是$ngx_feature。当然ngx_nngx_c是有可能都为空的,这时就没有换行了。

3.5.2、初始化ngx_found变量

代码如下:

ngx_found=no

3.5.3、初始化ngx_have_feature变量

代码如下:

if test -n "$ngx_feature_name"; then
    ngx_have_feature=`echo $ngx_feature_name \\
                   | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
fi

test -n的意思是测试参数的长度是否为0。那么如果ngx_feature_name的值为空,则不会执行if语句,if语句的内容是将ngx_have_feature的值设置为ngx_feature_name的值的大写版本(代码中使用tr命令将小写全部改为大写)。

3.5.4、初始化ngx_feature_inc_path变量

代码如下:

if test -n "$ngx_feature_path"; then
    for ngx_temp in $ngx_feature_path; do
        ngx_feature_inc_path="$ngx_feature_inc_path -I $ngx_temp"
    done
fi

test -n的意思是测试参数的长度是否为0。假设ngx_feature_path的值为/path/111 /path/222 /path/333,则经过for循环后ngx_feature_inc_path的值将被置为-I /path/111 -I /path/222 -I /path/333
-I pathgcc编译中指定头文件路径的语法)

3.5.5、生成自动测试程序

代码如下:

cat << END > $NGX_AUTOTEST.c

#include <sys/types.h>
$NGX_INCLUDE_UNISTD_H
$ngx_feature_incs

int main(void) {
    $ngx_feature_test;
    return 0;
}

END
  • NGX_AUTOTEST的值是在auto/init脚本中被初始化的,默认为objs/autotest,在此处最终加上后缀名变为objs/autotest.c
  • NGX_INCLUDE_UNISTD_H暂时没有什么用,不用理会
  • ngx_feature_incs表示需要包含的头文件信息
  • ngx_feature_test表示测试函数,如果编译能成功表示当前系统环境支持改函数,反之不支持

3.5.6、编译自动测试程序

代码如下:

ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \\
          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"

ngx_feature_inc_path=

eval "/bin/sh -c \\"$ngx_test\\" >> $NGX_AUTOCONF_ERR 2>&1"
  • CC的值是在atuo/options中设置的,值默认为cc
  • CC_TEST_FLAGS的值是在atuo/cc/目录中根据环境不同进行不同的设置的,在Linux该值默认为-pipe

-pipegcc的一个编译选项,用于加快编译速度用的。gcc在将源代码变成可执行文件的过程中,需要经过许多中间步骤,包括预处理、编译、汇编和连接,这些过程实际上是由不同的程序负责完成的。大多数情况下gcc可以自动调用相应程序进行处理,替程序员完成一整套编译工作。但是这样做有一个很明显的缺点,就是gcc在处理每一个源文件时,最终都需要生成好几个临时文件才能完成相应的工作,从而无形中导致处理速度变慢。例如,gcc在处理一个源文件时,可能需要一个临时文件来保存预处理的输出,一个临时文件来保存编译器的输出,一个临时文件来保存汇编器的输出,而读写这些临时文件显然需要耗费一定的时间。当软件项目变得非常庞大的时候,花费在这上面的代价可能会变得很大。解决的办法是,使用Linux提供的一种更加高效的通信方式——管道。它可以用来同时连接两个程序,其中一个程序的输出将直接作为另一个程序的输入,这样就可以避免使用临时文件,但编译时需要消耗更多的内存。

  • CC_AUX_FLAGS的值是在atuo/os/目录中根据环境不同进行不同的设置的
  • ngx_feature_inc_path3.5.4小节介绍过了,这里就不赘述了
  • NGX_AUTOTEST3.5.5小节介绍过了,这里就不赘述了
  • NGX_TEST_LD_OPT是链接选项了,一般为空
  • ngx_feature_libs是需要链接的动态库,有些需要有些不需要,比如测试epoll就不需要链接动态库了,测试pthread则需要链接动态库了
  • 展开示例:
ngx_test="cc -pipe -D_GNU_SOURCE -o objs/autotest objs/autotest.c -ldl"
  • 使用ngx_feature_inc_path=ngx_feature_inc_path的值置为空,以免影响后续调用
  • 最后运行编译程序生成可执行文件,并将标准错误信息输出到$NGX_AUTOCONF_ERR文件中

3.5.7、根据ngx_feature_run进行相应的处理

  • Shell编程中-x表示检查文件是否存在且是一个可执行文件。如果$NGX_AUTOTEST文件符合条件则执行then的操作。
if [ -x $NGX_AUTOTEST ]; then

    case "$ngx_feature_run" in
  • 如果ngx_feature_run的值为yes,则将执行$NGX_AUTOTEST文件,将标准错误信息输出到$NGX_AUTOCONF_ERR文件中。
    可以看到如果执行成功,会输出 found,并将ngx_found的值置为yes。如果此时ngx_feature_name的值不为空,则将have的值设置为ngx_have_feature的值,并引用auto/have脚本向objs/ngx_auto_config.h写入宏定义,以此来表示某个功能被开启。
    如果程序执行错误,则执行else,输出错误信息。
    代码如下:
        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
        ;;
  • 如果ngx_feature_run的值为value,则也是执行$NGX_AUTOTEST文件,将标准错误信息输出到$NGX_AUTOCONF_ERR文件中。
    可以看到如果执行成功,会输出 found,并将ngx_found的值置为yes,最后向$NGX_AUTO_CONFIG_H文件中写入宏定义。
    写入文件示例如下:
#ifndef NGX_HTTP_SCGI_TEMP_PATH
#define NGX_HTTP_SCGI_TEMP_PATH  "scgi_temp"
#endif

如果程序执行错误,则执行else,输出错误信息。

        value)
            # /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

                cat << END >> $NGX_AUTO_CONFIG_H

#ifndef $ngx_feature_name
#define $ngx_feature_name  `$NGX_AUTOTEST`
#endif

END
            else
                echo " found but is not working"
            fi
        ;;
  • 如果ngx_feature_run的值为bug,情况与前面类似,不过这个是当程序执行成功才会写入信息到文件中去的,与前面的逻辑相反,其他的操作都是一样的了,代码如下:
        bug)
            # /bin/sh is used to intercept "Killed" or "Abort trap" messages
            if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
                echo " not found"

            else
                echo " found"
                ngx_found=yes

                if test -n "$ngx_feature_name"; then
                    have=$ngx_have_feature . auto/have
                fi
            fi
        ;;
  • 如果是其他情况,则只要ngx_feature_name不为空的话就将ngx_have_feature相关的宏写入$NGX_AUTO_CONFIG_H文件中。
    (这种情况一般是某些函数接口在所有系统上都有实现,且暴露出来的接口是一致的,则不需要去特意检查当前环境是否支持该函数接口了)
        *)
            echo " found"
            ngx_found=yes

            if test -n "$ngx_feature_name"; then
                have=$ngx_have_feature . auto/have
            fi
        ;;

    esac
  • 如果$NGX_AUTOTEST文件不存在或者不可执行,则执行下面的else里面的内容,输出错误信息到$NGX_AUTOCONF_ERR文件中。
else
    echo " not found"

    echo "----------"    >> $NGX_AUTOCONF_ERR
    cat $NGX_AUTOTEST.c  >> $NGX_AUTOCONF_ERR
    echo "----------"    >> $NGX_AUTOCONF_ERR
    echo $ngx_test       >> $NGX_AUTOCONF_ERR
    echo "----------"    >> $NGX_AUTOCONF_ERR
fi

3.5.8、删除与本次测试生成的文件

代码如下:

rm -rf $NGX_AUTOTEST*

3.6、其它与auto/feature具有类似功能的脚本文件

3.6.1、auto/types/sizeof脚本文件

该文件与auto/feature文件类似,也是通过生成测试文件来进行操作的,不同的是auto/types/sizeof是测试当前系统是32位还是64位的。该文件在auto/unix文件中被调用。

3.6.2、auto/types/typedef脚本文件

该文件的作用是检查某个类型名是否被占用,没被占用的话就使用它来作为其它某个类型的别名(使用typedef),然后输出到$NGX_AUTO_CONFIG_H文件中。该文件在auto/unix文件中被调用。

3.6.3、auto/types/uintptr_t脚本文件

该文件的作用是检查系统是否已经定义了uintptr_t类型,有定义的话就不做任何动作,没定义的话就自己定义一个改类型,然后输出到$NGX_AUTO_CONFIG_H文件中。该文件在auto/unix文件中被调用。

3.6.4、auto/types/value脚本文件

该文件在auto/unix文件中被调用的,比较简单,就不具体分析了。
代码如下:

cat << END >> $NGX_AUTO_CONFIG_H

#ifndef $ngx_param
#define $ngx_param  $ngx_value
#endif

END

4、总结

本文主要介绍了一系列工具脚本的内容,它们有如下特点:

  • auto/haveauto/nohaveauto/defineauto/have_headersauto/types/value这五个脚本的作用都是往头文件里面写入宏,它们会被其它脚本多次复用,属于通用类型的脚本。
  • auto/featureauto/types/sizeofauto/types/typedefauto/types/uintptr_t这四个脚本属于功能性测试脚本,用于测试当前系统环境是否支持某一操作,不支持的话就会有对应的动作,它们也会被其它脚本复用。

以上是关于Nginx编译配置脚本篇- 工具型脚本系列的主要内容,如果未能解决你的问题,请参考以下文章

Nginx编译配置脚本最终篇 - configure脚本

Nginx配置编译脚本篇- 解析配置选项脚本auto/options

Nginx编译配置脚本篇- 动态库配置脚本auto/lib/conf

Nginx编译配置脚本篇- 系统环境相关脚本

Nginx编译配置脚本篇(10)- Makefile相关脚本

Nginx编译配置脚本篇- 模块配置脚本auto/modules