Skip to content

Commit

Permalink
feature: dune targets
Browse files Browse the repository at this point in the history
Add a dune targets command similar to ls that prints the available
targets in a given directory.

fix ocaml#265

Signed-off-by: Ali Caglayan <alizter@gmail.com>
  • Loading branch information
Alizter committed May 22, 2023
1 parent 06ac510 commit 565e0f4
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Unreleased
----------

- Add a `dune targets` command similar to `ls` that displays all the available
targets in a given directory. (#7770, grants #265, @Alizter)

- Read `pkg-config` arguments from the `PKG_CONFIG_ARGN` environment variable
(#1492, #7734, @anmonteiro)

Expand Down
1 change: 1 addition & 0 deletions bin/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ let all : _ Cmdliner.Cmd.t list =
; Ocaml_merlin.command
; Shutdown.command
; Diagnostics.command
; Targets_cmd.command
]
in
let groups =
Expand Down
69 changes: 69 additions & 0 deletions bin/targets_cmd.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
open Import
open Stdune

let doc = "Print available targets in a given directory. Works similalry to ls."

let pp_all_direct_targets path =
let dir = Path.of_string path in
let root =
match (dir : Path.t) with
| External e ->
Code_error.raise "target_hint: external path"
[ ("path", Path.External.to_dyn e) ]
| In_source_tree d -> d
| In_build_dir d -> (
match Path.Build.drop_build_context d with
| Some d -> d
| None -> Path.Source.root)
in
let open Action_builder.O in
let+ targets =
let open Memo.O in
Action_builder.of_memo
(Target.all_direct_targets (Some root) >>| Path.Build.Map.to_list)
in
let targets =
if Path.is_in_build_dir dir then
List.map ~f:(fun (path, k) -> (Path.build path, k)) targets
else
List.map targets ~f:(fun (path, k) ->
match Path.Build.extract_build_context path with
| None -> (Path.build path, k)
| Some (_, path) -> (Path.source path, k))
in
let targets =
(* Only suggest hints for the basename, otherwise it's slow when there are
lots of files *)
List.filter_map targets ~f:(fun (path, kind) ->
if Path.equal (Path.parent_exn path) dir then
(* directory targets can be distinguied by the trailing path seperator *)
Some
(match kind with
| File -> Path.basename path
| Directory -> Path.basename path ^ Filename.dir_sep)
else None)
in
[ Pp.textf "%s:" (Path.to_string dir)
; Pp.concat_map targets ~f:Pp.text ~sep:Pp.newline
]
|> Pp.concat ~sep:Pp.newline

let term =
let+ common = Common.term
and+ paths = Arg.(value & pos_all string [ "." ] & info [] ~docv:"DIR") in
let config = Common.init common in
let request _setup =
let open Action_builder.O in
let+ paragraphs = Action_builder.List.map paths ~f:pp_all_direct_targets in
paragraphs
|> Pp.concat ~sep:(Pp.seq Pp.newline Pp.newline)
|> List.singleton |> User_message.make |> User_message.print
in
Scheduler.go ~common ~config @@ fun () ->
let open Fiber.O in
let+ res = Build_cmd.run_build_system ~common ~request in
match res with
| Error `Already_reported -> raise Dune_util.Report_error.Already_reported
| Ok () -> ()

let command = Cmd.v (Cmd.info "targets" ~doc ~envs:Common.envs) term
5 changes: 5 additions & 0 deletions bin/targets_cmd.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
open Import

(** The targets command lists all the targets available in the given directory,
defaulting to the current working direcctory. *)
val command : unit Cmd.t
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(library
(name simple2))
10 changes: 10 additions & 0 deletions test/blackbox-tests/test-cases/targets/dune-targets-simple.t/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(library
(name simple))

(rule
(targets
(dir d))
(action
(progn
(run mkdir d)
(run cat > d/foo))))
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(lang dune 3.8)
(using directory-targets 0.1)
75 changes: 75 additions & 0 deletions test/blackbox-tests/test-cases/targets/dune-targets-simple.t/run.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
Testing the "dune targets" command in a simple OCaml project with an additional
directory target to see the behaviour there.

We have two libraries with one in a subdirectory. We also have a directory
target d to see how the command will behave.

With no directory provided to the command, it should default to the current
working directory.

$ dune targets
.:
a.ml
d/
dune
dune-project
simple.a
simple.cma
simple.cmxa
simple.cmxs
simple.ml-gen

Multiple directories can be provided to the command. Also subdirectories may be
used, and only the targets available in that directory will be displayed.

$ dune targets . b/
.:
a.ml
d/
dune
dune-project
simple.a
simple.cma
simple.cmxa
simple.cmxs
simple.ml-gen

b:
c.ml
dune
simple2.a
simple2.cma
simple2.cmxa
simple2.cmxs
simple2.ml-gen

The command also works with files in the _build directory.

$ dune targets _build/default/
_build/default:
a.ml
d/
dune
dune-project
simple.a
simple.cma
simple.cmxa
simple.cmxs
simple.ml-gen

$ dune targets _build/default/b
_build/default/b:
c.ml
dune
simple2.a
simple2.cma
simple2.cmxa
simple2.cmxs
simple2.ml-gen

We cannot see inside directory targets

$ dune targets d
d:


0 comments on commit 565e0f4

Please sign in to comment.