Merge pull request #950 from rgrinberg/dep-conf-list

Syntax for naming dependencies
This commit is contained in:
Rudi Grinberg 2018-07-10 02:47:51 +07:00 committed by GitHub
commit 1ac0da6347
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 702 additions and 455 deletions

View File

@ -143,6 +143,9 @@ next
- Lowercase all built-in %{variables} in dune files (#956, @rgrinberg) - Lowercase all built-in %{variables} in dune files (#956, @rgrinberg)
- New syntax for naming dependencies: `(deps (:x a b) (:y (glob_files *.c*)))`.
This replaces the use for `${<}` in dune files. (#950, @diml, @rgrinberg)
1.0+beta20 (10/04/2018) 1.0+beta20 (10/04/2018)
----------------------- -----------------------

View File

@ -22,7 +22,7 @@ Stanzas
(rule (rule
(targets foo.ml) (targets foo.ml)
(deps generator/gen.exe) (deps generator/gen.exe)
(action (run %{<} -o %{@}))) (action (run %{deps} -o %{targets})))
The following sections describe the available stanzas and their meaning. The following sections describe the available stanzas and their meaning.
@ -457,9 +457,9 @@ For instance:
.. code:: scheme .. code:: scheme
(rule (rule
(targets b (targets b)
(deps a (deps a)
(action (copy %{<} %{@}))))) (action (copy %{deps} %{targets})))
In this example it is obvious by inspecting the action what the In this example it is obvious by inspecting the action what the
dependencies and targets are. When this is the case you can use the dependencies and targets are. When this is the case you can use the
@ -495,7 +495,7 @@ ocamllex
(rule (rule
(targets <name>.ml) (targets <name>.ml)
(deps <name>.mll) (deps <name>.mll)
(action (chdir %{root} (run %{bin:ocamllex} -q -o %{<})))) (action (chdir %{root} (run %{bin:ocamllex} -q -o %{targets} %{deps}))))
To use a different rule mode, use the long form: To use a different rule mode, use the long form:
@ -515,7 +515,7 @@ ocamlyacc
(rule (rule
(targets <name>.ml <name>.mli) (targets <name>.ml <name>.mli)
(deps <name>.mly) (deps <name>.mly)
(action (chdir %{root} (run %{bin:ocamlyacc} %{<})))) (action (chdir %{root} (run %{bin:ocamlyacc} %{deps}))))
To use a different rule mode, use the long form: To use a different rule mode, use the long form:
@ -866,9 +866,8 @@ Dune supports the following variables:
In addition, ``(action ...)`` fields support the following special variables: In addition, ``(action ...)`` fields support the following special variables:
- ``@`` expands to the list of target - ``targets`` expands to the list of target
- ``<`` expands to the first dependency, or the empty string if there are no - ``deps`` expands to the list of dependencies
dependencies
- ``^`` expands to the list of dependencies, separated by spaces - ``^`` expands to the list of dependencies, separated by spaces
- ``dep:<path>`` expands to ``<path>`` (and adds ``<path>`` as a dependency of - ``dep:<path>`` expands to ``<path>`` (and adds ``<path>`` as a dependency of
the action) the action)
@ -909,7 +908,7 @@ In addition, ``(action ...)`` fields support the following special variables:
The ``%{<kind>:...}`` forms are what allows you to write custom rules that work The ``%{<kind>:...}`` forms are what allows you to write custom rules that work
transparently whether things are installed or not. transparently whether things are installed or not.
Note that aliases are ignored by both ``%{<}`` and ``%{^}``. Note that aliases are ignored by ``%{deps}``
The intent of this last form is to reliably read a list of strings The intent of this last form is to reliably read a list of strings
generated by an OCaml program via: generated by an OCaml program via:
@ -920,13 +919,13 @@ generated by an OCaml program via:
#. Expansion of lists #. Expansion of lists
Forms that expands to list of items, such as ``%{cc}``, ``%{^}``, Forms that expands to list of items, such as ``%{cc}``, ``%{deps}``,
``%{@}`` or ``%{read-lines:...}``, are suitable to be used in, say, ``%{targets}`` or ``%{read-lines:...}``, are suitable to be used in, say,
``(run <prog> <arguments>)``. For instance in: ``(run <prog> <arguments>)``. For instance in:
.. code:: scheme .. code:: scheme
(run foo %{^}) (run foo %{deps})
if there are two dependencies ``a`` and ``b``, the produced command if there are two dependencies ``a`` and ``b``, the produced command
will be equivalent to the shell command: will be equivalent to the shell command:
@ -940,7 +939,7 @@ you have to quote the variable as in:
.. code:: scheme .. code:: scheme
(run foo "%{^}") (run foo "%{deps}")
which is equivalent to the following shell command: which is equivalent to the following shell command:
@ -949,7 +948,7 @@ which is equivalent to the following shell command:
$ foo "a b" $ foo "a b"
(the items of the list are concatenated with space). (the items of the list are concatenated with space).
Note that, since ``%{^}`` is a list of items, the first one may be Note that, since ``%{deps}`` is a list of items, the first one may be
used as a program name, for instance: used as a program name, for instance:
.. code:: scheme .. code:: scheme
@ -957,7 +956,7 @@ used as a program name, for instance:
(rule (rule
(targets result.txt) (targets result.txt)
(deps foo.exe (glob_files *.txt)) (deps foo.exe (glob_files *.txt))
(action (run %{^}))) (action (run %{deps})))
Here is another example: Here is another example:
@ -966,7 +965,7 @@ Here is another example:
(rule (rule
(targets foo.exe) (targets foo.exe)
(deps foo.c) (deps foo.c)
(action (run %{cc} -o %{@} %{<} -lfoolib))) (action (run %{cc} -o %{targets} %{deps} -lfoolib)))
Library dependencies Library dependencies
@ -1038,11 +1037,11 @@ the ``-pp`` or ``-ppx`` of the various OCaml tools.
Preprocessing with actions Preprocessing with actions
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
``<action>`` uses the same DSL as described in the `User actions`_ section, and ``<action>`` uses the same DSL as described in the `User actions`_
for the same reason given in that section, it will be executed from the root of section, and for the same reason given in that section, it will be
the current build context. It is expected to be an action that reads the file executed from the root of the current build context. It is expected to
given as only dependency and outputs the preprocessed file on its standard be an action that reads the file given as only dependency named
output. ``input-file`` and outputs the preprocessed file on its standard output.
More precisely, ``(preprocess (action <action>))`` acts as if More precisely, ``(preprocess (action <action>))`` acts as if
you had setup a rule for every file of the form: you had setup a rule for every file of the form:
@ -1052,10 +1051,10 @@ you had setup a rule for every file of the form:
(rule (rule
(targets file.pp.ml) (targets file.pp.ml)
(deps file.ml) (deps file.ml)
(action (with-stdout-to %{@} (chdir %{root} <action>)))) (action (with-stdout-to %{targets} (chdir %{root} <action>))))
The equivalent of a ``-pp <command>`` option passed to the OCaml compiler is The equivalent of a ``-pp <command>`` option passed to the OCaml compiler is
``(system "<command> %{<}")``. ``(system "<command> %{input-file}")``.
Preprocessing with ppx rewriters Preprocessing with ppx rewriters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1105,8 +1104,8 @@ For instance:
.. code:: scheme .. code:: scheme
(preprocess (per_module (preprocess (per_module
(((action (run ./pp.sh X=1 %{<})) (foo bar))) (((action (run ./pp.sh X=1 %{input-file})) (foo bar)))
(((action (run ./pp.sh X=2 %{<})) (baz))))) (((action (run ./pp.sh X=2 %{input-file})) (baz)))))
.. _deps-field: .. _deps-field:
@ -1116,6 +1115,8 @@ Dependency specification
Dependencies in ``dune`` files can be specified using one of the following Dependencies in ``dune`` files can be specified using one of the following
syntax: syntax:
- ``(:name <dependencies>)`` will bind the the list of dependencies to the
``name`` variable. This variable will be available as ``%{name}`` in actions.
- ``(file <filename>)`` or simply ``<filename>``: depend on this file - ``(file <filename>)`` or simply ``<filename>``: depend on this file
- ``(alias <alias-name>)``: depend on the construction of this alias, for - ``(alias <alias-name>)``: depend on the construction of this alias, for
instance: ``(alias src/runtest)`` instance: ``(alias src/runtest)``
@ -1143,6 +1144,33 @@ syntax:
In all these cases, the argument supports `Variables expansion`_. In all these cases, the argument supports `Variables expansion`_.
Named Dependencies
~~~~~~~~~~~~~~~~~~
dune allows a user to organize dependency lists by naming them. The user is
allowed to assign a group of dependencies a name that can later be referred to
in actions (like the ``%{deps}`` and ``%{targets}`` built in variables).
One instance where is useful is for naming globs. Here's an example of an
imaginary bundle command:
.. code:: scheme
(rule
(targets archive.tar)
(deps
index.html
(:css (glob_files *.css))
(:js foo.js bar.js)
(:img (glob_files *.png) (glob_files *.jpg)))
(action
(run %{bin:bundle} index.html -css %{css} -js %{js} -img %{img} -o %{targets})))
Note that such named dependency list can also include unnamed dependencies (like
``index.html`` in the example above). Also, such user defined names wil shadow
built in variables. So ``(:root x)`` will shadow the built in ``%{root}``
variable.
.. _glob: .. _glob:
Glob Glob
@ -1310,7 +1338,7 @@ To understand why this is important, let's consider this dune file living in
(rule (rule
(targets blah.ml) (targets blah.ml)
(deps blah.mll) (deps blah.mll)
(action (run ocamllex -o %{@} %{<}))) (action (run ocamllex -o %{targets} %{deps})))
Here the command that will be executed is: Here the command that will be executed is:
@ -1334,7 +1362,7 @@ of your project. What you should write instead is:
(rule (rule
(targets blah.ml) (targets blah.ml)
(deps blah.mll) (deps blah.mll)
(action (chdir %{root} (run ocamllex -o %{@} %{<})))) (action (chdir %{root} (run ocamllex -o %{targets} %{deps}))))
Locks Locks
----- -----
@ -1357,13 +1385,13 @@ same lock:
(name runtest) (name runtest)
(deps foo) (deps foo)
(locks m) (locks m)
(action (run test.exe %{<}))) (action (run test.exe %{deps})))
(alias (alias
(name runtest) (name runtest)
(deps bar) (deps bar)
(locks m) (locks m)
(action (run test.exe %{<}))) (action (run test.exe %{deps})))
Dune will make sure that the executions of ``test.exe foo`` and Dune will make sure that the executions of ``test.exe foo`` and
``test.exe bar`` are serialized. ``test.exe bar`` are serialized.
@ -1383,7 +1411,7 @@ simply use an absolute filename:
(name runtest) (name runtest)
(deps foo) (deps foo)
(locks /tcp-port/1042) (locks /tcp-port/1042)
(action (run test.exe %{<}))) (action (run test.exe %{deps})))
.. _ocaml-syntax: .. _ocaml-syntax:

