为了研究nginx源码,笔者想编译调试一下nginx源码,由于nginx是使用configure脚本方式生成Makefile来编译的,MinGW中理论上也是可以的,但是直接在MinGW中编译nginx源码会出现找不到PCRE库以及zlib库的问题:

在这里插入图片描述

在这里插入图片描述 实际上MinGW中是有安装这两个库的:

在这里插入图片描述 在这里插入图片描述

在Linux下如果安装了这两个库,在运行auto/configure时,是完全没问题的,能够正确找到这两个库: 在这里插入图片描述

笔者经过研究,发现在查找PCRE库以及zlib库的脚本中都只对非win32平台进行了检测,win32平台没做检测。可以参见目前最新稳定版本nginx 1.26的源码, PCRE配置以及 zlib配置

只需要把条件判定去掉即可。

1. PCRE配置

在这里插入图片描述

2. zlib配置

在这里插入图片描述

3. OpenSSL配置

在这里插入图片描述

3. libxslt配置

在这里插入图片描述

75行处添加:

 1if [ $ngx_found = no ]; then
 2
 3    # MinGW64
 4
 5    ngx_feature="libxslt in /mingw64"
 6    ngx_feature_path="/mingw64/include/libxml2"
 7    ngx_feature_libs="-L/opt/local/lib -lxml2 -lxslt"
 8
 9    . auto/feature
10fi

168行处添加:

 1if [ $ngx_found = no ]; then
 2
 3    # MinGW64
 4
 5    ngx_feature="libexslt in /mingw64"
 6    ngx_feature_path="/mingw64/include/libxml2"
 7    ngx_feature_libs="-lexslt"
 8
 9    . auto/feature
10fi

再运行:

1 auto/configure --prefix= --with-cc=clang

在这里插入图片描述

如果要启用https,需要添加参数:--with-http_ssl_module,如果要调试添加参数:--with-debug

在这里插入图片描述

生成好Makefile之后,就可以编译了:

1make -j8

可以使用VSCode进行调试,以下是笔者的launch.json

 1{
 2  // 使用 IntelliSense 了解相关属性。
 3  // 悬停以查看现有属性的描述。
 4  // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
 5  "version": "0.2.0",
 6  "configurations": [
 7    {
 8      "type": "lldb",
 9      "request": "launch",
10      "name": "(lldb) 启动",
11      "program": "${workspaceFolder}/objs/nginx.exe",
12      "args": [],
13      "cwd": "${workspaceFolder}",
14      "env": {
15        "PATH": "G:\\msys64\\mingw64\\bin"
16      }
17    },
18    {
19      "name": "(gdb) 启动",
20      "type": "cppdbg",
21      "request": "launch",
22      "program": "${workspaceFolder}/objs/nginx.exe",
23      "args": [],
24      "stopAtEntry": false,
25      "cwd": "${workspaceFolder}",
26      "environment": [],
27      "externalConsole": false,
28      "MIMode": "gdb",
29      "miDebuggerPath": "G:\\msys64\\mingw64\\bin\\gdb.exe",
30      "setupCommands": [
31        {
32          "description": "为 gdb 启用整齐打印",
33          "text": "-enable-pretty-printing",
34          "ignoreFailures": true
35        },
36        {
37          "description": "将反汇编风格设置为 Intel",
38          "text": "-gdb-set disassembly-flavor intel",
39          "ignoreFailures": true
40        }
41      ],
42      "windows": {
43        "environment": [
44          {
45            "name": "PATH",
46            "value": "G:\\msys64\\mingw64\\bin"
47          }
48        ]
49      }
50    }
51  ]
52}

需要注意的是,由于nginx默认是使用的多进程模式,如果直接调试,将无法调试工作进程的情况,为此需要在调试时改为单进程的运行方式,修改 nginx.c:1143为:

1ngx_conf_init_value(ccf->daemon, 0)
2ngx_conf_init_value(ccf->master, 0);

重新编译后,即可使用GDB或者LLDB调试了:

在这里插入图片描述

目前虽然可以调试了,但是看代码,是没有intellisense的,也就不能正常代码跳转。所以最好是改为能够使用CMake构建系统,这样就可以使用clangd分析代码,进行代码跳转了。笔者根据源码中的脚本,写了一份可以在MinGW以及ubuntu 22.04中使用的CMakeLists.txt

