Skip to content

Commit

Permalink
Disallow rename for unwrapped libs
Browse files Browse the repository at this point in the history
Such libraries do not have an alias module

Signed-off-by: Rudi Grinberg <[email protected]>
  • Loading branch information
rgrinberg committed Oct 12, 2020
1 parent 42058ff commit 8e03069
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 40 deletions.
5 changes: 1 addition & 4 deletions src/dune_rules/cinaps.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ let decode =
field "files" Predicate_lang.Glob.decode ~default:Predicate_lang.any
and+ preprocess, preprocessor_deps = Dune_file.preprocess_fields
and+ libraries =
field "libraries"
(Dune_file.Lib_deps.decode ~allow_re_export:false
~require_mangling:false)
~default:[]
field "libraries" (Dune_file.Lib_deps.decode Executable) ~default:[]
and+ flags = Ocaml_flags.Spec.decode in
{ loc; files; libraries; preprocess; preprocessor_deps; flags })

Expand Down
75 changes: 48 additions & 27 deletions src/dune_rules/dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ module Js_of_ocaml = struct
{ flags = Ordered_set_lang.Unexpanded.standard; javascript_files = [] }
end

type for_ =
| Executable
| Library of Wrapped.t option

module Lib_deps = struct
type t = Lib_dep.t list

Expand All @@ -53,10 +57,21 @@ module Lib_deps = struct
| Optional
| Forbidden

let decode ~allow_re_export ~require_mangling =
let rename_unwrapped_error loc =
User_error.raise ~loc
[ Pp.text "rename may not be used in unwrapped libraries" ]

let decode for_ =
let+ loc = loc
and+ project = Dune_project.get_exn ()
and+ t = repeat (Lib_dep.decode ~allow_re_export) in
and+ t =
let allow_re_export =
match for_ with
| Library _ -> true
| Executable -> false
in
repeat (Lib_dep.decode ~allow_re_export)
in
let add kind name acc =
match Lib_name.Map.find acc name with
| None -> Lib_name.Map.set acc name kind
Expand All @@ -83,22 +98,28 @@ module Lib_deps = struct
(Lib_name.to_string name)
] )
in
let mangling =
Dune_project.wrapped_executables project || require_mangling
let check_rename =
match for_ with
| Library (Some (Simple false)) -> rename_unwrapped_error
| Library _ -> fun _loc -> ()
| Executable ->
if Dune_project.wrapped_executables project then
fun _loc ->
()
else
fun loc ->
User_error.raise ~loc
[ Pp.text
"rename may not be used in executables without \
wrapped_executables switched on in the dune-project file"
]
in
ignore
( List.fold_left t ~init:Lib_name.Map.empty ~f:(fun acc x ->
match x with
| Lib_dep.Rename ((loc, name), _) ->
if mangling then
add Required name acc
else
User_error.raise ~loc
[ Pp.text
"rename may not be used in executables without \
wrapped_executables switched on in the dune-project \
file"
]
check_rename loc;
add Required name acc
| Lib_dep.Re_export (_, s)
| Lib_dep.Direct (_, s) ->
add Required s acc
Expand Down Expand Up @@ -178,16 +199,15 @@ module Buildable = struct
; allow_overlapping_dependencies : bool
}

let decode ~in_library ~allow_re_export =
let decode (for_ : for_) =
let use_foreign =
Dune_lang.Syntax.deleted_in Stanza.syntax (2, 0)
~extra_info:"Use the (foreign_stubs ...) field instead."
in
let only_in_library decode =
if in_library then
decode
else
return None
match for_ with
| Executable -> decode
| Library _ -> return None
in
let add_stubs language ~loc ~names ~flags foreign_stubs =
match names with
Expand Down Expand Up @@ -234,10 +254,7 @@ module Buildable = struct
>>> enter (maybe string) )))
and+ modules_without_implementation =
Stanza_common.modules_field "modules_without_implementation"
and+ libraries =
field "libraries"
(Lib_deps.decode ~allow_re_export ~require_mangling:(not in_library))
~default:[]
and+ libraries = field "libraries" (Lib_deps.decode for_) ~default:[]
and+ flags = Ocaml_flags.Spec.decode
and+ js_of_ocaml =
field "js_of_ocaml" Js_of_ocaml.decode ~default:Js_of_ocaml.default
Expand Down Expand Up @@ -306,6 +323,11 @@ module Buildable = struct

let has_foreign t =
List.is_non_empty t.foreign_stubs || List.is_non_empty t.foreign_archives

let first_rename_dep (t : t) =
List.find_map t.libraries ~f:(function
| Lib_dep.Rename ((loc, _), _) -> Some loc
| _ -> None)
end

