On Friday morning I discovered a Raspberry Pi on my desk. The Raspberry Pi is a small single-board computer powered by a 700MHz ARM CPU. You can pick them up for as little as $25 and boot ready-made full-featured Linux images off of SD. Out of the box, however, the Raspberry Pi includes no cables, instructions, or boot media. Fortunately the office community quickly came together and delivered an HDMI-to-DVI cable, an SD card, and a mini-USB charger. Ready to roll!
We followed the Quick Start Guide, opting for the Soft-float Debian “wheezy” image to play it safe.
Power on! Lacking any real BIOS, the Raspberry Pi booted to Linux almost instantly and after choosing some yes/nos from an ncurses setup menu (the only way to GUI) it rendered the standard soothing Linux gray-on-black console with bash prompt, cursor blinking expectantly. It even went ahead and requested an IP address from our DHCP server once I connected ethernet.
Since this is Jane Street it wasn’t long before someone popped the question:
Can the Raspberry Pi run OCaml?
Can it build and run Async!?
It sure can! It’s a snap with opam:
sudo apt-get install ocaml git m4 git clone https://github.com/OCamlPro/opam.git cd opam ./configure && make install opam init
Update your shell environment as per opam init’s instructions. I threw this into
~/.profile and re-logged in:
which opam && eval $(opam config --env)
Next I used opam to install async and all of its dependencies:
If you have trouble building opam from the github tip try updating to the
revision we used,
cdc6decbf. The entire process takes about 2-3 hours as opam
builds everything from source.
Here’s how we pulled together a simple async echo server:
mkdir echo_server cd echo_server cat > hello_async.ml
open Core.Std open Async.Std let port = 10007 let handler _addr reader writer = let rec echo_loop () = Reader.read_line reader >>= function | Eof -> return () | Ok line -> let s = line ^ "\n" in Writer.write writer s; echo_loop () in echo_loop () let () = let d = Tcp.Server.create (Tcp.on_port port) ~on_handler_error:`Ignore handler >>| fun _server -> printf "Echo server started on port %d\n%!" port in don't_wait_for d; never_returns (Scheduler.go ())
cat > Makefile
OCAMLMAKEFILE = OCamlMakefile RESULT = hello_async SOURCES = hello_async.ml PACKS = async THREADS = true ANNOTATE = true -include $(OCAMLMAKEFILE)
For simple projects OCamlMakefile is hard to beat. Grab it here
You should now have a file called OCamlMakefile.
make ./hello_async &
Now for the moment of truth, let’s connect to the echo server with netcat.
nc localhost 10007 hello async! hello async!