Nginx 在 Windows 平台上编译

「爱情、让人受尽委屈。」 2022-03-02 13:26 803阅读 0赞

在Windows平台上编译Nginx遇到一些问题, 最终都逐个解决了, 记录一下过程.

打开网址

http://nginx.org/en/download.html

其中 nginx/Windows-1.10.1 是直接下载编译好的Windows版本的二进制程序
而要下载源码需要使用 Mercurial 去 clone, 源代码地址是
http://hg.nginx.org/nginx

Mercurial 是一个源代码管理工具, 与 SVN 类似
他有Windows的版本, 在Windows环境下也能使用, 但是官网貌似打不开
https://www.mercurial-scm.org/
但可以在别的地方下载到它 如:
http://www.onlinedown.net/soft/87736.htm
版本不一定最新, 但是能用
安装过程很简单, 为了方便起见, 可以允许将它的安装目录添加到Windows的环境变量PATH中

打开命令行, cd 到某个目录(用来存放和编译Nginx源码的位置), 执行

hg clone http://hg.nginx.org/nginx
开始下载源码, 看网速可能需要好几分钟

下面需要下载Nginx依赖的三个库, 分别是 PCRE, zlib 和 OpenSSL (非必须)
Nginx 1.10.1 对应的第三方库的版本分别是

pcre-8.39.tar.gz
zlib-1.2.8.tar.gz
openssl-1.0.2h.tar.gz
基本上都能从sourceforge上获取, 或直接用搜索引擎去找download

然后需要在Nginx源码根目录下创建 “objs” 和 “objs/lib” 两级目录, 将以上三个库解压到 objs/lib 下
注: 这三个第三方库实际上也是源码形式, 并没有lib或dll, 都需要一起编译

然后需要执行配置, 命令是

auto/configure —with-cc=cl —builddir=objs —prefix= \
--conf-path=conf/nginx.conf —pid-path=logs/nginx.pid \
--http-log-path=logs/access.log —error-log-path=logs/error.log \
--sbin-path=nginx.exe —http-client-body-temp-path=temp/client_body_temp \
--http-proxy-temp-path=temp/proxy_temp \
--http-fastcgi-temp-path=temp/fastcgi_temp \
--with-cc-opt=-DFD_SETSIZE=1024 —with-pcre=objs/lib/pcre-8.39 \
--with-zlib=objs/lib/zlib-1.2.8 —with-openssl=objs/lib/openssl-1.0.2h \
--with-select_module —with-http_ssl_module —with-ipv6

但这个命令是无法直接在 Windows 命令行中执行的, 需要一个Linux环境, 方法便是使用 MinGW, 里面有一个MSYS 的工具, 类似 Linux 中的 bash
打开网站
http://www.mingw.org/wiki/MSYS
下载 MinGW 的 Installer, 注意: 这只是一个安装器

其他下载地址
最终下载下来的文件是 mingw-get-setup.exe, 很小不到 1MB, 双击安装

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNzU2OTA0OA_size_16_color_FFFFFF_t_70
需要注意的是, 安装路径可以修改, 但路径中不能有空格(中文应该也不行, 没试过)

真正的安装过程也不快,需要在线下载很多东西
安装完成, 点击 Continue 会直接打开一个管理界面

Basic Setup设置
å¨è¿éæå¥å¾çæè¿°
接下来勾选上 Basic Setup 里的 msys-base, 然后 Apply Changes, 开始安装msys
这个过程也不快, 需要等几分钟

打开msys的安装目录, 启动msys.bat, 类似Linux环境, 默认目录为home/username, 貌似不能访问到 “/” 根目录之外的地方(没有研究), 简单的方式是将Nginx的源代码目录整个拷贝到用户目录下
然后执行 auto/Configure …… 创建Makefile文件

Makefile 文件会生成到 nginx\objs 目录下
然后就不需要MSYS了

在正式编译前可以安装一下sed这个工具, sed 下载地址因为编译完后, 脚本会调用它生成一个nginx.8的文件(具体什么用没搞清楚), 需要将sed.exe的目录加到环境变量PATH中

还需要安装Perl, 可以从
http://www.activestate.com/activeperl
下载, 并允许将安装路径加入到环境变量PATH中

下面启动 Visual Studio 工具命令提示, 我用的版本是 Visual Studio 2015
cd 到 Nginx 源代码目录, 执行 nmake -f objs/Makefile 开始编译

但会发现编译错误

  1. ml /nologo /Cp /coff /c /Cx /Zi /Fotmp32\\sha1-586.obj tmp32\\sha1-586.asm