module Public_lib = struct
Expand Down Expand Up @@ -557,8 +579,9 @@ module Library = struct
let decode =
fields
(let* stanza_loc = loc in
let* wrapped = Wrapped.field in
let* dune_version = Dune_lang.Syntax.get_exn Stanza.syntax in
let+ buildable = Buildable.decode ~in_library:true ~allow_re_export:true
let+ buildable = Buildable.decode (Library (Option.map ~f:snd wrapped))
and+ name = field_o "name" Lib_name.Local.decode_loc
and+ public =
field_o "public_name" (Public_lib.decode ~allow_deprecated_names:false)
Expand All @@ -578,7 +601,6 @@ module Library = struct
field "modes" Mode_conf.Set.decode
~default:(Mode_conf.Set.default stanza_loc)
and+ kind = field "kind" Lib_kind.decode ~default:Lib_kind.Normal
and+ wrapped = Wrapped.field
and+ optional = field_b "optional"
and+ no_dynlink = field_b "no_dynlink"
and+ () =
Expand Down Expand Up @@ -1317,7 +1339,7 @@ module Executables = struct

let common =
let* dune_version = Dune_lang.Syntax.get_exn Stanza.syntax in
let+ buildable = Buildable.decode ~in_library:false ~allow_re_export:false
let+ buildable = Buildable.decode Executable
and+ (_ : bool) =
field "link_executables" ~default:true
(Dune_lang.Syntax.deleted_in Stanza.syntax (1, 0) >>> bool)
Expand Down Expand Up @@ -1740,8 +1762,7 @@ module Tests = struct

let gen_parse names =
fields
(let+ buildable =
Buildable.decode ~in_library:false ~allow_re_export:false
(let+ buildable = Buildable.decode Executable
and+ link_flags = Ordered_set_lang.Unexpanded.field "link_flags"
and+ names = names
and+ package = field_o "package" Stanza_common.Pkg.decode
Expand Down
11 changes: 9 additions & 2 deletions src/dune_rules/dune_file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ module Js_of_ocaml : sig
val default : t
end

type for_ =
| Executable
| Library of Wrapped.t option

module Lib_deps : sig
type nonrec t = Lib_dep.t list

val of_pps : Lib_name.t list -> t

val info : t -> kind:Lib_deps_info.Kind.t -> Lib_deps_info.t

val decode :
allow_re_export:bool -> require_mangling:bool -> t Dune_lang.Decoder.t
val decode : for_ -> t Dune_lang.Decoder.t

val rename_unwrapped_error : Loc.t -> 'a
end

(** [preprocess] and [preprocessor_deps] fields *)
Expand All @@ -54,6 +59,8 @@ module Buildable : sig

(** Check if the buildable has any foreign stubs or archives. *)
val has_foreign : t -> bool

val first_rename_dep : t -> Loc.t option
end

module Public_lib : sig
Expand Down
22 changes: 15 additions & 7 deletions src/dune_rules/ml_sources.ml
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,15 @@ let make_lib_modules (d : _ Dir_with_dune.t) ~lookup_vlib ~(lib : Library.t)
in
(kind, main_module_name, wrapped)
in
let () =
match wrapped with
| Simple false ->
Buildable.first_rename_dep lib.buildable
|> Option.iter ~f:Lib_deps.rename_unwrapped_error
| Simple true
| Yes_with_transition _ ->
()
in
let modules =
Modules_field_evaluator.eval ~modules ~buildable:lib.buildable ~kind
~private_modules:
Expand All @@ -276,15 +285,12 @@ let make_lib_modules (d : _ Dir_with_dune.t) ~lookup_vlib ~(lib : Library.t)
~main_module_name ~wrapped ~force_alias

let libs_and_exes (d : _ Dir_with_dune.t) ~lookup_vlib ~modules =
let force_alias (b : Buildable.t) =
List.exists b.libraries ~f:(function
| Lib_dep.Rename _ -> true
| _ -> false)
in
List.filter_partition_map d.data ~f:(fun stanza ->
match (stanza : Stanza.t) with
| Library lib ->
let force_alias = force_alias lib.buildable in
let force_alias =
Buildable.first_rename_dep lib.buildable |> Option.is_some
in
let modules =
make_lib_modules d ~lookup_vlib ~modules ~lib ~force_alias
in
Expand All @@ -299,7 +305,9 @@ let libs_and_exes (d : _ Dir_with_dune.t) ~lookup_vlib ~modules =
let modules =
let project = Scope.project d.scope in
if Dune_project.wrapped_executables project then
let force_alias = force_alias exes.buildable in
let force_alias =
Buildable.first_rename_dep exes.buildable |> Option.is_some
in
Modules_group.exe_wrapped ~src_dir:d.ctx_dir ~modules ~force_alias
else
Modules_group.exe_unwrapped modules
Expand Down
20 changes: 20 additions & 0 deletions test/blackbox-tests/test-cases/rename-deps.t
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,23 @@ This works for single module executables:
$ rm exe/lib1.ml
$ dune exec ./exe/foo.exe
Hello World

And for single module libs:
$ rm lib2/lib1.ml
$ dune build @lib2/all

This mode is disabled for unwrapped libraries

$ mkdir unwrapped
$ cat >unwrapped/dune <<EOF
> (library
> (libraries (rename lib1 -> lib1_unshadow))
> (wrapped false)
> (name unwrapped_lib))
> EOF
$ dune build @unwrapped/all
File "unwrapped/dune", line 2, characters 20-24:
2 | (libraries (rename lib1 -> lib1_unshadow))
^^^^
Error: rename may not be used in unwrapped libraries
[1]

0 comments on commit 8e03069

Please sign in to comment.