From Chumby Wiki
Jump to: navigation, search

Building Ocaml

OCaml is pretty tricky to cross compile - like many programming languages, it will build part of itself, then use that to continue the build. This is great if you're building something for the same machine you building on - however, it's not so good when you're targeting a completely different processor.

Fortunately, in this case, somebody created a patch for the OCaml distribution that makes it at least possible, with a little bit of interaction and hacking.

Install the toolchain

Install the GNU Toolchain

Create the install directory

# sudo mkdir /mnt/usb
# sudo chmod 777 /mnt/usb

Download the source code to OCaml

# mkdir ocaml
# cd ocaml
# wget http://caml.inria.fr/pub/distrib/ocaml-3.10/ocaml-3.10.1.tar.gz
# tar xzf ocaml-3.10.1.tar.gz

Make a copy for the host machine

# cp -a ocaml-3.10.1 ocaml-3.10.1.host

Apply the cross-compile patch

# wget http://web.yl.is.s.u-tokyo.ac.jp/~tosh/cross-ocaml/diffs/cross-ocaml-3.10.1-002.diff.gz
# gunzip ross-ocaml-3.10.1-002.diff.gz
# cd ocaml-3.10.1
# patch -p1 < ../cross-ocaml-3.10.1-002.diff
# cd ..

Build the build machine version

# cd ocaml-3.10.1.host
# ./configure
# make world
# cd ..

Configure the target version

You will be asked several questions during the configuration steps, because the test programs to figure these out won't run when being cross-compiled.

# cd ocaml-3.10.1
# ./configure --prefix=/mnt/usb/ocaml -host arm-unknown-linux -cc arm-linux-gcc -ranlib arm-linux-ranlib -ar arm-linux-ar -aspp arm-linux-gcc -ld arm-linux-ld

(bunch of stuff happens)

Unable to compile the test program.
Make sure the C compiler (* your cross-gcc *) -O is properly installed.
Press <enter> to proceed or <interrupt> to stop.
(just hit Enter key)

(bunch of stuff happens)

Input sizeof(int) sizeof(long) sizeof(long *) sizeof(short)
4 4 4 2

(bunch of stuff happens)

Is 64-bit integer supported? (y/n: default y)
(just hit Enter key)

What is the type of signed 64-bit integer? (example: long long)
long long

What is the type of unsigned 64-bit integer? (example: unsigned long long)
unsigned long

What is the printf format? (example: "ll")

(bunch of stuff happens)

Something went wrong during endianness determination.
You'll have to figure out endianness yourself
Is this a big-endian architecture? (y/n: default n)
(just hit Enter key)

(bunch of stuff happens)

Should doubles be doubleword-aligned? (y/n: default: y)

(bunch of stuff happens)

Should 64-bit integers be doubleword-aligned? (y/n: default: y)

(bunch of stuff happens)

Do native division and modulus have round-towards-zero semantics? (y/n: default y)
(bunch of stuff happens)

(bunch of stuff happens)

Edit the MakeFile

# vi config/Makefile
(remove "graph" from the variable OTHERLIBRARIES, if any)

Build the target version

The build process will fail several times because it uses binaries it previously built as part of the process. When this happens, you'll be renaming the target version of the binary and replacing it with the host version. Once the build is complete, we'll go back and restore the host version with the target version as part of the installation process.

# make world

(bunch of stuff happens)

