Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/changes/fixed/13712.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Fixed interpreting relative paths in `%{bin:..}` and `%{bin-available:..}`.
These are now interpreted correctly, relative to the dune file they're in.
(#13712, fixes #9564, @anmonteiro)
5 changes: 3 additions & 2 deletions src/dune_rules/action_unexpanded.ml
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,9 @@ end = struct
Action_builder.of_memo
@@
let open Memo.O in
let dir = env.dir in
let* where =
let+ project = Dune_load.find_project ~dir:env.dir in
let+ project = Dune_load.find_project ~dir in
if Dune_project.dune_version project >= (3, 14)
then Artifacts.Original_path
else Install_dir
Expand All @@ -415,7 +416,7 @@ end = struct
| "rescript_syntax" -> Some "opam install rescript-syntax"
| _ -> None
in
Artifacts.binary ?hint ~loc:(Some loc) ~where artifacts s)
Artifacts.binary ?hint ~loc:(Some loc) ~where ~dir artifacts s)
in
let args = Value.L.to_strings ~dir args in
match prog with
Expand Down
19 changes: 12 additions & 7 deletions src/dune_rules/artifacts.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,23 @@ let local_binaries { local_bins; _ } =
| _, Origin _origins -> None)
;;

let analyze_binary t name =
let analyze_binary t ~dir name =
match Filename.is_relative name with
| false -> Memo.return (`Resolved (Path.of_filename_relative_to_initial_cwd name))
| true ->
let* local_bins = Memo.Lazy.force t.local_bins in
let lookup_name =
match Filename.analyze_program_name name with
| Absolute | In_path -> name
| Relative_to_current_dir -> Path.Build.relative dir name |> Path.Build.basename
in
let which () =
Context.which t.context name
Context.which t.context lookup_name
>>| function
| None -> `None
| Some path -> `Resolved path
in
(match Filename.Map.find local_bins name with
(match Filename.Map.find local_bins lookup_name with
| Some (Resolved p) -> Memo.return (`Resolved (Path.build p.path))
| None -> which ()
| Some (Origin origins) ->
Expand All @@ -82,8 +87,8 @@ let analyze_binary t name =
]))
;;

let binary t ?hint ?(where = Install_dir) ~loc name =
analyze_binary t name
let binary t ?hint ?(where = Install_dir) ~dir ~loc name =
analyze_binary t ~dir name
>>= function
| `Resolved path -> Memo.return @@ Ok path
| `None ->
Expand All @@ -107,8 +112,8 @@ let binary t ?hint ?(where = Install_dir) ~loc name =
Ok (Path.build src))
;;

