From d1d7672e96e25d51aea1a2098aa81283c135aa31 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Mon, 27 Aug 2018 18:36:05 +0300 Subject: [PATCH 01/17] wrapped transition mode Signed-off-by: Rudi Grinberg --- src/compilation_context.ml | 3 + src/compilation_context.mli | 2 + src/dir_contents.ml | 22 +++++-- src/dir_contents.mli | 1 + src/dune_file.ml | 25 ++++++- src/dune_file.mli | 10 ++- src/install_rules.ml | 7 +- src/js_of_ocaml_rules.ml | 8 +-- src/lib_rules.ml | 65 +++++++++++++++---- src/module.ml | 36 ++++++++++ src/module.mli | 4 ++ src/ocamldep.ml | 17 +++++ src/ocamldep.mli | 5 ++ src/stanza.ml | 2 +- test/blackbox-tests/dune.inc | 14 +++- .../test-cases/dune-project-edition/run.t | 6 +- .../test-cases/no-name-field/run.t | 2 +- .../test-cases/wrapped-transition/dune | 7 ++ .../wrapped-transition/dune-project | 1 + .../test-cases/wrapped-transition/fooexe.ml | 4 ++ .../test-cases/wrapped-transition/lib/bar.ml | 1 + .../test-cases/wrapped-transition/lib/dune | 3 + .../test-cases/wrapped-transition/lib/foo.ml | 1 + .../test-cases/wrapped-transition/run.t | 6 ++ 24 files changed, 216 insertions(+), 36 deletions(-) create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/dune create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/dune-project create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/lib/bar.ml create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/lib/dune create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/lib/foo.ml create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/run.t diff --git a/src/compilation_context.ml b/src/compilation_context.ml index 78883c1d..6b39af76 100644 --- a/src/compilation_context.ml +++ b/src/compilation_context.ml @@ -105,3 +105,6 @@ let for_alias_module t = ; includes = Includes.empty ; alias_module = None } + +let set_modules t modules = + { t with modules } diff --git a/src/compilation_context.mli b/src/compilation_context.mli index 529239e8..40cde805 100644 --- a/src/compilation_context.mli +++ b/src/compilation_context.mli @@ -48,3 +48,5 @@ val includes : t -> string list Arg_spec.t Cm_kind.Dict.t val preprocessing : t -> Preprocessing.t val no_keep_locs : t -> bool val opaque : t -> bool + +val set_modules : t -> Module.t Module.Name.Map.t -> t diff --git a/src/dir_contents.ml b/src/dir_contents.ml index bf565198..3aaf9742 100644 --- a/src/dir_contents.ml +++ b/src/dir_contents.ml @@ -168,6 +168,7 @@ module Library_modules : sig { modules : Module.t Module.Name.Map.t ; alias_module : Module.t option ; main_module_name : Module.Name.t + ; deprecated : Module.t Module.Name.Map.t } val make : Library.t -> dir:Path.t -> Module.t Module.Name.Map.t -> t @@ -176,25 +177,32 @@ end = struct { modules : Module.t Module.Name.Map.t ; alias_module : Module.t option ; main_module_name : Module.Name.t + ; deprecated : Module.t Module.Name.Map.t } let make (lib : Library.t) ~dir (modules : Module.t Module.Name.Map.t) = let main_module_name = Module.Name.of_string (Lib_name.Local.to_string lib.name) in - let modules = - if not lib.wrapped then - modules - else + let (modules, deprecated) = + let wrap_modules modules = let open Module.Name.Infix in - Module.Name.Map.map modules ~f:(fun m -> + Module.Name.Map.map modules ~f:(fun (m : Module.t) -> if m.name = main_module_name then m else Module.with_wrapper m ~libname:lib.name) + in + match lib.wrapped with + | Simple false -> (modules, Module.Name.Map.empty) + | Simple true -> (wrap_modules modules, Module.Name.Map.empty) + | Yes_with_transition _ -> + ( wrap_modules modules + , Module.Name.Map.map ~f:Module.deprecate modules + ) in let alias_module = let lib_name = Lib_name.Local.to_string lib.name in - if not lib.wrapped || + if not (Library.Wrapped.to_bool lib.wrapped) || (Module.Name.Map.cardinal modules = 1 && Module.Name.Map.mem modules main_module_name) then None @@ -215,7 +223,7 @@ end = struct (Path.relative dir (lib_name ^ ".ml-gen"))) ~obj_name:lib_name) in - { modules; alias_module; main_module_name } + { modules; alias_module; main_module_name; deprecated } end module Executables_modules = struct diff --git a/src/dir_contents.mli b/src/dir_contents.mli index 09833d17..ca96ce43 100644 --- a/src/dir_contents.mli +++ b/src/dir_contents.mli @@ -21,6 +21,7 @@ module Library_modules : sig { modules : Module.t Module.Name.Map.t ; alias_module : Module.t option ; main_module_name : Module.Name.t + ; deprecated : Module.t Module.Name.Map.t } end diff --git a/src/dune_file.ml b/src/dune_file.ml index 1bb6a9c4..b31e7bf6 100644 --- a/src/dune_file.ml +++ b/src/dune_file.ml @@ -859,6 +859,25 @@ module Library = struct syntax end + module Wrapped = struct + type t = + | Simple of bool + | Yes_with_transition of string + + let dparse = + if_list + ~then_:( + Syntax.since Stanza.syntax (1, 2) >>= fun () -> + sum ["transition_until", string >>| fun x -> Yes_with_transition x]) + ~else_:(bool >>| fun w -> Simple w) + + let field = field "wrapped" ~default:(Simple true) dparse + + let to_bool = function + | Simple b -> b + | Yes_with_transition _ -> true + end + type t = { name : Lib_name.Local.t ; public : Public_lib.t option @@ -875,7 +894,7 @@ module Library = struct ; c_library_flags : Ordered_set_lang.Unexpanded.t ; self_build_stubs_archive : string option ; virtual_deps : (Loc.t * Lib_name.t) list - ; wrapped : bool + ; wrapped : Wrapped.t ; optional : bool ; buildable : Buildable.t ; dynlink : Dynlink_supported.t @@ -908,7 +927,7 @@ module Library = struct field "virtual_deps" (list (located Lib_name.dparse)) ~default:[] and modes = field "modes" Mode_conf.Set.dparse ~default:Mode_conf.Set.default and kind = field "kind" Kind.dparse ~default:Kind.Normal - and wrapped = field "wrapped" bool ~default:true + and wrapped = Wrapped.field and optional = field_b "optional" and self_build_stubs_archive = field "self_build_stubs_archive" (option string) ~default:None @@ -932,7 +951,7 @@ module Library = struct let open Syntax.Version.Infix in match name, public with | Some n, _ -> - Lib_name.Local.validate n ~wrapped + Lib_name.Local.validate n ~wrapped:(Wrapped.to_bool wrapped) | None, Some { name = (loc, name) ; _ } -> if dune_version >= (1, 1) then match Lib_name.to_local name with diff --git a/src/dune_file.mli b/src/dune_file.mli index 0823c813..c462c5d0 100644 --- a/src/dune_file.mli +++ b/src/dune_file.mli @@ -216,6 +216,14 @@ module Library : sig | Ppx_rewriter end + module Wrapped : sig + type t = + | Simple of bool + | Yes_with_transition of string + + val to_bool : t -> bool + end + type t = { name : Lib_name.Local.t ; public : Public_lib.t option @@ -232,7 +240,7 @@ module Library : sig ; c_library_flags : Ordered_set_lang.Unexpanded.t ; self_build_stubs_archive : string option ; virtual_deps : (Loc.t * Lib_name.t) list - ; wrapped : bool + ; wrapped : Wrapped.t ; optional : bool ; buildable : Buildable.t ; dynlink : Dynlink_supported.t diff --git a/src/install_rules.ml b/src/install_rules.ml index c832d925..31620633 100644 --- a/src/install_rules.ml +++ b/src/install_rules.ml @@ -138,7 +138,8 @@ module Gen(P : Params) = struct let if_ cond l = if cond then l else [] in let files = let modules = - let { Dir_contents.Library_modules.modules; alias_module; _ } = + let { Dir_contents.Library_modules.modules; alias_module; deprecated + ; main_module_name = _ } = Dir_contents.modules_of_library dir_contents ~name:(Library.best_name lib) in @@ -147,7 +148,9 @@ module Gen(P : Params) = struct | None -> modules | Some m -> Module.Name.Map.add modules m.name m in - Module.Name.Map.values modules + List.rev_append + (Module.Name.Map.values modules) + (Module.Name.Map.values deprecated) in let virtual_library = Library.is_virtual lib in List.concat diff --git a/src/js_of_ocaml_rules.ml b/src/js_of_ocaml_rules.ml index 3d13a464..76bf7943 100644 --- a/src/js_of_ocaml_rules.ml +++ b/src/js_of_ocaml_rules.ml @@ -113,15 +113,15 @@ let link_rule cc ~runtime ~target = ; Arg_spec.Dyn get_all ] -let build_cm cc ~(js_of_ocaml:Dune_file.Js_of_ocaml.t) ~src ~target = - let sctx = Compilation_context.super_context cc in - let dir = Compilation_context.dir cc in +let build_cm cctx ~(js_of_ocaml:Dune_file.Js_of_ocaml.t) ~src ~target = + let sctx = Compilation_context.super_context cctx in + let dir = Compilation_context.dir cctx in if separate_compilation_enabled sctx then let itarget = Path.extend_basename src ~suffix:".js" in let spec = Arg_spec.Dep src in let flags = - let scope = Compilation_context.scope cc in + let scope = Compilation_context.scope cctx in SC.expand_and_eval_set sctx ~scope ~dir js_of_ocaml.flags ~standard:(Build.return (standard sctx)) in diff --git a/src/lib_rules.ml b/src/lib_rules.ml index 2db4c20a..255d0174 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -120,6 +120,37 @@ module Gen (P : Install_rules.Params) = struct ~sandbox:alias_module_build_sandbox ~dep_graphs:(Ocamldep.Dep_graphs.dummy m) + let build_deprecated_modules (lib : Library.t) + cctx + ~modules + ~js_of_ocaml + ~dynlink + ~(deprecated : Module.t Module.Name.Map.t) = + let lib_name = String.capitalize (Lib_name.Local.to_string lib.name) in + let transition_until = + match lib.wrapped with + | Simple _ -> "" (* will never be accessed anyway *) + | Yes_with_transition r -> r + in + Module.Name.Map.iteri deprecated ~f:(fun name m -> + let contents = + let name = Module.Name.to_string name in + let hidden_name = sprintf "%s__%s" lib_name name in + let real_name = sprintf "%s.%s" lib_name name in + sprintf "include %s [@@deprecated \"%s is not guaranteed past %s. \ + Use %s instead.\"]" + hidden_name name transition_until real_name + in + let source_path = Option.value_exn (Module.file m Impl) in + Build.return contents + >>> Build.write_file_dyn source_path + |> SC.add_rule sctx + ); + let dep_graphs = + Ocamldep.Dep_graphs.deprecated ~modules ~deprecated in + let cctx = Compilation_context.set_modules cctx deprecated in + Module_compilation.build_modules cctx ~js_of_ocaml ~dynlink ~dep_graphs + let build_c_file (lib : Library.t) ~scope ~dir ~includes (src, dst) = SC.add_rule sctx (SC.expand_and_eval_set sctx ~scope ~dir lib.c_flags @@ -293,7 +324,7 @@ module Gen (P : Install_rules.Params) = struct in let flags = SC.ocaml_flags sctx ~scope ~dir lib.buildable in let { Dir_contents.Library_modules. - modules; main_module_name; alias_module } = + modules; main_module_name; alias_module ; deprecated } = Dir_contents.modules_of_library dir_contents ~name:(Library.best_name lib) in let source_modules = modules in @@ -318,7 +349,7 @@ module Gen (P : Install_rules.Params) = struct in let lib_interface_module = - if lib.wrapped then + if Library.Wrapped.to_bool lib.wrapped then Module.Name.Map.find modules main_module_name else None @@ -340,12 +371,16 @@ module Gen (P : Install_rules.Params) = struct ~opaque in - let dep_graphs = Ocamldep.rules cctx in - let dynlink = Dynlink_supported.get lib.dynlink ctx.supports_shared_libraries in let js_of_ocaml = lib.buildable.js_of_ocaml in + + build_deprecated_modules lib cctx ~dynlink ~js_of_ocaml + ~deprecated ~modules; + + let dep_graphs = Ocamldep.rules cctx in + Module_compilation.build_modules cctx ~js_of_ocaml ~dynlink ~dep_graphs; Option.iter alias_module @@ -355,15 +390,17 @@ module Gen (P : Install_rules.Params) = struct if Library.has_stubs lib then build_stubs lib ~dir ~scope ~requires ~dir_contents; + let add_cms ~cm_kind ~init = Module.Name.Map.fold ~init ~f:(fun m acc -> + match Module.cm_file m ~obj_dir cm_kind with + | None -> acc + | Some fn -> Path.Set.add acc fn) + in List.iter Cm_kind.all ~f:(fun cm_kind -> - let files = - Module.Name.Map.fold modules ~init:Path.Set.empty ~f:(fun m acc -> - match Module.cm_file m ~obj_dir cm_kind with - | None -> acc - | Some fn -> Path.Set.add acc fn) - in + let files = add_cms ~cm_kind ~init:Path.Set.empty modules in + let files = add_cms ~cm_kind ~init:files deprecated in SC.Libs.setup_file_deps_alias sctx ~dir lib ~ext:(Cm_kind.ext cm_kind) files); + SC.Libs.setup_file_deps_group_alias sctx ~dir lib ~exts:[".cmi"; ".cmx"]; SC.Libs.setup_file_deps_alias sctx ~dir lib ~ext:".h" (List.map lib.install_c_headers ~f:(fun header -> @@ -377,12 +414,16 @@ module Gen (P : Install_rules.Params) = struct else acc) in + let deprecated_modules = Module.Name.Map.values deprecated in + (* deprecated modules have implementations so we can just append them *) let top_sorted_modules = Ocamldep.Dep_graph.top_closed_implementations dep_graphs.impl modules + >>^ fun modules -> modules @ deprecated_modules in - List.iter Mode.all ~f:(fun mode -> + (let modules = modules @ deprecated_modules in + List.iter Mode.all ~f:(fun mode -> build_lib lib ~scope ~flags ~dir ~obj_dir ~mode ~top_sorted_modules - ~modules)); + ~modules))); (* Build *.cma.js *) SC.add_rules sctx ( let src = Library.archive lib ~dir ~ext:(Mode.compiled_lib_ext Mode.Byte) in diff --git a/src/module.ml b/src/module.ml index b06c6e7f..c7d26694 100644 --- a/src/module.ml +++ b/src/module.ml @@ -32,6 +32,12 @@ end module Syntax = struct type t = OCaml | Reason + + let to_sexp = + let open Sexp.To_sexp in + function + | OCaml -> string "OCaml" + | Reason -> string "Reason" end module File = struct @@ -41,6 +47,13 @@ module File = struct } let make syntax path = { syntax; path } + + let to_sexp { path; syntax } = + let open Sexp.To_sexp in + record + [ "path", Path.to_sexp path + ; "syntax", Syntax.to_sexp syntax + ] end type t = @@ -140,3 +153,26 @@ let dir t = Path.parent_exn file.path let set_pp t pp = { t with pp } + +let to_sexp { name; impl; intf; obj_name ; pp } = + let open Sexp.To_sexp in + record + [ "name", Name.to_sexp name + ; "obj_name", string obj_name + ; "impl", (option File.to_sexp) impl + ; "intf", (option File.to_sexp) intf + ; "pp", (option string) (Option.map ~f:(fun _ -> "has pp") pp) + ] + +let deprecate t = + { t with + intf = None + ; impl = + Some ( + let impl = Option.value_exn t.impl in + let (base, _) = Path.split_extension impl.path in + { syntax = OCaml + ; path = Path.extend_basename base ~suffix:".ml-gen" + } + ) + } diff --git a/src/module.mli b/src/module.mli index 4ac943b9..4e3201da 100644 --- a/src/module.mli +++ b/src/module.mli @@ -92,3 +92,7 @@ val with_wrapper : t -> libname:Lib_name.Local.t -> t val map_files : t -> f:(Ml_kind.t -> File.t -> File.t) -> t val set_pp : t -> (unit, string list) Build.t option -> t + +val to_sexp : t Sexp.To_sexp.t + +val deprecate : t -> t diff --git a/src/ocamldep.ml b/src/ocamldep.ml index 9d60073c..1a5d134d 100644 --- a/src/ocamldep.ml +++ b/src/ocamldep.ml @@ -51,6 +51,20 @@ module Dep_graph = struct { dir = Path.root ; per_module = Module.Name.Map.singleton m.name (Build.return []) } + + let deprecated ~modules ~deprecated = + { dir = Path.root + ; per_module = Module.Name.Map.merge deprecated modules ~f:(fun _ d m -> + match d, m with + | None, None -> assert false + | Some deprecated, None -> + Exn.code_error "deprecated module needs counterpart" + [ "deprecated", Module.to_sexp deprecated + ] + | None, Some _ -> None + | Some _, Some m -> Some (Build.return [m]) + ) + } end module Dep_graphs = struct @@ -58,6 +72,9 @@ module Dep_graphs = struct let dummy m = Ml_kind.Dict.make_both (Dep_graph.dummy m) + + let deprecated ~modules ~deprecated = + Ml_kind.Dict.make_both (Dep_graph.deprecated ~modules ~deprecated) end let parse_module_names ~(unit : Module.t) ~modules words = diff --git a/src/ocamldep.mli b/src/ocamldep.mli index 653f4904..83028590 100644 --- a/src/ocamldep.mli +++ b/src/ocamldep.mli @@ -18,6 +18,11 @@ module Dep_graphs : sig type t = Dep_graph.t Ml_kind.Dict.t val dummy : Module.t -> t + + val deprecated + : modules:Module.t Module.Name.Map.t + -> deprecated:Module.t Module.Name.Map.t + -> t end (** Generate ocamldep rules for all the modules in the context. *) diff --git a/src/stanza.ml b/src/stanza.ml index e4b92120..0d60784b 100644 --- a/src/stanza.ml +++ b/src/stanza.ml @@ -9,7 +9,7 @@ end let syntax = Syntax.create ~name:"dune" ~desc:"the dune language" [ (0, 0) (* Jbuild syntax *) - ; (1, 1) + ; (1, 2) ] module File_kind = struct diff --git a/test/blackbox-tests/dune.inc b/test/blackbox-tests/dune.inc index be56c3da..1f5680f3 100644 --- a/test/blackbox-tests/dune.inc +++ b/test/blackbox-tests/dune.inc @@ -836,6 +836,14 @@ test-cases/workspaces (progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))) +(alias + (name wrapped-transition) + (deps (package dune) (source_tree test-cases/wrapped-transition)) + (action + (chdir + test-cases/wrapped-transition + (progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))) + (alias (name runtest) (deps @@ -938,7 +946,8 @@ (alias utop-default) (alias variants) (alias windows-diff) - (alias workspaces))) + (alias workspaces) + (alias wrapped-transition))) (alias (name runtest-no-deps) @@ -1029,7 +1038,8 @@ (alias utop-default) (alias variants) (alias windows-diff) - (alias workspaces))) + (alias workspaces) + (alias wrapped-transition))) (alias (name runtest-disabled) (deps (alias envs-and-contexts))) diff --git a/test/blackbox-tests/test-cases/dune-project-edition/run.t b/test/blackbox-tests/test-cases/dune-project-edition/run.t index 311d7d88..2fe9158f 100644 --- a/test/blackbox-tests/test-cases/dune-project-edition/run.t +++ b/test/blackbox-tests/test-cases/dune-project-edition/run.t @@ -3,9 +3,9 @@ $ mkdir src $ echo '(alias (name runtest) (action (progn)))' > src/dune $ dune build - Info: creating file dune-project with this contents: (lang dune 1.1) + Info: creating file dune-project with this contents: (lang dune 1.2) $ cat dune-project - (lang dune 1.1) + (lang dune 1.2) Test that using menhir automatically update the dune-project file @@ -13,5 +13,5 @@ Test that using menhir automatically update the dune-project file $ dune build Info: appending this line to dune-project: (using menhir 1.0) $ cat dune-project - (lang dune 1.1) + (lang dune 1.2) (using menhir 1.0) diff --git a/test/blackbox-tests/test-cases/no-name-field/run.t b/test/blackbox-tests/test-cases/no-name-field/run.t index bbe69b55..449e053d 100644 --- a/test/blackbox-tests/test-cases/no-name-field/run.t +++ b/test/blackbox-tests/test-cases/no-name-field/run.t @@ -37,7 +37,7 @@ there's only a public name which is invalid, but sine the library is unwrapped, it's just a warning $ dune build --root public-name-invalid-wrapped-false - Info: creating file dune-project with this contents: (lang dune 1.1) + Info: creating file dune-project with this contents: (lang dune 1.2) File "dune", line 3, characters 14-21: (public_name foo.bar)) ^^^^^^^ diff --git a/test/blackbox-tests/test-cases/wrapped-transition/dune b/test/blackbox-tests/test-cases/wrapped-transition/dune new file mode 100644 index 00000000..ce2f67cb --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/dune @@ -0,0 +1,7 @@ +(executable + (name fooexe) + (libraries mylib)) + +(alias + (name default) + (action (run ./fooexe.exe))) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/wrapped-transition/dune-project b/test/blackbox-tests/test-cases/wrapped-transition/dune-project new file mode 100644 index 00000000..47f0de83 --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/dune-project @@ -0,0 +1 @@ +(lang dune 1.2) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml b/test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml new file mode 100644 index 00000000..05f52bc8 --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml @@ -0,0 +1,4 @@ +Mylib.Bar.run ();; +Mylib.Foo.run ();; +Bar.run ();; +Foo.run ();; diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/bar.ml b/test/blackbox-tests/test-cases/wrapped-transition/lib/bar.ml new file mode 100644 index 00000000..75e45f5d --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/bar.ml @@ -0,0 +1 @@ +let run () = print_endline "bar" diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/dune b/test/blackbox-tests/test-cases/wrapped-transition/lib/dune new file mode 100644 index 00000000..019f3b0c --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/dune @@ -0,0 +1,3 @@ +(library + (name mylib) + (wrapped (transition_until "2020-20-20"))) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/foo.ml b/test/blackbox-tests/test-cases/wrapped-transition/lib/foo.ml new file mode 100644 index 00000000..66de3158 --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/foo.ml @@ -0,0 +1 @@ +let run () = print_endline "foo" diff --git a/test/blackbox-tests/test-cases/wrapped-transition/run.t b/test/blackbox-tests/test-cases/wrapped-transition/run.t new file mode 100644 index 00000000..2e9a5d3b --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/run.t @@ -0,0 +1,6 @@ + $ dune build + fooexe alias default + bar + foo + bar + foo From 492286ba120b06860d75350caff8f082a0dbe9f8 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 29 Aug 2018 13:12:18 +0300 Subject: [PATCH 02/17] Don't hardcode the transition message to be date based Signed-off-by: Rudi Grinberg --- src/dune_file.ml | 2 +- src/lib_rules.ml | 7 +++---- test/blackbox-tests/test-cases/wrapped-transition/lib/dune | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/dune_file.ml b/src/dune_file.ml index b31e7bf6..7421d4b6 100644 --- a/src/dune_file.ml +++ b/src/dune_file.ml @@ -868,7 +868,7 @@ module Library = struct if_list ~then_:( Syntax.since Stanza.syntax (1, 2) >>= fun () -> - sum ["transition_until", string >>| fun x -> Yes_with_transition x]) + sum ["transition", string >>| fun x -> Yes_with_transition x]) ~else_:(bool >>| fun w -> Simple w) let field = field "wrapped" ~default:(Simple true) dparse diff --git a/src/lib_rules.ml b/src/lib_rules.ml index 255d0174..7deb093c 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -127,7 +127,7 @@ module Gen (P : Install_rules.Params) = struct ~dynlink ~(deprecated : Module.t Module.Name.Map.t) = let lib_name = String.capitalize (Lib_name.Local.to_string lib.name) in - let transition_until = + let transition_message = match lib.wrapped with | Simple _ -> "" (* will never be accessed anyway *) | Yes_with_transition r -> r @@ -137,9 +137,8 @@ module Gen (P : Install_rules.Params) = struct let name = Module.Name.to_string name in let hidden_name = sprintf "%s__%s" lib_name name in let real_name = sprintf "%s.%s" lib_name name in - sprintf "include %s [@@deprecated \"%s is not guaranteed past %s. \ - Use %s instead.\"]" - hidden_name name transition_until real_name + sprintf "include %s [@@deprecated \"%s. Use %s instead.\"]" + hidden_name transition_message real_name in let source_path = Option.value_exn (Module.file m Impl) in Build.return contents diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/dune b/test/blackbox-tests/test-cases/wrapped-transition/lib/dune index 019f3b0c..29516cc2 100644 --- a/test/blackbox-tests/test-cases/wrapped-transition/lib/dune +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/dune @@ -1,3 +1,3 @@ (library (name mylib) - (wrapped (transition_until "2020-20-20"))) \ No newline at end of file + (wrapped (transition "Will be removed past 2020-20-20"))) \ No newline at end of file From f9ad608e8cf9b033810410c7a532d090c367ef56 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 29 Aug 2018 13:14:51 +0300 Subject: [PATCH 03/17] Fix deprecation attribute for transition modules Signed-off-by: Rudi Grinberg --- src/lib_rules.ml | 4 ++-- .../test-cases/wrapped-transition/run.t | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/lib_rules.ml b/src/lib_rules.ml index 7deb093c..6f5abe3f 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -137,8 +137,8 @@ module Gen (P : Install_rules.Params) = struct let name = Module.Name.to_string name in let hidden_name = sprintf "%s__%s" lib_name name in let real_name = sprintf "%s.%s" lib_name name in - sprintf "include %s [@@deprecated \"%s. Use %s instead.\"]" - hidden_name transition_message real_name + sprintf {|[@@@deprecated "%s. Use %s instead."] include %s|} + transition_message real_name hidden_name in let source_path = Option.value_exn (Module.file m Impl) in Build.return contents diff --git a/test/blackbox-tests/test-cases/wrapped-transition/run.t b/test/blackbox-tests/test-cases/wrapped-transition/run.t index 2e9a5d3b..76b1fea0 100644 --- a/test/blackbox-tests/test-cases/wrapped-transition/run.t +++ b/test/blackbox-tests/test-cases/wrapped-transition/run.t @@ -1,6 +1,7 @@ - $ dune build - fooexe alias default - bar - foo - bar - foo + $ dune build 2>&1 | grep -v ocamlc + File "fooexe.ml", line 3, characters 0-7: + Error (warning 3): deprecated: module Bar + Will be removed past 2020-20-20. Use Mylib.Bar instead. + File "fooexe.ml", line 4, characters 0-7: + Error (warning 3): deprecated: module Foo + Will be removed past 2020-20-20. Use Mylib.Foo instead. From d0b937c25e18bd85b22ca829de7cf9187fd7abbe Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 29 Aug 2018 15:00:21 +0300 Subject: [PATCH 04/17] Use proper sum type wrapped.t Signed-off-by: Rudi Grinberg --- src/dune_file.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dune_file.ml b/src/dune_file.ml index 7421d4b6..924d42a6 100644 --- a/src/dune_file.ml +++ b/src/dune_file.ml @@ -865,11 +865,11 @@ module Library = struct | Yes_with_transition of string let dparse = - if_list - ~then_:( - Syntax.since Stanza.syntax (1, 2) >>= fun () -> - sum ["transition", string >>| fun x -> Yes_with_transition x]) - ~else_:(bool >>| fun w -> Simple w) + sum + [ "true", return (Simple true) + ; "false", return (Simple false) + ; "transition", string >>| fun x -> Yes_with_transition x + ] let field = field "wrapped" ~default:(Simple true) dparse From 8acca614dae94fed321b6cc43d030cd5cb49ec6d Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 29 Aug 2018 20:20:07 +0300 Subject: [PATCH 05/17] Use dedicated compilation context for deprecated modules Signed-off-by: Rudi Grinberg --- src/compilation_context.ml | 9 +++++++-- src/compilation_context.mli | 2 +- src/lib_rules.ml | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/compilation_context.ml b/src/compilation_context.ml index 6b39af76..9f572dc4 100644 --- a/src/compilation_context.ml +++ b/src/compilation_context.ml @@ -106,5 +106,10 @@ let for_alias_module t = ; alias_module = None } -let set_modules t modules = - { t with modules } +let for_deprecated t modules = + { t with + flags = Ocaml_flags.default ~profile:(SC.profile t.super_context) + ; includes = Includes.empty + ; alias_module = None + ; modules + } diff --git a/src/compilation_context.mli b/src/compilation_context.mli index 40cde805..a4bf2dc4 100644 --- a/src/compilation_context.mli +++ b/src/compilation_context.mli @@ -49,4 +49,4 @@ val preprocessing : t -> Preprocessing.t val no_keep_locs : t -> bool val opaque : t -> bool -val set_modules : t -> Module.t Module.Name.Map.t -> t +val for_deprecated : t -> Module.t Module.Name.Map.t -> t diff --git a/src/lib_rules.ml b/src/lib_rules.ml index 6f5abe3f..8f71bd7c 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -147,7 +147,7 @@ module Gen (P : Install_rules.Params) = struct ); let dep_graphs = Ocamldep.Dep_graphs.deprecated ~modules ~deprecated in - let cctx = Compilation_context.set_modules cctx deprecated in + let cctx = Compilation_context.for_deprecated cctx deprecated in Module_compilation.build_modules cctx ~js_of_ocaml ~dynlink ~dep_graphs let build_c_file (lib : Library.t) ~scope ~dir ~includes (src, dst) = From f47834d80b3fe6300bbd61ea0e0278b9f10136ec Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 29 Aug 2018 20:22:59 +0300 Subject: [PATCH 06/17] Add modules_without_implementation example to wrapped transition mode Signed-off-by: Rudi Grinberg --- src/module.ml | 13 +++++++++---- .../test-cases/wrapped-transition/fooexe.ml | 3 +++ .../test-cases/wrapped-transition/lib/dune | 1 + .../test-cases/wrapped-transition/lib/intf_only.mli | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/lib/intf_only.mli diff --git a/src/module.ml b/src/module.ml index c7d26694..2ef21c34 100644 --- a/src/module.ml +++ b/src/module.ml @@ -166,11 +166,16 @@ let to_sexp { name; impl; intf; obj_name ; pp } = let deprecate t = { t with - intf = None - ; impl = + impl = Some ( - let impl = Option.value_exn t.impl in - let (base, _) = Path.split_extension impl.path in + let path = + match t.intf, t.impl with + | Some _, Some impl + | None, Some impl -> impl.path + | Some intf, _ -> intf.path + | None, None -> assert false + in + let (base, _) = Path.split_extension path in { syntax = OCaml ; path = Path.extend_basename base ~suffix:".ml-gen" } diff --git a/test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml b/test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml index 05f52bc8..7ea5bdc1 100644 --- a/test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml +++ b/test/blackbox-tests/test-cases/wrapped-transition/fooexe.ml @@ -2,3 +2,6 @@ Mylib.Bar.run ();; Mylib.Foo.run ();; Bar.run ();; Foo.run ();; + +module Y : Mylib.Intf_only.S = struct end +module X : Intf_only.S = struct end diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/dune b/test/blackbox-tests/test-cases/wrapped-transition/lib/dune index 29516cc2..8cd2dab1 100644 --- a/test/blackbox-tests/test-cases/wrapped-transition/lib/dune +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/dune @@ -1,3 +1,4 @@ (library (name mylib) + (modules_without_implementation intf_only) (wrapped (transition "Will be removed past 2020-20-20"))) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/intf_only.mli b/test/blackbox-tests/test-cases/wrapped-transition/lib/intf_only.mli new file mode 100644 index 00000000..d63d6c08 --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/intf_only.mli @@ -0,0 +1 @@ +module type S = sig end From c8970ab9777e5f4c19676d14f55a30f4024f30c0 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 29 Aug 2018 21:20:31 +0300 Subject: [PATCH 07/17] Change terminology to wrapped_compat Signed-off-by: Rudi Grinberg --- src/compilation_context.ml | 2 +- src/compilation_context.mli | 2 +- src/dir_contents.ml | 12 ++++++++---- src/dir_contents.mli | 2 +- src/install_rules.ml | 7 +++++-- src/lib_rules.ml | 20 ++++++++++---------- src/ocamldep.ml | 12 ++++++------ src/ocamldep.mli | 4 ++-- 8 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/compilation_context.ml b/src/compilation_context.ml index 9f572dc4..d71550a8 100644 --- a/src/compilation_context.ml +++ b/src/compilation_context.ml @@ -106,7 +106,7 @@ let for_alias_module t = ; alias_module = None } -let for_deprecated t modules = +let for_wrapped_compat t modules = { t with flags = Ocaml_flags.default ~profile:(SC.profile t.super_context) ; includes = Includes.empty diff --git a/src/compilation_context.mli b/src/compilation_context.mli index a4bf2dc4..4460f90e 100644 --- a/src/compilation_context.mli +++ b/src/compilation_context.mli @@ -49,4 +49,4 @@ val preprocessing : t -> Preprocessing.t val no_keep_locs : t -> bool val opaque : t -> bool -val for_deprecated : t -> Module.t Module.Name.Map.t -> t +val for_wrapped_compat : t -> Module.t Module.Name.Map.t -> t diff --git a/src/dir_contents.ml b/src/dir_contents.ml index 3aaf9742..5401b8a3 100644 --- a/src/dir_contents.ml +++ b/src/dir_contents.ml @@ -168,7 +168,7 @@ module Library_modules : sig { modules : Module.t Module.Name.Map.t ; alias_module : Module.t option ; main_module_name : Module.Name.t - ; deprecated : Module.t Module.Name.Map.t + ; wrapped_compat : Module.t Module.Name.Map.t } val make : Library.t -> dir:Path.t -> Module.t Module.Name.Map.t -> t @@ -177,13 +177,13 @@ end = struct { modules : Module.t Module.Name.Map.t ; alias_module : Module.t option ; main_module_name : Module.Name.t - ; deprecated : Module.t Module.Name.Map.t + ; wrapped_compat : Module.t Module.Name.Map.t } let make (lib : Library.t) ~dir (modules : Module.t Module.Name.Map.t) = let main_module_name = Module.Name.of_string (Lib_name.Local.to_string lib.name) in - let (modules, deprecated) = + let (modules, wrapped_compat) = let wrap_modules modules = let open Module.Name.Infix in Module.Name.Map.map modules ~f:(fun (m : Module.t) -> @@ -223,7 +223,11 @@ end = struct (Path.relative dir (lib_name ^ ".ml-gen"))) ~obj_name:lib_name) in - { modules; alias_module; main_module_name; deprecated } + { modules + ; alias_module + ; main_module_name + ; wrapped_compat + } end module Executables_modules = struct diff --git a/src/dir_contents.mli b/src/dir_contents.mli index ca96ce43..3430d239 100644 --- a/src/dir_contents.mli +++ b/src/dir_contents.mli @@ -21,7 +21,7 @@ module Library_modules : sig { modules : Module.t Module.Name.Map.t ; alias_module : Module.t option ; main_module_name : Module.Name.t - ; deprecated : Module.t Module.Name.Map.t + ; wrapped_compat : Module.t Module.Name.Map.t } end diff --git a/src/install_rules.ml b/src/install_rules.ml index 31620633..d7cdf09e 100644 --- a/src/install_rules.ml +++ b/src/install_rules.ml @@ -138,7 +138,10 @@ module Gen(P : Params) = struct let if_ cond l = if cond then l else [] in let files = let modules = - let { Dir_contents.Library_modules.modules; alias_module; deprecated + let { Dir_contents.Library_modules. + modules + ; alias_module + ; wrapped_compat ; main_module_name = _ } = Dir_contents.modules_of_library dir_contents ~name:(Library.best_name lib) @@ -150,7 +153,7 @@ module Gen(P : Params) = struct in List.rev_append (Module.Name.Map.values modules) - (Module.Name.Map.values deprecated) + (Module.Name.Map.values wrapped_compat) in let virtual_library = Library.is_virtual lib in List.concat diff --git a/src/lib_rules.ml b/src/lib_rules.ml index 8f71bd7c..c35bfc44 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -120,19 +120,19 @@ module Gen (P : Install_rules.Params) = struct ~sandbox:alias_module_build_sandbox ~dep_graphs:(Ocamldep.Dep_graphs.dummy m) - let build_deprecated_modules (lib : Library.t) + let build_wrapped_compat_modules (lib : Library.t) cctx ~modules ~js_of_ocaml ~dynlink - ~(deprecated : Module.t Module.Name.Map.t) = + ~(wrapped_compat : Module.t Module.Name.Map.t) = let lib_name = String.capitalize (Lib_name.Local.to_string lib.name) in let transition_message = match lib.wrapped with | Simple _ -> "" (* will never be accessed anyway *) | Yes_with_transition r -> r in - Module.Name.Map.iteri deprecated ~f:(fun name m -> + Module.Name.Map.iteri wrapped_compat ~f:(fun name m -> let contents = let name = Module.Name.to_string name in let hidden_name = sprintf "%s__%s" lib_name name in @@ -146,8 +146,8 @@ module Gen (P : Install_rules.Params) = struct |> SC.add_rule sctx ); let dep_graphs = - Ocamldep.Dep_graphs.deprecated ~modules ~deprecated in - let cctx = Compilation_context.for_deprecated cctx deprecated in + Ocamldep.Dep_graphs.wrapped_compat ~modules ~wrapped_compat in + let cctx = Compilation_context.for_wrapped_compat cctx wrapped_compat in Module_compilation.build_modules cctx ~js_of_ocaml ~dynlink ~dep_graphs let build_c_file (lib : Library.t) ~scope ~dir ~includes (src, dst) = @@ -323,7 +323,7 @@ module Gen (P : Install_rules.Params) = struct in let flags = SC.ocaml_flags sctx ~scope ~dir lib.buildable in let { Dir_contents.Library_modules. - modules; main_module_name; alias_module ; deprecated } = + modules; main_module_name; alias_module ; wrapped_compat } = Dir_contents.modules_of_library dir_contents ~name:(Library.best_name lib) in let source_modules = modules in @@ -375,8 +375,8 @@ module Gen (P : Install_rules.Params) = struct in let js_of_ocaml = lib.buildable.js_of_ocaml in - build_deprecated_modules lib cctx ~dynlink ~js_of_ocaml - ~deprecated ~modules; + build_wrapped_compat_modules lib cctx ~dynlink ~js_of_ocaml + ~wrapped_compat ~modules; let dep_graphs = Ocamldep.rules cctx in @@ -396,7 +396,7 @@ module Gen (P : Install_rules.Params) = struct in List.iter Cm_kind.all ~f:(fun cm_kind -> let files = add_cms ~cm_kind ~init:Path.Set.empty modules in - let files = add_cms ~cm_kind ~init:files deprecated in + let files = add_cms ~cm_kind ~init:files wrapped_compat in SC.Libs.setup_file_deps_alias sctx ~dir lib ~ext:(Cm_kind.ext cm_kind) files); @@ -413,7 +413,7 @@ module Gen (P : Install_rules.Params) = struct else acc) in - let deprecated_modules = Module.Name.Map.values deprecated in + let deprecated_modules = Module.Name.Map.values wrapped_compat in (* deprecated modules have implementations so we can just append them *) let top_sorted_modules = Ocamldep.Dep_graph.top_closed_implementations dep_graphs.impl modules diff --git a/src/ocamldep.ml b/src/ocamldep.ml index 1a5d134d..268c75d7 100644 --- a/src/ocamldep.ml +++ b/src/ocamldep.ml @@ -52,14 +52,14 @@ module Dep_graph = struct ; per_module = Module.Name.Map.singleton m.name (Build.return []) } - let deprecated ~modules ~deprecated = + let wrapped_compat ~modules ~wrapped_compat = { dir = Path.root - ; per_module = Module.Name.Map.merge deprecated modules ~f:(fun _ d m -> + ; per_module = Module.Name.Map.merge wrapped_compat modules ~f:(fun _ d m -> match d, m with | None, None -> assert false - | Some deprecated, None -> + | Some wrapped_compat, None -> Exn.code_error "deprecated module needs counterpart" - [ "deprecated", Module.to_sexp deprecated + [ "deprecated", Module.to_sexp wrapped_compat ] | None, Some _ -> None | Some _, Some m -> Some (Build.return [m]) @@ -73,8 +73,8 @@ module Dep_graphs = struct let dummy m = Ml_kind.Dict.make_both (Dep_graph.dummy m) - let deprecated ~modules ~deprecated = - Ml_kind.Dict.make_both (Dep_graph.deprecated ~modules ~deprecated) + let wrapped_compat ~modules ~wrapped_compat = + Ml_kind.Dict.make_both (Dep_graph.wrapped_compat ~modules ~wrapped_compat) end let parse_module_names ~(unit : Module.t) ~modules words = diff --git a/src/ocamldep.mli b/src/ocamldep.mli index 83028590..184da31d 100644 --- a/src/ocamldep.mli +++ b/src/ocamldep.mli @@ -19,9 +19,9 @@ module Dep_graphs : sig val dummy : Module.t -> t - val deprecated + val wrapped_compat : modules:Module.t Module.Name.Map.t - -> deprecated:Module.t Module.Name.Map.t + -> wrapped_compat:Module.t Module.Name.Map.t -> t end From dfd3b1083c61cb45a0c17d2e1c77429c42b06bba Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 29 Aug 2018 22:19:48 +0300 Subject: [PATCH 08/17] Handle case when module alias exists Signed-off-by: Rudi Grinberg --- src/dir_contents.ml | 3 ++- test/blackbox-tests/test-cases/wrapped-transition/lib/mylib.ml | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/lib/mylib.ml diff --git a/src/dir_contents.ml b/src/dir_contents.ml index 5401b8a3..8eb1aa3c 100644 --- a/src/dir_contents.ml +++ b/src/dir_contents.ml @@ -197,7 +197,8 @@ end = struct | Simple true -> (wrap_modules modules, Module.Name.Map.empty) | Yes_with_transition _ -> ( wrap_modules modules - , Module.Name.Map.map ~f:Module.deprecate modules + , Module.Name.Map.remove modules main_module_name + |> Module.Name.Map.map ~f:Module.deprecate ) in let alias_module = diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/mylib.ml b/test/blackbox-tests/test-cases/wrapped-transition/lib/mylib.ml new file mode 100644 index 00000000..54287077 --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/mylib.ml @@ -0,0 +1,3 @@ +module Bar = Bar +module Foo = Foo +module Intf_only = Intf_only From 366c102aa0b24236cd03ebc1281f8641289561fb Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 11:25:01 +0300 Subject: [PATCH 09/17] Add .mli to one of transitioned modules Somehow this removes the deprecation Signed-off-by: Rudi Grinberg --- test/blackbox-tests/test-cases/wrapped-transition/lib/foo.mli | 1 + test/blackbox-tests/test-cases/wrapped-transition/run.t | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) create mode 100644 test/blackbox-tests/test-cases/wrapped-transition/lib/foo.mli diff --git a/test/blackbox-tests/test-cases/wrapped-transition/lib/foo.mli b/test/blackbox-tests/test-cases/wrapped-transition/lib/foo.mli new file mode 100644 index 00000000..733b2a32 --- /dev/null +++ b/test/blackbox-tests/test-cases/wrapped-transition/lib/foo.mli @@ -0,0 +1 @@ +val run : unit -> unit diff --git a/test/blackbox-tests/test-cases/wrapped-transition/run.t b/test/blackbox-tests/test-cases/wrapped-transition/run.t index 76b1fea0..a59994bb 100644 --- a/test/blackbox-tests/test-cases/wrapped-transition/run.t +++ b/test/blackbox-tests/test-cases/wrapped-transition/run.t @@ -2,6 +2,3 @@ File "fooexe.ml", line 3, characters 0-7: Error (warning 3): deprecated: module Bar Will be removed past 2020-20-20. Use Mylib.Bar instead. - File "fooexe.ml", line 4, characters 0-7: - Error (warning 3): deprecated: module Foo - Will be removed past 2020-20-20. Use Mylib.Foo instead. From 161ca64030da8c2da09bab8ad90d5e15547e5938 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 13:10:59 +0300 Subject: [PATCH 10/17] Add Cm_kind.to_sexp conversion Signed-off-by: Rudi Grinberg --- src/cm_kind.ml | 9 +++++++++ src/cm_kind.mli | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/src/cm_kind.ml b/src/cm_kind.ml index 0b52c7af..f2959463 100644 --- a/src/cm_kind.ml +++ b/src/cm_kind.ml @@ -1,3 +1,5 @@ +open Stdune + type t = Cmi | Cmo | Cmx let all = [Cmi; Cmo; Cmx] @@ -35,3 +37,10 @@ module Dict = struct ; cmx = x } end + +let to_sexp = + let open Sexp.To_sexp in + function + | Cmi -> string "cmi" + | Cmo -> string "cmo" + | Cmx -> string "cmx" diff --git a/src/cm_kind.mli b/src/cm_kind.mli index 71e8d087..ec8e4501 100644 --- a/src/cm_kind.mli +++ b/src/cm_kind.mli @@ -1,3 +1,5 @@ +open Stdune + type t = Cmi | Cmo | Cmx val all : t list @@ -5,6 +7,8 @@ val all : t list val ext : t -> string val source : t -> Ml_kind.t +val to_sexp : t Sexp.To_sexp.t + module Dict : sig type cm_kind = t From ba1b3f8d2434f62c446303ce0b4efcd43d6c45b2 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 13:11:16 +0300 Subject: [PATCH 11/17] Set intf to None deprecated modules don't really have interfaces Signed-off-by: Rudi Grinberg --- src/module.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/module.ml b/src/module.ml index 2ef21c34..7c8639c5 100644 --- a/src/module.ml +++ b/src/module.ml @@ -166,7 +166,8 @@ let to_sexp { name; impl; intf; obj_name ; pp } = let deprecate t = { t with - impl = + intf = None + ; impl = Some ( let path = match t.intf, t.impl with From 868ecbc63254e4627bb6c514db0b8375942ffed5 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 13:50:07 +0300 Subject: [PATCH 12/17] Change deprecated modules in a separate directory Signed-off-by: Rudi Grinberg --- src/dir_contents.ml | 2 +- src/lib_rules.ml | 6 +++--- src/module.ml | 8 +++++++- src/module.mli | 2 +- src/stdune/path.ml | 5 +++++ src/stdune/path.mli | 4 ++++ 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/dir_contents.ml b/src/dir_contents.ml index 8eb1aa3c..35a42df0 100644 --- a/src/dir_contents.ml +++ b/src/dir_contents.ml @@ -198,7 +198,7 @@ end = struct | Yes_with_transition _ -> ( wrap_modules modules , Module.Name.Map.remove modules main_module_name - |> Module.Name.Map.map ~f:Module.deprecate + |> Module.Name.Map.map ~f:Module.wrapped_compat ) in let alias_module = diff --git a/src/lib_rules.ml b/src/lib_rules.ml index c35bfc44..4074fa07 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -413,13 +413,13 @@ module Gen (P : Install_rules.Params) = struct else acc) in - let deprecated_modules = Module.Name.Map.values wrapped_compat in + let wrapped_compat = Module.Name.Map.values wrapped_compat in (* deprecated modules have implementations so we can just append them *) let top_sorted_modules = Ocamldep.Dep_graph.top_closed_implementations dep_graphs.impl modules - >>^ fun modules -> modules @ deprecated_modules + >>^ fun modules -> modules @ wrapped_compat in - (let modules = modules @ deprecated_modules in + (let modules = modules @ wrapped_compat in List.iter Mode.all ~f:(fun mode -> build_lib lib ~scope ~flags ~dir ~obj_dir ~mode ~top_sorted_modules ~modules))); diff --git a/src/module.ml b/src/module.ml index 7c8639c5..bb19fb20 100644 --- a/src/module.ml +++ b/src/module.ml @@ -164,7 +164,7 @@ let to_sexp { name; impl; intf; obj_name ; pp } = ; "pp", (option string) (Option.map ~f:(fun _ -> "has pp") pp) ] -let deprecate t = +let wrapped_compat t = { t with intf = None ; impl = @@ -176,6 +176,12 @@ let deprecate t = | Some intf, _ -> intf.path | None, None -> assert false in + let path = + Path.L.relative (Path.parent_exn path) + [ ".wrapped_compat" + ; Path.basename path + ] + in let (base, _) = Path.split_extension path in { syntax = OCaml ; path = Path.extend_basename base ~suffix:".ml-gen" diff --git a/src/module.mli b/src/module.mli index 4e3201da..fec3aa25 100644 --- a/src/module.mli +++ b/src/module.mli @@ -95,4 +95,4 @@ val set_pp : t -> (unit, string list) Build.t option -> t val to_sexp : t Sexp.To_sexp.t -val deprecate : t -> t +val wrapped_compat : t -> t diff --git a/src/stdune/path.ml b/src/stdune/path.ml index c277df2f..e832c76a 100644 --- a/src/stdune/path.ml +++ b/src/stdune/path.ml @@ -943,3 +943,8 @@ module Internal = struct | In_source_tree l -> Local l | External l -> External l end + +module L = struct + (* TODO more efficient implementation *) + let relative t = List.fold_left ~init:t ~f:relative +end diff --git a/src/stdune/path.mli b/src/stdune/path.mli index 6880fa24..3da71c48 100644 --- a/src/stdune/path.mli +++ b/src/stdune/path.mli @@ -169,3 +169,7 @@ val set_root : External.t -> unit module Internal : sig val raw_kind : t -> Kind.t end + +module L : sig + val relative : t -> string list -> t +end From 96e3448228d647c698500de8e6a0a6026097131f Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 14:03:25 +0300 Subject: [PATCH 13/17] Add documentation and change log entry Signed-off-by: Rudi Grinberg --- CHANGES.md | 4 ++++ doc/dune-files.rst | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 40596326..91d298c8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -38,6 +38,10 @@ next - Improve message suggesting to remove parentheses (#1196, fix #1173, @emillon) +- Add `(wrapped (transition "..message.."))` as an option that will generate + wrapped modules but keep unwrapped modules with a deprecation message to + preserve compatibility. (#1188, fix #985, @rgrinberg) + 1.1.1 (08/08/2018) ------------------ diff --git a/doc/dune-files.rst b/doc/dune-files.rst index 3c2915ee..ce87c4dc 100644 --- a/doc/dune-files.rst +++ b/doc/dune-files.rst @@ -96,6 +96,13 @@ to use the :ref:`include_subdirs` stanza. only intended for libraries that manually prefix all their modules by the library name and to ease porting of existing projects to dune +- ``(wrapped (transition ))`` Is the same as ``(wrapped true)`` except + that it will also generate unwrapped (not prefixed by the library name) + modules to preserve compatibility. This is useful for libraries that would + like to transition from ``(wrapped false)`` to ``(wrapped true)`` without + breaking compatibility for users. The ```` will be included in the + deprecation notice for the unwrapped modules. + - ``(preprocess )`` specifies how to preprocess files if needed. The default is ``no_processing``. Other options are described in the `Preprocessing specification`_ section From 8449b46bc1eaecce2f9eb742119ee3ba2ea528b9 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 15:47:43 +0300 Subject: [PATCH 14/17] Fix tests Signed-off-by: Rudi Grinberg --- test/blackbox-tests/test-cases/wrapped-transition/run.t | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/blackbox-tests/test-cases/wrapped-transition/run.t b/test/blackbox-tests/test-cases/wrapped-transition/run.t index a59994bb..fda4cc0b 100644 --- a/test/blackbox-tests/test-cases/wrapped-transition/run.t +++ b/test/blackbox-tests/test-cases/wrapped-transition/run.t @@ -2,3 +2,9 @@ File "fooexe.ml", line 3, characters 0-7: Error (warning 3): deprecated: module Bar Will be removed past 2020-20-20. Use Mylib.Bar instead. + File "fooexe.ml", line 4, characters 0-7: + Error (warning 3): deprecated: module Foo + Will be removed past 2020-20-20. Use Mylib.Foo instead. + File "fooexe.ml", line 7, characters 11-22: + Error (warning 3): deprecated: module Intf_only + Will be removed past 2020-20-20. Use Mylib.Intf_only instead. From 28b311cf95486154a25cbb2d1884c8e6d80a57f2 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 17:45:42 +0300 Subject: [PATCH 15/17] Clarifying comment about appending wrapped compat modules Signed-off-by: Rudi Grinberg --- src/lib_rules.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib_rules.ml b/src/lib_rules.ml index 4074fa07..976819a6 100644 --- a/src/lib_rules.ml +++ b/src/lib_rules.ml @@ -414,7 +414,9 @@ module Gen (P : Install_rules.Params) = struct acc) in let wrapped_compat = Module.Name.Map.values wrapped_compat in - (* deprecated modules have implementations so we can just append them *) + (* Compatibility modules have implementations so we can just append them. + We append the modules at the end as no library modules depend on + them. *) let top_sorted_modules = Ocamldep.Dep_graph.top_closed_implementations dep_graphs.impl modules >>^ fun modules -> modules @ wrapped_compat From 18abaa7def18b5320c0ac10bfba7fde688d444ca Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 17:52:44 +0300 Subject: [PATCH 16/17] Simplify code using Module.dir Signed-off-by: Rudi Grinberg --- src/module.ml | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/module.ml b/src/module.ml index bb19fb20..26fd5fc0 100644 --- a/src/module.ml +++ b/src/module.ml @@ -169,22 +169,12 @@ let wrapped_compat t = intf = None ; impl = Some ( - let path = - match t.intf, t.impl with - | Some _, Some impl - | None, Some impl -> impl.path - | Some intf, _ -> intf.path - | None, None -> assert false - in - let path = - Path.L.relative (Path.parent_exn path) - [ ".wrapped_compat" - ; Path.basename path - ] - in - let (base, _) = Path.split_extension path in { syntax = OCaml - ; path = Path.extend_basename base ~suffix:".ml-gen" + ; path = + Path.L.relative (dir t) + [ ".wrapped_compat" + ; Name.to_string t.name ^ ".ml-gen" + ] } ) } From 3c89b6c131e056dd7cf04a008191107e049bb928 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 31 Aug 2018 17:58:58 +0300 Subject: [PATCH 17/17] Require dune lang 1.2 for transitioning wraps Signed-off-by: Rudi Grinberg --- src/dune_file.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dune_file.ml b/src/dune_file.ml index 924d42a6..d2116fcf 100644 --- a/src/dune_file.ml +++ b/src/dune_file.ml @@ -868,7 +868,9 @@ module Library = struct sum [ "true", return (Simple true) ; "false", return (Simple false) - ; "transition", string >>| fun x -> Yes_with_transition x + ; "transition", + Syntax.since Stanza.syntax (1, 2) >>= fun () -> + string >>| fun x -> Yes_with_transition x ] let field = field "wrapped" ~default:(Simple true) dparse