Assembling: tmp32\sha1-586.asm
tmp32\sha1-586.asm(1432) : error A2070:invalid instruction operands
tmp32\sha1-586.asm(1576) : error A2070:invalid instruction operands
NMAKE : fatal error U1077: “”D:\Program Files (x86)\Microsoft Visual Studio 14.
0\VC\BIN\ml.EXE””: 返回代码“0x1”
Stop.
NMAKE : fatal error U1077: “”D:\Program Files (x86)\Microsoft Visual Studio 14.
0\VC\BIN\nmake.exe””: 返回代码“0x2”
Stop.
NMAKE : fatal error U1077: “”D:\Program Files (x86)\Microsoft Visual Studio 14.
0\VC\BIN\nmake.exe””: 返回代码“0x2”
Stop.
其实是在编译OpenSSL时报错, 具体报错的语句是

tmp32\sha1-586.asm line:1432 movd xmm1,XMMWORD PTR 16[edi]
tmp32\sha1-586.asm line:1576 movd XMMWORD PTR 16[edi],xmm1

整个文件就两个地方用到了 movd 指令, 而且都报错了
movd 是一条SSE指令, 作用是将源存储器32位内容送入目的寄存器的低32位,高96位清零
而 XMMWORD PTR 是指向 128 位的数据,
参考 MSDN
https://msdn.microsoft.com/zh-cn/library/cw0399sf(v=vs.140).aspx

这里要编译通过要么将 XMMWORD 改为 DWORD, 或将指令改为movdqa
尝试改完后发现又报出了其他的很多指令语法错误

看来有可能不是能简单修改代码的问题
查看了一下Openssl的开发者网站, 有对应问题的描述
http://mailing.openssl.dev.narkive.com/f9PT0DaI/openssl-dev-openssl-org-3650-sha1-586-asm-broken-in-1-0-2-stable-for-windows-builds

要解决这个问题可以在Windows平台上使用nasm, 而不使用微软的masm
下载 nasm for Windows
http://www.nasm.us/pub/nasm/releasebuilds/2.12.02rc9/win64/nasm-2.12.02rc9-installer-x64.exe

安装完成后需要 手动将安装目录加到环境变量PATH中, 并需要重启一个VS命令行窗口(需要重新加载环境变量)

然后需要修改 nginx\auto\lib\openssl\makefile.msvc 文件将

ms\do_ms 改为 ms\do_nasm
此时最好将上次编译的目录临时目录 “nginx\objs\lib\openssl-1.0.2h\tmp32” 和 输出目录 “nginx\objs\lib\openssl-1.0.2h\out32” 清空一下
符: 关于 OpenSSL 的编译可以 阅读 nginx\objs\lib\openssl-1.0.2h\INSTALL.W32 这个说明文件
注: Nginx 需要编译的是 OpenSSL 的静态库, 所以 nginx\auto\lib\openssl\makefile.msvc 中使用的是

$(MAKE) -f ms\nt.mak
而不是$(MAKE) -f ms\ntdll.mak

最后回到 Nginx 源码的根目录, 再次执行 nmake -f objs/Makefile
编译成功!

补充1: 关于执行 auto/Configure … 有报错提示的问题
提示为:

auto/cc/msvc: line 117: [: : integer expression expected
1
原因是: 在脚本文件 nginx\auto\cc\msvc 中变量 NGX_MSVC_VER 的值计算有误
具体代码是

NGX_MSVC_VER=`$NGX_WINE $CC 2>&1 | grep ‘Compiler Version’ 2>&1 \
| sed -e ‘s/^.* Version \(.*\)/\1/‘`
echo “ + cl version: $NGX_MSVC_VER”
貌似是根据 $CC 也就是 cl.exe 命令执行后的输出 用正则匹配出编译器的版本号, 另外在后面

# MSVC 2005 supports C99 variadic macros
if [ “$ngx_msvc_ver” -ge 14 ]; then
have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have
fi

用到了变量NGX_MSVC_VER, 用于比较这个值是否大于等于14, 而提示报错的也就是这一句话
由于对Configure的写法不是很了解(初步猜想是因为我用得是中文版本的原因), 可以简单的根据自己的Visual Studio的版本, 直接设定这个值, 参考

# MSVC 6.0 SP2 cl 12.00
# MSVC Toolkit 2003 (7.1) cl 13.10
# MSVC 2005 Express Edition SP1 (8.0) cl 14.00
# MSVC 2008 Express Edition (9.0) cl 15.00
# MSVC 2010 (10.0) cl 16.00
# MSVC 2015 (14.0) cl 19.00

我编译时用的是 Visual Studio 2015, 于是将代码改为

NGX_MSVC_VER=`$NGX_WINE $CC 2>&1 | grep ‘Compiler Version’ 2>&1 \
| sed -e ‘s/^.* Version \(.*\)/\1/‘`
NGX_MSVC_VER=19.00
echo “ + cl version: $NGX_MSVC_VER”

然后重新在msys中执行 auto/Configure …
成功执行没有报错

发表评论

表情:
评论列表 (有 0 条评论,803人围观)

还没有评论,来说两句吧...

相关阅读

    相关 VLC编译Windows 平台

            VLC2.0版本是最近的,比VLC2.0.1版本更稳定,所以打算下载VLC2.0,并在WINDOWS上成功编译。编译过程花啦近两个小时,终于成功!! 1,准备