`dune test` and test-only dependencies

Does anyone have a solution for this scenario:

I am building an OCaml library, nothing exciting.

I have some tests for the library, the tests use some test-only deps (e.g. Popper)

I want to be able to:

  • install just the base lib deps and run dune build to build just the base lib
  • install the test deps and run dune test

So far it seems like these goals are mutually exclusive.

I can add :with-test markers in dune-project to separate the deps into a group that has to be installed with --with-test flag. That covers the opam install separation, but dune build still tries to build the tests.

The generated mylib.opam file has an entry like:

build: [
  ["dune" "subst"] {dev}
  [
    "dune"
    "build"
    "-p"
    name
    "-j"
    jobs
    "@install"
    "@runtest" {with-test}
    "@doc" {with-doc}
  ]
]

…which makes clear why tests are included.

So I had a chat with an agent…

It said I can do dune build -p mylib @install to build just the base lib without tests. Ok, but I’d like to be able to just do dune build for the base case, and then add args to apply other cases.

Next it gave me profiles, so now dune-project has:

(test
 (name mylib)
 (build_if
  (= %{profile} test))
...

and this lets me do dune build without test deps installed.

But now I have to dune test –profile test to run the tests. Feels redundant.

I realise this isn’t the end of the world, but I feel like I should be able to configure dune test to work without extra args.

The agent says it isn’t possible to have both properties that I want though.

Or any wizards out there have a solution for this?

2 Likes

dune build is dune build @@default which translates to ā€œbuild the ā€˜default’ alias non-recursively (ignoring subdirs) at the current directoryā€. When you haven’t manually overridden the @default alias it defaults to @all. @all will build all the executables and libraries in your project, this includes your test executables.

If you don’t want dune build to build your test executables, then you can override the meaning of default in your workspace-level directory. See here for more information:

Here is a similar question from another user recently:

(alias
 (name default)
 (deps
  (alias_rec lib/all)))

is lib/all a thing itself that dune recognises, or it’s a placeholder that I should replace with the name(s) of libs that I want build by the default target?

can I put this in dune-project? that feels right but the docs for alias are under dune

if it has to be in a dune file… I have this project structure:

lib/
  dune
  mylib.ml
  extra.ml
tests/
  dune
  test_mylib.ml

do I need to override default alias in both dune files?

ie in lib/dune to say ā€œbuild mylib" and in tests/dune to say ā€œdo nothingā€?

(is this a bad project structure?)

This would go in a dune file at the same level as lib/ and tests/ since you want to override the meaning of default in that directory.

lib/all is something that dune recognises. It’s the all alias inside of lib/. So having

in a dune file at your project root would tell dune that the meaning of the default alias here is to build lib/all rather than the default value of lib/all test/all.

This would give the meaning that you want to dune build at the root of your project.

1 Like

Thank you!

With this pointer and a bit of thought on my side I have now been able to get my project building the way I wanted

I now have a root dune file like:

(dirs lib test)

(alias
 (name default)
 (deps
  (alias_rec lib/all)))

(alias
 (name runtest)
 (deps
  (alias_rec test/all)))

and I can dune build just the main lib with no test deps installed

or install test deps and dune test to build and run the tests

it’s simpler and cleaner than the mess that Copilot had cobbled together, and I’ve learned a bit about dune

1 Like

hmm, one snag is that dune build no longer automatically rebuilds myproject.opam

but I now understand one way to fix that…

(alias
 (name default)
 (deps
  (alias_rec lib/all)
  (file "oktree.opam")))

is there another way?

is there anything like (alias_rec lib/all) that would mean ā€œall the sugars in my dune-projectā€ or something?