我需要构建一个 OCaml 交叉编译器。遗憾的是,这似乎不支持开箱即用,需要做一些工作,如旧版本的OCaml 编译器所述。
我的第一个问题是:生成文件 config/mh、config/sh和config/Makefile的好方法是什么?
2 回答
几年来,我一直在构建 OCaml 交叉编译器。(请参阅我的个人资料以获取我网站的链接。)我所做的是构建编译器 1 1/2 次。第一次是针对主机(对目标进行一些设置)。后半部分构建是为目标构建运行时。
我用于构建从 OS X 到 ARM/iOS 的交叉编译器的脚本名为xarm-build
. 如果您有 Subversion,您可以从我的公共存储库中获取副本:
$ svn cat svn://svn.psellos.com/trunk/ocamlxarm/3.1/xarm-build
免责声明:现在,这个脚本只是构建编译器的字节码版本。即,编译器本身是一个OCaml 字节码可执行文件。但是,它会为目标生成本机代码。
如果你尝试这个并且有任何问题,请告诉我。
要回答您的具体问题,如果您的目标系统类似于 Unix,您可以尝试configure
在目标上运行脚本以生成config/s.h
、config/m.h
和config/Makefile
,正如您提到的那样,它们是关键文件。如果你的目标有一个模拟器,你可以configure
在模拟器中运行——这就是我为 iOS 所做的。否则你必须自己找出合理的内容。(也许在与您的目标尽可能相似的类 Unix 系统上运行 configure。)
使用修改后的配置“链”可以生成文件。Ocamls 配置脚本假定它可以在同一次运行中编译和执行结果,这在交叉编译环境中是不可能的。
因此,必须修改配置过程,以便存储编译结果(包括可执行文件)并且可以在目标机器上的第二次运行中使用。这是显示修改的差异文件(约 200 行)。
diff -r -U 1 ocaml-4.00.0-orig/config/auto-aux/hasgot ocaml-4.00.0-cross/config/auto-aux/hasgot
--- ocaml-4.00.0-orig/config/auto-aux/hasgot
+++ ocaml-4.00.0-cross/config/auto-aux/hasgot
@@ -15,2 +15,4 @@
+. ./keyval.sh
+
opts=""
@@ -36,7 +38,13 @@
+key="$cc $args"
+getValueExit "$key"
+
if test "$verbose" = yes; then
echo "hasgot $args: $cc $opts -o tst hasgot.c $libs" >&2
- exec $cc $opts -o tst hasgot.c $libs > /dev/null
+ `exec $cc $opts -o tst hasgot.c $libs > /dev/null`
else
- exec $cc $opts -o tst hasgot.c $libs > /dev/null 2>/dev/null
+ `exec $cc $opts -o tst hasgot.c $libs > /dev/null 2>/dev/null`
fi
+res=$?
+setValue "$key" "$res"
+exit "$res"
diff -r -U 1 ocaml-4.00.0-orig/config/auto-aux/hasgot2 ocaml-4.00.0-cross/config/auto-aux/hasgot2
--- ocaml-4.00.0-orig/config/auto-aux/hasgot2
+++ ocaml-4.00.0-cross/config/auto-aux/hasgot2
@@ -15,2 +15,4 @@
+. ./keyval.sh
+
opts=""
@@ -36,7 +38,13 @@
+key="$cc $args"
+getValueExit "$key"
+
if test "$verbose" = yes; then
echo "hasgot2 $args: $cc $opts -o tst hasgot.c $libs" >&2
- exec $cc $opts -o tst hasgot.c $libs > /dev/null
+ `exec $cc $opts -o tst hasgot.c $libs > /dev/null`
else
- exec $cc $opts -o tst hasgot.c $libs > /dev/null 2>/dev/null
+ `exec $cc $opts -o tst hasgot.c $libs > /dev/null 2>/dev/null`
fi
+res=$?
+setValue "$key" "$res"
+exit "$res"
Only in ocaml-4.00.0-cross/config/auto-aux: keyval.sh
diff -r -U 1 ocaml-4.00.0-orig/config/auto-aux/runtest ocaml-4.00.0-cross/config/auto-aux/runtest
--- ocaml-4.00.0-orig/config/auto-aux/runtest
+++ ocaml-4.00.0-cross/config/auto-aux/runtest
@@ -17,6 +17,30 @@
echo "runtest: $cc -o tst $* $cclibs" >&2
-$cc -o tst $* $cclibs || exit 100
+stream=/dev/stderr
else
-$cc -o tst $* $cclibs 2> /dev/null || exit 100
+stream=/dev/null
+#$cc -o tst $* $cclibs 2> /dev/null || exit 100
fi
+
+key="$* $cclibs"
+
+if test "$crossmode" = cross-cc; then
+ i=`cat ./counter`
+ $cc -o tst"$i" $* $cclibs 2> "$stream" || exit 100
+ echo "$key"'%%#%%'tst"$i" >> ./map_runtest
+ i=`expr $i + 1`
+ echo "$i" > ./counter
+ if test "$*" = sizes.c; then
+ echo "4 4 4 2"
+ fi
+ if test `expr "$*" : '.*tclversion.c'` -ne 0; then
+ echo "8.5"
+ fi
+ exit 0
+fi
+if test "$crossmode" = cross-run; then
+ tst=`awk -v ccargs="$key" 'BEGIN {FS="%%#%%"} $1 == ccargs {print $2}' ./map_runtest`
+ exec ./"$tst"
+fi
+
+$cc -o tst $* $cclibs 2> "$stream" || exit 100
exec ./tst
diff -r -U 1 ocaml-4.00.0-orig/config/auto-aux/tryassemble ocaml-4.00.0-cross/config/auto-aux/tryassemble
--- ocaml-4.00.0-orig/config/auto-aux/tryassemble
+++ ocaml-4.00.0-cross/config/auto-aux/tryassemble
@@ -1,8 +1,16 @@
#!/bin/sh
+
+. ./keyval.sh
+
+key="$aspp $*"
+getValueExit "$key"
+
if test "$verbose" = yes; then
echo "tryassemble: $aspp -o tst $*" >&2
-$aspp -o tst $* || exit 100
+`$aspp -o tst $* || exit 100`
else
-$aspp -o tst $* 2> /dev/null || exit 100
+`$aspp -o tst $* 2> /dev/null || exit 100`
fi
+res=$?
+setValue "$key" "$res"
@@ -11,7 +19,14 @@
if test "$verbose" = yes; then
+key="$as $*"
+getValueExit "$key"
echo "tryassemble: $as -o tst $*" >&2
-$as -o tst $* || exit 100
+`$as -o tst $* || exit 100`
else
-$as -o tst $* 2> /dev/null || exit 100
+`$as -o tst $* 2> /dev/null || exit 100`
fi
+res=$?
+setValue "$key" "$res"
+exit $res
+else
+exit $res
fi
diff -r -U 1 ocaml-4.00.0-orig/config/auto-aux/trycompile ocaml-4.00.0-cross/config/auto-aux/trycompile
--- ocaml-4.00.0-orig/config/auto-aux/trycompile
+++ ocaml-4.00.0-cross/config/auto-aux/trycompile
@@ -15,7 +15,15 @@
+. ./keyval.sh
+
+key="$cc $* $cclibs"
+getValueExit "$key"
+
if test "$verbose" = yes; then
echo "trycompile: $cc -o tst $* $cclibs" >&2
-$cc -o tst $* $cclibs || exit 100
+`$cc -o tst $* $cclibs || exit 100`
else
-$cc -o tst $* $cclibs 2> /dev/null || exit 100
+`$cc -o tst $* $cclibs 2> /dev/null || exit 100`
fi
+res=$?
+setValue "$key" "$res"
+exit $res
diff -r -U 1 ocaml-4.00.0-orig/configure ocaml-4.00.0-cross/configure
--- ocaml-4.00.0-orig/configure
+++ ocaml-4.00.0-cross/configure
@@ -47,2 +47,3 @@
withcamlp4=camlp4
+crossmode=''
@@ -119,2 +120,4 @@
withcamlp4="";;
+ -cross|--cross)
+ crossmode="$2"; shift;;
*) echo "Unknown option \"$1\"." 1>&2; exit 2;;
@@ -158,2 +161,21 @@
+case "$crossmode" in
+ cc)
+ crossmode=cross-cc
+ echo 0 > ./counter
+ rm -f ./map_runtest ./map_hasgot
+ touch ./map_runtest ./map_hasgot;;
+ run)
+ crossmode=cross-run
+ if test ! -e ./map_runtest -o ! -e ./map_hasgot; then
+ echo 'Run with -cross cc first'
+ exit 2
+ fi
+ rm -f ./counter;;
+ none) crossmode=none;;
+ "") crossmode=none ;;
+ *)
+ echo 'Unknown crossmode'>&2
+ exit 2;;
+esac
# Write options to Makefile
@@ -350,3 +372,3 @@
cc="$bytecc -O $bytecclinkopts"
-export cc cclibs verbose
+export cc cclibs verbose crossmode
@@ -1647,2 +1669,5 @@
+if test "$crossmode" = cross-run; then
+ rm -f tst* ./map_runtest ./map_hasgot
+fi
# Print a summary
配置脚本有一个新-cross
选项。当cc
是它的参数时,它只编译,当它是时run
,它只执行编译的东西。中间结果存储在config/auto-aux/map_{hasgot,runtest}setValue
中,主要getValueExit
用于检索,两者都在config/auto-aux/keyval.sh中定义。如果提供跨工具链数据
-cc
, -as
, -aspp
, -partialld
, -libs
, -dllibs
,-dldefs
Makefile 应该是可用的。最后是keyval.sh
内容不在差异中的文件:
getValueExit()
{
if test "$crossmode" = cross-run; then
res=`awk -v ccargs="$1" 'BEGIN {FS="%%#%%"} $1 == ccargs {print $2; exit}' ./map_hasgot`
exit "$res"
fi
}
setValue()
{
if test "$crossmode" = cross-cc; then
echo "$1"'%%#%%'"$2" >> ./map_hasgot
fi
}
如果tk
使用,必须修改config/auto-aux/runtest并替换0.0
为它的版本号。此外,如果将 solaris 用作目标或主机,则可能需要修改文件config/auto-aux/solaris-ld 。