Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow dependencies for executables #3499

Open
talex5 opened this issue May 20, 2020 · 7 comments
Open

Allow dependencies for executables #3499

talex5 opened this issue May 20, 2020 · 7 comments
Labels
enhancement feature-request User wanted features

Comments

@talex5
Copy link

talex5 commented May 20, 2020

Desired Behavior

Dune should provide a way to say that an executable depends on another build target (at runtime). Without this, running a program with dune exec may run with a stale build of the dependency (or fail completely).

Example

main.ml:

let () =
  print_endline "Hello from main";
  Unix.execvp "stage2" [| "stage2" |]

stage2.ml:

let () =
  print_endline "Hello from stage 2"

dune

(executable
 (name main)
 (modules main)
 (libraries unix))

(executable
 (public_name stage2)
 (modules stage2))

Results:

$ dune exec -- ./main.exe
Hello from main      
Fatal error: exception Unix.Unix_error(Unix.ENOENT, "execvp", "stage2")
$ dune build @install
$ dune exec -- ./main.exe
Hello from main      
Hello from stage 2

Real projects where this is a problem:

  • In ocaml-ci I have a separate process for the solver. The main process spawns this as a subprocess when testing locally. When I test it with dune exec, I may be testing the old version of the solver.
  • In the CI unit-tests, I need to make sure the executables are built before running the tests. I use:
    (rule
      (alias runtest)
      (package ocaml-ci-service)
      (deps (alias ../install))
      (action (run ./test.exe)))
    
    This seems to ensure that the executables are built on the first run, but doesn't always run the tests again when the executables change.
  • @avsm said on Slack:

    I was discussing this same issue with @NathanReb yesterday, as ocaml-mdx has the same issue (it needs to exec ocaml-mdx-test. I think this is a pretty good feature request to file on the Dune issue tracker -- inter-binary dependencies are really useful and missing.

  • @emillon notes that this is related to dune exec for adverbial commands (time, afl, ...) #3171
  • I test 0install using dune exec -- 0install, but this doesn't ensure that the GUI plugin is up-to-date.
@bobot
Copy link
Collaborator

bobot commented May 20, 2020

#3104 also gives examples where you want all the ressource directories to be up-to-date.

@ghost
Copy link

ghost commented May 20, 2020

This seems to ensure that the executables are built on the first run, but doesn't always run the tests again when the executables change.

If dune doesn't re-run the test when the executable changes, that is definitely a bug

talex5 added a commit to talex5/ocaml-ci that referenced this issue May 21, 2020
This can be cleaned up once ocaml/dune#3499
is implemented. It should help running entirely separate solver services
in future, and also fixes a bug where the unit-tests might test against
an old version of the solver.
talex5 added a commit to talex5/ocaml-ci that referenced this issue May 21, 2020
This can be cleaned up once ocaml/dune#3499
is implemented. It should help running entirely separate solver services
in future, and also fixes a bug where the unit-tests might test against
an old version of the solver.
talex5 added a commit to talex5/ocaml-ci that referenced this issue May 21, 2020
This can be cleaned up once ocaml/dune#3499
is implemented. It should help running entirely separate solver services
in future, and also fixes a bug where the unit-tests might test against
an old version of the solver.
talex5 added a commit to talex5/ocaml-ci that referenced this issue May 21, 2020
This can be cleaned up once ocaml/dune#3499
is implemented. It should help running entirely separate solver services
in future, and also fixes a bug where the unit-tests might test against
an old version of the solver.
jonludlam added a commit to jonludlam/odoc that referenced this issue Sep 23, 2020
Dune has no way currently to specify runtime dependencies between
binaries (see ocaml/dune#3499). With vendored
mdx this causes a problem because we want to run ocaml-mdx, but that
depends upon ocaml-mdx-test, which may not have been built by the time
it gets execd. Instead, we tell dune to execute ocaml-mdx-test directly.

Signed-off-by: Jon Ludlam <[email protected]>
jonludlam added a commit to ocaml/odoc that referenced this issue Sep 24, 2020
Dune has no way currently to specify runtime dependencies between
binaries (see ocaml/dune#3499). With vendored
mdx this causes a problem because we want to run ocaml-mdx, but that
depends upon ocaml-mdx-test, which may not have been built by the time
it gets execd. Instead, we tell dune to execute ocaml-mdx-test directly.

Signed-off-by: Jon Ludlam <[email protected]>
@rgrinberg
Copy link
Member

If dune doesn't re-run the test when the executable changes, that is definitely a bug

I wonder if this is related to the alias expansion bug @aalekseyev and @snowleopard fixed recently

@ghost
Copy link

ghost commented Mar 8, 2021

It is. So there were two issues:

  • if rule R depended on alias A and A depended on file F, then Dune didn't thought that R depended on the contents of F. So if F changed, then R wasn't re-executed
  • if R was sandboxed, then F wasn't copied in the sandbox

the first fix feels like something we should backport in the 2.x branch. The second I'm less sure about because there is a performance degradation we should look more into before Dune 3.0.

@Alizter Alizter added the feature-request User wanted features label Mar 21, 2023
moyodiallo referenced this issue in moyodiallo/opam-dune-lint Apr 14, 2023
This case is a hack to make dependency on an executable. It's trying to
copy in another name before to install it. OCaml-CI raised this issue
which can be found here `https://github.com/ocaml/dune/issues/3499`

This commit try solve the case but not perfect because to get the rules,
we are parsing the dune source and there's some limitation on that, like
dune variables.
moyodiallo referenced this issue in moyodiallo/opam-dune-lint Apr 14, 2023
This case is a hack to make dependency on an executable. It's trying to
copy in another name before to install it. OCaml-CI raised this issue
which can be found here `https://github.com/ocaml/dune/issues/3499`

This commit try solve the case but not perfect because to get the rules,
we are parsing the dune source and there's some limitation on that, like
dune variables.
moyodiallo referenced this issue in moyodiallo/opam-dune-lint Sep 22, 2023
This case is a hack to make dependency on an executable. It's trying to
copy in another name before to install it. OCaml-CI raised this issue
which can be found here `https://github.com/ocaml/dune/issues/3499`

This commit try solve the case but not perfect because to get the rules,
we are parsing the dune source and there's some limitation on that, like
dune variables.
@jchavarri
Copy link
Collaborator

For the record, I have been using libraries are "poor man deps" for this kind of case with some success. It's clunky,... but it helps workaround the problem until there is a better solution.

E.g.:

(executable
 (name main)
 (modules main)
 (libraries stage2_hook unix))

(executable
 (public_name stage2)
 (modules stage2))

(library
 (name stage2_hook)
 (modules stage2_hook))

;;; Dummy file just to be able to add a custom dependency to the executable

(rule
 (targets stage2_hook.ml)
 (deps %{bin:stage2})
 (action
  (with-stdout-to
   %{targets}
   (run echo ""))))

@gasche
Copy link
Member

gasche commented Jul 26, 2024

What is the current best approach for this problem? I have two public executables in my Dune project, foo and bar, and bar calls foo at runtime, and I would like to write a test for bar. I don't know how to specify, in the test for bar, that the test also depends on foo. So when I run the test, it passes or fails depending on the build order.

I wrote a synthetic repro case here: https://gitlab.com/gasche/dune-executable-dependencies-repro-case

# start from a clean state
$ dune clean

# this run of "dune runtest" fails
$ dune runtest
sh: line 1: foo: command not found
File "test/bar.expected", line 1, characters 0-0:
diff --git 1/_build/default/test/bar.expected 2/_build/default/test/bar.out
index 31f77a6..e69de29 100644
--- 1/_build/default/test/bar.expected
+++ 2/_build/default/test/bar.out
@@ -1 +0,0 @@
-Foo !

# dune build now also fails
$ dune build
sh: line 1: foo: command not found  
File "test/bar.expected", line 1, characters 0-0:
diff --git 1/_build/default/test/bar.expected 2/_build/default/test/bar.out
index 31f77a6..e69de29 100644
--- 1/_build/default/test/bar.expected
+++ 2/_build/default/test/bar.out
@@ -1 +0,0 @@
-Foo !

# but a second run (different ordering) succeeds
$ dune build

# and now the test passes
$ dune runtest

@gasche
Copy link
Member

gasche commented Jul 27, 2024

I just pushed a fix suggested by @nojb, which is to use (deps %{bin:foo} %{bin:bar}) in the test rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement feature-request User wanted features
Projects
None yet
Development

No branches or pull requests

6 participants