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

Add support for %{bin-available:...} #4995

Merged
2 commits merged into from Oct 13, 2021
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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ Unreleased
- Add support for `(empty_module_interface_if_absent)` in executable and library
stanzas. (#4955, @nojb)

- Add support for `%{bin-available:...}` (#4995, @jeremiedimino)

2.9.1 (07/09/2021)
------------------

Expand Down
2 changes: 2 additions & 0 deletions doc/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ In addition, ``(action ...)`` fields support the following special variables:
%{bin:program} ...)`` and ``(run program ...)`` behave in the same
way. ``%{bin:...}`` is only necessary when you are using ``(bash
...)`` or ``(system ...)``
- ``bin-available:<program>`` expands to ``true`` or ``false`` depending
on whether ``<program>`` is available or not.
- ``lib:<public-library-name>:<file>`` expands to the installation path of
the file ``<file>`` in the library ``<public-library-name>``. If
``<public-library-name>`` is available in the current workspace, the local
Expand Down
7 changes: 7 additions & 0 deletions src/dune_engine/pform.ml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ module Macro = struct
; lib_private : bool
}
| Lib_available
| Bin_available
| Version
| Read
| Read_strings
Expand Down Expand Up @@ -165,6 +166,9 @@ module Macro = struct
| Lib_available, Lib_available -> Eq
| Lib_available, _ -> Lt
| _, Lib_available -> Gt
| Bin_available, Bin_available -> Eq
| Bin_available, _ -> Lt
| _, Bin_available -> Gt
| Version, Version -> Eq
| Version, _ -> Lt
| _, Version -> Gt
Expand Down Expand Up @@ -200,6 +204,7 @@ module Macro = struct
[ ("lib_exec", bool lib_exec); ("lib_private", bool lib_private) ]
]
| Lib_available -> string "Lib_available"
| Bin_available -> string "Bin_available"
| Version -> string "Version"
| Read -> string "Read"
| Read_strings -> string "Read_strings"
Expand Down Expand Up @@ -302,6 +307,7 @@ let encode_to_latest_dune_lang_version t =
| Lib { lib_exec = false; lib_private = true } -> Some "lib-private"
| Lib { lib_exec = true; lib_private = true } -> Some "libexec-private"
| Lib_available -> Some "lib-available"
| Bin_available -> Some "bin-available"
| Version -> Some "version"
| Read -> Some "read"
| Read_strings -> Some "read-strings"
Expand Down Expand Up @@ -388,6 +394,7 @@ module Env = struct
, since ~version:(2, 1)
(Macro.Lib { lib_exec = true; lib_private = true }) )
; ("lib-available", macro Lib_available)
; ("bin-available", since ~version:(3, 0) Macro.Bin_available)
; ("version", macro Version)
; ("read", macro Read)
; ("read-lines", macro Read_lines)
Expand Down
1 change: 1 addition & 0 deletions src/dune_engine/pform.mli
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ module Macro : sig
; lib_private : bool
}
| Lib_available
| Bin_available
| Version
| Read
| Read_strings
Expand Down
12 changes: 12 additions & 0 deletions src/dune_rules/artifacts.ml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ module Bin = struct
(let context = t.context.name in
Action.Prog.Not_found.create ~program:name ?hint ~context ~loc ()))

let binary_available t name =
if not (Filename.is_relative name) then
let p = Path.of_filename_relative_to_initial_cwd name in
Fs_memo.path_exists p
Copy link
Collaborator

@snowleopard snowleopard Oct 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will return true even if p is not a binary. Perhaps, we could check the executable permissions bit and raise a user error if bin_available is used on a non-binary (to prevent possible confusion).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's consistent with %{bin:...} though. %{bin:...} will happily return a non-executable binary and then things will fail later on. We should either change both or neither of them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, staying consistent with bin seems right.

else
match String.Map.find t.local_bins name with
| Some _ -> Memo.Build.return true
| None -> (
t.context.which name >>| function
| Some _ -> true
| None -> false)

let add_binaries t ~dir l =
let local_bins =
List.fold_left l ~init:t.local_bins ~f:(fun acc fb ->
Expand Down
2 changes: 2 additions & 0 deletions src/dune_rules/artifacts.mli
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ module Bin : sig
-> string
-> Action.Prog.t Memo.Build.t

val binary_available : t -> string -> bool Memo.Build.t

val add_binaries : t -> dir:Path.Build.t -> File_binding.Expanded.t list -> t
end

Expand Down
7 changes: 7 additions & 0 deletions src/dune_rules/expander.ml
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,13 @@ let expand_pform_gen ~(context : Context.t) ~bindings ~dir ~source
let open Memo.Build.O in
let+ available = Lib.DB.available (Scope.libs t.scope) lib in
available |> string_of_bool |> string))
| Bin_available ->
Need_full_expander
(fun t ->
Without
(let open Memo.Build.O in
let+ b = Artifacts.Bin.binary_available t.bin_artifacts_host s in
b |> string_of_bool |> string))
| Read ->
let path = relative ~source dir s in
Direct
Expand Down
23 changes: 23 additions & 0 deletions test/blackbox-tests/test-cases/bin-available.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Test for %{bin-available:...}

$ cat >dune-project <<"EOF"
> (lang dune 3.0)
> (package (name foo))
> EOF
$ cat >dune<<"EOF"
> (rule
> (alias default)
> (action
> (progn
> (echo "dune: %{bin-available:dune}\n")
> (echo "local program foo: %{bin-available:foo}\n")
> (echo "non existant program: %{bin-available:*}\n"))))
>
> (executable (public_name foo))
> EOF
$ touch foo.ml

$ dune build
dune: true
local program foo: true
non existant program: false