let binary_available t name =
analyze_binary t name
let binary_available t ~dir name =
analyze_binary t ~dir name
>>| function
| `None -> false
| `Resolved _ | `Origin _ -> true
Expand Down
3 changes: 2 additions & 1 deletion src/dune_rules/artifacts.mli
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ val binary
: t
-> ?hint:string
-> ?where:where
-> dir:Path.Build.t
-> loc:Loc.t option
-> Filename.t
-> Action.Prog.t Memo.t

val binary_available : t -> string -> bool Memo.t
val binary_available : t -> dir:Path.Build.t -> string -> bool Memo.t
val add_binaries : t -> dir:Path.Build.t -> File_binding.Expanded.t list -> t

val create
Expand Down
6 changes: 4 additions & 2 deletions src/dune_rules/coq/coq_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,12 @@ let by_name { coqlib; coqcorelib; coq_native_compiler_default } name =
[ "name", Dyn.string name ]
;;

let expand source macro artifacts_host =
let expand source macro ~dir artifacts_host =
let s = Pform.Macro_invocation.Args.whole macro in
let open Memo.O in
let* coqc = Artifacts.binary artifacts_host ~where:Original_path ~loc:None "coqc" in
let* coqc =
Artifacts.binary artifacts_host ~where:Original_path ~dir ~loc:None "coqc"
in
let expand m k s =
let+ t = m ~coqc in
match t with
Expand Down
1 change: 1 addition & 0 deletions src/dune_rules/coq/coq_config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,6 @@ val by_name : t -> string -> Value.t Option.t
val expand
: Dune_lang.Template.Pform.t
-> Pform.Macro_invocation.t
-> dir:Path.Build.t
-> Artifacts.t
-> Dune_lang.Value.t list Memo.t
7 changes: 4 additions & 3 deletions src/dune_rules/expander.ml
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ let expand_pform_macro
let* artifacts_host = t.artifacts_host in
Artifacts.binary
~loc:(Some (Dune_lang.Template.Pform.loc source))
~dir:t.dir
artifacts_host
s)
in
Expand Down Expand Up @@ -692,7 +693,7 @@ let expand_pform_macro
Without
(let open Memo.O in
let* artifacts_host = t.artifacts_host in
let+ b = Artifacts.binary_available artifacts_host s in
let+ b = Artifacts.binary_available artifacts_host ~dir:t.dir s in
b |> string_of_bool |> string))
| File_available ->
Direct
Expand Down Expand Up @@ -723,7 +724,7 @@ let expand_pform_macro
Without
(let open Memo.O in
let* artifacts_host = t.artifacts_host in
Coq_config.expand source macro_invocation artifacts_host))
Coq_config.expand source macro_invocation ~dir:t.dir artifacts_host))
| Ppx ->
Need_full_expander
(fun t ->
Expand All @@ -747,7 +748,7 @@ let expand_pform_macro
Without
(let open Memo.O in
let* artifacts_host = t.artifacts_host in
Rocq_config.expand source macro_invocation artifacts_host))
Rocq_config.expand source macro_invocation ~dir:t.dir artifacts_host))
;;

let expand_pform_gen ~(context : Context.t) ~bindings ~dir ~source (pform : Pform.t)
Expand Down
6 changes: 4 additions & 2 deletions src/dune_rules/rocq/rocq_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,12 @@ let by_name { rocqlib; rocq_native_compiler_default } name =
[ "name", Dyn.string name ]
;;

let expand source macro artifacts_host =
let expand source macro ~dir artifacts_host =
let s = Pform.Macro_invocation.Args.whole macro in
let open Memo.O in
let* rocq = Artifacts.binary artifacts_host ~where:Original_path ~loc:None "rocq" in
let* rocq =
Artifacts.binary artifacts_host ~where:Original_path ~dir ~loc:None "rocq"
in
let expand m k s =
let+ t = m ~rocq in
match t with
Expand Down
1 change: 1 addition & 0 deletions src/dune_rules/rocq/rocq_config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,6 @@ val by_name : t -> string -> Value.t Option.t
val expand
: Dune_lang.Template.Pform.t
-> Pform.Macro_invocation.t
-> dir:Path.Build.t
-> Artifacts.t
-> Dune_lang.Value.t list Memo.t
2 changes: 1 addition & 1 deletion src/dune_rules/super_context.ml
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ let add_alias_action t alias ~dir ~loc action =

let resolve_program_memo t ~dir ?where ?hint ~loc bin =
let* artifacts = artifacts_host t ~dir in
Artifacts.binary ?hint ?where ~loc artifacts bin
Artifacts.binary ?hint ?where ~dir ~loc artifacts bin
;;

let resolve_program t ~dir ?where ?hint ~loc bin =
Expand Down
71 changes: 71 additions & 0 deletions test/blackbox-tests/test-cases/bin-available-relative.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Relative paths in %{bin:...} and %{bin-available:...} are resolved from the
current directory. See #9564.

$ cat > dune-project << EOF
> (lang dune 3.10)
>
> (package
> (name p))
> EOF

$ cat > dune << EOF
> (executable
> (public_name e)
> (package p))
>
> (executable
> (public_name disabled)
> (package p)
> (modules disabled)
> (enabled_if false))
>
> (rule
> (alias all)
> (action
> (progn
> (echo "available e: %{bin-available:./e}\n")
> (echo "available root foo: %{bin-available:./foo}\n")
> (echo "available pathonly: %{bin-available:./pathonly}\n")
> (echo "available dironly: %{bin-available:./dironly}\n")
> (echo "available disabled: %{bin-available:./disabled}\n")
> (run %{bin:./pathonly})
> (run %{bin:./e}))))
> EOF
$ mkdir path-bin
$ cat > path-bin/pathonly << EOF
> #!/bin/sh
> echo "running pathonly"
> EOF
$ chmod +x path-bin/pathonly
$ mkdir dironly
$ export PATH=$PWD:$PWD/path-bin:$PATH
$ mkdir sub
$ cat > sub/dune << EOF
> (executable
> (public_name nested)
> (package p)
> (modules nested))
>
> (env
> (_ (binaries (nested.exe as foo))))
>
> (rule
> (alias all)
> (action
> (echo "available nested foo: %{bin-available:./foo}\n")))
> EOF
$ cat > e.ml << EOF
> let () = print_endline "running e"
> EOF
$ touch sub/nested.ml
$ touch disabled.ml

$ dune build @all
available nested foo: true
available e: true
available root foo: false
available pathonly: true
available dironly: false
available disabled: false
running pathonly
running e
2 changes: 1 addition & 1 deletion test/blackbox-tests/test-cases/bin-available.t
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Test for %{bin-available:...}
dune: true
local program foo: true
non existent program: false
local path foo: false
local path foo: true
local path bar: false
disabled binary is available: false
disabled by enabled_if: false
Loading