diff --git a/src/dune_rules/pkg_rules.ml b/src/dune_rules/pkg_rules.ml index 2fbe5e01307..f3f465619c2 100644 --- a/src/dune_rules/pkg_rules.ml +++ b/src/dune_rules/pkg_rules.ml @@ -920,27 +920,32 @@ module Action_expander = struct let dir = t.paths.source_dir in Memo.return @@ Ok (Path.relative dir program) | In_path -> - let* artifacts = t.artifacts in - (match Filename.Map.find artifacts program with - | Some s -> Memo.return @@ Ok s - | None -> - (let path = Global.env () |> Env_path.path in - Which.which ~path program) - >>= (function - | Some p -> Memo.return (Ok p) + (match program with + | "dune" -> + let dune = Path.of_string Sys.executable_name in + Memo.return @@ Ok dune + | program -> + let* artifacts = t.artifacts in + (match Filename.Map.find artifacts program with + | Some s -> Memo.return @@ Ok s | None -> - let+ depexts = filtered_depexts t in - let hint = - Run_with_path.depexts_hint depexts - |> Option.map ~f:(fun pp -> Format.asprintf "%a" Pp.to_fmt pp) - in - Error - (Action.Prog.Not_found.create - ?hint - ~program - ~context:t.context - ~loc:(Some loc) - ())))) + (let path = Global.env () |> Env_path.path in + Which.which ~path program) + >>= (function + | Some p -> Memo.return (Ok p) + | None -> + let+ depexts = filtered_depexts t in + let hint = + Run_with_path.depexts_hint depexts + |> Option.map ~f:(fun pp -> Format.asprintf "%a" Pp.to_fmt pp) + in + Error + (Action.Prog.Not_found.create + ?hint + ~program + ~context:t.context + ~loc:(Some loc) + ()))))) in Result.map prog ~f:(map_exe t) ;; diff --git a/test/blackbox-tests/test-cases/pkg/different-dune-in-path.t b/test/blackbox-tests/test-cases/pkg/different-dune-in-path.t index e47994f41f5..264a0a7fc5d 100644 --- a/test/blackbox-tests/test-cases/pkg/different-dune-in-path.t +++ b/test/blackbox-tests/test-cases/pkg/different-dune-in-path.t @@ -89,12 +89,18 @@ Remember the digests, to not to have to call nested Dunes: Call Dune with an absolute PATH as argv[0]: $ PATH=$fakepath $DUNE build "$pkg_root/$foo_digest/target/" - Fake dune! (args: build -p foo @install) $ PATH=$fakepath $DUNE build "$pkg_root/$bar_digest/target/" Fake dune! (args: build -p bar @install) -Make sure that fake dune is not picked up when dune is called with argv[0] = "dune": +argv[0] is set by the calling program (like a shell or cram test runner) and +could be wrong, hence it cannot always be trusted. In the examples above we +launch dune with an absolute path, thus one could just use argv[0] to get the +exact path to the `dune` binary. + +To make sure that we pick up the right dune even when argv[0] is being set to +unhelpful values we launch the binary but set the value to a relative value, +namely argv[0] = "dune". This is exactly what happens if `dune` is in the PATH +and the user launches `dune` in a shell. $ dune clean $ PATH=$fakepath dune_cmd exec-a "dune" $DUNE build "$pkg_root/$foo_digest/target/" - Fake dune! (args: build -p foo @install)