檢視原始碼 在 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_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 編譯器的使用訊息。
透過 erts/etc/win32/wsl_tools/SetupWSLcross.bat
在 otp_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.exe
或 otp_win64_27.exe
的檔案。
讓我們更詳細地探討
$ ./otp_build configure
- 這會使用新產生的 configure 指令碼執行,並帶有使 configure 正常運作的選項。目標機器類型是純粹的win32
,因此許多 configure 指令碼會辨識這個奇怪的目標名稱並據此運作。CC 變數也會使編譯器成為cc.sh
,它會包裝 MSVC++,因此所有關於 C 編譯器的 configure 測試都會執行正確的編譯器。許多測試在 Windows 上是不需要的,但我們認為最好還是執行整個 configure。$ ./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_27.exe
或otp_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。