Y'all should know right away that I'm a newcomer to these parts. I don't speak your fancy theorems and I ain't never proved anything sound. Still, I reckon I got things to say, and I aim to have some fun while I'm here. So strap yourselves in; I just had a great little moment with ocaml and I'm going to hold forth on it, with metaphors! I've been building a tournament program, but that's not important. The point is, I had just gotten my feet wet with everyone's favorite packaging manager. Excuse me, I mean *platform* manager. But I had built exactly *one* OPAM package in my life. And I'd been beavering away on that project for months, and it was unfinished. So technically I had built zero. But I decided to build another one anyway. Not in a considered, deliberate way, mind you. In a seat-of-the-pants, New Year's morning kind of way. It all just sort of happened, really. I had been reading the js_of_ocaml documentation irregularly for months, which is a bit like prospecting for gold. Only there's tons of gold. But still, it takes work, and even ingenuity if I do say so myself. So I found some shiny lumps about binding to the javascript world, and I had been wondering what I might do for unit testing that tournament program; So I guess I'd been kicking around thoughts about binding to the jasmine javascript unit testing framework for a while. Anyway, js_of_ocaml's runtime was starting to make a lot of sense, and I had something I already wanted, nay "needed" to build. The combination of a new tool and something to use it on is like crack to me. So I really had no choice. I had to bind to jasmine. (Jumping into the world of ocaml is like taking a course from a brilliant, but somewhat aloof professor. You will experience a regular series of epiphanies punctuated by moments of frustration. But that's the yin and the yang of ocaml. It's kind of ideal, actually. Indeed, you wouldn't *want* a completely smooth path, because that would rob you of the satisfaction of having bested so many private demons. And even though that professor sometimes seems cold, you know that she's built your course with care, and with your benefit at heart. But I digress.) So I looked at the official jasmine tutorial and just started guessing how I might bind to it. In an hour I had a minimally viable binding. I could write multi-suite, multi-spec unit tests in ocaml for the browser, and get a nice interface. So this was a lot of fun. Incidentally, the API looks like this: describe (string "a suite exercising jasmine itself") (fun () -> it (string "runs basic boolean tests") (fun () -> (expect_bool _true)##toBe(_true)); it (string "understands \"not\"") (fun () -> (expect_bool _false)##_not##toBe(_true))) Having gotten this far, I wondered how to use this new binding from my tournament program. An OPAM package? But it's so minimal that I'm the only one who could find it useful! And I don't want to maintain it! And what if people make fun of me? I wrestled with my soul, then threw caution to the wind. I would build, and eventually publish, my second OPAM package. Elated by this reckless decision, I wasn't in the mood to go out and read documentation (I admit I ran an opam pin --help). I wanted to fire my gun. I wanted to test myself, and OPAM, to see what we were made of. So I did. Here's what happened [comments inline]: ------------- Begin Transcript --------------- ~/ocaml/ojasmine$ opam pin add ojasmine . Package ojasmine does not exist, create as a NEW package ? [Y/n] [I edited the opam file...] ojasmine is now path-pinned to /home/laheadle/ocaml/ojasmine [NOTE] You are pinning to /home/laheadle/ocaml/ojasmine as a raw path while it seems to be a git repository. [NOTE] Consider pinning with '-k git' to have OPAM synchronise with your commits and ignore build artefacts. [ I did not know about this feature and found OPAM's hints helpful. ] [ojasmine.~unknown] Synchronizing with /home/laheadle/ocaml/ojasmine [WARNING] The opam file didn't pass validation: - Some fields are present but empty; remove or fill them - Missing field 'dev-repo' Continue anyway ('no' will reedit) ? [Y/n] [ This is a good default; I will add the field later. ] You can edit this file again with "opam pin edit ojasmine" [ I did not know this. Again, helpful. ] Save the new opam file back to "/home/laheadle/ocaml/ojasmine/opam" ? [Y/n] [ Yes. ] ojasmine needs to be installed. The following actions will be performed: - install ojasmine.0.1* === 1 to install === Do you want to continue ? [Y/n] [ Sure. I thought I was just creating an opam file, but why not? Like I said, I am feeling reckless. ] =-=- Synchronizing package archives -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= [ojasmine.0.1] Synchronizing with /home/laheadle/ocaml/ojasmine =-=- Installing packages =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Building ojasmine.0.1: make make install [ERROR] The compilation of ojasmine.0.1 failed. Removing ojasmine.0.1. make uninstall #=== ERROR while installing ojasmine.0.1 ======================================# # opam-version 1.2.0 # os linux # command make install # path /home/laheadle/.opam/4.02.0/build/ojasmine.0.1 # compiler 4.02.0 # exit-code 2 # env-file /home/laheadle/.opam/4.02.0/build/ojasmine.0.1/ojasmine-9015-6cc03f.env # stdout-file /home/laheadle/.opam/4.02.0/build/ojasmine.0.1/ojasmine-9015-6cc03f.out # stderr-file /home/laheadle/.opam/4.02.0/build/ojasmine.0.1/ojasmine-9015-6cc03f.err ### stdout ### # ocamlbuild -cflag -annot -use-ocamlfind -pkgs js_of_ocaml.log,js_of_ocaml,js_of_ocaml.syntax -syntax camlp4o ojasmine.byte # js_of_ocaml +weak.js ojasmine.byte # ocamlbuild -cflag -annot -use-ocamlfind -pkgs js_of_ocaml.log,js_of_ocaml,js_of_ocaml.syntax -syntax camlp4o test_ojasmine.byte # js_of_ocaml +weak.js test_ojasmine.byte ### stderr ### # make: *** No rule to make target `install'. Stop. [NOTE] Pinning command successful, but your installed packages may be out of sync. [Ok, that makes sense. I haven't even defined a make install target. ] ------------- End of Transcript --------------- Even though the install failed, OPAM helpfully reminded me that the pinning command worked. I found this reassuring. Overall, this was a nice experience. I got to fire my gun and everything went fine. OPAM anticipated my needs, led me through what I needed to do, and gave me hints, all of which were very helpful. OPAM's designers had thought carefully about what new developer-users like me would be thinking. Thanks OPAM! Lyn Headley