/bin/sh: ../boot/ocamlrun: cannot execute binary file
make[1]: *** [pervasives.cmi] Error 126
make[1]: Leaving directory `/work/tosh/port_caml/ocaml-3.10.1/stdlib'
make: *** [coldstart] Error 2
# mv byterun/ocamlrun byterun/ocamlrun.target
# cp ../ocaml-3.10.1.host/byterun/ocamlrun byterun/ocamlrun
# make world

(bunch of stuff happens)

boot/ocamlyacc: boot/ocamlyacc: cannot execute binary file
make: *** [parsing/parser.ml] Error 126
# mv yacc/ocamlyacc yacc/ocamlyacc.target
# cp ../ocaml-3.10.1.host/yacc/ocamlyacc yacc/ocamlyacc
# make world

(bunch of stuff happens)

Error on dynamically loaded library: ../otherlibs/unix/dllunix.so: ../otherlibs/unix/dllunix.so: invalid ELF header
Exit code 2 while executing this command:
boot/ocamlrun ./ocamlc -nostdlib unix.cma -g -I stdlib -I ../otherlibs/unix ocamlbuild/ocamlbuild_pack.cmo ocamlbuild/executor.cmo ocamlbuild/my_unix_with_unix.cmo ocamlbuild/ocamlbuild.cmo -o ocamlbuild/ocamlbuild.byte
make: *** [ocamlbuild.byte] Error 2
# mv otherlibs/unix/dllunix.so otherlibs/unix/dllunix.so.target
# cp ../ocaml-3.10.1.host/otherlibs/unix/dllunix.so otherlibs/unix/dllunix.so
# make world

(bunch of stuff happens)

../ocamlcomp.sh -o ocamldoc -linkall unix.cma str.cma dynlink.cma -I ../parsing -I ../utils -I ../typing -I ../driver -I ../bytecomp -I ../tools -I ../toplevel/ -I ../stdlib -I ../otherlibs/str -I ../otherlibs/dynlink -I ../otherlibs/unix -I ../otherlibs/num -I ../otherlibs/graph ../parsing/printast.cmo ../typing/ident.cmo ../utils/tbl.cmo ../utils/misc.cmo ../utils/config.cmo ../utils/clflags.cmo ../utils/warnings.cmo ../utils/ccomp.cmo ../utils/consistbl.cmo ../parsing/linenum.cmo ../parsing/location.cmo ../parsing/longident.cmo ../parsing/syntaxerr.cmo ../parsing/parser.cmo ../parsing/lexer.cmo ../parsing/parse.cmo ../typing/types.cmo ../typing/path.cmo ../typing/btype.cmo ../typing/predef.cmo ../typing/datarepr.cmo ../typing/subst.cmo ../typing/env.cmo ../typing/ctype.cmo ../typing/primitive.cmo ../typing/oprint.cmo ../typing/printtyp.cmo ../typing/includecore.cmo ../typing/typetexp.cmo ../typing/typedtree.cmo ../typing/parmatch.cmo ../typing/stypes.cmo ../typing/typecore.cmo ../typing/includeclass.cmo ../typing/typedecl.cmo ../typing/typeclass.cmo ../typing/mtype.cmo ../typing/includemod.cmo ../typing/typemod.cmo ../bytecomp/lambda.cmo ../bytecomp/typeopt.cmo ../bytecomp/printlambda.cmo ../bytecomp/switch.cmo ../bytecomp/matching.cmo ../bytecomp/translobj.cmo ../bytecomp/translcore.cmo ../bytecomp/translclass.cmo ../tools/depend.cmo odoc_config.cmo odoc_global.cmo odoc_messages.cmo odoc_types.cmo odoc_misc.cmo odoc_text_parser.cmo odoc_text_lexer.cmo odoc_text.cmo odoc_name.cmo odoc_parameter.cmo odoc_value.cmo odoc_type.cmo odoc_exception.cmo odoc_class.cmo odoc_module.cmo odoc_print.cmo odoc_str.cmo odoc_args.cmo odoc_comments_global.cmo odoc_parser.cmo odoc_lexer.cmo odoc_see_lexer.cmo odoc_env.cmo odoc_merge.cmo odoc_sig.cmo odoc_ast.cmo odoc_control.cmo odoc_inherit.cmo odoc_search.cmo odoc_scan.cmo odoc_cross.cmo odoc_comments.cmo odoc_dep.cmo odoc_analyse.cmo odoc_info.cmo odoc_dag2html.cmo odoc_to_text.cmo odoc_ocamlhtml.cmo odoc_html.cmo odoc_man.cmo odoc_latex_style.cmo odoc_latex.cmo odoc_texi.cmo odoc_dot.cmo odoc.cmo
Error on dynamically loaded library: ../otherlibs/str/dllstr.so: ../otherlibs/str/dllstr.so: invalid ELF header
make[1]: *** [ocamldoc] Error 2
make[1]: Leaving directory `/work/tosh/tmp/src/ocaml-3.10.1/ocamldoc'
make: *** [ocamldoc] Error 2
# mv otherlibs/str/dllstr.so otherlibs/str/dllstr.so.target
# cp ../ocaml-3.10.1.host/otherlibs/str/dllstr.so otherlibs/str/dllstr.so
# make world

Install to the installation directory

# make install
# cp byterun/ocamlrun.target /mnt/usb/ocaml/bin/ocamlrun
# cp yacc/ocamlyacc.target /mnt/usb/ocaml/bin/ocamlyacc
# cp otherlibs/unix/dllunix.so.target /mnt/usb/ocaml/lib/ocaml/studlibs/dllunix.so
# cp otherlibs/str/dllstr.so.target /mnt/usb/ocaml/lib/ocaml/studlibs/dllstr.so

Copy the entire /mnt/usb/ocaml directory to a USB dongle.

Too lazy to do all this?

A dongle image for ocaml-3.10 can be found at ocaml-3.10.tar,gz (27.3MB).

You can unpack this and use a debugchumby file to launch a ocaml program or launch sshd.