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.

raspberry_pi_rot90

Cool.

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:

  1. sudo apt-get install ocaml git m4
  2. git clone https://github.com/OCamlPro/opam.git
  3. cd opam
  4. ./configure && make install
  5. opam init

Update your shell environment as per opam init's instructions. I threw this into my ~/.profile and re-logged in:

which opam && eval $(opam config --env)

Next I used opam to install async and all of its dependencies: opam install async

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
  1. open Core.Std
  2. open Async.Std
  3.  
  4. let port = 10007
  5.  
  6. let handler \_addr reader writer =
  7. let rec echo\_loop () =
  8. Reader.read_line reader
  9. >>= function
  10. | Eof -> return ()
  11. | Ok line ->
  12. let s = line ^ "\n" in
  13. Writer.write writer s;
  14. echo_loop ()
  15. in
  16. echo_loop ()
  17.  
  18. let () =
  19. let d =
  20. Tcp.Server.create (Tcp.on_port port) ~on_handler_error:`Ignore handler
  21. >>| fun \_server ->
  22. printf "Echo server started on port %d\n%!" port
  23. in
  24. don't\_wait_for d;
  25. never_returns (Scheduler.go ())

cat > Makefile

  1. OCAMLMAKEFILE = OCamlMakefile
  2.  
  3. RESULT = hello_async
  4.  
  5. SOURCES = hello_async.ml
  6. PACKS = async
  7. THREADS = true
  8. ANNOTATE = true
  9.  
  10. -include $(OCAMLMAKEFILE)

For simple projects OCamlMakefile is hard to beat. Grab it here

  1. wget https://bitbucket.org/mmottl/ocaml-makefile/raw/a50165b23fb73c66716777d778c4c84ec2aa7183/OCamlMakefile

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.

  1. c localhost 10007
  2. hello async!
  3. hello async!

Awesome!