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
4 changes: 4 additions & 0 deletions doc/changes/added/13734.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- Allow multiple `(dirs ..)` stanzas in the same Dune file. Starting with
`(lang dune 3.23)`, Dune takes the union of the specified directories
(#13734, fixes #6249, @anmonteiro)

30 changes: 20 additions & 10 deletions src/source/dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ module Ast = struct
fields
@@
let+ subdirs = multi_field "subdir" (subdir ~inside_include)
and+ dirs = field_o "dirs" dirs
and+ dirs = multi_field "dirs" dirs
and+ files = field_o "files" files
and+ ignored_sub_dirs =
multi_field "ignored_subdirs" (ignored_sub_dirs ~inside_subdir)
Expand All @@ -298,7 +298,7 @@ module Ast = struct
and+ rest = leftover_fields in
let ast =
List.concat
[ Option.to_list dirs
[ dirs
; Option.to_list files
; Option.to_list vendored_dirs
; subdirs
Expand Down Expand Up @@ -410,7 +410,7 @@ module Group = struct
{ Source_dir_status.Map.normal = dirs; data_only; vendored = vendored_dirs }
;;

let combine t (ast : Ast.t) =
let combine ~dune_version t (ast : Ast.t) =
match ast with
| Ignored_sub_dirs (loc, glob) ->
{ t with ignored_sub_dirs = (loc, glob) :: t.ignored_sub_dirs }
Expand All @@ -420,15 +420,25 @@ module Group = struct
}
| Vendored_dirs (loc, glob) ->
{ t with vendored_dirs = Some (no_dupes "vendored_dirs" loc t.vendored_dirs glob) }
| Dirs (loc, glob) -> { t with dirs = Some (no_dupes "dirs" loc t.dirs glob) }
| Dirs (loc, glob) ->
let dirs =
if dune_version >= (3, 23)
then (
match t.dirs with
| None -> loc, glob
| Some (existing_loc, existing_glob) ->
existing_loc, Predicate_lang.or_ [ existing_glob; glob ])
else no_dupes "dirs" loc t.dirs glob
in
{ t with dirs = Some dirs }
| Files (loc, glob) -> { t with files = Some (no_dupes "files" loc t.files glob) }
| Subdir (path, stanzas) -> { t with subdirs = (path, stanzas) :: t.subdirs }
| Leftovers stanzas -> { t with leftovers = List.rev_append stanzas t.leftovers }
| Include _ -> assert false
;;

let of_ast (ast : Ast.t list) =
let t = List.fold_left ast ~init:empty ~f:combine in
let of_ast (ast : Ast.t list) ~dune_version =
let t = List.fold_left ast ~init:empty ~f:(combine ~dune_version) in
let t = { t with leftovers = List.rev t.leftovers } in
match t.data_only_dirs, t.dirs, t.ignored_sub_dirs with
| _, Some (loc, _), _ :: _ ->
Expand All @@ -445,16 +455,16 @@ module Group = struct
;;
end

let rec to_dir_map ast =
let group = Group.of_ast ast in
let rec to_dir_map ast ~dune_version =
let group = Group.of_ast ast ~dune_version in
let node =
let subdir_status = Group.subdir_status group in
let files = group.files in
Dir_map.singleton { Dir_map.Per_dir.sexps = group.leftovers; subdir_status; files }
in
let subdirs =
List.map group.subdirs ~f:(fun (path, stanzas) ->
Dir_map.make_at_path (Path.Local.explode path) (to_dir_map stanzas))
Dir_map.make_at_path (Path.Local.explode path) (to_dir_map stanzas ~dune_version))
in
Dir_map.merge_all (node :: subdirs)
;;
Expand All @@ -478,7 +488,7 @@ let decode ~file project sexps =
~inside_subdir
~inside_include
Filename.current_dir_name
>>| to_dir_map
>>| to_dir_map ~dune_version:(Dune_project.dune_version project)
;;

type t =
Expand Down
1 change: 0 additions & 1 deletion test/blackbox-tests/lacking-description
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@
./test-cases/stanzas/env/env-link_flags.t/run.t
./test-cases/stanzas/env/env-var-expansion/missing-default-in-blang.t/run.t
./test-cases/stanzas/env/env-var-expansion/nesting.t/run.t
./test-cases/stanzas/include-stanza/github2711.t
./test-cases/stanzas/include-stanza/include-loop.t/run.t
./test-cases/stanzas/install/github2123.t/run.t
./test-cases/stanzas/ocamllex/ocamllex-include-qualified.t
Expand Down
107 changes: 107 additions & 0 deletions test/blackbox-tests/test-cases/stanzas/include-stanza/github2711.t
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Dirs stanzas from included files are evaluated.

$ make_dune_project 2.7
$ cat >dune.inc <<EOF
> (dirs foo)
Expand All @@ -9,3 +11,108 @@
$ dune build ./foo
$ cat _build/default/foo
bar

Multiple dirs stanzas are unioned across dune and include files.

$ mkdir composed
$ cd composed
$ make_dune_project 3.23
$ mkdir keep foo bar
$ cat >keep/dune <<EOF
> (rule (with-stdout-to ok (echo keep)))
> EOF
$ cat >foo/dune <<EOF
> (rule (with-stdout-to nope (echo foo)))
> EOF
$ cat >bar/dune <<EOF
> (rule (with-stdout-to nope (echo bar)))
> EOF
$ cat >dune.inc <<EOF
> (dirs :standard \ foo)
> EOF
$ cat >dune <<EOF
> (dirs :standard \ bar)
> (include dune.inc)
> EOF
$ dune build ./keep/ok
$ cat _build/default/keep/ok
keep
$ dune build ./foo/nope
$ cat _build/default/foo/nope
foo
$ dune build ./bar/nope
$ cat _build/default/bar/nope
bar
$ cd ..

Dirs stanzas that use :standard are interpreted independently.

$ mkdir override
$ cd override
$ make_dune_project 3.23
$ mkdir keep other
$ cat >keep/dune <<EOF
> (rule (with-stdout-to ok (echo keep)))
> EOF
$ cat >other/dune <<EOF
> (rule (with-stdout-to nope (echo other)))
> EOF
$ cat >dune.inc <<EOF
> (dirs keep)
> EOF
$ cat >dune <<EOF
> (dirs :standard \ keep)
> (include dune.inc)
> EOF
$ dune build ./keep/ok
$ cat _build/default/keep/ok
keep
$ dune build ./other/nope
$ cat _build/default/other/nope
other
$ cd ..

The review example evaluates to the union of all matching directories.

$ mkdir review-example
$ cd review-example
$ make_dune_project 3.23
$ mkdir foo keep
$ cat >foo/dune <<EOF
> (rule (with-stdout-to ok (echo foo)))
> EOF
$ cat >keep/dune <<EOF
> (rule (with-stdout-to ok (echo keep)))
> EOF
$ cat >dune <<EOF
> (dirs foo)
> (dirs :standard \ foo)
> (dirs foo)
> EOF
$ dune build ./foo/ok
$ cat _build/default/foo/ok
foo
$ dune build ./keep/ok
$ cat _build/default/keep/ok
keep
$ cd ..

Before version 3.23, multiple dirs stanzas are rejected.

$ mkdir pre-3-23
$ cd pre-3-23
$ make_dune_project 3.22
$ cat >dune.inc <<EOF
> (dirs foo)
> EOF
$ cat >dune <<EOF
> (dirs bar)
> (include dune.inc)
> EOF
$ dune build
File "dune.inc", line 1, characters 6-9:
1 | (dirs foo)
^^^
Error: may not set the "dirs" stanza more than once
[1]
$ cd ..
Loading