From 97ff1432df7a56958b3ffd5202129583efbe5b7d Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 24 Apr 2018 13:55:33 +0100 Subject: [PATCH 01/15] First pass at renaming the package to dune --- bin/jbuild | 2 +- bin/main.ml | 8 +- doc/jbuild | 30 ++++- doc/jbuild.inc.dune | 118 ++++++++++++++++++ doc/{jbuild.inc => jbuild.inc.jbuilder} | 0 doc/update-jbuild.sh | 10 +- jbuilder.descr => dune.descr | 0 jbuilder.opam => dune.opam | 0 example/jbuild | 12 +- example/sample-projects/hello_world/run.t | 2 +- .../sample-projects/with-configure-step/run.t | 2 +- src/configurator/jbuild | 2 +- src/jbuild | 5 +- src/main.ml | 2 +- src/ocaml-config/jbuild | 2 +- src/stdune/caml/jbuild | 2 +- src/stdune/jbuild | 2 +- src/usexp/jbuild | 2 +- test/blackbox-tests/cram.mll | 4 +- test/blackbox-tests/gen_tests.ml | 2 +- test/blackbox-tests/jbuild | 2 +- test/blackbox-tests/jbuild.inc | 106 ++++++++-------- .../test-cases/configurator/c_test/jbuild | 2 +- .../test-cases/configurator/config/jbuild | 2 +- .../configurator/import-define/jbuild | 2 +- test/unit-tests/action.mlt | 6 +- test/unit-tests/expect_test.mll | 2 +- test/unit-tests/filename.mlt | 2 +- test/unit-tests/import_dot_map.mlt | 4 +- test/unit-tests/jbuild | 12 +- test/unit-tests/tests.mlt | 11 +- vendor/boot/opamBaseParser.ml | 2 +- vendor/re/src/jbuild | 2 +- 33 files changed, 245 insertions(+), 117 deletions(-) create mode 100644 doc/jbuild.inc.dune rename doc/{jbuild.inc => jbuild.inc.jbuilder} (100%) rename jbuilder.descr => dune.descr (100%) rename jbuilder.opam => dune.opam (100%) diff --git a/bin/jbuild b/bin/jbuild index bfec655054f..0b167d7d69b 100644 --- a/bin/jbuild +++ b/bin/jbuild @@ -1,5 +1,5 @@ (executable ((name main) (public_name jbuilder) - (libraries (unix jbuilder cmdliner)) + (libraries (unix dune cmdliner)) (preprocess no_preprocessing))) diff --git a/bin/main.ml b/bin/main.ml index 68fe877c06d..ac7f5bd907b 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -1,4 +1,4 @@ -open Jbuilder +open Dune open Import open Cmdliner open Fiber.O @@ -70,7 +70,7 @@ let restore_cwd_and_execve common prog argv env = Unix.execve prog argv env module Main = struct - include Jbuilder.Main + include Dune.Main let setup ~log ?external_lib_deps_mode common = setup @@ -85,14 +85,14 @@ module Main = struct end module Log = struct - include Jbuilder.Log + include Dune.Log let create common = Log.create ~display:common.config.display () end module Scheduler = struct - include Jbuilder.Scheduler + include Dune.Scheduler let go ?log ~common fiber = let fiber = diff --git a/doc/jbuild b/doc/jbuild index 2501e3a8f9e..17782108f56 100644 --- a/doc/jbuild +++ b/doc/jbuild @@ -1,5 +1,10 @@ (jbuild_version 1) +(rule + ((targets (dune.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} --help=groff))))) + (rule ((targets (jbuilder.1)) (action (with-stdout-to ${@} @@ -7,7 +12,7 @@ (install ((section man) - (files (jbuilder.1)))) + (files (dune.1 jbuilder.1)))) (rule ((targets (dune-config.5)) @@ -18,12 +23,27 @@ ((section man) (files (dune-config.5)))) -(include jbuild.inc) +(include jbuild.inc.dune) +(include jbuild.inc.jbuilder) + +(rule + ((targets (jbuild.inc.dune.gen)) + (deps ((package dune))) + (action + (with-stdout-to ${@} + (run bash ${path:update-jbuild.sh} dune))))) (rule - (with-stdout-to jbuild.inc.gen - (run bash ${path:update-jbuild.sh} ${bin:jbuilder}))) + ((targets (jbuild.inc.jbuilder.gen)) + (deps ((package dune))) + (action + (with-stdout-to ${@} + (run bash ${path:update-jbuild.sh} jbuilder))))) + +(alias + ((name runtest) + (action (diff jbuild.inc.dune jbuild.inc.dune.gen)))) (alias ((name runtest) - (action (diff jbuild.inc jbuild.inc.gen)))) + (action (diff jbuild.inc.jbuilder jbuild.inc.jbuilder.gen)))) diff --git a/doc/jbuild.inc.dune b/doc/jbuild.inc.dune new file mode 100644 index 00000000000..f90aae57e47 --- /dev/null +++ b/doc/jbuild.inc.dune @@ -0,0 +1,118 @@ + +(rule + ((targets (dune-build.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} build --help=groff))))) + +(install + ((section man) + (files (dune-build.1)))) + +(rule + ((targets (dune-clean.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} clean --help=groff))))) + +(install + ((section man) + (files (dune-clean.1)))) + +(rule + ((targets (dune-exec.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} exec --help=groff))))) + +(install + ((section man) + (files (dune-exec.1)))) + +(rule + ((targets (dune-external-lib-deps.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} external-lib-deps --help=groff))))) + +(install + ((section man) + (files (dune-external-lib-deps.1)))) + +(rule + ((targets (dune-help.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} help --help=groff))))) + +(install + ((section man) + (files (dune-help.1)))) + +(rule + ((targets (dune-install.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} install --help=groff))))) + +(install + ((section man) + (files (dune-install.1)))) + +(rule + ((targets (dune-installed-libraries.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} installed-libraries --help=groff))))) + +(install + ((section man) + (files (dune-installed-libraries.1)))) + +(rule + ((targets (dune-promote.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} promote --help=groff))))) + +(install + ((section man) + (files (dune-promote.1)))) + +(rule + ((targets (dune-rules.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} rules --help=groff))))) + +(install + ((section man) + (files (dune-rules.1)))) + +(rule + ((targets (dune-runtest.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} runtest --help=groff))))) + +(install + ((section man) + (files (dune-runtest.1)))) + +(rule + ((targets (dune-subst.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} subst --help=groff))))) + +(install + ((section man) + (files (dune-subst.1)))) + +(rule + ((targets (dune-uninstall.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} uninstall --help=groff))))) + +(install + ((section man) + (files (dune-uninstall.1)))) + +(rule + ((targets (dune-utop.1)) + (action (with-stdout-to ${@} + (run ${bin:dune} utop --help=groff))))) + +(install + ((section man) + (files (dune-utop.1)))) + diff --git a/doc/jbuild.inc b/doc/jbuild.inc.jbuilder similarity index 100% rename from doc/jbuild.inc rename to doc/jbuild.inc.jbuilder diff --git a/doc/update-jbuild.sh b/doc/update-jbuild.sh index 3ec82dae1df..ae6981a7c40 100755 --- a/doc/update-jbuild.sh +++ b/doc/update-jbuild.sh @@ -4,22 +4,22 @@ set -e -o pipefail -jbuilder=$1 +prog=$1 -CMDS=$($jbuilder --help=plain | \ +CMDS=$($prog --help=plain | \ sed -n '/COMMANDS/,/OPTIONS/p' | sed -En 's/^ ([a-z-]+)/\1/p') for cmd in $CMDS; do cat <>= fun { build_system = bs; _ } -> Build_system.do_build bs - ~request:(Build.path (Path.of_string "_build/default/jbuilder.install"))) + ~request:(Build.path (Path.of_string "_build/default/dune.install"))) in try main () diff --git a/src/ocaml-config/jbuild b/src/ocaml-config/jbuild index 3fa057e438e..fdf0a24d03c 100644 --- a/src/ocaml-config/jbuild +++ b/src/ocaml-config/jbuild @@ -2,6 +2,6 @@ (library ((name ocaml_config) - (public_name jbuilder.ocaml_config) + (public_name dune.ocaml_config) (libraries (stdune usexp)) (synopsis "[Internal] Interpret the output of 'ocamlc -config'"))) diff --git a/src/stdune/caml/jbuild b/src/stdune/caml/jbuild index 04b16834208..389bb77a2ad 100644 --- a/src/stdune/caml/jbuild +++ b/src/stdune/caml/jbuild @@ -1,4 +1,4 @@ (library ((name caml) - (public_name jbuilder.caml) + (public_name dune.caml) (synopsis "[Internal] Wrapped version of the OCaml stdlib"))) diff --git a/src/stdune/jbuild b/src/stdune/jbuild index f79d508be9a..edfecd7bfbf 100644 --- a/src/stdune/jbuild +++ b/src/stdune/jbuild @@ -1,5 +1,5 @@ (library ((name stdune) - (public_name jbuilder.stdune) + (public_name dune.stdune) (synopsis "[Internal] Standard library of Dune") (libraries (caml unix usexp)))) diff --git a/src/usexp/jbuild b/src/usexp/jbuild index 53b46ee96e5..4eb9b73d22e 100644 --- a/src/usexp/jbuild +++ b/src/usexp/jbuild @@ -3,7 +3,7 @@ (library ((name usexp) (synopsis "[Internal] S-expression library") - (public_name jbuilder.usexp))) + (public_name dune.usexp))) (rule (with-stdout-to table.ml.gen (run gen/gen_parser_automaton.exe))) diff --git a/test/blackbox-tests/cram.mll b/test/blackbox-tests/cram.mll index 5fe4cd0ae53..124bf06bc86 100644 --- a/test/blackbox-tests/cram.mll +++ b/test/blackbox-tests/cram.mll @@ -1,7 +1,7 @@ (* Mini implementation of cram tests *) { -open Jbuilder +open Dune open Import type item = @@ -132,7 +132,7 @@ and postprocess tbl b = parse end; Test_common.run_expect_test expect_test ~f:(fun file_contents lexbuf -> let items = file lexbuf in - let temp_file = Filename.temp_file "jbuilder-test" ".output" in + let temp_file = Filename.temp_file "dune-test" ".output" in at_exit (fun () -> Sys.remove temp_file); let buf = Buffer.create (String.length file_contents + 1024) in List.iter items ~f:(function diff --git a/test/blackbox-tests/gen_tests.ml b/test/blackbox-tests/gen_tests.ml index c6d8e93fbcc..505bc1e04d4 100644 --- a/test/blackbox-tests/gen_tests.ml +++ b/test/blackbox-tests/gen_tests.ml @@ -79,7 +79,7 @@ module Test = struct ; action ] in alias t.name ~deps:( - [ Sexp.strings ["package"; "jbuilder"] + [ Sexp.strings ["package"; "dune"] ; Sexp.strings [ "files_recursively_in" ; sprintf "test-cases/%s" t.name] ] diff --git a/test/blackbox-tests/jbuild b/test/blackbox-tests/jbuild index da7ec349c73..52f7e509cb1 100644 --- a/test/blackbox-tests/jbuild +++ b/test/blackbox-tests/jbuild @@ -8,7 +8,7 @@ (executable ((name cram) (modules (cram)) - (libraries (test_common platform jbuilder configurator)))) + (libraries (test_common platform dune configurator)))) (ocamllex (cram)) diff --git a/test/blackbox-tests/jbuild.inc b/test/blackbox-tests/jbuild.inc index 1eb4e6a5d4b..ed9ac7b0af9 100644 --- a/test/blackbox-tests/jbuild.inc +++ b/test/blackbox-tests/jbuild.inc @@ -1,6 +1,6 @@ (alias ((name aliases) - (deps ((package jbuilder) (files_recursively_in test-cases/aliases))) + (deps ((package dune) (files_recursively_in test-cases/aliases))) (action (chdir test-cases/aliases @@ -8,7 +8,7 @@ (alias ((name byte-code-only) - (deps ((package jbuilder) (files_recursively_in test-cases/byte-code-only))) + (deps ((package dune) (files_recursively_in test-cases/byte-code-only))) (action (chdir test-cases/byte-code-only @@ -16,7 +16,7 @@ (alias ((name c-stubs) - (deps ((package jbuilder) (files_recursively_in test-cases/c-stubs))) + (deps ((package dune) (files_recursively_in test-cases/c-stubs))) (action (chdir test-cases/c-stubs @@ -24,7 +24,7 @@ (alias ((name configurator) - (deps ((package jbuilder) (files_recursively_in test-cases/configurator))) + (deps ((package dune) (files_recursively_in test-cases/configurator))) (action (chdir test-cases/configurator @@ -34,7 +34,7 @@ (alias ((name copy_files) - (deps ((package jbuilder) (files_recursively_in test-cases/copy_files))) + (deps ((package dune) (files_recursively_in test-cases/copy_files))) (action (chdir test-cases/copy_files @@ -42,8 +42,7 @@ (alias ((name cross-compilation) - (deps - ((package jbuilder) (files_recursively_in test-cases/cross-compilation))) + (deps ((package dune) (files_recursively_in test-cases/cross-compilation))) (action (chdir test-cases/cross-compilation @@ -52,8 +51,7 @@ (alias ((name depend-on-the-universe) (deps - ((package jbuilder) - (files_recursively_in test-cases/depend-on-the-universe))) + ((package dune) (files_recursively_in test-cases/depend-on-the-universe))) (action (chdir test-cases/depend-on-the-universe @@ -62,8 +60,7 @@ (alias ((name exclude-missing-module) (deps - ((package jbuilder) - (files_recursively_in test-cases/exclude-missing-module))) + ((package dune) (files_recursively_in test-cases/exclude-missing-module))) (action (chdir test-cases/exclude-missing-module @@ -71,7 +68,7 @@ (alias ((name exec-cmd) - (deps ((package jbuilder) (files_recursively_in test-cases/exec-cmd))) + (deps ((package dune) (files_recursively_in test-cases/exec-cmd))) (action (chdir test-cases/exec-cmd @@ -79,7 +76,7 @@ (alias ((name findlib) - (deps ((package jbuilder) (files_recursively_in test-cases/findlib))) + (deps ((package dune) (files_recursively_in test-cases/findlib))) (action (chdir test-cases/findlib @@ -87,7 +84,7 @@ (alias ((name force-test) - (deps ((package jbuilder) (files_recursively_in test-cases/force-test))) + (deps ((package dune) (files_recursively_in test-cases/force-test))) (action (chdir test-cases/force-test @@ -96,8 +93,7 @@ (alias ((name gen-opam-install-file) (deps - ((package jbuilder) - (files_recursively_in test-cases/gen-opam-install-file))) + ((package dune) (files_recursively_in test-cases/gen-opam-install-file))) (action (chdir test-cases/gen-opam-install-file @@ -105,7 +101,7 @@ (alias ((name github20) - (deps ((package jbuilder) (files_recursively_in test-cases/github20))) + (deps ((package dune) (files_recursively_in test-cases/github20))) (action (chdir test-cases/github20 @@ -113,7 +109,7 @@ (alias ((name github24) - (deps ((package jbuilder) (files_recursively_in test-cases/github24))) + (deps ((package dune) (files_recursively_in test-cases/github24))) (action (chdir test-cases/github24 @@ -121,7 +117,7 @@ (alias ((name github25) - (deps ((package jbuilder) (files_recursively_in test-cases/github25))) + (deps ((package dune) (files_recursively_in test-cases/github25))) (action (setenv OCAMLPATH @@ -132,7 +128,7 @@ (alias ((name github534) - (deps ((package jbuilder) (files_recursively_in test-cases/github534))) + (deps ((package dune) (files_recursively_in test-cases/github534))) (action (chdir test-cases/github534 @@ -140,7 +136,7 @@ (alias ((name github568) - (deps ((package jbuilder) (files_recursively_in test-cases/github568))) + (deps ((package dune) (files_recursively_in test-cases/github568))) (action (chdir test-cases/github568 @@ -148,7 +144,7 @@ (alias ((name github597) - (deps ((package jbuilder) (files_recursively_in test-cases/github597))) + (deps ((package dune) (files_recursively_in test-cases/github597))) (action (chdir test-cases/github597 @@ -156,7 +152,7 @@ (alias ((name github644) - (deps ((package jbuilder) (files_recursively_in test-cases/github644))) + (deps ((package dune) (files_recursively_in test-cases/github644))) (action (chdir test-cases/github644 @@ -164,7 +160,7 @@ (alias ((name github660) - (deps ((package jbuilder) (files_recursively_in test-cases/github660))) + (deps ((package dune) (files_recursively_in test-cases/github660))) (action (chdir test-cases/github660 @@ -183,7 +179,7 @@ (alias ((name include-loop) - (deps ((package jbuilder) (files_recursively_in test-cases/include-loop))) + (deps ((package dune) (files_recursively_in test-cases/include-loop))) (action (chdir test-cases/include-loop @@ -191,7 +187,7 @@ (alias ((name inline_tests) - (deps ((package jbuilder) (files_recursively_in test-cases/inline_tests))) + (deps ((package dune) (files_recursively_in test-cases/inline_tests))) (action (chdir test-cases/inline_tests @@ -200,7 +196,7 @@ (alias ((name installable-dup-private-libs) (deps - ((package jbuilder) + ((package dune) (files_recursively_in test-cases/installable-dup-private-libs))) (action (chdir @@ -209,7 +205,7 @@ (alias ((name intf-only) - (deps ((package jbuilder) (files_recursively_in test-cases/intf-only))) + (deps ((package dune) (files_recursively_in test-cases/intf-only))) (action (chdir test-cases/intf-only @@ -217,7 +213,7 @@ (alias ((name js_of_ocaml) - (deps ((package jbuilder) (files_recursively_in test-cases/js_of_ocaml))) + (deps ((package dune) (files_recursively_in test-cases/js_of_ocaml))) (action (setenv NODE @@ -228,7 +224,7 @@ (alias ((name lib-available) - (deps ((package jbuilder) (files_recursively_in test-cases/lib-available))) + (deps ((package dune) (files_recursively_in test-cases/lib-available))) (action (chdir test-cases/lib-available @@ -236,7 +232,7 @@ (alias ((name loop) - (deps ((package jbuilder) (files_recursively_in test-cases/loop))) + (deps ((package dune) (files_recursively_in test-cases/loop))) (action (chdir test-cases/loop @@ -244,7 +240,7 @@ (alias ((name menhir) - (deps ((package jbuilder) (files_recursively_in test-cases/menhir))) + (deps ((package dune) (files_recursively_in test-cases/menhir))) (action (chdir test-cases/menhir @@ -252,7 +248,7 @@ (alias ((name merlin-tests) - (deps ((package jbuilder) (files_recursively_in test-cases/merlin-tests))) + (deps ((package dune) (files_recursively_in test-cases/merlin-tests))) (action (chdir test-cases/merlin-tests @@ -260,7 +256,7 @@ (alias ((name meta-gen) - (deps ((package jbuilder) (files_recursively_in test-cases/meta-gen))) + (deps ((package dune) (files_recursively_in test-cases/meta-gen))) (action (chdir test-cases/meta-gen @@ -268,7 +264,7 @@ (alias ((name misc) - (deps ((package jbuilder) (files_recursively_in test-cases/misc))) + (deps ((package dune) (files_recursively_in test-cases/misc))) (action (chdir test-cases/misc @@ -277,8 +273,7 @@ (alias ((name multiple-private-libs) (deps - ((package jbuilder) - (files_recursively_in test-cases/multiple-private-libs))) + ((package dune) (files_recursively_in test-cases/multiple-private-libs))) (action (chdir test-cases/multiple-private-libs @@ -288,7 +283,7 @@ (alias ((name null-dep) - (deps ((package jbuilder) (files_recursively_in test-cases/null-dep))) + (deps ((package dune) (files_recursively_in test-cases/null-dep))) (action (chdir test-cases/null-dep @@ -296,7 +291,7 @@ (alias ((name ocaml-syntax) - (deps ((package jbuilder) (files_recursively_in test-cases/ocaml-syntax))) + (deps ((package dune) (files_recursively_in test-cases/ocaml-syntax))) (action (chdir test-cases/ocaml-syntax @@ -305,8 +300,7 @@ (alias ((name ocamldep-multi-stanzas) (deps - ((package jbuilder) - (files_recursively_in test-cases/ocamldep-multi-stanzas))) + ((package dune) (files_recursively_in test-cases/ocamldep-multi-stanzas))) (action (chdir test-cases/ocamldep-multi-stanzas @@ -314,7 +308,7 @@ (alias ((name odoc) - (deps ((package jbuilder) (files_recursively_in test-cases/odoc))) + (deps ((package dune) (files_recursively_in test-cases/odoc))) (action (chdir test-cases/odoc @@ -324,8 +318,7 @@ (alias ((name odoc-unique-mlds) - (deps - ((package jbuilder) (files_recursively_in test-cases/odoc-unique-mlds))) + (deps ((package dune) (files_recursively_in test-cases/odoc-unique-mlds))) (action (chdir test-cases/odoc-unique-mlds @@ -335,7 +328,7 @@ (alias ((name output-obj) - (deps ((package jbuilder) (files_recursively_in test-cases/output-obj))) + (deps ((package dune) (files_recursively_in test-cases/output-obj))) (action (chdir test-cases/output-obj @@ -352,7 +345,7 @@ (alias ((name package-dep) - (deps ((package jbuilder) (files_recursively_in test-cases/package-dep))) + (deps ((package dune) (files_recursively_in test-cases/package-dep))) (action (chdir test-cases/package-dep @@ -360,7 +353,7 @@ (alias ((name ppx-rewriter) - (deps ((package jbuilder) (files_recursively_in test-cases/ppx-rewriter))) + (deps ((package dune) (files_recursively_in test-cases/ppx-rewriter))) (action (chdir test-cases/ppx-rewriter @@ -371,8 +364,7 @@ (alias ((name private-public-overlap) (deps - ((package jbuilder) - (files_recursively_in test-cases/private-public-overlap))) + ((package dune) (files_recursively_in test-cases/private-public-overlap))) (action (chdir test-cases/private-public-overlap @@ -380,7 +372,7 @@ (alias ((name promote) - (deps ((package jbuilder) (files_recursively_in test-cases/promote))) + (deps ((package dune) (files_recursively_in test-cases/promote))) (action (chdir test-cases/promote @@ -388,7 +380,7 @@ (alias ((name quoting) - (deps ((package jbuilder) (files_recursively_in test-cases/quoting))) + (deps ((package dune) (files_recursively_in test-cases/quoting))) (action (chdir test-cases/quoting @@ -396,7 +388,7 @@ (alias ((name reason) - (deps ((package jbuilder) (files_recursively_in test-cases/reason))) + (deps ((package dune) (files_recursively_in test-cases/reason))) (action (chdir test-cases/reason @@ -404,7 +396,7 @@ (alias ((name redirections) - (deps ((package jbuilder) (files_recursively_in test-cases/redirections))) + (deps ((package dune) (files_recursively_in test-cases/redirections))) (action (chdir test-cases/redirections @@ -412,7 +404,7 @@ (alias ((name scope-bug) - (deps ((package jbuilder) (files_recursively_in test-cases/scope-bug))) + (deps ((package dune) (files_recursively_in test-cases/scope-bug))) (action (chdir test-cases/scope-bug @@ -420,7 +412,7 @@ (alias ((name scope-ppx-bug) - (deps ((package jbuilder) (files_recursively_in test-cases/scope-ppx-bug))) + (deps ((package dune) (files_recursively_in test-cases/scope-ppx-bug))) (action (chdir test-cases/scope-ppx-bug @@ -428,7 +420,7 @@ (alias ((name select) - (deps ((package jbuilder) (files_recursively_in test-cases/select))) + (deps ((package dune) (files_recursively_in test-cases/select))) (action (chdir test-cases/select @@ -436,7 +428,7 @@ (alias ((name utop) - (deps ((package jbuilder) (files_recursively_in test-cases/utop))) + (deps ((package dune) (files_recursively_in test-cases/utop))) (action (chdir test-cases/utop diff --git a/test/blackbox-tests/test-cases/configurator/c_test/jbuild b/test/blackbox-tests/test-cases/configurator/c_test/jbuild index 0f63b54a30c..422628bfc75 100644 --- a/test/blackbox-tests/test-cases/configurator/c_test/jbuild +++ b/test/blackbox-tests/test-cases/configurator/c_test/jbuild @@ -2,4 +2,4 @@ (executable ((name run) - (libraries (jbuilder.configurator)))) + (libraries (dune.configurator)))) diff --git a/test/blackbox-tests/test-cases/configurator/config/jbuild b/test/blackbox-tests/test-cases/configurator/config/jbuild index 0f63b54a30c..422628bfc75 100644 --- a/test/blackbox-tests/test-cases/configurator/config/jbuild +++ b/test/blackbox-tests/test-cases/configurator/config/jbuild @@ -2,4 +2,4 @@ (executable ((name run) - (libraries (jbuilder.configurator)))) + (libraries (dune.configurator)))) diff --git a/test/blackbox-tests/test-cases/configurator/import-define/jbuild b/test/blackbox-tests/test-cases/configurator/import-define/jbuild index 0f63b54a30c..422628bfc75 100644 --- a/test/blackbox-tests/test-cases/configurator/import-define/jbuild +++ b/test/blackbox-tests/test-cases/configurator/import-define/jbuild @@ -2,4 +2,4 @@ (executable ((name run) - (libraries (jbuilder.configurator)))) + (libraries (dune.configurator)))) diff --git a/test/unit-tests/action.mlt b/test/unit-tests/action.mlt index a4a28804c8f..45ba02a76b3 100644 --- a/test/unit-tests/action.mlt +++ b/test/unit-tests/action.mlt @@ -2,7 +2,7 @@ #warnings "-40";; -open Jbuilder;; +open Dune;; open Import;; open Action.Infer.Outcome;; @@ -12,8 +12,8 @@ let infer (a : Action.t) = (List.map (Path.Set.to_list x.deps) ~f:Path.to_string, List.map (Path.Set.to_list x.targets) ~f:Path.to_string) [%%expect{| -val p : ?error_loc:Usexp.Loc.t -> string -> Jbuilder.Import.Path.t = -val infer : Jbuilder.Action.t -> string list * string list = +val p : ?error_loc:Usexp.Loc.t -> string -> Dune.Import.Path.t = +val infer : Dune.Action.t -> string list * string list = |}] infer (Copy (p "a", p "b"));; diff --git a/test/unit-tests/expect_test.mll b/test/unit-tests/expect_test.mll index 51dec32eaf5..806ca671e64 100644 --- a/test/unit-tests/expect_test.mll +++ b/test/unit-tests/expect_test.mll @@ -45,7 +45,7 @@ let main () = Toploop.initialize_toplevel_env (); List.iter [ "src/stdune/.stdune.objs" - ; "src/.jbuilder.objs" + ; "src/.dune.objs" ] ~f:Topdirs.dir_directory; diff --git a/test/unit-tests/filename.mlt b/test/unit-tests/filename.mlt index 2c53ea8631d..96f8b9ec1bf 100644 --- a/test/unit-tests/filename.mlt +++ b/test/unit-tests/filename.mlt @@ -2,7 +2,7 @@ #warnings "-40";; -open Jbuilder;; +open Dune;; open Import;; Filename.extension "toto.titi";; diff --git a/test/unit-tests/import_dot_map.mlt b/test/unit-tests/import_dot_map.mlt index a82fc6d8758..1f2f70a6878 100644 --- a/test/unit-tests/import_dot_map.mlt +++ b/test/unit-tests/import_dot_map.mlt @@ -2,7 +2,7 @@ #warnings "-40";; -open Jbuilder;; +open Dune;; open Import;; (* Check that [of_alist_multi] groups elements in the right order *) @@ -15,6 +15,6 @@ String.Map.of_list_multi ] |> String.Map.to_list;; [%%expect{| -- : (Jbuilder.Import.String.Map.key * int list) list = +- : (Dune.Import.String.Map.key * int list) list = [("a", [1; 2; 3]); ("b", [1; 2])] |}] diff --git a/test/unit-tests/jbuild b/test/unit-tests/jbuild index eae5a2813b6..9764b1c4b6e 100644 --- a/test/unit-tests/jbuild +++ b/test/unit-tests/jbuild @@ -5,7 +5,7 @@ (modules (expect_test)) (link_flags (-linkall)) (modes (byte)) - (libraries (unix jbuilder compiler-libs.toplevel test_common)))) + (libraries (unix dune compiler-libs.toplevel test_common)))) (ocamllex (expect_test)) @@ -21,7 +21,7 @@ (alias ((name runtest) (deps (tests.mlt - (glob_files ${SCOPE_ROOT}/src/.jbuilder.objs/*.cmi) + (glob_files ${SCOPE_ROOT}/src/.dune.objs/*.cmi) (glob_files ${SCOPE_ROOT}/src/stdune/.stdune.objs/*.cmi) (files_recursively_in toolchain.d) (files_recursively_in findlib-db))) @@ -33,7 +33,7 @@ (alias ((name runtest) (deps (filename.mlt - (glob_files ${SCOPE_ROOT}/src/.jbuilder.objs/*.cmi) + (glob_files ${SCOPE_ROOT}/src/.dune.objs/*.cmi) (glob_files ${SCOPE_ROOT}/src/stdune/.stdune.objs/*.cmi))) (action (chdir ${SCOPE_ROOT} (progn @@ -43,7 +43,7 @@ (alias ((name runtest) (deps (import_dot_map.mlt - (glob_files ${SCOPE_ROOT}/src/.jbuilder.objs/*.cmi) + (glob_files ${SCOPE_ROOT}/src/.dune.objs/*.cmi) (glob_files ${SCOPE_ROOT}/src/stdune/.stdune.objs/*.cmi))) (action (chdir ${SCOPE_ROOT} (progn @@ -53,7 +53,7 @@ (alias ((name runtest) (deps (action.mlt - (glob_files ${SCOPE_ROOT}/src/.jbuilder.objs/*.cmi) + (glob_files ${SCOPE_ROOT}/src/.dune.objs/*.cmi) (glob_files ${SCOPE_ROOT}/src/stdune/.stdune.objs/*.cmi))) (action (chdir ${SCOPE_ROOT} (progn @@ -63,7 +63,7 @@ (alias ((name runtest) (deps (path.mlt - (glob_files ${SCOPE_ROOT}/src/.jbuilder.objs/*.cmi) + (glob_files ${SCOPE_ROOT}/src/.dune.objs/*.cmi) (glob_files ${SCOPE_ROOT}/src/stdune/.stdune.objs/*.cmi))) (action (chdir ${SCOPE_ROOT} (progn diff --git a/test/unit-tests/tests.mlt b/test/unit-tests/tests.mlt index c3fafb4e68a..55fc30a215c 100644 --- a/test/unit-tests/tests.mlt +++ b/test/unit-tests/tests.mlt @@ -2,7 +2,7 @@ #warnings "-40";; -open Jbuilder +open Dune open Import let print_pkg ppf pkg = @@ -13,8 +13,7 @@ let print_pkg ppf pkg = #install_printer String_map.pp;; [%%expect{| -val print_pkg : Format.formatter -> Jbuilder.Findlib.Package.t -> unit = - +val print_pkg : Format.formatter -> Dune.Findlib.Package.t -> unit = |}] let findlib = @@ -25,7 +24,7 @@ let findlib = ;; [%%expect{| -val findlib : Jbuilder.Findlib.t = +val findlib : Dune.Findlib.t = |}] let pkg = @@ -34,7 +33,7 @@ let pkg = | Error _ -> assert false;; [%%expect{| -val pkg : Jbuilder.Findlib.Package.t = +val pkg : Dune.Findlib.Package.t = |}] (* "foo" should depend on "baz" *) @@ -56,7 +55,7 @@ let meta = |> Meta.load ~name:"foo" [%%expect{| -val meta : Jbuilder.Meta.Simplified.t = +val meta : Dune.Meta.Simplified.t = { name = "foo" ; vars = (requires = diff --git a/vendor/boot/opamBaseParser.ml b/vendor/boot/opamBaseParser.ml index 434b59b37db..b90785758fa 100644 --- a/vendor/boot/opamBaseParser.ml +++ b/vendor/boot/opamBaseParser.ml @@ -1,6 +1,6 @@ open OpamParserTypes let main _lex _lexbuf fn = - assert (fn = "jbuilder.opam"); + assert (fn = "dune.opam"); { file_contents = [] ; file_name = fn } diff --git a/vendor/re/src/jbuild b/vendor/re/src/jbuild index b24a23ef2a9..1f311e23ed1 100644 --- a/vendor/re/src/jbuild +++ b/vendor/re/src/jbuild @@ -3,4 +3,4 @@ (library ((name re) (flags (:standard -w -50)) - (synopsis "Internal Jbuilder library, do not use!"))) + (synopsis "Internal Dune library, do not use!"))) From 2120a6a5268ff5e01e8f973dab63eed80df2fbf1 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 24 Apr 2018 14:39:58 +0100 Subject: [PATCH 02/15] Build and install two binaries: dune and jbuilder --- Makefile | 2 +- bin/jbuild | 6 +- bin/main.ml | 2657 +++++++++++++++++++++-------------------- bin/main.mli | 4 +- bin/main_dune.ml | 1 + bin/main_dune.mli | 1 + bin/main_jbuilder.ml | 1 + bin/main_jbuilder.mli | 1 + 8 files changed, 1344 insertions(+), 1329 deletions(-) create mode 100644 bin/main_dune.ml create mode 100644 bin/main_dune.mli create mode 100644 bin/main_jbuilder.ml create mode 100644 bin/main_jbuilder.mli diff --git a/Makefile b/Makefile index 1b08bf0d0fe..cde32d45d23 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ INSTALL_ARGS := $(if $(PREFIX),--prefix $(PREFIX),) -BIN := ./_build/default/bin/main.exe +BIN := ./_build/default/bin/main_dune.exe -include Makefile.dev diff --git a/bin/jbuild b/bin/jbuild index 0b167d7d69b..92690f41c1d 100644 --- a/bin/jbuild +++ b/bin/jbuild @@ -1,5 +1,5 @@ -(executable - ((name main) - (public_name jbuilder) +(executables + ((names (main_dune main_jbuilder)) + (public_names ( dune jbuilder)) (libraries (unix dune cmdliner)) (preprocess no_preprocessing))) diff --git a/bin/main.ml b/bin/main.ml index ac7f5bd907b..f00e4700295 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -1,738 +1,746 @@ -open Dune -open Import -open Cmdliner -open Fiber.O +type which = Dune | Jbuilder -(* Things in src/ don't depend on cmdliner to speed up the bootstrap, so we set this - reference here *) -let () = suggest_function := Cmdliner_suggest.value +module Make(M : sig val which : which end) = struct + open Dune + open Import + open Cmdliner + open Fiber.O -type common = - { debug_dep_path : bool - ; debug_findlib : bool - ; debug_backtraces : bool - ; dev_mode : bool - ; workspace_file : string option - ; root : string - ; target_prefix : string - ; only_packages : Package.Name.Set.t option - ; capture_outputs : bool - ; x : string option - ; diff_command : string option - ; auto_promote : bool - ; force : bool - ; ignore_promoted_rules : bool - ; (* Original arguments for the external-lib-deps hint *) - orig_args : string list - ; config : Config.t - } + (* Things in src/ don't depend on cmdliner to speed up the + bootstrap, so we set this reference here *) + let () = suggest_function := Cmdliner_suggest.value -let prefix_target common s = common.target_prefix ^ s + let program_name = + match M.which with + | Jbuilder -> "jbuilder" + | Dune -> "dune" -let set_common c ~targets = - Clflags.debug_dep_path := c.debug_dep_path; - Clflags.debug_findlib := c.debug_findlib; - Clflags.debug_backtraces := c.debug_backtraces; - Clflags.dev_mode := c.dev_mode; - Clflags.capture_outputs := c.capture_outputs; - if c.root <> Filename.current_dir_name then - Sys.chdir c.root; - Clflags.workspace_root := Sys.getcwd (); - Clflags.diff_command := c.diff_command; - Clflags.auto_promote := c.auto_promote; - Clflags.force := c.force; - Clflags.external_lib_deps_hint := - List.concat - [ ["jbuilder"; "external-lib-deps"; "--missing"] - ; c.orig_args - ; targets - ] + type common = + { debug_dep_path : bool + ; debug_findlib : bool + ; debug_backtraces : bool + ; dev_mode : bool + ; workspace_file : string option + ; root : string + ; target_prefix : string + ; only_packages : Package.Name.Set.t option + ; capture_outputs : bool + ; x : string option + ; diff_command : string option + ; auto_promote : bool + ; force : bool + ; ignore_promoted_rules : bool + ; (* Original arguments for the external-lib-deps hint *) + orig_args : string list + ; config : Config.t + } -let restore_cwd_and_execve common prog argv env = - let env = Env.to_unix env in - let prog = - if Filename.is_relative prog then - Filename.concat common.root prog - else - prog - in - Sys.chdir initial_cwd; - if Sys.win32 then - let pid = Unix.create_process_env prog argv env - Unix.stdin Unix.stdout Unix.stderr - in - match snd (Unix.waitpid [] pid) with - | WEXITED 0 -> () - | WEXITED n -> exit n - | WSIGNALED _ -> exit 255 - | WSTOPPED _ -> assert false - else - Unix.execve prog argv env + let prefix_target common s = common.target_prefix ^ s -module Main = struct - include Dune.Main + let set_common c ~targets = + Clflags.debug_dep_path := c.debug_dep_path; + Clflags.debug_findlib := c.debug_findlib; + Clflags.debug_backtraces := c.debug_backtraces; + Clflags.dev_mode := c.dev_mode; + Clflags.capture_outputs := c.capture_outputs; + if c.root <> Filename.current_dir_name then + Sys.chdir c.root; + Clflags.workspace_root := Sys.getcwd (); + Clflags.diff_command := c.diff_command; + Clflags.auto_promote := c.auto_promote; + Clflags.force := c.force; + Clflags.external_lib_deps_hint := + List.concat + [ [program_name; "external-lib-deps"; "--missing"] + ; c.orig_args + ; targets + ] - let setup ~log ?external_lib_deps_mode common = - setup - ~log - ?workspace_file:(Option.map ~f:Path.of_string common.workspace_file) - ?only_packages:common.only_packages - ?external_lib_deps_mode - ?x:common.x - ~ignore_promoted_rules:common.ignore_promoted_rules - ~capture_outputs:common.capture_outputs - () -end + let restore_cwd_and_execve common prog argv env = + let env = Env.to_unix env in + let prog = + if Filename.is_relative prog then + Filename.concat common.root prog + else + prog + in + Sys.chdir initial_cwd; + if Sys.win32 then + let pid = Unix.create_process_env prog argv env + Unix.stdin Unix.stdout Unix.stderr + in + match snd (Unix.waitpid [] pid) with + | WEXITED 0 -> () + | WEXITED n -> exit n + | WSIGNALED _ -> exit 255 + | WSTOPPED _ -> assert false + else + Unix.execve prog argv env -module Log = struct - include Dune.Log + module Main = struct + include Dune.Main - let create common = - Log.create ~display:common.config.display () -end + let setup ~log ?external_lib_deps_mode common = + setup + ~log + ?workspace_file:(Option.map ~f:Path.of_string common.workspace_file) + ?only_packages:common.only_packages + ?external_lib_deps_mode + ?x:common.x + ~ignore_promoted_rules:common.ignore_promoted_rules + ~capture_outputs:common.capture_outputs + () + end -module Scheduler = struct - include Dune.Scheduler + module Log = struct + include Dune.Log - let go ?log ~common fiber = - let fiber = - Main.set_concurrency ?log common.config - >>= fun () -> - fiber - in - Scheduler.go ?log ~config:common.config fiber -end + let create common = + Log.create ~display:common.config.display () + end -type target = - | File of Path.t - | Alias_rec of Path.t + module Scheduler = struct + include Dune.Scheduler -let request_of_targets (setup : Main.setup) targets = - let open Build.O in - let contexts = List.map setup.contexts ~f:(fun c -> c.Context.name) in - List.fold_left targets ~init:(Build.return ()) ~f:(fun acc target -> - acc >>> - match target with - | File path -> Build.path path - | Alias_rec path -> - let dir = Path.parent path in - let name = Path.basename path in - let contexts, dir = - match Path.extract_build_context dir with - | None -> (contexts, dir) - | Some ("install", _) -> - die "Invalid alias: %s.\n\ - There are no aliases in _build/install." - (Path.to_string_maybe_quoted path) - | Some (ctx, dir) -> ([ctx], dir) + let go ?log ~common fiber = + let fiber = + Main.set_concurrency ?log common.config + >>= fun () -> + fiber in - Build_system.Alias.dep_rec_multi_contexts ~dir ~name - ~file_tree:setup.file_tree ~contexts) + Scheduler.go ?log ~config:common.config fiber + end + + type target = + | File of Path.t + | Alias_rec of Path.t + + let request_of_targets (setup : Main.setup) targets = + let open Build.O in + let contexts = List.map setup.contexts ~f:(fun c -> c.Context.name) in + List.fold_left targets ~init:(Build.return ()) ~f:(fun acc target -> + acc >>> + match target with + | File path -> Build.path path + | Alias_rec path -> + let dir = Path.parent path in + let name = Path.basename path in + let contexts, dir = + match Path.extract_build_context dir with + | None -> (contexts, dir) + | Some ("install", _) -> + die "Invalid alias: %s.\n\ + There are no aliases in _build/install." + (Path.to_string_maybe_quoted path) + | Some (ctx, dir) -> ([ctx], dir) + in + Build_system.Alias.dep_rec_multi_contexts ~dir ~name + ~file_tree:setup.file_tree ~contexts) -let do_build (setup : Main.setup) targets = - Build_system.do_build setup.build_system - ~request:(request_of_targets setup targets) + let do_build (setup : Main.setup) targets = + Build_system.do_build setup.build_system + ~request:(request_of_targets setup targets) -let find_root () = - let cwd = Sys.getcwd () in - let rec loop counter ~candidates ~to_cwd dir = - let files = Sys.readdir dir |> Array.to_list |> String.Set.of_list in - if String.Set.mem files "jbuild-workspace" then - cont counter ~candidates:((0, dir, to_cwd) :: candidates) dir ~to_cwd - else if String.Set.exists files ~f:(fun fn -> + let find_root () = + let cwd = Sys.getcwd () in + let rec loop counter ~candidates ~to_cwd dir = + let files = Sys.readdir dir |> Array.to_list |> String.Set.of_list in + if String.Set.mem files "jbuild-workspace" then + cont counter ~candidates:((0, dir, to_cwd) :: candidates) dir ~to_cwd + else if String.Set.exists files ~f:(fun fn -> String.is_prefix fn ~prefix:"jbuild-workspace") then - cont counter ~candidates:((1, dir, to_cwd) :: candidates) dir ~to_cwd - else - cont counter ~candidates dir ~to_cwd - and cont counter ~candidates ~to_cwd dir = - if counter > String.length cwd then - candidates - else - let parent = Filename.dirname dir in - if parent = dir then + cont counter ~candidates:((1, dir, to_cwd) :: candidates) dir ~to_cwd + else + cont counter ~candidates dir ~to_cwd + and cont counter ~candidates ~to_cwd dir = + if counter > String.length cwd then candidates else - let base = Filename.basename dir in - loop (counter + 1) parent ~candidates ~to_cwd:(base :: to_cwd) - in - match loop 0 ~candidates:[] ~to_cwd:[] cwd with - | [] -> (cwd, []) - | l -> - let lowest_priority = - List.fold_left l ~init:max_int ~f:(fun acc (prio, _, _) -> - min acc prio) + let parent = Filename.dirname dir in + if parent = dir then + candidates + else + let base = Filename.basename dir in + loop (counter + 1) parent ~candidates ~to_cwd:(base :: to_cwd) in - match List.find l ~f:(fun (prio, _, _) -> prio = lowest_priority) with - | None -> assert false - | Some (_, dir, to_cwd) -> (dir, to_cwd) + match loop 0 ~candidates:[] ~to_cwd:[] cwd with + | [] -> (cwd, []) + | l -> + let lowest_priority = + List.fold_left l ~init:max_int ~f:(fun acc (prio, _, _) -> + min acc prio) + in + match List.find l ~f:(fun (prio, _, _) -> prio = lowest_priority) with + | None -> assert false + | Some (_, dir, to_cwd) -> (dir, to_cwd) -let package_name = - Arg.conv ((fun p -> Ok (Package.Name.of_string p)), Package.Name.pp) + let package_name = + Arg.conv ((fun p -> Ok (Package.Name.of_string p)), Package.Name.pp) -let common_footer = - `Blocks - [ `S "BUGS" - ; `P "Check bug reports at https://github.com/ocaml/dune/issues" - ] + let common_footer = + `Blocks + [ `S "BUGS" + ; `P "Check bug reports at https://github.com/ocaml/dune/issues" + ] -let copts_sect = "COMMON OPTIONS" -let help_secs = - [ `S copts_sect - ; `P "These options are common to all commands." - ; `S "MORE HELP" - ; `P "Use `$(mname) $(i,COMMAND) --help' for help on a single command." - ; common_footer - ] + let copts_sect = "COMMON OPTIONS" + let help_secs = + [ `S copts_sect + ; `P "These options are common to all commands." + ; `S "MORE HELP" + ; `P "Use `$(mname) $(i,COMMAND) --help' for help on a single command." + ; common_footer + ] -type config_file = - | No_config - | Default - | This of Path.t + type config_file = + | No_config + | Default + | This of Path.t -let incompatible a b = - `Error (true, - sprintf - "Cannot use %s and %s simultaneously" - a b) + let incompatible a b = + `Error (true, + sprintf + "Cannot use %s and %s simultaneously" + a b) -let common = - let dump_opt name value = - match value with - | None -> [] - | Some s -> [name; s] - in - let make - concurrency - debug_dep_path - debug_findlib - debug_backtraces - dev_mode - no_buffer - workspace_file - diff_command - auto_promote - force - (root, - only_packages, - ignore_promoted_rules, - config_file, - orig) - x - display - = - let root, to_cwd = - match root with - | Some dn -> (dn, []) - | None -> - if Config.inside_dune then - (".", []) - else - find_root () + let common = + let dump_opt name value = + match value with + | None -> [] + | Some s -> [name; s] in - let orig_args = - List.concat - [ if dev_mode then ["--dev"] else [] - ; dump_opt "--workspace" workspace_file - ; orig - ] + let make + concurrency + debug_dep_path + debug_findlib + debug_backtraces + dev_mode + no_buffer + workspace_file + diff_command + auto_promote + force + (root, + only_packages, + ignore_promoted_rules, + config_file, + orig) + x + display + = + let root, to_cwd = + match root with + | Some dn -> (dn, []) + | None -> + if Config.inside_dune then + (".", []) + else + find_root () + in + let orig_args = + List.concat + [ if dev_mode then ["--dev"] else [] + ; dump_opt "--workspace" workspace_file + ; orig + ] + in + let config = + match config_file with + | No_config -> Config.default + | This fname -> Config.load_config_file fname + | Default -> + if Config.inside_dune then + Config.default + else + Config.load_user_config_file () + in + let config = + Config.merge config + { display + ; concurrency + } + in + let config = + Config.adapt_display config + ~output_is_a_tty:(Lazy.force Colors.stderr_supports_colors) + in + { debug_dep_path + ; debug_findlib + ; debug_backtraces + ; dev_mode + ; capture_outputs = not no_buffer + ; workspace_file + ; root + ; orig_args + ; target_prefix = String.concat ~sep:"" (List.map to_cwd ~f:(sprintf "%s/")) + ; diff_command + ; auto_promote + ; force + ; ignore_promoted_rules + ; only_packages = + Option.map only_packages + ~f:(fun s -> Package.Name.Set.of_list ( + List.map ~f:Package.Name.of_string (String.split s ~on:','))) + ; x + ; config + } in - let config = - match config_file with - | No_config -> Config.default - | This fname -> Config.load_config_file fname - | Default -> - if Config.inside_dune then - Config.default - else - Config.load_user_config_file () + let docs = copts_sect in + let concurrency = + let arg = + Arg.conv + ((fun s -> + Result.map_error (Config.Concurrency.of_string s) + ~f:(fun s -> `Msg s)), + fun pp x -> + Format.pp_print_string pp (Config.Concurrency.to_string x)) + in + Arg.(value + & opt (some arg) None + & info ["j"] ~docs ~docv:"JOBS" + ~doc:{|Run no more than $(i,JOBS) commands simultaneously.|} + ) in - let config = - Config.merge config - { display - ; concurrency - } + let only_packages = + Arg.(value + & opt (some string) None + & info ["only-packages"] ~docs ~docv:"PACKAGES" + ~doc:{|Ignore stanzas referring to a package that is not in $(b,PACKAGES). + $(b,PACKAGES) is a comma-separated list of package names. + Note that this has the same effect as deleting the relevant stanzas + from jbuild files. It is mostly meant for releases. + During development, it is likely that what you want instead is to + build a particular $(b,.install) target.|} + ) in - let config = - Config.adapt_display config - ~output_is_a_tty:(Lazy.force Colors.stderr_supports_colors) + let ddep_path = + Arg.(value + & flag + & info ["debug-dependency-path"] ~docs + ~doc:{|In case of error, print the dependency path from + the targets on the command line to the rule that failed. + |}) in - { debug_dep_path - ; debug_findlib - ; debug_backtraces - ; dev_mode - ; capture_outputs = not no_buffer - ; workspace_file - ; root - ; orig_args - ; target_prefix = String.concat ~sep:"" (List.map to_cwd ~f:(sprintf "%s/")) - ; diff_command - ; auto_promote - ; force - ; ignore_promoted_rules - ; only_packages = - Option.map only_packages - ~f:(fun s -> Package.Name.Set.of_list ( - List.map ~f:Package.Name.of_string (String.split s ~on:','))) - ; x - ; config - } - in - let docs = copts_sect in - let concurrency = - let arg = - Arg.conv - ((fun s -> - Result.map_error (Config.Concurrency.of_string s) - ~f:(fun s -> `Msg s)), - fun pp x -> - Format.pp_print_string pp (Config.Concurrency.to_string x)) + let dfindlib = + Arg.(value + & flag + & info ["debug-findlib"] ~docs + ~doc:{|Debug the findlib sub-system.|}) in - Arg.(value - & opt (some arg) None - & info ["j"] ~docs ~docv:"JOBS" - ~doc:{|Run no more than $(i,JOBS) commands simultaneously.|} - ) - in - let only_packages = - Arg.(value - & opt (some string) None - & info ["only-packages"] ~docs ~docv:"PACKAGES" - ~doc:{|Ignore stanzas referring to a package that is not in $(b,PACKAGES). - $(b,PACKAGES) is a comma-separated list of package names. - Note that this has the same effect as deleting the relevant stanzas - from jbuild files. It is mostly meant for releases. - During development, it is likely that what you want instead is to - build a particular $(b,.install) target.|} - ) - in - let ddep_path = - Arg.(value - & flag - & info ["debug-dependency-path"] ~docs - ~doc:{|In case of error, print the dependency path from - the targets on the command line to the rule that failed. - |}) - in - let dfindlib = - Arg.(value - & flag - & info ["debug-findlib"] ~docs - ~doc:{|Debug the findlib sub-system.|}) - in - let dbacktraces = - Arg.(value - & flag - & info ["debug-backtraces"] ~docs - ~doc:{|Always print exception backtraces.|}) - in - let dev = - Arg.(value - & flag - & info ["dev"] ~docs - ~doc:{|Use stricter compilation flags by default.|}) - in - let display = - let verbose = + let dbacktraces = Arg.(value & flag - & info ["verbose"] ~docs - ~doc:"Same as $(b,--display verbose)") + & info ["debug-backtraces"] ~docs + ~doc:{|Always print exception backtraces.|}) in - let display = + let dev = Arg.(value - & opt (some (enum Config.Display.all)) None - & info ["display"] ~docs ~docv:"MODE" - ~doc:{|Control the display mode of Jbuilder. - See $(b,dune-config\(5\)) for more details.|}) + & flag + & info ["dev"] ~docs + ~doc:{|Use stricter compilation flags by default.|}) in - let merge verbose display = - match verbose, display with - | false , None -> `Ok None - | false , Some x -> `Ok (Some x) - | true , None -> `Ok (Some Config.Display.Verbose) - | true , Some _ -> incompatible "--display" "--verbose" + let display = + let verbose = + Arg.(value + & flag + & info ["verbose"] ~docs + ~doc:"Same as $(b,--display verbose)") + in + let display = + Arg.(value + & opt (some (enum Config.Display.all)) None + & info ["display"] ~docs ~docv:"MODE" + ~doc:{|Control the display mode of Dune. + See $(b,dune-config\(5\)) for more details.|}) + in + let merge verbose display = + match verbose, display with + | false , None -> `Ok None + | false , Some x -> `Ok (Some x) + | true , None -> `Ok (Some Config.Display.Verbose) + | true , Some _ -> incompatible "--display" "--verbose" + in + Term.(ret (const merge $ verbose $ display)) in - Term.(ret (const merge $ verbose $ display)) - in - let no_buffer = - Arg.(value - & flag - & info ["no-buffer"] ~docs ~docv:"DIR" - ~doc:{|Do not buffer the output of commands executed by jbuilder. - By default jbuilder buffers the output of subcommands, in order - to prevent interleaving when multiple commands are executed - in parallel. However, this can be an issue when debugging - long running tests. With $(b,--no-buffer), commands have direct - access to the terminal. Note that as a result their output won't - be captured in the log file. + let no_buffer = + Arg.(value + & flag + & info ["no-buffer"] ~docs ~docv:"DIR" + ~doc:{|Do not buffer the output of commands executed by dune. + By default dune buffers the output of subcommands, in order + to prevent interleaving when multiple commands are executed + in parallel. However, this can be an issue when debugging + long running tests. With $(b,--no-buffer), commands have direct + access to the terminal. Note that as a result their output won't + be captured in the log file. - You should use this option in conjunction with $(b,-j 1), - to avoid interleaving. Additionally you should use - $(b,--verbose) as well, to make sure that commands are printed - before they are being executed.|}) - in - let workspace_file = - Arg.(value - & opt (some file) None - & info ["workspace"] ~docs ~docv:"FILE" - ~doc:"Use this specific workspace file instead of looking it up.") - in - let auto_promote = - Arg.(value - & flag - & info ["auto-promote"] ~docs - ~doc:"Automatically promote files. This is similar to running - $(b,jbuilder promote) after the build.") - in - let force = - Arg.(value - & flag - & info ["force"; "f"] - ~doc:"Force actions associated to aliases to be re-executed even - if their dependencies haven't changed.") - in - let merged_options = - let root = + You should use this option in conjunction with $(b,-j 1), + to avoid interleaving. Additionally you should use + $(b,--verbose) as well, to make sure that commands are printed + before they are being executed.|}) + in + let workspace_file = Arg.(value - & opt (some dir) None - & info ["root"] ~docs ~docv:"DIR" - ~doc:{|Use this directory as workspace root instead of guessing it. - Note that this option doesn't change the interpretation of - targets given on the command line. It is only intended - for scripts.|}) + & opt (some file) None + & info ["workspace"] ~docs ~docv:"FILE" + ~doc:"Use this specific workspace file instead of looking it up.") in - let ignore_promoted_rules = + let auto_promote = Arg.(value & flag - & info ["ignore-promoted-rules"] ~docs - ~doc:"Ignore rules with (mode promote)") + & info ["auto-promote"] ~docs + ~doc:"Automatically promote files. This is similar to running + $(b,dune promote) after the build.") in - let config_file = - let config_file = + let force = + Arg.(value + & flag + & info ["force"; "f"] + ~doc:"Force actions associated to aliases to be re-executed even + if their dependencies haven't changed.") + in + let merged_options = + let root = Arg.(value - & opt (some file) None - & info ["config-file"] ~docs ~docv:"FILE" - ~doc:"Load this configuration file instead of the default one.") + & opt (some dir) None + & info ["root"] ~docs ~docv:"DIR" + ~doc:{|Use this directory as workspace root instead of guessing it. + Note that this option doesn't change the interpretation of + targets given on the command line. It is only intended + for scripts.|}) in - let no_config = + let ignore_promoted_rules = Arg.(value & flag - & info ["no-config"] ~docs - ~doc:"Do not load the configuration file") + & info ["ignore-promoted-rules"] ~docs + ~doc:"Ignore rules with (mode promote)") in - let merge config_file no_config = - match config_file, no_config with - | None , false -> `Ok (None , Default) - | Some fn, false -> `Ok (Some "--config-file", This (Path.of_string fn)) - | None , true -> `Ok (Some "--no-config" , No_config) - | Some _ , true -> incompatible "--no-config" "--config-file" + let config_file = + let config_file = + Arg.(value + & opt (some file) None + & info ["config-file"] ~docs ~docv:"FILE" + ~doc:"Load this configuration file instead of the default one.") + in + let no_config = + Arg.(value + & flag + & info ["no-config"] ~docs + ~doc:"Do not load the configuration file") + in + let merge config_file no_config = + match config_file, no_config with + | None , false -> `Ok (None , Default) + | Some fn, false -> `Ok (Some "--config-file", This (Path.of_string fn)) + | None , true -> `Ok (Some "--no-config" , No_config) + | Some _ , true -> incompatible "--no-config" "--config-file" + in + Term.(ret (const merge $ config_file $ no_config)) + in + let for_release = "for-release-of-packages" in + let frop = + Arg.(value + & opt (some string) None + & info ["p"; for_release] ~docs ~docv:"PACKAGES" + ~doc:{|Shorthand for $(b,--root . --only-packages PACKAGE + --promote ignore --no-config). + You must use this option in your $(i,.opam) files, in order + to build only what's necessary when your project contains multiple + packages as well as getting reproducible builds.|}) + in + let merge root only_packages ignore_promoted_rules + (config_file_opt, config_file) release = + let fail opt = incompatible ("-p/--" ^ for_release) opt in + match release, root, only_packages, ignore_promoted_rules, config_file_opt with + | Some _, Some _, _, _, _ -> fail "--root" + | Some _, _, Some _, _, _ -> fail "--only-packages" + | Some _, _, _, true , _ -> fail "--ignore-promoted-rules" + | Some _, _, _, _ , Some s -> fail s + | Some pkgs, None, None, false, None -> + `Ok (Some ".", + Some pkgs, + true, + No_config, + ["-p"; pkgs] + ) + | None, _, _, _, _ -> + `Ok (root, + only_packages, + ignore_promoted_rules, + config_file, + List.concat + [ dump_opt "--root" root + ; dump_opt "--only-packages" only_packages + ; if ignore_promoted_rules then + ["--ignore-promoted-rules"] + else + [] + ; (match config_file with + | This fn -> ["--config-file"; fn] + | No_config -> ["--no-config"] + | Default -> []) + ] + ) in - Term.(ret (const merge $ config_file $ no_config)) + Term.(ret (const merge + $ root + $ only_packages + $ ignore_promoted_rules + $ config_file + $ frop)) in - let for_release = "for-release-of-packages" in - let frop = + let x = Arg.(value & opt (some string) None - & info ["p"; for_release] ~docs ~docv:"PACKAGES" - ~doc:{|Shorthand for $(b,--root . --only-packages PACKAGE - --promote ignore --no-config). - You must use this option in your $(i,.opam) files, in order - to build only what's necessary when your project contains multiple - packages as well as getting reproducible builds.|}) + & info ["x"] ~docs + ~doc:{|Cross-compile using this toolchain.|}) in - let merge root only_packages ignore_promoted_rules - (config_file_opt, config_file) release = - let fail opt = incompatible ("-p/--" ^ for_release) opt in - match release, root, only_packages, ignore_promoted_rules, config_file_opt with - | Some _, Some _, _, _, _ -> fail "--root" - | Some _, _, Some _, _, _ -> fail "--only-packages" - | Some _, _, _, true , _ -> fail "--ignore-promoted-rules" - | Some _, _, _, _ , Some s -> fail s - | Some pkgs, None, None, false, None -> - `Ok (Some ".", - Some pkgs, - true, - No_config, - ["-p"; pkgs] - ) - | None, _, _, _, _ -> - `Ok (root, - only_packages, - ignore_promoted_rules, - config_file, - List.concat - [ dump_opt "--root" root - ; dump_opt "--only-packages" only_packages - ; if ignore_promoted_rules then - ["--ignore-promoted-rules"] - else - [] - ; (match config_file with - | This fn -> ["--config-file"; Path.to_string fn] - | No_config -> ["--no-config"] - | Default -> []) - ] - ) + let diff_command = + Arg.(value + & opt (some string) None + & info ["diff-command"] ~docs + ~doc:"Shell command to use to diff files") in - Term.(ret (const merge - $ root - $ only_packages - $ ignore_promoted_rules - $ config_file - $ frop)) - in - let x = - Arg.(value - & opt (some string) None - & 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 - Term.(const make - $ concurrency - $ ddep_path - $ dfindlib - $ dbacktraces - $ dev - $ no_buffer - $ workspace_file - $ diff_command - $ auto_promote - $ force - $ merged_options - $ x - $ display - ) + Term.(const make + $ concurrency + $ ddep_path + $ dfindlib + $ dbacktraces + $ dev + $ no_buffer + $ workspace_file + $ diff_command + $ auto_promote + $ force + $ merged_options + $ x + $ display + ) -let installed_libraries = - let doc = "Print out libraries installed on the system." in - let go common na = - set_common common ~targets:[]; - let env = Main.setup_env ~capture_outputs:common.capture_outputs in - Scheduler.go ~log:(Log.create common) ~common - (Context.create (Default [Native]) ~env >>= fun ctxs -> - let ctx = List.hd ctxs in - let findlib = ctx.findlib in - if na then begin - let pkgs = Findlib.all_unavailable_packages findlib in - let longest = String.longest_map pkgs ~f:fst in - let ppf = Format.std_formatter in - List.iter pkgs ~f:(fun (n, r) -> - Format.fprintf ppf "%-*s -> %a@\n" longest n - Findlib.Unavailable_reason.pp r); - Format.pp_print_flush ppf (); - Fiber.return () - end else begin - let pkgs = Findlib.all_packages findlib in - let max_len = String.longest_map pkgs ~f:Findlib.Package.name in - List.iter pkgs ~f:(fun pkg -> - let ver = - Option.value (Findlib.Package.version pkg) ~default:"n/a" - in - Printf.printf "%-*s (version: %s)\n" max_len - (Findlib.Package.name pkg) ver); - Fiber.return () - end) - in - ( Term.(const go - $ common - $ Arg.(value - & flag - & info ["na"; "not-available"] - ~doc:"List libraries that are not available and explain why")) - , Term.info "installed-libraries" ~doc - ) + let installed_libraries = + let doc = "Print out libraries installed on the system." in + let go common na = + set_common common ~targets:[]; + let env = Main.setup_env ~capture_outputs:common.capture_outputs in + Scheduler.go ~log:(Log.create common) ~common + (Context.create (Default [Native]) ~env >>= fun ctxs -> + let ctx = List.hd ctxs in + let findlib = ctx.findlib in + if na then begin + let pkgs = Findlib.all_unavailable_packages findlib in + let longest = String.longest_map pkgs ~f:fst in + let ppf = Format.std_formatter in + List.iter pkgs ~f:(fun (n, r) -> + Format.fprintf ppf "%-*s -> %a@\n" longest n + Findlib.Unavailable_reason.pp r); + Format.pp_print_flush ppf (); + Fiber.return () + end else begin + let pkgs = Findlib.all_packages findlib in + let max_len = String.longest_map pkgs ~f:Findlib.Package.name in + List.iter pkgs ~f:(fun pkg -> + let ver = + Option.value (Findlib.Package.version pkg) ~default:"n/a" + in + Printf.printf "%-*s (version: %s)\n" max_len + (Findlib.Package.name pkg) ver); + Fiber.return () + end) + in + ( Term.(const go + $ common + $ Arg.(value + & flag + & info ["na"; "not-available"] + ~doc:"List libraries that are not available and explain why")) + , Term.info "installed-libraries" ~doc + ) -let resolve_package_install setup pkg = - match Main.package_install_file setup pkg with - | Ok path -> path - | Error () -> - let pkg = Package.Name.to_string pkg in - die "Unknown package %s!%s" pkg - (hint pkg - (Package.Name.Map.keys setup.packages - |> List.map ~f:Package.Name.to_string)) + let resolve_package_install setup pkg = + match Main.package_install_file setup pkg with + | Ok path -> path + | Error () -> + let pkg = Package.Name.to_string pkg in + die "Unknown package %s!%s" pkg + (hint pkg + (Package.Name.Map.keys setup.packages + |> List.map ~f:Package.Name.to_string)) -let target_hint (setup : Main.setup) path = - assert (Path.is_local path); - let sub_dir = - if Path.is_root path then - path - else - Path.parent path in - let candidates = Build_system.all_targets setup.build_system in - let candidates = - if Path.is_in_build_dir path then - candidates - else - List.map candidates ~f:(fun path -> - match Path.extract_build_context path with - | None -> path - | Some (_, path) -> path) - in - let candidates = - (* Only suggest hints for the basename, otherwise it's slow when there are lots of - files *) - List.filter_map candidates ~f:(fun path -> - if Path.parent path = sub_dir then - Some (Path.to_string path) + let target_hint (setup : Main.setup) path = + assert (Path.is_local path); + let sub_dir = + if Path.is_root path then + path else - None) - in - let candidates = String.Set.of_list candidates |> String.Set.to_list in - hint (Path.to_string path) candidates - -let check_path contexts = - let contexts = - String.Set.of_list (List.map contexts ~f:(fun c -> c.Context.name)) - in - fun path -> - let internal path = - die "This path is internal to jbuilder: %s" - (Path.to_string_maybe_quoted path) + Path.parent path in + let candidates = Build_system.all_targets setup.build_system in + let candidates = + if Path.is_in_build_dir path then + candidates + else + List.map candidates ~f:(fun path -> + match Path.extract_build_context path with + | None -> path + | Some (_, path) -> path) + in + let candidates = + (* Only suggest hints for the basename, otherwise it's slow when there are lots of + files *) + List.filter_map candidates ~f:(fun path -> + if Path.parent path = sub_dir then + Some (Path.to_string path) + else + None) in - if Path.is_in_build_dir path then - match Path.extract_build_context path with - | None -> internal path - | Some (name, _) -> - if name = "" || name.[0] = '.' then internal path; - if not (name = "install" || String.Set.mem contexts name) then - die "%s refers to unknown build context: %s%s" - (Path.to_string_maybe_quoted path) - name - (hint name (String.Set.to_list contexts)) + let candidates = String.Set.of_list candidates |> String.Set.to_list in + hint (Path.to_string path) candidates -let resolve_targets ~log common (setup : Main.setup) user_targets = - match user_targets with - | [] -> [] - | _ -> - let check_path = check_path setup.contexts in - let targets = - List.map user_targets ~f:(fun s -> - if String.is_prefix s ~prefix:"@" then begin - let s = String.sub s ~pos:1 ~len:(String.length s - 1) in - let path = Path.relative Path.root (prefix_target common s) in - check_path path; - if Path.is_root path then - die "@@ on the command line must be followed by a valid alias name" - else if not (Path.is_local path) then - die "@@ on the command line must be followed by a relative path" - else - Ok [Alias_rec path] - end else begin - let path = Path.relative Path.root (prefix_target common s) in - check_path path; - let can't_build path = - Error (path, target_hint setup path); - in - if not (Path.is_local path) then - Ok [File path] - else if Path.is_in_build_dir path then begin - if Build_system.is_target setup.build_system path then - Ok [File path] - else - can't_build path - end else - match - List.filter_map setup.contexts ~f:(fun ctx -> - let path = Path.append ctx.Context.build_dir path in - if Build_system.is_target setup.build_system path then - Some (File path) - else - None) - with - | [] -> can't_build path - | l -> Ok l - end - ) + let check_path contexts = + let contexts = + String.Set.of_list (List.map contexts ~f:(fun c -> c.Context.name)) in - if common.config.display = Verbose then begin - Log.info log "Actual targets:"; + fun path -> + let internal path = + die "This path is internal to dune: %s" + (Path.to_string_maybe_quoted path) + in + if Path.is_in_build_dir path then + match Path.extract_build_context path with + | None -> internal path + | Some (name, _) -> + if name = "" || name.[0] = '.' then internal path; + if not (name = "install" || String.Set.mem contexts name) then + die "%s refers to unknown build context: %s%s" + (Path.to_string_maybe_quoted path) + name + (hint name (String.Set.to_list contexts)) + + let resolve_targets ~log common (setup : Main.setup) user_targets = + match user_targets with + | [] -> [] + | _ -> + let check_path = check_path setup.contexts in let targets = - List.concat_map targets ~f:(function - | Ok targets -> targets - | Error _ -> []) in - List.iter targets ~f:(function - | File path -> - Log.info log @@ "- " ^ (Path.to_string path) - | Alias_rec path -> - Log.info log @@ "- recursive alias " ^ - (Path.to_string_maybe_quoted path)); - flush stdout; - end; - targets + List.map user_targets ~f:(fun s -> + if String.is_prefix s ~prefix:"@" then begin + let s = String.sub s ~pos:1 ~len:(String.length s - 1) in + let path = Path.relative Path.root (prefix_target common s) in + check_path path; + if Path.is_root path then + die "@@ on the command line must be followed by a valid alias name" + else if not (Path.is_local path) then + die "@@ on the command line must be followed by a relative path" + else + Ok [Alias_rec path] + end else begin + let path = Path.relative Path.root (prefix_target common s) in + check_path path; + let can't_build path = + Error (path, target_hint setup path); + in + if not (Path.is_local path) then + Ok [File path] + else if Path.is_in_build_dir path then begin + if Build_system.is_target setup.build_system path then + Ok [File path] + else + can't_build path + end else + match + List.filter_map setup.contexts ~f:(fun ctx -> + let path = Path.append ctx.Context.build_dir path in + if Build_system.is_target setup.build_system path then + Some (File path) + else + None) + with + | [] -> can't_build path + | l -> Ok l + end + ) + in + if common.config.display = Verbose then begin + Log.info log "Actual targets:"; + let targets = + List.concat_map targets ~f:(function + | Ok targets -> targets + | Error _ -> []) in + List.iter targets ~f:(function + | File path -> + Log.info log @@ "- " ^ (Path.to_string path) + | Alias_rec path -> + Log.info log @@ "- recursive alias " ^ + (Path.to_string_maybe_quoted path)); + flush stdout; + end; + targets -let resolve_targets_exn ~log common setup user_targets = - resolve_targets ~log common setup user_targets - |> List.concat_map ~f:(function - | Error (path, hint) -> - die "Don't know how to build %a%s" Path.pp path hint - | Ok targets -> - targets) + let resolve_targets_exn ~log common setup user_targets = + resolve_targets ~log common setup user_targets + |> List.concat_map ~f:(function + | Error (path, hint) -> + die "Don't know how to build %a%s" Path.pp path hint + | Ok targets -> + targets) -let build_targets = - let doc = "Build the given targets, or all installable targets if none are given." in - let man = - [ `S "DESCRIPTION" - ; `P {|Targets starting with a $(b,@) are interpreted as aliases.|} - ; `Blocks help_secs - ] - in - let name_ = Arg.info [] ~docv:"TARGET" in - let go common targets = - set_common common ~targets; - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common >>= fun setup -> - let targets = resolve_targets_exn ~log common setup targets in - do_build setup targets) in - ( Term.(const go - $ common - $ Arg.(value & pos_all string ["@install"] name_)) - , Term.info "build" ~doc ~man) + let build_targets = + let doc = "Build the given targets, or all installable targets if none are given." in + let man = + [ `S "DESCRIPTION" + ; `P {|Targets starting with a $(b,@) are interpreted as aliases.|} + ; `Blocks help_secs + ] + in + let name_ = Arg.info [] ~docv:"TARGET" in + let go common targets = + set_common common ~targets; + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common >>= fun setup -> + let targets = resolve_targets_exn ~log common setup targets in + do_build setup targets) in + ( Term.(const go + $ common + $ Arg.(value & pos_all string ["@install"] name_)) + , Term.info "build" ~doc ~man) -let runtest = - let doc = "Run tests." in - let man = - [ `S "DESCRIPTION" - ; `P {|This is a short-hand for calling:|} - ; `Pre {| jbuilder build @runtest|} - ; `Blocks help_secs - ] - in - let name_ = Arg.info [] ~docv:"DIR" in - let go common dirs = - set_common common - ~targets:(List.map dirs ~f:(function - | "" | "." -> "@runtest" - | dir when dir.[String.length dir - 1] = '/' -> sprintf "@%sruntest" dir - | dir -> sprintf "@%s/runtest" dir)); - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common >>= fun setup -> - let check_path = check_path setup.contexts in - let targets = - List.map dirs ~f:(fun dir -> - let dir = Path.(relative root) (prefix_target common dir) in - check_path dir; - Alias_rec (Path.relative dir "runtest")) - in - do_build setup targets) in - ( Term.(const go - $ common - $ Arg.(value & pos_all string ["."] name_)) - , Term.info "runtest" ~doc ~man) + let runtest = + let doc = "Run tests." in + let man = + [ `S "DESCRIPTION" + ; `P {|This is a short-hand for calling:|} + ; `Pre {| dune build @runtest|} + ; `Blocks help_secs + ] + in + let name_ = Arg.info [] ~docv:"DIR" in + let go common dirs = + set_common common + ~targets:(List.map dirs ~f:(function + | "" | "." -> "@runtest" + | dir when dir.[String.length dir - 1] = '/' -> sprintf "@%sruntest" dir + | dir -> sprintf "@%s/runtest" dir)); + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common >>= fun setup -> + let check_path = check_path setup.contexts in + let targets = + List.map dirs ~f:(fun dir -> + let dir = Path.(relative root) (prefix_target common dir) in + check_path dir; + Alias_rec (Path.relative dir "runtest")) + in + do_build setup targets) in + ( Term.(const go + $ common + $ Arg.(value & pos_all string ["."] name_)) + , Term.info "runtest" ~doc ~man) let clean = let doc = "Clean the project." in let man = [ `S "DESCRIPTION" - ; `P {|Removes files added by jbuilder such as _build, .install, and .merlin|} + ; `P {|Removes files added by dune such as _build, .install, and .merlin|} ; `Blocks help_secs ] in @@ -747,698 +755,699 @@ let clean = ( Term.(const go $ common) , Term.info "clean" ~doc ~man) -let format_external_libs libs = - String.Map.to_list libs - |> List.map ~f:(fun (name, kind) -> - match (kind : Build.lib_dep_kind) with - | Optional -> sprintf "- %s (optional)" name - | Required -> sprintf "- %s" name) - |> String.concat ~sep:"\n" + let format_external_libs libs = + String.Map.to_list libs + |> List.map ~f:(fun (name, kind) -> + match (kind : Build.lib_dep_kind) with + | Optional -> sprintf "- %s (optional)" name + | Required -> sprintf "- %s" name) + |> String.concat ~sep:"\n" -let external_lib_deps = - let doc = "Print out external libraries needed to build the given targets." in - let man = - [ `S "DESCRIPTION" - ; `P {|Print out the external libraries needed to build the given targets.|} - ; `P {|The output of $(b,jbuild external-lib-deps @install) should be included - in what is written in your $(i,.opam) file.|} - ; `Blocks help_secs - ] - in - let go common only_missing targets = - set_common common ~targets:[]; - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common ~external_lib_deps_mode:true - >>= fun setup -> - let targets = resolve_targets_exn ~log common setup targets in - let request = request_of_targets setup targets in - let failure = - String.Map.foldi ~init:false - (Build_system.all_lib_deps_by_context setup.build_system ~request) - ~f:(fun context_name lib_deps acc -> - let internals = - Jbuild.Stanzas.lib_names - (match String.Map.find setup.Main.stanzas context_name with - | None -> assert false - | Some x -> x) - in - let externals = - String.Map.filteri lib_deps ~f:(fun name _ -> - not (String.Set.mem internals name)) - in - if only_missing then begin - let context = - match - List.find setup.contexts ~f:(fun c -> c.name = context_name) - with - | None -> assert false - | Some c -> c + let external_lib_deps = + let doc = "Print out external libraries needed to build the given targets." in + let man = + [ `S "DESCRIPTION" + ; `P {|Print out the external libraries needed to build the given targets.|} + ; `P {|The output of $(b,jbuild external-lib-deps @install) should be included + in what is written in your $(i,.opam) file.|} + ; `Blocks help_secs + ] + in + let go common only_missing targets = + set_common common ~targets:[]; + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common ~external_lib_deps_mode:true + >>= fun setup -> + let targets = resolve_targets_exn ~log common setup targets in + let request = request_of_targets setup targets in + let failure = + String.Map.foldi ~init:false + (Build_system.all_lib_deps_by_context setup.build_system ~request) + ~f:(fun context_name lib_deps acc -> + let internals = + Jbuild.Stanzas.lib_names + (match String.Map.find setup.Main.stanzas context_name with + | None -> assert false + | Some x -> x) in - let missing = - String.Map.filteri externals ~f:(fun name _ -> - not (Findlib.available context.findlib name)) + let externals = + String.Map.filteri lib_deps ~f:(fun name _ -> + not (String.Set.mem internals name)) in - if String.Map.is_empty missing then - acc - else if String.Map.for_alli missing - ~f:(fun _ kind -> kind = Build.Optional) - then begin - Format.eprintf - "@{Error@}: The following libraries are missing \ - in the %s context:\n\ - %s@." - context_name - (format_external_libs missing); - false + if only_missing then begin + let context = + match + List.find setup.contexts ~f:(fun c -> c.name = context_name) + with + | None -> assert false + | Some c -> c + in + let missing = + String.Map.filteri externals ~f:(fun name _ -> + not (Findlib.available context.findlib name)) + in + if String.Map.is_empty missing then + acc + else if String.Map.for_alli missing + ~f:(fun _ kind -> kind = Build.Optional) + then begin + Format.eprintf + "@{Error@}: The following libraries are missing \ + in the %s context:\n\ + %s@." + context_name + (format_external_libs missing); + false + end else begin + Format.eprintf + "@{Error@}: The following libraries are missing \ + in the %s context:\n\ + %s\n\ + Hint: try: opam install %s@." + context_name + (format_external_libs missing) + (String.Map.to_list missing + |> List.filter_map ~f:(fun (name, kind) -> + match (kind : Build.lib_dep_kind) with + | Optional -> None + | Required -> Some (Findlib.root_package_name name)) + |> String.Set.of_list + |> String.Set.to_list + |> String.concat ~sep:" "); + true + end end else begin - Format.eprintf - "@{Error@}: The following libraries are missing \ - in the %s context:\n\ - %s\n\ - Hint: try: opam install %s@." + Printf.printf + "These are the external library dependencies in the %s context:\n\ + %s\n%!" context_name - (format_external_libs missing) - (String.Map.to_list missing - |> List.filter_map ~f:(fun (name, kind) -> - match (kind : Build.lib_dep_kind) with - | Optional -> None - | Required -> Some (Findlib.root_package_name name)) - |> String.Set.of_list - |> String.Set.to_list - |> String.concat ~sep:" "); - true - end - end else begin - Printf.printf - "These are the external library dependencies in the %s context:\n\ - %s\n%!" - context_name - (format_external_libs externals); - acc - end) - in - if failure then raise Already_reported; - Fiber.return ()) - in - ( Term.(const go - $ common - $ Arg.(value - & flag - & info ["missing"] - ~doc:{|Only print out missing dependencies|}) - $ Arg.(non_empty - & pos_all string [] - & Arg.info [] ~docv:"TARGET")) - , Term.info "external-lib-deps" ~doc ~man) + (format_external_libs externals); + acc + end) + in + if failure then raise Already_reported; + Fiber.return ()) + in + ( Term.(const go + $ common + $ Arg.(value + & flag + & info ["missing"] + ~doc:{|Only print out missing dependencies|}) + $ Arg.(non_empty + & pos_all string [] + & Arg.info [] ~docv:"TARGET")) + , Term.info "external-lib-deps" ~doc ~man) -let rules = - let doc = "Dump internal rules." in - let man = - [ `S "DESCRIPTION" - ; `P {|Dump Jbuilder internal rules for the given targets. - If no targets are given, dump all the internal rules.|} - ; `P {|By default the output is a list of S-expressions, - one S-expression per rule. Each S-expression is of the form:|} - ; `Pre " ((deps ())\n\ - \ (targets ())\n\ - \ (context )\n\ - \ (action ))" - ; `P {|$(b,) is the context is which the action is executed. - It is omitted if the action is independant from the context.|} - ; `P {|$(b,) is the action following the same syntax as user actions, - as described in the manual.|} - ; `Blocks help_secs - ] - in - let go common out recursive makefile_syntax targets = - let out = Option.map ~f:Path.of_string out in - set_common common ~targets; - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common ~external_lib_deps_mode:true - >>= fun setup -> - let request = - match targets with - | [] -> Build.paths (Build_system.all_targets setup.build_system) - | _ -> resolve_targets_exn ~log common setup targets |> request_of_targets setup - in - Build_system.build_rules setup.build_system ~request ~recursive >>= fun rules -> - let sexp_of_action action = - Action.for_shell action |> Action.For_shell.sexp_of_t - in - let print oc = - let ppf = Format.formatter_of_out_channel oc in - Sexp.prepare_formatter ppf; - Format.pp_open_vbox ppf 0; - if makefile_syntax then begin - List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> - Format.fprintf ppf "@[@{%a:%t@}@]@,@<0>\t@{%a@}@,@," - (Format.pp_print_list ~pp_sep:Format.pp_print_space (fun ppf p -> - Format.pp_print_string ppf (Path.to_string p))) - (Path.Set.to_list rule.targets) - (fun ppf -> - Path.Set.iter rule.deps ~f:(fun dep -> - Format.fprintf ppf "@ %s" (Path.to_string dep))) - Sexp.pp_split_strings (sexp_of_action rule.action)) - end else begin - List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> - let sexp = - let paths ps = - Sexp.To_sexp.list Path.sexp_of_t (Path.Set.to_list ps) + let rules = + let doc = "Dump internal rules." in + let man = + [ `S "DESCRIPTION" + ; `P {|Dump Dune internal rules for the given targets. + If no targets are given, dump all the internal rules.|} + ; `P {|By default the output is a list of S-expressions, + one S-expression per rule. Each S-expression is of the form:|} + ; `Pre " ((deps ())\n\ + \ (targets ())\n\ + \ (context )\n\ + \ (action ))" + ; `P {|$(b,) is the context is which the action is executed. + It is omitted if the action is independant from the context.|} + ; `P {|$(b,) is the action following the same syntax as user actions, + as described in the manual.|} + ; `Blocks help_secs + ] + in + let go common out recursive makefile_syntax targets = + let out = Option.map ~f:Path.of_string out in + set_common common ~targets; + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common ~external_lib_deps_mode:true + >>= fun setup -> + let request = + match targets with + | [] -> Build.paths (Build_system.all_targets setup.build_system) + | _ -> resolve_targets_exn ~log common setup targets |> request_of_targets setup + in + Build_system.build_rules setup.build_system ~request ~recursive >>= fun rules -> + let sexp_of_action action = + Action.for_shell action |> Action.For_shell.sexp_of_t + in + let print oc = + let ppf = Format.formatter_of_out_channel oc in + Sexp.prepare_formatter ppf; + Format.pp_open_vbox ppf 0; + if makefile_syntax then begin + List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> + Format.fprintf ppf "@[@{%a:%t@}@]@,@<0>\t@{%a@}@,@," + (Format.pp_print_list ~pp_sep:Format.pp_print_space (fun ppf p -> + Format.pp_print_string ppf (Path.to_string p))) + (Path.Set.to_list rule.targets) + (fun ppf -> + Path.Set.iter rule.deps ~f:(fun dep -> + Format.fprintf ppf "@ %s" (Path.to_string dep))) + Sexp.pp_split_strings (sexp_of_action rule.action)) + end else begin + List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> + let sexp = + let paths ps = + Sexp.To_sexp.list Path.sexp_of_t (Path.Set.to_list ps) + in + Sexp.To_sexp.record ( + List.concat + [ [ "deps" , paths rule.deps + ; "targets", paths rule.targets ] + ; (match rule.context with + | None -> [] + | Some c -> ["context", + Sexp.atom_or_quoted_string c.name]) + ; [ "action" , sexp_of_action rule.action ] + ]) in - Sexp.To_sexp.record ( - List.concat - [ [ "deps" , paths rule.deps - ; "targets", paths rule.targets ] - ; (match rule.context with - | None -> [] - | Some c -> ["context", - Sexp.atom_or_quoted_string c.name]) - ; [ "action" , sexp_of_action rule.action ] - ]) - in - Format.fprintf ppf "%a@," Sexp.pp_split_strings sexp) - end; - Format.pp_print_flush ppf (); - Fiber.return () - in - match out with - | None -> print stdout - | Some fn -> Io.with_file_out fn ~f:print) - in - ( Term.(const go - $ common - $ Arg.(value - & opt (some string) None - & info ["o"] ~docv:"FILE" - ~doc:"Output to a file instead of stdout.") - $ Arg.(value - & flag - & info ["r"; "recursive"] - ~doc:"Print all rules needed to build the transitive dependencies of the given targets.") - $ Arg.(value - & flag - & info ["m"; "makefile"] - ~doc:"Output the rules in Makefile syntax.") - $ Arg.(value - & pos_all string [] - & Arg.info [] ~docv:"TARGET")) - , Term.info "rules" ~doc ~man) + Format.fprintf ppf "%a@," Sexp.pp_split_strings sexp) + end; + Format.pp_print_flush ppf (); + Fiber.return () + in + match out with + | None -> print stdout + | Some fn -> Io.with_file_out fn ~f:print) + in + ( Term.(const go + $ common + $ Arg.(value + & opt (some string) None + & info ["o"] ~docv:"FILE" + ~doc:"Output to a file instead of stdout.") + $ Arg.(value + & flag + & info ["r"; "recursive"] + ~doc:"Print all rules needed to build the transitive dependencies of the given targets.") + $ Arg.(value + & flag + & info ["m"; "makefile"] + ~doc:"Output the rules in Makefile syntax.") + $ Arg.(value + & pos_all string [] + & Arg.info [] ~docv:"TARGET")) + , Term.info "rules" ~doc ~man) -let opam_installer () = - match Bin.which "opam-installer" with - | None -> - die "\ + let opam_installer () = + match Bin.which "opam-installer" with + | None -> + die "\ Sorry, you need the opam-installer tool to be able to install or uninstall packages. I couldn't find the opam-installer binary :-(" - | Some fn -> fn + | Some fn -> fn -let get_prefix context ~from_command_line = - match from_command_line with - | Some p -> Fiber.return (Path.of_string p) - | None -> Context.install_prefix context + let get_prefix context ~from_command_line = + match from_command_line with + | Some p -> Fiber.return (Path.of_string p) + | None -> Context.install_prefix context -let get_libdir context ~libdir_from_command_line = - match libdir_from_command_line with - | Some p -> Fiber.return (Some (Path.of_string p)) - | None -> Context.install_ocaml_libdir context + let get_libdir context ~libdir_from_command_line = + match libdir_from_command_line with + | Some p -> Fiber.return (Some (Path.of_string p)) + | None -> Context.install_ocaml_libdir context -let install_uninstall ~what = - let doc = - sprintf "%s packages using opam-installer." (String.capitalize what) - in - let name_ = Arg.info [] ~docv:"PACKAGE" in - let go common prefix_from_command_line libdir_from_command_line pkgs = - set_common common ~targets:[]; - let opam_installer = opam_installer () in - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common >>= fun setup -> - let pkgs = - match pkgs with - | [] -> Package.Name.Map.keys setup.packages - | l -> l - in - let install_files, missing_install_files = - List.concat_map pkgs ~f:(fun pkg -> - let fn = resolve_package_install setup pkg in - List.map setup.contexts ~f:(fun ctx -> - let fn = Path.append ctx.Context.build_dir fn in - if Path.exists fn then - Left (ctx, fn) - else - Right fn)) - |> List.partition_map ~f:(fun x -> x) - in - if missing_install_files <> [] then begin - die "The following .install are missing:\n\ - %s\n\ - You need to run: jbuilder build @install" - (String.concat ~sep:"\n" - (List.map missing_install_files - ~f:(fun p -> sprintf "- %s" (Path.to_string p)))) - end; - (match - setup.contexts, prefix_from_command_line, libdir_from_command_line - with - | _ :: _ :: _, Some _, _ | _ :: _ :: _, _, Some _ -> - die "Cannot specify --prefix or --libdir when installing \ - into multiple contexts!" - | _ -> ()); - let module CMap = Map.Make(Context) in - let install_files_by_context = - CMap.of_list_multi install_files |> CMap.to_list - in - Fiber.parallel_iter install_files_by_context - ~f:(fun (context, install_files) -> - get_prefix context ~from_command_line:prefix_from_command_line - >>= fun prefix -> - get_libdir context ~libdir_from_command_line - >>= fun libdir -> - Fiber.parallel_iter install_files ~f:(fun path -> - let purpose = Process.Build_job install_files in - Process.run ~purpose ~env:setup.env Strict opam_installer - ([ sprintf "-%c" what.[0] - ; Path.to_string path - ; "--prefix" - ; Path.to_string prefix - ] @ - match libdir with - | None -> [] - | Some p -> [ "--libdir"; Path.to_string p ] - )))) - in - ( Term.(const go - $ common - $ Arg.(value - & opt (some dir) None - & info ["destdir"; "prefix"] - ~docv:"PREFIX" - ~doc:"Directory where files are copied. For instance binaries \ - are copied into $(i,\\$prefix/bin), library files into \ - $(i,\\$prefix/lib), etc... It defaults to the current opam \ - prefix if opam is available and configured, otherwise it uses \ - the same prefix as the ocaml compiler.") - $ Arg.(value - & opt (some dir) None - & info ["libdir"] - ~docv:"PATH" - ~doc:"Directory where library files are copied, relative to \ - $(b,prefix) or absolute. If $(b,--prefix) \ - is specified the default is $(i,\\$prefix/lib), otherwise \ - it is the output of $(b,ocamlfind printconf destdir)" - ) - $ Arg.(value & pos_all package_name [] name_)) - , Term.info what ~doc ~man:help_secs) + let install_uninstall ~what = + let doc = + sprintf "%s packages using opam-installer." (String.capitalize what) + in + let name_ = Arg.info [] ~docv:"PACKAGE" in + let go common prefix_from_command_line libdir_from_command_line pkgs = + set_common common ~targets:[]; + let opam_installer = opam_installer () in + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common >>= fun setup -> + let pkgs = + match pkgs with + | [] -> Package.Name.Map.keys setup.packages + | l -> l + in + let install_files, missing_install_files = + List.concat_map pkgs ~f:(fun pkg -> + let fn = resolve_package_install setup pkg in + List.map setup.contexts ~f:(fun ctx -> + let fn = Path.append ctx.Context.build_dir fn in + if Path.exists fn then + Left (ctx, fn) + else + Right fn)) + |> List.partition_map ~f:(fun x -> x) + in + if missing_install_files <> [] then begin + die "The following .install are missing:\n\ + %s\n\ + You need to run: dune build @install" + (String.concat ~sep:"\n" + (List.map missing_install_files + ~f:(fun p -> sprintf "- %s" (Path.to_string p)))) + end; + (match + setup.contexts, prefix_from_command_line, libdir_from_command_line + with + | _ :: _ :: _, Some _, _ | _ :: _ :: _, _, Some _ -> + die "Cannot specify --prefix or --libdir when installing \ + into multiple contexts!" + | _ -> ()); + let module CMap = Map.Make(Context) in + let install_files_by_context = + CMap.of_list_multi install_files |> CMap.to_list + in + Fiber.parallel_iter install_files_by_context + ~f:(fun (context, install_files) -> + get_prefix context ~from_command_line:prefix_from_command_line + >>= fun prefix -> + get_libdir context ~libdir_from_command_line + >>= fun libdir -> + Fiber.parallel_iter install_files ~f:(fun path -> + let purpose = Process.Build_job install_files in + Process.run ~purpose ~env:setup.env Strict opam_installer + ([ sprintf "-%c" what.[0] + ; Path.to_string path + ; "--prefix" + ; Path.to_string prefix + ] @ + match libdir with + | None -> [] + | Some p -> [ "--libdir"; Path.to_string p ] + )))) + in + ( Term.(const go + $ common + $ Arg.(value + & opt (some dir) None + & info ["destdir"; "prefix"] + ~docv:"PREFIX" + ~doc:"Directory where files are copied. For instance binaries \ + are copied into $(i,\\$prefix/bin), library files into \ + $(i,\\$prefix/lib), etc... It defaults to the current opam \ + prefix if opam is available and configured, otherwise it uses \ + the same prefix as the ocaml compiler.") + $ Arg.(value + & opt (some dir) None + & info ["libdir"] + ~docv:"PATH" + ~doc:"Directory where library files are copied, relative to \ + $(b,prefix) or absolute. If $(b,--prefix) \ + is specified the default is $(i,\\$prefix/lib), otherwise \ + it is the output of $(b,ocamlfind printconf destdir)" + ) + $ Arg.(value & pos_all package_name [] name_)) + , Term.info what ~doc ~man:help_secs) -let install = install_uninstall ~what:"install" -let uninstall = install_uninstall ~what:"uninstall" + let install = install_uninstall ~what:"install" + let uninstall = install_uninstall ~what:"uninstall" -let context_arg ~doc = - Arg.(value - & opt string "default" - & info ["context"] ~docv:"CONTEXT" ~doc) + let context_arg ~doc = + Arg.(value + & opt string "default" + & info ["context"] ~docv:"CONTEXT" ~doc) -let exec = - let doc = - "Execute a command in a similar environment as if installation was performed." - in - let man = - [ `S "DESCRIPTION" - ; `P {|$(b,jbuilder exec -- COMMAND) should behave in the same way as if you - do:|} - ; `Pre " \\$ jbuilder install\n\ - \ \\$ COMMAND" - ; `P {|In particular if you run $(b,jbuilder exec ocaml), you will have - access to the libraries defined in the workspace using your usual - directives ($(b,#require) for instance)|} - ; `P {|When a leading / is present in the command (absolute path), then the - path is interpreted as an absolute path|} - ; `P {|When a / is present at any other position (relative path), then the - path is interpreted as relative to the build context + current - working directory (or the value of $(b,--root) when ran outside of - the project root)|} - ; `Blocks help_secs - ] - in - let go common context prog no_rebuild args = - set_common common ~targets:[]; - let log = Log.create common in - let setup = Scheduler.go ~log ~common (Main.setup ~log common) in - let context = Main.find_context_exn setup ~name:context in - let prog_where = - match Filename.analyze_program_name prog with - | Absolute -> - `This_abs (Path.of_string prog) - | In_path -> - `Search prog - | Relative_to_current_dir -> - let prog = prefix_target common prog in - `This_rel (Path.relative context.build_dir prog) in - let targets = lazy ( - (match prog_where with - | `Search p -> - [Path.relative (Config.local_install_bin_dir ~context:context.name) p] - | `This_rel p when Sys.win32 -> - [p; Path.extend_basename p ~suffix:Bin.exe] - | `This_rel p -> - [p] - | `This_abs p when Path.is_in_build_dir p -> - [p] - | `This_abs _ -> - []) - |> List.map ~f:Path.to_string - |> resolve_targets ~log common setup - |> List.concat_map ~f:(function - | Ok targets -> targets - | Error _ -> []) - ) in - let real_prog = - if not no_rebuild then begin - match Lazy.force targets with - | [] -> () - | targets -> - Scheduler.go ~log ~common (do_build setup targets); - Build_system.finalize setup.build_system - end; - match prog_where with - | `Search prog -> - let path = Config.local_install_bin_dir ~context:context.name :: context.path in - Bin.which prog ~path - | `This_rel prog - | `This_abs prog -> - if Path.exists prog then - Some prog - else if not Sys.win32 then - None - else - let prog = Path.extend_basename prog ~suffix:Bin.exe in - Option.some_if (Path.exists prog) prog + let exec = + let doc = + "Execute a command in a similar environment as if installation was performed." in - match real_prog, no_rebuild with - | None, true -> - begin match Lazy.force targets with - | [] -> + let man = + [ `S "DESCRIPTION" + ; `P {|$(b,dune exec -- COMMAND) should behave in the same way as if you + do:|} + ; `Pre " \\$ dune install\n\ + \ \\$ COMMAND" + ; `P {|In particular if you run $(b,dune exec ocaml), you will have + access to the libraries defined in the workspace using your usual + directives ($(b,#require) for instance)|} + ; `P {|When a leading / is present in the command (absolute path), then the + path is interpreted as an absolute path|} + ; `P {|When a / is present at any other position (relative path), then the + path is interpreted as relative to the build context + current + working directory (or the value of $(b,--root) when ran outside of + the project root)|} + ; `Blocks help_secs + ] + in + let go common context prog no_rebuild args = + set_common common ~targets:[]; + let log = Log.create common in + let setup = Scheduler.go ~log ~common (Main.setup ~log common) in + let context = Main.find_context_exn setup ~name:context in + let prog_where = + match Filename.analyze_program_name prog with + | Absolute -> + `This_abs (Path.of_string prog) + | In_path -> + `Search prog + | Relative_to_current_dir -> + let prog = prefix_target common prog in + `This_rel (Path.relative context.build_dir prog) in + let targets = lazy ( + (match prog_where with + | `Search p -> + [Path.relative (Config.local_install_bin_dir ~context:context.name) p] + | `This_rel p when Sys.win32 -> + [p; Path.extend_basename p ~suffix:Bin.exe] + | `This_rel p -> + [p] + | `This_abs p when Path.is_in_build_dir p -> + [p] + | `This_abs _ -> + []) + |> List.map ~f:Path.to_string + |> resolve_targets ~log common setup + |> List.concat_map ~f:(function + | Ok targets -> targets + | Error _ -> []) + ) in + let real_prog = + if not no_rebuild then begin + match Lazy.force targets with + | [] -> () + | targets -> + Scheduler.go ~log ~common (do_build setup targets); + Build_system.finalize setup.build_system + end; + match prog_where with + | `Search prog -> + let path = Config.local_install_bin_dir ~context:context.name :: context.path in + Bin.which prog ~path + | `This_rel prog + | `This_abs prog -> + if Path.exists prog then + Some prog + else if not Sys.win32 then + None + else + let prog = Path.extend_basename prog ~suffix:Bin.exe in + Option.some_if (Path.exists prog) prog + in + match real_prog, no_rebuild with + | None, true -> + begin match Lazy.force targets with + | [] -> + Format.eprintf "@{Error@}: Program %S not found!@." prog; + raise Already_reported + | _::_ -> + Format.eprintf "@{Error@}: Program %S isn't built yet \ + you need to buid it first or remove the \ + --no-build option.@." prog; + raise Already_reported + end + | None, false -> Format.eprintf "@{Error@}: Program %S not found!@." prog; raise Already_reported - | _::_ -> - Format.eprintf "@{Error@}: Program %S isn't built yet \ - you need to buid it first or remove the \ - --no-build option.@." prog; - raise Already_reported - end - | None, false -> - Format.eprintf "@{Error@}: Program %S not found!@." prog; - raise Already_reported - | Some real_prog, _ -> - let real_prog = Path.to_string real_prog in - let argv = Array.of_list (prog :: args) in - restore_cwd_and_execve common real_prog argv context.env - in - ( Term.(const go - $ common - $ context_arg ~doc:{|Run the command in this build context.|} - $ Arg.(required - & pos 0 (some string) None (Arg.info [] ~docv:"PROG")) - $ Arg.(value & flag - & info ["no-build"] - ~doc:"don't rebuild target before executing") - $ Arg.(value - & pos_right 0 string [] (Arg.info [] ~docv:"ARGS")) - ) - , Term.info "exec" ~doc ~man) + | Some real_prog, _ -> + let real_prog = Path.to_string real_prog in + let argv = Array.of_list (prog :: args) in + restore_cwd_and_execve common real_prog argv context.env + in + ( Term.(const go + $ common + $ context_arg ~doc:{|Run the command in this build context.|} + $ Arg.(required + & pos 0 (some string) None (Arg.info [] ~docv:"PROG")) + $ Arg.(value & flag + & info ["no-build"] + ~doc:"don't rebuild target before executing") + $ Arg.(value + & pos_right 0 string [] (Arg.info [] ~docv:"ARGS")) + ) + , Term.info "exec" ~doc ~man) -let subst = - let doc = - "Substitute watermarks in source files." - in - let man = - let var name desc = - `Blocks [`Noblank; `P ("- $(b,%%" ^ name ^ "%%), " ^ desc) ] + let subst = + let doc = + "Substitute watermarks in source files." in - let opam field = - var ("PKG_" ^ String.uppercase field) - ("contents of the $(b," ^ field ^ ":) field from the opam file") + let man = + let var name desc = + `Blocks [`Noblank; `P ("- $(b,%%" ^ name ^ "%%), " ^ desc) ] + in + let opam field = + var ("PKG_" ^ String.uppercase field) + ("contents of the $(b," ^ field ^ ":) field from the opam file") + in + [ `S "DESCRIPTION" + ; `P {|Substitute $(b,%%ID%%) strings in source files, in a similar fashion to + what topkg does in the default configuration.|} + ; `P {|This command is only meant to be called when a user pins a package to + its development version. Especially it replaces $(b,%%VERSION%%) strings + by the version obtained from the vcs. Currently only git is supported and + the version is obtained from the output of:|} + ; `Pre {| \$ git describe --always --dirty|} + ; `P {|$(b,dune subst) substitutes the variables that topkg substitutes with + the defatult configuration:|} + ; var "NAME" "the name of the package" + ; var "VERSION" "output of $(b,git describe --always --dirty)" + ; var "VERSION_NUM" "same as $(b,%%VERSION%%) but with a potential leading \ + 'v' or 'V' dropped" + ; var "VCS_COMMIT_ID" "commit hash from the vcs" + ; opam "maintainer" + ; opam "authors" + ; opam "homepage" + ; opam "issues" + ; opam "doc" + ; opam "license" + ; opam "repo" + ; `P {|It is not possible to customize this list. If you wish to do so you need to + configure topkg instead and use it to perform the substitution.|} + ; `P {|Note that the expansion of $(b,%%NAME%%) is guessed using the following + heuristic: if all the $(b,.opam) files in the current directory are + prefixed by the shortest package name, this prefix is used. Otherwise you must + specify a name with the $(b,-n) command line option.|} + ; `P {|In order to call $(b,dune subst) when your package is pinned, add this line + to the $(b,build:) field of your opam file:|} + ; `Pre (sprintf {| [%S "subst"] {pinned}|} program_name) + ; `Blocks help_secs + ] in - [ `S "DESCRIPTION" - ; `P {|Substitute $(b,%%ID%%) strings in source files, in a similar fashion to - what topkg does in the default configuration.|} - ; `P {|This command is only meant to be called when a user pins a package to - its development version. Especially it replaces $(b,%%VERSION%%) strings - by the version obtained from the vcs. Currently only git is supported and - the version is obtained from the output of:|} - ; `Pre {| \$ git describe --always --dirty|} - ; `P {|$(b,jbuilder subst) substitutes the variables that topkg substitutes with - the defatult configuration:|} - ; var "NAME" "the name of the package" - ; var "VERSION" "output of $(b,git describe --always --dirty)" - ; var "VERSION_NUM" "same as $(b,%%VERSION%%) but with a potential leading \ - 'v' or 'V' dropped" - ; var "VCS_COMMIT_ID" "commit hash from the vcs" - ; opam "maintainer" - ; opam "authors" - ; opam "homepage" - ; opam "issues" - ; opam "doc" - ; opam "license" - ; opam "repo" - ; `P {|It is not possible to customize this list. If you wish to do so you need to - configure topkg instead and use it to perform the substitution.|} - ; `P {|Note that the expansion of $(b,%%NAME%%) is guessed using the following - heuristic: if all the $(b,.opam) files in the current directory are - prefixed by the shortest package name, this prefix is used. Otherwise you must - specify a name with the $(b,-n) command line option.|} - ; `P {|In order to call $(b,jbuilder subst) when your package is pinned, add this line - to the $(b,build:) field of your opam file:|} - ; `Pre {| ["jbuilder" "subst"] {pinned}|} - ; `Blocks help_secs - ] - in - let go common name = - set_common common ~targets:[]; - Scheduler.go ~common (Watermarks.subst ?name ()) - in - ( Term.(const go - $ common - $ Arg.(value - & opt (some string) None - & info ["n"; "name"] ~docv:"NAME" - ~doc:"Use this package name instead of detecting it.") - ) - , Term.info "subst" ~doc ~man) - -let utop = - let doc = "Load library in utop" in - let man = - [ `S "DESCRIPTION" - ; `P {|$(b,jbuilder utop DIR) build and run utop toplevel with libraries defined in DIR|} - ; `Blocks help_secs - ] in - let go common dir ctx_name args = - let utop_target = dir |> Path.of_string |> Utop.utop_exe |> Path.to_string in - set_common common ~targets:[utop_target]; - let log = Log.create common in - let (build_system, context, utop_path) = - (Main.setup ~log common >>= fun setup -> - let context = Main.find_context_exn setup ~name:ctx_name in - let setup = { setup with contexts = [context] } in - let target = - match resolve_targets_exn ~log common setup [utop_target] with - | [] -> die "no libraries defined in %s" dir - | [File target] -> target - | [Alias_rec _] | _::_::_ -> assert false - in - do_build setup [File target] >>| fun () -> - (setup.build_system, context, Path.to_string target) - ) |> Scheduler.go ~log ~common in - Build_system.finalize build_system; - restore_cwd_and_execve common utop_path (Array.of_list (utop_path :: args)) - context.env - in - let name_ = Arg.info [] ~docv:"PATH" in - ( Term.(const go - $ common - $ Arg.(value & pos 0 dir "" name_) - $ context_arg ~doc:{|Select context where to build/run utop.|} - $ Arg.(value & pos_right 0 string [] (Arg.info [] ~docv:"ARGS"))) - , Term.info "utop" ~doc ~man ) - -let promote = - let doc = "Promote files from the last run" in - let man = - [ `S "DESCRIPTION" - ; `P {|Considering all actions of the form $(b,(diff a b)) that failed - in the last run of jbuilder, $(b,jbuilder promote) does the following: - - If $(b,a) is present in the source tree but $(b,b) isn't, $(b,b) is - copied over to $(b,a) in the source tree. The idea behind this is that - you might use $(b,(diff file.expected file.generated)) and then call - $(b,jbuilder promote) to promote the generated file. - |} - ; `Blocks help_secs - ] in - let go common = - set_common common ~targets:[]; - (* We load and restore the digest cache as we need to clear the - cache for promoted files, due to issues on OSX. *) - Utils.Cached_digest.load (); - Action.Promotion.promote_files_registered_in_last_run (); - Utils.Cached_digest.dump () - in - ( Term.(const go - $ common) - , Term.info "promote" ~doc ~man ) - -module Help = struct - let config = - ("dune-config", 5, "", "Jbuilder", "Jbuilder manual"), - [ `S Manpage.s_synopsis - ; `Pre "~/.config/dune/config" - ; `S Manpage.s_description - ; `P {|Unless $(b,--no-config) or $(b,-p) is passed, Jbuilder will read a - configuration file from the user home directory. This file is used - to control various aspects of the behavior of Jbuilder.|} - ; `P {|The configuration file is normally $(b,~/.config/dune/config) on - Unix systems and $(b,Local Settings/dune/config) in the User home - directory on Windows. However, it is possible to specify an - alternative configuration file with the $(b,--config-file) option.|} - ; `P {|This file must be written in S-expression syntax and be composed of - a list of stanzas. The following sections describe the stanzas available.|} - ; `S "DISPLAY MODES" - ; `P {|Syntax: $(b,\(display MODE\))|} - ; `P {|This stanza controls how Jbuilder reports what it is doing to the user. - This parameter can also be set from the command line via $(b,--display MODE). - The following display modes are available:|} - ; `Blocks - (List.map ~f:(fun (x, desc) -> `I (sprintf "$(b,%s)" x, desc)) - [ "progress", - {|This is the default, Jbuilder shows and update a - status line as build goals are being completed.|} - ; "quiet", - {|Only display errors.|} - ; "short", - {|Print one line per command being executed, with the - binary name on the left and the reason it is being executed for - on the right.|} - ; "verbose", - {|Print the full command lines of programs being - executed by Jbuilder, with some colors to help differentiate - programs.|} - ]) - ; `P {|Note that when the selected display mode is $(b,progress) and the - output is not a terminal then the $(b,quiet) mode is selected - instead. This rule doesn't apply when running Jbuilder inside Emacs. - Jbuilder detects whether it is executed from inside Emacs or not by - looking at the environment variable $(b,INSIDE_EMACS) that is set by - Emacs. If you want the same behavior with another editor, you can set - this variable. If your editor already sets another variable, - please open a ticket on the ocaml/dune github project so that we can - add support for it.|} - ; `S "JOBS" - ; `P {|Syntax: $(b,\(jobs NUMBER\))|} - ; `P {|Set the maximum number of jobs Jbuilder might run in parallel. - This can also be set from the command line via $(b,-j NUMBER).|} - ; `P {|The default for this value is 4.|} - ; common_footer - ] - - type what = - | Man of Manpage.t - | List_topics + let go common name = + set_common common ~targets:[]; + Scheduler.go ~common (Watermarks.subst ?name ()) + in + ( Term.(const go + $ common + $ Arg.(value + & opt (some string) None + & info ["n"; "name"] ~docv:"NAME" + ~doc:"Use this package name instead of detecting it.") + ) + , Term.info "subst" ~doc ~man) - let commands = - [ "config", Man config - ; "topics", List_topics - ] + let utop = + let doc = "Load library in utop" in + let man = + [ `S "DESCRIPTION" + ; `P {|$(b,dune utop DIR) build and run utop toplevel with libraries defined in DIR|} + ; `Blocks help_secs + ] in + let go common dir ctx_name args = + let utop_target = dir |> Path.of_string |> Utop.utop_exe |> Path.to_string in + set_common common ~targets:[utop_target]; + let log = Log.create common in + let (build_system, context, utop_path) = + (Main.setup ~log common >>= fun setup -> + let context = Main.find_context_exn setup ~name:ctx_name in + let setup = { setup with contexts = [context] } in + let target = + match resolve_targets_exn ~log common setup [utop_target] with + | [] -> die "no libraries defined in %s" dir + | [File target] -> target + | [Alias_rec _] | _::_::_ -> assert false + in + do_build setup [File target] >>| fun () -> + (setup.build_system, context, Path.to_string target) + ) |> Scheduler.go ~log ~common in + Build_system.finalize build_system; + restore_cwd_and_execve common utop_path (Array.of_list (utop_path :: args)) + context.env + in + let name_ = Arg.info [] ~docv:"PATH" in + ( Term.(const go + $ common + $ Arg.(value & pos 0 dir "" name_) + $ context_arg ~doc:{|Select context where to build/run utop.|} + $ Arg.(value & pos_right 0 string [] (Arg.info [] ~docv:"ARGS"))) + , Term.info "utop" ~doc ~man ) - let help = - let doc = "Additional Jbuilder help" in + let promote = + let doc = "Promote files from the last run" in let man = [ `S "DESCRIPTION" - ; `P {|$(b,jbuilder help TOPIC) provides additional help on the given topic. - The following topics are available:|} - ; `Blocks (List.concat_map commands ~f:(fun (s, what) -> - match what with - | List_topics -> [] - | Man ((title, _, _, _, _), _) -> [`I (sprintf "$(b,%s)" s, title)])) + ; `P {|Considering all actions of the form $(b,(diff a b)) that failed + in the last run of dune, $(b,dune promote) does the following: + + If $(b,a) is present in the source tree but $(b,b) isn't, $(b,b) is + copied over to $(b,a) in the source tree. The idea behind this is that + you might use $(b,(diff file.expected file.generated)) and then call + $(b,dune promote) to promote the generated file. + |} + ; `Blocks help_secs + ] in + let go common = + set_common common ~targets:[]; + (* We load and restore the digest cache as we need to clear the + cache for promoted files, due to issues on OSX. *) + Utils.Cached_digest.load (); + Action.Promotion.promote_files_registered_in_last_run (); + Utils.Cached_digest.dump () + in + ( Term.(const go + $ common) + , Term.info "promote" ~doc ~man ) + + module Help = struct + let config = + ("dune-config", 5, "", "Dune", "Dune manual"), + [ `S Manpage.s_synopsis + ; `Pre "~/.config/dune/config" + ; `S Manpage.s_description + ; `P {|Unless $(b,--no-config) or $(b,-p) is passed, Dune will read a + configuration file from the user home directory. This file is used + to control various aspects of the behavior of Dune.|} + ; `P {|The configuration file is normally $(b,~/.config/dune/config) on + Unix systems and $(b,Local Settings/dune/config) in the User home + directory on Windows. However, it is possible to specify an + alternative configuration file with the $(b,--config-file) option.|} + ; `P {|This file must be written in S-expression syntax and be composed of + a list of stanzas. The following sections describe the stanzas available.|} + ; `S "DISPLAY MODES" + ; `P {|Syntax: $(b,\(display MODE\))|} + ; `P {|This stanza controls how Dune reports what it is doing to the user. + This parameter can also be set from the command line via $(b,--display MODE). + The following display modes are available:|} + ; `Blocks + (List.map ~f:(fun (x, desc) -> `I (sprintf "$(b,%s)" x, desc)) + [ "progress", + {|This is the default, Dune shows and update a + status line as build goals are being completed.|} + ; "quiet", + {|Only display errors.|} + ; "short", + {|Print one line per command being executed, with the + binary name on the left and the reason it is being executed for + on the right.|} + ; "verbose", + {|Print the full command lines of programs being + executed by Dune, with some colors to help differentiate + programs.|} + ]) + ; `P {|Note that when the selected display mode is $(b,progress) and the + output is not a terminal then the $(b,quiet) mode is selected + instead. This rule doesn't apply when running Dune inside Emacs. + Dune detects whether it is executed from inside Emacs or not by + looking at the environment variable $(b,INSIDE_EMACS) that is set by + Emacs. If you want the same behavior with another editor, you can set + this variable. If your editor already sets another variable, + please open a ticket on the ocaml/dune github project so that we can + add support for it.|} + ; `S "JOBS" + ; `P {|Syntax: $(b,\(jobs NUMBER\))|} + ; `P {|Set the maximum number of jobs Dune might run in parallel. + This can also be set from the command line via $(b,-j NUMBER).|} + ; `P {|The default for this value is 4.|} ; common_footer ] - in - let go man_format what = - match what with - | None -> - `Help (man_format, Some "help") - | Some (Man man_page) -> - Format.printf "%a@?" (Manpage.print man_format) man_page; - `Ok () - | Some List_topics -> - List.filter_map commands ~f:(fun (s, what) -> - match what with - | List_topics -> None - | _ -> Some s) - |> List.sort ~compare:String.compare - |> String.concat ~sep:"\n" - |> print_endline; - `Ok () - in - ( Term.(ret (const go - $ Arg.man_format - $ Arg.(value - & pos 0 (some (enum commands)) None - & info [] ~docv:"TOPIC") - )) - , Term.info "help" ~doc ~man - ) -end -let all = - [ installed_libraries - ; external_lib_deps - ; build_targets - ; runtest - ; clean - ; install - ; uninstall - ; exec - ; subst - ; rules - ; utop - ; promote - ; Help.help - ] + type what = + | Man of Manpage.t + | List_topics + + let commands = + [ "config", Man config + ; "topics", List_topics + ] -let default = - let doc = "composable build system for OCaml" in - ( Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common)) - , Term.info "jbuilder" ~doc ~version:"%%VERSION%%" - ~man: + let help = + let doc = "Additional Dune help" in + let man = [ `S "DESCRIPTION" - ; `P {|Jbuilder is a build system designed for OCaml projects only. It - focuses on providing the user with a consistent experience and takes - care of most of the low-level details of OCaml compilation. All you - have to do is provide a description of your project and Jbuilder will - do the rest. - |} - ; `P {|The scheme it implements is inspired from the one used inside Jane - Street and adapted to the open source world. It has matured over a - long time and is used daily by hundreds of developers, which means - that it is highly tested and productive. - |} - ; `Blocks help_secs + ; `P {|$(b,dune help TOPIC) provides additional help on the given topic. + The following topics are available:|} + ; `Blocks (List.concat_map commands ~f:(fun (s, what) -> + match what with + | List_topics -> [] + | Man ((title, _, _, _, _), _) -> [`I (sprintf "$(b,%s)" s, title)])) + ; common_footer ] - ) + in + let go man_format what = + match what with + | None -> + `Help (man_format, Some "help") + | Some (Man man_page) -> + Format.printf "%a@?" (Manpage.print man_format) man_page; + `Ok () + | Some List_topics -> + List.filter_map commands ~f:(fun (s, what) -> + match what with + | List_topics -> None + | _ -> Some s) + |> List.sort ~compare:String.compare + |> String.concat ~sep:"\n" + |> print_endline; + `Ok () + in + ( Term.(ret (const go + $ Arg.man_format + $ Arg.(value + & pos 0 (some (enum commands)) None + & info [] ~docv:"TOPIC") + )) + , Term.info "help" ~doc ~man + ) + end + + let all = + [ installed_libraries + ; external_lib_deps + ; build_targets + ; runtest + ; clean + ; install + ; uninstall + ; exec + ; subst + ; rules + ; utop + ; promote + ; Help.help + ] + + let default = + let doc = "composable build system for OCaml" in + ( Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common)) + , Term.info program_name ~doc ~version:"%%VERSION%%" + ~man: + [ `S "DESCRIPTION" + ; `P {|Dune is a build system designed for OCaml projects only. It + focuses on providing the user with a consistent experience and takes + care of most of the low-level details of OCaml compilation. All you + have to do is provide a description of your project and Dune will + do the rest. + |} + ; `P {|The scheme it implements is inspired from the one used inside Jane + Street and adapted to the open source world. It has matured over a + long time and is used daily by hundreds of developers, which means + that it is highly tested and productive. + |} + ; `Blocks help_secs + ] + ) -let () = - Colors.setup_err_formatter_colors (); - try - match Term.eval_choice default all ~catch:false with - | `Error _ -> exit 1 - | _ -> exit 0 - with - | Fiber.Never -> exit 1 - | exn -> - Report_error.report exn; - exit 1 + let () = + Colors.setup_err_formatter_colors (); + try + match Term.eval_choice default all ~catch:false with + | `Error _ -> exit 1 + | _ -> exit 0 + with + | Fiber.Never -> exit 1 + | exn -> + Report_error.report exn; + exit 1 +end diff --git a/bin/main.mli b/bin/main.mli index e790aeb70f0..622a8287404 100644 --- a/bin/main.mli +++ b/bin/main.mli @@ -1 +1,3 @@ -(* empty *) +type which = Dune | Jbuilder + +module Make(M : sig val which : which end) : sig end diff --git a/bin/main_dune.ml b/bin/main_dune.ml new file mode 100644 index 00000000000..014b18448b6 --- /dev/null +++ b/bin/main_dune.ml @@ -0,0 +1 @@ +include Main.Make(struct let which = Main.Dune end) diff --git a/bin/main_dune.mli b/bin/main_dune.mli new file mode 100644 index 00000000000..e790aeb70f0 --- /dev/null +++ b/bin/main_dune.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/bin/main_jbuilder.ml b/bin/main_jbuilder.ml new file mode 100644 index 00000000000..aa9950e99d3 --- /dev/null +++ b/bin/main_jbuilder.ml @@ -0,0 +1 @@ +include Main.Make(struct let which = Main.Jbuilder end) diff --git a/bin/main_jbuilder.mli b/bin/main_jbuilder.mli new file mode 100644 index 00000000000..e790aeb70f0 --- /dev/null +++ b/bin/main_jbuilder.mli @@ -0,0 +1 @@ +(* empty *) From b785e2282c9762a2f08b4aa68f1d7f1af3598e11 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 24 Apr 2018 15:41:00 +0100 Subject: [PATCH 03/15] Preliminary support for dune-project files --- bin/main.ml | 7 ++- doc/jbuild.rst | 4 +- doc/project-layout-specification.rst | 38 +++++++++++++-- doc/usage.rst | 5 +- src/dune_project.ml | 69 ++++++++++++++++++++++++++++ src/dune_project.mli | 10 ++++ src/jbuild_load.ml | 25 ++++++++++ 7 files changed, 148 insertions(+), 10 deletions(-) create mode 100644 src/dune_project.ml create mode 100644 src/dune_project.mli diff --git a/bin/main.ml b/bin/main.ml index f00e4700295..d1b64cb5e8b 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -147,9 +147,12 @@ module Make(M : sig val which : which end) = struct let files = Sys.readdir dir |> Array.to_list |> String.Set.of_list in if String.Set.mem files "jbuild-workspace" then cont counter ~candidates:((0, dir, to_cwd) :: candidates) dir ~to_cwd - else if String.Set.exists files ~f:(fun fn -> - String.is_prefix fn ~prefix:"jbuild-workspace") then + else if M.which = Jbuilder && + String.Set.exists files ~f:(fun fn -> + String.is_prefix fn ~prefix:"jbuild-workspace") then cont counter ~candidates:((1, dir, to_cwd) :: candidates) dir ~to_cwd + else if String.Set.mem files "dune-project" then + cont counter ~candidates:((2, dir, to_cwd) :: candidates) dir ~to_cwd else cont counter ~candidates dir ~to_cwd and cont counter ~candidates ~to_cwd dir = diff --git a/doc/jbuild.rst b/doc/jbuild.rst index fc376ec55bc..7026ff10e3a 100644 --- a/doc/jbuild.rst +++ b/doc/jbuild.rst @@ -31,8 +31,8 @@ The following sections describe the available stanzas and their meaning. jbuild_version -------------- -``(jbuild_version 1)`` specifies that we are using the version 1 of -the Jbuilder metadata format in this ``jbuild`` file. +Deprecated. This stanza is no longer used and will be removed in the +future. library ------- diff --git a/doc/project-layout-specification.rst b/doc/project-layout-specification.rst index 44305a30d48..20b71efb3b0 100644 --- a/doc/project-layout-specification.rst +++ b/doc/project-layout-specification.rst @@ -2,9 +2,10 @@ Project Layout and Metadata Specification ***************************************** -A typical jbuilder project will have one or more ``.opam`` file -at toplevel as well as ``jbuild`` files wherever interesting things are: -libraries, executables, tests, documents to install, etc... +A typical jbuilder project will have a ```dune-project`` and one or +more ``.opam`` file at toplevel as well as ``jbuild`` files +wherever interesting things are: libraries, executables, tests, +documents to install, etc... It is recommended to organize your project so that you have exactly one library per directory. You can have several executables in the same @@ -83,10 +84,10 @@ Examples this_is_an_atom_123'&^%! ; this is a comment "another atom in an OCaml-string \"string in a string\" \123" - + ; empty list follows below () - + ; a more complex example ( ( @@ -103,6 +104,33 @@ Examples .. _opam-files: +dune-project files +================== + +These files are used to mark the root of projects as well as define +project-wide parameters. These files are required to have a ``lang`` +which controls the names and contents of all configuration files read +by Dune. The ``lang`` stanza looks like: + +.. code:: scheme + + (lang dune 0.1) + +The 0.1 version of the language is exactly the same as the Jbuilder +language. So to convert a Jbuilder project to Dune, simply write this +file at the root of your project. + +Additionally, they can contains the following stanzas. + +name +---- + +Sets the name of the project: + +.. code:: scheme + + (name ) + .opam files ==================== diff --git a/doc/usage.rst b/doc/usage.rst index 20059b74fde..d253f94bc6a 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -15,7 +15,8 @@ jbuild-workspace ---------------- The root of the current workspace is determined by looking up a -``jbuild-workspace`` file in the current directory and parent directories. +``jbuild-workspace`` or ``dune-project`` file in the current directory +and parent directories. ``jbuilder`` prints out the root when starting if it is not the current directory: @@ -50,6 +51,8 @@ this file. jbuild-workspace\* ------------------ +The following is deprecated and no longer works with ``dune``. + In addition to the previous rule, if no ``jbuild-workspace`` file is found, ``jbuilder`` will look for any file whose name starts with ``jbuild-workspace`` in ancestor directories. For instance ``jbuild-workspace.dev``. If such a file diff --git a/src/dune_project.ml b/src/dune_project.ml new file mode 100644 index 00000000000..3d68083d71e --- /dev/null +++ b/src/dune_project.ml @@ -0,0 +1,69 @@ +open Import +open Sexp.Of_sexp + +type t = + { name : string + } + +let filename = "dune-project" + +type lang = + | Dune_0_1 + +let lang = + let version ver = + match string ver with + | "0.1" -> Dune_0_1 + | _ -> + of_sexp_error ver "unsupported version of the dune language" + in + let name = + enum + [ ("dune", ()) ] + in + sum + [ cstr "lang" (name @> version @> nil) (fun () v -> v) ] + +module Acc = struct + type t = + { name : string option + } + + let init = + { name = None } +end + +let load ~dir = + let fname = Path.to_string (Path.relative dir filename) in + let sexps = Sexp.load ~fname ~mode:Many in + let langs, sexps = + List.partition_map sexps ~f:(function + | List (loc, Atom (_, A "lang") :: _) as sexp -> + Left (lang sexp, loc) + | sexp -> Right sexp) + in + let _lang = + match langs with + | [] -> + Loc.fail (Loc.in_file fname) + "language not specified, you need to add (lang dune 0.1)" + | [(v, _)] -> v + | _ :: (_, loc) :: _ -> + Loc.fail loc "language specified too many times" + in + let acc = + List.fold_left sexps ~init:Acc.init ~f:(fun (acc : Acc.t) sexp -> + sum + [ cstr "lang" nil acc + ; cstr_loc "name" (string @> nil) (fun loc name -> + match acc.name with + | None -> { Acc.name = Some name } + | Some _ -> Loc.fail loc "name specified too many times") + ] + sexp) + in + { name = + match acc.name with + | Some s -> s + | None -> "_" ^ String.concat ~sep:"_" (Path.explode_exn dir) + } diff --git a/src/dune_project.mli b/src/dune_project.mli new file mode 100644 index 00000000000..9a6e7a59468 --- /dev/null +++ b/src/dune_project.mli @@ -0,0 +1,10 @@ +(** dune-project files *) + +type t = + { name : string + } + +val load : dir:Path.t -> t + +(** "dune-project" *) +val filename : string diff --git a/src/jbuild_load.ml b/src/jbuild_load.ml index 3c8d6a7b2fb..056ba8aabf4 100644 --- a/src/jbuild_load.ml +++ b/src/jbuild_load.ml @@ -258,6 +258,31 @@ let load ?extra_ignored_subtrees ?(ignore_promoted_rules=false) () = |> Path.Map.of_list_multi |> Path.Map.map ~f:Scope_info.make in + + let projects = + File_tree.fold ftree ~traverse_ignored_dirs:false ~init:[] + ~f:(fun dir acc -> + let path = File_tree.Dir.path dir in + let files = File_tree.Dir.files dir in + if String.Set.mem files Dune_project.filename then begin + (path, Dune_project.load ~dir:path) :: acc + end else + acc) + |> Path.Map.of_list_exn + in + let scopes = + Path.Map.merge scopes projects ~f:(fun path scope project -> + match scope, project with + | None, None -> assert false + | Some _, None -> scope + | None, Some { name } -> + Some { name = Some name + ; packages = Package.Name.Map.empty + ; root = path + } + | Some scope, Some { name } -> Some { scope with name = Some name }) + in + let scopes = if Path.Map.mem scopes Path.root then scopes From c200b4c178b1882c7942ff6af1fd434e83425bd0 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 24 Apr 2018 15:44:35 +0100 Subject: [PATCH 04/15] Add a dune-project file --- dune-project | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 dune-project diff --git a/dune-project b/dune-project new file mode 100644 index 00000000000..fd56c71312b --- /dev/null +++ b/dune-project @@ -0,0 +1,2 @@ +(lang dune 0.1) +(name dune) From fd8429143c47b8e20bed4b40e43dc8ab5af65134 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Wed, 25 Apr 2018 17:45:14 +0100 Subject: [PATCH 05/15] Make dune look for dune-workspace rather than jbuild-workspace --- bin/main.ml | 19 ++++++++++++++----- src/dune_project.ml | 6 +++--- src/dune_project.mli | 2 ++ src/main.ml | 9 +++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/bin/main.ml b/bin/main.ml index d1b64cb5e8b..eea4ab6ee92 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -15,6 +15,11 @@ module Make(M : sig val which : which end) = struct | Jbuilder -> "jbuilder" | Dune -> "dune" + let workspace_file = + match M.which with + | Jbuilder -> "jbuild-workspace" + | Dune -> "dune-workspace" + type common = { debug_dep_path : bool ; debug_findlib : bool @@ -83,7 +88,11 @@ module Make(M : sig val which : which end) = struct let setup ~log ?external_lib_deps_mode common = setup ~log - ?workspace_file:(Option.map ~f:Path.of_string common.workspace_file) + ~workspace_file:( + Path.of_string ( + match common.workspace_file with + | Some fn -> fn + | None -> workspace_file)) ?only_packages:common.only_packages ?external_lib_deps_mode ?x:common.x @@ -145,13 +154,13 @@ module Make(M : sig val which : which end) = struct let cwd = Sys.getcwd () in let rec loop counter ~candidates ~to_cwd dir = let files = Sys.readdir dir |> Array.to_list |> String.Set.of_list in - if String.Set.mem files "jbuild-workspace" then + if String.Set.mem files workspace_file then cont counter ~candidates:((0, dir, to_cwd) :: candidates) dir ~to_cwd else if M.which = Jbuilder && String.Set.exists files ~f:(fun fn -> - String.is_prefix fn ~prefix:"jbuild-workspace") then + String.is_prefix fn ~prefix:workspace_file) then cont counter ~candidates:((1, dir, to_cwd) :: candidates) dir ~to_cwd - else if String.Set.mem files "dune-project" then + else if String.Set.mem files Dune_project.filename then cont counter ~candidates:((2, dir, to_cwd) :: candidates) dir ~to_cwd else cont counter ~candidates dir ~to_cwd @@ -479,7 +488,7 @@ module Make(M : sig val which : which end) = struct else [] ; (match config_file with - | This fn -> ["--config-file"; fn] + | This fn -> ["--config-file"; Path.to_string fn] | No_config -> ["--no-config"] | Default -> []) ] diff --git a/src/dune_project.ml b/src/dune_project.ml index 3d68083d71e..4baf76ab66f 100644 --- a/src/dune_project.ml +++ b/src/dune_project.ml @@ -34,8 +34,8 @@ module Acc = struct end let load ~dir = - let fname = Path.to_string (Path.relative dir filename) in - let sexps = Sexp.load ~fname ~mode:Many in + let fname = Path.relative dir filename in + let sexps = Io.Sexp.load fname ~mode:Many in let langs, sexps = List.partition_map sexps ~f:(function | List (loc, Atom (_, A "lang") :: _) as sexp -> @@ -45,7 +45,7 @@ let load ~dir = let _lang = match langs with | [] -> - Loc.fail (Loc.in_file fname) + Loc.fail (Loc.in_file (Path.to_string fname)) "language not specified, you need to add (lang dune 0.1)" | [(v, _)] -> v | _ :: (_, loc) :: _ -> diff --git a/src/dune_project.mli b/src/dune_project.mli index 9a6e7a59468..07dbf30a84f 100644 --- a/src/dune_project.mli +++ b/src/dune_project.mli @@ -1,5 +1,7 @@ (** dune-project files *) +open Import + type t = { name : string } diff --git a/src/main.ml b/src/main.ml index 8d942f777ad..b493bb56a6c 100644 --- a/src/main.ml +++ b/src/main.ml @@ -30,7 +30,7 @@ let setup_env ~capture_outputs = let setup ?(log=Log.no_log) ?external_lib_deps_mode - ?workspace ?(workspace_file=Path.of_string "jbuild-workspace") + ?workspace ?workspace_file ?only_packages ?extra_ignored_subtrees ?x @@ -55,9 +55,10 @@ let setup ?(log=Log.no_log) match workspace with | Some w -> w | None -> - if Path.exists workspace_file then - Workspace.load ?x workspace_file - else + match workspace_file with + | Some p when Path.exists p -> + Workspace.load ?x p + | _ -> { merlin_context = Some "default" ; contexts = [Default [ match x with From a4c586ddc05aac7cb30d5b63733db68dc623af03 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Wed, 25 Apr 2018 17:46:38 +0100 Subject: [PATCH 06/15] jbuild-workspace.dev --> dune-workspace.dev --- Makefile | 2 +- jbuild-workspace.dev => dune-workspace.dev | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename jbuild-workspace.dev => dune-workspace.dev (100%) diff --git a/Makefile b/Makefile index cde32d45d23..ba6526f4e7a 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ promote: accept-corrections: promote all-supported-ocaml-versions: - $(BIN) build --dev @install @runtest --workspace jbuild-workspace.dev --root . + $(BIN) build --dev @install @runtest --workspace dune-workspace.dev --root . clean: $(BIN) clean diff --git a/jbuild-workspace.dev b/dune-workspace.dev similarity index 100% rename from jbuild-workspace.dev rename to dune-workspace.dev From 829f6cfd63b3bb5b62b7e33b2f740e4b412aa044 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Thu, 26 Apr 2018 16:26:04 +0100 Subject: [PATCH 07/15] Update the travis script --- .travis-ci.sh | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index a22e62966ea..1d81364ac82 100644 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -48,6 +48,9 @@ case "$TARGET" in eval $(opam config env) opam install utop ppx_driver odoc menhir ocaml-migrate-parsetree js_of_ocaml-ppx js_of_ocaml-compiler--yes opam remove jbuilder `opam list --depends-on jbuilder --installed --short` --yes + if opam info dune &> /dev/null; then + opam remove dune `opam list --depends-on dune --installed --short` --yes + fi fi cp -a ~/.opam ~/.opam-start echo -en "travis_fold:end:opam.init\r" @@ -63,6 +66,10 @@ case "$TARGET" in UPDATE_OPAM=1 opam pin remove jbuilder --no-action --yes opam remove jbuilder --yes + if opam pin list -s | grep dune; then + opam pin remove dune --no-action --yes + opam remove dune --yes + fi fi if [ ! -e ~/.opam/last-update ] || [ $(cat ~/.opam/last-update) != $DATE ] ; then opam update --yes @@ -71,22 +78,34 @@ case "$TARGET" in opam upgrade --yes fi opam list - echo "version: \"1.0+dev$DATE\"" >> jbuilder.opam + echo "version: \"1.0+dev$DATE\"" >> dune.opam + cat > jbuilder.opam <"] +homepage: "https://github.com/ocaml/dune" +bug-reports: "https://github.com/ocaml/dune/issues" +dev-repo: "https://github.com/ocaml/dune.git" +license: "Apache-2.0" +depends: [ "dune" ] +EOF + opam pin add dune . --no-action --yes opam pin add jbuilder . --no-action --yes opam install utop ppx_driver odoc ocaml-migrate-parsetree js_of_ocaml-ppx js_of_ocaml-compiler --yes echo -en "travis_fold:end:opam.deps\r" fi - echo -en "travis_fold:start:jbuilder.bootstrap\r" + echo -en "travis_fold:start:dune.bootstrap\r" ocaml bootstrap.ml - echo -en "travis_fold:end:jbuilder.bootstrap\r" + echo -en "travis_fold:end:dune.bootstrap\r" ./boot.exe --subst - echo -en "travis_fold:start:jbuilder.boot\r" + echo -en "travis_fold:start:dune.boot\r" ./boot.exe --dev - echo -en "travis_fold:end:jbuilder.boot\r" + echo -en "travis_fold:end:dune.boot\r" if [ $WITH_OPAM -eq 1 ] ; then - _build/install/default/bin/jbuilder runtest && \ - _build/install/default/bin/jbuilder build @test/blackbox-tests/runtest-js && \ - ! _build/install/default/bin/jbuilder build @test/fail-with-background-jobs-running + _build/install/default/bin/dune runtest && \ + _build/install/default/bin/dune build @test/blackbox-tests/runtest-js && \ + ! _build/install/default/bin/dune build @test/fail-with-background-jobs-running RESULT=$? if [ $UPDATE_OPAM -eq 0 ] ; then rm -rf ~/.opam From 054909452f84cec52b7004628bbd6c2b31b2a44f Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Thu, 26 Apr 2018 17:25:53 +0100 Subject: [PATCH 08/15] s/jbuilder/dune/ for ./boot.exe --subst --- src/main.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ml b/src/main.ml index b493bb56a6c..b7e8e9f06a5 100644 --- a/src/main.ml +++ b/src/main.ml @@ -194,7 +194,7 @@ let bootstrap () = let main () = let anon s = raise (Arg.Bad (Printf.sprintf "don't know what to do with %s\n" s)) in let subst () = - Scheduler.go (Watermarks.subst () ~name:"jbuilder"); + Scheduler.go (Watermarks.subst () ~name:"dune"); exit 0 in let display = ref None in From 4523bd1b2c8f6a4ed06987d675f1b80a0883e7b1 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Mon, 30 Apr 2018 16:14:07 +0100 Subject: [PATCH 09/15] Fix for travis --- vendor/boot/opamBaseParser.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/boot/opamBaseParser.ml b/vendor/boot/opamBaseParser.ml index b90785758fa..6cf29b4bed4 100644 --- a/vendor/boot/opamBaseParser.ml +++ b/vendor/boot/opamBaseParser.ml @@ -1,6 +1,8 @@ open OpamParserTypes let main _lex _lexbuf fn = - assert (fn = "dune.opam"); + assert (fn = "dune.opam" || + (* For travis *) + fn = "jbuilder.opam"); { file_contents = [] ; file_name = fn } From 8ec41dc4bdf77a1ca66dd60d853a5f9f4c5fdb1a Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Mon, 30 Apr 2018 17:07:30 +0100 Subject: [PATCH 10/15] _ --- .travis-ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index 1d81364ac82..e4bfd8c73d2 100644 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -68,7 +68,7 @@ case "$TARGET" in opam remove jbuilder --yes if opam pin list -s | grep dune; then opam pin remove dune --no-action --yes - opam remove dune --yes + opam remove dune --yes || true fi fi if [ ! -e ~/.opam/last-update ] || [ $(cat ~/.opam/last-update) != $DATE ] ; then From d3d68baad5d4f1e1dfd41b76ad52ffe90855572f Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Mon, 30 Apr 2018 19:13:03 +0100 Subject: [PATCH 11/15] _ --- .travis-ci.sh | 7 ++++--- vendor/boot/opamBaseParser.ml | 4 +--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis-ci.sh b/.travis-ci.sh index e4bfd8c73d2..702158d169c 100644 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -79,7 +79,8 @@ case "$TARGET" in fi opam list echo "version: \"1.0+dev$DATE\"" >> dune.opam - cat > jbuilder.opam < ../jbuilder/jbuilder.opam < Date: Tue, 1 May 2018 12:14:27 +0100 Subject: [PATCH 12/15] _ --- test/blackbox-tests/jbuild.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/blackbox-tests/jbuild.inc b/test/blackbox-tests/jbuild.inc index ed9ac7b0af9..f366d6876b1 100644 --- a/test/blackbox-tests/jbuild.inc +++ b/test/blackbox-tests/jbuild.inc @@ -169,7 +169,7 @@ (alias ((name github717-odoc-index) (deps - ((package jbuilder) (files_recursively_in test-cases/github717-odoc-index))) + ((package dune) (files_recursively_in test-cases/github717-odoc-index))) (action (chdir test-cases/github717-odoc-index From afa4b8083f5f5a41fe7849a62e0e2317e3362646 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 1 May 2018 17:23:27 +0100 Subject: [PATCH 13/15] Simplify --- Makefile | 2 +- bin/jbuild | 10 +- bin/main.ml | 2673 ++++++++--------- bin/main.mli | 4 +- bin/main_dune.ml | 1 - bin/main_dune.mli | 1 - bin/main_jbuilder.ml | 1 - bin/main_jbuilder.mli | 1 - doc/jbuild | 27 +- doc/{jbuild.inc.dune => jbuild.inc} | 26 +- doc/jbuild.inc.jbuilder | 118 - doc/update-jbuild.sh | 10 +- src/main.ml | 26 +- test/blackbox-tests/test-cases/findlib/run.t | 2 +- test/blackbox-tests/test-cases/github25/run.t | 2 +- .../blackbox-tests/test-cases/github644/run.t | 2 +- 16 files changed, 1380 insertions(+), 1526 deletions(-) delete mode 100644 bin/main_dune.ml delete mode 100644 bin/main_dune.mli delete mode 100644 bin/main_jbuilder.ml delete mode 100644 bin/main_jbuilder.mli rename doc/{jbuild.inc.dune => jbuild.inc} (69%) delete mode 100644 doc/jbuild.inc.jbuilder diff --git a/Makefile b/Makefile index ba6526f4e7a..b9d49ac34e8 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ INSTALL_ARGS := $(if $(PREFIX),--prefix $(PREFIX),) -BIN := ./_build/default/bin/main_dune.exe +BIN := ./_build/default/bin/main.exe -include Makefile.dev diff --git a/bin/jbuild b/bin/jbuild index 92690f41c1d..19ffd943938 100644 --- a/bin/jbuild +++ b/bin/jbuild @@ -1,5 +1,9 @@ -(executables - ((names (main_dune main_jbuilder)) - (public_names ( dune jbuilder)) +(executable + ((name main) + (public_name dune) (libraries (unix dune cmdliner)) (preprocess no_preprocessing))) + +(install + ((section bin) + (files ((main.exe as jbuilder))))) diff --git a/bin/main.ml b/bin/main.ml index eea4ab6ee92..3405ad80ff3 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -1,752 +1,736 @@ -type which = Dune | Jbuilder +open Dune +open Import +open Cmdliner +open Fiber.O -module Make(M : sig val which : which end) = struct - open Dune - open Import - open Cmdliner - open Fiber.O +(* Things in src/ don't depend on cmdliner to speed up the + bootstrap, so we set this reference here *) +let () = suggest_function := Cmdliner_suggest.value - (* Things in src/ don't depend on cmdliner to speed up the - bootstrap, so we set this reference here *) - let () = suggest_function := Cmdliner_suggest.value +type common = + { debug_dep_path : bool + ; debug_findlib : bool + ; debug_backtraces : bool + ; dev_mode : bool + ; workspace_file : string option + ; root : string + ; target_prefix : string + ; only_packages : Package.Name.Set.t option + ; capture_outputs : bool + ; x : string option + ; diff_command : string option + ; auto_promote : bool + ; force : bool + ; ignore_promoted_rules : bool + ; (* Original arguments for the external-lib-deps hint *) + orig_args : string list + ; config : Config.t + } - let program_name = - match M.which with - | Jbuilder -> "jbuilder" - | Dune -> "dune" +let prefix_target common s = common.target_prefix ^ s - let workspace_file = - match M.which with - | Jbuilder -> "jbuild-workspace" - | Dune -> "dune-workspace" - - type common = - { debug_dep_path : bool - ; debug_findlib : bool - ; debug_backtraces : bool - ; dev_mode : bool - ; workspace_file : string option - ; root : string - ; target_prefix : string - ; only_packages : Package.Name.Set.t option - ; capture_outputs : bool - ; x : string option - ; diff_command : string option - ; auto_promote : bool - ; force : bool - ; ignore_promoted_rules : bool - ; (* Original arguments for the external-lib-deps hint *) - orig_args : string list - ; config : Config.t - } - - let prefix_target common s = common.target_prefix ^ s - - let set_common c ~targets = - Clflags.debug_dep_path := c.debug_dep_path; - Clflags.debug_findlib := c.debug_findlib; - Clflags.debug_backtraces := c.debug_backtraces; - Clflags.dev_mode := c.dev_mode; - Clflags.capture_outputs := c.capture_outputs; - if c.root <> Filename.current_dir_name then - Sys.chdir c.root; - Clflags.workspace_root := Sys.getcwd (); - Clflags.diff_command := c.diff_command; - Clflags.auto_promote := c.auto_promote; - Clflags.force := c.force; - Clflags.external_lib_deps_hint := - List.concat - [ [program_name; "external-lib-deps"; "--missing"] - ; c.orig_args - ; targets - ] +let set_common c ~targets = + Clflags.debug_dep_path := c.debug_dep_path; + Clflags.debug_findlib := c.debug_findlib; + Clflags.debug_backtraces := c.debug_backtraces; + Clflags.dev_mode := c.dev_mode; + Clflags.capture_outputs := c.capture_outputs; + if c.root <> Filename.current_dir_name then + Sys.chdir c.root; + Clflags.workspace_root := Sys.getcwd (); + Clflags.diff_command := c.diff_command; + Clflags.auto_promote := c.auto_promote; + Clflags.force := c.force; + Clflags.external_lib_deps_hint := + List.concat + [ ["dune"; "external-lib-deps"; "--missing"] + ; c.orig_args + ; targets + ] - let restore_cwd_and_execve common prog argv env = - let env = Env.to_unix env in - let prog = - if Filename.is_relative prog then - Filename.concat common.root prog - else - prog - in - Sys.chdir initial_cwd; - if Sys.win32 then - let pid = Unix.create_process_env prog argv env - Unix.stdin Unix.stdout Unix.stderr - in - match snd (Unix.waitpid [] pid) with - | WEXITED 0 -> () - | WEXITED n -> exit n - | WSIGNALED _ -> exit 255 - | WSTOPPED _ -> assert false +let restore_cwd_and_execve common prog argv env = + let env = Env.to_unix env in + let prog = + if Filename.is_relative prog then + Filename.concat common.root prog else - Unix.execve prog argv env + prog + in + Sys.chdir initial_cwd; + if Sys.win32 then + let pid = Unix.create_process_env prog argv env + Unix.stdin Unix.stdout Unix.stderr + in + match snd (Unix.waitpid [] pid) with + | WEXITED 0 -> () + | WEXITED n -> exit n + | WSIGNALED _ -> exit 255 + | WSTOPPED _ -> assert false + else + Unix.execve prog argv env - module Main = struct - include Dune.Main +module Main = struct + include Dune.Main - let setup ~log ?external_lib_deps_mode common = - setup - ~log - ~workspace_file:( - Path.of_string ( - match common.workspace_file with - | Some fn -> fn - | None -> workspace_file)) - ?only_packages:common.only_packages - ?external_lib_deps_mode - ?x:common.x - ~ignore_promoted_rules:common.ignore_promoted_rules - ~capture_outputs:common.capture_outputs - () - end + let setup ~log ?external_lib_deps_mode common = + setup + ~log + ?workspace_file:( + Option.map common.workspace_file ~f:Path.of_string) + ?only_packages:common.only_packages + ?external_lib_deps_mode + ?x:common.x + ~ignore_promoted_rules:common.ignore_promoted_rules + ~capture_outputs:common.capture_outputs + () +end - module Log = struct - include Dune.Log +module Log = struct + include Dune.Log - let create common = - Log.create ~display:common.config.display () - end + let create common = + Log.create ~display:common.config.display () +end - module Scheduler = struct - include Dune.Scheduler +module Scheduler = struct + include Dune.Scheduler - let go ?log ~common fiber = - let fiber = - Main.set_concurrency ?log common.config - >>= fun () -> - fiber - in - Scheduler.go ?log ~config:common.config fiber - end + let go ?log ~common fiber = + let fiber = + Main.set_concurrency ?log common.config + >>= fun () -> + fiber + in + Scheduler.go ?log ~config:common.config fiber +end - type target = - | File of Path.t - | Alias_rec of Path.t +type target = + | File of Path.t + | Alias_rec of Path.t - let request_of_targets (setup : Main.setup) targets = - let open Build.O in - let contexts = List.map setup.contexts ~f:(fun c -> c.Context.name) in - List.fold_left targets ~init:(Build.return ()) ~f:(fun acc target -> - acc >>> - match target with - | File path -> Build.path path - | Alias_rec path -> - let dir = Path.parent path in - let name = Path.basename path in - let contexts, dir = - match Path.extract_build_context dir with - | None -> (contexts, dir) - | Some ("install", _) -> - die "Invalid alias: %s.\n\ - There are no aliases in _build/install." - (Path.to_string_maybe_quoted path) - | Some (ctx, dir) -> ([ctx], dir) - in - Build_system.Alias.dep_rec_multi_contexts ~dir ~name - ~file_tree:setup.file_tree ~contexts) +let request_of_targets (setup : Main.setup) targets = + let open Build.O in + let contexts = List.map setup.contexts ~f:(fun c -> c.Context.name) in + List.fold_left targets ~init:(Build.return ()) ~f:(fun acc target -> + acc >>> + match target with + | File path -> Build.path path + | Alias_rec path -> + let dir = Path.parent path in + let name = Path.basename path in + let contexts, dir = + match Path.extract_build_context dir with + | None -> (contexts, dir) + | Some ("install", _) -> + die "Invalid alias: %s.\n\ + There are no aliases in _build/install." + (Path.to_string_maybe_quoted path) + | Some (ctx, dir) -> ([ctx], dir) + in + Build_system.Alias.dep_rec_multi_contexts ~dir ~name + ~file_tree:setup.file_tree ~contexts) - let do_build (setup : Main.setup) targets = - Build_system.do_build setup.build_system - ~request:(request_of_targets setup targets) +let do_build (setup : Main.setup) targets = + Build_system.do_build setup.build_system + ~request:(request_of_targets setup targets) - let find_root () = - let cwd = Sys.getcwd () in - let rec loop counter ~candidates ~to_cwd dir = - let files = Sys.readdir dir |> Array.to_list |> String.Set.of_list in - if String.Set.mem files workspace_file then - cont counter ~candidates:((0, dir, to_cwd) :: candidates) dir ~to_cwd - else if M.which = Jbuilder && - String.Set.exists files ~f:(fun fn -> - String.is_prefix fn ~prefix:workspace_file) then - cont counter ~candidates:((1, dir, to_cwd) :: candidates) dir ~to_cwd - else if String.Set.mem files Dune_project.filename then - cont counter ~candidates:((2, dir, to_cwd) :: candidates) dir ~to_cwd - else - cont counter ~candidates dir ~to_cwd - and cont counter ~candidates ~to_cwd dir = - if counter > String.length cwd then +let find_root () = + let cwd = Sys.getcwd () in + let rec loop counter ~candidates ~to_cwd dir = + let files = Sys.readdir dir |> Array.to_list |> String.Set.of_list in + if String.Set.mem files "dune-workspace" || + String.Set.mem files "jbuild-workspace" then + cont counter ~candidates:((0, dir, to_cwd) :: candidates) dir ~to_cwd + else if String.Set.exists files ~f:(fun fn -> + String.is_prefix fn ~prefix:"jbuild-workspace") then + cont counter ~candidates:((1, dir, to_cwd) :: candidates) dir ~to_cwd + else if String.Set.mem files Dune_project.filename then + cont counter ~candidates:((2, dir, to_cwd) :: candidates) dir ~to_cwd + else + cont counter ~candidates dir ~to_cwd + and cont counter ~candidates ~to_cwd dir = + if counter > String.length cwd then + candidates + else + let parent = Filename.dirname dir in + if parent = dir then candidates else - let parent = Filename.dirname dir in - if parent = dir then - candidates - else - let base = Filename.basename dir in - loop (counter + 1) parent ~candidates ~to_cwd:(base :: to_cwd) + let base = Filename.basename dir in + loop (counter + 1) parent ~candidates ~to_cwd:(base :: to_cwd) + in + match loop 0 ~candidates:[] ~to_cwd:[] cwd with + | [] -> (cwd, []) + | l -> + let lowest_priority = + List.fold_left l ~init:max_int ~f:(fun acc (prio, _, _) -> + min acc prio) in - match loop 0 ~candidates:[] ~to_cwd:[] cwd with - | [] -> (cwd, []) - | l -> - let lowest_priority = - List.fold_left l ~init:max_int ~f:(fun acc (prio, _, _) -> - min acc prio) - in - match List.find l ~f:(fun (prio, _, _) -> prio = lowest_priority) with - | None -> assert false - | Some (_, dir, to_cwd) -> (dir, to_cwd) + match List.find l ~f:(fun (prio, _, _) -> prio = lowest_priority) with + | None -> assert false + | Some (_, dir, to_cwd) -> (dir, to_cwd) - let package_name = - Arg.conv ((fun p -> Ok (Package.Name.of_string p)), Package.Name.pp) +let package_name = + Arg.conv ((fun p -> Ok (Package.Name.of_string p)), Package.Name.pp) - let common_footer = - `Blocks - [ `S "BUGS" - ; `P "Check bug reports at https://github.com/ocaml/dune/issues" - ] - - let copts_sect = "COMMON OPTIONS" - let help_secs = - [ `S copts_sect - ; `P "These options are common to all commands." - ; `S "MORE HELP" - ; `P "Use `$(mname) $(i,COMMAND) --help' for help on a single command." - ; common_footer +let common_footer = + `Blocks + [ `S "BUGS" + ; `P "Check bug reports at https://github.com/ocaml/dune/issues" ] - type config_file = - | No_config - | Default - | This of Path.t +let copts_sect = "COMMON OPTIONS" +let help_secs = + [ `S copts_sect + ; `P "These options are common to all commands." + ; `S "MORE HELP" + ; `P "Use `$(mname) $(i,COMMAND) --help' for help on a single command." + ; common_footer + ] - let incompatible a b = - `Error (true, - sprintf - "Cannot use %s and %s simultaneously" - a b) +type config_file = + | No_config + | Default + | This of Path.t - let common = - let dump_opt name value = - match value with - | None -> [] - | Some s -> [name; s] - in - let make - concurrency - debug_dep_path - debug_findlib - debug_backtraces - dev_mode - no_buffer - workspace_file - diff_command - auto_promote - force - (root, - only_packages, - ignore_promoted_rules, - config_file, - orig) - x - display - = - let root, to_cwd = - match root with - | Some dn -> (dn, []) - | None -> - if Config.inside_dune then - (".", []) - else - find_root () - in - let orig_args = - List.concat - [ if dev_mode then ["--dev"] else [] - ; dump_opt "--workspace" workspace_file - ; orig - ] - in - let config = - match config_file with - | No_config -> Config.default - | This fname -> Config.load_config_file fname - | Default -> - if Config.inside_dune then - Config.default - else - Config.load_user_config_file () - in - let config = - Config.merge config - { display - ; concurrency - } - in - let config = - Config.adapt_display config - ~output_is_a_tty:(Lazy.force Colors.stderr_supports_colors) - in - { debug_dep_path - ; debug_findlib - ; debug_backtraces - ; dev_mode - ; capture_outputs = not no_buffer - ; workspace_file - ; root - ; orig_args - ; target_prefix = String.concat ~sep:"" (List.map to_cwd ~f:(sprintf "%s/")) - ; diff_command - ; auto_promote - ; force - ; ignore_promoted_rules - ; only_packages = - Option.map only_packages - ~f:(fun s -> Package.Name.Set.of_list ( - List.map ~f:Package.Name.of_string (String.split s ~on:','))) - ; x - ; config - } +let incompatible a b = + `Error (true, + sprintf + "Cannot use %s and %s simultaneously" + a b) + +let common = + let dump_opt name value = + match value with + | None -> [] + | Some s -> [name; s] + in + let make + concurrency + debug_dep_path + debug_findlib + debug_backtraces + dev_mode + no_buffer + workspace_file + diff_command + auto_promote + force + (root, + only_packages, + ignore_promoted_rules, + config_file, + orig) + x + display + = + let root, to_cwd = + match root with + | Some dn -> (dn, []) + | None -> + if Config.inside_dune then + (".", []) + else + find_root () in - let docs = copts_sect in - let concurrency = - let arg = - Arg.conv - ((fun s -> - Result.map_error (Config.Concurrency.of_string s) - ~f:(fun s -> `Msg s)), - fun pp x -> - Format.pp_print_string pp (Config.Concurrency.to_string x)) - in - Arg.(value - & opt (some arg) None - & info ["j"] ~docs ~docv:"JOBS" - ~doc:{|Run no more than $(i,JOBS) commands simultaneously.|} - ) + let orig_args = + List.concat + [ if dev_mode then ["--dev"] else [] + ; dump_opt "--workspace" workspace_file + ; orig + ] in - let only_packages = - Arg.(value - & opt (some string) None - & info ["only-packages"] ~docs ~docv:"PACKAGES" - ~doc:{|Ignore stanzas referring to a package that is not in $(b,PACKAGES). - $(b,PACKAGES) is a comma-separated list of package names. - Note that this has the same effect as deleting the relevant stanzas - from jbuild files. It is mostly meant for releases. - During development, it is likely that what you want instead is to - build a particular $(b,.install) target.|} - ) + let config = + match config_file with + | No_config -> Config.default + | This fname -> Config.load_config_file fname + | Default -> + if Config.inside_dune then + Config.default + else + Config.load_user_config_file () in - let ddep_path = - Arg.(value - & flag - & info ["debug-dependency-path"] ~docs - ~doc:{|In case of error, print the dependency path from - the targets on the command line to the rule that failed. - |}) + let config = + Config.merge config + { display + ; concurrency + } in - let dfindlib = - Arg.(value - & flag - & info ["debug-findlib"] ~docs - ~doc:{|Debug the findlib sub-system.|}) + let config = + Config.adapt_display config + ~output_is_a_tty:(Lazy.force Colors.stderr_supports_colors) in - let dbacktraces = - Arg.(value - & flag - & info ["debug-backtraces"] ~docs - ~doc:{|Always print exception backtraces.|}) + { debug_dep_path + ; debug_findlib + ; debug_backtraces + ; dev_mode + ; capture_outputs = not no_buffer + ; workspace_file + ; root + ; orig_args + ; target_prefix = String.concat ~sep:"" (List.map to_cwd ~f:(sprintf "%s/")) + ; diff_command + ; auto_promote + ; force + ; ignore_promoted_rules + ; only_packages = + Option.map only_packages + ~f:(fun s -> Package.Name.Set.of_list ( + List.map ~f:Package.Name.of_string (String.split s ~on:','))) + ; x + ; config + } + in + let docs = copts_sect in + let concurrency = + let arg = + Arg.conv + ((fun s -> + Result.map_error (Config.Concurrency.of_string s) + ~f:(fun s -> `Msg s)), + fun pp x -> + Format.pp_print_string pp (Config.Concurrency.to_string x)) in - let dev = + Arg.(value + & opt (some arg) None + & info ["j"] ~docs ~docv:"JOBS" + ~doc:{|Run no more than $(i,JOBS) commands simultaneously.|} + ) + in + let only_packages = + Arg.(value + & opt (some string) None + & info ["only-packages"] ~docs ~docv:"PACKAGES" + ~doc:{|Ignore stanzas referring to a package that is not in $(b,PACKAGES). + $(b,PACKAGES) is a comma-separated list of package names. + Note that this has the same effect as deleting the relevant stanzas + from jbuild files. It is mostly meant for releases. + During development, it is likely that what you want instead is to + build a particular $(b,.install) target.|} + ) + in + let ddep_path = + Arg.(value + & flag + & info ["debug-dependency-path"] ~docs + ~doc:{|In case of error, print the dependency path from + the targets on the command line to the rule that failed. + |}) + in + let dfindlib = + Arg.(value + & flag + & info ["debug-findlib"] ~docs + ~doc:{|Debug the findlib sub-system.|}) + in + let dbacktraces = + Arg.(value + & flag + & info ["debug-backtraces"] ~docs + ~doc:{|Always print exception backtraces.|}) + in + let dev = + Arg.(value + & flag + & info ["dev"] ~docs + ~doc:{|Use stricter compilation flags by default.|}) + in + let display = + let verbose = Arg.(value & flag - & info ["dev"] ~docs - ~doc:{|Use stricter compilation flags by default.|}) + & info ["verbose"] ~docs + ~doc:"Same as $(b,--display verbose)") in let display = - let verbose = - Arg.(value - & flag - & info ["verbose"] ~docs - ~doc:"Same as $(b,--display verbose)") - in - let display = - Arg.(value - & opt (some (enum Config.Display.all)) None - & info ["display"] ~docs ~docv:"MODE" - ~doc:{|Control the display mode of Dune. - See $(b,dune-config\(5\)) for more details.|}) - in - let merge verbose display = - match verbose, display with - | false , None -> `Ok None - | false , Some x -> `Ok (Some x) - | true , None -> `Ok (Some Config.Display.Verbose) - | true , Some _ -> incompatible "--display" "--verbose" - in - Term.(ret (const merge $ verbose $ display)) - in - let no_buffer = Arg.(value - & flag - & info ["no-buffer"] ~docs ~docv:"DIR" - ~doc:{|Do not buffer the output of commands executed by dune. - By default dune buffers the output of subcommands, in order - to prevent interleaving when multiple commands are executed - in parallel. However, this can be an issue when debugging - long running tests. With $(b,--no-buffer), commands have direct - access to the terminal. Note that as a result their output won't - be captured in the log file. - - You should use this option in conjunction with $(b,-j 1), - to avoid interleaving. Additionally you should use - $(b,--verbose) as well, to make sure that commands are printed - before they are being executed.|}) + & opt (some (enum Config.Display.all)) None + & info ["display"] ~docs ~docv:"MODE" + ~doc:{|Control the display mode of Dune. + See $(b,dune-config\(5\)) for more details.|}) in - let workspace_file = - Arg.(value - & opt (some file) None - & info ["workspace"] ~docs ~docv:"FILE" - ~doc:"Use this specific workspace file instead of looking it up.") + let merge verbose display = + match verbose, display with + | false , None -> `Ok None + | false , Some x -> `Ok (Some x) + | true , None -> `Ok (Some Config.Display.Verbose) + | true , Some _ -> incompatible "--display" "--verbose" in - let auto_promote = - Arg.(value - & flag - & info ["auto-promote"] ~docs - ~doc:"Automatically promote files. This is similar to running + Term.(ret (const merge $ verbose $ display)) + in + let no_buffer = + Arg.(value + & flag + & info ["no-buffer"] ~docs ~docv:"DIR" + ~doc:{|Do not buffer the output of commands executed by dune. + By default dune buffers the output of subcommands, in order + to prevent interleaving when multiple commands are executed + in parallel. However, this can be an issue when debugging + long running tests. With $(b,--no-buffer), commands have direct + access to the terminal. Note that as a result their output won't + be captured in the log file. + + You should use this option in conjunction with $(b,-j 1), + to avoid interleaving. Additionally you should use + $(b,--verbose) as well, to make sure that commands are printed + before they are being executed.|}) + in + let workspace_file = + Arg.(value + & opt (some file) None + & info ["workspace"] ~docs ~docv:"FILE" + ~doc:"Use this specific workspace file instead of looking it up.") + in + let auto_promote = + Arg.(value + & flag + & info ["auto-promote"] ~docs + ~doc:"Automatically promote files. This is similar to running $(b,dune promote) after the build.") + in + let force = + Arg.(value + & flag + & info ["force"; "f"] + ~doc:"Force actions associated to aliases to be re-executed even + if their dependencies haven't changed.") + in + let merged_options = + let root = + Arg.(value + & opt (some dir) None + & info ["root"] ~docs ~docv:"DIR" + ~doc:{|Use this directory as workspace root instead of guessing it. + Note that this option doesn't change the interpretation of + targets given on the command line. It is only intended + for scripts.|}) in - let force = + let ignore_promoted_rules = Arg.(value & flag - & info ["force"; "f"] - ~doc:"Force actions associated to aliases to be re-executed even - if their dependencies haven't changed.") + & info ["ignore-promoted-rules"] ~docs + ~doc:"Ignore rules with (mode promote)") in - let merged_options = - let root = + let config_file = + let config_file = Arg.(value - & opt (some dir) None - & info ["root"] ~docs ~docv:"DIR" - ~doc:{|Use this directory as workspace root instead of guessing it. - Note that this option doesn't change the interpretation of - targets given on the command line. It is only intended - for scripts.|}) + & opt (some file) None + & info ["config-file"] ~docs ~docv:"FILE" + ~doc:"Load this configuration file instead of the default one.") in - let ignore_promoted_rules = + let no_config = Arg.(value & flag - & info ["ignore-promoted-rules"] ~docs - ~doc:"Ignore rules with (mode promote)") - in - let config_file = - let config_file = - Arg.(value - & opt (some file) None - & info ["config-file"] ~docs ~docv:"FILE" - ~doc:"Load this configuration file instead of the default one.") - in - let no_config = - Arg.(value - & flag - & info ["no-config"] ~docs - ~doc:"Do not load the configuration file") - in - let merge config_file no_config = - match config_file, no_config with - | None , false -> `Ok (None , Default) - | Some fn, false -> `Ok (Some "--config-file", This (Path.of_string fn)) - | None , true -> `Ok (Some "--no-config" , No_config) - | Some _ , true -> incompatible "--no-config" "--config-file" - in - Term.(ret (const merge $ config_file $ no_config)) - in - let for_release = "for-release-of-packages" in - let frop = - Arg.(value - & opt (some string) None - & info ["p"; for_release] ~docs ~docv:"PACKAGES" - ~doc:{|Shorthand for $(b,--root . --only-packages PACKAGE - --promote ignore --no-config). - You must use this option in your $(i,.opam) files, in order - to build only what's necessary when your project contains multiple - packages as well as getting reproducible builds.|}) + & info ["no-config"] ~docs + ~doc:"Do not load the configuration file") in - let merge root only_packages ignore_promoted_rules - (config_file_opt, config_file) release = - let fail opt = incompatible ("-p/--" ^ for_release) opt in - match release, root, only_packages, ignore_promoted_rules, config_file_opt with - | Some _, Some _, _, _, _ -> fail "--root" - | Some _, _, Some _, _, _ -> fail "--only-packages" - | Some _, _, _, true , _ -> fail "--ignore-promoted-rules" - | Some _, _, _, _ , Some s -> fail s - | Some pkgs, None, None, false, None -> - `Ok (Some ".", - Some pkgs, - true, - No_config, - ["-p"; pkgs] - ) - | None, _, _, _, _ -> - `Ok (root, - only_packages, - ignore_promoted_rules, - config_file, - List.concat - [ dump_opt "--root" root - ; dump_opt "--only-packages" only_packages - ; if ignore_promoted_rules then - ["--ignore-promoted-rules"] - else - [] - ; (match config_file with - | This fn -> ["--config-file"; Path.to_string fn] - | No_config -> ["--no-config"] - | Default -> []) - ] - ) + let merge config_file no_config = + match config_file, no_config with + | None , false -> `Ok (None , Default) + | Some fn, false -> `Ok (Some "--config-file", This (Path.of_string fn)) + | None , true -> `Ok (Some "--no-config" , No_config) + | Some _ , true -> incompatible "--no-config" "--config-file" in - Term.(ret (const merge - $ root - $ only_packages - $ ignore_promoted_rules - $ config_file - $ frop)) + Term.(ret (const merge $ config_file $ no_config)) in - let x = + let for_release = "for-release-of-packages" in + let frop = Arg.(value & opt (some string) None - & info ["x"] ~docs - ~doc:{|Cross-compile using this toolchain.|}) + & info ["p"; for_release] ~docs ~docv:"PACKAGES" + ~doc:{|Shorthand for $(b,--root . --only-packages PACKAGE + --promote ignore --no-config). + You must use this option in your $(i,.opam) files, in order + to build only what's necessary when your project contains multiple + packages as well as getting reproducible builds.|}) in - let diff_command = - Arg.(value - & opt (some string) None - & info ["diff-command"] ~docs - ~doc:"Shell command to use to diff files") + let merge root only_packages ignore_promoted_rules + (config_file_opt, config_file) release = + let fail opt = incompatible ("-p/--" ^ for_release) opt in + match release, root, only_packages, ignore_promoted_rules, config_file_opt with + | Some _, Some _, _, _, _ -> fail "--root" + | Some _, _, Some _, _, _ -> fail "--only-packages" + | Some _, _, _, true , _ -> fail "--ignore-promoted-rules" + | Some _, _, _, _ , Some s -> fail s + | Some pkgs, None, None, false, None -> + `Ok (Some ".", + Some pkgs, + true, + No_config, + ["-p"; pkgs] + ) + | None, _, _, _, _ -> + `Ok (root, + only_packages, + ignore_promoted_rules, + config_file, + List.concat + [ dump_opt "--root" root + ; dump_opt "--only-packages" only_packages + ; if ignore_promoted_rules then + ["--ignore-promoted-rules"] + else + [] + ; (match config_file with + | This fn -> ["--config-file"; Path.to_string fn] + | No_config -> ["--no-config"] + | Default -> []) + ] + ) in - Term.(const make - $ concurrency - $ ddep_path - $ dfindlib - $ dbacktraces - $ dev - $ no_buffer - $ workspace_file - $ diff_command - $ auto_promote - $ force - $ merged_options - $ x - $ display - ) + Term.(ret (const merge + $ root + $ only_packages + $ ignore_promoted_rules + $ config_file + $ frop)) + in + let x = + Arg.(value + & opt (some string) None + & 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 + Term.(const make + $ concurrency + $ ddep_path + $ dfindlib + $ dbacktraces + $ dev + $ no_buffer + $ workspace_file + $ diff_command + $ auto_promote + $ force + $ merged_options + $ x + $ display + ) - let installed_libraries = - let doc = "Print out libraries installed on the system." in - let go common na = - set_common common ~targets:[]; - let env = Main.setup_env ~capture_outputs:common.capture_outputs in - Scheduler.go ~log:(Log.create common) ~common - (Context.create (Default [Native]) ~env >>= fun ctxs -> - let ctx = List.hd ctxs in - let findlib = ctx.findlib in - if na then begin - let pkgs = Findlib.all_unavailable_packages findlib in - let longest = String.longest_map pkgs ~f:fst in - let ppf = Format.std_formatter in - List.iter pkgs ~f:(fun (n, r) -> - Format.fprintf ppf "%-*s -> %a@\n" longest n - Findlib.Unavailable_reason.pp r); - Format.pp_print_flush ppf (); - Fiber.return () - end else begin - let pkgs = Findlib.all_packages findlib in - let max_len = String.longest_map pkgs ~f:Findlib.Package.name in - List.iter pkgs ~f:(fun pkg -> - let ver = - Option.value (Findlib.Package.version pkg) ~default:"n/a" - in - Printf.printf "%-*s (version: %s)\n" max_len - (Findlib.Package.name pkg) ver); - Fiber.return () - end) - in - ( Term.(const go - $ common - $ Arg.(value - & flag - & info ["na"; "not-available"] - ~doc:"List libraries that are not available and explain why")) - , Term.info "installed-libraries" ~doc - ) +let installed_libraries = + let doc = "Print out libraries installed on the system." in + let go common na = + set_common common ~targets:[]; + let env = Main.setup_env ~capture_outputs:common.capture_outputs in + Scheduler.go ~log:(Log.create common) ~common + (Context.create (Default [Native]) ~env >>= fun ctxs -> + let ctx = List.hd ctxs in + let findlib = ctx.findlib in + if na then begin + let pkgs = Findlib.all_unavailable_packages findlib in + let longest = String.longest_map pkgs ~f:fst in + let ppf = Format.std_formatter in + List.iter pkgs ~f:(fun (n, r) -> + Format.fprintf ppf "%-*s -> %a@\n" longest n + Findlib.Unavailable_reason.pp r); + Format.pp_print_flush ppf (); + Fiber.return () + end else begin + let pkgs = Findlib.all_packages findlib in + let max_len = String.longest_map pkgs ~f:Findlib.Package.name in + List.iter pkgs ~f:(fun pkg -> + let ver = + Option.value (Findlib.Package.version pkg) ~default:"n/a" + in + Printf.printf "%-*s (version: %s)\n" max_len + (Findlib.Package.name pkg) ver); + Fiber.return () + end) + in + ( Term.(const go + $ common + $ Arg.(value + & flag + & info ["na"; "not-available"] + ~doc:"List libraries that are not available and explain why")) + , Term.info "installed-libraries" ~doc + ) - let resolve_package_install setup pkg = - match Main.package_install_file setup pkg with - | Ok path -> path - | Error () -> - let pkg = Package.Name.to_string pkg in - die "Unknown package %s!%s" pkg - (hint pkg - (Package.Name.Map.keys setup.packages - |> List.map ~f:Package.Name.to_string)) +let resolve_package_install setup pkg = + match Main.package_install_file setup pkg with + | Ok path -> path + | Error () -> + let pkg = Package.Name.to_string pkg in + die "Unknown package %s!%s" pkg + (hint pkg + (Package.Name.Map.keys setup.packages + |> List.map ~f:Package.Name.to_string)) - let target_hint (setup : Main.setup) path = - assert (Path.is_local path); - let sub_dir = - if Path.is_root path then - path - else - Path.parent path in - let candidates = Build_system.all_targets setup.build_system in - let candidates = - if Path.is_in_build_dir path then - candidates +let target_hint (setup : Main.setup) path = + assert (Path.is_local path); + let sub_dir = + if Path.is_root path then + path + else + Path.parent path in + let candidates = Build_system.all_targets setup.build_system in + let candidates = + if Path.is_in_build_dir path then + candidates + else + List.map candidates ~f:(fun path -> + match Path.extract_build_context path with + | None -> path + | Some (_, path) -> path) + in + let candidates = + (* Only suggest hints for the basename, otherwise it's slow when there are lots of + files *) + List.filter_map candidates ~f:(fun path -> + if Path.parent path = sub_dir then + Some (Path.to_string path) else - List.map candidates ~f:(fun path -> - match Path.extract_build_context path with - | None -> path - | Some (_, path) -> path) - in - let candidates = - (* Only suggest hints for the basename, otherwise it's slow when there are lots of - files *) - List.filter_map candidates ~f:(fun path -> - if Path.parent path = sub_dir then - Some (Path.to_string path) - else - None) - in - let candidates = String.Set.of_list candidates |> String.Set.to_list in - hint (Path.to_string path) candidates + None) + in + let candidates = String.Set.of_list candidates |> String.Set.to_list in + hint (Path.to_string path) candidates - let check_path contexts = - let contexts = - String.Set.of_list (List.map contexts ~f:(fun c -> c.Context.name)) +let check_path contexts = + let contexts = + String.Set.of_list (List.map contexts ~f:(fun c -> c.Context.name)) + in + fun path -> + let internal path = + die "This path is internal to dune: %s" + (Path.to_string_maybe_quoted path) in - fun path -> - let internal path = - die "This path is internal to dune: %s" - (Path.to_string_maybe_quoted path) - in - if Path.is_in_build_dir path then - match Path.extract_build_context path with - | None -> internal path - | Some (name, _) -> - if name = "" || name.[0] = '.' then internal path; - if not (name = "install" || String.Set.mem contexts name) then - die "%s refers to unknown build context: %s%s" - (Path.to_string_maybe_quoted path) - name - (hint name (String.Set.to_list contexts)) + if Path.is_in_build_dir path then + match Path.extract_build_context path with + | None -> internal path + | Some (name, _) -> + if name = "" || name.[0] = '.' then internal path; + if not (name = "install" || String.Set.mem contexts name) then + die "%s refers to unknown build context: %s%s" + (Path.to_string_maybe_quoted path) + name + (hint name (String.Set.to_list contexts)) - let resolve_targets ~log common (setup : Main.setup) user_targets = - match user_targets with - | [] -> [] - | _ -> - let check_path = check_path setup.contexts in - let targets = - List.map user_targets ~f:(fun s -> - if String.is_prefix s ~prefix:"@" then begin - let s = String.sub s ~pos:1 ~len:(String.length s - 1) in - let path = Path.relative Path.root (prefix_target common s) in - check_path path; - if Path.is_root path then - die "@@ on the command line must be followed by a valid alias name" - else if not (Path.is_local path) then - die "@@ on the command line must be followed by a relative path" - else - Ok [Alias_rec path] - end else begin - let path = Path.relative Path.root (prefix_target common s) in - check_path path; - let can't_build path = - Error (path, target_hint setup path); - in - if not (Path.is_local path) then +let resolve_targets ~log common (setup : Main.setup) user_targets = + match user_targets with + | [] -> [] + | _ -> + let check_path = check_path setup.contexts in + let targets = + List.map user_targets ~f:(fun s -> + if String.is_prefix s ~prefix:"@" then begin + let s = String.sub s ~pos:1 ~len:(String.length s - 1) in + let path = Path.relative Path.root (prefix_target common s) in + check_path path; + if Path.is_root path then + die "@@ on the command line must be followed by a valid alias name" + else if not (Path.is_local path) then + die "@@ on the command line must be followed by a relative path" + else + Ok [Alias_rec path] + end else begin + let path = Path.relative Path.root (prefix_target common s) in + check_path path; + let can't_build path = + Error (path, target_hint setup path); + in + if not (Path.is_local path) then + Ok [File path] + else if Path.is_in_build_dir path then begin + if Build_system.is_target setup.build_system path then Ok [File path] - else if Path.is_in_build_dir path then begin - if Build_system.is_target setup.build_system path then - Ok [File path] - else - can't_build path - end else - match - List.filter_map setup.contexts ~f:(fun ctx -> - let path = Path.append ctx.Context.build_dir path in - if Build_system.is_target setup.build_system path then - Some (File path) - else - None) - with - | [] -> can't_build path - | l -> Ok l - end - ) - in - if common.config.display = Verbose then begin - Log.info log "Actual targets:"; - let targets = - List.concat_map targets ~f:(function - | Ok targets -> targets - | Error _ -> []) in - List.iter targets ~f:(function - | File path -> - Log.info log @@ "- " ^ (Path.to_string path) - | Alias_rec path -> - Log.info log @@ "- recursive alias " ^ - (Path.to_string_maybe_quoted path)); - flush stdout; - end; - targets + else + can't_build path + end else + match + List.filter_map setup.contexts ~f:(fun ctx -> + let path = Path.append ctx.Context.build_dir path in + if Build_system.is_target setup.build_system path then + Some (File path) + else + None) + with + | [] -> can't_build path + | l -> Ok l + end + ) + in + if common.config.display = Verbose then begin + Log.info log "Actual targets:"; + let targets = + List.concat_map targets ~f:(function + | Ok targets -> targets + | Error _ -> []) in + List.iter targets ~f:(function + | File path -> + Log.info log @@ "- " ^ (Path.to_string path) + | Alias_rec path -> + Log.info log @@ "- recursive alias " ^ + (Path.to_string_maybe_quoted path)); + flush stdout; + end; + targets - let resolve_targets_exn ~log common setup user_targets = - resolve_targets ~log common setup user_targets - |> List.concat_map ~f:(function - | Error (path, hint) -> - die "Don't know how to build %a%s" Path.pp path hint - | Ok targets -> - targets) +let resolve_targets_exn ~log common setup user_targets = + resolve_targets ~log common setup user_targets + |> List.concat_map ~f:(function + | Error (path, hint) -> + die "Don't know how to build %a%s" Path.pp path hint + | Ok targets -> + targets) - let build_targets = - let doc = "Build the given targets, or all installable targets if none are given." in - let man = - [ `S "DESCRIPTION" - ; `P {|Targets starting with a $(b,@) are interpreted as aliases.|} - ; `Blocks help_secs - ] - in - let name_ = Arg.info [] ~docv:"TARGET" in - let go common targets = - set_common common ~targets; - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common >>= fun setup -> - let targets = resolve_targets_exn ~log common setup targets in - do_build setup targets) in - ( Term.(const go - $ common - $ Arg.(value & pos_all string ["@install"] name_)) - , Term.info "build" ~doc ~man) +let build_targets = + let doc = "Build the given targets, or all installable targets if none are given." in + let man = + [ `S "DESCRIPTION" + ; `P {|Targets starting with a $(b,@) are interpreted as aliases.|} + ; `Blocks help_secs + ] + in + let name_ = Arg.info [] ~docv:"TARGET" in + let go common targets = + set_common common ~targets; + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common >>= fun setup -> + let targets = resolve_targets_exn ~log common setup targets in + do_build setup targets) in + ( Term.(const go + $ common + $ Arg.(value & pos_all string ["@install"] name_)) + , Term.info "build" ~doc ~man) - let runtest = - let doc = "Run tests." in - let man = - [ `S "DESCRIPTION" - ; `P {|This is a short-hand for calling:|} - ; `Pre {| dune build @runtest|} - ; `Blocks help_secs - ] - in - let name_ = Arg.info [] ~docv:"DIR" in - let go common dirs = - set_common common - ~targets:(List.map dirs ~f:(function - | "" | "." -> "@runtest" - | dir when dir.[String.length dir - 1] = '/' -> sprintf "@%sruntest" dir - | dir -> sprintf "@%s/runtest" dir)); - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common >>= fun setup -> - let check_path = check_path setup.contexts in - let targets = - List.map dirs ~f:(fun dir -> - let dir = Path.(relative root) (prefix_target common dir) in - check_path dir; - Alias_rec (Path.relative dir "runtest")) - in - do_build setup targets) in - ( Term.(const go - $ common - $ Arg.(value & pos_all string ["."] name_)) - , Term.info "runtest" ~doc ~man) +let runtest = + let doc = "Run tests." in + let man = + [ `S "DESCRIPTION" + ; `P {|This is a short-hand for calling:|} + ; `Pre {| dune build @runtest|} + ; `Blocks help_secs + ] + in + let name_ = Arg.info [] ~docv:"DIR" in + let go common dirs = + set_common common + ~targets:(List.map dirs ~f:(function + | "" | "." -> "@runtest" + | dir when dir.[String.length dir - 1] = '/' -> sprintf "@%sruntest" dir + | dir -> sprintf "@%s/runtest" dir)); + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common >>= fun setup -> + let check_path = check_path setup.contexts in + let targets = + List.map dirs ~f:(fun dir -> + let dir = Path.(relative root) (prefix_target common dir) in + check_path dir; + Alias_rec (Path.relative dir "runtest")) + in + do_build setup targets) in + ( Term.(const go + $ common + $ Arg.(value & pos_all string ["."] name_)) + , Term.info "runtest" ~doc ~man) let clean = let doc = "Clean the project." in @@ -767,699 +751,698 @@ let clean = ( Term.(const go $ common) , Term.info "clean" ~doc ~man) - let format_external_libs libs = - String.Map.to_list libs - |> List.map ~f:(fun (name, kind) -> - match (kind : Build.lib_dep_kind) with - | Optional -> sprintf "- %s (optional)" name - | Required -> sprintf "- %s" name) - |> String.concat ~sep:"\n" +let format_external_libs libs = + String.Map.to_list libs + |> List.map ~f:(fun (name, kind) -> + match (kind : Build.lib_dep_kind) with + | Optional -> sprintf "- %s (optional)" name + | Required -> sprintf "- %s" name) + |> String.concat ~sep:"\n" - let external_lib_deps = - let doc = "Print out external libraries needed to build the given targets." in - let man = - [ `S "DESCRIPTION" - ; `P {|Print out the external libraries needed to build the given targets.|} - ; `P {|The output of $(b,jbuild external-lib-deps @install) should be included - in what is written in your $(i,.opam) file.|} - ; `Blocks help_secs - ] - in - let go common only_missing targets = - set_common common ~targets:[]; - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common ~external_lib_deps_mode:true - >>= fun setup -> - let targets = resolve_targets_exn ~log common setup targets in - let request = request_of_targets setup targets in - let failure = - String.Map.foldi ~init:false - (Build_system.all_lib_deps_by_context setup.build_system ~request) - ~f:(fun context_name lib_deps acc -> - let internals = - Jbuild.Stanzas.lib_names - (match String.Map.find setup.Main.stanzas context_name with - | None -> assert false - | Some x -> x) +let external_lib_deps = + let doc = "Print out external libraries needed to build the given targets." in + let man = + [ `S "DESCRIPTION" + ; `P {|Print out the external libraries needed to build the given targets.|} + ; `P {|The output of $(b,jbuild external-lib-deps @install) should be included + in what is written in your $(i,.opam) file.|} + ; `Blocks help_secs + ] + in + let go common only_missing targets = + set_common common ~targets:[]; + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common ~external_lib_deps_mode:true + >>= fun setup -> + let targets = resolve_targets_exn ~log common setup targets in + let request = request_of_targets setup targets in + let failure = + String.Map.foldi ~init:false + (Build_system.all_lib_deps_by_context setup.build_system ~request) + ~f:(fun context_name lib_deps acc -> + let internals = + Jbuild.Stanzas.lib_names + (match String.Map.find setup.Main.stanzas context_name with + | None -> assert false + | Some x -> x) + in + let externals = + String.Map.filteri lib_deps ~f:(fun name _ -> + not (String.Set.mem internals name)) + in + if only_missing then begin + let context = + match + List.find setup.contexts ~f:(fun c -> c.name = context_name) + with + | None -> assert false + | Some c -> c in - let externals = - String.Map.filteri lib_deps ~f:(fun name _ -> - not (String.Set.mem internals name)) + let missing = + String.Map.filteri externals ~f:(fun name _ -> + not (Findlib.available context.findlib name)) in - if only_missing then begin - let context = - match - List.find setup.contexts ~f:(fun c -> c.name = context_name) - with - | None -> assert false - | Some c -> c - in - let missing = - String.Map.filteri externals ~f:(fun name _ -> - not (Findlib.available context.findlib name)) - in - if String.Map.is_empty missing then - acc - else if String.Map.for_alli missing - ~f:(fun _ kind -> kind = Build.Optional) - then begin - Format.eprintf - "@{Error@}: The following libraries are missing \ - in the %s context:\n\ - %s@." - context_name - (format_external_libs missing); - false - end else begin - Format.eprintf - "@{Error@}: The following libraries are missing \ - in the %s context:\n\ - %s\n\ - Hint: try: opam install %s@." - context_name - (format_external_libs missing) - (String.Map.to_list missing - |> List.filter_map ~f:(fun (name, kind) -> - match (kind : Build.lib_dep_kind) with - | Optional -> None - | Required -> Some (Findlib.root_package_name name)) - |> String.Set.of_list - |> String.Set.to_list - |> String.concat ~sep:" "); - true - end + if String.Map.is_empty missing then + acc + else if String.Map.for_alli missing + ~f:(fun _ kind -> kind = Build.Optional) + then begin + Format.eprintf + "@{Error@}: The following libraries are missing \ + in the %s context:\n\ + %s@." + context_name + (format_external_libs missing); + false end else begin - Printf.printf - "These are the external library dependencies in the %s context:\n\ - %s\n%!" + Format.eprintf + "@{Error@}: The following libraries are missing \ + in the %s context:\n\ + %s\n\ + Hint: try: opam install %s@." context_name - (format_external_libs externals); - acc - end) - in - if failure then raise Already_reported; - Fiber.return ()) - in - ( Term.(const go - $ common - $ Arg.(value - & flag - & info ["missing"] - ~doc:{|Only print out missing dependencies|}) - $ Arg.(non_empty - & pos_all string [] - & Arg.info [] ~docv:"TARGET")) - , Term.info "external-lib-deps" ~doc ~man) + (format_external_libs missing) + (String.Map.to_list missing + |> List.filter_map ~f:(fun (name, kind) -> + match (kind : Build.lib_dep_kind) with + | Optional -> None + | Required -> Some (Findlib.root_package_name name)) + |> String.Set.of_list + |> String.Set.to_list + |> String.concat ~sep:" "); + true + end + end else begin + Printf.printf + "These are the external library dependencies in the %s context:\n\ + %s\n%!" + context_name + (format_external_libs externals); + acc + end) + in + if failure then raise Already_reported; + Fiber.return ()) + in + ( Term.(const go + $ common + $ Arg.(value + & flag + & info ["missing"] + ~doc:{|Only print out missing dependencies|}) + $ Arg.(non_empty + & pos_all string [] + & Arg.info [] ~docv:"TARGET")) + , Term.info "external-lib-deps" ~doc ~man) - let rules = - let doc = "Dump internal rules." in - let man = - [ `S "DESCRIPTION" - ; `P {|Dump Dune internal rules for the given targets. - If no targets are given, dump all the internal rules.|} - ; `P {|By default the output is a list of S-expressions, - one S-expression per rule. Each S-expression is of the form:|} - ; `Pre " ((deps ())\n\ - \ (targets ())\n\ - \ (context )\n\ - \ (action ))" - ; `P {|$(b,) is the context is which the action is executed. - It is omitted if the action is independant from the context.|} - ; `P {|$(b,) is the action following the same syntax as user actions, - as described in the manual.|} - ; `Blocks help_secs - ] - in - let go common out recursive makefile_syntax targets = - let out = Option.map ~f:Path.of_string out in - set_common common ~targets; - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common ~external_lib_deps_mode:true - >>= fun setup -> - let request = - match targets with - | [] -> Build.paths (Build_system.all_targets setup.build_system) - | _ -> resolve_targets_exn ~log common setup targets |> request_of_targets setup - in - Build_system.build_rules setup.build_system ~request ~recursive >>= fun rules -> - let sexp_of_action action = - Action.for_shell action |> Action.For_shell.sexp_of_t - in - let print oc = - let ppf = Format.formatter_of_out_channel oc in - Sexp.prepare_formatter ppf; - Format.pp_open_vbox ppf 0; - if makefile_syntax then begin - List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> - Format.fprintf ppf "@[@{%a:%t@}@]@,@<0>\t@{%a@}@,@," - (Format.pp_print_list ~pp_sep:Format.pp_print_space (fun ppf p -> - Format.pp_print_string ppf (Path.to_string p))) - (Path.Set.to_list rule.targets) - (fun ppf -> - Path.Set.iter rule.deps ~f:(fun dep -> - Format.fprintf ppf "@ %s" (Path.to_string dep))) - Sexp.pp_split_strings (sexp_of_action rule.action)) - end else begin - List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> - let sexp = - let paths ps = - Sexp.To_sexp.list Path.sexp_of_t (Path.Set.to_list ps) - in - Sexp.To_sexp.record ( - List.concat - [ [ "deps" , paths rule.deps - ; "targets", paths rule.targets ] - ; (match rule.context with - | None -> [] - | Some c -> ["context", - Sexp.atom_or_quoted_string c.name]) - ; [ "action" , sexp_of_action rule.action ] - ]) +let rules = + let doc = "Dump internal rules." in + let man = + [ `S "DESCRIPTION" + ; `P {|Dump Dune internal rules for the given targets. + If no targets are given, dump all the internal rules.|} + ; `P {|By default the output is a list of S-expressions, + one S-expression per rule. Each S-expression is of the form:|} + ; `Pre " ((deps ())\n\ + \ (targets ())\n\ + \ (context )\n\ + \ (action ))" + ; `P {|$(b,) is the context is which the action is executed. + It is omitted if the action is independant from the context.|} + ; `P {|$(b,) is the action following the same syntax as user actions, + as described in the manual.|} + ; `Blocks help_secs + ] + in + let go common out recursive makefile_syntax targets = + let out = Option.map ~f:Path.of_string out in + set_common common ~targets; + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common ~external_lib_deps_mode:true + >>= fun setup -> + let request = + match targets with + | [] -> Build.paths (Build_system.all_targets setup.build_system) + | _ -> resolve_targets_exn ~log common setup targets |> request_of_targets setup + in + Build_system.build_rules setup.build_system ~request ~recursive >>= fun rules -> + let sexp_of_action action = + Action.for_shell action |> Action.For_shell.sexp_of_t + in + let print oc = + let ppf = Format.formatter_of_out_channel oc in + Sexp.prepare_formatter ppf; + Format.pp_open_vbox ppf 0; + if makefile_syntax then begin + List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> + Format.fprintf ppf "@[@{%a:%t@}@]@,@<0>\t@{%a@}@,@," + (Format.pp_print_list ~pp_sep:Format.pp_print_space (fun ppf p -> + Format.pp_print_string ppf (Path.to_string p))) + (Path.Set.to_list rule.targets) + (fun ppf -> + Path.Set.iter rule.deps ~f:(fun dep -> + Format.fprintf ppf "@ %s" (Path.to_string dep))) + Sexp.pp_split_strings (sexp_of_action rule.action)) + end else begin + List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> + let sexp = + let paths ps = + Sexp.To_sexp.list Path.sexp_of_t (Path.Set.to_list ps) in - Format.fprintf ppf "%a@," Sexp.pp_split_strings sexp) - end; - Format.pp_print_flush ppf (); - Fiber.return () - in - match out with - | None -> print stdout - | Some fn -> Io.with_file_out fn ~f:print) - in - ( Term.(const go - $ common - $ Arg.(value - & opt (some string) None - & info ["o"] ~docv:"FILE" - ~doc:"Output to a file instead of stdout.") - $ Arg.(value - & flag - & info ["r"; "recursive"] - ~doc:"Print all rules needed to build the transitive dependencies of the given targets.") - $ Arg.(value - & flag - & info ["m"; "makefile"] - ~doc:"Output the rules in Makefile syntax.") - $ Arg.(value - & pos_all string [] - & Arg.info [] ~docv:"TARGET")) - , Term.info "rules" ~doc ~man) + Sexp.To_sexp.record ( + List.concat + [ [ "deps" , paths rule.deps + ; "targets", paths rule.targets ] + ; (match rule.context with + | None -> [] + | Some c -> ["context", + Sexp.atom_or_quoted_string c.name]) + ; [ "action" , sexp_of_action rule.action ] + ]) + in + Format.fprintf ppf "%a@," Sexp.pp_split_strings sexp) + end; + Format.pp_print_flush ppf (); + Fiber.return () + in + match out with + | None -> print stdout + | Some fn -> Io.with_file_out fn ~f:print) + in + ( Term.(const go + $ common + $ Arg.(value + & opt (some string) None + & info ["o"] ~docv:"FILE" + ~doc:"Output to a file instead of stdout.") + $ Arg.(value + & flag + & info ["r"; "recursive"] + ~doc:"Print all rules needed to build the transitive dependencies of the given targets.") + $ Arg.(value + & flag + & info ["m"; "makefile"] + ~doc:"Output the rules in Makefile syntax.") + $ Arg.(value + & pos_all string [] + & Arg.info [] ~docv:"TARGET")) + , Term.info "rules" ~doc ~man) - let opam_installer () = - match Bin.which "opam-installer" with - | None -> - die "\ +let opam_installer () = + match Bin.which "opam-installer" with + | None -> + die "\ Sorry, you need the opam-installer tool to be able to install or uninstall packages. I couldn't find the opam-installer binary :-(" - | Some fn -> fn + | Some fn -> fn - let get_prefix context ~from_command_line = - match from_command_line with - | Some p -> Fiber.return (Path.of_string p) - | None -> Context.install_prefix context +let get_prefix context ~from_command_line = + match from_command_line with + | Some p -> Fiber.return (Path.of_string p) + | None -> Context.install_prefix context - let get_libdir context ~libdir_from_command_line = - match libdir_from_command_line with - | Some p -> Fiber.return (Some (Path.of_string p)) - | None -> Context.install_ocaml_libdir context +let get_libdir context ~libdir_from_command_line = + match libdir_from_command_line with + | Some p -> Fiber.return (Some (Path.of_string p)) + | None -> Context.install_ocaml_libdir context - let install_uninstall ~what = - let doc = - sprintf "%s packages using opam-installer." (String.capitalize what) - in - let name_ = Arg.info [] ~docv:"PACKAGE" in - let go common prefix_from_command_line libdir_from_command_line pkgs = - set_common common ~targets:[]; - let opam_installer = opam_installer () in - let log = Log.create common in - Scheduler.go ~log ~common - (Main.setup ~log common >>= fun setup -> - let pkgs = - match pkgs with - | [] -> Package.Name.Map.keys setup.packages - | l -> l - in - let install_files, missing_install_files = - List.concat_map pkgs ~f:(fun pkg -> - let fn = resolve_package_install setup pkg in - List.map setup.contexts ~f:(fun ctx -> - let fn = Path.append ctx.Context.build_dir fn in - if Path.exists fn then - Left (ctx, fn) - else - Right fn)) - |> List.partition_map ~f:(fun x -> x) - in - if missing_install_files <> [] then begin - die "The following .install are missing:\n\ - %s\n\ - You need to run: dune build @install" - (String.concat ~sep:"\n" - (List.map missing_install_files - ~f:(fun p -> sprintf "- %s" (Path.to_string p)))) - end; - (match - setup.contexts, prefix_from_command_line, libdir_from_command_line - with - | _ :: _ :: _, Some _, _ | _ :: _ :: _, _, Some _ -> - die "Cannot specify --prefix or --libdir when installing \ - into multiple contexts!" - | _ -> ()); - let module CMap = Map.Make(Context) in - let install_files_by_context = - CMap.of_list_multi install_files |> CMap.to_list - in - Fiber.parallel_iter install_files_by_context - ~f:(fun (context, install_files) -> - get_prefix context ~from_command_line:prefix_from_command_line - >>= fun prefix -> - get_libdir context ~libdir_from_command_line - >>= fun libdir -> - Fiber.parallel_iter install_files ~f:(fun path -> - let purpose = Process.Build_job install_files in - Process.run ~purpose ~env:setup.env Strict opam_installer - ([ sprintf "-%c" what.[0] - ; Path.to_string path - ; "--prefix" - ; Path.to_string prefix - ] @ - match libdir with - | None -> [] - | Some p -> [ "--libdir"; Path.to_string p ] - )))) - in - ( Term.(const go - $ common - $ Arg.(value - & opt (some dir) None - & info ["destdir"; "prefix"] - ~docv:"PREFIX" - ~doc:"Directory where files are copied. For instance binaries \ - are copied into $(i,\\$prefix/bin), library files into \ - $(i,\\$prefix/lib), etc... It defaults to the current opam \ - prefix if opam is available and configured, otherwise it uses \ - the same prefix as the ocaml compiler.") - $ Arg.(value - & opt (some dir) None - & info ["libdir"] - ~docv:"PATH" - ~doc:"Directory where library files are copied, relative to \ - $(b,prefix) or absolute. If $(b,--prefix) \ - is specified the default is $(i,\\$prefix/lib), otherwise \ - it is the output of $(b,ocamlfind printconf destdir)" - ) - $ Arg.(value & pos_all package_name [] name_)) - , Term.info what ~doc ~man:help_secs) +let install_uninstall ~what = + let doc = + sprintf "%s packages using opam-installer." (String.capitalize what) + in + let name_ = Arg.info [] ~docv:"PACKAGE" in + let go common prefix_from_command_line libdir_from_command_line pkgs = + set_common common ~targets:[]; + let opam_installer = opam_installer () in + let log = Log.create common in + Scheduler.go ~log ~common + (Main.setup ~log common >>= fun setup -> + let pkgs = + match pkgs with + | [] -> Package.Name.Map.keys setup.packages + | l -> l + in + let install_files, missing_install_files = + List.concat_map pkgs ~f:(fun pkg -> + let fn = resolve_package_install setup pkg in + List.map setup.contexts ~f:(fun ctx -> + let fn = Path.append ctx.Context.build_dir fn in + if Path.exists fn then + Left (ctx, fn) + else + Right fn)) + |> List.partition_map ~f:(fun x -> x) + in + if missing_install_files <> [] then begin + die "The following .install are missing:\n\ + %s\n\ + You need to run: dune build @install" + (String.concat ~sep:"\n" + (List.map missing_install_files + ~f:(fun p -> sprintf "- %s" (Path.to_string p)))) + end; + (match + setup.contexts, prefix_from_command_line, libdir_from_command_line + with + | _ :: _ :: _, Some _, _ | _ :: _ :: _, _, Some _ -> + die "Cannot specify --prefix or --libdir when installing \ + into multiple contexts!" + | _ -> ()); + let module CMap = Map.Make(Context) in + let install_files_by_context = + CMap.of_list_multi install_files |> CMap.to_list + in + Fiber.parallel_iter install_files_by_context + ~f:(fun (context, install_files) -> + get_prefix context ~from_command_line:prefix_from_command_line + >>= fun prefix -> + get_libdir context ~libdir_from_command_line + >>= fun libdir -> + Fiber.parallel_iter install_files ~f:(fun path -> + let purpose = Process.Build_job install_files in + Process.run ~purpose ~env:setup.env Strict opam_installer + ([ sprintf "-%c" what.[0] + ; Path.to_string path + ; "--prefix" + ; Path.to_string prefix + ] @ + match libdir with + | None -> [] + | Some p -> [ "--libdir"; Path.to_string p ] + )))) + in + ( Term.(const go + $ common + $ Arg.(value + & opt (some dir) None + & info ["destdir"; "prefix"] + ~docv:"PREFIX" + ~doc:"Directory where files are copied. For instance binaries \ + are copied into $(i,\\$prefix/bin), library files into \ + $(i,\\$prefix/lib), etc... It defaults to the current opam \ + prefix if opam is available and configured, otherwise it uses \ + the same prefix as the ocaml compiler.") + $ Arg.(value + & opt (some dir) None + & info ["libdir"] + ~docv:"PATH" + ~doc:"Directory where library files are copied, relative to \ + $(b,prefix) or absolute. If $(b,--prefix) \ + is specified the default is $(i,\\$prefix/lib), otherwise \ + it is the output of $(b,ocamlfind printconf destdir)" + ) + $ Arg.(value & pos_all package_name [] name_)) + , Term.info what ~doc ~man:help_secs) - let install = install_uninstall ~what:"install" - let uninstall = install_uninstall ~what:"uninstall" +let install = install_uninstall ~what:"install" +let uninstall = install_uninstall ~what:"uninstall" - let context_arg ~doc = - Arg.(value - & opt string "default" - & info ["context"] ~docv:"CONTEXT" ~doc) +let context_arg ~doc = + Arg.(value + & opt string "default" + & info ["context"] ~docv:"CONTEXT" ~doc) - let exec = - let doc = - "Execute a command in a similar environment as if installation was performed." - in - let man = - [ `S "DESCRIPTION" - ; `P {|$(b,dune exec -- COMMAND) should behave in the same way as if you - do:|} - ; `Pre " \\$ dune install\n\ - \ \\$ COMMAND" - ; `P {|In particular if you run $(b,dune exec ocaml), you will have - access to the libraries defined in the workspace using your usual - directives ($(b,#require) for instance)|} - ; `P {|When a leading / is present in the command (absolute path), then the - path is interpreted as an absolute path|} - ; `P {|When a / is present at any other position (relative path), then the - path is interpreted as relative to the build context + current - working directory (or the value of $(b,--root) when ran outside of - the project root)|} - ; `Blocks help_secs - ] +let exec = + let doc = + "Execute a command in a similar environment as if installation was performed." + in + let man = + [ `S "DESCRIPTION" + ; `P {|$(b,dune exec -- COMMAND) should behave in the same way as if you + do:|} + ; `Pre " \\$ dune install\n\ + \ \\$ COMMAND" + ; `P {|In particular if you run $(b,dune exec ocaml), you will have + access to the libraries defined in the workspace using your usual + directives ($(b,#require) for instance)|} + ; `P {|When a leading / is present in the command (absolute path), then the + path is interpreted as an absolute path|} + ; `P {|When a / is present at any other position (relative path), then the + path is interpreted as relative to the build context + current + working directory (or the value of $(b,--root) when ran outside of + the project root)|} + ; `Blocks help_secs + ] + in + let go common context prog no_rebuild args = + set_common common ~targets:[]; + let log = Log.create common in + let setup = Scheduler.go ~log ~common (Main.setup ~log common) in + let context = Main.find_context_exn setup ~name:context in + let prog_where = + match Filename.analyze_program_name prog with + | Absolute -> + `This_abs (Path.of_string prog) + | In_path -> + `Search prog + | Relative_to_current_dir -> + let prog = prefix_target common prog in + `This_rel (Path.relative context.build_dir prog) in + let targets = lazy ( + (match prog_where with + | `Search p -> + [Path.relative (Config.local_install_bin_dir ~context:context.name) p] + | `This_rel p when Sys.win32 -> + [p; Path.extend_basename p ~suffix:Bin.exe] + | `This_rel p -> + [p] + | `This_abs p when Path.is_in_build_dir p -> + [p] + | `This_abs _ -> + []) + |> List.map ~f:Path.to_string + |> resolve_targets ~log common setup + |> List.concat_map ~f:(function + | Ok targets -> targets + | Error _ -> []) + ) in + let real_prog = + if not no_rebuild then begin + match Lazy.force targets with + | [] -> () + | targets -> + Scheduler.go ~log ~common (do_build setup targets); + Build_system.finalize setup.build_system + end; + match prog_where with + | `Search prog -> + let path = Config.local_install_bin_dir ~context:context.name :: context.path in + Bin.which prog ~path + | `This_rel prog + | `This_abs prog -> + if Path.exists prog then + Some prog + else if not Sys.win32 then + None + else + let prog = Path.extend_basename prog ~suffix:Bin.exe in + Option.some_if (Path.exists prog) prog in - let go common context prog no_rebuild args = - set_common common ~targets:[]; - let log = Log.create common in - let setup = Scheduler.go ~log ~common (Main.setup ~log common) in - let context = Main.find_context_exn setup ~name:context in - let prog_where = - match Filename.analyze_program_name prog with - | Absolute -> - `This_abs (Path.of_string prog) - | In_path -> - `Search prog - | Relative_to_current_dir -> - let prog = prefix_target common prog in - `This_rel (Path.relative context.build_dir prog) in - let targets = lazy ( - (match prog_where with - | `Search p -> - [Path.relative (Config.local_install_bin_dir ~context:context.name) p] - | `This_rel p when Sys.win32 -> - [p; Path.extend_basename p ~suffix:Bin.exe] - | `This_rel p -> - [p] - | `This_abs p when Path.is_in_build_dir p -> - [p] - | `This_abs _ -> - []) - |> List.map ~f:Path.to_string - |> resolve_targets ~log common setup - |> List.concat_map ~f:(function - | Ok targets -> targets - | Error _ -> []) - ) in - let real_prog = - if not no_rebuild then begin - match Lazy.force targets with - | [] -> () - | targets -> - Scheduler.go ~log ~common (do_build setup targets); - Build_system.finalize setup.build_system - end; - match prog_where with - | `Search prog -> - let path = Config.local_install_bin_dir ~context:context.name :: context.path in - Bin.which prog ~path - | `This_rel prog - | `This_abs prog -> - if Path.exists prog then - Some prog - else if not Sys.win32 then - None - else - let prog = Path.extend_basename prog ~suffix:Bin.exe in - Option.some_if (Path.exists prog) prog - in - match real_prog, no_rebuild with - | None, true -> - begin match Lazy.force targets with - | [] -> - Format.eprintf "@{Error@}: Program %S not found!@." prog; - raise Already_reported - | _::_ -> - Format.eprintf "@{Error@}: Program %S isn't built yet \ - you need to buid it first or remove the \ - --no-build option.@." prog; - raise Already_reported - end - | None, false -> + match real_prog, no_rebuild with + | None, true -> + begin match Lazy.force targets with + | [] -> Format.eprintf "@{Error@}: Program %S not found!@." prog; raise Already_reported - | Some real_prog, _ -> - let real_prog = Path.to_string real_prog in - let argv = Array.of_list (prog :: args) in - restore_cwd_and_execve common real_prog argv context.env - in - ( Term.(const go - $ common - $ context_arg ~doc:{|Run the command in this build context.|} - $ Arg.(required - & pos 0 (some string) None (Arg.info [] ~docv:"PROG")) - $ Arg.(value & flag - & info ["no-build"] - ~doc:"don't rebuild target before executing") - $ Arg.(value - & pos_right 0 string [] (Arg.info [] ~docv:"ARGS")) - ) - , Term.info "exec" ~doc ~man) + | _::_ -> + Format.eprintf "@{Error@}: Program %S isn't built yet \ + you need to buid it first or remove the \ + --no-build option.@." prog; + raise Already_reported + end + | None, false -> + Format.eprintf "@{Error@}: Program %S not found!@." prog; + raise Already_reported + | Some real_prog, _ -> + let real_prog = Path.to_string real_prog in + let argv = Array.of_list (prog :: args) in + restore_cwd_and_execve common real_prog argv context.env + in + ( Term.(const go + $ common + $ context_arg ~doc:{|Run the command in this build context.|} + $ Arg.(required + & pos 0 (some string) None (Arg.info [] ~docv:"PROG")) + $ Arg.(value & flag + & info ["no-build"] + ~doc:"don't rebuild target before executing") + $ Arg.(value + & pos_right 0 string [] (Arg.info [] ~docv:"ARGS")) + ) + , Term.info "exec" ~doc ~man) - let subst = - let doc = - "Substitute watermarks in source files." - in - let man = - let var name desc = - `Blocks [`Noblank; `P ("- $(b,%%" ^ name ^ "%%), " ^ desc) ] - in - let opam field = - var ("PKG_" ^ String.uppercase field) - ("contents of the $(b," ^ field ^ ":) field from the opam file") - in - [ `S "DESCRIPTION" - ; `P {|Substitute $(b,%%ID%%) strings in source files, in a similar fashion to - what topkg does in the default configuration.|} - ; `P {|This command is only meant to be called when a user pins a package to - its development version. Especially it replaces $(b,%%VERSION%%) strings - by the version obtained from the vcs. Currently only git is supported and - the version is obtained from the output of:|} - ; `Pre {| \$ git describe --always --dirty|} - ; `P {|$(b,dune subst) substitutes the variables that topkg substitutes with - the defatult configuration:|} - ; var "NAME" "the name of the package" - ; var "VERSION" "output of $(b,git describe --always --dirty)" - ; var "VERSION_NUM" "same as $(b,%%VERSION%%) but with a potential leading \ - 'v' or 'V' dropped" - ; var "VCS_COMMIT_ID" "commit hash from the vcs" - ; opam "maintainer" - ; opam "authors" - ; opam "homepage" - ; opam "issues" - ; opam "doc" - ; opam "license" - ; opam "repo" - ; `P {|It is not possible to customize this list. If you wish to do so you need to - configure topkg instead and use it to perform the substitution.|} - ; `P {|Note that the expansion of $(b,%%NAME%%) is guessed using the following - heuristic: if all the $(b,.opam) files in the current directory are - prefixed by the shortest package name, this prefix is used. Otherwise you must - specify a name with the $(b,-n) command line option.|} - ; `P {|In order to call $(b,dune subst) when your package is pinned, add this line - to the $(b,build:) field of your opam file:|} - ; `Pre (sprintf {| [%S "subst"] {pinned}|} program_name) - ; `Blocks help_secs - ] +let subst = + let doc = + "Substitute watermarks in source files." + in + let man = + let var name desc = + `Blocks [`Noblank; `P ("- $(b,%%" ^ name ^ "%%), " ^ desc) ] in - let go common name = - set_common common ~targets:[]; - Scheduler.go ~common (Watermarks.subst ?name ()) + let opam field = + var ("PKG_" ^ String.uppercase field) + ("contents of the $(b," ^ field ^ ":) field from the opam file") in - ( Term.(const go - $ common - $ Arg.(value - & opt (some string) None - & info ["n"; "name"] ~docv:"NAME" - ~doc:"Use this package name instead of detecting it.") - ) - , Term.info "subst" ~doc ~man) + [ `S "DESCRIPTION" + ; `P {|Substitute $(b,%%ID%%) strings in source files, in a similar fashion to + what topkg does in the default configuration.|} + ; `P {|This command is only meant to be called when a user pins a package to + its development version. Especially it replaces $(b,%%VERSION%%) strings + by the version obtained from the vcs. Currently only git is supported and + the version is obtained from the output of:|} + ; `Pre {| \$ git describe --always --dirty|} + ; `P {|$(b,dune subst) substitutes the variables that topkg substitutes with + the defatult configuration:|} + ; var "NAME" "the name of the package" + ; var "VERSION" "output of $(b,git describe --always --dirty)" + ; var "VERSION_NUM" "same as $(b,%%VERSION%%) but with a potential leading \ + 'v' or 'V' dropped" + ; var "VCS_COMMIT_ID" "commit hash from the vcs" + ; opam "maintainer" + ; opam "authors" + ; opam "homepage" + ; opam "issues" + ; opam "doc" + ; opam "license" + ; opam "repo" + ; `P {|It is not possible to customize this list. If you wish to do so you need to + configure topkg instead and use it to perform the substitution.|} + ; `P {|Note that the expansion of $(b,%%NAME%%) is guessed using the following + heuristic: if all the $(b,.opam) files in the current directory are + prefixed by the shortest package name, this prefix is used. Otherwise you must + specify a name with the $(b,-n) command line option.|} + ; `P {|In order to call $(b,dune subst) when your package is pinned, add this line + to the $(b,build:) field of your opam file:|} + ; `Pre {| [dune "subst"] {pinned}|} + ; `Blocks help_secs + ] + in + let go common name = + set_common common ~targets:[]; + Scheduler.go ~common (Watermarks.subst ?name ()) + in + ( Term.(const go + $ common + $ Arg.(value + & opt (some string) None + & info ["n"; "name"] ~docv:"NAME" + ~doc:"Use this package name instead of detecting it.") + ) + , Term.info "subst" ~doc ~man) - let utop = - let doc = "Load library in utop" in - let man = - [ `S "DESCRIPTION" - ; `P {|$(b,dune utop DIR) build and run utop toplevel with libraries defined in DIR|} - ; `Blocks help_secs - ] in - let go common dir ctx_name args = - let utop_target = dir |> Path.of_string |> Utop.utop_exe |> Path.to_string in - set_common common ~targets:[utop_target]; - let log = Log.create common in - let (build_system, context, utop_path) = - (Main.setup ~log common >>= fun setup -> - let context = Main.find_context_exn setup ~name:ctx_name in - let setup = { setup with contexts = [context] } in - let target = - match resolve_targets_exn ~log common setup [utop_target] with - | [] -> die "no libraries defined in %s" dir - | [File target] -> target - | [Alias_rec _] | _::_::_ -> assert false - in - do_build setup [File target] >>| fun () -> - (setup.build_system, context, Path.to_string target) - ) |> Scheduler.go ~log ~common in - Build_system.finalize build_system; - restore_cwd_and_execve common utop_path (Array.of_list (utop_path :: args)) - context.env - in - let name_ = Arg.info [] ~docv:"PATH" in - ( Term.(const go - $ common - $ Arg.(value & pos 0 dir "" name_) - $ context_arg ~doc:{|Select context where to build/run utop.|} - $ Arg.(value & pos_right 0 string [] (Arg.info [] ~docv:"ARGS"))) - , Term.info "utop" ~doc ~man ) +let utop = + let doc = "Load library in utop" in + let man = + [ `S "DESCRIPTION" + ; `P {|$(b,dune utop DIR) build and run utop toplevel with libraries defined in DIR|} + ; `Blocks help_secs + ] in + let go common dir ctx_name args = + let utop_target = dir |> Path.of_string |> Utop.utop_exe |> Path.to_string in + set_common common ~targets:[utop_target]; + let log = Log.create common in + let (build_system, context, utop_path) = + (Main.setup ~log common >>= fun setup -> + let context = Main.find_context_exn setup ~name:ctx_name in + let setup = { setup with contexts = [context] } in + let target = + match resolve_targets_exn ~log common setup [utop_target] with + | [] -> die "no libraries defined in %s" dir + | [File target] -> target + | [Alias_rec _] | _::_::_ -> assert false + in + do_build setup [File target] >>| fun () -> + (setup.build_system, context, Path.to_string target) + ) |> Scheduler.go ~log ~common in + Build_system.finalize build_system; + restore_cwd_and_execve common utop_path (Array.of_list (utop_path :: args)) + context.env + in + let name_ = Arg.info [] ~docv:"PATH" in + ( Term.(const go + $ common + $ Arg.(value & pos 0 dir "" name_) + $ context_arg ~doc:{|Select context where to build/run utop.|} + $ Arg.(value & pos_right 0 string [] (Arg.info [] ~docv:"ARGS"))) + , Term.info "utop" ~doc ~man ) - let promote = - let doc = "Promote files from the last run" in - let man = - [ `S "DESCRIPTION" - ; `P {|Considering all actions of the form $(b,(diff a b)) that failed - in the last run of dune, $(b,dune promote) does the following: +let promote = + let doc = "Promote files from the last run" in + let man = + [ `S "DESCRIPTION" + ; `P {|Considering all actions of the form $(b,(diff a b)) that failed + in the last run of dune, $(b,dune promote) does the following: - If $(b,a) is present in the source tree but $(b,b) isn't, $(b,b) is - copied over to $(b,a) in the source tree. The idea behind this is that - you might use $(b,(diff file.expected file.generated)) and then call - $(b,dune promote) to promote the generated file. - |} - ; `Blocks help_secs - ] in - let go common = - set_common common ~targets:[]; - (* We load and restore the digest cache as we need to clear the - cache for promoted files, due to issues on OSX. *) - Utils.Cached_digest.load (); - Action.Promotion.promote_files_registered_in_last_run (); - Utils.Cached_digest.dump () - in - ( Term.(const go - $ common) - , Term.info "promote" ~doc ~man ) + If $(b,a) is present in the source tree but $(b,b) isn't, $(b,b) is + copied over to $(b,a) in the source tree. The idea behind this is that + you might use $(b,(diff file.expected file.generated)) and then call + $(b,dune promote) to promote the generated file. + |} + ; `Blocks help_secs + ] in + let go common = + set_common common ~targets:[]; + (* We load and restore the digest cache as we need to clear the + cache for promoted files, due to issues on OSX. *) + Utils.Cached_digest.load (); + Action.Promotion.promote_files_registered_in_last_run (); + Utils.Cached_digest.dump () + in + ( Term.(const go + $ common) + , Term.info "promote" ~doc ~man ) - module Help = struct - let config = - ("dune-config", 5, "", "Dune", "Dune manual"), - [ `S Manpage.s_synopsis - ; `Pre "~/.config/dune/config" - ; `S Manpage.s_description - ; `P {|Unless $(b,--no-config) or $(b,-p) is passed, Dune will read a - configuration file from the user home directory. This file is used - to control various aspects of the behavior of Dune.|} - ; `P {|The configuration file is normally $(b,~/.config/dune/config) on - Unix systems and $(b,Local Settings/dune/config) in the User home - directory on Windows. However, it is possible to specify an - alternative configuration file with the $(b,--config-file) option.|} - ; `P {|This file must be written in S-expression syntax and be composed of - a list of stanzas. The following sections describe the stanzas available.|} - ; `S "DISPLAY MODES" - ; `P {|Syntax: $(b,\(display MODE\))|} - ; `P {|This stanza controls how Dune reports what it is doing to the user. - This parameter can also be set from the command line via $(b,--display MODE). - The following display modes are available:|} - ; `Blocks - (List.map ~f:(fun (x, desc) -> `I (sprintf "$(b,%s)" x, desc)) - [ "progress", - {|This is the default, Dune shows and update a - status line as build goals are being completed.|} - ; "quiet", - {|Only display errors.|} - ; "short", - {|Print one line per command being executed, with the - binary name on the left and the reason it is being executed for - on the right.|} - ; "verbose", - {|Print the full command lines of programs being - executed by Dune, with some colors to help differentiate - programs.|} - ]) - ; `P {|Note that when the selected display mode is $(b,progress) and the - output is not a terminal then the $(b,quiet) mode is selected - instead. This rule doesn't apply when running Dune inside Emacs. - Dune detects whether it is executed from inside Emacs or not by - looking at the environment variable $(b,INSIDE_EMACS) that is set by - Emacs. If you want the same behavior with another editor, you can set - this variable. If your editor already sets another variable, - please open a ticket on the ocaml/dune github project so that we can - add support for it.|} - ; `S "JOBS" - ; `P {|Syntax: $(b,\(jobs NUMBER\))|} - ; `P {|Set the maximum number of jobs Dune might run in parallel. - This can also be set from the command line via $(b,-j NUMBER).|} - ; `P {|The default for this value is 4.|} - ; common_footer - ] +module Help = struct + let config = + ("dune-config", 5, "", "Dune", "Dune manual"), + [ `S Manpage.s_synopsis + ; `Pre "~/.config/dune/config" + ; `S Manpage.s_description + ; `P {|Unless $(b,--no-config) or $(b,-p) is passed, Dune will read a + configuration file from the user home directory. This file is used + to control various aspects of the behavior of Dune.|} + ; `P {|The configuration file is normally $(b,~/.config/dune/config) on + Unix systems and $(b,Local Settings/dune/config) in the User home + directory on Windows. However, it is possible to specify an + alternative configuration file with the $(b,--config-file) option.|} + ; `P {|This file must be written in S-expression syntax and be composed of + a list of stanzas. The following sections describe the stanzas available.|} + ; `S "DISPLAY MODES" + ; `P {|Syntax: $(b,\(display MODE\))|} + ; `P {|This stanza controls how Dune reports what it is doing to the user. + This parameter can also be set from the command line via $(b,--display MODE). + The following display modes are available:|} + ; `Blocks + (List.map ~f:(fun (x, desc) -> `I (sprintf "$(b,%s)" x, desc)) + [ "progress", + {|This is the default, Dune shows and update a + status line as build goals are being completed.|} + ; "quiet", + {|Only display errors.|} + ; "short", + {|Print one line per command being executed, with the + binary name on the left and the reason it is being executed for + on the right.|} + ; "verbose", + {|Print the full command lines of programs being + executed by Dune, with some colors to help differentiate + programs.|} + ]) + ; `P {|Note that when the selected display mode is $(b,progress) and the + output is not a terminal then the $(b,quiet) mode is selected + instead. This rule doesn't apply when running Dune inside Emacs. + Dune detects whether it is executed from inside Emacs or not by + looking at the environment variable $(b,INSIDE_EMACS) that is set by + Emacs. If you want the same behavior with another editor, you can set + this variable. If your editor already sets another variable, + please open a ticket on the ocaml/dune github project so that we can + add support for it.|} + ; `S "JOBS" + ; `P {|Syntax: $(b,\(jobs NUMBER\))|} + ; `P {|Set the maximum number of jobs Dune might run in parallel. + This can also be set from the command line via $(b,-j NUMBER).|} + ; `P {|The default for this value is 4.|} + ; common_footer + ] + + type what = + | Man of Manpage.t + | List_topics - type what = - | Man of Manpage.t - | List_topics + let commands = + [ "config", Man config + ; "topics", List_topics + ] - let commands = - [ "config", Man config - ; "topics", List_topics + let help = + let doc = "Additional Dune help" in + let man = + [ `S "DESCRIPTION" + ; `P {|$(b,dune help TOPIC) provides additional help on the given topic. + The following topics are available:|} + ; `Blocks (List.concat_map commands ~f:(fun (s, what) -> + match what with + | List_topics -> [] + | Man ((title, _, _, _, _), _) -> [`I (sprintf "$(b,%s)" s, title)])) + ; common_footer ] + in + let go man_format what = + match what with + | None -> + `Help (man_format, Some "help") + | Some (Man man_page) -> + Format.printf "%a@?" (Manpage.print man_format) man_page; + `Ok () + | Some List_topics -> + List.filter_map commands ~f:(fun (s, what) -> + match what with + | List_topics -> None + | _ -> Some s) + |> List.sort ~compare:String.compare + |> String.concat ~sep:"\n" + |> print_endline; + `Ok () + in + ( Term.(ret (const go + $ Arg.man_format + $ Arg.(value + & pos 0 (some (enum commands)) None + & info [] ~docv:"TOPIC") + )) + , Term.info "help" ~doc ~man + ) +end + +let all = + [ installed_libraries + ; external_lib_deps + ; build_targets + ; runtest + ; clean + ; install + ; uninstall + ; exec + ; subst + ; rules + ; utop + ; promote + ; Help.help + ] - let help = - let doc = "Additional Dune help" in - let man = +let default = + let doc = "composable build system for OCaml" in + ( Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common)) + , Term.info "dune" ~doc ~version:"%%VERSION%%" + ~man: [ `S "DESCRIPTION" - ; `P {|$(b,dune help TOPIC) provides additional help on the given topic. - The following topics are available:|} - ; `Blocks (List.concat_map commands ~f:(fun (s, what) -> - match what with - | List_topics -> [] - | Man ((title, _, _, _, _), _) -> [`I (sprintf "$(b,%s)" s, title)])) - ; common_footer + ; `P {|Dune is a build system designed for OCaml projects only. It + focuses on providing the user with a consistent experience and takes + care of most of the low-level details of OCaml compilation. All you + have to do is provide a description of your project and Dune will + do the rest. + |} + ; `P {|The scheme it implements is inspired from the one used inside Jane + Street and adapted to the open source world. It has matured over a + long time and is used daily by hundreds of developers, which means + that it is highly tested and productive. + |} + ; `Blocks help_secs ] - in - let go man_format what = - match what with - | None -> - `Help (man_format, Some "help") - | Some (Man man_page) -> - Format.printf "%a@?" (Manpage.print man_format) man_page; - `Ok () - | Some List_topics -> - List.filter_map commands ~f:(fun (s, what) -> - match what with - | List_topics -> None - | _ -> Some s) - |> List.sort ~compare:String.compare - |> String.concat ~sep:"\n" - |> print_endline; - `Ok () - in - ( Term.(ret (const go - $ Arg.man_format - $ Arg.(value - & pos 0 (some (enum commands)) None - & info [] ~docv:"TOPIC") - )) - , Term.info "help" ~doc ~man - ) - end - - let all = - [ installed_libraries - ; external_lib_deps - ; build_targets - ; runtest - ; clean - ; install - ; uninstall - ; exec - ; subst - ; rules - ; utop - ; promote - ; Help.help - ] - - let default = - let doc = "composable build system for OCaml" in - ( Term.(ret (const (fun _ -> `Help (`Pager, None)) $ common)) - , Term.info program_name ~doc ~version:"%%VERSION%%" - ~man: - [ `S "DESCRIPTION" - ; `P {|Dune is a build system designed for OCaml projects only. It - focuses on providing the user with a consistent experience and takes - care of most of the low-level details of OCaml compilation. All you - have to do is provide a description of your project and Dune will - do the rest. - |} - ; `P {|The scheme it implements is inspired from the one used inside Jane - Street and adapted to the open source world. It has matured over a - long time and is used daily by hundreds of developers, which means - that it is highly tested and productive. - |} - ; `Blocks help_secs - ] - ) + ) - let () = - Colors.setup_err_formatter_colors (); - try - match Term.eval_choice default all ~catch:false with - | `Error _ -> exit 1 - | _ -> exit 0 - with - | Fiber.Never -> exit 1 - | exn -> - Report_error.report exn; - exit 1 -end +let () = + Colors.setup_err_formatter_colors (); + try + match Term.eval_choice default all ~catch:false with + | `Error _ -> exit 1 + | _ -> exit 0 + with + | Fiber.Never -> exit 1 + | exn -> + Report_error.report exn; + exit 1 diff --git a/bin/main.mli b/bin/main.mli index 622a8287404..e790aeb70f0 100644 --- a/bin/main.mli +++ b/bin/main.mli @@ -1,3 +1 @@ -type which = Dune | Jbuilder - -module Make(M : sig val which : which end) : sig end +(* empty *) diff --git a/bin/main_dune.ml b/bin/main_dune.ml deleted file mode 100644 index 014b18448b6..00000000000 --- a/bin/main_dune.ml +++ /dev/null @@ -1 +0,0 @@ -include Main.Make(struct let which = Main.Dune end) diff --git a/bin/main_dune.mli b/bin/main_dune.mli deleted file mode 100644 index e790aeb70f0..00000000000 --- a/bin/main_dune.mli +++ /dev/null @@ -1 +0,0 @@ -(* empty *) diff --git a/bin/main_jbuilder.ml b/bin/main_jbuilder.ml deleted file mode 100644 index aa9950e99d3..00000000000 --- a/bin/main_jbuilder.ml +++ /dev/null @@ -1 +0,0 @@ -include Main.Make(struct let which = Main.Jbuilder end) diff --git a/bin/main_jbuilder.mli b/bin/main_jbuilder.mli deleted file mode 100644 index e790aeb70f0..00000000000 --- a/bin/main_jbuilder.mli +++ /dev/null @@ -1 +0,0 @@ -(* empty *) diff --git a/doc/jbuild b/doc/jbuild index 17782108f56..2054d50ea93 100644 --- a/doc/jbuild +++ b/doc/jbuild @@ -5,14 +5,9 @@ (action (with-stdout-to ${@} (run ${bin:dune} --help=groff))))) -(rule - ((targets (jbuilder.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} --help=groff))))) - (install ((section man) - (files (dune.1 jbuilder.1)))) + (files (dune.1)))) (rule ((targets (dune-config.5)) @@ -23,27 +18,15 @@ ((section man) (files (dune-config.5)))) -(include jbuild.inc.dune) -(include jbuild.inc.jbuilder) +(include jbuild.inc) (rule - ((targets (jbuild.inc.dune.gen)) + ((targets (jbuild.inc.gen)) (deps ((package dune))) (action (with-stdout-to ${@} - (run bash ${path:update-jbuild.sh} dune))))) - -(rule - ((targets (jbuild.inc.jbuilder.gen)) - (deps ((package dune))) - (action - (with-stdout-to ${@} - (run bash ${path:update-jbuild.sh} jbuilder))))) - -(alias - ((name runtest) - (action (diff jbuild.inc.dune jbuild.inc.dune.gen)))) + (run bash ${path:update-jbuild.sh}))))) (alias ((name runtest) - (action (diff jbuild.inc.jbuilder jbuild.inc.jbuilder.gen)))) + (action (diff jbuild.inc jbuild.inc.gen)))) diff --git a/doc/jbuild.inc.dune b/doc/jbuild.inc similarity index 69% rename from doc/jbuild.inc.dune rename to doc/jbuild.inc index f90aae57e47..f915ebab95d 100644 --- a/doc/jbuild.inc.dune +++ b/doc/jbuild.inc @@ -2,7 +2,7 @@ (rule ((targets (dune-build.1)) (action (with-stdout-to ${@} - (run ${bin:dune} build --help=groff))))) + (run dune build --help=groff))))) (install ((section man) @@ -11,7 +11,7 @@ (rule ((targets (dune-clean.1)) (action (with-stdout-to ${@} - (run ${bin:dune} clean --help=groff))))) + (run dune clean --help=groff))))) (install ((section man) @@ -20,7 +20,7 @@ (rule ((targets (dune-exec.1)) (action (with-stdout-to ${@} - (run ${bin:dune} exec --help=groff))))) + (run dune exec --help=groff))))) (install ((section man) @@ -29,7 +29,7 @@ (rule ((targets (dune-external-lib-deps.1)) (action (with-stdout-to ${@} - (run ${bin:dune} external-lib-deps --help=groff))))) + (run dune external-lib-deps --help=groff))))) (install ((section man) @@ -38,7 +38,7 @@ (rule ((targets (dune-help.1)) (action (with-stdout-to ${@} - (run ${bin:dune} help --help=groff))))) + (run dune help --help=groff))))) (install ((section man) @@ -47,7 +47,7 @@ (rule ((targets (dune-install.1)) (action (with-stdout-to ${@} - (run ${bin:dune} install --help=groff))))) + (run dune install --help=groff))))) (install ((section man) @@ -56,7 +56,7 @@ (rule ((targets (dune-installed-libraries.1)) (action (with-stdout-to ${@} - (run ${bin:dune} installed-libraries --help=groff))))) + (run dune installed-libraries --help=groff))))) (install ((section man) @@ -65,7 +65,7 @@ (rule ((targets (dune-promote.1)) (action (with-stdout-to ${@} - (run ${bin:dune} promote --help=groff))))) + (run dune promote --help=groff))))) (install ((section man) @@ -74,7 +74,7 @@ (rule ((targets (dune-rules.1)) (action (with-stdout-to ${@} - (run ${bin:dune} rules --help=groff))))) + (run dune rules --help=groff))))) (install ((section man) @@ -83,7 +83,7 @@ (rule ((targets (dune-runtest.1)) (action (with-stdout-to ${@} - (run ${bin:dune} runtest --help=groff))))) + (run dune runtest --help=groff))))) (install ((section man) @@ -92,7 +92,7 @@ (rule ((targets (dune-subst.1)) (action (with-stdout-to ${@} - (run ${bin:dune} subst --help=groff))))) + (run dune subst --help=groff))))) (install ((section man) @@ -101,7 +101,7 @@ (rule ((targets (dune-uninstall.1)) (action (with-stdout-to ${@} - (run ${bin:dune} uninstall --help=groff))))) + (run dune uninstall --help=groff))))) (install ((section man) @@ -110,7 +110,7 @@ (rule ((targets (dune-utop.1)) (action (with-stdout-to ${@} - (run ${bin:dune} utop --help=groff))))) + (run dune utop --help=groff))))) (install ((section man) diff --git a/doc/jbuild.inc.jbuilder b/doc/jbuild.inc.jbuilder deleted file mode 100644 index 443cb0c90f2..00000000000 --- a/doc/jbuild.inc.jbuilder +++ /dev/null @@ -1,118 +0,0 @@ - -(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-help.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} help --help=groff))))) - -(install - ((section man) - (files (jbuilder-help.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-promote.1)) - (action (with-stdout-to ${@} - (run ${bin:jbuilder} promote --help=groff))))) - -(install - ((section man) - (files (jbuilder-promote.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/update-jbuild.sh b/doc/update-jbuild.sh index ae6981a7c40..929af2052bf 100755 --- a/doc/update-jbuild.sh +++ b/doc/update-jbuild.sh @@ -4,22 +4,20 @@ set -e -o pipefail -prog=$1 - -CMDS=$($prog --help=plain | \ +CMDS=$(dune --help=plain | \ sed -n '/COMMANDS/,/OPTIONS/p' | sed -En 's/^ ([a-z-]+)/\1/p') for cmd in $CMDS; do cat < w | None -> match workspace_file with - | Some p when Path.exists p -> + | Some p -> Workspace.load ?x p | _ -> - { merlin_context = Some "default" - ; contexts = [Default [ - match x with - | None -> Native - | Some x -> Named x - ]] - } + match + List.find_map ["dune-workspace"; "jbuild-workspace"] ~f:(fun fn -> + let p = Path.of_string fn in + if Path.exists p then + Some p + else + None) + with + | Some p -> Workspace.load ?x p + | None -> + { merlin_context = Some "default" + ; contexts = [Default [ + match x with + | None -> Native + | Some x -> Named x + ]] + } in Fiber.parallel_map workspace.contexts ~f:(fun ctx_def -> diff --git a/test/blackbox-tests/test-cases/findlib/run.t b/test/blackbox-tests/test-cases/findlib/run.t index d8028be9e6d..2fb9e848cad 100644 --- a/test/blackbox-tests/test-cases/findlib/run.t +++ b/test/blackbox-tests/test-cases/findlib/run.t @@ -9,5 +9,5 @@ Reproduction case for #484. The error should point to src/jbuild $ jbuilder build @install File "src/jbuild", line 4, characters 16-17: Error: Library "a" not found. - Hint: try: jbuilder external-lib-deps --missing @install + Hint: try: dune external-lib-deps --missing @install [1] diff --git a/test/blackbox-tests/test-cases/github25/run.t b/test/blackbox-tests/test-cases/github25/run.t index bdab8e7a529..cc275cdf522 100644 --- a/test/blackbox-tests/test-cases/github25/run.t +++ b/test/blackbox-tests/test-cases/github25/run.t @@ -18,7 +18,7 @@ We need ocamlfind to run this test File ".../plop/META", line 1, characters 0-0: Error: Library "une-lib-qui-nexiste-pas" not found. -> required by library "plop.ca-marche-pas" in .../plop - Hint: try: jbuilder external-lib-deps --missing --only-packages pas-de-bol @install + Hint: try: dune external-lib-deps --missing --only-packages pas-de-bol @install ocamldep root/b.ml.d ocamlc root/.pas_de_bol.objs/pas_de_bol.{cmi,cmo,cmt} ocamlopt root/.pas_de_bol.objs/pas_de_bol.{cmx,o} diff --git a/test/blackbox-tests/test-cases/github644/run.t b/test/blackbox-tests/test-cases/github644/run.t index d5bf265dab9..c7172c24952 100644 --- a/test/blackbox-tests/test-cases/github644/run.t +++ b/test/blackbox-tests/test-cases/github644/run.t @@ -1,7 +1,7 @@ $ jbuilder runtest File "jbuild", line 4, characters 20-42: Error: Library "ppx_that_doesn't_exist" not found. - Hint: try: jbuilder external-lib-deps --missing @runtest + Hint: try: dune external-lib-deps --missing @runtest [1] These should print something: From 0324e18c89c4c2293da54339e6f39a5861d09669 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 1 May 2018 17:23:56 +0100 Subject: [PATCH 14/15] Update tests --- test/unit-tests/tests.mlt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit-tests/tests.mlt b/test/unit-tests/tests.mlt index 55fc30a215c..af422c8bd45 100644 --- a/test/unit-tests/tests.mlt +++ b/test/unit-tests/tests.mlt @@ -84,7 +84,7 @@ let conf = ~toolchain:"tlc" ~context:"" [%%expect{| -val conf : Jbuilder.Findlib.Config.t = +val conf : Dune.Findlib.Config.t = { vars = [ (FOO_BAR, { set_rules = [ { preds_required = [ "tlc"; "env" ] @@ -103,11 +103,11 @@ let env_pp fmt env = Sexp.pp fmt (Env.sexp_of_t env);; #install_printer env_pp;; [%%expect{| -val env_pp : Format.formatter -> Jbuilder.Env.t -> unit = +val env_pp : Format.formatter -> Dune.Env.t -> unit = |}] let env = Findlib.Config.env conf [%%expect{| -val env : Jbuilder.Env.t = ((FOO_BAR "my variable")) +val env : Dune.Env.t = ((FOO_BAR "my variable")) |}] From d6e878674a78857088142f363870bebed506626c Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Tue, 1 May 2018 17:25:02 +0100 Subject: [PATCH 15/15] Update tests --- test/blackbox-tests/test-cases/aliases/run.t | 16 ++++++++-------- test/blackbox-tests/test-cases/c-stubs/run.t | 4 ++-- .../blackbox-tests/test-cases/configurator/run.t | 6 +++--- test/blackbox-tests/test-cases/copy_files/run.t | 4 ++-- .../test-cases/depend-on-the-universe/run.t | 10 +++++----- .../test-cases/exclude-missing-module/run.t | 2 +- test/blackbox-tests/test-cases/exec-cmd/run.t | 12 ++++++------ test/blackbox-tests/test-cases/findlib/run.t | 4 ++-- test/blackbox-tests/test-cases/force-test/run.t | 8 ++++---- .../test-cases/gen-opam-install-file/run.t | 2 +- test/blackbox-tests/test-cases/github20/run.t | 2 +- test/blackbox-tests/test-cases/github24/run.t | 2 +- test/blackbox-tests/test-cases/github25/run.t | 4 ++-- test/blackbox-tests/test-cases/github534/run.t | 2 +- test/blackbox-tests/test-cases/github568/run.t | 2 +- test/blackbox-tests/test-cases/github597/run.t | 2 +- test/blackbox-tests/test-cases/github644/run.t | 6 +++--- test/blackbox-tests/test-cases/github660/run.t | 8 ++++---- .../test-cases/github717-odoc-index/run.t | 2 +- .../blackbox-tests/test-cases/include-loop/run.t | 2 +- .../blackbox-tests/test-cases/inline_tests/run.t | 8 ++++---- .../installable-dup-private-libs/run.t | 2 +- test/blackbox-tests/test-cases/intf-only/run.t | 10 +++++----- test/blackbox-tests/test-cases/js_of_ocaml/run.t | 4 ++-- .../test-cases/lib-available/run.t | 2 +- test/blackbox-tests/test-cases/loop/run.t | 6 +++--- test/blackbox-tests/test-cases/menhir/run.t | 2 +- .../blackbox-tests/test-cases/merlin-tests/run.t | 2 +- test/blackbox-tests/test-cases/meta-gen/run.t | 2 +- test/blackbox-tests/test-cases/misc/run.t | 2 +- .../test-cases/multiple-private-libs/run.t | 2 +- test/blackbox-tests/test-cases/null-dep/run.t | 2 +- .../blackbox-tests/test-cases/ocaml-syntax/run.t | 2 +- .../test-cases/ocamldep-multi-stanzas/run.t | 4 ++-- .../test-cases/odoc-unique-mlds/run.t | 4 ++-- test/blackbox-tests/test-cases/odoc/run.t | 8 ++++---- test/blackbox-tests/test-cases/output-obj/run.t | 4 ++-- test/blackbox-tests/test-cases/package-dep/run.t | 2 +- .../blackbox-tests/test-cases/ppx-rewriter/run.t | 6 +++--- .../test-cases/private-public-overlap/run.t | 10 +++++----- test/blackbox-tests/test-cases/promote/run.t | 12 ++++++------ test/blackbox-tests/test-cases/quoting/run.t | 2 +- test/blackbox-tests/test-cases/reason/run.t | 2 +- .../blackbox-tests/test-cases/redirections/run.t | 2 +- test/blackbox-tests/test-cases/scope-bug/run.t | 2 +- .../test-cases/scope-ppx-bug/run.t | 2 +- test/blackbox-tests/test-cases/select/run.t | 2 +- test/blackbox-tests/test-cases/utop/run.t | 2 +- 48 files changed, 105 insertions(+), 105 deletions(-) diff --git a/test/blackbox-tests/test-cases/aliases/run.t b/test/blackbox-tests/test-cases/aliases/run.t index 1211d4d56ad..b249a3bbb63 100644 --- a/test/blackbox-tests/test-cases/aliases/run.t +++ b/test/blackbox-tests/test-cases/aliases/run.t @@ -1,22 +1,22 @@ - $ jbuilder clean --display short - $ jbuilder build --display short @just-in-src + $ dune clean --display short + $ dune build --display short @just-in-src running in src - $ jbuilder clean --display short - $ jbuilder build --display short @everywhere + $ dune clean --display short + $ dune build --display short @everywhere running in src/foo/bar running in src/foo/baz running in src - $ jbuilder clean --display short - $ jbuilder build --display short @x + $ dune clean --display short + $ dune build --display short @x running in src/foo/bar running in src/foo/baz running in src - $ jbuilder build --display short @plop + $ dune build --display short @plop From the command line: Error: Alias plop is empty. It is not defined in . or any of its descendants. [1] - $ jbuilder build --display short @truc/x + $ dune build --display short @truc/x From the command line: Error: Don't know about directory truc! [1] diff --git a/test/blackbox-tests/test-cases/c-stubs/run.t b/test/blackbox-tests/test-cases/c-stubs/run.t index bdf668e4e82..5dcbb41986c 100644 --- a/test/blackbox-tests/test-cases/c-stubs/run.t +++ b/test/blackbox-tests/test-cases/c-stubs/run.t @@ -1,4 +1,4 @@ - $ jbuilder exec ./qnativerun/run.exe --display short + $ dune exec ./qnativerun/run.exe --display short ocamldep qnativerun/run.ml.d ocamlc q/q_stub$ext_obj ocamlmklib q/dllq_stubs$ext_dll,q/libq_stubs$ext_lib @@ -11,4 +11,4 @@ ocamlopt qnativerun/.run.eobjs/run.{cmx,o} ocamlopt qnativerun/run.exe 42 -# $ jbuilder exec ./qbyterun/run.bc --display short +# $ dune exec ./qbyterun/run.bc --display short diff --git a/test/blackbox-tests/test-cases/configurator/run.t b/test/blackbox-tests/test-cases/configurator/run.t index 3e29af3b883..533b38039b5 100644 --- a/test/blackbox-tests/test-cases/configurator/run.t +++ b/test/blackbox-tests/test-cases/configurator/run.t @@ -1,14 +1,14 @@ Show that config values are present - $ jbuilder exec config/run.exe + $ dune exec config/run.exe DUNE_CONFIGURATOR is present version is present We're able to compile C program sucessfully - $ jbuilder exec c_test/run.exe + $ dune exec c_test/run.exe Successfully compiled c program Importing #define's from code is successful - $ jbuilder exec import-define/run.exe + $ dune exec import-define/run.exe CAML_CONFIG_H=true Page_log=12 CONFIGURATOR_TESTING=foobar diff --git a/test/blackbox-tests/test-cases/copy_files/run.t b/test/blackbox-tests/test-cases/copy_files/run.t index feba60bcd8c..eb92ac921cc 100644 --- a/test/blackbox-tests/test-cases/copy_files/run.t +++ b/test/blackbox-tests/test-cases/copy_files/run.t @@ -1,4 +1,4 @@ - $ jbuilder build test.exe .merlin --display short --debug-dependency-path + $ dune build test.exe .merlin --display short --debug-dependency-path ocamllex lexers/lexer1.ml ocamldep lexer1.ml.d ocamldep test.ml.d @@ -13,6 +13,6 @@ ocamlc .test.eobjs/test.{cmi,cmo,cmt} ocamlopt .test.eobjs/test.{cmx,o} ocamlopt test.exe - $ jbuilder build @bar-source --display short + $ dune build @bar-source --display short #line 1 "include/bar.h" int foo () {return 42;} diff --git a/test/blackbox-tests/test-cases/depend-on-the-universe/run.t b/test/blackbox-tests/test-cases/depend-on-the-universe/run.t index 362ffdc53e5..720c0ab08b5 100644 --- a/test/blackbox-tests/test-cases/depend-on-the-universe/run.t +++ b/test/blackbox-tests/test-cases/depend-on-the-universe/run.t @@ -1,10 +1,10 @@ - $ jbuilder build @x + $ dune build @x Hello, world! - $ jbuilder build @x + $ dune build @x Hello, world! - $ jbuilder build @x + $ dune build @x Hello, world! - $ jbuilder build @x + $ dune build @x Hello, world! - $ jbuilder build @x + $ dune build @x Hello, world! diff --git a/test/blackbox-tests/test-cases/exclude-missing-module/run.t b/test/blackbox-tests/test-cases/exclude-missing-module/run.t index 1748c2435fb..900bbcae9f4 100644 --- a/test/blackbox-tests/test-cases/exclude-missing-module/run.t +++ b/test/blackbox-tests/test-cases/exclude-missing-module/run.t @@ -1,3 +1,3 @@ - $ jbuilder build --display short + $ dune build --display short File "jbuild", line 3, characters 24-28: Warning: Module Fake is excluded but it doesn't exist. diff --git a/test/blackbox-tests/test-cases/exec-cmd/run.t b/test/blackbox-tests/test-cases/exec-cmd/run.t index 04381a7c018..230a7552652 100644 --- a/test/blackbox-tests/test-cases/exec-cmd/run.t +++ b/test/blackbox-tests/test-cases/exec-cmd/run.t @@ -1,22 +1,22 @@ - $ jbuilder clean --display short - $ jbuilder exec --no-build ./foo.exe --display short + $ dune clean --display short + $ dune exec --no-build ./foo.exe --display short Error: Program "./foo.exe" isn't built yet you need to buid it first or remove the --no-build option. [1] - $ jbuilder exec ./foo.exe --display short + $ dune exec ./foo.exe --display short ocamldep foo.ml.d ocamlc .foo.eobjs/foo.{cmi,cmo,cmt} ocamlopt .foo.eobjs/foo.{cmx,o} ocamlopt foo.exe Foo - $ jbuilder exec --dev ./foo.exe --display short + $ dune exec --dev ./foo.exe --display short ocamlc .foo.eobjs/foo.{cmi,cmo,cmt} ocamlopt .foo.eobjs/foo.{cmx,o} ocamlopt foo.exe Foo - $ jbuilder exec dunetestbar --no-build --display short + $ dune exec dunetestbar --no-build --display short Error: Program "dunetestbar" isn't built yet you need to buid it first or remove the --no-build option. [1] - $ jbuilder exec dunetestbar --display short + $ dune exec dunetestbar --display short ocamldep bar.ml.d ocamlc .bar.eobjs/bar.{cmi,cmo,cmt} ocamlopt .bar.eobjs/bar.{cmx,o} diff --git a/test/blackbox-tests/test-cases/findlib/run.t b/test/blackbox-tests/test-cases/findlib/run.t index 2fb9e848cad..8d6adaec77d 100644 --- a/test/blackbox-tests/test-cases/findlib/run.t +++ b/test/blackbox-tests/test-cases/findlib/run.t @@ -1,4 +1,4 @@ - $ jbuilder external-lib-deps @install + $ dune external-lib-deps @install These are the external library dependencies in the default context: - a - b @@ -6,7 +6,7 @@ Reproduction case for #484. The error should point to src/jbuild - $ jbuilder build @install + $ dune build @install File "src/jbuild", line 4, characters 16-17: Error: Library "a" not found. Hint: try: dune external-lib-deps --missing @install diff --git a/test/blackbox-tests/test-cases/force-test/run.t b/test/blackbox-tests/test-cases/force-test/run.t index 2da42648115..23530751bb0 100644 --- a/test/blackbox-tests/test-cases/force-test/run.t +++ b/test/blackbox-tests/test-cases/force-test/run.t @@ -1,12 +1,12 @@ - $ jbuilder clean --display short - $ jbuilder runtest --display short + $ dune clean --display short + $ dune runtest --display short ocamldep f.ml.d ocamlc .f.eobjs/f.{cmi,cmo,cmt} ocamlopt .f.eobjs/f.{cmx,o} ocamlopt f.exe f alias runtest Foo Bar - $ jbuilder runtest --display short - $ jbuilder runtest --force --display short + $ dune runtest --display short + $ dune runtest --force --display short f alias runtest Foo Bar diff --git a/test/blackbox-tests/test-cases/gen-opam-install-file/run.t b/test/blackbox-tests/test-cases/gen-opam-install-file/run.t index d2b1e354a2b..990fb4ad249 100644 --- a/test/blackbox-tests/test-cases/gen-opam-install-file/run.t +++ b/test/blackbox-tests/test-cases/gen-opam-install-file/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest --display short + $ dune runtest --display short ocamldep bar.ml.d ocamldep foo.ml.d ocamldep foo.mli.d diff --git a/test/blackbox-tests/test-cases/github20/run.t b/test/blackbox-tests/test-cases/github20/run.t index a409cea8823..bee70b53c36 100644 --- a/test/blackbox-tests/test-cases/github20/run.t +++ b/test/blackbox-tests/test-cases/github20/run.t @@ -1 +1 @@ - $ jbuilder build .merlin --display short + $ dune build .merlin --display short diff --git a/test/blackbox-tests/test-cases/github24/run.t b/test/blackbox-tests/test-cases/github24/run.t index 766b11ee60c..3ddf0a6fc21 100644 --- a/test/blackbox-tests/test-cases/github24/run.t +++ b/test/blackbox-tests/test-cases/github24/run.t @@ -1 +1 @@ - $ jbuilder build @install --display short --debug-dependency-path + $ dune build @install --display short --debug-dependency-path diff --git a/test/blackbox-tests/test-cases/github25/run.t b/test/blackbox-tests/test-cases/github25/run.t index cc275cdf522..1da192cc177 100644 --- a/test/blackbox-tests/test-cases/github25/run.t +++ b/test/blackbox-tests/test-cases/github25/run.t @@ -6,14 +6,14 @@ problem. So jbuilder shouldn't crash because of "plop.ca-marche-pas" We need ocamlfind to run this test - $ jbuilder build @install --display short --only hello + $ dune build @install --display short --only hello ocamlc root/.hello.objs/hello.{cmi,cmo,cmt} ocamlopt root/.hello.objs/hello.{cmx,o} ocamlopt root/hello.{a,cmxa} ocamlopt root/hello.cmxs ocamlc root/hello.cma - $ jbuilder build @install --display short --only pas-de-bol 2>&1 | sed 's/[^ "]*findlib-packages/.../' + $ dune build @install --display short --only pas-de-bol 2>&1 | sed 's/[^ "]*findlib-packages/.../' ocamldep root/a.ml.d File ".../plop/META", line 1, characters 0-0: Error: Library "une-lib-qui-nexiste-pas" not found. diff --git a/test/blackbox-tests/test-cases/github534/run.t b/test/blackbox-tests/test-cases/github534/run.t index 6e65f624dbb..4de9911bbf5 100644 --- a/test/blackbox-tests/test-cases/github534/run.t +++ b/test/blackbox-tests/test-cases/github534/run.t @@ -1,4 +1,4 @@ - $ jbuilder exec ./main.exe --display short + $ dune exec ./main.exe --display short echo main.ml ocamldep main.ml.d ocamlc .main.eobjs/main.{cmi,cmo,cmt} diff --git a/test/blackbox-tests/test-cases/github568/run.t b/test/blackbox-tests/test-cases/github568/run.t index dae6e266f9f..6fc6e849020 100644 --- a/test/blackbox-tests/test-cases/github568/run.t +++ b/test/blackbox-tests/test-cases/github568/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest --display short -p lib1 --debug-dependency-path + $ dune runtest --display short -p lib1 --debug-dependency-path ocamldep test1.ml.d ocamldep lib1.ml.d ocamlc .lib1.objs/lib1.{cmi,cmo,cmt} diff --git a/test/blackbox-tests/test-cases/github597/run.t b/test/blackbox-tests/test-cases/github597/run.t index b9f40b7a65a..786edd87e11 100644 --- a/test/blackbox-tests/test-cases/github597/run.t +++ b/test/blackbox-tests/test-cases/github597/run.t @@ -1 +1 @@ - $ jbuilder build b/b.cma + $ dune build b/b.cma diff --git a/test/blackbox-tests/test-cases/github644/run.t b/test/blackbox-tests/test-cases/github644/run.t index c7172c24952..ac881f2d567 100644 --- a/test/blackbox-tests/test-cases/github644/run.t +++ b/test/blackbox-tests/test-cases/github644/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest + $ dune runtest File "jbuild", line 4, characters 20-42: Error: Library "ppx_that_doesn't_exist" not found. Hint: try: dune external-lib-deps --missing @runtest @@ -6,12 +6,12 @@ These should print something: - $ jbuilder external-lib-deps --display quiet @runtest + $ dune external-lib-deps --display quiet @runtest These are the external library dependencies in the default context: - ocaml-migrate-parsetree.driver-main - ppx_that_doesn't_exist - $ jbuilder external-lib-deps --display quiet --missing @runtest + $ dune external-lib-deps --display quiet --missing @runtest Error: The following libraries are missing in the default context: - ppx_that_doesn't_exist Hint: try: opam install ppx_that_doesn't_exist diff --git a/test/blackbox-tests/test-cases/github660/run.t b/test/blackbox-tests/test-cases/github660/run.t index 2b37f52ef7f..8e5b0f64851 100644 --- a/test/blackbox-tests/test-cases/github660/run.t +++ b/test/blackbox-tests/test-cases/github660/run.t @@ -1,20 +1,20 @@ When there are explicit interfaces, modules must be rebuilt. - $ jbuilder runtest --root explicit-interfaces --display quiet -j1 2>&1 | grep -v Entering + $ dune runtest --root explicit-interfaces --display quiet -j1 2>&1 | grep -v Entering main alias runtest hello $ echo 'let x = 1' >> explicit-interfaces/lib_sub.ml - $ jbuilder runtest --root explicit-interfaces --display quiet -j1 2>&1 | grep -v Entering | grep -v ocamlopt + $ dune runtest --root explicit-interfaces --display quiet -j1 2>&1 | grep -v Entering | grep -v ocamlopt main alias runtest hello When there are no interfaces, the situation is the same, but it is not possible to rely on these. - $ jbuilder runtest --root no-interfaces --display quiet -j1 2>&1 | grep -v Entering + $ dune runtest --root no-interfaces --display quiet -j1 2>&1 | grep -v Entering main alias runtest hello $ echo 'let x = 1' >> no-interfaces/lib_sub.ml - $ jbuilder runtest --root no-interfaces --display quiet -j1 2>&1 | grep -v Entering | grep -v ocamlopt + $ dune runtest --root no-interfaces --display quiet -j1 2>&1 | grep -v Entering | grep -v ocamlopt main alias runtest hello diff --git a/test/blackbox-tests/test-cases/github717-odoc-index/run.t b/test/blackbox-tests/test-cases/github717-odoc-index/run.t index bc867e11647..0ad4da8bfb5 100644 --- a/test/blackbox-tests/test-cases/github717-odoc-index/run.t +++ b/test/blackbox-tests/test-cases/github717-odoc-index/run.t @@ -1 +1 @@ - $ jbuilder build @doc + $ dune build @doc diff --git a/test/blackbox-tests/test-cases/include-loop/run.t b/test/blackbox-tests/test-cases/include-loop/run.t index b8e089d5f64..28650d8484b 100644 --- a/test/blackbox-tests/test-cases/include-loop/run.t +++ b/test/blackbox-tests/test-cases/include-loop/run.t @@ -1,4 +1,4 @@ - $ jbuilder build --display short + $ dune build --display short File "jbuild", line 2, characters 0-15: Error: Recursive inclusion of jbuild files detected: File a.inc is included from c.inc:2 diff --git a/test/blackbox-tests/test-cases/inline_tests/run.t b/test/blackbox-tests/test-cases/inline_tests/run.t index 6b43987f7f9..4e2e7e450ba 100644 --- a/test/blackbox-tests/test-cases/inline_tests/run.t +++ b/test/blackbox-tests/test-cases/inline_tests/run.t @@ -4,23 +4,23 @@ Fatal error: exception File "simple/.foo_simple.inline-tests/run.ml", line 1, characters 10-16: Assertion failed [1] - $ jbuilder runtest missing-backend + $ dune runtest missing-backend File "missing-backend/jbuild", line 3, characters 2-16: Error: No inline tests backend found. [1] - $ jbuilder runtest too-many-backends + $ dune runtest too-many-backends File "too-many-backends/jbuild", line 17, characters 2-16: Error: Too many independant inline tests backends found: - "backend_tmb1" in _build/default/too-many-backends - "backend_tmb2" in _build/default/too-many-backends [1] - $ jbuilder runtest many-backends-choose + $ dune runtest many-backends-choose run alias many-backends-choose/runtest backend_mbc1 - $ jbuilder runtest dune-file + $ dune runtest dune-file (dune 1 ((inline_tests.backend diff --git a/test/blackbox-tests/test-cases/installable-dup-private-libs/run.t b/test/blackbox-tests/test-cases/installable-dup-private-libs/run.t index 623b3e481be..1f836ebbfb7 100644 --- a/test/blackbox-tests/test-cases/installable-dup-private-libs/run.t +++ b/test/blackbox-tests/test-cases/installable-dup-private-libs/run.t @@ -1,4 +1,4 @@ - $ jbuilder build @install --display short + $ dune build @install --display short ocamldep a1/a.ml.d ocamlc a1/.a.objs/a.{cmi,cmo,cmt} ocamlopt a1/.a.objs/a.{cmx,o} diff --git a/test/blackbox-tests/test-cases/intf-only/run.t b/test/blackbox-tests/test-cases/intf-only/run.t index b52067c2518..3d3a3c1f3a6 100644 --- a/test/blackbox-tests/test-cases/intf-only/run.t +++ b/test/blackbox-tests/test-cases/intf-only/run.t @@ -1,6 +1,6 @@ Successes: - $ jbuilder build --display short --root foo --debug-dep 2>&1 | grep -v Entering + $ dune build --display short --root foo --debug-dep 2>&1 | grep -v Entering ocamldep test/bar.ml.d ocamldep foo.ml.d ocamlc .foo.objs/foo__.{cmi,cmo,cmt} @@ -20,7 +20,7 @@ Successes: Errors: - $ jbuilder build --display short --root a foo.cma 2>&1 | grep -v Entering + $ dune build --display short --root a foo.cma 2>&1 | grep -v Entering File "jbuild", line 2, characters 1-13: Warning: Some modules don't have an implementation. You need to add the following field to this stanza: @@ -30,16 +30,16 @@ Errors: This will become an error in the future. ocamlc .foo.objs/foo.{cmi,cmo,cmt} ocamlc foo.cma - $ jbuilder build --display short --root b foo.cma 2>&1 | grep -v Entering + $ dune build --display short --root b foo.cma 2>&1 | grep -v Entering File "jbuild", line 3, characters 34-37: Warning: The following modules must be listed here as they don't have an implementation: - y This will become an error in the future. ocamlc .foo.objs/foo.{cmi,cmo,cmt} ocamlc foo.cma - $ jbuilder build --display short --root c foo.cma 2>&1 | grep -v Entering + $ dune build --display short --root c foo.cma 2>&1 | grep -v Entering File "jbuild", line 3, characters 35-36: Error: Module X doesn't exist. - $ jbuilder build --display short --root d foo.cma 2>&1 | grep -v Entering + $ dune build --display short --root d foo.cma 2>&1 | grep -v Entering File "jbuild", line 3, characters 35-36: Error: Module X has an implementation, it cannot be listed here diff --git a/test/blackbox-tests/test-cases/js_of_ocaml/run.t b/test/blackbox-tests/test-cases/js_of_ocaml/run.t index d0c442f88a4..56caadd96e6 100644 --- a/test/blackbox-tests/test-cases/js_of_ocaml/run.t +++ b/test/blackbox-tests/test-cases/js_of_ocaml/run.t @@ -1,4 +1,4 @@ - $ jbuilder build --display short --dev bin/technologic.bc.js @install lib/x.cma.js lib/x__Y.cmo.js bin/z.cmo.js + $ dune build --display short --dev bin/technologic.bc.js @install lib/x.cma.js lib/x__Y.cmo.js bin/z.cmo.js ocamlc lib/stubs$ext_obj ocamlmklib lib/dllx_stubs$ext_dll,lib/libx_stubs$ext_lib ocamlopt .ppx/js_of_ocaml-ppx/ppx.exe @@ -34,7 +34,7 @@ use it break it fix it - $ jbuilder build --display short bin/technologic.bc.js @install + $ dune build --display short bin/technologic.bc.js @install ocamlc lib/.x.objs/x__.{cmi,cmo,cmt} ocamlc lib/.x.objs/x__Y.{cmi,cmo,cmt} ocamlc lib/.x.objs/x.{cmi,cmo,cmt} diff --git a/test/blackbox-tests/test-cases/lib-available/run.t b/test/blackbox-tests/test-cases/lib-available/run.t index a38b9fad41b..b8e91df63f5 100644 --- a/test/blackbox-tests/test-cases/lib-available/run.t +++ b/test/blackbox-tests/test-cases/lib-available/run.t @@ -1,3 +1,3 @@ - $ jbuilder build @runtest --display short --debug-dependency-path 2>&1 | sed "s/ cmd / sh /" + $ dune build @runtest --display short --debug-dependency-path 2>&1 | sed "s/ cmd / sh /" sh alias runtest sh alias runtest diff --git a/test/blackbox-tests/test-cases/loop/run.t b/test/blackbox-tests/test-cases/loop/run.t index 0d568fe781a..5569a88e70a 100644 --- a/test/blackbox-tests/test-cases/loop/run.t +++ b/test/blackbox-tests/test-cases/loop/run.t @@ -1,4 +1,4 @@ - $ jbuilder build --display short a + $ dune build --display short a true x true y Dependency cycle between the following files: @@ -11,14 +11,14 @@ This second example is slightly more complicated as we request result1 but the cycle doesn't involve result1. We must make sure the output does show a cycle. - $ jbuilder build --display short result1 + $ dune build --display short result1 Dependency cycle between the following files: _build/default/result2 --> _build/default/input --> _build/default/result2 [1] - $ jbuilder build --display short result1 --debug-dependency-path + $ dune build --display short result1 --debug-dependency-path Dependency cycle between the following files: _build/default/result2 --> _build/default/input diff --git a/test/blackbox-tests/test-cases/menhir/run.t b/test/blackbox-tests/test-cases/menhir/run.t index 8dc89d999d1..83912cf3172 100644 --- a/test/blackbox-tests/test-cases/menhir/run.t +++ b/test/blackbox-tests/test-cases/menhir/run.t @@ -1,4 +1,4 @@ - $ jbuilder build src/test.exe --display short --debug-dependency-path + $ dune build src/test.exe --display short --debug-dependency-path ocamllex src/lexer1.ml ocamldep src/lexer1.ml.d ocamllex src/lexer2.ml diff --git a/test/blackbox-tests/test-cases/merlin-tests/run.t b/test/blackbox-tests/test-cases/merlin-tests/run.t index ac15339788c..a65734540aa 100644 --- a/test/blackbox-tests/test-cases/merlin-tests/run.t +++ b/test/blackbox-tests/test-cases/merlin-tests/run.t @@ -1,4 +1,4 @@ - $ jbuilder build @print-merlins --display short + $ dune build @print-merlins --display short ocamldep sanitize-dot-merlin/sanitize_dot_merlin.ml.d ocamlc sanitize-dot-merlin/.sanitize_dot_merlin.eobjs/sanitize_dot_merlin.{cmi,cmo,cmt} ocamlopt sanitize-dot-merlin/.sanitize_dot_merlin.eobjs/sanitize_dot_merlin.{cmx,o} diff --git a/test/blackbox-tests/test-cases/meta-gen/run.t b/test/blackbox-tests/test-cases/meta-gen/run.t index a423c5ca30f..ba2558481be 100644 --- a/test/blackbox-tests/test-cases/meta-gen/run.t +++ b/test/blackbox-tests/test-cases/meta-gen/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest --force --display short + $ dune runtest --force --display short description = "contains \"quotes\"" requires = "bytes" archive(byte) = "foobar.cma" diff --git a/test/blackbox-tests/test-cases/misc/run.t b/test/blackbox-tests/test-cases/misc/run.t index cd9d83f3d40..0dcbe42ec64 100644 --- a/test/blackbox-tests/test-cases/misc/run.t +++ b/test/blackbox-tests/test-cases/misc/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest --display short + $ dune runtest --display short File "jbuild", line 65, characters 21-44: Warning: Directory dir-that-doesnt-exist doesn't exist. diff alias runtest diff --git a/test/blackbox-tests/test-cases/multiple-private-libs/run.t b/test/blackbox-tests/test-cases/multiple-private-libs/run.t index 3ecc4bf4c41..d4ca816648a 100644 --- a/test/blackbox-tests/test-cases/multiple-private-libs/run.t +++ b/test/blackbox-tests/test-cases/multiple-private-libs/run.t @@ -1,6 +1,6 @@ This test checks that there is no clash when two private libraries have the same name - $ jbuilder build --display short @doc-private + $ dune build --display short @doc-private ocamldep a/test.ml.d ocamlc a/.test.objs/test.{cmi,cmo,cmt} odoc _doc/_odoc/lib/test@a/test.odoc diff --git a/test/blackbox-tests/test-cases/null-dep/run.t b/test/blackbox-tests/test-cases/null-dep/run.t index c3b3574c608..41f62eea89b 100644 --- a/test/blackbox-tests/test-cases/null-dep/run.t +++ b/test/blackbox-tests/test-cases/null-dep/run.t @@ -1 +1 @@ - $ jbuilder runtest --debug-dependency-path + $ dune runtest --debug-dependency-path diff --git a/test/blackbox-tests/test-cases/ocaml-syntax/run.t b/test/blackbox-tests/test-cases/ocaml-syntax/run.t index b9c7f7e5b71..15f1ec1cea4 100644 --- a/test/blackbox-tests/test-cases/ocaml-syntax/run.t +++ b/test/blackbox-tests/test-cases/ocaml-syntax/run.t @@ -1,2 +1,2 @@ - $ jbuilder runtest --force --display short + $ dune runtest --force --display short ocaml syntax diff --git a/test/blackbox-tests/test-cases/ocamldep-multi-stanzas/run.t b/test/blackbox-tests/test-cases/ocamldep-multi-stanzas/run.t index bd4bdc97ea0..0bd5be8a6af 100644 --- a/test/blackbox-tests/test-cases/ocamldep-multi-stanzas/run.t +++ b/test/blackbox-tests/test-cases/ocamldep-multi-stanzas/run.t @@ -1,4 +1,4 @@ - $ jbuilder exec ./test.exe --debug-dep --display short + $ dune exec ./test.exe --debug-dep --display short File "jbuild", line 1, characters 0-0: Warning: Module "Lib" is used in several stanzas: - jbuild:8 @@ -13,7 +13,7 @@ - [1] - $ jbuilder build src/a.cma --debug-dep --display short + $ dune build src/a.cma --debug-dep --display short File "src/jbuild", line 1, characters 0-0: Warning: Module "X" is used in several stanzas: - src/jbuild:4 diff --git a/test/blackbox-tests/test-cases/odoc-unique-mlds/run.t b/test/blackbox-tests/test-cases/odoc-unique-mlds/run.t index b677338b14f..65ff14bc492 100644 --- a/test/blackbox-tests/test-cases/odoc-unique-mlds/run.t +++ b/test/blackbox-tests/test-cases/odoc-unique-mlds/run.t @@ -1,5 +1,5 @@ Duplicate mld's in the same scope - $ jbuilder build @doc --display short --root ./same-scope 2>&1 | grep -v Entering + $ dune build @doc --display short --root ./same-scope 2>&1 | grep -v Entering odoc _doc/_html/odoc.css ocamlc lib1/.root_lib1.objs/root_lib1.{cmi,cmo,cmt} odoc _doc/_odoc/lib/root.lib1/root_lib1.odoc @@ -12,7 +12,7 @@ Duplicate mld's in the same scope Duplicate mld's in different scope $ rm -rf diff-scope/_build - $ jbuilder build @doc --display short --root ./diff-scope 2>&1 | grep -v Entering + $ dune build @doc --display short --root ./diff-scope 2>&1 | grep -v Entering odoc _doc/_html/odoc.css ocamlc scope1/.scope1.objs/scope1.{cmi,cmo,cmt} odoc _doc/_odoc/lib/scope1/scope1.odoc diff --git a/test/blackbox-tests/test-cases/odoc/run.t b/test/blackbox-tests/test-cases/odoc/run.t index 5d4d79cfcda..32a544307d0 100644 --- a/test/blackbox-tests/test-cases/odoc/run.t +++ b/test/blackbox-tests/test-cases/odoc/run.t @@ -1,4 +1,4 @@ - $ jbuilder build @doc --display short + $ dune build @doc --display short ocamldep bar.ml.d ocamlc .bar.objs/bar.{cmi,cmo,cmt} odoc _doc/_odoc/lib/bar/bar.odoc @@ -20,7 +20,7 @@ odoc _doc/_html/foo/index.html odoc _doc/_html/foo/Foo_byte/.jbuilder-keep,_doc/_html/foo/Foo_byte/index.html odoc _doc/_html/foo/Foo2/.jbuilder-keep,_doc/_html/foo/Foo2/index.html - $ jbuilder runtest --display short + $ dune runtest --display short @@ -40,7 +40,7 @@ - $ jbuilder build @foo-mld --display short + $ dune build @foo-mld --display short {1 Library foo} This library exposes the following toplevel modules: {!modules:Foo Foo2}. @@ -48,7 +48,7 @@ The entry point of this library is the module: {!module-Foo_byte}. - $ jbuilder build @bar-mld --display short + $ dune build @bar-mld --display short {1 Library bar} The entry point of this library is the module: {!module-Bar}. diff --git a/test/blackbox-tests/test-cases/output-obj/run.t b/test/blackbox-tests/test-cases/output-obj/run.t index b93484d7e26..6a1dc8337d2 100644 --- a/test/blackbox-tests/test-cases/output-obj/run.t +++ b/test/blackbox-tests/test-cases/output-obj/run.t @@ -1,4 +1,4 @@ - $ jbuilder build --display short @all + $ dune build --display short @all ocamldep test.ml.d ocamlc .test.eobjs/test.{cmi,cmo,cmt} ocamlc test.bc.o @@ -11,7 +11,7 @@ ocamlopt test.exe ocamlopt test$ext_dll - $ jbuilder build @runtest + $ dune build @runtest static alias runtest OK: ./static.bc dynamic alias runtest diff --git a/test/blackbox-tests/test-cases/package-dep/run.t b/test/blackbox-tests/test-cases/package-dep/run.t index c7462fa2861..10e5e34be6b 100644 --- a/test/blackbox-tests/test-cases/package-dep/run.t +++ b/test/blackbox-tests/test-cases/package-dep/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest --display short + $ dune runtest --display short ocamldep bar.ml.d ocamldep foo.ml.d ocamlc .foo.objs/foo.{cmi,cmo,cmt} diff --git a/test/blackbox-tests/test-cases/ppx-rewriter/run.t b/test/blackbox-tests/test-cases/ppx-rewriter/run.t index 465a6879d1c..f5fbe1cea8f 100644 --- a/test/blackbox-tests/test-cases/ppx-rewriter/run.t +++ b/test/blackbox-tests/test-cases/ppx-rewriter/run.t @@ -1,4 +1,4 @@ - $ jbuilder build ./w_omp_driver.exe --display short + $ dune build ./w_omp_driver.exe --display short ocamldep ppx/fooppx.ml.d ocamlc ppx/.fooppx.objs/fooppx.{cmi,cmo,cmt} ocamlopt ppx/.fooppx.objs/fooppx.{cmx,o} @@ -9,7 +9,7 @@ ocamlc .w_omp_driver.eobjs/w_omp_driver.{cmi,cmo,cmt} ocamlopt .w_omp_driver.eobjs/w_omp_driver.{cmx,o} ocamlopt w_omp_driver.exe - $ jbuilder build ./w_ppx_driver.exe --display short + $ dune build ./w_ppx_driver.exe --display short ocamlopt .ppx/ppx_driver.runner/ppx.exe ppx w_ppx_driver.pp.ml ocamldep w_ppx_driver.pp.ml.d @@ -17,4 +17,4 @@ ocamlopt .w_ppx_driver.eobjs/w_ppx_driver.{cmx,o} ocamlopt w_ppx_driver.exe This test is broken because ppx_driver doesn't support migrate custom arguments -# $ jbuilder build ./w_ppx_driver_flags.exe --display short +# $ dune build ./w_ppx_driver_flags.exe --display short diff --git a/test/blackbox-tests/test-cases/private-public-overlap/run.t b/test/blackbox-tests/test-cases/private-public-overlap/run.t index 5c74df5db44..c3aa05d40d1 100644 --- a/test/blackbox-tests/test-cases/private-public-overlap/run.t +++ b/test/blackbox-tests/test-cases/private-public-overlap/run.t @@ -1,13 +1,13 @@ public libraries may not have private dependencies - $ jbuilder build --display short --root private-dep 2>&1 | grep -v Entering + $ dune build --display short --root private-dep 2>&1 | grep -v Entering File "jbuild", line 10, characters 14-24: Error: Library "privatelib" is private, it cannot be a dependency of a public library. You need to give "privatelib" a public name. ocamldep publiclib.ml.d On the other hand, public libraries may have private preprocessors - $ jbuilder build --display short --root private-rewriter 2>&1 | grep -v Entering + $ dune build --display short --root private-rewriter 2>&1 | grep -v Entering ocamlc .ppx_internal.objs/ppx_internal.{cmi,cmo,cmt} ocamlopt .ppx_internal.objs/ppx_internal.{cmx,o} ocamlopt ppx_internal.{a,cmxa} @@ -21,7 +21,7 @@ On the other hand, public libraries may have private preprocessors ocamlc mylib.cma Unless they introduce private runtime dependencies: - $ jbuilder build --display short --root private-runtime-deps 2>&1 | grep -v Entering + $ dune build --display short --root private-runtime-deps 2>&1 | grep -v Entering File "jbuild", line 16, characters 20-31: Error: Library "private_runtime_dep" is private, it cannot be a dependency of a public library. You need to give "private_runtime_dep" a public name. @@ -33,12 +33,12 @@ Unless they introduce private runtime dependencies: ocamldep mylib.pp.ml.d However, public binaries may accept private dependencies - $ jbuilder build --display short --root exes 2>&1 | grep -v Entering + $ dune build --display short --root exes 2>&1 | grep -v Entering ocamldep publicbin.ml.d ocamlc .publicbin.eobjs/publicbin.{cmi,cmo,cmt} ocamlopt .publicbin.eobjs/publicbin.{cmx,o} ocamlopt publicbin.exe Private dependencies shouldn't make the library optional - $ jbuilder build --display short --root optional 2>&1 | grep -v Entering + $ dune build --display short --root optional 2>&1 | grep -v Entering [1] diff --git a/test/blackbox-tests/test-cases/promote/run.t b/test/blackbox-tests/test-cases/promote/run.t index abf6c6b08e1..3564d891427 100644 --- a/test/blackbox-tests/test-cases/promote/run.t +++ b/test/blackbox-tests/test-cases/promote/run.t @@ -1,30 +1,30 @@ $ printf titi > x - $ jbuilder build --display short --diff-command false @blah 2>&1 | sed 's/.*false.*/DIFF/' + $ dune build --display short --diff-command false @blah 2>&1 | sed 's/.*false.*/DIFF/' sh (internal) (exit 1) DIFF $ cat x titi - $ jbuilder promote --display short + $ dune promote --display short Promoting _build/default/x.gen to x. $ cat x toto - $ jbuilder build --display short --diff-command false @blah + $ dune build --display short --diff-command false @blah $ cat x toto Otherwise this test fails on OSX - $ jbuilder clean --display short + $ dune clean --display short $ printf titi > x - $ jbuilder build --display short --diff-command false @blah --auto-promote 2>&1 | sed 's/.*false.*/DIFF/' + $ dune build --display short --diff-command false @blah --auto-promote 2>&1 | sed 's/.*false.*/DIFF/' sh (internal) (exit 1) DIFF Promoting _build/default/x.gen to x. $ cat x toto - $ jbuilder build --display short --diff-command false @blah + $ dune build --display short --diff-command false @blah $ cat x toto diff --git a/test/blackbox-tests/test-cases/quoting/run.t b/test/blackbox-tests/test-cases/quoting/run.t index ade020b2844..4116104902f 100644 --- a/test/blackbox-tests/test-cases/quoting/run.t +++ b/test/blackbox-tests/test-cases/quoting/run.t @@ -1,7 +1,7 @@ This behavior is surprising, we should get an error about the fact that ${@} is not quoted and doesn't contain exactly 1 element - $ jbuilder build x + $ dune build x Error: Rule failed to generate the following targets: - x - y diff --git a/test/blackbox-tests/test-cases/reason/run.t b/test/blackbox-tests/test-cases/reason/run.t index 7f8815f3366..29a914478b7 100644 --- a/test/blackbox-tests/test-cases/reason/run.t +++ b/test/blackbox-tests/test-cases/reason/run.t @@ -1,4 +1,4 @@ - $ jbuilder build @runtest @install-file --display short + $ dune build @runtest @install-file --display short refmt bar.re.ml ocamldep pp/reasononlypp.depends.ocamldep-output ocamldep ppx/reasonppx.depends.ocamldep-output diff --git a/test/blackbox-tests/test-cases/redirections/run.t b/test/blackbox-tests/test-cases/redirections/run.t index 8e655100ab0..8df19d09eed 100644 --- a/test/blackbox-tests/test-cases/redirections/run.t +++ b/test/blackbox-tests/test-cases/redirections/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest --display short 2>&1 | sed "s/ cmd / sh /" + $ dune runtest --display short 2>&1 | sed "s/ cmd / sh /" sh stderr,stdout sh stderr,stdout diff alias runtest diff --git a/test/blackbox-tests/test-cases/scope-bug/run.t b/test/blackbox-tests/test-cases/scope-bug/run.t index 29aab26dd2b..cff4674d169 100644 --- a/test/blackbox-tests/test-cases/scope-bug/run.t +++ b/test/blackbox-tests/test-cases/scope-bug/run.t @@ -1,4 +1,4 @@ - $ jbuilder build --display short @install + $ dune build --display short @install ocamldep alib/alib.ml.d ocamldep alib/main.ml.d ocamldep blib/blib.ml.d diff --git a/test/blackbox-tests/test-cases/scope-ppx-bug/run.t b/test/blackbox-tests/test-cases/scope-ppx-bug/run.t index ef83f91c59b..7920c5d42aa 100644 --- a/test/blackbox-tests/test-cases/scope-ppx-bug/run.t +++ b/test/blackbox-tests/test-cases/scope-ppx-bug/run.t @@ -1,4 +1,4 @@ - $ jbuilder build --display short @install --debug-dep + $ dune build --display short @install --debug-dep ocamlc a/ppx/.a.objs/a.{cmi,cmo,cmt} ocamlopt a/ppx/.a.objs/a.{cmx,o} ocamlopt a/ppx/a.{a,cmxa} diff --git a/test/blackbox-tests/test-cases/select/run.t b/test/blackbox-tests/test-cases/select/run.t index 379b874b7cc..3d03d99b241 100644 --- a/test/blackbox-tests/test-cases/select/run.t +++ b/test/blackbox-tests/test-cases/select/run.t @@ -1,4 +1,4 @@ - $ jbuilder runtest --display short + $ dune runtest --display short ocamldep bar.ml.d ocamldep bar_no_unix.ml.d ocamldep bar_unix.ml.d diff --git a/test/blackbox-tests/test-cases/utop/run.t b/test/blackbox-tests/test-cases/utop/run.t index e859918b44f..118c19b5439 100644 --- a/test/blackbox-tests/test-cases/utop/run.t +++ b/test/blackbox-tests/test-cases/utop/run.t @@ -1,4 +1,4 @@ - $ jbuilder utop --display short forutop -- init_forutop.ml + $ dune utop --display short forutop -- init_forutop.ml ocamldep forutop/.utop/utop.ml.d ocamldep forutop/forutop.ml.d ocamlc forutop/.forutop.objs/forutop.{cmi,cmo,cmt}