在类 Unix 系统中将 Nginx 源码导入 CLion 并调试运行

零、写在最前面

0.1 关于系统

如标题所述,本文的操作需要一个类 Unix 系统(MacOS、CentOS、Ubuntu 等)。

同时这些类 Unix 系统还需要有 gcc 编译器。具体如何搞定这些编译器的内容不在本文范围内,忽略之。

0.2 关于版本

本文作者测试过的 Nginx 源码版本是 1.16.0 & 1.20.0 & 1.25.0,基本上认为在 [1.16.0 - 1.25.0] 之间的版本都是 OK 的,其他版本请注意区别。

作者学习 Nginx 源码的版本是 1.16.0,可以和这个版本保持一致。

一、背景

想要对 Nginx 源码进行深入学习并了解:

  • 架构是怎样的?
  • 多进程还是多线程?
  • 哪些高级数据结构?
  • 内存如何管理?
  • 配置文件如何解析,如何热加载?
  • Epoll 事件机制?
  • 负载均衡如何实现的,如何扩展?

但是 Nginx 源码是用 C 语言编写的,且默认使用 Makefile 来构建,不利于导入 CLion 和调试。

于是,需要想办法将其转换为 CMake 工程,这样用 CLion 调试和运行很方便。

二、获取 Nginx 源码

方式一(不太推荐):官网链接

注意下载合适的版本

方式二(推荐):Github 链接

下载后切换到合适的版本

三、生成 CMakeLists.txt

3.1 创建 bash 脚本文件 cmake

执行命令: cd /home/cyh/nginx (作者的 Nginx 根目录、后续都是这个目录)

执行命令: vim auto/cmake
cmake 文件的内容一共 46 行,具体如下:

复制代码
 1 #!/usr/bin/env bash
 2 NGX_CMAKE_FILE=CMakeLists.txt
 3 NGX_CMAKE_TMP=$NGX_OBJS/tmp
 4 
 5 #output includes
 6 cmake_ngx_incs=`echo $CORE_INCS $NGX_OBJS $HTTP_INCS $MAIL_INCS \
 7              sed -e "s/  *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
 8                    -e "s/\//$ngx_regex_dirsep/g"`
 9 cat << END                                  > $NGX_CMAKE_TMP
10 cmake_minimum_required(VERSION 3.6)
11 include_directories(
12     .
13     $cmake_ngx_incs)
14 END
15 
16 #output src
17 cmake_ngx_src="$CORE_SRCS $HTTP_SRCS $MAIL_SRCS $NGX_MISC_SRCS $NGX_ADDON_SRCS $NGX_SHARED_SRCS"
18 
19 cmake_ngx_src=`echo $cmake_ngx_src | sed -e "s/  *\([^ ][^ ]*\)/$ngx_regex_cont\1/g"\
20                              -e "s/\//$ngx_regex_dirsep/g"`
21 
22 cat << END                                    >> $NGX_CMAKE_TMP
23 set(SOURCE_FILES
24     $NGX_OBJS/ngx_modules.c
25     $cmake_ngx_src)
26 END
27 
28 #output target
29 cat << END                                   >> $NGX_CMAKE_TMP
30 add_executable(nginx \${SOURCE_FILES})
31 END
32 
33 
34 #output lib
35 echo ${CORE_LIBS}
36 CMAKE_CORE_LIBS=`echo ${CORE_LIBS} | sed -e "s/-l//g"`
37 
38 cat << END                                   >> $NGX_CMAKE_TMP
39 target_link_libraries(nginx $CMAKE_CORE_LIBS)
40 END
41 
42 if [ -f $NGX_CMAKE_TMP ]
43 then
44     (cat $NGX_CMAKE_TMP | sed -e "s/\\\//g") > $NGX_CMAKE_FILE
45     rm $NGX_CMAKE_TMP
46 fi

继续执行命令: vim auto/configure

