檢視原始碼 在 Windows 上建置 Erlang/OTP

簡介

本節說明如何在 Windows 上建置 Erlang 模擬器和 OTP 程式庫。請注意,如果沒有 Microsoft 的開發工具,或不想安裝 WSL,Windows 二進位版本仍然是較佳的選擇。您可以從 https://erlang.dev.org.tw/downloads 下載二進位版本。

這些說明適用於支援 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_27.exe

如果您熟悉環境和建置系統,並且擁有所有必要的工具,那麼您就有很好的機會讓 Windows 版的 Erlang/OTP 發行版本變得更好。請將任何建議或修補程式提交到我們的 git 專案,讓它們納入 Erlang 的下一個版本中。如果對建置系統(如 makefiles 等)進行變更,請記住,相同的 makefiles 也用於 Unix,因此您的變更不會破壞其他平台。當然,C 程式碼也是如此;系統特定的程式碼主要位於 $ERL_TOP/erts/emulator/sys/win32$ERL_TOP/erts/etc/win32 目錄中。$ERL_TOP/erts/emulator/beam 目錄則用於通用程式碼。

簡短版本

在以下各節中,我們盡可能詳細地說明了所需工具的安裝。一旦安裝了這些工具,建置就相當容易了。我們也嘗試讓這些說明對 Unix 經驗有限的人們也能理解。對於某些 Windows 使用者來說,WSL 是一個全新的環境,因此仔細說明環境變數等似乎是適當的。

對於有經驗且沒有耐心的人來說,以下是簡短說明

  • 取得並安裝完整的 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 或更新版本(已測試最高至該版本可正常運作),並使用靜態程式庫。

  • 取得 Erlang 原始碼發行版本(從 https://erlang.dev.org.tw/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_27 變更為 otp_win32_27

    $ 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_27 /S
    

瞧!開始->程式集->Erlang OTP 27->Erlang 會啟動 Erlang Windows shell。

您需要的工具及其環境

您需要一些工具才能在 Windows 上建置 Erlang/OTP。最值得注意的是,您需要 WSL (搭配 ubuntu)、Visual Studio 和 Microsoft 的 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 尚未推出,且由於 (目前) WSL-2 存取 Windows 磁碟的速度較慢,因此在建置 Erlang/OTP 時可能不是首選。

  • 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(選用)您需要此程式庫來建置 crypto、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

    如果 c:/opt/local64/pgm/wxWidgets-3.2.2.1/include/wx/msw/setup.h 中未啟用 wxUSE_POSTSCRIPT,請啟用它。

    我們建議為 wxWebView 啟用 wxUSE_WEBVIEW_EDGE。

    • 下載 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 中啟用 wxUSE_WEBVIEW_EDGE

    使用以下命令建置

    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.dev.org.tw/download.html)。與 Unix 平台相同。最好使用 tar 來解壓縮原始碼 tar.gz (tar zxf otp_src_27.tar.gz) 到 Windows 磁碟上的某個位置,/mnt/c/path/to/otp_src

    注意:原始碼必須在 Windows 磁碟上,這一點很重要。

    將環境變數 ERL_TOP 設定為指向原始碼發行版本的根目錄。假設我停留在 /mnt/c/src 中,並解壓縮了 otp_src_27.tar.gz,然後我將以下內容新增到 .profile

    ERL_TOP=/mnt/c/src/otp_src_27
    export ERL_TOP

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_TARGETCCCXXARRANLIB 會設定為各自的包裝函式,並且會將目錄 $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 編譯器的使用訊息。

透過 erts/etc/win32/wsl_tools/SetupWSLcross.batotp_build 內部設定所需的編譯器環境變數。它包含一些硬式編碼的路徑,如果您的安裝路徑不同,則可以將其新增到該檔案中。

建置和安裝

使用 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

現在,在 <安裝目錄> 中,也就是 $ERL_TOP/release/win32 中,會有一個名為 otp_win32_27.exeotp_win64_27.exe 的檔案。

