Cross-compiling OCaml with GitHub Actions

For those that are interested in cross-compiling, there is:

  • a GitHub Actions workflow with an example workflow run that creates an OCaml cross-compiler from:
    1. macOS x86_64 host into macOS arm64 target executables (to make universal binaries, for example, on non-Apple Silicon hardware)
    2. Linux x86_64 host into Android arm64 (v8)
    3. Linux x86_64 host into Android arm32 (v7a)
    4. Linux x86_64 host into Android x86_64
  • internally there are some patches to the OCaml 4.12.1 source code to create a cross-compiling OCaml compiler
  • a document I wrote to help me understand what was happening: Compiling OCaml in Depth — Diskuv OCaml documentation

For example, the GitHub Actions workflow contains a test that illustrates how to use it. When the following is run on 64-bit AMD/Intel Ubuntu Linux:

$ dist/android_arm32v7a-on-linux_x86/opt/mlcross/android_arm32v7a/bin/ocamlopt.opt \
  hello_world.ml -o hello_world.opt.exe

the hello_world.opt.exe should run on Android arm32 (v7a):

$ file hello_world.opt.exe
hello_world.opt.exe: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /system/bin/linker, with debug_info, not stripped

This is just a preview and I’m not generating binary packages at the moment. But if it is useful enough to you that you will test it out (ex. copy/paste the GitHub workflow, or do it manually on your mac or Ubuntu machine), please tell me if you have any problems. Be aware it will likely be months before I package it up in a simpler form because it will take time to upstream patches into the OCaml compiler trunk.

This is a continuation of the closed topic Cross-compiling implementations / how they work . Thanks EduardoRFS, Antonio Nuno Monteiro and Romain Beauxis for showing me the technique!

7 Likes

Thanks! This is an excellent summary.

Just a small remark: the assembly bits in runtime/ (amd64.S, riscv.S, etc) are not used in the bytecode runtime (ocamlrun). They are only used with the native-code compiler, they are linked into the native-code version of the runtime system (libasmrun).

Cheers,
Nicolas

2 Likes

Thanks for that feedback! I’ve updated the doc.

Today all the actions in your repo are failing, saying something like
/home/runner/work/_temp/fcadd2f3-cd46-4ae5-b328-5ff9a6ffb097.sh: line 1: vendor/dkml-compiler/src/r-c-ocaml-1-setup.sh: No such file or directory

Is it normal?

awesome. thanks for doing this. I’m new to OCaml and would love to run compiled apps on android at some point.

As mentioned in the original post, that was a preview for a few months. Jan 2022 was long ago, and I didn’t get any feedback that anybody was using it.

Regardless, I rolled up the cross-compiling functionality into the dkml-base-compiler package. But a huge dose of caution … cross-compiling is not officially supported by OCaml! And unlike when I originally wrote the post, I now actively use my non-free DkSDK CMake product because, among other things, it wraps dkml-base-compiler cross-compiling into a “normal” IDE push-button experience (in fact, as we speak I’m helping some high schoolers use Android Studio to cross-compile OCaml into their Android Java app). So if you use dkml-base-compiler for its cross-compiling features, make sure you have intermediate-advanced comfort with the OCaml compiler, and be comfortable with getting your own support.

Here is what you’ll need if you (or anyone searching in the future) are that intermediate-advanced compiler user and want to get dkml-base-compiler working in your environment:

All the best!

4 Likes