fxfactorial / opam-ios

OCaml cross-compiler for iOS
http://hyegar.com
78 stars 2 forks source link

+AUTHOR: Edgar Aroutiounian

+EMAIL: edgar.factorial@gmail.com

+LANGUAGE: en

+STARTUP: indent

+LATEX_HEADER: \usepackage{lmodern}

+LATEX_HEADER: \usepackage[T1]{fontenc}

+OPTIONS: toc:nil num:0

This repository contains a 32 bit and 64 bit cross-compiler for OCaml on iOS SDK 7.0-9.2, ~armv7~ and ~arm64~ respectively. Do read this README, it has instructions on how to install, compile and codesigning for jailbroken phones.

IMPORTANT

You do not need to have a jailbroken iOS device to run OCaml, you can use the compiler to make an object file out of the OCaml code and then use OCaml as a C library from your Objective-C programs.

To run OCaml on jailbroken phones, that is to make arbitrary pure OCaml executables, you need to use ~codesign~ or ~ldid~ to sign your binary.

+BEGIN_SRC shell

$ opam switch ios -A 4.02.3

+END_SRC

Then add this repository with:

+BEGIN_SRC shell

$ opam repository add ios git://github.com/fxfactorial/opam-ios

+END_SRC

Now you have a choice, do you want the 32 bit for armv7 or 64-bit compiled for arm64 cross-compiler.

For 32-bit

+BEGIN_SRC shell

$ opam install ios-thirty-two-bit

+END_SRC

For 64-bit

+BEGIN_SRC shell

$ opam install ios-sixty-four-bit

+END_SRC

Now you can compile OCaml that will run on the iPhone!

Here is a stupid server, mostly useful to show how one can use the Unix module with no problem on the iPhone.

+BEGIN_SRC ocaml -n

open UnixLabels

let () = let sock = socket ~domain:PF_INET ~kind:SOCK_STREAM ~protocol:0 in bind sock ~addr:(ADDR_INET (inet_addr_any, 3000)); print_endline "About to listen"; listen sock 5; let resp = "Thanks for the Test!\n" in let buf = String.create 255 in while true do let (listen_sock, listen_addr) = accept sock in (ignore (read listen_sock ~buf ~pos:0 ~len:255)); print_endline buf; (ignore @@ write listen_sock ~buf:resp ~pos:0 ~len:(String.length resp - 1)); Unix.close listen_sock done

+END_SRC

Compile with (same for 32-bit, 64-bit):

+BEGIN_SRC shell

$ ocamlopt -o The_server unix.cmxa server.ml

+END_SRC

Now you need to code sign the binary. You can use ~ldid~, available via ~brew~ or Apple's native ~codesign~ tool.

with ~ldid~:

+BEGIN_SRC shell

$ ldid -S your_binary

+END_SRC

with ~codesign~:

first need to get your developer hash account:

+BEGIN_SRC shell

$ security find-identity -pcodesigning -v 1) XXXXX "Some Account: Fool bar" ...

+END_SRC

And now use ~XXXXX~ to sign your binary:

+BEGIN_SRC shell

$ codesign --deep --sign XXXXX The_server

+END_SRC

(You can also try using ~ldid~ on the device directly, its in Cydia).

And here's an example of it working: (The invocation uses ocamloptrev, this was an old version created from a previous verion offered by this repository but the Unix code is exactly the same)

[[./working_server.gif]]

For an example of calling OCaml from Objective-C, see this [[http://hyegar.com/blog/2016/01/23/calling-ocaml-from-objective-c-on-the-iphone/][blog post]]

Also thanks to @whitequark for his ~opam-android~ repo. Although I ended up going in a different approach, his repo was a great starting point for me.