diff --git a/doc/changes/9827.md b/doc/changes/9827.md new file mode 100644 index 00000000000..bad7a3ec485 --- /dev/null +++ b/doc/changes/9827.md @@ -0,0 +1,2 @@ +- add `only_sources` field to `copy_files` stanza (#9827, fixes #9709, + @jchavarri) diff --git a/doc/stanzas/copy_files.rst b/doc/stanzas/copy_files.rst index 7279a6bfa9b..8f1c274bdcb 100644 --- a/doc/stanzas/copy_files.rst +++ b/doc/stanzas/copy_files.rst @@ -25,6 +25,9 @@ details. - ``(enabled_if )`` conditionally disables this stanza. The condition is specified using the :doc:`reference/boolean-language`. +- ``(only_sources )`` specifies that the glob in ``files`` + gets applied over the source tree, and not the build tree. + The short form: .. code:: dune diff --git a/src/dune_rules/simple_rules.ml b/src/dune_rules/simple_rules.ml index 135102e7f58..63e99b54be4 100644 --- a/src/dune_rules/simple_rules.ml +++ b/src/dune_rules/simple_rules.ml @@ -218,7 +218,15 @@ let copy_files sctx ~dir ~expander ~src_dir (def : Copy_files.t) = not the current directory." ]; (* add rules *) - let* files = Build_system.eval_pred (File_selector.of_glob ~dir:src_in_build glob) in + let* only_sources = Expander.eval_blang expander def.only_sources in + let* files = + let dir = + match only_sources with + | true -> src_in_src + | false -> src_in_build + in + Build_system.eval_pred (File_selector.of_glob ~dir glob) + in (* CR-someday amokhov: We currently traverse the set [files] twice: first, to add the corresponding rules, and then to convert the files to [targets]. To do only one traversal we need [Memo.parallel_map_set]. *) diff --git a/src/dune_rules/stanzas/copy_files.ml b/src/dune_rules/stanzas/copy_files.ml index 5c3a92167ca..d4085cd7271 100644 --- a/src/dune_rules/stanzas/copy_files.ml +++ b/src/dune_rules/stanzas/copy_files.ml @@ -1,12 +1,17 @@ open Import open Dune_lang.Decoder +type origin = + | Build + | Source + type t = { add_line_directive : bool ; alias : Alias.Name.t option ; mode : Rule.Mode.t ; enabled_if : Blang.t ; files : String_with_vars.t + ; only_sources : Blang.t ; syntax_version : Dune_lang.Syntax.Version.t } @@ -16,14 +21,33 @@ include Stanza.Make (struct include Poly end) +let decode_only_sources = + let* blang = peek in + match blang with + | Some _ -> Blang.decode + | None -> return Blang.true_ +;; + let long_form = let check = Dune_lang.Syntax.since Stanza.syntax (2, 7) in let+ alias = field_o "alias" (check >>> Dune_lang.Alias.decode) and+ mode = field "mode" ~default:Rule.Mode.Standard (check >>> Rule_mode_decoder.decode) and+ enabled_if = Enabled_if.decode ~allowed_vars:Any ~since:(Some (2, 8)) () and+ files = field "files" (check >>> String_with_vars.decode) + and+ only_sources = + field_o + "only_sources" + (Dune_lang.Syntax.since Stanza.syntax (3, 14) >>> decode_only_sources) and+ syntax_version = Dune_lang.Syntax.get_exn Stanza.syntax in - { add_line_directive = false; alias; mode; enabled_if; files; syntax_version } + let only_sources = Option.value only_sources ~default:Blang.false_ in + { add_line_directive = false + ; alias + ; mode + ; enabled_if + ; files + ; only_sources + ; syntax_version + } ;; let decode = @@ -38,6 +62,7 @@ let decode = ; mode = Standard ; enabled_if = Blang.true_ ; files + ; only_sources = Blang.false_ ; syntax_version } ;; diff --git a/src/dune_rules/stanzas/copy_files.mli b/src/dune_rules/stanzas/copy_files.mli index 1702735a099..16d5e383994 100644 --- a/src/dune_rules/stanzas/copy_files.mli +++ b/src/dune_rules/stanzas/copy_files.mli @@ -1,11 +1,16 @@ open Import +type origin = + | Build + | Source + type t = { add_line_directive : bool ; alias : Alias.Name.t option ; mode : Rule.Mode.t ; enabled_if : Blang.t ; files : String_with_vars.t + ; only_sources : Blang.t ; syntax_version : Dune_lang.Syntax.Version.t } diff --git a/test/blackbox-tests/test-cases/copy_files/test6.t b/test/blackbox-tests/test-cases/copy_files/test6.t new file mode 100644 index 00000000000..9c8dc1d541a --- /dev/null +++ b/test/blackbox-tests/test-cases/copy_files/test6.t @@ -0,0 +1,45 @@ +Show that copy_files operates on the build folder + + $ mkdir -p target foo + $ cat >dune-project < (lang dune 3.14) + > EOF + $ cat >target/dune < (copy_files + > (files ../foo/*.txt)) + > EOF + $ cat >foo/dune < (rule + > (write-file in-build.txt "")) + > EOF + + $ touch foo/in-source.txt + + $ dune build target/in-source.txt + $ dune build target/in-build.txt + +Show the difference when `only_sources` is used + + $ cat >target/dune < (copy_files + > (only_sources) + > (files ../foo/*.txt)) + > EOF + + $ dune build target/in-source.txt + $ dune build target/in-build.txt + Error: Don't know how to build target/in-build.txt + [1] + +A blang expression can be used: + + $ cat >target/dune < (copy_files + > (only_sources (= x x)) + > (files ../foo/*.txt)) + > EOF + + $ dune build target/in-source.txt + $ dune build target/in-build.txt + Error: Don't know how to build target/in-build.txt + [1]