在原来的 . auto/make 的前面,添加一行,内容是: . auto/cmake

如下图所示:

3.2 执行 configure 脚本生成 CMakeLists.txt 文件

执行命令: ./auto/configure --prefix="./" --without-http_rewrite_module --without-http_gzip_module

命令说明:

  1. 执行 auto/configure 这个脚本
  2. --prefix 指定前缀
  3. --without-http_rewrite_module 编译时不要 HTTP 重写模块(要的话,需要安装其他的依赖包,增加复杂度)
  4. --without-http_gzip_module 编译时不要 HTTP 压缩模块(要的话,需要安装其他的依赖包,增加复杂度)

命令执行成功的效果,如下图所示:

最终在 nginx 源码根目录会生成一个 CMakeLists.txt 文件。同时会生成 objs 目录以及里面的几个文件。

如下图所示:

3.3 用 CLion 打开这个 Nginx 工程

此步骤起提示作用,具体操作省略。

3.4 修改 CMakeLists.txt 文件

将 include_directories 指令进行修改,内容如下,否则 clion 会将 /root 目录也作为头文件的搜索路径,这是没有必要的。

复制代码
include_directories(
    .
    src/core src/event src/event/modules src/os/unix objs src/http src/http/modules)

注意查看生成的 CMakeLists.txt 文件的内容,如果缺少下图中的这一行的话,自行补充上去一下。

具体如图所示:

四、创建 nginx 运行时必要的目录和文件

CLion 这个编辑器,调试过程中的产物都位于 cmake-build-debug 目录下,因此需要在这个目录下创建相关文件。

方式一:执行如下的命令
**  mkdir -p cmake-build-debug/logs**
**  cp -fr conf cmake-build-debug/**
**  cp -fr html cmake-build-debug/**
方式二:鼠标右键操作
打开 CLion 后,直接通过鼠标拷贝,效果是一样的。

最终的想要效果,如下图所示:

五、修改 nginx 配置文件

方式一:执行如下的命令

vim cmake-build-debug/conf/nginx.conf
方式二:直接在 CLion 中编辑文件
不管那种方式,最终的目标是在文件开头新增如下两行内容,表示 nginx 处于前台运行并且是单进程模式工作。

复制代码
daemon off;
master_process off;

最终的效果如下:

六、clion 打开 nginx 源码进行调试

在 src/core/nginx.c 中找 main() 方法,右键点击运行或者调试。

运行成功后,打开浏览器输入 localhost 或者 locaolhost:80 就可以看到 Nginx 的那个标准首页了。

如图所示:

七、总结

使用 CLion 调试 nginx 需要依赖于 CMakeLists.txt 文件。
而 CMakeLists.txt 文件是通过 nginx 源码目录下的 auto/configure 脚本来生成。
有了 CMakeLists.txt 文件,只需要创建 nginx 运行时必须使用到的目录和文件,打开 clion 找到 main 方法点击调试即可。

八、我的 Nginx 源码

在这里

九、参考文档

clion本地调试nginx-1.22.1
使用 CLion debug 跟踪 nginx/OpenResty 源码

十、书籍推荐

|------------------------|------------|---------|----------------|----------|--------------------------------------|
| 书名 | 作者 | 版次 | Nginx 源码版本 | 推荐指数 | 其他信息 |
| 《Nginx 底层设计与源码分析》 | 聂松松,赵禹,施洪宝 | 2023.12 | 1.16.0 | 4星 | 版本较新,内容全面,难易适中 作为第一本学习 Nginx 的书籍 |
| 《深入理解 Nginx 模块开发与架构解析》 | 陶辉 | 2019.09 | 1.0.14 | 3星 | 书很好,但是版本比较老了,内容比较深 作为第二本学习 Nginx 的书籍 |
| 《Nginx 高性能Web服务开发详解》 | 苗泽 | 2013.10 | 1.2.3 | 2星 | 版本比较老,后续有空再来学习吧 |