So here’s an example of what I mean: I’m starting to use mdx
to write tests and documentation. I want those tests to run under build-system control (of course). Here’s an example: https://github.com/camlp5/pa_ppx_static/blob/master/tests/toplevel_test.asciidoc#in-the-ocaml-toplevel
I’ve pointed directly at the spot with the toplevel directives to load the required findlib modules. One of those modules, pa_ppx_static
, is built by this opam package, and I want to use it in this test (for obvious reasons). But I want this test to also be documentation, showing how to use this module. So I want the package-naming to be the same whether I’m inside the build, or outside it. As it turns out, that’s hard to do when there are a bunch of findlib modules being built (e.g. pa_ppx.deriving
, pa_ppx.import
, etc). So inside the build of pa_ppx
I name them without the “.”, and outside, I name them with the “.”. That is, inside the build, it’s pa_ppx_import
and outside, it’s pa_ppx.import
.
BUT aside from this trivial naming issue, in the opam package pa_ppx
(which has 52 findlib submodules !) are all built in directories and installed into a local-install
directory, from which they can be run. So for instance, the module pa_ppx_base
is built from the base
directory, and then is used by pa_ppx_deriving
(built from pa_deriving
directory). Make a change to base
and build that, and when you go to make pa_deriving
, it’ll recompile. And why? B/c “make depend” picks up the dependency on other sub-modules in the opam package.
So what you get, is that you can treat each submodule as an independent project, except that when you do a toplevel “make”, the ones that need to get recompiled, get recompiled. And in tests, you name your packages nearly as if they were installed globally.
I don’t know whether other toolchains have an open or closed-world assumption, but I do know that when the toolchain is “make”, it’s usually straightforward to pull out a (in-build-system) build-step and figure out how to run it “outside the build system”. That’s quite, quite, quite, quite not the case with dune. I’ve often reverse-engineered dune build-logs and figured out how to run something outside of dune, and it’s always a complete PITA.
For instance, I figured out how ppx_expect_test worked, and it was a horrorshow. Just all sorts of weird shit going on. And for no good reason, either.
Dune could have really been better, if it had made a committment that all the build-commands it emitted were comprehensible outside the build-system. Ah, well. Heck, it could have been better if it compiled the dune-files of a project, into a toplevel Makefile, and then just invoked make. Again, ah, well.