I am trying to compile Unison, which is written in OCaml, for Android.
The only two OCaml toolchains for Android that I am aware of are opam-cross-android and opam-android-repository. However, they have been unmaintained since 2018 and 2014, respectively, and the OCaml versions they support no longer meet the minimum version requirements of the latest Unison version. I also remember coming across an OCaml compiler which generates Java bytecode, which is also unmaintained by now.
I have managed to compiled Unison into a static binary for the intended ABI using a foreign chroot, albeit for a Linux target rather than an Android one. The resulting binary starts up on Android but on certain operations exits with code 159, indicating abnormal termination with signal 31, presumably due to a system call that is not allowed by the seccomp-bpf policy in Android 8 and higher (source).
Regarding file permissions, the app has WRITE_EXTERNAL_STORAGE
permission, thus it should have access to all of /sdcard
. (Yes, this is nowadays restricted to apps with limited use cases, and only an issue if you want to get the app on the Play store, as the OS itself treats it like any other permission. Even then, Google considers file managers a valid use case, thus chances are the same applies to file sync tools.)
Question: How can I compile OCaml into a binary (executable or library) which runs on Android?
Do the problematic system calls come from the compiler or in the linker? Or rather: would they come from the OCaml-specific part of the toolchain, or from a generic one (for which one could then substitute the appropriate NDK counterpart)?
Are there other alternatives which are still being maintained and work with code expecting to be built on a somewhat recent OCaml version? Such as tools which modify an existing Linux binary, rewriting system calls so they comply with Android’s seccomp policies? Or a OCaml compiler which generates Java bytecode?
For now, please ignore the fact that Android has begun to restrict execution of native binaries in their own process. This could be alleviated by refactoring the executable into a library, but the build target problem would still remain. For now, apps targeting API 28 or lower can still execute native binaries in a separate process, albeit they won’t get accepted on the Play Store, and future Android version may introduce further restrictions even for legacy apps. This, as well as security implications, is for the individual developer/organization to decide.