Dune aliases, deps, and rules with same alias

I have a question concerning Dune aliases and deps.

Currently, I have a lot of different dune files, in different directories, all defining rules which are aliased to foo-configure:

; in src/widget/dune
(rule
  (alias foo-configure)
  (deps (universe))
  (action (progn
            (echo "Widget:" %{lib-available:widget.core} "\n")
          )
  )
)
...
; in src/baz/dune
(rule
  (alias foo-configure)
  (deps (universe))
  (action (progn
            (echo "Baz:" %{lib-available:baz.core} "\n")
          )
  )
)

I want to refactor the dependencies, using a single alias to do so:

; in src/dune
(alias
  (name foo-configure)
  (deps (universe))
)

So that I can remove the (deps (universe)) that is written inside each rule.

I have two questions:

  1. Is this equivalent? Does defining a single deps in the “global” alias stanza ensure that it will be always rebuilt, even if the individual rules that have it as alias no longer have the deps stanza?
  2. If I did not have the (deps (universe)) in the alias stanza, but in a single rule having (alias foo-configure), would this deps be “shared” to all the others? In other words, when there are several rules with the same alias, are all deps computed as a union, and thus it suffices to have (deps (universe)) in one of them to ensure it becomes part of the “whole”?

It seems to me that both answers are yes, but maybe my mental model of how Dune computes the rules is incorrect.

You should be able to answer both questions empirically. IIRC, the (universe) dep means that actions aren’t cached across dune restarts (or dune retriggers if in watch mode, or something). So you should see the echo in the output of dune on every restart with the (universe) dep, and only once without the (universe).

Without testing, I’d expect both answers to be no. Your stanzas are defining this foo-configure alias to be the set { the rule from src/widget/dune, the rule from src/baz/dune, the deps listed in src/dune }. Removing a dependency from a rule isn’t going to be compensated by the dependency appearing elsewhere.

Assuming you’re trying to shorten your dune files, I don’t think that that’s possible. Although in your example, I’m unsure why the (universe) dep is needed in the first place.

1 Like

Thanks. When testing empirically it seems to do what I want, but I’m always afraid that there’s some slightly different usage scenario where things will go wrong. My thinking was that, when dune is computing the set for foo-configure, it will find some rules without deps, but then a (deps (universe)). Thus it will say “ok, (deps (universe))” means “recompute this alias”, and thus it will re-execute each action for the rules aliased to it.

I want the foo-configure alias to be the equivalent of a .PHONY target on Makefile, that will always run. It will go through each component of my system and locally print some status about its availability. So the (universe) seemed justified by that.

I feel like .PHONY targets in Makefiles are sort of the antithesis of what a build system should do. This is true in Make as well as Dune, where the goal is to produce something as efficiently as possible.

I know that it is common to have such targets in Make, but I’d argue that this is basically hacking Make into a command runner for convenience’s sake. In such case I feel that tools like Just are the better solution for it, as you don’t want any build output, you don’t want any dependency tracking, you don’t want any caching - basically: you don’t want a build system.

As for the Dune-specific part of your question, I don’t think that “optimizing” your build like this is legal (it might work, but I don’t think the semantics are valid like this, thus future versions might break it). An alias is kind of like a rule without a target and and it can get built (thus dune build @foo-configure is actually a rather apt description what happens). Building the alias means resolving the dependencies. If these dependencies have been built already (by virtual of having succeeded once and not having dependencies that would require them to be rebuilt (like (universe))) then there is no point in re-running the rules. So the build of the alias foo-configure can succeed without re-running the subsequent rules because Dune knows that it has successfully built the other rules before.

1 Like