讓我們更詳細地探討

  1. $ ./otp_build configure - 這會使用新產生的 configure 指令碼執行,並帶有使 configure 正常運作的選項。目標機器類型是純粹的 win32,因此許多 configure 指令碼會辨識這個奇怪的目標名稱並據此運作。CC 變數也會使編譯器成為 cc.sh,它會包裝 MSVC++,因此所有關於 C 編譯器的 configure 測試都會執行正確的編譯器。許多測試在 Windows 上是不需要的,但我們認為最好還是執行整個 configure。

  2. $ ./otp_build boot -a - 這會使用啟動目錄(隨原始碼一起提供,$ERL_TOP/bootstrap)來建置完整的 OTP 系統。完成此操作後,您可以在原始碼樹狀結構中執行 erl;只需輸入 $ERL_TOP/bin/erl,您就應該會有提示符號。

  3. $ ./otp_build release -a - 從原始碼樹狀結構建置商業發行版本樹狀結構。預設是將其放入 $ERL_TOP/release/win32 中。您可以提供任何目錄作為參數,但如果您也要建置自我解壓縮的安裝程式,則沒有太大的差別。

  4. $ ./otp_build installer_win32 - 建立自動解壓縮安裝程式執行檔。執行檔 otp_win32_27.exeotp_win64_27.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_27 /S
    ...
    

    $ cd $ERL_TOP
    $ release/win32/otp_win64_27 /S
    ...
    

    一段時間後,Erlang/OTP-27 將會安裝在 C:\Program Files\erl%ERTS-VSN%\ 中,選單中也會有捷徑等等。

開發

一旦系統建置完成,您可能想要變更它。在某些方便的目錄中擁有一個測試版本可能很有用,但您也可以從原始碼樹中執行 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 時,您應該會有一個除錯編譯的模擬器,如果您在 erlang shell 中執行

1> erlang:system_info(system_version).

您會看到。如果傳回的字串包含 [debug],則您已取得除錯編譯的模擬器。

若要修改 erlang 函式庫,您只需在特定的「應用程式」目錄中執行 make opt,例如

$ cd $ERL_TOP/lib/stdlib
$ make opt

甚至是原始碼目錄中...

$ cd $ERL_TOP/lib/stdlib/src
$ make opt

請注意,在執行此操作時,您應該在您的路徑中有一個新的 Erlang,最好是您在上一個步驟中建置的純 27 版本。您也可以在重新建置特定函式庫之前將 $ERL_TOP/bootstrap/bin 新增至您的 PATH。這會為您提供一個足夠好的 Erlang 系統來編譯任何 OTP erlang 程式碼。正確設定路徑有點棘手。您仍然需要在路徑中將 $ERL_TOP/erts/etc/win32/wsl_tools/vc$ERL_TOP/erts/etc/win32/wsl_tools 放置在實際模擬器之前。使用 bootstrap 編譯器的路徑的典型設定會是

$ 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,

這基本上是您開始使用所需的一切。

常見問題

  • 問:所以,現在我可以在 Windows 上使用 GCC 建置 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 hack 將產生的物件程式碼轉換為與 MS VC++ 相容的 coff。這是因為那個特定的檔案 beam_emu.c 從能夠使用 GCC labels-as-values 擴充功能中受益匪淺,這將模擬器效能提高了高達 50%。但不幸的是,這 (尚未) 表示所有 OTP 都可以使用 GCC 編譯。該特定原始碼不會執行任何系統特定的操作,並且實際上是為了配合在 Windows 上使用 GCC 編譯而改編的。

  • 問:所以現在某處有一個 MS VC++ 專案檔,我可以使用漂亮的 VC++ GUI 建置 OTP 了嗎?

    答:不,永遠不會。保持專案檔最新狀態,並從 VC++ GUI 中執行構成 OTP 建置的所有步驟的麻煩根本不值得,甚至可能不可能。Erlang/OTP 的 VC++ 專案檔永遠不會出現。

  • 問:那麼這一切是如何運作的呢?

    答:WSL/Ubuntu 是環境,它幾乎就像在 Windows 內部有一個虛擬的 Unix 機器。設定在給定某些參數的情況下,然後建立環境的 gnu-make 用於建置系統的 makefile。但是,大多數實際的編譯器等都不是 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 和其他工具呢?

    答:我們使用 WSL 1 和 Ubuntu 18.04。我們用於 27 的 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。