View File

@ -169,7 +169,6 @@ Jbuild Dune
======================== ============ ======================== ============
``${@}`` ``%{targets}`` ``${@}`` ``%{targets}``
``${^}`` ``%{deps}`` ``${^}`` ``%{deps}``
``${<}`` ``%{first-dep}``
``${path:file}`` ``%{dep:file}`` ``${path:file}`` ``%{dep:file}``
``${SCOPE_ROOT}`` ``%{project_root}`` ``${SCOPE_ROOT}`` ``%{project_root}``
``${findlib:..}`` ``%{lib:..}`` ``${findlib:..}`` ``%{lib:..}``
@ -186,8 +185,26 @@ Jbuild Dune
Removed Variables Removed Variables
----------------- -----------------
``${path-no-dep:file}`` has been removed. ``${path-no-dep:file}`` and ``${<}`` have been removed.
A named dependency should be used instead of ``${<}``. For instance
the following jbuild file:
.. code:: scheme
(alias
((name runtest)
(deps (input))
(action (run ./test.exe %{<}))))
should be rewritten to the following dune file:
.. code:: scheme
(alias
(name runtest)
(deps (:x input))
(action (run ./test.exe %{x})))
``# JBUILDER_GEN`` renamed ``# JBUILDER_GEN`` renamed
-------------------------- --------------------------

View File

