Skip to content

Commit

Permalink
Support (package) in (mdx)
Browse files Browse the repository at this point in the history
This adds a (package) field to (mdx) with the usual semantics.

The syntax is not ideal since (packages) is already supported as sugar
to specify dependencies.

Closes ocaml#3756

Signed-off-by: Etienne Millon <me@emillon.org>
  • Loading branch information
emillon committed Jun 4, 2021
1 parent 9ef424f commit 2a9a067
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 77 deletions.
9 changes: 9 additions & 0 deletions src/dune_rules/dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2074,6 +2074,14 @@ module Generate_sites_module = struct
{ loc; module_; sourceroot; relocatable; sites; plugins })
end

module Package_proxy = struct
type Stanza.t +=
| T of
{ package : Package.t option
; stanza : Stanza.t
}
end

type Stanza.t +=
| Library of Library.t
| Foreign_library of Foreign.Library.t
Expand Down Expand Up @@ -2264,6 +2272,7 @@ let stanza_package = function
| Tests { package = Some package; _ } ->
Some package
| Coq_stanza.Theory.T { package = Some package; _ } -> Some package
| Package_proxy.T { package; _ } -> package
| _ -> None

type t =
Expand Down
13 changes: 13 additions & 0 deletions src/dune_rules/dune_file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,19 @@ module Generate_sites_module : sig
}
end

module Package_proxy : sig
(** A wrapper to implement the (package) field on a stanza that does not
support it. This also helps with dependency cycles since [stanza_package]
(used to filter irrelevant stanzas) is part of [Dune_file] and can not
depend on all stanzas. *)

type Stanza.t +=
| T of
{ package : Package.t option
; stanza : Stanza.t
}
end

type Stanza.t +=
| Library of Library.t
| Foreign_library of Foreign.Library.t
Expand Down
154 changes: 79 additions & 75 deletions src/dune_rules/gen_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -68,86 +68,90 @@ end = struct
let of_stanza stanza ~sctx ~src_dir ~ctx_dir ~scope ~dir_contents ~expander
~files_to_install =
let dir = ctx_dir in
match stanza with
| Toplevel toplevel ->
let+ () = Toplevel_rules.setup ~sctx ~dir ~toplevel in
empty_none
| Library lib
when Lib.DB.available (Scope.libs scope) (Dune_file.Library.best_name lib)
->
let+ cctx, merlin =
Lib_rules.rules lib ~sctx ~dir ~scope ~dir_contents ~expander
in
{ merlin = Some merlin
; cctx = Some (lib.buildable.loc, cctx)
; js = None
; source_dirs = None
}
| Foreign_library lib ->
let+ () =
Lib_rules.foreign_rules lib ~sctx ~dir ~dir_contents ~expander
in
empty_none
| Executables exes -> (
Expander.eval_blang expander exes.enabled_if >>= function
| false -> Memo.Build.return empty_none
| true ->
let* () =
Memo.Build.Option.iter exes.install_conf ~f:files_to_install
let rec go stanza =
match stanza with
| Toplevel toplevel ->
let+ () = Toplevel_rules.setup ~sctx ~dir ~toplevel in
empty_none
| Library lib
when Lib.DB.available (Scope.libs scope)
(Dune_file.Library.best_name lib) ->
let+ cctx, merlin =
Lib_rules.rules lib ~sctx ~dir ~scope ~dir_contents ~expander
in
{ merlin = Some merlin
; cctx = Some (lib.buildable.loc, cctx)
; js = None
; source_dirs = None
}
| Foreign_library lib ->
let+ () =
Lib_rules.foreign_rules lib ~sctx ~dir ~dir_contents ~expander
in
empty_none
| Executables exes -> (
Expander.eval_blang expander exes.enabled_if >>= function
| false -> Memo.Build.return empty_none
| true ->
let* () =
Memo.Build.Option.iter exes.install_conf ~f:files_to_install
in
let+ cctx, merlin =
Exe_rules.rules exes ~sctx ~dir ~scope ~expander ~dir_contents
in
{ merlin = Some merlin
; cctx = Some (exes.buildable.loc, cctx)
; js =
Some
(List.concat_map exes.names ~f:(fun (_, exe) ->
List.map
[ exe ^ ".bc.js"; exe ^ ".bc.runtime.js" ]
~f:(Path.Build.relative dir)))
; source_dirs = None
})
| Alias alias ->
let+ () = Simple_rules.alias sctx alias ~dir ~expander in
empty_none
| Tests tests ->
let+ cctx, merlin =
Exe_rules.rules exes ~sctx ~dir ~scope ~expander ~dir_contents
Test_rules.rules tests ~sctx ~dir ~scope ~expander ~dir_contents
in
{ merlin = Some merlin
; cctx = Some (exes.buildable.loc, cctx)
; js =
Some
(List.concat_map exes.names ~f:(fun (_, exe) ->
List.map
[ exe ^ ".bc.js"; exe ^ ".bc.runtime.js" ]
~f:(Path.Build.relative dir)))
; cctx = Some (tests.exes.buildable.loc, cctx)
; js = None
; source_dirs = None
})
| Alias alias ->
let+ () = Simple_rules.alias sctx alias ~dir ~expander in
empty_none
| Tests tests ->
let+ cctx, merlin =
Test_rules.rules tests ~sctx ~dir ~scope ~expander ~dir_contents
in
{ merlin = Some merlin
; cctx = Some (tests.exes.buildable.loc, cctx)
; js = None
; source_dirs = None
}
| Copy_files { files = glob; _ } ->
let* source_dirs =
let loc = String_with_vars.loc glob in
let+ src_glob = Expander.No_deps.expand_str expander glob in
if Filename.is_relative src_glob then
Some
(Path.Source.relative src_dir src_glob ~error_loc:loc
|> Path.Source.parent_exn)
else
None
in
Memo.Build.return { merlin = None; cctx = None; js = None; source_dirs }
| Install i ->
let+ () = files_to_install i in
empty_none
| Plugin p ->
let+ () = Plugin_rules.setup_rules ~sctx ~dir p in
empty_none
| Cinaps.T cinaps ->
let+ () = Cinaps.gen_rules sctx cinaps ~dir ~scope in
empty_none
| Mdx.T mdx -> (
Expander.eval_blang expander (Mdx.enabled_if mdx) >>= function
| false -> Memo.Build.return empty_none
| true ->
let+ () = Mdx.gen_rules ~sctx ~dir ~expander mdx in
empty_none)
| _ -> Memo.Build.return empty_none
}
| Copy_files { files = glob; _ } ->
let* source_dirs =
let loc = String_with_vars.loc glob in
let+ src_glob = Expander.No_deps.expand_str expander glob in
if Filename.is_relative src_glob then
Some
(Path.Source.relative src_dir src_glob ~error_loc:loc
|> Path.Source.parent_exn)
else
None
in
Memo.Build.return { merlin = None; cctx = None; js = None; source_dirs }
| Install i ->
let+ () = files_to_install i in
empty_none
| Plugin p ->
let+ () = Plugin_rules.setup_rules ~sctx ~dir p in
empty_none
| Cinaps.T cinaps ->
let+ () = Cinaps.gen_rules sctx cinaps ~dir ~scope in
empty_none
| Mdx.T mdx -> (
Expander.eval_blang expander (Mdx.enabled_if mdx) >>= function
| false -> Memo.Build.return empty_none
| true ->
let+ () = Mdx.gen_rules ~sctx ~dir ~expander mdx in
empty_none)
| Package_proxy.T { stanza; _ } -> go stanza
| _ -> Memo.Build.return empty_none
in
go stanza

