diff --git a/CHANGES.md b/CHANGES.md index 0f91caa243c4..f4417dd64cd3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -33,6 +33,12 @@ next [opam-cross-windows](https://github.com/whitequark/opam-cross-windows) (#355) +- Add an `(include ...)` stanza allowing one to include another + non-generated jbuild file in the current file (#402) + +- Add a `(promote ( as ) ...)` action allowing one to + promote generated files as source files (#402) + 1.0+beta16 (05/11/2017) ----------------------- diff --git a/Makefile b/Makefile index 8e10e07196ba..c3d6ca44a4c0 100644 --- a/Makefile +++ b/Makefile @@ -33,24 +33,8 @@ clean: doc: cd doc && sphinx-build . _build -CMDS = $(shell $(BIN) --help=plain | \ - sed -n '/COMMANDS/,/OPTIONS/p' | sed -En 's/^ ([a-z-]+)/\1/p') - update-jbuilds: $(BIN) - sed -n '1,/;;GENERATED/p' doc/jbuild > doc/jbuild.tmp - { for cmd in $(CMDS); do \ - echo -ne "\n"\ - "(rule\n"\ - " ((targets (jbuilder-$$cmd.1))\n"\ - " (action (with-stdout-to $$""{@}\n"\ - " (run $$""{bin:jbuilder} $$cmd --help=groff)))))\n"\ - "\n"\ - "(install\n"\ - " ((section man)\n"\ - " (files (jbuilder-$$cmd.1))))\n"; \ - done } >> doc/jbuild.tmp - rm -f doc/jbuild - mv doc/jbuild.tmp doc/jbuild + $(BIN) build --dev @jbuild --promote copy accept-corrections: for i in `find . -name \*.corrected`; do \ diff --git a/bin/main.ml b/bin/main.ml index 07b43e4d17f1..958343158e5a 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -22,6 +22,8 @@ type common = ; only_packages : String_set.t option ; capture_outputs : bool ; x : string option + ; diff_command : string option + ; promote_mode : Clflags.promote_mode ; (* Original arguments for the external-lib-deps hint *) orig_args : string list } @@ -39,6 +41,8 @@ let set_common c ~targets = if c.root <> Filename.current_dir_name then Sys.chdir c.root; Clflags.workspace_root := Sys.getcwd (); + Clflags.diff_command := c.diff_command; + Clflags.promote_mode := c.promote_mode; Clflags.external_lib_deps_hint := List.concat [ ["jbuilder"; "external-lib-deps"; "--missing"] @@ -156,6 +160,8 @@ let common = verbose no_buffer workspace_file + diff_command + promote_mode (root, only_packages, orig) x = @@ -182,6 +188,8 @@ let common = ; root ; orig_args ; target_prefix = String.concat ~sep:"" (List.map to_cwd ~f:(sprintf "%s/")) + ; diff_command + ; promote_mode ; only_packages = Option.map only_packages ~f:(fun s -> String_set.of_list (String.split s ~on:',')) @@ -315,6 +323,36 @@ let common = & info ["x"] ~docs ~doc:{|Cross-compile using this toolchain.|}) in + let diff_command = + Arg.(value + & opt (some string) None + & info ["diff-command"] ~docs + ~doc:"Shell command to use to diff files") + in + let promote = + let mode = + Arg.(conv + (Arg.parser_of_kind_of_string ~kind:"promotion mode" + (function + | "ignore" -> Some Clflags.Ignore + | "check" -> Some Check + | "copy" -> Some Copy + | _ -> None), + fun ppf mode -> + Format.pp_print_string ppf + (match mode with + | Clflags.Ignore -> "ignore" + | Check -> "check" + | Copy -> "copy"))) + in + Arg.(value + & opt mode Check + & info ["promote"] ~docs + ~doc:"How to interpret promote actions. $(b,check), the default, means to + only check that promoted files are equal to the source files. + $(b,ignore) means to ignore promote action altogether and $(b,copy) + means to copy generated files to the source tree.") + in Term.(const make $ concurrency $ ddep_path @@ -324,6 +362,8 @@ let common = $ verbose $ no_buffer $ workspace_file + $ diff_command + $ promote $ root_and_only_packages $ x ) diff --git a/doc/jbuild b/doc/jbuild index e36aa02f9a55..1cf5729584f4 100644 --- a/doc/jbuild +++ b/doc/jbuild @@ -9,104 +9,12 @@ ((section man) (files (jbuilder.1)))) -;; Run "make update-jbuilds" to update the rest of this file -;;GENERATED +(include jbuild.inc) (rule - ((targets (jbuilder-build.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} build --help=groff))))) + (with-stdout-to jbuild.inc.gen + (run bash ${path:update-jbuild.sh} ${bin:jbuilder}))) -(install - ((section man) - (files (jbuilder-build.1)))) - -(rule - ((targets (jbuilder-clean.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} clean --help=groff))))) - -(install - ((section man) - (files (jbuilder-clean.1)))) - -(rule - ((targets (jbuilder-exec.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} exec --help=groff))))) - -(install - ((section man) - (files (jbuilder-exec.1)))) - -(rule - ((targets (jbuilder-external-lib-deps.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} external-lib-deps --help=groff))))) - -(install - ((section man) - (files (jbuilder-external-lib-deps.1)))) - -(rule - ((targets (jbuilder-install.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} install --help=groff))))) - -(install - ((section man) - (files (jbuilder-install.1)))) - -(rule - ((targets (jbuilder-installed-libraries.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} installed-libraries --help=groff))))) - -(install - ((section man) - (files (jbuilder-installed-libraries.1)))) - -(rule - ((targets (jbuilder-rules.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} rules --help=groff))))) - -(install - ((section man) - (files (jbuilder-rules.1)))) - -(rule - ((targets (jbuilder-runtest.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} runtest --help=groff))))) - -(install - ((section man) - (files (jbuilder-runtest.1)))) - -(rule - ((targets (jbuilder-subst.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} subst --help=groff))))) - -(install - ((section man) - (files (jbuilder-subst.1)))) - -(rule - ((targets (jbuilder-uninstall.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} uninstall --help=groff))))) - -(install - ((section man) - (files (jbuilder-uninstall.1)))) - -(rule - ((targets (jbuilder-utop.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} utop --help=groff))))) - -(install - ((section man) - (files (jbuilder-utop.1)))) +(alias + ((name jbuild) + (action (promote (jbuild.inc.gen as jbuild.inc))))) diff --git a/doc/jbuild.inc b/doc/jbuild.inc new file mode 100644 index 000000000000..7e66762bddf3 --- /dev/null +++ b/doc/jbuild.inc @@ -0,0 +1,100 @@ + +(rule + ((targets (jbuilder-build.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} build --help=groff))))) + +(install + ((section man) + (files (jbuilder-build.1)))) + +(rule + ((targets (jbuilder-clean.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} clean --help=groff))))) + +(install + ((section man) + (files (jbuilder-clean.1)))) + +(rule + ((targets (jbuilder-exec.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} exec --help=groff))))) + +(install + ((section man) + (files (jbuilder-exec.1)))) + +(rule + ((targets (jbuilder-external-lib-deps.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} external-lib-deps --help=groff))))) + +(install + ((section man) + (files (jbuilder-external-lib-deps.1)))) + +(rule + ((targets (jbuilder-install.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} install --help=groff))))) + +(install + ((section man) + (files (jbuilder-install.1)))) + +(rule + ((targets (jbuilder-installed-libraries.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} installed-libraries --help=groff))))) + +(install + ((section man) + (files (jbuilder-installed-libraries.1)))) + +(rule + ((targets (jbuilder-rules.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} rules --help=groff))))) + +(install + ((section man) + (files (jbuilder-rules.1)))) + +(rule + ((targets (jbuilder-runtest.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} runtest --help=groff))))) + +(install + ((section man) + (files (jbuilder-runtest.1)))) + +(rule + ((targets (jbuilder-subst.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} subst --help=groff))))) + +(install + ((section man) + (files (jbuilder-subst.1)))) + +(rule + ((targets (jbuilder-uninstall.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} uninstall --help=groff))))) + +(install + ((section man) + (files (jbuilder-uninstall.1)))) + +(rule + ((targets (jbuilder-utop.1)) + (action (with-stdout-to ${@} + (run ${bin:jbuilder} utop --help=groff))))) + +(install + ((section man) + (files (jbuilder-utop.1)))) + diff --git a/doc/jbuild.rst b/doc/jbuild.rst index 78e8bb635b25..8c6487a79973 100644 --- a/doc/jbuild.rst +++ b/doc/jbuild.rst @@ -537,6 +537,34 @@ The difference between ``copy_files`` and ``copy_files#`` is the same as the difference between the ``copy`` and ``copy#`` action. See the `User actions`_ section for more details. +include +------- + +The ``include`` stanza allows to include the contents of another file +into the current jbuild file. Currently, the included file cannot be +generated and must be present in the source tree. This feature is +intended to be used in conjunction with promotion, when parts of a +jbuild file are to be generated. + +For instance: + +.. code:: scheme + + (include jbuild.inc) + + (rule (with-stdout-to jbuild.inc.gen (run ./gen-jbuild.exe))) + + (alias + ((name jbuild) + (action (promote (jbuild.inc.gen as jbuild.inc))))) + +With this jbuild file, running jbuilder as follow will replace the +``jbuild.inc`` file in the source tree by the generated one: + +.. code:: shell + + $ jbuilder build @jbuild --promote copy + Common items ============ @@ -971,6 +999,12 @@ The following constructions are available: and ``cmd`` on Windows - ``(bash )`` to execute a command using ``/bin/bash``. This is obviously not very portable +- ``(promote )`` copy generated files to the source + tree. See `Promotion`_ for more details +- ``(promote-if )`` is the same as ``(promote + )`` except that it does nothing when the files to + copy don't exist. This can be used with command that only produce a + correction when differences are found As mentioned ``copy#`` inserts a line directive at the beginning of the destination file. More precisely, it inserts the following line: @@ -1088,6 +1122,31 @@ is global to all build contexts, simply use an absolute filename: .. _ocaml-syntax: +Promotion +--------- + +The ``(promote ( as ) ( as ) ...)`` action +can be used to copy generated files to the source tree. + +This method is used when one wants to comit a generated file that is +independent of the systems where it is generated. Typically this can +be used to: + +- cut dependencies and/or speed up the build in release mode: we use + the file in the source tree rather than re-generate it +- support bootstrap cycles + +How jbuilder interprets promotions can be controlled using the +``--promote`` command line argument. The following behaviors are +available: + +- ``--promote check``: this is the default. Jbuilder just checks that + the two files given in each ``( as )`` form are equal. If not, + it prints a diff +- ``--promote ignore``: ``promote`` actions are simply ignored +- ``--promote copy``: when the two files are different, jbuilder + prints a diff and copies ```` to ```` directly in the source tree + OCaml syntax ============ diff --git a/doc/update-jbuild.sh b/doc/update-jbuild.sh new file mode 100755 index 000000000000..3ec82dae1df8 --- /dev/null +++ b/doc/update-jbuild.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# CR-someday jdimino: maybe it's possible to get cmdliner to print that directly + +set -e -o pipefail + +jbuilder=$1 + +CMDS=$($jbuilder --help=plain | \ + sed -n '/COMMANDS/,/OPTIONS/p' | sed -En 's/^ ([a-z-]+)/\1/p') + +for cmd in $CMDS; do + cat < "outputs" end +module Promote_mode = Action_intf.Promote_mode + module type Sexpable = sig type t val t : t Sexp.Of_sexp.t @@ -29,6 +31,14 @@ module Make_ast struct include Ast + let promoted_file sexp = + match sexp with + | List (_, [src; Atom (_, "as"); dst]) -> + { Promote. src = Path.t src; dst = Path.t dst } + | _ -> + of_sexp_error sexp + "( as ) expected" + let rec t sexp = let path = Path.t and string = String.t in sum @@ -59,9 +69,16 @@ struct ; cstr "system" (string @> nil) (fun cmd -> System cmd) ; cstr "bash" (string @> nil) (fun cmd -> Bash cmd) ; cstr "write-file" (path @> string @> nil) (fun fn s -> Write_file (fn, s)) + ; cstr_rest "promote" nil promoted_file + (fun files -> Promote { mode = Always; files }) + ; cstr_rest "promote-if" nil promoted_file + (fun files -> Promote { mode = If_corrected_file_exists; files }) ] sexp + let sexp_of_promoted_file (file : Promote.file) = + Sexp.List [Path.sexp_of_t file.src; Atom "as"; Path.sexp_of_t file.dst] + let rec sexp_of_t : _ -> Sexp.t = let path = Path.sexp_of_t and string = String.sexp_of_t in function @@ -93,6 +110,10 @@ struct | Remove_tree x -> List [Atom "remove-tree"; path x] | Mkdir x -> List [Atom "mkdir"; path x] | Digest_files paths -> List [Atom "digest-files"; List (List.map paths ~f:path)] + | Promote { mode = Always; files } -> + List (Atom "promote" :: List.map files ~f:sexp_of_promoted_file) + | Promote { mode = If_corrected_file_exists; files } -> + List (Atom "promote-if" :: List.map files ~f:sexp_of_promoted_file) end module Make_mapper @@ -126,6 +147,12 @@ module Make_mapper | Remove_tree x -> Remove_tree (f_path x) | Mkdir x -> Mkdir (f_path x) | Digest_files x -> Digest_files (List.map x ~f:f_path) + | Promote p -> + let files = + List.map p.files ~f:(fun { Src.Promote. src; dst } -> + { Dst.Promote.src = f_path src; dst = f_path dst }) + in + Promote { mode = p.mode; files } end module Prog = struct @@ -374,6 +401,15 @@ module Unexpanded = struct end | Digest_files x -> Digest_files (List.map x ~f:(E.path ~dir ~f)) + | Promote p -> + let files = + List.map p.files ~f:(fun { Promote.src; dst } -> + { Unresolved.Promote. + src = E.path ~dir ~f src + ; dst = Path.drop_build_context (E.path ~dir ~f dst) + }) + in + Promote { mode = p.mode; files } end module E = struct @@ -475,6 +511,15 @@ module Unexpanded = struct Mkdir res | Digest_files x -> Digest_files (List.map x ~f:(E.path ~dir ~f)) + | Promote p -> + let files = + List.map p.files ~f:(fun { Promote.src; dst } -> + { Partial.Promote. + src = E.path ~dir ~f src + ; dst = E.path ~dir ~f dst + }) + in + Promote { mode = p.mode; files } end let fold_one_step t ~init:acc ~f = @@ -496,7 +541,8 @@ let fold_one_step t ~init:acc ~f = | Rename _ | Remove_tree _ | Mkdir _ - | Digest_files _ -> acc + | Digest_files _ + | Promote _ -> acc include Make_mapper(Ast)(Ast) @@ -667,6 +713,36 @@ let rec exec t ~ectx ~dir ~env_extra ~stdout_to ~stderr_to = (Marshal.to_string data []) in exec_echo stdout_to s + | Promote { mode; files } -> + let promote_mode = !Clflags.promote_mode in + if promote_mode = Ignore then + return () + else begin + let files = + match mode with + | Always -> files + | If_corrected_file_exists -> + List.filter files ~f:(fun file -> Path.exists file.Promote.src) + in + let not_ok = + List.filter files ~f:(fun { Promote. src; dst } -> + let src_contents = Io.read_file (Path.to_string src) in + let dst_contents = Io.read_file (Path.to_string dst) in + src_contents <> dst_contents) + in + match not_ok with + | [] -> return () + | _ -> + if promote_mode = Copy then + Future.Scheduler.at_exit_after_waiting_for_commands (fun () -> + List.iter not_ok ~f:(fun { Promote. src; dst } -> + Format.eprintf "Promoting %s to %s.@." + (Path.to_string_maybe_quoted src) + (Path.to_string_maybe_quoted dst); + Io.copy_file ~src:(Path.to_string src) ~dst:(Path.to_string dst))); + Future.all_unit (List.map not_ok ~f:(fun { Promote. src; dst } -> + Diff.print dst src)) + end and redirect outputs fn t ~ectx ~dir ~env_extra ~stdout_to ~stderr_to = let fn = Path.to_string fn in @@ -731,6 +807,13 @@ module Infer = struct end open Outcome + let infer_promote mode files ~init ~f = + if mode = Promote_mode.If_corrected_file_exists || + !Clflags.promote_mode = Ignore then + init + else + List.fold_left files ~init ~f + let ( +@ ) acc fn = { acc with targets = S.add fn acc.targets } let ( +< ) acc fn = { acc with deps = S.add fn acc.deps } @@ -750,6 +833,8 @@ module Infer = struct | Ignore (_, t) -> infer acc t | Progn l -> List.fold_left l ~init:acc ~f:infer | Digest_files l -> List.fold_left l ~init:acc ~f:(+<) + | Promote { mode; files } -> + infer_promote mode files ~init:acc ~f:(fun acc file -> acc +< file.Promote.src) | Echo _ | System _ | Bash _ @@ -791,6 +876,9 @@ module Infer = struct | Ignore (_, t) -> partial acc t | Progn l -> List.fold_left l ~init:acc ~f:partial | Digest_files l -> List.fold_left l ~init:acc ~f:(+ + infer_promote mode files ~init:acc ~f:(fun acc file -> + acc + partial_with_all_targets acc t | Progn l -> List.fold_left l ~init:acc ~f:partial_with_all_targets | Digest_files l -> List.fold_left l ~init:acc ~f:(+ + infer_promote mode files ~init:acc ~f:(fun acc file -> + acc +>= ) = Future.( >>= ) + +let print file1 file2 = + let loc = Loc.in_file (Path.to_string file1) in + let fallback () = + die "%aFiles \"%s\" and \"%s\" differ." Loc.print loc + (Path.to_string file1) (Path.to_string file2) + in + let normal_diff () = + match Bin.which "diff" with + | None -> fallback () + | Some prog -> + Format.eprintf "%a@?" Loc.print loc; + Future.run Strict (Path.to_string prog) + ["-u"; Path.to_string file1; Path.to_string file2] + >>= fun () -> + die "diff reported no differences on \"%s\" and \"%s\"" + (Path.to_string file1) (Path.to_string file2) + in + match !Clflags.diff_command with + | Some cmd -> + let sh, arg = Utils.system_shell_exn ~needed_to:"print diffs" in + let q fn = Filename.quote (Path.to_string fn) in + let cmd = sprintf "%s %s %s" cmd (q file1) (q file2) in + Future.run Strict (Path.to_string sh) [arg; cmd] + >>= fun () -> + die "command reported no differences: %s" cmd + | None -> + match Bin.which "patdiff" with + | None -> normal_diff () + | Some prog -> + Future.run Strict (Path.to_string prog) + [ "-keep-whitespace" + ; "-location-style"; "omake" + ; "-unrefined" + ; Path.to_string file1 + ; Path.to_string file2 + ] + >>= fun () -> + (* Use "diff" if "patdiff" reported no differences *) + normal_diff () diff --git a/src/diff.mli b/src/diff.mli new file mode 100644 index 000000000000..80d6ecc78488 --- /dev/null +++ b/src/diff.mli @@ -0,0 +1,2 @@ +(** Diff two files that are expected not to match. *) +val print : Path.t -> Path.t -> _ Future.t diff --git a/src/jbuild.ml b/src/jbuild.ml index 9b77817e961f..1fbd16ebc0d9 100644 --- a/src/jbuild.ml +++ b/src/jbuild.ml @@ -66,6 +66,12 @@ let file_in_current_dir sexp = of_sexp_error sexp "file in current directory expected"; fn +let relative_file sexp = + let fn = file sexp in + if not (Filename.is_relative fn) then + of_sexp_error sexp "relative filename expected"; + fn + module Scope = struct type t = { name : string option @@ -926,6 +932,14 @@ module Stanza = struct | Install of Install_conf.t | Alias of Alias_conf.t | Copy_files of Copy_files.t +end + +module Stanzas = struct + type t = Stanza.t list + + type syntax = OCaml | Plain + + open Stanza let rules l = List.map l ~f:(fun x -> Rule x) @@ -934,7 +948,7 @@ module Stanza = struct | None -> [Executables exe] | Some i -> [Executables exe; Install i] - let v1 pkgs = + let rec v1 pkgs : Stanza.t list Sexp.Of_sexp.t = sum [ cstr "library" (Library.v1 pkgs @> nil) (fun x -> [Library x]) ; cstr "executable" (Executables.v1_single pkgs @> nil) execs @@ -951,30 +965,36 @@ module Stanza = struct (fun glob -> [Copy_files {add_line_directive = true; glob}]) (* Just for validation and error messages *) ; cstr "jbuild_version" (Jbuild_version.t @> nil) (fun _ -> []) + ; cstr_loc "include" (relative_file @> nil) (fun loc fn -> + let dir = Filename.dirname loc.start.pos_fname in + let fn = + if dir <> Filename.current_dir_name then + Filename.concat dir fn + else + fn + in + let sexps = Sexp.load ~fname:fn ~mode:Many in + parse pkgs sexps ~default_version:Jbuild_version.V1) ] - let select : Jbuild_version.t -> Scope.t -> t list Sexp.Of_sexp.t = function + and select : Jbuild_version.t -> Scope.t -> Stanza.t list Sexp.Of_sexp.t = function | V1 -> v1 -end - -module Stanzas = struct - type t = Stanza.t list - let parse pkgs sexps = + and parse ?(default_version=Jbuild_version.latest_stable) pkgs sexps = let versions, sexps = List.partition_map sexps ~f:(function - | List (loc, [Atom (_, "jbuild_version"); ver]) -> + | List (loc, [Atom (_, "jbuild_version"); ver]) -> Inl (Jbuild_version.t ver, loc) | sexp -> Inr sexp) in let version = match versions with - | [] -> Jbuild_version.latest_stable + | [] -> default_version | [(v, _)] -> v | _ :: (_, loc) :: _ -> Loc.fail loc "jbuild_version specified too many times" in - List.concat_map sexps ~f:(Stanza.select version pkgs) + List.concat_map sexps ~f:(select version pkgs) let lib_names ts = List.fold_left ts ~init:String_set.empty ~f:(fun acc (_, _, stanzas) -> diff --git a/src/jbuild.mli b/src/jbuild.mli index b905652d7ea8..f092b037f5d2 100644 --- a/src/jbuild.mli +++ b/src/jbuild.mli @@ -252,6 +252,12 @@ end module Stanzas : sig type t = Stanza.t list - val parse : Scope.t -> Sexp.Ast.t list -> t + type syntax = OCaml | Plain + + val parse + : ?default_version:Jbuild_version.t + -> Scope.t + -> Sexp.Ast.t list + -> t val lib_names : (_ * _ * t) list -> String_set.t end diff --git a/test/blackbox-tests/jbuild b/test/blackbox-tests/jbuild index a2ed025c13a4..7ef0da971ef5 100644 --- a/test/blackbox-tests/jbuild +++ b/test/blackbox-tests/jbuild @@ -169,3 +169,10 @@ (action (chdir test-cases/cross-compilation (setenv JBUILDER ${bin:jbuilder} (run ${exe:cram.exe} run.t)))))) + +(alias + ((name runtest) + (deps ((files_recursively_in test-cases/promote))) + (action + (chdir test-cases/promote + (setenv JBUILDER ${bin:jbuilder} (run ${exe:cram.exe} run.t)))))) diff --git a/test/blackbox-tests/test-cases/promote/jbuild b/test/blackbox-tests/test-cases/promote/jbuild new file mode 100644 index 000000000000..f5a126ad585b --- /dev/null +++ b/test/blackbox-tests/test-cases/promote/jbuild @@ -0,0 +1,7 @@ +(jbuild_version 1) + +(rule (with-stdout-to x.gen (echo "toto"))) + +(alias + ((name blah) + (action (promote (x.gen as x))))) diff --git a/test/blackbox-tests/test-cases/promote/run.t b/test/blackbox-tests/test-cases/promote/run.t new file mode 100644 index 000000000000..8f8ffb8b6ecc --- /dev/null +++ b/test/blackbox-tests/test-cases/promote/run.t @@ -0,0 +1,21 @@ + $ echo titi > x + + $ $JBUILDER build --root . -j1 --diff-command false @blah + sh (internal) (exit 1) + /usr/bin/sh -c 'false '\''x'\'' '\''_build/default/x.gen'\''' + [1] + $ cat x + titi + + $ $JBUILDER build --root . -j1 --diff-command false @blah --promote ignore + $ cat x + titi + + $ $JBUILDER build --root . -j1 --diff-command false @blah --promote copy + sh (internal) (exit 1) + /usr/bin/sh -c 'false '\''x'\'' '\''_build/default/x.gen'\''' + Promoting _build/default/x.gen to x. + [1] + $ cat x + toto + $ $JBUILDER build --root . -j1 --diff-command false @blah --promote copy