@ -307,7 +307,7 @@ The backend for such a framework looks like this:
(library (library
((name simple_tests) ((name simple_tests)
(inline_tests.backend (inline_tests.backend
((generate_runner (run sed "s/(\\*TEST:\\(.*\\)\\*)/let () = \\1;;/" ${impl-files})) ((generate_runner (run sed "s/(\\*TEST:\\(.*\\)\\*)/let () = \\1;;/" %{impl-files}))
)))) ))))
Now all you have to do is write ``(inline_tests ((backend Now all you have to do is write ``(inline_tests ((backend

View File

@ -525,7 +525,7 @@ module Unexpanded = struct
Redirect (outputs, E.path ~dir ~f fn, partial_expand t ~dir ~map_exe ~f) Redirect (outputs, E.path ~dir ~f fn, partial_expand t ~dir ~map_exe ~f)
| Ignore (outputs, t) -> | Ignore (outputs, t) ->
Ignore (outputs, partial_expand t ~dir ~map_exe ~f) Ignore (outputs, partial_expand t ~dir ~map_exe ~f)
| Progn l -> Progn (List.map l ~f:(fun t -> partial_expand t ~dir ~map_exe ~f)) | Progn l -> Progn (List.map l ~f:(partial_expand ~dir ~map_exe ~f))
| Echo xs -> Echo (List.map xs ~f:(E.cat_strings ~dir ~f)) | Echo xs -> Echo (List.map xs ~f:(E.cat_strings ~dir ~f))
| Cat x -> Cat (E.path ~dir ~f x) | Cat x -> Cat (E.path ~dir ~f x)
| Copy (x, y) -> | Copy (x, y) ->

View File

@ -187,13 +187,14 @@ module Gen(P : Install_rules.Params) = struct
in in
SC.add_rule_get_targets sctx ~mode:rule.mode ~loc:rule.loc SC.add_rule_get_targets sctx ~mode:rule.mode ~loc:rule.loc
~locks:(interpret_locks ~dir ~scope rule.locks) ~locks:(interpret_locks ~dir ~scope rule.locks)
(SC.Deps.interpret sctx ~scope ~dir rule.deps (SC.Deps.interpret_named sctx ~scope ~dir rule.deps
>>> >>>
SC.Action.run SC.Action.run
sctx sctx
(snd rule.action) (snd rule.action)
~loc:(fst rule.action) ~loc:(fst rule.action)
~dir ~dir
~bindings:(Pform.Map.of_bindings rule.deps)
~dep_kind:Required ~dep_kind:Required
~targets ~targets
~scope) ~scope)
@ -929,7 +930,7 @@ module Gen(P : Install_rules.Params) = struct
let module S = Sexp.To_sexp in let module S = Sexp.To_sexp in
Sexp.List Sexp.List
[ Sexp.unsafe_atom_of_string "user-alias" [ Sexp.unsafe_atom_of_string "user-alias"
; S.list Jbuild.Dep_conf.sexp_of_t alias_conf.deps ; Jbuild.Bindings.sexp_of_t Jbuild.Dep_conf.sexp_of_t alias_conf.deps
; S.option Action.Unexpanded.sexp_of_t ; S.option Action.Unexpanded.sexp_of_t
(Option.map alias_conf.action ~f:snd) (Option.map alias_conf.action ~f:snd)
] ]
@ -939,7 +940,7 @@ module Gen(P : Install_rules.Params) = struct
~name:alias_conf.name ~name:alias_conf.name
~stamp ~stamp
~locks:(interpret_locks ~dir ~scope alias_conf.locks) ~locks:(interpret_locks ~dir ~scope alias_conf.locks)
(SC.Deps.interpret sctx ~scope ~dir alias_conf.deps (SC.Deps.interpret_named sctx ~scope ~dir alias_conf.deps
>>> >>>
match alias_conf.action with match alias_conf.action with
| None -> Build.progn [] | None -> Build.progn []
@ -950,6 +951,7 @@ module Gen(P : Install_rules.Params) = struct
~loc ~loc
~dir ~dir
~dep_kind:Required ~dep_kind:Required
~bindings:(Pform.Map.of_bindings alias_conf.deps)
~targets:Alias ~targets:Alias
~scope) ~scope)
@ -976,7 +978,7 @@ module Gen(P : Install_rules.Params) = struct
let rule = let rule =
{ Rule. { Rule.
targets = Infer targets = Infer
; deps = [] ; deps = Bindings.empty
; action = ; action =
(loc, Action.Unexpanded.Redirect (Stdout, diff.file2, run_action)) (loc, Action.Unexpanded.Redirect (Stdout, diff.file2, run_action))
; mode = Standard ; mode = Standard

View File

@ -179,8 +179,9 @@ include Sub_system.Register_end_point(
~obj_name:name) ~obj_name:name)
in in
let extra_vars = let bindings =
String.Map.singleton "library-name" ([Value.String lib.name]) Pform.Map.singleton "library-name"
(Values [String lib.name])
in in
let runner_libs = let runner_libs =
@ -202,25 +203,24 @@ include Sub_system.Register_end_point(
let target = Path.relative inline_test_dir main_module_filename in let target = Path.relative inline_test_dir main_module_filename in
let source_modules = Module.Name.Map.values source_modules in let source_modules = Module.Name.Map.values source_modules in
let files ml_kind = let files ml_kind =
Value.L.paths ( Pform.Values (Value.L.paths (
List.filter_map source_modules ~f:(fun m -> List.filter_map source_modules ~f:(fun m ->
Module.file m ~dir ml_kind)) Module.file m ~dir ml_kind)))
in in
let extra_vars = let bindings =
List.fold_left Pform.Map.of_list_exn
[ "impl-files", files Impl [ "impl-files", files Impl
; "intf-files", files Intf ; "intf-files", files Intf
] ]
~init:extra_vars
~f:(fun acc (k, v) -> String.Map.add acc k v)
in in
Build.return [] Build.return Bindings.empty
>>> >>>
Build.all Build.all
(List.filter_map backends ~f:(fun (backend : Backend.t) -> (List.filter_map backends ~f:(fun (backend : Backend.t) ->
Option.map backend.info.generate_runner ~f:(fun (loc, action) -> Option.map backend.info.generate_runner ~f:(fun (loc, action) ->
SC.Action.run sctx action ~loc SC.Action.run sctx action ~loc
~extra_vars ~dir ~dep_kind:Required ~targets:Alias ~scope))) ~bindings
~dir ~dep_kind:Required ~targets:Alias ~scope)))
>>^ (fun actions -> >>^ (fun actions ->
Action.with_stdout_to target Action.with_stdout_to target
(Action.progn actions)) (Action.progn actions))
@ -251,7 +251,7 @@ include Sub_system.Register_end_point(
Super_context.expand_and_eval_set sctx flags Super_context.expand_and_eval_set sctx flags
~scope ~scope
~dir ~dir
~extra_vars ~bindings
~standard:(Build.return []))) ~standard:(Build.return [])))
>>^ List.concat >>^ List.concat
in in

View File

@ -232,6 +232,63 @@ module Pps_and_flags = struct
Dune_syntax.t Dune_syntax.t
end end
module Bindings = struct
type 'a one =
| Unnamed of 'a
| Named of string * 'a list
type 'a t = 'a one list
let fold t ~f ~init = List.fold_left ~f:(fun acc x -> f x acc) ~init t
let to_list =
List.concat_map ~f:(function
| Unnamed x -> [x]
| Named (_, xs) -> xs)
let find t k =
List.find_map t ~f:(function
| Unnamed _ -> None
| Named (k', x) -> Option.some_if (k = k') x)
let empty = []
let singleton x = [Unnamed x]
let t elem =
let rec loop vars acc =
peek >>= function
| None -> return (List.rev acc)
| Some (List (_, Atom (loc, A s) :: _)) when
String.length s > 1 && s.[0] = ':' ->
let name = String.sub s ~pos:1 ~len:(String.length s - 1) in
let vars =
if not (String.Set.mem vars name) then
String.Set.add vars name
else
of_sexp_errorf loc "Variable %s is defined for the second time."
name
in
enter (junk >>= fun () -> repeat elem)
>>= fun values ->
loop vars (Named (name, values) :: acc)
| _ ->
elem >>= fun x ->
loop vars (Unnamed x :: acc)
in
Stanza.file_kind () >>= function
| Jbuild -> list (elem >>| fun x -> Unnamed x)
| Dune -> loop String.Set.empty []
let sexp_of_t sexp_of_a bindings =
Sexp.List (
List.map bindings ~f:(function
| Unnamed a -> sexp_of_a a
| Named (name, bindings) ->
Sexp.List (Sexp.atom (":" ^ name) :: List.map ~f:sexp_of_a bindings))
)
end
module Dep_conf = struct module Dep_conf = struct
type t = type t =
| File of String_with_vars.t | File of String_with_vars.t
@ -269,21 +326,23 @@ module Dep_conf = struct
open Sexp open Sexp
let sexp_of_t = function let sexp_of_t = function
| File t -> | File t ->
List [Sexp.unsafe_atom_of_string "file" ; String_with_vars.sexp_of_t t] List [ Sexp.unsafe_atom_of_string "file"
; String_with_vars.sexp_of_t t ]
| Alias t -> | Alias t ->
List [Sexp.unsafe_atom_of_string "alias" ; String_with_vars.sexp_of_t t] List [ Sexp.unsafe_atom_of_string "alias"
; String_with_vars.sexp_of_t t ]
| Alias_rec t -> | Alias_rec t ->
List [Sexp.unsafe_atom_of_string "alias_rec" ; List [ Sexp.unsafe_atom_of_string "alias_rec"
String_with_vars.sexp_of_t t] ; String_with_vars.sexp_of_t t ]
| Glob_files t -> | Glob_files t ->
List [Sexp.unsafe_atom_of_string "glob_files" ; List [ Sexp.unsafe_atom_of_string "glob_files"
String_with_vars.sexp_of_t t] ; String_with_vars.sexp_of_t t ]
| Source_tree t -> | Source_tree t ->
List [Sexp.unsafe_atom_of_string "files_recursively_in" ; List [ Sexp.unsafe_atom_of_string "files_recursively_in"
String_with_vars.sexp_of_t t] ; String_with_vars.sexp_of_t t ]
| Package t -> | Package t ->
List [Sexp.unsafe_atom_of_string "package" ; List [ Sexp.unsafe_atom_of_string "package"
String_with_vars.sexp_of_t t] ; String_with_vars.sexp_of_t t]
| Universe -> | Universe ->
Sexp.unsafe_atom_of_string "universe" Sexp.unsafe_atom_of_string "universe"
end end
@ -1071,7 +1130,7 @@ module Rule = struct
type t = type t =
{ targets : Targets.t { targets : Targets.t
; deps : Dep_conf.t list ; deps : Dep_conf.t Bindings.t
; action : Loc.t * Action.Unexpanded.t ; action : Loc.t * Action.Unexpanded.t
; mode : Mode.t ; mode : Mode.t
; locks : String_with_vars.t list ; locks : String_with_vars.t list
@ -1113,7 +1172,7 @@ module Rule = struct
let short_form = let short_form =
located Action.Unexpanded.t >>| fun (loc, action) -> located Action.Unexpanded.t >>| fun (loc, action) ->
{ targets = Infer { targets = Infer
; deps = [] ; deps = Bindings.empty
; action = (loc, action) ; action = (loc, action)
; mode = Standard ; mode = Standard
; locks = [] ; locks = []
@ -1126,7 +1185,8 @@ module Rule = struct
>>= fun action -> >>= fun action ->
field "targets" (list file_in_current_dir) field "targets" (list file_in_current_dir)
>>= fun targets -> >>= fun targets ->
field "deps" (list Dep_conf.t) ~default:[] >>= fun deps -> field "deps" (Bindings.t Dep_conf.t) ~default:Bindings.empty
>>= fun deps ->
field "locks" (list String_with_vars.t) ~default:[] >>= fun locks -> field "locks" (list String_with_vars.t) ~default:[] >>= fun locks ->
map_validate map_validate
(field_b (field_b
@ -1231,7 +1291,7 @@ module Rule = struct
let src = name ^ ".mll" in let src = name ^ ".mll" in
let dst = name ^ ".ml" in let dst = name ^ ".ml" in
{ targets = Static [dst] { targets = Static [dst]
; deps = [File (S.virt_text __POS__ src)] ; deps = Bindings.singleton (Dep_conf.File (S.virt_text __POS__ src))
; action = ; action =
(loc, (loc,
Chdir Chdir
@ -1240,7 +1300,7 @@ module Rule = struct
[ S.virt_text __POS__ "-q" [ S.virt_text __POS__ "-q"
; S.virt_text __POS__ "-o" ; S.virt_text __POS__ "-o"
; S.virt_var __POS__ "targets" ; S.virt_var __POS__ "targets"
; S.virt_var __POS__"first-dep" ; S.virt_var __POS__"deps"
]))) ])))
; mode ; mode
; locks = [] ; locks = []
@ -1252,13 +1312,13 @@ module Rule = struct
List.map modules ~f:(fun name -> List.map modules ~f:(fun name ->
let src = name ^ ".mly" in let src = name ^ ".mly" in
{ targets = Static [name ^ ".ml"; name ^ ".mli"] { targets = Static [name ^ ".ml"; name ^ ".mli"]
; deps = [File (S.virt_text __POS__ src)] ; deps = Bindings.singleton (Dep_conf.File (S.virt_text __POS__ src))
; action = ; action =
(loc, (loc,
Chdir Chdir
(S.virt_var __POS__ "root", (S.virt_var __POS__ "root",
Run (S.virt_text __POS__ "ocamlyacc", Run (S.virt_text __POS__ "ocamlyacc",
[S.virt_var __POS__ "first-dep"]))) [S.virt_var __POS__ "deps"])))
; mode ; mode
; locks = [] ; locks = []
; loc ; loc
@ -1320,7 +1380,7 @@ end
module Alias_conf = struct module Alias_conf = struct
type t = type t =
{ name : string { name : string
; deps : Dep_conf.t list ; deps : Dep_conf.t Bindings.t
; action : (Loc.t * Action.Unexpanded.t) option ; action : (Loc.t * Action.Unexpanded.t) option
; locks : String_with_vars.t list ; locks : String_with_vars.t list
; package : Package.t option ; package : Package.t option
@ -1336,10 +1396,11 @@ module Alias_conf = struct
let t = let t =
record record
(field "name" alias_name >>= fun name -> (field "name" alias_name >>= fun name ->
field "deps" (list Dep_conf.t) ~default:[] >>= fun deps ->
field_o "package" Pkg.t >>= fun package -> field_o "package" Pkg.t >>= fun package ->
field_o "action" (located Action.Unexpanded.t) >>= fun action -> field_o "action" (located Action.Unexpanded.t) >>= fun action ->
field "locks" (list String_with_vars.t) ~default:[] >>= fun locks -> field "locks" (list String_with_vars.t) ~default:[] >>= fun locks ->
field "deps" (Bindings.t Dep_conf.t) ~default:Bindings.empty
>>= fun deps ->
return return
{ name { name
; deps ; deps
@ -1354,7 +1415,7 @@ module Tests = struct
{ exes : Executables.t { exes : Executables.t
; locks : String_with_vars.t list ; locks : String_with_vars.t list
; package : Package.t option ; package : Package.t option
; deps : Dep_conf.t list ; deps : Dep_conf.t Bindings.t
} }
let gen_parse names = let gen_parse names =
@ -1362,11 +1423,12 @@ module Tests = struct
(Buildable.t >>= fun buildable -> (Buildable.t >>= fun buildable ->
field_oslu "link_flags" >>= fun link_flags -> field_oslu "link_flags" >>= fun link_flags ->
names >>= fun names -> names >>= fun names ->
field "deps" (list Dep_conf.t) ~default:[] >>= fun deps ->
field_o "package" Pkg.t >>= fun package -> field_o "package" Pkg.t >>= fun package ->
field "locks" (list String_with_vars.t) ~default:[] >>= fun locks -> field "locks" (list String_with_vars.t) ~default:[] >>= fun locks ->
field "modes" Executables.Link_mode.Set.t field "modes" Executables.Link_mode.Set.t
~default:Executables.Link_mode.Set.default >>= fun modes -> ~default:Executables.Link_mode.Set.default >>= fun modes ->
field "deps" (Bindings.t Dep_conf.t) ~default:Bindings.empty
>>= fun deps ->
return return
{ exes = { exes =
{ Executables. { Executables.

View File

@ -81,6 +81,26 @@ module Lib_deps : sig
val of_pps : Pp.t list -> t val of_pps : Pp.t list -> t
end end
module Bindings : sig
type 'a one =
| Unnamed of 'a
| Named of string * 'a list
type 'a t = 'a one list
val find : 'a t -> string -> 'a list option
val fold : 'a t -> f:('a one -> 'acc -> 'acc) -> init:'acc -> 'acc
val empty : 'a t
val to_list : 'a t -> 'a list
val singleton : 'a -> 'a t
val sexp_of_t : ('a -> Usexp.t) -> 'a t -> Usexp.t
end
module Dep_conf : sig module Dep_conf : sig
type t = type t =
| File of String_with_vars.t | File of String_with_vars.t
@ -284,7 +304,7 @@ module Rule : sig
type t = type t =
{ targets : Targets.t { targets : Targets.t
; deps : Dep_conf.t list ; deps : Dep_conf.t Bindings.t
; action : Loc.t * Action.Unexpanded.t ; action : Loc.t * Action.Unexpanded.t
; mode : Mode.t ; mode : Mode.t
; locks : String_with_vars.t list ; locks : String_with_vars.t list
@ -307,7 +327,7 @@ end
module Alias_conf : sig module Alias_conf : sig
type t = type t =
{ name : string { name : string
; deps : Dep_conf.t list ; deps : Dep_conf.t Bindings.t
; action : (Loc.t * Action.Unexpanded.t) option ; action : (Loc.t * Action.Unexpanded.t) option
; locks : String_with_vars.t list ; locks : String_with_vars.t list
; package : Package.t option ; package : Package.t option
@ -350,7 +370,7 @@ module Tests : sig
{ exes : Executables.t { exes : Executables.t
; locks : String_with_vars.t list ; locks : String_with_vars.t list
; package : Package.t option ; package : Package.t option
; deps : Dep_conf.t list ; deps : Dep_conf.t Bindings.t
} }
end end

View File

@ -1,68 +1,55 @@
open Import open Import
module Var = struct type t =
type t = | Values of Value.t list
| Values of Value.t list | Project_root
| Project_root | First_dep
| First_dep | Deps
| Deps | Targets
| Targets | Named_local
| Exe
| Dep
| Bin
| Lib
| Libexec
| Lib_available
| Version
| Read
| Read_strings
| Read_lines
| Path_no_dep
| Ocaml_config
let to_value_no_deps_or_targets t ~scope = type with_info =
match t with | No_info of t
| Values v -> Some v | Since of t * Syntax.Version.t
| Project_root -> Some [Value.Dir (Scope.root scope)] | Deleted_in of t * Syntax.Version.t * string option
| First_dep
| Deps
| Targets -> None
end
module Macro = struct
type t =
| Exe
| Dep
| Bin
| Lib
| Libexec
| Lib_available
| Version
| Read
| Read_strings
| Read_lines
| Path_no_dep
| Ocaml_config
end
type 'a t =
| No_info of 'a
| Since of 'a * Syntax.Version.t
| Deleted_in of 'a * Syntax.Version.t
| Renamed_in of Syntax.Version.t * string | Renamed_in of Syntax.Version.t * string
module Map = struct module Map = struct
type nonrec 'a t = 'a t String.Map.t type t = with_info String.Map.t
let values v = No_info (Var.Values v) let values v = No_info (Values v)
let renamed_in ~new_name ~version = Renamed_in (version, new_name) let renamed_in ~new_name ~version = Renamed_in (version, new_name)
let deleted_in ~version kind = Deleted_in (kind, version) let deleted_in ~version ?repl kind = Deleted_in (kind, version, repl)
let since ~version v = Since (v, version) let since ~version v = Since (v, version)
let static_vars = let static =
[ "first-dep", since ~version:(1, 0) Var.First_dep let macro x = No_info x in
; "targets", since ~version:(1, 0) Var.Targets [ "targets", since ~version:(1, 0) Targets
; "deps", since ~version:(1, 0) Var.Deps ; "deps", since ~version:(1, 0) Deps
; "project_root", since ~version:(1, 0) Var.Project_root ; "project_root", since ~version:(1, 0) Project_root
; "<", renamed_in ~version:(1, 0) ~new_name:"first-dep" ; "<", deleted_in First_dep ~version:(1, 0)
~repl:"Use a named dependency instead:\
\n\
\n\ (deps (:x <dep>) ...)\
\n\ ... %{x} ..."
; "@", renamed_in ~version:(1, 0) ~new_name:"targets" ; "@", renamed_in ~version:(1, 0) ~new_name:"targets"
; "^", renamed_in ~version:(1, 0) ~new_name:"deps" ; "^", renamed_in ~version:(1, 0) ~new_name:"deps"
; "SCOPE_ROOT", renamed_in ~version:(1, 0) ~new_name:"project_root" ; "SCOPE_ROOT", renamed_in ~version:(1, 0) ~new_name:"project_root"
]
let macros = ; "exe", macro Exe
let macro kind = No_info kind in
let open Macro in
[ "exe", macro Exe
; "bin", macro Bin ; "bin", macro Bin
; "lib", macro Lib ; "lib", macro Lib
; "libexec", macro Libexec ; "libexec", macro Libexec
@ -82,7 +69,7 @@ module Map = struct
] ]
|> String.Map.of_list_exn |> String.Map.of_list_exn
let create_vars ~(context : Context.t) ~cxx_flags = let create ~(context : Context.t) ~cxx_flags =
let ocamlopt = let ocamlopt =
match context.ocamlopt with match context.ocamlopt with
| None -> Path.relative context.ocaml_bin "ocamlopt" | None -> Path.relative context.ocaml_bin "ocamlopt"
@ -107,11 +94,13 @@ module Map = struct
; "arch_sixtyfour" , string (string_of_bool context.arch_sixtyfour) ; "arch_sixtyfour" , string (string_of_bool context.arch_sixtyfour)
; "make" , make ; "make" , make
; "root" , values [Value.Dir context.build_dir] ; "root" , values [Value.Dir context.build_dir]
] in ]
in
let uppercased = let uppercased =
List.map lowercased ~f:(fun (k, _) -> List.map lowercased ~f:(fun (k, _) ->
(String.uppercase k, renamed_in ~new_name:k ~version:(1, 0))) in (String.uppercase k, renamed_in ~new_name:k ~version:(1, 0)))
let vars = in
let other =
[ "-verbose" , values [] [ "-verbose" , values []
; "pa_cpp" , strings (context.c_compiler :: cflags ; "pa_cpp" , strings (context.c_compiler :: cflags
@ ["-undef"; "-traditional"; @ ["-undef"; "-traditional";
@ -128,49 +117,67 @@ module Map = struct
; "profile" , string context.profile ; "profile" , string context.profile
] ]
in in
[ static_vars String.Map.superpose
; lowercased static
; uppercased (String.Map.of_list_exn
; vars (List.concat
] [ lowercased
|> List.concat ; uppercased
|> String.Map.of_list_exn ; other
]))
let static_vars = String.Map.of_list_exn static_vars let superpose = String.Map.superpose
let rec expand t ~syntax_version ~var = let rec expand t ~syntax_version ~pform =
let name = String_with_vars.Var.name var in let name = String_with_vars.Var.name pform in
Option.bind (String.Map.find t name) ~f:(fun v -> Option.bind (String.Map.find t name) ~f:(fun v ->
let what var = let describe = String_with_vars.Var.describe in
String_with_vars.Var.to_string (
if String_with_vars.Var.is_macro var then
String_with_vars.Var.with_payload var ~payload:(Some "..")
else
var)
in
match v with match v with
| No_info v -> Some v | No_info v -> Some v
| Since (v, min_version) -> | Since (v, min_version) ->
if syntax_version >= min_version then if syntax_version >= min_version then
Some v Some v
else else
Syntax.Error.since (String_with_vars.Var.loc var) Syntax.Error.since (String_with_vars.Var.loc pform)
Stanza.syntax min_version Stanza.syntax min_version
~what:(what var) ~what:(describe pform)
| Renamed_in (in_version, new_name) -> begin | Renamed_in (in_version, new_name) -> begin
if syntax_version >= in_version then if syntax_version >= in_version then
Syntax.Error.renamed_in (String_with_vars.Var.loc var) Syntax.Error.renamed_in (String_with_vars.Var.loc pform)
Stanza.syntax syntax_version Stanza.syntax syntax_version
~what:(what var) ~what:(describe pform)
~to_:(what (String_with_vars.Var.with_name var ~name:new_name)) ~to_:(describe
(String_with_vars.Var.with_name pform ~name:new_name))
else else
expand t ~syntax_version:in_version expand t ~syntax_version:in_version
~var:(String_with_vars.Var.with_name var ~name:new_name) ~pform:(String_with_vars.Var.with_name pform ~name:new_name)
end end
| Deleted_in (v, in_version) -> | Deleted_in (v, in_version, repl) ->
if syntax_version < in_version then if syntax_version < in_version then
Some v Some v
else else
Syntax.Error.deleted_in (String_with_vars.Var.loc var) Syntax.Error.deleted_in (String_with_vars.Var.loc pform)
Stanza.syntax syntax_version ~what:(what var)) Stanza.syntax syntax_version ~what:(describe pform) ?repl)
let empty = String.Map.empty
let singleton k v = String.Map.singleton k (No_info v)
let of_list_exn pforms =
List.map ~f:(fun (k, x) -> (k, No_info x)) pforms
|> String.Map.of_list_exn
let of_bindings =
Jbuild.Bindings.fold ~f:(fun x acc ->
match x with
| Unnamed _ -> acc
| Named (s, _) -> String.Map.add acc s (No_info Named_local)
) ~init:empty
let input_file path =
let value = Values (Value.L.paths [path]) in
[ "input-file", since ~version:(1, 0) value
; "<", renamed_in ~new_name:"input-file" ~version:(1, 0)
]
|> String.Map.of_list_exn
end end

View File

@ -1,49 +1,50 @@
module Var : sig open Stdune
type t =
| Values of Value.t list
| Project_root
| First_dep
| Deps
| Targets
val to_value_no_deps_or_targets : t -> scope:Scope.t -> Value.t list option type t =
end (* Variables *)
| Values of Value.t list
| Project_root
| First_dep
| Deps
| Targets
| Named_local
module Macro : sig (* Macros *)
type t = | Exe
| Exe | Dep
| Dep | Bin
| Bin | Lib
| Lib | Libexec
| Libexec | Lib_available
| Lib_available | Version
| Version | Read
| Read | Read_strings
| Read_strings | Read_lines
| Read_lines | Path_no_dep
| Path_no_dep | Ocaml_config
| Ocaml_config
end
type 'a t =
| No_info of 'a
| Since of 'a * Syntax.Version.t
| Deleted_in of 'a * Syntax.Version.t
| Renamed_in of Syntax.Version.t * string
module Map : sig module Map : sig
type 'a var type pform
type 'a t type t
val create_vars : context:Context.t -> cxx_flags:string list -> Var.t t val create : context:Context.t -> cxx_flags:string list -> t
val macros : Macro.t t val superpose : t -> t -> t
val static_vars : Var.t t (** Map with all named values as [Named_local] *)
val of_bindings : _ Jbuild.Bindings.t -> t
val singleton : string -> pform -> t
val of_list_exn : (string * pform) list -> t
val input_file : Path.t -> t
val expand val expand
: 'a t : t
-> syntax_version:Syntax.Version.t -> syntax_version:Syntax.Version.t
-> var:String_with_vars.Var.t -> pform:String_with_vars.Var.t
-> 'a option -> pform option
end with type 'a var := 'a t
val empty : t
end with type pform := t

View File

@ -454,14 +454,16 @@ let lint_module sctx ~dir ~dep_kind ~lint ~lib_name ~scope ~dir_kind =
let action = Action.Unexpanded.Chdir (root_var, action) in let action = Action.Unexpanded.Chdir (root_var, action) in
Module.iter source ~f:(fun _ (src : Module.File.t) -> Module.iter source ~f:(fun _ (src : Module.File.t) ->
let src_path = Path.relative dir src.name in let src_path = Path.relative dir src.name in
let bindings = Pform.Map.input_file src_path in
add_alias src.name add_alias src.name
(Build.path src_path (Build.path src_path
>>^ (fun _ -> [src_path]) >>^ (fun _ -> Jbuild.Bindings.empty)
>>> SC.Action.run sctx >>> SC.Action.run sctx
action action
~loc ~loc
~dir ~dir
~dep_kind ~dep_kind
~bindings
~targets:(Static []) ~targets:(Static [])
~scope))) ~scope)))
| Pps { loc; pps; flags } -> | Pps { loc; pps; flags } ->
@ -476,14 +478,15 @@ let lint_module sctx ~dir ~dep_kind ~lint ~lib_name ~scope ~dir_kind =
get_ppx_driver sctx ~loc ~scope ~dir_kind pps get_ppx_driver sctx ~loc ~scope ~dir_kind pps
>>| fun (exe, driver) -> >>| fun (exe, driver) ->
(exe, (exe,
let extra_vars = let bindings =
String_map.singleton "corrected-suffix" [Value.String corrected_suffix] Pform.Map.singleton "corrected-suffix"
(Values [String corrected_suffix])
in in
Build.memoize "ppx flags" Build.memoize "ppx flags"
(SC.expand_and_eval_set sctx driver.info.lint_flags (SC.expand_and_eval_set sctx driver.info.lint_flags
~scope ~scope
~dir ~dir
~extra_vars ~bindings
~standard:(Build.return []))) ~standard:(Build.return [])))
in in
(fun ~source ~ast -> (fun ~source ~ast ->
@ -527,11 +530,12 @@ let make sctx ~dir ~dep_kind ~lint ~preprocess
(fun m ~lint -> (fun m ~lint ->
let ast = let ast =
pped_module m ~dir ~f:(fun _kind src dst -> pped_module m ~dir ~f:(fun _kind src dst ->
let bindings = Pform.Map.input_file src in
SC.add_rule sctx SC.add_rule sctx
(preprocessor_deps (preprocessor_deps
>>> >>>
Build.path src Build.path src
>>^ (fun _ -> [src]) >>^ (fun _ -> Jbuild.Bindings.empty)
>>> >>>
SC.Action.run sctx SC.Action.run sctx
(Redirect (Redirect
@ -542,6 +546,7 @@ let make sctx ~dir ~dep_kind ~lint ~preprocess
~loc ~loc
~dir ~dir
~dep_kind ~dep_kind
~bindings
~targets:(Static [dst]) ~targets:(Static [dst])
~scope)) ~scope))
|> setup_reason_rules sctx ~dir in |> setup_reason_rules sctx ~dir in
@ -558,14 +563,15 @@ let make sctx ~dir ~dep_kind ~lint ~preprocess
let open Result.O in let open Result.O in
get_ppx_driver sctx ~loc ~scope ~dir_kind pps >>| fun (exe, driver) -> get_ppx_driver sctx ~loc ~scope ~dir_kind pps >>| fun (exe, driver) ->
(exe, (exe,
let extra_vars = let bindings =
String_map.singleton "corrected-suffix" [Value.String corrected_suffix] Pform.Map.singleton "corrected-suffix"
(Values [String corrected_suffix])
in in
Build.memoize "ppx flags" Build.memoize "ppx flags"
(SC.expand_and_eval_set sctx driver.info.flags (SC.expand_and_eval_set sctx driver.info.flags
~scope ~scope
~dir ~dir
~extra_vars ~bindings
~standard:(Build.return []))) ~standard:(Build.return [])))
in in
(fun m ~lint -> (fun m ~lint ->

View File

@ -211,6 +211,8 @@ module Var = struct
| Var s -> s | Var s -> s
| Macro (k, v) -> k ^ ":" ^ v | Macro (k, v) -> k ^ ":" ^ v
let payload t = t.payload
let to_string = string_of_var let to_string = string_of_var
let pp fmt t = Format.pp_print_string fmt (to_string t) let pp fmt t = Format.pp_print_string fmt (to_string t)
@ -224,6 +226,12 @@ module Var = struct
{ t with name } { t with name }
let is_macro t = Option.is_some t.payload let is_macro t = Option.is_some t.payload
let describe t =
to_string
(match t.payload with
| None -> t
| Some _ -> { t with payload = Some ".." })
end end
let partial_expand let partial_expand
@ -277,10 +285,10 @@ let expand t ~mode ~dir ~f =
| None -> | None ->
begin match var.syntax with begin match var.syntax with
| Percent -> | Percent ->
begin match Var.destruct var with if Var.is_macro var then
| Var v -> Loc.fail var.loc "unknown variable %S" v Loc.fail var.loc "Unknown macro %s" (Var.describe var)
| Macro _ -> Loc.fail var.loc "unknown form %s" (string_of_var var) else
end Loc.fail var.loc "Unknown variable %S" (Var.name var)
| Dollar_brace | Dollar_brace
| Dollar_paren -> Some [Value.String (string_of_var var)] | Dollar_paren -> Some [Value.String (string_of_var var)]
end end

View File

@ -56,6 +56,7 @@ module Var : sig
val name : t -> string val name : t -> string
val loc : t -> Loc.t val loc : t -> Loc.t
val full_name : t -> string val full_name : t -> string
val payload : t -> string option
type kind = type kind =
| Var of string | Var of string
@ -63,13 +64,14 @@ module Var : sig
val destruct : t -> kind val destruct : t -> kind
val to_string : t -> string
val with_name : t -> name:string -> t val with_name : t -> name:string -> t
val with_payload : t -> payload:string option -> t val with_payload : t -> payload:string option -> t
val is_macro : t -> bool val is_macro : t -> bool
(** Describe what this variable is *)
val describe : t -> string
end end
val expand val expand

View File

@ -45,8 +45,7 @@ type t =
; artifacts : Artifacts.t ; artifacts : Artifacts.t
; stanzas_to_consider_for_install : Installable.t list ; stanzas_to_consider_for_install : Installable.t list
; cxx_flags : string list ; cxx_flags : string list
; vars : Pform.Var.t Pform.Map.t ; pforms : Pform.Map.t
; macros : Pform.Macro.t Pform.Map.t
; ocaml_config : Value.t list String.Map.t ; ocaml_config : Value.t list String.Map.t
; chdir : (Action.t, Action.t) Build.t ; chdir : (Action.t, Action.t) Build.t
; host : t option ; host : t option
@ -86,64 +85,43 @@ let installed_libs t = t.installed_libs
let find_scope_by_dir t dir = Scope.DB.find_by_dir t.scopes dir let find_scope_by_dir t dir = Scope.DB.find_by_dir t.scopes dir
let find_scope_by_name t name = Scope.DB.find_by_name t.scopes name let find_scope_by_name t name = Scope.DB.find_by_name t.scopes name
let expand_vars t ~syntax_version ~var = let expand_ocaml_config t pform =
if String_with_vars.Var.is_macro var then let name = Option.value_exn (String_with_vars.Var.payload pform) in
Loc.fail (String_with_vars.Var.loc var) match String.Map.find t.ocaml_config name with
"macros of the form %%{name:..} cannot be expanded here" | Some x -> x
else | None ->
Pform.Map.expand t.vars ~syntax_version ~var Loc.fail (String_with_vars.Var.loc pform)
"Unknown ocaml configuration variable %S"
let expand_macro t ~syntax_version ~var = name
if String_with_vars.Var.is_macro var then
Pform.Map.expand t.macros ~syntax_version ~var
else
Exn.code_error "expand_macro can't expand variables"
[ "var", String_with_vars.Var.sexp_of_t var ]
let expand t ~syntax_version ~var =
match
match String_with_vars.Var.destruct var with
| Var _ -> Left (expand_vars t ~syntax_version ~var)
| Macro (_, _) -> Right (expand_macro t ~syntax_version ~var)
with
| Right None
| Left None -> None
| Right (Some x) -> Some (Right x)
| Left (Some x) -> Some (Left x)
let (expand_vars_string, expand_vars_path) = let (expand_vars_string, expand_vars_path) =
let expand t ~scope ~dir ?(extra_vars=String.Map.empty) s = let expand t ~scope ~dir ?(bindings=Pform.Map.empty) s =
String_with_vars.expand ~mode:Single ~dir s ~f:(fun var syntax_version -> String_with_vars.expand ~mode:Single ~dir s ~f:(fun pform syntax_version ->
match expand t ~syntax_version ~var with (match Pform.Map.expand bindings ~syntax_version ~pform with
| None -> | None -> Pform.Map.expand t.pforms ~syntax_version ~pform
String.Map.find extra_vars (String_with_vars.Var.full_name var) | Some _ as x -> x)
| Some (Left v) -> |> Option.map ~f:(function
begin match Pform.Var.to_value_no_deps_or_targets ~scope v with | Pform.Values l -> l
| Some _ as v -> v | Ocaml_config -> expand_ocaml_config t pform
| None -> | Project_root -> [Value.Dir (Scope.root scope)]
Loc.fail (String_with_vars.Var.loc var) | _ ->
"Variable %a is not allowed in this context" Loc.fail (String_with_vars.Var.loc pform)
String_with_vars.Var.pp var "%s isn't allowed in this position"
end (String_with_vars.Var.describe pform)))
| Some (Right Ocaml_config) ->
String.Map.find t.ocaml_config (String_with_vars.Var.name var)
| Some (Right _) ->
Loc.fail (String_with_vars.Var.loc var)
"This percent form isn't allowed in this position")
in in
let expand_vars t ~scope ~dir ?extra_vars s = let expand_vars t ~scope ~dir ?bindings s =
expand t ~scope ~dir ?extra_vars s expand t ~scope ~dir ?bindings s
|> Value.to_string ~dir |> Value.to_string ~dir
in in
let expand_vars_path t ~scope ~dir ?extra_vars s = let expand_vars_path t ~scope ~dir ?bindings s =
expand t ~scope ~dir ?extra_vars s expand t ~scope ~dir ?bindings s
|> Value.to_path ~error_loc:(String_with_vars.loc s) ~dir |> Value.to_path ~error_loc:(String_with_vars.loc s) ~dir
in in
(expand_vars, expand_vars_path) (expand_vars, expand_vars_path)
let expand_and_eval_set t ~scope ~dir ?extra_vars set ~standard = let expand_and_eval_set t ~scope ~dir ?bindings set ~standard =
let open Build.O in let open Build.O in
let f = expand_vars_string t ~scope ~dir ?extra_vars in let f = expand_vars_string t ~scope ~dir ?bindings in
let parse ~loc:_ s = s in let parse ~loc:_ s = s in
let (syntax, files) = Ordered_set_lang.Unexpanded.files set ~f in let (syntax, files) = Ordered_set_lang.Unexpanded.files set ~f in
match String.Set.to_list files with match String.Set.to_list files with
@ -208,7 +186,7 @@ module Env = struct
~ocamlopt_flags:cfg.ocamlopt_flags ~ocamlopt_flags:cfg.ocamlopt_flags
~default ~default
~eval:(expand_and_eval_set t ~scope:node.scope ~dir:node.dir ~eval:(expand_and_eval_set t ~scope:node.scope ~dir:node.dir
?extra_vars:None) ?bindings:None)
in in
node.ocaml_flags <- Some flags; node.ocaml_flags <- Some flags;
flags flags
@ -223,7 +201,7 @@ let ocaml_flags t ~dir ~scope (x : Buildable.t) =
~ocamlc_flags:x.ocamlc_flags ~ocamlc_flags:x.ocamlc_flags
~ocamlopt_flags:x.ocamlopt_flags ~ocamlopt_flags:x.ocamlopt_flags
~default:(Env.ocaml_flags t ~dir) ~default:(Env.ocaml_flags t ~dir)
~eval:(expand_and_eval_set t ~scope ~dir ?extra_vars:None) ~eval:(expand_and_eval_set t ~scope ~dir ?bindings:None)
let dump_env t ~dir = let dump_env t ~dir =
Ocaml_flags.dump (Env.ocaml_flags t ~dir) Ocaml_flags.dump (Env.ocaml_flags t ~dir)
@ -306,7 +284,7 @@ let create
List.filter context.ocamlc_cflags List.filter context.ocamlc_cflags
~f:(fun s -> not (String.is_prefix s ~prefix:"-std=")) ~f:(fun s -> not (String.is_prefix s ~prefix:"-std="))
in in
let vars = Pform.Map.create_vars ~context ~cxx_flags in let pforms = Pform.Map.create ~context ~cxx_flags in
let ocaml_config = let ocaml_config =
let string s = [Value.String s] in let string s = [Value.String s] in
Ocaml_config.to_list context.ocaml_config Ocaml_config.to_list context.ocaml_config
@ -333,8 +311,7 @@ let create
; stanzas_to_consider_for_install ; stanzas_to_consider_for_install
; artifacts ; artifacts
; cxx_flags ; cxx_flags
; vars ; pforms
; macros = Pform.Map.macros
; ocaml_config ; ocaml_config
; chdir = Build.arr (fun (action : Action.t) -> ; chdir = Build.arr (fun (action : Action.t) ->
match action with match action with
@ -523,8 +500,23 @@ module Deps = struct
>>^ fun () -> [] >>^ fun () -> []
let interpret t ~scope ~dir l = let interpret t ~scope ~dir l =
Build.all (List.map l ~f:(dep t ~scope ~dir)) List.map l ~f:(dep t ~scope ~dir)
|> Build.all
>>^ List.concat >>^ List.concat
let interpret_named t ~scope ~dir bindings =
let unnamed x = Jbuild.Bindings.Unnamed x in
List.map bindings ~f:(function
| Jbuild.Bindings.Unnamed p ->
dep t ~scope ~dir p >>^ unnamed
| Named (s, ps) ->
List.map ~f:(dep t ~scope ~dir) ps
|> Build.all
>>^ (fun deps -> Jbuild.Bindings.Named (s, deps)))
|> Build.all
>>^ List.concat_map ~f:(function
| Jbuild.Bindings.Unnamed s -> List.map s ~f:unnamed
| Named (s, ps) -> [Named (s, List.concat ps)])
end end
module Pkg_version = struct module Pkg_version = struct
@ -615,7 +607,7 @@ module Action = struct
| Some x -> x | Some x -> x
let expand_step1 sctx ~dir ~dep_kind ~scope ~targets_written_by_user let expand_step1 sctx ~dir ~dep_kind ~scope ~targets_written_by_user
~map_exe ~extra_vars t = ~map_exe ~bindings t =
let acc = let acc =
{ failures = [] { failures = []
; lib_deps = String.Map.empty ; lib_deps = String.Map.empty
@ -623,127 +615,117 @@ module Action = struct
; ddeps = String.Map.empty ; ddeps = String.Map.empty
} }
in in
let expand_form s var syntax_version = let expand pform syntax_version =
let loc = String_with_vars.Var.loc var in let loc = String_with_vars.Var.loc pform in
let key = String_with_vars.Var.full_name var in let key = String_with_vars.Var.full_name pform in
begin match expand_macro sctx ~syntax_version ~var with let s = Option.value (String_with_vars.Var.payload pform) ~default:"" in
| Some Pform.Macro.Exe -> Some (path_exp (map_exe (Path.relative dir s)))
| Some Ocaml_config -> String.Map.find sctx.ocaml_config s
| Some Dep -> Some (path_exp (Path.relative dir s))
| Some Bin -> begin
let sctx = host sctx in
match Artifacts.binary (artifacts sctx) s with
| Ok path -> Some (path_exp path)
| Error e ->
add_fail acc ({ fail = fun () -> Action.Prog.Not_found.raise e })
end
| Some Lib -> begin
let lib_dep, file = parse_lib_file ~loc s in
add_lib_dep acc lib_dep dep_kind;
match
Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file
with
| Ok path -> Some (path_exp path)
| Error fail -> add_fail acc fail
end
| Some Libexec -> begin
let sctx = host sctx in
let lib_dep, file = parse_lib_file ~loc s in
add_lib_dep acc lib_dep dep_kind;
match
Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file
with
| Error fail -> add_fail acc fail
| Ok path ->
if not Sys.win32 || Filename.extension s = ".exe" then begin
Some (path_exp path)
end else begin
let path_exe = Path.extend_basename path ~suffix:".exe" in
let dep =
Build.if_file_exists path_exe
~then_:(Build.path path_exe >>^ fun _ -> path_exp path_exe)
~else_:(Build.path path >>^ fun _ -> path_exp path)
in
add_ddep acc ~key dep
end
end
| Some Lib_available -> begin
let lib = s in
add_lib_dep acc lib Optional;
Some (str_exp (string_of_bool (
Lib.DB.available (Scope.libs scope) lib)))
end
| Some Version -> begin
match Package.Name.Map.find (Scope.project scope).packages
(Package.Name.of_string s) with
| Some p ->
let x =
Pkg_version.read sctx p >>^ function
| None -> [Value.String ""]
| Some s -> [String s]
in
add_ddep acc ~key x
| None ->
add_fail acc { fail = fun () ->
Loc.fail loc "Package %S doesn't exist in the current project." s
}
end
| Some Read -> begin
let path = Path.relative dir s in
let data =
Build.contents path
>>^ fun s -> [Value.String s]
in
add_ddep acc ~key data
end
| Some Read_lines -> begin
let path = Path.relative dir s in
let data =
Build.lines_of path
>>^ Value.L.strings
in
add_ddep acc ~key data
end
| Some Read_strings -> begin
let path = Path.relative dir s in
let data =
Build.strings path
>>^ Value.L.strings
in
add_ddep acc ~key data
end
| Some Path_no_dep -> Some [Value.Dir (Path.relative dir s)]
| None ->
Loc.fail (String_with_vars.Var.loc var) "Unknown form: %a"
String_with_vars.Var.pp var
end
in
let expand var syntax_version =
let loc = String_with_vars.Var.loc var in
let key = String_with_vars.Var.full_name var in
let res = let res =
match String_with_vars.Var.destruct var with Pform.Map.expand bindings ~syntax_version ~pform
| Macro (_, s) -> expand_form s var syntax_version |> Option.bind ~f:(function
| Var var_name -> | Pform.Values l -> Some l
begin match expand_vars sctx ~syntax_version ~var with | Ocaml_config -> Some (expand_ocaml_config sctx pform)
| None -> String.Map.find extra_vars key | Project_root -> Some [Value.Dir (Scope.root scope)]
| Some Targets -> | First_dep | Deps | Named_local -> None
let var () = | Targets ->
match var_name with
| "@" -> sprintf "${%s}" var_name
| "targets" -> sprintf "%%{%s}" var_name
| _ -> assert false
in
begin match targets_written_by_user with begin match targets_written_by_user with
| Infer -> | Infer ->
Loc.fail loc "You cannot use %s with inferred rules." (var ()) Loc.fail loc "You cannot use %s with inferred rules."
(String_with_vars.Var.describe pform)
| Alias -> | Alias ->
Loc.fail loc "You cannot use %s in aliases." (var ()) Loc.fail loc "You cannot use %s in aliases."
(String_with_vars.Var.describe pform)
| Static l -> | Static l ->
Some (Value.L.dirs l) (* XXX hack to signal no dep *) Some (Value.L.dirs l) (* XXX hack to signal no dep *)
end end
| Some v -> Pform.Var.to_value_no_deps_or_targets v ~scope | Exe -> Some (path_exp (map_exe (Path.relative dir s)))
end | Dep -> Some (path_exp (Path.relative dir s))
| Bin -> begin
let sctx = host sctx in
match Artifacts.binary (artifacts sctx) s with
| Ok path -> Some (path_exp path)
| Error e ->
add_fail acc
({ fail = fun () -> Action.Prog.Not_found.raise e })
end
| Lib -> begin
let lib_dep, file = parse_lib_file ~loc s in
add_lib_dep acc lib_dep dep_kind;
match
Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file
with
| Ok path -> Some (path_exp path)
| Error fail -> add_fail acc fail
end
| Libexec -> begin
let sctx = host sctx in
let lib_dep, file = parse_lib_file ~loc s in
add_lib_dep acc lib_dep dep_kind;
match
Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file
with
| Error fail -> add_fail acc fail
| Ok path ->
if not Sys.win32 || Filename.extension s = ".exe" then begin
Some (path_exp path)
end else begin
let path_exe = Path.extend_basename path ~suffix:".exe" in
let dep =
Build.if_file_exists path_exe
~then_:(Build.path path_exe >>^ fun _ ->
path_exp path_exe)
~else_:(Build.path path >>^ fun _ ->
path_exp path)
in
add_ddep acc ~key dep
end
end
| Lib_available -> begin
let lib = s in
add_lib_dep acc lib Optional;
Some (str_exp (string_of_bool (
Lib.DB.available (Scope.libs scope) lib)))
end
| Version -> begin
match Package.Name.Map.find (Scope.project scope).packages
(Package.Name.of_string s) with
| Some p ->
let x =
Pkg_version.read sctx p >>^ function
| None -> [Value.String ""]
| Some s -> [String s]
in
add_ddep acc ~key x
| None ->
add_fail acc { fail = fun () ->
Loc.fail loc
"Package %S doesn't exist in the current project." s
}
end
| Read -> begin
let path = Path.relative dir s in
let data =
Build.contents path
>>^ fun s -> [Value.String s]
in
add_ddep acc ~key data
end
| Read_lines -> begin
let path = Path.relative dir s in
let data =
Build.lines_of path
>>^ Value.L.strings
in
add_ddep acc ~key data
end
| Read_strings -> begin
let path = Path.relative dir s in
let data =
Build.strings path
>>^ Value.L.strings
in
add_ddep acc ~key data
end
| Path_no_dep -> Some [Value.Dir (Path.relative dir s)])
in in
Option.iter res ~f:(fun v -> Option.iter res ~f:(fun v ->
acc.sdeps <- Path.Set.union acc.sdeps <- Path.Set.union
@ -754,31 +736,51 @@ module Action = struct
let t = U.partial_expand t ~dir ~map_exe ~f:expand in let t = U.partial_expand t ~dir ~map_exe ~f:expand in
(t, acc) (t, acc)
let expand_step2 ~dir ~dynamic_expansions ~deps_written_by_user ~map_exe t = let expand_step2 ~dir ~dynamic_expansions ~bindings
U.Partial.expand t ~dir ~map_exe ~f:(fun var syntax_version -> ~(deps_written_by_user : Path.t Jbuild.Bindings.t)
let key = String_with_vars.Var.full_name var in ~map_exe t =
let loc = String_with_vars.Var.loc var in U.Partial.expand t ~dir ~map_exe ~f:(fun pform syntax_version ->
let key = String_with_vars.Var.full_name pform in
let loc = String_with_vars.Var.loc pform in
match String.Map.find dynamic_expansions key with match String.Map.find dynamic_expansions key with
| Some _ as opt -> opt | Some _ as opt -> opt
| None -> | None ->
Pform.Map.expand Pform.Map.static_vars ~syntax_version ~var Option.map (Pform.Map.expand bindings ~syntax_version ~pform) ~f:(function
|> Option.map ~f:(function | Named_local ->
| Pform.Var.Deps -> (Value.L.paths deps_written_by_user) begin match Jbuild.Bindings.find deps_written_by_user key with
| None ->
Exn.code_error "Local named variable not present in named deps"
[ "pform", String_with_vars.Var.sexp_of_t pform
; "deps_written_by_user",
Jbuild.Bindings.sexp_of_t Path.sexp_of_t deps_written_by_user
]
| Some x -> Value.L.paths x
end
| Deps ->
deps_written_by_user
|> Jbuild.Bindings.to_list
|> Value.L.paths
| First_dep -> | First_dep ->
begin match deps_written_by_user with begin match deps_written_by_user with
| Named _ :: _ ->
(* This case is not possible: ${<} only exist in jbuild
files and named dependencies are not available in
jbuild files *)
assert false
| Unnamed v :: _ -> [Path v]
| [] -> | [] ->
Loc.warn loc "Variable '%s' used with no explicit \ Loc.warn loc "Variable '%s' used with no explicit \
dependencies@." key; dependencies@." key;
[Value.String ""] [Value.String ""]
| v :: _ -> [Path v]
end end
| _ -> | _ ->
Exn.code_error "Unexpected variable in step2" Exn.code_error "Unexpected variable in step2"
["var", String_with_vars.Var.sexp_of_t var])) ["var", String_with_vars.Var.sexp_of_t pform]))
let run sctx ~loc ?(extra_vars=String.Map.empty) let run sctx ~loc ~bindings t ~dir ~dep_kind
t ~dir ~dep_kind ~targets:targets_written_by_user ~scope ~targets:targets_written_by_user ~scope
: (Path.t list, Action.t) Build.t = : (Path.t Bindings.t, Action.t) Build.t =
let bindings = Pform.Map.superpose sctx.pforms bindings in
let map_exe = map_exe sctx in let map_exe = map_exe sctx in
if targets_written_by_user = Alias then begin if targets_written_by_user = Alias then begin
match Action.Infer.unexpanded_targets t with match Action.Infer.unexpanded_targets t with
@ -791,7 +793,7 @@ module Action = struct
end; end;
let t, forms = let t, forms =
expand_step1 sctx t ~dir ~dep_kind ~scope expand_step1 sctx t ~dir ~dep_kind ~scope
~targets_written_by_user ~map_exe ~extra_vars ~targets_written_by_user ~map_exe ~bindings
in in
let { Action.Infer.Outcome. deps; targets } = let { Action.Infer.Outcome. deps; targets } =
match targets_written_by_user with match targets_written_by_user with
@ -850,6 +852,7 @@ module Action = struct
in in
let unresolved = let unresolved =
expand_step2 t ~dir ~dynamic_expansions ~deps_written_by_user ~map_exe expand_step2 t ~dir ~dynamic_expansions ~deps_written_by_user ~map_exe
~bindings
in in
Action.Unresolved.resolve unresolved ~f:(fun prog -> Action.Unresolved.resolve unresolved ~f:(fun prog ->
let sctx = host sctx in let sctx = host sctx in

View File

@ -82,7 +82,7 @@ val expand_vars_string
: t : t
-> scope:Scope.t -> scope:Scope.t
-> dir:Path.t -> dir:Path.t
-> ?extra_vars:Value.t list String.Map.t -> ?bindings:Pform.Map.t
-> String_with_vars.t -> String_with_vars.t
-> string -> string
@ -90,7 +90,7 @@ val expand_vars_path
: t : t
-> scope:Scope.t -> scope:Scope.t
-> dir:Path.t -> dir:Path.t
-> ?extra_vars:Value.t list String.Map.t -> ?bindings:Pform.Map.t
-> String_with_vars.t -> String_with_vars.t
-> Path.t -> Path.t
@ -98,7 +98,7 @@ val expand_and_eval_set
: t : t
-> scope:Scope.t -> scope:Scope.t
-> dir:Path.t -> dir:Path.t
-> ?extra_vars:Value.t list String.Map.t -> ?bindings:Pform.Map.t
-> Ordered_set_lang.Unexpanded.t -> Ordered_set_lang.Unexpanded.t
-> standard:(unit, string list) Build.t -> standard:(unit, string list) Build.t
-> (unit, string list) Build.t -> (unit, string list) Build.t
@ -219,6 +219,13 @@ module Deps : sig
-> dir:Path.t -> dir:Path.t
-> Dep_conf.t list -> Dep_conf.t list
-> (unit, Path.t list) Build.t -> (unit, Path.t list) Build.t
val interpret_named
: t
-> scope:Scope.t
-> dir:Path.t
-> Dep_conf.t Bindings.t
-> (unit, Path.t Bindings.t) Build.t
end end
(** Interpret action written in jbuild files *) (** Interpret action written in jbuild files *)
@ -232,13 +239,13 @@ module Action : sig
val run val run
: t : t
-> loc:Loc.t -> loc:Loc.t
-> ?extra_vars:Value.t list String.Map.t -> bindings:Pform.Map.t
-> Action.Unexpanded.t -> Action.Unexpanded.t
-> dir:Path.t -> dir:Path.t
-> dep_kind:Build.lib_dep_kind -> dep_kind:Build.lib_dep_kind
-> targets:targets -> targets:targets
-> scope:Scope.t -> scope:Scope.t
-> (Path.t list, Action.t) Build.t -> (Path.t Bindings.t, Action.t) Build.t
end end
module Pkg_version : sig module Pkg_version : sig

View File

@ -65,9 +65,12 @@ module Error = struct
Loc.fail loc "%s was renamed to '%s' in the %s version of %s" Loc.fail loc "%s was renamed to '%s' in the %s version of %s"
what to_ (Version.to_string ver) t.desc what to_ (Version.to_string ver) t.desc
let deleted_in loc t ver ~what = let deleted_in loc t ?repl ver ~what =
Loc.fail loc "%s was deleted in version %s of %s" Loc.fail loc "%s was deleted in version %s of %s%s"
what (Version.to_string ver) t.desc what (Version.to_string ver) t.desc
(match repl with
| None -> ""
| Some s -> ".\n" ^ s)
end end

View File

@ -25,7 +25,13 @@ module Error : sig
val renamed_in : Loc.t -> t -> Version.t -> what:string -> to_:string -> _ val renamed_in : Loc.t -> t -> Version.t -> what:string -> to_:string -> _
val deleted_in : Loc.t -> t -> Version.t -> what:string -> _ val deleted_in
: Loc.t
-> t
-> ?repl:string
-> Version.t
-> what:string
-> _
end end
(** [create ~name ~desc supported_versions] defines a new (** [create ~name ~desc supported_versions] defines a new

View File

@ -80,6 +80,14 @@
test-cases/custom-build-dir test-cases/custom-build-dir
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))) (progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
(alias
(name dep-vars)
(deps (package dune) (source_tree test-cases/dep-vars))
(action
(chdir
test-cases/dep-vars
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
(alias (alias
(name depend-on-the-universe) (name depend-on-the-universe)
(deps (package dune) (source_tree test-cases/depend-on-the-universe)) (deps (package dune) (source_tree test-cases/depend-on-the-universe))
@ -531,6 +539,14 @@
(run %{exe:cram.exe} -skip-versions 4.02.3 -test run.t) (run %{exe:cram.exe} -skip-versions 4.02.3 -test run.t)
(diff? run.t run.t.corrected))))) (diff? run.t run.t.corrected)))))
(alias
(name preprocess-with-action)
(deps (package dune) (source_tree test-cases/preprocess-with-action))
(action
(chdir
test-cases/preprocess-with-action
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
(alias (alias
(name private-public-overlap) (name private-public-overlap)
(deps (package dune) (source_tree test-cases/private-public-overlap)) (deps (package dune) (source_tree test-cases/private-public-overlap))
@ -603,6 +619,14 @@
test-cases/select test-cases/select
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))) (progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
(alias
(name shadow-bindings)
(deps (package dune) (source_tree test-cases/shadow-bindings))
(action
(chdir
test-cases/shadow-bindings
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
(alias (alias
(name subst) (name subst)
(deps (package dune) (source_tree test-cases/subst)) (deps (package dune) (source_tree test-cases/subst))
@ -680,6 +704,7 @@
(alias copy_files) (alias copy_files)
(alias cross-compilation) (alias cross-compilation)
(alias custom-build-dir) (alias custom-build-dir)
(alias dep-vars)
(alias depend-on-the-universe) (alias depend-on-the-universe)
(alias dune-jbuild-var-case) (alias dune-jbuild-var-case)
(alias dune-ppx-driver-system) (alias dune-ppx-driver-system)
@ -732,6 +757,7 @@
(alias package-dep) (alias package-dep)
(alias path-variables) (alias path-variables)
(alias ppx-rewriter) (alias ppx-rewriter)
(alias preprocess-with-action)
(alias private-public-overlap) (alias private-public-overlap)
(alias project-root) (alias project-root)
(alias promote) (alias promote)
@ -740,6 +766,7 @@
(alias scope-bug) (alias scope-bug)
(alias scope-ppx-bug) (alias scope-ppx-bug)
(alias select) (alias select)
(alias shadow-bindings)
(alias subst) (alias subst)
(alias syntax-versioning) (alias syntax-versioning)
(alias tests-stanza) (alias tests-stanza)
@ -762,6 +789,7 @@
(alias copy_files) (alias copy_files)
(alias cross-compilation) (alias cross-compilation)
(alias custom-build-dir) (alias custom-build-dir)
(alias dep-vars)
(alias depend-on-the-universe) (alias depend-on-the-universe)
(alias dune-jbuild-var-case) (alias dune-jbuild-var-case)
(alias dune-ppx-driver-system) (alias dune-ppx-driver-system)
@ -807,6 +835,7 @@
(alias output-obj) (alias output-obj)
(alias package-dep) (alias package-dep)
(alias path-variables) (alias path-variables)
(alias preprocess-with-action)
(alias project-root) (alias project-root)
(alias promote) (alias promote)
(alias quoting) (alias quoting)
@ -814,6 +843,7 @@
(alias scope-bug) (alias scope-bug)
(alias scope-ppx-bug) (alias scope-ppx-bug)
(alias select) (alias select)
(alias shadow-bindings)
(alias subst) (alias subst)
(alias syntax-versioning) (alias syntax-versioning)
(alias tests-stanza) (alias tests-stanza)

View File

@ -0,0 +1,5 @@
(rule
(deps (:foo a b) (:baz foo (alias test)) a b c)
(targets bar)
(action (with-stdout-to bar (echo "foo"))))

View File

@ -0,0 +1 @@
(lang dune 1.0)

View File

@ -0,0 +1,3 @@
Dependencies are allowed :patterns
$ dune build

View File

@ -1,7 +1 @@
(executable (test (name f))
(name f))
(alias
(name runtest)
(deps f.exe)
(action (run %{first-dep})))

View File

@ -7,8 +7,7 @@
(alias (alias
(name runtest) (name runtest)
(package lib1) (package lib1)
(deps test1.exe) (action (run ./test1.exe)))
(action (run %{first-dep})))
(executable (executable
(name test1) (name test1)
@ -24,8 +23,7 @@
(alias (alias
(name runtest) (name runtest)
(package lib2) (package lib2)
(deps test2.exe) (action (run ./test2.exe)))
(action (run %{first-dep})))
(executable (executable
(name test2) (name test2)

View File

@ -1,6 +1,5 @@
(alias (alias
(name runtest) (name runtest)
(deps main.exe) (action (run ./main.exe)))
(action (run %{first-dep})))
(executable (name main)) (executable (name main))

View File

@ -1,6 +1,5 @@
(alias (alias
(name runtest) (name runtest)
(deps main.exe) (action (run ./main.exe)))
(action (run %{first-dep})))
(executable (name main)) (executable (name main))

View File

@ -4,5 +4,5 @@ inappropariate place:
$ dune build $ dune build
Info: creating file dune-project with this contents: (lang dune 1.0) Info: creating file dune-project with this contents: (lang dune 1.0)
File "dune", line 1, characters 14-21: File "dune", line 1, characters 14-21:
Error: This percent form isn't allowed in this position Error: %{read:..} isn't allowed in this position
[1] [1]

View File

@ -33,7 +33,7 @@
(rule (rule
(targets dynamic.exe) (targets dynamic.exe)
(deps dynamic.c) (deps dynamic.c)
(action (run %{cc} -o %{targets} %{first-dep} %{ocaml-config:native_c_libraries}))) (action (run %{cc} -o %{targets} %{deps} %{ocaml-config:native_c_libraries})))
(alias (alias
(name runtest) (name runtest)
@ -48,9 +48,9 @@
(alias (alias
(name runtest) (name runtest)
(deps test.bc%{ext_dll}) (deps test.bc%{ext_dll})
(action (run ./dynamic.exe ./%{first-dep}))) (action (run ./dynamic.exe ./%{deps})))
(alias (alias
(name runtest) (name runtest)
(deps test%{ext_dll}) (deps test%{ext_dll})
(action (run ./dynamic.exe ./%{first-dep}))) (action (run ./dynamic.exe ./%{deps})))

View File

@ -0,0 +1 @@
(lang dune 1.0)

View File

@ -0,0 +1,3 @@
(test
(name test)
(preprocess (action (run pp/pp.exe %{input-file}))))

View File

@ -0,0 +1 @@
Hello, world!

View File

@ -0,0 +1 @@
print_endline _STRING_

View File

@ -0,0 +1,10 @@
(executable
((name test)
(preprocess (action (run pp/pp.exe ${<})))))
(rule
(with-stdout-to test.output (run ./test.exe)))
(alias
((name runtest)
(action (diff test.expected test.output))))

View File

@ -0,0 +1 @@
Hello, world!

View File

@ -0,0 +1 @@
print_endline _STRING_

View File

@ -0,0 +1,4 @@
(executable
(name pp))
(ocamllex pp)

View File

@ -0,0 +1,10 @@
rule main = parse
| eof { () }
| "_STRING_" { Printf.printf "%S" "Hello, world!"; main lexbuf }
| _ as c { print_char c; main lexbuf }
{
let () =
set_binary_mode_out stdout true;
main (Lexing.from_channel (open_in_bin Sys.argv.(1)))
}

View File

@ -0,0 +1 @@
$ dune runtest

View File

@ -10,5 +10,4 @@
(alias (alias
(name runtest) (name runtest)
(deps main.exe) (action (run ./main.exe)))
(action (run %{first-dep})))

View File

@ -0,0 +1,5 @@
(alias
(name runtest)
(deps (:root foo))
(action (echo %{root})))

View File

@ -0,0 +1 @@
(lang dune 1.0)

View File

@ -0,0 +1,4 @@
Bindings introduced by user dependencies should shadow existing bindings
$ dune runtest
foo

View File

@ -16,3 +16,14 @@
Error: 'link_executables' was deleted in version 1.0 of the dune language Error: 'link_executables' was deleted in version 1.0 of the dune language
[1] [1]
$ rm -f dune $ rm -f dune
$ echo '(alias (name x) (deps x) (action (run %{<})))' > dune
$ dune build
File "dune", line 1, characters 40-42:
Error: %{<} was deleted in version 1.0 of the dune language.
Use a named dependency instead:
(deps (:x <dep>) ...)
... %{x} ...
[1]
$ rm -f dune

View File

@ -1,8 +1,3 @@
(executable (test
(name test_configurator) (name test_configurator)
(libraries configurator)) (libraries configurator))
(alias
(name runtest)
(deps ./test_configurator.exe)
(action (run %{first-dep})))

View File

@ -18,72 +18,72 @@
(alias (alias
(name runtest) (name runtest)
(deps tests.mlt (deps (:t tests.mlt)
(glob_files %{project_root}/src/.dune.objs/*.cmi) (glob_files %{project_root}/src/.dune.objs/*.cmi)
(glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi) (glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi)
(source_tree toolchain.d) (source_tree toolchain.d)
(source_tree findlib-db)) (source_tree findlib-db))
(action (chdir %{project_root} (action (chdir %{project_root}
(progn (progn
(run %{exe:expect_test.exe} %{first-dep}) (run %{exe:expect_test.exe} %{t})
(diff? %{first-dep} %{first-dep}.corrected))))) (diff? %{t} %{t}.corrected)))))
(alias (alias
(name runtest) (name runtest)
(deps filename.mlt (deps (:t filename.mlt)
(glob_files %{project_root}/src/.dune.objs/*.cmi) (glob_files %{project_root}/src/.dune.objs/*.cmi)
(glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi)) (glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi))
(action (chdir %{project_root} (action (chdir %{project_root}
(progn (progn
(run %{exe:expect_test.exe} %{first-dep}) (run %{exe:expect_test.exe} %{t})
(diff? %{first-dep} %{first-dep}.corrected))))) (diff? %{t} %{t}.corrected)))))
(alias (alias
(name runtest) (name runtest)
(deps import_dot_map.mlt (deps (:t import_dot_map.mlt)
(glob_files %{project_root}/src/.dune.objs/*.cmi) (glob_files %{project_root}/src/.dune.objs/*.cmi)
(glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi)) (glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi))
(action (chdir %{project_root} (action (chdir %{project_root}
(progn (progn
(run %{exe:expect_test.exe} %{first-dep}) (run %{exe:expect_test.exe} %{t})
(diff? %{first-dep} %{first-dep}.corrected))))) (diff? %{t} %{t}.corrected)))))
(alias (alias
(name runtest) (name runtest)
(deps action.mlt (deps (:t action.mlt)
(glob_files %{project_root}/src/.dune.objs/*.cmi) (glob_files %{project_root}/src/.dune.objs/*.cmi)
(glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi)) (glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi))
(action (chdir %{project_root} (action (chdir %{project_root}
(progn (progn
(run %{exe:expect_test.exe} %{first-dep}) (run %{exe:expect_test.exe} %{t})
(diff? %{first-dep} %{first-dep}.corrected))))) (diff? %{t} %{t}.corrected)))))
(alias (alias
(name runtest) (name runtest)
(deps path.mlt (deps (:t path.mlt)
(glob_files %{project_root}/src/.dune.objs/*.cmi) (glob_files %{project_root}/src/.dune.objs/*.cmi)
(glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi)) (glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi))
(action (chdir %{project_root} (action (chdir %{project_root}
(progn (progn
(run %{exe:expect_test.exe} %{first-dep}) (run %{exe:expect_test.exe} %{t})
(diff? %{first-dep} %{first-dep}.corrected))))) (diff? %{t} %{t}.corrected)))))
(alias (alias
(name runtest) (name runtest)
(deps sexp.mlt (deps (:t sexp.mlt)
(glob_files %{project_root}/src/.dune.objs/*.cmi) (glob_files %{project_root}/src/.dune.objs/*.cmi)
(glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi)) (glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi))
(action (chdir %{project_root} (action (chdir %{project_root}
(progn (progn
(run %{exe:expect_test.exe} %{first-dep}) (run %{exe:expect_test.exe} %{t})
(diff? %{first-dep} %{first-dep}.corrected))))) (diff? %{t} %{t}.corrected)))))
(alias (alias
(name runtest) (name runtest)
(deps jbuild.mlt (deps (:t jbuild.mlt)
(glob_files %{project_root}/src/.dune.objs/*.cmi) (glob_files %{project_root}/src/.dune.objs/*.cmi)
(glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi)) (glob_files %{project_root}/src/stdune/.stdune.objs/*.cmi))
(action (chdir %{project_root} (action (chdir %{project_root}
(progn (progn
(run %{exe:expect_test.exe} %{first-dep}) (run %{exe:expect_test.exe} %{t})
(diff? %{first-dep} %{first-dep}.corrected))))) (diff? %{t} %{t}.corrected)))))

View File

@ -1,8 +1,3 @@
(executable (test
(name gh637) (name gh637)
(libraries ocaml_config)) (libraries ocaml_config))
(alias
(name runtest)
(deps ./gh637.exe)
(action (run %{first-dep})))