檢視原始碼 交叉編譯 Erlang/OTP
簡介
本文檔描述如何交叉編譯 Erlang/OTP-27。在嘗試交叉編譯 Erlang/OTP 之前,建議您閱讀完整文檔。但是,在閱讀本文檔之前,您應該閱讀建置與安裝 Erlang/OTP,其中描述了建置與安裝 Erlang/OTP 的一般方法。
在下面的文字中,$ERL_TOP
是 Erlang/OTP 原始碼樹的頂層目錄。
otp_build 與 configure/make 的比較
建置 Erlang/OTP 可以透過使用 $ERL_TOP/otp_build
腳本,或直接調用 $ERL_TOP/configure
和 make
來完成。使用 otp_build
進行建置比較容易,因為它涉及的步驟較少,但是 otp_build
的建置程序不如 configure
/make
的建置程序靈活。請注意,otp_build configure
將產生與 configure
預設產生不同的預設配置。例如,目前除非明確傳遞 --enable-dynamic-ssl-lib
,否則 --disable-dynamic-ssl-lib
會新增至 configure
的命令列引數。 otp_build configure
使用的預設值可能隨時變更,恕不另行通知。
交叉配置
$ERL_TOP/xcomp/erl-xcomp.conf.template
檔案包含所有可用的交叉配置變數,並且可以在建立交叉編譯配置時用作範本。所有目前使用的配置變數也都列在本文件末尾。如需了解可運作的交叉配置範例,請參閱 $ERL_TOP/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf
檔案和 $ERL_TOP/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf
檔案。如果變數的預設行為令人滿意,則不需要設定該變數。但是,當使用預設值時,configure
腳本會發出警告。設定變數後,將不會發出警告。
可以使用 --xcomp-conf
命令列引數將交叉配置檔案傳遞給 otp_build configure
。請注意,configure
不接受此命令列引數。直接使用 configure
腳本時,請使用 <VARIABLE>=<VALUE>
語法將配置變數作為引數傳遞給 configure
。也可以將變數作為環境變數傳遞給 configure
。但是,如果您在環境中傳遞配置,請務必在調用 make
之前取消設定所有這些環境變數;否則,環境變數可能會在某些應用程式或某些應用程式的部分中設定 make 變數,並且您可能會以錯誤配置的建置結束。
可以交叉編譯的內容?
除了 wx
應用程式之外,可以交叉編譯所有 Erlang/OTP 應用程式。交叉編譯時,wx
驅動程式的建置目前將會自動停用。
相容性
建置系統(包括使用的交叉編譯配置變數)可能會在沒有事先通知的情況下進行不向後相容的變更。目前的交叉建置系統已在交叉編譯一些 Linux/GNU 系統時進行測試,但僅在其他平台上進行了部分測試。
修補程式
請以與此系統一致的方式提交任何用於交叉編譯的修補程式。歡迎所有意見,因為我們只有非常有限的交叉編譯環境可以進行測試。如果需要新的配置變數,請將其新增至 $ERL_TOP/xcomp/erl-xcomp.conf.template
,並在 configure.in
中使用它。可能需要更新的其他檔案為
$ERL_TOP/xcomp/erl-xcomp-vars.sh
$ERL_TOP/erl-build-tool-vars.sh
$ERL_TOP/erts/aclocal.m4
$ERL_TOP/xcomp/README.md
$ERL_TOP/xcomp/erl-xcomp-*.conf
請注意,這可能是不完整的需要更新的檔案清單。
有關如何提交修補程式的一般資訊,請參閱:http://wiki.github.com/erlang/otp/submitting-patches
建置與安裝程序
我們將首先介紹人們可能最熟悉的 configure
/make
建置程序。
直接使用 configure/make 進行建置
將目錄變更為 Erlang/OTP 原始碼樹的頂層目錄。
$ cd $ERL_TOP
為了編譯 Erlang 程式碼,必須建置一個小的 Erlang 啟動系統,或者必須在 $PATH
中提供與正在建置的版本相同的 Erlang/OTP 系統。將使用此 Erlang 系統以及提供的交叉編譯工具來建置目標系統的 Erlang/OTP。
如果您想使用 $PATH
中相容的 Erlang/OTP 系統進行建置,請跳至交叉建置系統。
建置啟動系統
$ ./configure --enable-bootstrap-only
$ make
對於 configure
而言,--enable-bootstrap-only
引數並非絕對必要,但可以加快速度。它只會在啟動所需的應用程式中執行 configure
,並會停用啟動系統不需要的許多項目。如果您在沒有 --enable-boostrap-only
的情況下執行 configure
,也必須將 make 作為 make bootstrap
執行;否則,將會建置整個系統。
交叉建置系統
$ ./configure --host=<HOST> --build=<BUILD> [Other Config Args]
$ make
<HOST>
是您為其建置的主機/目標系統。它不必是完整的 CPU-VENDOR-OS
三元組,但可以是。完整的標準化 CPU-VENDOR-OS
三元組將透過執行 $ERL_TOP/make/autoconf/config.sub <HOST>
來建立。如果 config.sub
失敗,您需要更明確。
<BUILD>
應等於您在其上進行建置之系統的 CPU-VENDOR-OS
三元組。如果您執行 $ERL_TOP/make/autoconf/config.guess
,在大多數情況下,它會列印您想用於此的三元組。
使用不同的 <HOST>
和 <BUILD>
值將會觸發交叉編譯。請注意,如果 <HOST>
和 <BUILD>
不同,則 <HOST>
和 <BUILD>
的標準化值也必須不同。如果它們不同,則配置將會失敗。
使用 <VARIABLE>=<VALUE>
語法將交叉編譯變數作為命令列引數傳遞給 configure
。
注意
當您直接調用
configure
時,不能 使用--xcomp-conf
引數傳遞配置檔案。--xcomp-conf
引數只能傳遞給otp_build configure
。
make
將會驗證建置時使用的 Erlang/OTP 系統是否與正在建置的系統版本相同,如果不是,則會失敗。但是,即使使用錯誤的 Erlang/OTP 系統,也可以強制進行交叉編譯,但不建議這樣做。透過這樣調用 make
來執行此操作:make ERL_XCOMP_FORCE_DIFFERENT_OTP=yes
。
警告
調用
make ERL_XCOMP_FORCE_DIFFERENT_OTP=yes
可能會失敗、靜默產生次佳程式碼,或靜默產生錯誤程式碼。
安裝
您可以使用使用 configure 確定的路徑進行安裝,或手動安裝。
使用 configure 確定的路徑進行安裝
$ make install DESTDIR=<TEMPORARY_PREFIX>
make install
會安裝在執行 configure
時指定的位置。指定安裝位置的 configure
引數例如:--prefix
、--exec-prefix
、--libdir
、--bindir
等。預設情況下,它將安裝在 /usr/local
下。您通常不希望在建置機上的 /usr/local
下安裝交叉建置。使用 DESTDIR 會導致安裝路徑以 $DESTDIR
作為字首。這樣就可以在建置機上安裝和封裝安裝,而不必將安裝放在建置機上與目標機上應執行安裝的相同目錄中。
當 make install
完成時,請將目錄變更為 $DESTDIR
,封裝系統,將其移動到目標機器,然後解壓縮。請注意,安裝只會在由 configure
確定的位置的目標機器上運作。
手動安裝
$ make release RELEASE_ROOT=<RELEASE_DIR>
make release
會將您為目標機器建置的內容複製到 <RELEASE_DIR>
。Install
腳本不會執行。 <RELEASE_DIR>
的內容預設會出現在 /usr/local/lib/erlang
中。
安裝 Erlang/OTP 時使用的 Install
腳本要求 $PATH
中存在常見的 Unix 工具,例如 sed
。如果您的目標系統沒有這些工具,您需要在封裝 Erlang/OTP 之前在建置機上執行 Install
腳本。Install
腳本目前應在它所在的目錄(頂層目錄)中按如下方式調用
$ ./Install [-cross] [-minimal|-sasl] <ERL_ROOT>
其中
-
-minimal
建立一個安裝,它會啟動最少的應用程式,也就是只會啟動kernel
和stdlib
。最小系統通常足夠,並且是make install
使用的系統。 -
-sasl
建立一個也會啟動sasl
應用程式的安裝。 -
-cross
用於交叉編譯。告知安裝腳本它是在建置機上執行的。 -
<ERL_ROOT>
- 執行時要使用的 Erlang 安裝的絕對路徑。這通常與目前的工作目錄相同,但不必相同。它可以遵循檔案系統中到相同目錄的任何其他路徑。
如果既沒有將 -minimal
也沒有將 -sasl
作為引數傳遞,系統將提示您。
您現在可以執行
決定安裝應位於目標機器上的位置,在建置機器上執行
Install
指令碼,並打包已安裝的安裝程式。安裝程式只需在目標機器上的正確位置解壓縮即可。$ cd <RELEASE_DIR> $ ./Install -cross [-minimal|-sasl] <ABSOLUTE_INSTALL_DIR_ON_TARGET>
或者
將安裝程式打包在
<RELEASE_DIR>
中,將其放置在目標機器上的任何位置,並在目標機器上執行Install
指令碼。$ cd <ABSOLUTE_INSTALL_DIR_ON_TARGET> $ ./Install [-minimal|-sasl] <ABSOLUTE_INSTALL_DIR_ON_TARGET>
使用 otp_build 指令碼建置
$ cd $ERL_TOP
$ ./otp_build configure --xcomp-conf=<FILE> [Other Config Args]
或者
$ ./otp_build configure --host=<HOST> --build=<BUILD> [Other Config Args]
如果您的交叉編譯設定在檔案中,請使用 --xcomp-conf=<FILE>
命令列引數傳遞它。如果沒有,請使用 --host=<HOST>
、--build=<BUILD>
以及在命令列上使用 <VARIABLE>=<VALUE>
語法的組態變數(與 交叉建置系統 中相同)。請注意,<HOST>
和 <BUILD>
必須以某種方式傳遞;可以使用組態檔案中的 erl_xcomp_host=<HOST>
和 erl_xcomp_build=<BUILD>
,或者使用 --host=<HOST>
和 --build=<BUILD>
命令列引數。
otp_build configure
將會為建置機器上的引導系統和交叉主機系統進行設定。
$ ./otp_build boot -a
otp_build boot -a
會先為建置機器建置引導系統,然後執行系統的交叉建置。
$ ./otp_build release -a <RELEASE_DIR>
otp_build release -a
將執行與 [手動安裝] 中的 make release
相同的操作,之後您必須在主機或目標上執行 手動 ./Install。
建置和安裝文件
在系統完成交叉建置後,您可以像在本機建置系統後一樣建置和安裝文件。有關如何建置文件的資訊,請參閱如何建置文件的資訊章節於建置和安裝 Erlang/OTP 文件中。
測試交叉編譯的系統
Erlang 隨附的一些測試會使用本機程式碼進行測試。這表示當交叉編譯 Erlang 時,您也必須交叉編譯測試套件,才能在目標主機上執行測試。若要執行此操作,您必須先像往常一樣發布測試。
$ make release_tests
或者
$ ./otp_build tests
測試將發布到 $ERL_TOP/release/tests
中。發布測試後,您必須在建置機器上安裝測試。您會提供與 使用 otp_build 指令碼建置 中 ./otp_build
相同的 xcomp 檔案。
$ cd $ERL_TOP/release/tests/test_server/
$ $ERL_TOP/bootstrap/bin/erl -eval 'ts:install([{xcomp,"<FILE>"}])' -s ts compile_testcases -s init stop
編譯測試案例時,您應該會收到許多列印輸出。完成後,您應該將整個 $ERL_TOP/release/tests
資料夾複製到交叉主機系統。
然後前往交叉主機系統,並設定將 Erlang 安裝到您的 $PATH
中。然後前往先前為 $ERL_TOP/release/tests/test_server
的位置,並發出下列命令。
$ erl -s ts install -s ts run all_tests -s init stop
應該跳過設定,且所有測試都應順利通過。如需有關如何使用 ts 的詳細資訊,請執行 erl -s ts help -s init stop
。
目前使用的組態變數
請注意,您無法在交叉編譯組態檔案中定義任意變數。只有以下列出的變數才能保證在所有 configure
指令碼的整個執行過程中可見。其他變數需要在 configure
的引數中定義,或在環境中匯出。
僅適用於 otp_build 的變數
當使用 $ERL_TOP/otp_build configure
設定 Erlang/OTP 進行交叉編譯時,才會使用本節中的變數。
注意
如果您直接使用
configure
指令碼進行設定,這些變數目前沒有效果。
erl_xcomp_build
- 使用的建置系統。此值將作為--build=$erl_xcomp_build
引數傳遞至configure
指令碼。它不一定要是完整的CPU-廠商-OS
三元組,但也可以是。完整的CPU-廠商-OS
三元組將由$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build
建立。如果設定為guess
,則會使用$ERL_TOP/make/autoconf/config.guess
來猜測建置系統。erl_xcomp_host
- 要建置的交叉主機/目標系統。此值將作為--host=$erl_xcomp_host
引數傳遞至configure
指令碼。它不一定要是完整的CPU-廠商-OS
三元組,但也可以是。完整的CPU-廠商-OS
三元組將由$ERL_TOP/make/autoconf/config.sub $erl_xcomp_host
建立。erl_xcomp_configure_flags
- 要傳遞至configure
指令碼的額外設定旗標。
交叉編譯器和其他工具
如果交叉編譯工具的前綴為 <HOST>-
,您可能不需要設定這些變數(其中 <HOST>
是已作為 --host=<HOST>
引數傳遞至 configure
的內容)。否則,可以透過在命令列上作為引數傳遞給 configure
的變數、xcomp 檔案或環境變數來識別編譯器和其他工具。如需更多資訊,請參閱設定檔檢查的重要變數章節於建置和安裝 Erlang/OTP。
交叉系統根目錄位置
erl_xcomp_sysroot
- 交叉編譯環境的系統根目錄的絕對路徑。目前,crypto
、odbc
、ssh
和ssl
應用程式需要系統根目錄。如果未設定系統根目錄,將會跳過這些應用程式。系統根目錄也可能需要用於其他用途。如果發生這種情況且未設定系統根目錄,configure
將會失敗並要求您設定。erl_xcomp_isysroot
- 交叉編譯環境的包含檔的系統根目錄的絕對路徑。如果未設定,此值預設為$erl_xcomp_sysroot
,也就是說,只有在包含系統根目錄路徑與系統根目錄路徑不同時,才設定此值。
選用功能和錯誤測試
在交叉編譯時,無法(總是)自動完成這些測試。您通常不需要設定這些變數。
警告
錯誤地設定這些變數可能會導致難以偵測的執行階段錯誤。如果您需要變更這些值,請務必確保這些值正確。
注意
其中一些值將會覆寫
configure
執行的測試結果,而有些值則會在configure
確定無法找出結果時才會使用。
當使用預設值時,configure
指令碼會發出警告。當變數設定完成時,將不會發出警告。
erl_xcomp_after_morecore_hook
-yes|no
。預設為no
。如果為yes
,目標系統必須具有可正常運作的__after_morecore_hook
,可用於追蹤所使用malloc()
實作的核心記憶體使用量。目前僅供不支援的功能使用。erl_xcomp_bigendian
-yes|no
。無預設值。如果為yes
,目標系統必須為大端位元組順序。如果為no
,則為小端位元組順序。通常可以自動偵測到,但並非總是如此。如果未自動偵測到,除非設定此變數,否則configure
將會失敗。由於未使用預設值,configure
將會嘗試自動找出此值。erl_xcomp_double_middle
-yes|no
。預設為no
。如果為yes
,目標系統必須採用「中間位元組順序」格式的雙精度浮點數。如果為no
,則採用「一般」位元組順序。erl_xcomp_clock_gettime_cpu_time
-yes|no
。預設為no
。如果為yes
,目標系統必須具有可正常運作的clock_gettime()
實作,可用於擷取處理序 CPU 時間。erl_xcomp_getaddrinfo
-yes|no
。預設為no
。如果為yes
,目標系統必須具有可正常運作的getaddrinfo()
實作,可處理 IPv4 和 IPv6。erl_xcomp_gethrvtime_procfs_ioctl
-yes|no
。預設為no
。如果為yes
,目標系統必須具有可正常運作的gethrvtime()
實作,並與 procfsioctl()
搭配使用。erl_xcomp_dlsym_brk_wrappers
-yes|no
。預設為no
。如果為yes
,目標系統必須具有可正常運作的dlsym(RTLD_NEXT, <S>)
實作,可用於malloc()
實作所使用的brk
和sbrk
符號,藉此追蹤malloc()
實作的核心記憶體使用量。目前僅供不支援的功能使用。erl_xcomp_kqueue
-yes|no
。預設為no
。如果為yes
,目標系統必須具有可正常運作的kqueue()
實作,會傳回可由poll()
和/或select()
使用的檔案描述子。如果為no
且目標系統沒有epoll()
或/dev/poll
,將會停用核心輪詢功能。erl_xcomp_linux_clock_gettime_correction
-yes|no
。預設在 Linux 上為yes
;否則為no
。如果為yes
,目標系統上的clock_gettime(CLOCK_MONOTONIC, _)
必須能正常運作。建議在核心版本低於 2.6 的 Linux 系統上將此變數設定為no
。erl_xcomp_linux_nptl
-yes|no
。預設在 Linux 上為yes
;否則為no
。如果為yes
,目標系統必須具有 NPTL (Native POSIX Thread Library)。較舊的 Linux 系統使用 LinuxThreads 而非 NPTL (Linux 核心版本通常低於 2.6)。erl_xcomp_linux_usable_sigaltstack
-yes|no
。預設在 Linux 上為yes
;否則為no
。如果為yes
,目標系統上必須可以使用sigaltstack()
。sigaltstack()
在 Linux 核心版本低於 2.4 時會損壞。erl_xcomp_linux_usable_sigusrx
-yes|no
。預設為yes
。如果為yes
,ERTS 必須可以使用SIGUSR1
和SIGUSR2
訊號。舊的 LinuxThreads 線程庫 (Linux 核心版本通常低於 2.2) 使用這些訊號,導致 ERTS 無法使用它們。erl_xcomp_poll
-yes|no
。預設在 Darwin/MacOSX 上為no
;否則為yes
。如果為yes
,目標系統必須具有可運作的poll()
實作,且該實作也能夠處理裝置。如果為no
,則將使用select()
來代替poll()
。erl_xcomp_putenv_copy
-yes|no
。預設為no
。如果為yes
,目標系統必須具有putenv()
實作,該實作會儲存鍵/值對的副本。erl_xcomp_reliable_fpe
-yes|no
。預設為no
。如果為yes
,目標系統必須具有可靠的浮點數例外處理。erl_xcomp_posix_memalign
-yes|no
。如果posix_memalign
系統呼叫存在,則預設為yes
;否則為no
。如果為yes
,目標系統必須具有posix_memalign
實作,該實作接受大於頁面大小的對齊。erl_xcomp_code_model_small
-yes|no
。預設為no
。如果為yes
,目標系統必須將 beam.smp 可執行檔放置在記憶體中較低的 2 GB 範圍內。也就是說,它不應該使用與位置無關的可執行檔。