diff --git a/CHANGES.md b/CHANGES.md index 21df2d87..f418619e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -95,6 +95,13 @@ next - Version `dune-workspace` and `~/.config/dune/config` files (#..., @diml) +- Add the ability to build an alias non-recursively from the command + line by writing `@@alias` (#926, @diml) + +- Add a special `default` alias that defaults to `(alias_rec install)` + when not defined by the user and make `@@default` be the default + target (#926, @diml) + 1.0+beta20 (10/04/2018) ----------------------- diff --git a/bin/main.ml b/bin/main.ml index 6679518c..be333e73 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -26,6 +26,7 @@ type common = ; (* Original arguments for the external-lib-deps hint *) orig_args : string list ; config : Config.t + ; default_target : string } let prefix_target common s = common.target_prefix ^ s @@ -234,6 +235,7 @@ let common = ignore_promoted_rules, config_file, profile, + default_target, orig) x display @@ -296,6 +298,7 @@ let common = ; x ; config ; build_dir + ; default_target } in let docs = copts_sect in @@ -484,6 +487,20 @@ let common = in Term.(ret (const merge $ config_file $ no_config)) in + let default_target_default = + match Which_program.t with + | Dune -> "@@default" + | Jbuilder -> "@install" + in + let default_target = + Arg.(value + & opt (some string) None + & info ["default-target"] ~docs ~docv:"TARGET" + ~doc:(sprintf + {|Set the default target that when none is specified to + $(b,dune build). It defaults to %s.|} + default_target_default)) + in let for_release = "for-release-of-packages" in let frop = Arg.(value @@ -496,33 +513,37 @@ let common = packages as well as getting reproducible builds.|}) in let merge root only_packages ignore_promoted_rules - (config_file_opt, config_file) profile release = + (config_file_opt, config_file) profile default_target release = let fail opt = incompatible ("-p/--" ^ for_release) opt in match release, root, only_packages, ignore_promoted_rules, - profile, config_file_opt with - | Some _, Some _, _, _, _, _ -> fail "--root" - | Some _, _, Some _, _, _, _ -> fail "--only-packages" - | Some _, _, _, true , _, _ -> fail "--ignore-promoted-rules" - | Some _, _, _, _, Some _, _ -> fail "--profile" - | Some _, _, _, _, _, Some s -> fail s - | Some pkgs, None, None, false, None, None -> + profile, default_target, config_file_opt with + | Some _, Some _, _, _, _, _, _ -> fail "--root" + | Some _, _, Some _, _, _, _, _ -> fail "--only-packages" + | Some _, _, _, true , _, _, _ -> fail "--ignore-promoted-rules" + | Some _, _, _, _, Some _, _, _ -> fail "--profile" + | Some _, _, _, _, _, Some s, _ -> fail s + | Some _, _, _, _, _, _, Some _ -> fail "--default-target" + | Some pkgs, None, None, false, None, None, None -> `Ok (Some ".", Some pkgs, true, No_config, Some "release", + "@install", ["-p"; pkgs] ) - | None, _, _, _, _, _ -> + | None, _, _, _, _, _, _ -> `Ok (root, only_packages, ignore_promoted_rules, config_file, profile, + Option.value default_target ~default:default_target_default, List.concat [ dump_opt "--root" root ; dump_opt "--only-packages" only_packages ; dump_opt "--profile" profile + ; dump_opt "--default-target" default_target ; if ignore_promoted_rules then ["--ignore-promoted-rules"] else @@ -540,6 +561,7 @@ let common = $ ignore_promoted_rules $ config_file $ profile + $ default_target $ frop)) in let x = @@ -771,9 +793,14 @@ let build_targets = (Main.setup ~log common >>= fun setup -> let targets = resolve_targets_exn ~log common setup targets in do_build setup targets) in + let default_target = + match Which_program.t with + | Dune -> "@@default" + | Jbuilder -> "@install" + in ( Term.(const go $ common - $ Arg.(value & pos_all string ["@install"] name_)) + $ Arg.(value & pos_all string [default_target] name_)) , Term.info "build" ~doc ~man) let runtest = diff --git a/doc/jbuild.rst b/doc/jbuild.rst index 892ea76c..3e8b4065 100644 --- a/doc/jbuild.rst +++ b/doc/jbuild.rst @@ -531,6 +531,8 @@ menhir A ``menhir`` stanza is available to support the menhir_ parser generator. See the :ref:`menhir-main` section for details. +.. _alias-stanza: + alias ----- diff --git a/doc/terminology.rst b/doc/terminology.rst index 7cac56d7..aed21bd3 100644 --- a/doc/terminology.rst +++ b/doc/terminology.rst @@ -50,6 +50,9 @@ Terminology alias in all children directories recursively. Jbuilder defines the following standard aliases: + - ``default`` which is the alias build by default when no targets + are specified on the command line. See :ref:`default-alias` for + details - ``runtest`` which runs user defined tests - ``install`` which depends on everything that should be installed - ``doc`` which depends on the generated HTML diff --git a/doc/usage.rst b/doc/usage.rst index 322951ba..b3ceea8b 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -68,8 +68,9 @@ directory as this is normally the case. Interpretation of targets ========================= -This section describes how ``jbuilder`` interprets the targets given on -the command line. +This section describes how ``dune`` interprets the targets given on +the command line. When no targets are specified, ``dune`` builds the +``default`` alias, see :ref:`default-alias` for more details. Resolution ---------- @@ -128,6 +129,31 @@ You can also build an alias non-recursively by using ``@@`` instead of dune build @@runtest +.. _default-alias: + +Default alias +------------- + +When no targets are given to ``dune build``, it builds the special +``default`` alias. Effectively ``dune build`` is equivalent to: + +.. code:: + + dune build @@default + +When a directory doesn't explicitly define what the ``default`` alias +means via an :ref:`alias-stanza` stanza, the following implicit +definition is assumed: + +.. code:: + + (alias + (name default) + (deps (alias_rec install))) + +Which means that by default ``dune build`` will build everything that +is installable. + Finding external libraries ========================== @@ -214,7 +240,7 @@ follows: build: [["dune" "build" "-p" name "-j" jobs]] ``-p pkg`` is a shorthand for ``--root . --only-packages pkg --profile -release``. ``-p`` is the short version of +release --default-target @install``. ``-p`` is the short version of ``--for-release-of-packages``. This has the following effects: @@ -224,6 +250,7 @@ This has the following effects: - it sets the root to prevent jbuilder from looking it up - it sets the build profile to ``release`` - it uses whatever concurrency option opam provides +- it sets the default target to ``@install`` rather than ``@@default`` Note that ``name`` and ``jobs`` are variables expanded by opam. ``name`` expands to the package name and ``jobs`` to the number of jobs available diff --git a/src/build_system.ml b/src/build_system.ml index 5ad424d0..281b6a7e 100644 --- a/src/build_system.ml +++ b/src/build_system.ml @@ -271,7 +271,7 @@ module Alias0 = struct stamp_file (make ~dir name))) let is_standard = function - | "runtest" | "install" | "doc" | "doc-private" | "lint" -> true + | "runtest" | "install" | "doc" | "doc-private" | "lint" | "default" -> true | _ -> false open Build.O @@ -318,7 +318,7 @@ module Alias0 = struct It is not defined in %s or any of its descendants." name (Path.to_string_maybe_quoted src_dir) - let default = make "DEFAULT" + let default = make "default" let runtest = make "runtest" let install = make "install" let doc = make "doc" @@ -914,7 +914,28 @@ and load_dir_step2_exn t ~dir ~collector ~lazy_generators = let alias_dir = Path.append (Path.relative alias_dir context_name) sub_dir in let alias_rules, alias_stamp_files = let open Build.O in - String.Map.foldi collector.aliases ~init:([], Path.Set.empty) + let aliases = collector.aliases in + let aliases = + if String.Map.mem collector.aliases "default" then + aliases + else + match Path.extract_build_context_dir dir with + | None -> aliases + | Some (_, src_dir) -> + match File_tree.find_dir t.file_tree src_dir with + | None -> aliases + | Some _ -> + String.Map.add aliases "default" + { deps = Path.Set.empty + ; dyn_deps = + Alias0.dep_rec (Alias0.install ~dir) ~loc:Loc.none + ~file_tree:t.file_tree + >>> + Build.return Path.Set.empty + ; actions = [] + } + in + String.Map.foldi aliases ~init:([], Path.Set.empty) ~f:(fun name { Dir_status. deps; dyn_deps; actions } (rules, alias_stamp_files) -> let base_path = Path.relative alias_dir name in let rules, deps =