CMakeLists.txt

  1
  2cmake_minimum_required(VERSION 3.20)
  3
  4project(nginx)
  5
  6set(ShareModules
  7	--with-http_ssl_module
  8	--with-http_v2_module
  9	--with-http_realip_module
 10	--with-http_addition_module
 11	--with-http_xslt_module
 12	--with-http_geoip_module
 13	--with-http_dav_module
 14	--with-http_stub_status_module
 15	--with-http_image_filter_module
 16	--with-mail
 17	--with-mail_ssl_module
 18	--with-stream
 19	--with-stream_ssl_module
 20)
 21
 22if(MINGW)
 23execute_process(COMMAND sh auto/configure
 24	--prefix=
 25	--with-cc=clang
 26	--with-debug
 27	${ShareModules}
 28	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 29)
 30else()
 31execute_process(COMMAND auto/configure
 32	--with-cc=clang
 33	--with-debug
 34	${ShareModules}
 35
 36	--with-http_degradation_module
 37	--with-threads
 38	--with-file-aio
 39	--with-http_v3_module
 40	--with-google_perftools_module
 41	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 42)
 43endif()
 44
 45if(WIN32)
 46if(MSVC)
 47message(FATAL_ERROR "WIN32下不支持使用MSVC编译,仅支持MinGW或者Cygwin环境下使用gcc或者clang编译器编译")
 48endif()
 49endif()
 50
 51if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/objs/ngx_auto_config.h)
 52message(STATUS "不存在ngx_auto_config.h,需要先执行`auto/configure`脚本")
 53endif()
 54
 55if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/objs/ngx_auto_headers.h)
 56message(STATUS "ngx_auto_headers.h,需要先执行`auto/configure`脚本")
 57endif()
 58
 59if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/objs/ngx_modules.c)
 60message(STATUS "不存在ngx_modules.c,需要先执行`auto/configure`脚本")
 61endif()
 62
 63aux_source_directory(src/core SRC_LIST)
 64aux_source_directory(src/event SRC_LIST)
 65
 66aux_source_directory(src/http SRC_LIST)
 67aux_source_directory(src/http/v2 SRC_LIST)
 68aux_source_directory(src/http/modules SRC_LIST)
 69
 70aux_source_directory(src/mail SRC_LIST)
 71aux_source_directory(src/misc SRC_LIST)
 72aux_source_directory(src/stream SRC_LIST)
 73
 74if(WIN32)
 75aux_source_directory(src/os/win32 SRC_LIST)
 76else()
 77aux_source_directory(src/os/unix SRC_LIST)
 78endif()
 79
 80list(APPEND SRC_LIST objs/ngx_modules.c)
 81
 82if(WIN32)
 83list(APPEND SRC_LIST src/event/modules/ngx_win32_poll_module.c)
 84list(APPEND SRC_LIST src/event/modules/ngx_iocp_module.c)
 85list(APPEND SRC_LIST src/event/modules/ngx_win32_select_module.c)
 86
 87list(REMOVE_ITEM SRC_LIST src/core/ngx_bpf.c)
 88
 89# 不支持Windows
 90list(REMOVE_ITEM SRC_LIST src/core/ngx_thread_pool.c)
 91# 代码有错误
 92list(REMOVE_ITEM SRC_LIST src/os/win32/ngx_service.c)
 93# 代码有错误
 94list(REMOVE_ITEM SRC_LIST src/event/ngx_event_connectex.c)
 95
 96#MinGW没sbrk函数
 97list(REMOVE_ITEM SRC_LIST src/http/modules/ngx_http_degradation_module.c)
 98
 99elseif(LINUX)
100aux_source_directory(src/http/v3 SRC_LIST)
101aux_source_directory(src/event/quic SRC_LIST)
102list(APPEND SRC_LIST src/event/modules/ngx_epoll_module.c)
103
104list(REMOVE_ITEM SRC_LIST src/event/ngx_event_connectex.c)
105list(REMOVE_ITEM SRC_LIST src/event/ngx_event_acceptex.c)
106
107list(REMOVE_ITEM SRC_LIST src/os/unix/ngx_darwin_init.c)
108list(REMOVE_ITEM SRC_LIST src/os/unix/ngx_darwin_sendfile_chain.c)
109list(REMOVE_ITEM SRC_LIST src/os/unix/ngx_freebsd_init.c)
110list(REMOVE_ITEM SRC_LIST src/os/unix/ngx_freebsd_sendfile_chain.c)
111list(REMOVE_ITEM SRC_LIST src/os/unix/ngx_solaris_init.c)
112list(REMOVE_ITEM SRC_LIST src/os/unix/ngx_solaris_sendfilev_chain.c)
113list(REMOVE_ITEM SRC_LIST src/os/unix/ngx_file_aio_read.c)
114endif()
115
116add_executable(${PROJECT_NAME} ${SRC_LIST})
117
118include_directories(
119	src/core
120	src/event
121	src/event/modules
122	src/http
123	src/http/modules
124	src/http/v2
125	src/http/v3
126	src/event/quic
127	src/mail
128	src/stream
129	objs
130)
131
132if(WIN32)
133include_directories(src/os/win32)
134else()
135include_directories(src/os/unix)
136endif()
137
138find_package(LibXml2 REQUIRED)
139find_package(LibXslt REQUIRED)
140
141target_include_directories(${PROJECT_NAME} PUBLIC ${LIBXML2_INCLUDE_DIRS} ${LIBXSLT_INCLUDE_DIRS})
142if(WIN32)
143target_link_libraries(${PROJECT_NAME} PUBLIC advapi32 ws2_32)
144else()
145target_link_libraries(${PROJECT_NAME} PUBLIC crypt profiler)
146endif()
147target_link_libraries(${PROJECT_NAME} PUBLIC pcre crypto z pcre2-8 ssl gd GeoIP ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${LIBXSLT_EXSLT_LIBRARIES})

MinGW需要安装的一些库(不一定全,需要自行安装一些库):

1pacman -S mingw-w64-x86_64-geoip mingw-w64-x86_64-libgd

ubuntu也需要安装的一些库(不一定全,需要自行安装一些库):

1sudo apt install libxslt1-dev libxml2-dev libgeoip-dev libgd-dev libgoogle-perftools-dev

当然,也可以使用辅助工具bear或者compiledb来生成compile_commands.json

  • bear ubuntu下使用sudo apt install bear安装bear工具。

bear 3.0之前使用

1bear make

在3.0之后使用

1bear --make

就可以生成compile_commands.json

  • compiledb compiledb是一个使用python开发的工具,所以需要使用
1pip install compiledb

来安装。 直接使用:

1compiledb make

就可以生成compile_commands.json

bear目前在MinGW中还没有安装包,貌似也暂时不支持MinGW,所以需要在Linux下使用。而compiledb是只要有python环境即可。

如果对你有帮助,欢迎点赞收藏!