在nginx调试过程中,会发现三个文件不是在源码包中的,而是根据具体平台自动生成,这三个文件分别是 ngx_modules.c ,ngx_auto_headers.h,ngx_auto_config.h。那么这三个文件是怎么自动生成的?生成的流程是怎样的?又是在什么地方调用的呢?本篇针对这些问题做个分析。
1.总控脚本configure
nginx-1.22.1/configure
- LC_ALL=C
- export LC_ALL
-
- . auto/options #该脚本生效全局变量,比如自动生成文件.h和.c名,模块是否安装控制开关
- . auto/init #不修改脚本auto/init权限,仍然可以执行脚本,需要root权限才可以
- . auto/sources #基本模块定义
- ...
- if test -z "$NGX_PLATFORM"; then
- echo "checking for OS"
-
- NGX_SYSTEM=`uname -s 2>/dev/null` #获取操作系统类型
- NGX_RELEASE=`uname -r 2>/dev/null` #获取操作系统版本
- NGX_MACHINE=`uname -m 2>/dev/null` #获取计算机CPU硬件架构
-
- echo " + $NGX_SYSTEM $NGX_RELEASE $NGX_MACHINE"
-
- NGX_PLATFORM="$NGX_SYSTEM:$NGX_RELEASE:$NGX_MACHINE";
-
- case "$NGX_SYSTEM" in
- MINGW32_* | MINGW64_* | MSYS_*)
- NGX_PLATFORM=win32
- ;;
- esac
-
- else
- echo "building for $NGX_PLATFORM"
- NGX_SYSTEM=$NGX_PLATFORM
- fi
- #调用编译器配置脚本
- ...
- . auto/cc/conf
- ...
- #调用操作系统配置脚本
- . auto/os/conf
- ...
2.初始化脚本中需要用到的全局变量
nginx-1.22.1/auto/init
- NGX_MAKEFILE=$NGX_OBJS/Makefile
- NGX_MODULES_C=$NGX_OBJS/ngx_modules.c
-
- NGX_AUTO_HEADERS_H=$NGX_OBJS/ngx_auto_headers.h #自动生成运行环境相关宏定义,例如操作系统宏开关
- NGX_AUTO_CONFIG_H=$NGX_OBJS/ngx_auto_config.h #操作系统属性相关宏开关,比如是否支持epoll,sendfile等系统函数调用
- ...
3.操作系统配置脚本
nginx-1.22.1/auto/os/conf
- case "$NGX_PLATFORM" in
-
- FreeBSD:*)
- . auto/os/freebsd
- ;;
-
- Linux:*)
- . auto/os/linux #执行linux系统脚本
- ;;
-
- SunOS:*)
- . auto/os/solaris
- ;;
-
- Darwin:*)
- . auto/os/darwin
- ;;
-
- win32)
- . auto/os/win32
- ;;
- ...
-
- *)
- CORE_INCS="$UNIX_INCS"
- CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
- CORE_SRCS="$UNIX_SRCS"
- ;;
-
- esac
4.自动生成头文件: ngx_auto_headers.h和ngx_auto_config.h
nginx-1.22.1/auto/os/linux
- ...
- have=NGX_LINUX . auto/have_headers #自动生成linux系统的头文件ngx_auto_headers.h
- ...
- . auto/feature #调用auto/have脚本和cat << END方法自动生成系统相关属性头文件ngx_auto_config.h
- ...
4.1 auto/have_headers脚本
nginx-1.22.1/auto/have_headers
- #脚本从变量NGX_AUTO_HEADERS_H获取值自动生成头文件ngx_auto_headers.h
- # Copyright (C) Igor Sysoev
- # Copyright (C) Nginx, Inc.
-
-
- cat << END >> $NGX_AUTO_HEADERS_H
- #ifndef $have
- #define $have 1
- #endif
- END
-
- #ngx_auto_headers.h文件样例
- ...
- #ifndef NGX_LINUX
- #define NGX_LINUX 1
- #endif
- ...
4.2 auto/have脚本,往ngx_auto_config.h中写入信息
nginx-1.22.1/auto/have
- # Copyright (C) Igor Sysoev
- # Copyright (C) Nginx, Inc.
-
-
- cat << END >> $NGX_AUTO_CONFIG_H
- #ifndef $have
- #define $have 1
- #endif
- END
-
- #ngx_auto_config.h文件样例
- nginx-1.22.1/objs/ngx_auto_config.h
- #define NGX_CONFIGURE " --prefix=/home/hesy/work/nginx-1.22.1/nginx/bin --with-http_ssl_module --with-stream --with-cc-opt='-O0 -g'"
-
- #ifndef NGX_COMPILER
- #define NGX_COMPILER "gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) "
- #endif
- ...
- #ifndef NGX_HAVE_EPOLL
- #define NGX_HAVE_EPOLL 1
- #endif
- ...
- #ifndef NGX_HAVE_SENDFILE
- #define NGX_HAVE_SENDFILE 1
- #endif
- ...
5.自动生成文件: ngx_modules.c
auto/init脚本中定义文件路径:NGX_MODULES_C=$NGX_OBJS/ngx_modules.c
根据. auto/options 和 . auto/sources脚本来确定相关模块名,存在全局变量中
. auto/modules(调用auto/module)脚本根据模块全局变量名来动态生成.c文件
. auto/options:该脚本可用来定义控制模块是否编译,是否是预定义
如下两个脚本负责往ngx_modules.c中写入数据
nginx-1.22.1/auto/modules
nginx-1.22.1/auto/modules
6.程序引用
6.1 nginx-1.22.1/src/core/ngx_config.h中引用ngx_auto_headers.h和
nginx-1.22.1/src/core/ngx_config.h
- #ifndef _NGX_CONFIG_H_INCLUDED_
- #define _NGX_CONFIG_H_INCLUDED_
-
-
- #include
- ...
- #elif (NGX_LINUX)
- #include
- ...
- #endif /* _NGX_CONFIG_H_INCLUDED_ */
6.2 nginx-1.22.1/src/os/unix/ngx_linux_config.h引用ngx_auto_config.h
nginx-1.22.1/src/os/unix/ngx_linux_config.h
- #ifndef _NGX_LINUX_CONFIG_H_INCLUDED_
- #define _NGX_LINUX_CONFIG_H_INCLUDED_
- ...
- #include
- ...
- #if (NGX_HAVE_EPOLL)
- #include
- #endif
-
- #endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */
nginx以模块的方式组织代码,使得代码编写和扩展相当灵活。而为了实现跨平台,其通过shell脚本检测本地系统,自动生成代码,这一套处理解决问题的思想值得IT同仁们在工作中借鉴。