4 如何在 Windows 上构建 Erlang/OTP
目录
4.1 简介
本节介绍如何在 Windows 上构建 Erlang 模拟器和 OTP 库。请注意,如果您没有 Microsoft 的开发工具或不想安装 WSL,则 Windows 二进制发行版仍然是首选的替代方案。
这些说明适用于支持 WSL.1(Windows Subsystem for Linux v.1)并使用 Ubuntu 18.04 版本的 Windows 10(v.1809 及更高版本)。
所述过程使用 WSL 作为构建环境。您在 WSL 中运行 bash shell,并使用 gnu configure/make 等进行构建。但是,模拟器 C 源代码主要使用 Microsoft Visual C++™ 编译,生成本机 Windows 二进制文件。这与我们用于构建预构建二进制文件的过程相同。我们为什么使用 VC++ 而不是 gcc 在常见问题解答部分有更详细的解释。
这些说明适用于 32 位和 64 位 Windows。请注意,即使您构建了 64 位版本的 Erlang,大多数相关目录和文件仍然名为 win32。但是,仍然存在一些名为 win64 的情况。例如,64 位 Windows 版本的 Erlang 的安装文件为 otp_win64_26.exe。
如果您熟悉环境和构建系统,并拥有所有必要的工具,您将有机会改进 Windows 的 Erlang/OTP 发行版。请将任何建议或补丁提交到我们的 git 项目,让他们进入 Erlang 的下一个版本。如果您对构建系统(如 makefile 等)进行更改,请记住,相同的 makefile 在 Unix 上使用,因此您的更改不会破坏其他平台。当然,这也适用于 C 代码;特定于系统的代码主要位于 $ERL_TOP/erts/emulator/sys/win32 和 $ERL_TOP/erts/etc/win32 目录中。 $ERL_TOP/erts/emulator/beam 目录用于通用代码。
4.2 简短版本
在接下来的部分中,我们已经尽可能详细地描述了所需工具的安装。工具安装完成后,构建非常容易。我们还尝试使这些说明对那些 Unix 经验有限的人来说更容易理解。WSL 对于某些 Windows 用户来说是一个全新的环境,因此对环境变量等的仔细解释似乎很有必要。
但是,对于经验丰富和急切的人来说,这就是简短的故事
-
获取并安装完整的 WSL 环境
-
安装 Visual Studio 2019
-
获取并安装 windows JDK-8
-
获取并安装 windows NSIS 3.05 或更高版本(3.05 已尝试并可行)
-
获取、构建和安装 OpenSSL v1.1.1d 或更高版本(已尝试并可行,最高版本为 1.1.1d),并使用静态库。
-
获取、构建和安装 wxWidgets-3.2.2.1 或更高版本(已尝试并可行,最高版本为 3.2.2.1),并使用静态库。
-
获取 Erlang 源代码发行版(来自 https://erlang.ac.cn/download.html)并使用 tar 解压缩到 Windows 磁盘,例如:/mnt/c/src/
-
安装 mingw-gcc 和 make:sudo apt update && sudo apt install g++-mingw-w64 gcc-mingw-w64 make
-
$ cd UNPACK_DIR
-
修改 PATH 和其他环境变量,以便从 bash shell 中运行所有这些工具。仍然位于 $ERL_TOP 中,发出以下命令(对于 32 位 Windows,从第一行中删除 x64,并将最后一行中的 otp_win64_26 更改为 otp_win32_26)
$ eval `./otp_build env_win32 x64` $ ./otp_build configure $ ./otp_build boot -a $ ./otp_build release -a $ ./otp_build installer_win32 $ release/win32/otp_win64_26 /S
瞧! Start->Programs->Erlang OTP 26->Erlang 启动 Erlang Windows shell。
-
4.3 您需要的工具及其环境
您需要一些工具才能在 Windows 上构建 Erlang/OTP。最重要的是,您需要 WSL(带 ubuntu)、Visual Studio 和 Microsofts Windows SDK,但您可能还需要 Java 编译器、NSIS 安装系统、OpenSSL 和 wxWidgets。以下是有关不同工具的一些信息
-
WSL:在 Windows 10 中安装 WSL 和 Ubuntu https://docs.microsoft.com/en-us/windows/wsl/install-win10
我们已经使用并测试了 WSL-1,WSL-2 在构建 Erlang/OTP 时不可用,并且可能不被首选,因为对 Windows 磁盘的访问速度(目前)比 WSL-2 慢。
-
Visual Studio 2019 从以下位置下载并运行安装程序:http://visualstudio.microsoft.com/downloads 将 C++ 和 SDK 包安装到默认安装目录。
-
Java JDK 8 或更高版本(可选)如果您不关心 Java,您可以跳过此步骤。结果是 jinterface 不会被构建。
我们的 Java 代码(jinterface、ic)在 windows 上使用 JDK 8 进行测试。获取它并将其安装在 Windows 上,JRE 不够。
URL:http://www.oracle.com/java/technologies/javase-downloads.html
将 javac 添加到您的路径环境中,在我的情况下,这意味着
`PATH="/mnt/c/Program\ Files/Java/jdk1.8.0_241/bin:$PATH`
不需要 CLASSPATH 或任何其他内容。在 bash 提示符中键入 javac.exe,您应该会看到一个可用 Java 选项列表。
-
Nullsoft NSIS 安装系统(可选)您需要它来构建自安装包。
从以下位置下载并运行安装程序:URL:http://nsis.sourceforge.net/download
将 'makensis.exe' 添加到您的路径环境中
`PATH="/mnt/c/Program\ Files/NSIS/Bin:$PATH`
在 bash 提示符中键入 which makensis.exe,您应该会看到该程序的路径。
-
OpenSSL(可选)您需要它来构建加密、ssh 和 ssl 库。
我们推荐 v1.1.1d 或更高版本。这里提供了可供您直接下载和安装的预构建二进制文件:URL:http://wiki.openssl.org/index.php/Binaries
安装到 C:/OpenSSL-Win64(或 C:/OpenSSL-Win32)
-
wxWidgets(可选)您需要它来构建 wx,以便在调试器和观察器中使用 gui。
我们推荐 v3.2.2.1 或更高版本。解压缩到 c:/opt/local64/pgm/wxWidgets-3.2.2.1
如果 wxUSE_POSTSCRIPT 未在 c:/opt/local64/pgm/wxWidgets-3.2.2.1/include/wx/msw/setup.h 中启用,请启用它。
我们建议为 wxWebView 启用 wxUSEWEBVIEWEDGE。
- 下载 nuget 包 'Microsoft.Web.WebView2'(版本 0.9.488 或更高版本)
- 将包解压缩(它是一个 zip 归档文件)到 wxWidgets/3rdparty/webview2(解压缩后您应该拥有 3rdparty/webview2/build/native/include/WebView2.h 文件)
- 在 c:/opt/local64/pgm/wxWidgets-3.2.2.1/include/wx/msw/setup.h 中启用 wxUSEWEBVIEWEDGE
使用以下命令构建:
C:\...\> cd c:\opt\local64\pgm\wxWidgets-3.2.2.1\build\msw C:\...\> nmake TARGET_CPU=amd64 BUILD=release SHARED=0 DIR_SUFFIX_CPU= -f makefile.vc
对于 32 位构建,请删除 TARGET_CPU=amd64。
-
获取 Erlang 源代码发行版(来自 https://erlang.ac.cn/download.html)。与 Unix 平台相同。最好使用 tar 解压缩源 tar.gz(tar zxf otp_src_26.tar.gz)到 Windows 磁盘上的某个位置,/mnt/c/path/to/otp_src
注意:将源代码放在 Windows 磁盘上非常重要。
设置环境变量 ERL_TOP 指向源代码发行版的根目录。假设我在 /mnt/c/src 中解压缩了 otp_src_26.tar.gz,那么我会在 .profile 中添加以下内容
ERL_TOP=/mnt/c/src/otp_src_26 export ERL_TOP
4.4 Shell 环境
路径变量现在应该包含指向 javac.exe 和 makensis.exe 的 Windows 路径。
使用以下命令设置环境
$ export PATH $ cd /mnt/c/path/to/otp_src/ $ eval `./otp_build env_win32 x64`
这应该设置额外的环境变量。
这应该对环境进行最终调整,此后构建应该很容易。您可以运行 ./otp_build env_win32(不带 eval)只是为了看看它做了什么,以及看看它设置的环境是否正常。如果可能,路径将清除空格(使用 DOS 样式的短名称代替),变量 OVERRIDE_TARGET、CC、CXX、AR 和 RANLIB 将设置为它们各自的包装器,并且目录 $ERL_TOP/erts/etc/win32/wsl_tools/vc 和 $ERL_TOP/erts/etc/win32/wsl_tools 将首先添加到 PATH 中。
现在您可以通过在 shell 中键入 type erlc 来检查您拥有哪个 erlc。它应该位于 $ERL_TOP/erts/etc/win32/wsl_tools 中。
运行 cl.exe 应该会打印 Microsoft 编译器的使用信息。
所需的编译器环境变量在 otp_build 内部通过 erts/etc/win32/wsl_tools/SetupWSLcross.bat 设置。它包含一些硬编码的路径,如果您的安装路径不同,则可以将其添加到该文件中。
4.5 构建和安装
构建最简单的方法是使用 otp_build 脚本
$ ./otp_build configure <optional configure options> $ ./otp_build boot -a $ ./otp_build release -a <installation directory> $ ./otp_build installer_win32 <installation directory> # optional
现在您将在 <installation directory> 中获得一个名为 otp_win32_26.exe 或 otp_win64_26.exe 的文件,即 $ERL_TOP/release/win32。
让我们更详细地了解一下
-
$ ./otp_build configure - 这将运行新生成的配置脚本,这些脚本具有使配置行为良好的选项。目标机器类型很明显是 win32,因此许多配置脚本识别出这个笨拙的目标名称,并相应地进行操作。CC 变量也使编译器成为 cc.sh,它包装了 MSVC++,因此所有关于 C 编译器的配置测试都能够运行正确的编译器。许多测试在 Windows 上不需要,但我们认为最好运行整个配置。
-
$ ./otp_build boot -a - 这将使用引导目录(与源代码一起提供,$ERL_TOP/bootstrap)来构建完整的 OTP 系统。完成后,您可以在源代码树中运行 erl;只需键入 $ERL_TOP/bin/erl,您应该会看到提示符。
-
$ ./otp_build release -a - 从源代码树构建商业发行版树。默认情况下,它位于 $ERL_TOP/release/win32 中。您可以指定任何目录作为参数,但如果您要构建自解压缩安装程序,它实际上并不重要。
-
$ ./otp_build installer_win32 - 创建自解压安装程序可执行文件。 可执行文件 otp_win32_26.exe 或 otp_win64_26.exe 将被放置在之前步骤中创建的发布的顶层目录中。 如果没有指定发布目录,则发布预计已构建到 $ERL_TOP/release/win32,这也是安装程序可执行文件将被放置的地方。 如果您为发布指定了其他目录(例如 ./otp_build release -a /tmp/erl_release),则您需要在此处给出相同的参数(例如 ./otp_build installer_win32 /tmp/erl_release)。 您需要在路径中安装完整的 NSIS 安装程序和 makensis.exe,才能使此方法起作用。 创建安装程序后,您可以运行它以以常规方式安装 Erlang/OTP,只需运行可执行文件并按照安装向导中的步骤操作。 要在安装过程中获得所有默认设置,无需询问任何问题,您可以使用参数 /S(大写 S)运行可执行文件,如下所示:
$ cd $ERL_TOP $ release/win32/otp_win32_26 /S ...
或者
$ cd $ERL_TOP $ release/win32/otp_win64_26 /S ...
一段时间后,Erlang/OTP-26 将安装在 C:\Program Files\erl14.2.3\ 中,并在菜单中创建快捷方式等。
4.6 开发
构建系统后,您可能希望对其进行更改。 在某个不错的目录中拥有一个测试发布版可能很有用,但您也可以从源代码树中运行 Erlang。 目标 local_setup 使程序 $ERL_TOP/bin/erl.exe 可用,并且还使用源代码树中的所有 OTP 库。
如果您修改了模拟器,可以通过进入 $ERL_TOP/erts/emulator 并执行简单的操作来构建模拟器可执行文件:
$ make opt
请注意,在 Windows 上构建任何内容之前,您需要在特定 shell 中运行 (cd $ERL_TOP && eval `./otp_build env_win32`)。 在执行 make opt 后,您可以通过运行 $ERL_TOP/bin/erl 来测试您的结果。 如果您想将结果复制到发布目录(例如 /tmp/erl_release),您可以执行以下操作(仍然在 $ERL_TOP/erts/emulator 中):
$ make TESTROOT=/tmp/erl_release release
这将复制模拟器可执行文件。
要创建模拟器的调试版本,您需要重新编译 beam.dll(实际的运行时系统)和 erlexec.dll。 执行以下操作:
$ cd $ERL_TOP $ rm bin/win32/erlexec.dll $ cd erts/emulator $ make debug $ cd ../etc $ make debug
有时还需执行:
$ cd $ERL_TOP $ make local_setup
因此,现在当您运行 $ERL_TOP/erl.exe 时,您应该拥有一个调试编译的模拟器,如果您执行以下操作,您将看到这一点:
1> erlang:system_info(system_version).
在 erlang shell 中。 如果返回的字符串包含 [debug],则说明您获得了调试编译的模拟器。
要修改 erlang 库,只需在特定“应用程序”目录中执行 make opt,例如:
$ cd $ERL_TOP/lib/stdlib $ make opt
甚至在源代码目录中...
$ cd $ERL_TOP/lib/stdlib/src $ make opt
请注意,您在执行此操作时需要在路径中拥有一个新的 Erlang,最好是您在之前步骤中构建的简单的 26。 您也可以将 $ERL_TOP/bootstrap/bin 添加到您的 PATH 中,然后再重新构建特定库。 这将为您提供一个足够好的 Erlang 系统来编译任何 OTP erlang 代码。 正确设置路径有点棘手。 您仍然需要在路径中的实际模拟器之前设置 $ERL_TOP/erts/etc/win32/wsl_tools/vc 和 $ERL_TOP/erts/etc/win32/wsl_tools。 使用引导编译器设置路径的典型方法是:
$ export PATH=$ERL_TOP/erts/etc/win32/wsl_tools/vc\ :$ERL_TOP/erts/etc/win32/wsl_tools:$ERL_TOP/bootstrap/bin:$PATH
这样应该可以轻松地重新构建任何库...
如果您想将新构建的库(应用程序)复制到发布区域,您可以像使用模拟器一样进行操作:
$ cd $ERL_TOP/lib/stdlib $ make TESTROOT=/tmp/erlang_release release
请记住:
-
Windows 特定的 C 代码位于 $ERL_TOP/erts/emulator/sys/win32、$ERL_TOP/erts/emulator/drivers/win32 或 $ERL_TOP/erts/etc/win32 中。
-
Windows 特定的 erlang 代码应在运行时使用条件语句,并在运行时测试主机操作系统,所有平台应分发完全相同的 beam 文件! 因此,编写类似以下的代码:
case os:type() of {win32,_} -> do_windows_specific(); Other -> do_fallback_or_exit() end,
基本上,这就是您入门所需的一切。
4.7 常见问题解答
-
问:所以,我现在可以使用 GCC 在 Windows 上构建 Erlang 吗?
答:不,不幸的是不行。 您仍然需要使用 Microsoft 的 Visual C++。 一个 Bourne shell 脚本 (cc.sh) 封装了 Visual C++ 编译器,并在 WSL 环境中运行它。 所有其他构建 Erlang 所需的工具都是免费软件/开源软件,但 C 编译器除外。
-
问:那你为什么没有摆脱 VC++ 呢,你这个混蛋?
答:嗯,部分原因是因为它是一个好编译器——真的! 事实上,在 R11 的后期版本中,可以使用 mingw 而不是 visual C++ 来构建(您可能会在某些脚本和目录中看到该方法的残余部分)。 不幸的是,Windows 上 SMP 版本的开发破坏了 mingw 构建,我们选择专注于 VC++ 构建,因为 VC++ 版本的性能要好得多。 mingw 构建可能会回归,但只要 VC++ 提供更好的性能,商业构建就会是 VC++ 构建。
-
问:哈哈,我看到了,你用了 GCC,虽然你说没有!
答:好吧,我承认,其中一个文件是用 MinGW 的 GCC 编译的,然后使用一个小的 C 技巧将生成的代码转换为与 MS VC++ 兼容的 coff。 这是因为该特定文件 beam_emu.c 非常受益于使用 GCC 的标签作为值扩展,这使得模拟器性能提高了 50%。 不幸的是,这并不意味着(目前)所有 OTP 都可以使用 GCC 编译。 该特定源代码不执行任何系统特定的操作,实际上它适用于使用 GCC 在 Windows 上编译它的事实。
-
问:所以现在有一个 MS VC++ 项目文件,我可以使用漂亮的 VC++ GUI 构建 OTP 吗?
答:不,永远不会。 在 VC++ GUI 中维护项目文件并执行构成 OTP 构建的所有步骤的麻烦,根本不值得,甚至可能无法实现。 永远不会有用于 Erlang/OTP 的 VC++ 项目文件。
-
问:那么它究竟是如何工作的?
答:WSL/Ubuntu 是环境,就像您在 Windows 中拥有一个虚拟的 Unix 机器一样。 Configure,在给定某些参数的情况下,会创建 makefile,这些 makefile 由环境的 gnu-make 用于构建系统。 然而,大多数实际编译器等并不是 WSL 工具,因此我们编写了一些包装器(Bourne shell 脚本),它们位于 $ERL_TOP/etc/win32/wsl_tools 中。 它们都将 Unix 环境中常见的参数和开关转换为适合本机 Windows 工具的格式。 最值得注意的当然是路径,在 WSL 中,路径是类 Unix 路径,使用“正斜杠”(/)且没有驱动器号。 WSL 特定的命令 wslpath 用于 WSL 环境中的大多数路径转换。 幸运的是,大多数编译器接受正斜杠而不是反斜杠作为路径分隔符,但仍然必须使驱动器号等正确,尽管如此。 包装器脚本并不通用,例如,cc.sh 不会理解和转换所有可能的 gcc 选项,并将正确的选项传递给 cl.exe。 原则是,脚本功能强大到足以允许构建 Erlang/OTP,不多不少。 它们可能需要扩展才能适应 Erlang 开发过程中的变化,这也是我们将它们制作成 shell 脚本而不是 Perl 脚本的原因之一。 我们相信,这样做更容易理解和修改。
在 $ERL_TOP 中,有一个名为 otp_build 的脚本。 该脚本负责将所有正确参数传递给 configure/make,并帮助您设置正确的环境变量,以便在 WSL 下使用 Erlang 源代码。
-
问:我可以构建一个看起来与商业发行版完全相同的东西吗?
答:是的,我们使用完全相同的构建流程。
-
问:那么您使用哪个版本的 WSL 和其他工具?
答:我们使用 Ubuntu 18.04 的 WSL 1。 我们用于 26 的 GCC 版本为 7.3-win32。 我们使用的是 Visual studio 2019、Sun 的 JDK 1.8.0_241、NSIS 3.05、Win32 OpenSSL 1.1.1d 和 wxWidgets-3.1.3。