let of_stanzas stanzas ~cctxs ~sctx ~src_dir ~ctx_dir ~scope ~dir_contents
~expander ~files_to_install =
Expand Down
11 changes: 9 additions & 2 deletions src/dune_rules/mdx.ml
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,21 @@ let decode =
and+ preludes = field ~default:[] "preludes" (repeat Prelude.decode)
and+ enabled_if =
Enabled_if.decode ~allowed_vars:Any ~since:(Some (2, 9)) ()
and+ package =
Stanza_common.Pkg.field_opt ()
~check:(Dune_lang.Syntax.since Stanza.syntax (2, 9))
in
{ loc; files; packages; preludes; enabled_if })
(package, { loc; files; packages; preludes; enabled_if }))

let () =
let open Dune_lang.Decoder in
let decode = Dune_lang.Syntax.since Stanza.syntax (2, 4) >>> decode in
Dune_project.Extension.register_simple syntax
(return [ ("mdx", decode >>| fun x -> [ T x ]) ])
(return
[ ( "mdx"
, decode >>| fun (package, x) ->
[ Dune_file.Package_proxy.T { package; stanza = T x } ] )
])

(** Returns the list of files (in _build) to be passed to mdx for the given
stanza and context *)
Expand Down
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```ocaml
# let x = 1;;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```ocaml
# let x = 1;;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(mdx
(files doc-a.md)
(package a))

(mdx
(files doc-b.md)
(package b))
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(lang dune 2.8)
(using mdx 0.1)
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions test/blackbox-tests/test-cases/mdx-stanza.t/package/doc-a.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```ocaml
# let x = 1;;
```
3 changes: 3 additions & 0 deletions test/blackbox-tests/test-cases/mdx-stanza.t/package/doc-b.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```ocaml
# let x = 1;;
```
7 changes: 7 additions & 0 deletions test/blackbox-tests/test-cases/mdx-stanza.t/package/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(mdx
(files doc-a.md)
(package a))

(mdx
(files doc-b.md)
(package b))
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(lang dune 2.9)
(using mdx 0.1)
20 changes: 20 additions & 0 deletions test/blackbox-tests/test-cases/mdx-stanza.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,23 @@ The mdx stanza supports (enabled_if):
Error: 'enabled_if' is only available since version 2.9 of the dune language.
Please update your dune-project file to have (lang dune 2.9).
[1]
The mdx stanza supports (package):
$ dune runtest --root package --only-packages b
Entering directory 'package'
File "doc-b.md", line 1, characters 0-0:
Error: Files _build/default/doc-b.md and
_build/default/.mdx/doc-b.md.corrected differ.
[1]
(package) needs a recent (lang dune):
$ dune runtest --root package-old-lang-dune --only-packages b
Entering directory 'package-old-lang-dune'
File "dune", line 3, characters 1-12:
3 | (package a))
^^^^^^^^^^^
Error: 'package' is only available since version 2.9 of the dune language.
Please update your dune-project file to have (lang dune 2.9).
[1]

0 comments on commit 2a9a067

Please sign in to comment.