3 交叉编译 Erlang/OTP
目录
3.1 简介
本文档介绍如何交叉编译 Erlang/OTP-26。建议您在尝试交叉编译 Erlang/OTP 之前通读整篇文档。但是,在阅读本文档之前,您应该阅读 $ERL_TOP/HOWTO/INSTALL.md 文档,该文档介绍了 Erlang/OTP 的通用构建和安装过程。 $ERL_TOP 是源代码树的顶层目录。
otp_build 与 configure/make
构建 Erlang/OTP 可以通过使用 $ERL_TOP/otp_build 脚本,或直接调用 $ERL_TOP/configure 和 make 来完成。使用 otp_build 构建更简单,因为它涉及的步骤更少,但 otp_build 构建过程不如 configure/make 构建过程灵活。请注意,otp_build configure 将生成与 configure 默认生成的配置不同的默认配置。例如,目前 --disable-dynamic-ssl-lib 被添加到 configure 命令行参数中,除非明确传递了 --enable-dynamic-ssl-lib。我们交付的二进制发行版是使用 otp_build 构建的。 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
3.2 构建和安装过程
如果您在 Git 中构建,请在继续之前阅读 $ERL_TOP/HOWTO/INSTALL.md 中的 在 Git 中构建 部分。
我们将首先介绍 configure/make 构建过程,人们可能对此最熟悉。
直接使用 configure/make 构建
(1)
更改目录到 Erlang/OTP 源代码树的顶层目录。
$ cd $ERL_TOP
为了编译 Erlang 代码,必须构建一个小型 Erlang 引导系统,或者在 $PATH 中提供与正在构建的版本相同的 Erlang/OTP 系统。目标系统的 Erlang/OTP 将使用此 Erlang 系统以及提供的交叉编译工具构建。
如果您想使用 $PATH 中兼容的 Erlang/OTP 系统构建,请跳到 (3)。
构建引导系统
(2)
$ ./configure --enable-bootstrap-only $ make
--enable-bootstrap-only 参数传递给 configure 不是严格必要的,但会加快速度。它只会在引导系统所需的应用程序中运行 configure,并将禁用引导系统不需要的大量内容。如果您在不使用 --enable-boostrap-only 的情况下运行 configure,您还需要以 make bootstrap 的方式运行 make;否则,将构建整个系统。
交叉构建系统
(3)
$ ./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 确定的安装路径 (4) 安装,也可以手动使用 (5) 安装。
使用 configure 确定的路径安装
(4)
$ make install DESTDIR=<TEMPORARY_PREFIX>
make install 将安装在执行 configure 时指定的目录中。指定安装位置的 configure 参数例如:--prefix、--exec-prefix、--libdir、--bindir 等。默认情况下,它将安装到 /usr/local 下。您通常不希望将交叉构建安装到构建机器上的 /usr/local 下。使用 DESTDIR 将导致安装路径以 $DESTDIR 为前缀。这使得能够在构建机器上安装和打包安装,而无需将安装放在构建机器上与在目标机器上执行时相同的目录中。
当 make install 完成后,更改目录到 $DESTDIR,打包系统,将其移动到目标机器,并解包。请注意,安装将仅在目标机器上由 configure 确定的位置正常工作。
手动安装
(5)
$ make release RELEASE_ROOT=<RELEASE_DIR>
make release 将把您为目标机器构建的内容复制到 <RELEASE_DIR> 中。不会运行 Install 脚本。 <RELEASE_DIR> 的内容默认情况下会最终出现在 /usr/local/lib/erlang 中。
安装 Erlang/OTP 时使用的 Install 脚本需要 sed 等常见的 Unix 工具存在于您的 $PATH 中。如果您的目标系统没有此类工具,您需要在打包 Erlang/OTP 之前在构建机器上运行 Install 脚本。 Install 脚本目前应该在它所在的目录(顶层目录)中以以下方式调用
$ ./Install [-cross] [-minimal|-sasl] <ERL_ROOT>
其中
- -minimal 创建一个仅启动少量应用程序的安装,即仅启动 kernel 和 stdlib。最小系统通常就足够了,也是 make install 使用的系统。
- -sasl 创建一个还启动 sasl 应用程序的安装。
- -cross 用于交叉编译。通知安装脚本它是在构建机器上运行的。
- <ERL_ROOT> - 运行时使用的 Erlang 安装的绝对路径。这通常与当前工作目录相同,但不必相同。它可以遵循文件系统中到相同目录的任何其他路径。
如果既没有-minimal,也没有-sasl作为参数传递,您将被提示。
您现在可以:
(6)
-
决定安装应该位于目标机器上的哪个位置,在构建机器上运行Install脚本,然后打包安装的安装程序。安装程序只需要解压缩到目标机器上的正确位置。
$ cd <RELEASE_DIR> $ ./Install -cross [-minimal|-sasl] <ABSOLUTE_INSTALL_DIR_ON_TARGET>
或者
(7)
-
在<RELEASE_DIR>中打包安装程序,将其放置在目标机器上的任何位置,然后在目标机器上运行Install脚本。
$ cd <ABSOLUTE_INSTALL_DIR_ON_TARGET> $ ./Install [-minimal|-sasl] <ABSOLUTE_INSTALL_DIR_ON_TARGET>
使用 otp_build 脚本构建
(8)
$ cd $ERL_TOP
(9)
$ ./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>语法传递配置变量(与(3)中的相同)。注意,<HOST>和<BUILD>必须以某种方式传递;要么在配置文件中使用erl_xcomp_host=<HOST>和erl_xcomp_build=<BUILD>,要么使用--host=<HOST>和--build=<BUILD>命令行参数。
otp_build configure将为构建机器上的引导系统和交叉主机系统进行配置。
(10)
$ ./otp_build boot -a
otp_build boot -a将首先为构建机器构建一个引导系统,然后执行系统的交叉构建。
(11)
$ ./otp_build release -a <RELEASE_DIR>
otp_build release -a将执行与(5)相同操作,之后您将不得不手动安装,要么通过执行(6),要么通过执行(7)。
3.3 构建和安装文档
系统交叉构建后,您可以像本地构建系统后一样构建和安装文档。有关如何构建文档的信息,请参阅如何构建文档部分,位于$ERL_TOP/HOWTO/INSTALL.md文档中。
3.4 测试交叉编译的系统
Erlang附带的一些测试使用本地代码进行测试。这意味着在交叉编译Erlang时,您还需要交叉编译测试套件才能在目标主机上运行测试。为此,您首先需要像往常一样发布测试。
$ make release_tests
或者
$ ./otp_build tests
测试将发布到$ERL_TOP/release/tests中。发布测试后,您需要在构建机器上安装测试。您需要提供与(9)中./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文件夹复制到交叉主机系统。
然后转到交叉主机系统,并将(4)或(5)中安装的Erlang设置为您的$PATH。然后转到之前为$ERL_TOP/release/tests/test_server的位置,并执行以下命令。
$ erl -s ts install -s ts run all_tests -s init stop
配置应该被跳过,所有测试都应该顺利通过。有关如何使用ts run的更多详细信息,请使用erl -s ts help -s init stop
3.5 当前使用的配置变量
请注意,您无法在交叉编译配置文件中定义任意变量。只有下面列出的变量才能保证在所有configure脚本的整个执行过程中可见。其他变量需要定义为configure的参数,或者在环境中导出。
仅适用于 otp_build 的变量
本节中的变量仅在使用$ERL_TOP/otp_build configure为交叉编译配置Erlang/OTP时使用。
如果您直接使用configure脚本进行配置,这些变量目前没有效果。
-
erl_xcomp_build - 用于构建的系统。此值将作为--build=$erl_xcomp_build参数传递给configure脚本。它不必是完整的CPU-VENDOR-OS三元组,但可以是。完整的CPU-VENDOR-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-VENDOR-OS三元组,但可以是。完整的CPU-VENDOR-OS三元组将由$ERL_TOP/make/autoconf/config.sub $erl_xcomp_host创建。
-
erl_xcomp_configure_flags - 要传递给configure脚本的额外配置标志。
交叉编译器和其他工具
如果交叉编译工具以<HOST>-为前缀,您可能不需要设置这些变量(其中<HOST>是作为--host=<HOST>参数传递给configure的)。否则,可以通过作为命令行参数传递给configure的变量、xcomp文件中的变量或环境变量来识别编译器和其他工具。有关更多信息,请参阅configure 检查的重要变量部分,位于$ERL_TOP/HOWTO/INSTALL.md文档中。
交叉系统根目录位置
-
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()实现,并与 procfs ioctl()一起使用。
-
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(原生 POSIX 线程库)。较旧的 Linux 系统具有 LinuxThreads 而不是 NPTL(Linux 内核版本通常低于 2.6)。
-
erl_xcomp_linux_usable_sigaltstack - yes|no。在 Linux 上默认为yes;否则为no。如果为yes,目标系统上必须可以使用sigaltstack()。Linux 内核版本低于 2.4 的sigaltstack()是损坏的。
-
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 处。也就是说,它不应该使用位置无关的执行文件。