Make name and names fields optional when public_name or public_names are present (#1041)
Make name field optional when public_name is specified When name is omitted, it will be defaulted to public_name This feature is 1.1 only.
This commit is contained in:
parent
a13325e389
commit
835a44ff1e
|
@ -304,7 +304,7 @@ module Gen(P : Params) = struct
|
||||||
~f:(fun { SC.Installable. dir; stanza; kind = dir_kind; scope; _ } ->
|
~f:(fun { SC.Installable. dir; stanza; kind = dir_kind; scope; _ } ->
|
||||||
let dir_contents = Dir_contents.get sctx ~dir in
|
let dir_contents = Dir_contents.get sctx ~dir in
|
||||||
match stanza with
|
match stanza with
|
||||||
| Library ({ public = Some { package; sub_dir; name; _ }
|
| Library ({ public = Some { package; sub_dir; name = (_, name); _ }
|
||||||
; _ } as lib) ->
|
; _ } as lib) ->
|
||||||
List.map (lib_install_files ~dir ~sub_dir ~name lib ~scope
|
List.map (lib_install_files ~dir ~sub_dir ~name lib ~scope
|
||||||
~dir_kind ~dir_contents)
|
~dir_kind ~dir_contents)
|
||||||
|
|
116
src/jbuild.ml
116
src/jbuild.ml
|
@ -640,20 +640,22 @@ end
|
||||||
|
|
||||||
module Public_lib = struct
|
module Public_lib = struct
|
||||||
type t =
|
type t =
|
||||||
{ name : string
|
{ name : Loc.t * string
|
||||||
; package : Package.t
|
; package : Package.t
|
||||||
; sub_dir : string option
|
; sub_dir : string option
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let name t = snd t.name
|
||||||
|
|
||||||
let public_name_field =
|
let public_name_field =
|
||||||
map_validate
|
map_validate
|
||||||
(let%map project = Dune_project.get_exn ()
|
(let%map project = Dune_project.get_exn ()
|
||||||
and name = field_o "public_name" string in
|
and loc_name = field_o "public_name" (located string) in
|
||||||
(project, name))
|
(project, loc_name))
|
||||||
~f:(fun (project, name) ->
|
~f:(fun (project, loc_name) ->
|
||||||
match name with
|
match loc_name with
|
||||||
| None -> Ok None
|
| None -> Ok None
|
||||||
| Some s ->
|
| Some ((_, s) as loc_name) ->
|
||||||
match String.split s ~on:'.' with
|
match String.split s ~on:'.' with
|
||||||
| [] -> assert false
|
| [] -> assert false
|
||||||
| pkg :: rest ->
|
| pkg :: rest ->
|
||||||
|
@ -664,7 +666,7 @@ module Public_lib = struct
|
||||||
; sub_dir =
|
; sub_dir =
|
||||||
if rest = [] then None else
|
if rest = [] then None else
|
||||||
Some (String.concat rest ~sep:"/")
|
Some (String.concat rest ~sep:"/")
|
||||||
; name = s
|
; name = loc_name
|
||||||
})
|
})
|
||||||
| Error _ as e -> e)
|
| Error _ as e -> e)
|
||||||
end
|
end
|
||||||
|
@ -805,7 +807,8 @@ module Library = struct
|
||||||
let t =
|
let t =
|
||||||
record
|
record
|
||||||
(let%map buildable = Buildable.t
|
(let%map buildable = Buildable.t
|
||||||
and name = field "name" library_name
|
and loc = loc
|
||||||
|
and name = field_o "name" library_name
|
||||||
and public = Public_lib.public_name_field
|
and public = Public_lib.public_name_field
|
||||||
and synopsis = field_o "synopsis" string
|
and synopsis = field_o "synopsis" string
|
||||||
and install_c_headers =
|
and install_c_headers =
|
||||||
|
@ -834,6 +837,23 @@ module Library = struct
|
||||||
and project = Dune_project.get_exn ()
|
and project = Dune_project.get_exn ()
|
||||||
and dune_version = Syntax.get_exn Stanza.syntax
|
and dune_version = Syntax.get_exn Stanza.syntax
|
||||||
in
|
in
|
||||||
|
let name =
|
||||||
|
match name, public with
|
||||||
|
| Some n, _ -> n
|
||||||
|
| None, Some { name = (_loc, name) ; _ } ->
|
||||||
|
if dune_version >= (1, 1) then
|
||||||
|
name
|
||||||
|
else
|
||||||
|
of_sexp_error loc "name field cannot be omitted before version \
|
||||||
|
1.1 of the dune language"
|
||||||
|
| None, None ->
|
||||||
|
of_sexp_error loc (
|
||||||
|
if dune_version >= (1, 1) then
|
||||||
|
"supply at least least one of name or public_name fields"
|
||||||
|
else
|
||||||
|
"name field is missing"
|
||||||
|
)
|
||||||
|
in
|
||||||
{ name
|
{ name
|
||||||
; public
|
; public
|
||||||
; synopsis
|
; synopsis
|
||||||
|
@ -876,7 +896,7 @@ module Library = struct
|
||||||
let best_name t =
|
let best_name t =
|
||||||
match t.public with
|
match t.public with
|
||||||
| None -> t.name
|
| None -> t.name
|
||||||
| Some p -> p.name
|
| Some p -> snd p.name
|
||||||
end
|
end
|
||||||
|
|
||||||
module Install_conf = struct
|
module Install_conf = struct
|
||||||
|
@ -1020,7 +1040,19 @@ module Executables = struct
|
||||||
; buildable : Buildable.t
|
; buildable : Buildable.t
|
||||||
}
|
}
|
||||||
|
|
||||||
let common =
|
let pluralize s ~multi =
|
||||||
|
if multi then
|
||||||
|
s
|
||||||
|
else
|
||||||
|
s ^ "s"
|
||||||
|
|
||||||
|
let common
|
||||||
|
(* : (Loc.t * string) list option
|
||||||
|
* -> (Loc.t * string) list option
|
||||||
|
* -> multi:bool
|
||||||
|
* -> unit
|
||||||
|
* -> t * Install_conf.t option Sexp.Of_sexp.t *)
|
||||||
|
=
|
||||||
let%map buildable = Buildable.t
|
let%map buildable = Buildable.t
|
||||||
and (_ : bool) = field "link_executables" ~default:true
|
and (_ : bool) = field "link_executables" ~default:true
|
||||||
(Syntax.deleted_in Stanza.syntax (1, 0) >>> bool)
|
(Syntax.deleted_in Stanza.syntax (1, 0) >>> bool)
|
||||||
|
@ -1040,8 +1072,33 @@ module Executables = struct
|
||||||
(loc, s))
|
(loc, s))
|
||||||
and project = Dune_project.get_exn ()
|
and project = Dune_project.get_exn ()
|
||||||
and file_kind = Stanza.file_kind ()
|
and file_kind = Stanza.file_kind ()
|
||||||
|
and dune_syntax = Syntax.get_exn Stanza.syntax
|
||||||
|
and loc = loc
|
||||||
in
|
in
|
||||||
fun names public_names ~multi ->
|
fun names public_names ~multi ->
|
||||||
|
let names =
|
||||||
|
match names, public_names with
|
||||||
|
| Some names, _ -> names
|
||||||
|
| None, Some public_names ->
|
||||||
|
if dune_syntax >= (1, 1) then
|
||||||
|
List.map public_names ~f:(fun (loc, p) ->
|
||||||
|
match p with
|
||||||
|
| None ->
|
||||||
|
of_sexp_error loc "This executable must have a name field"
|
||||||
|
| Some s -> (loc, s))
|
||||||
|
else
|
||||||
|
of_sexp_errorf loc
|
||||||
|
"%s field may not be omitted before dune version 1.1"
|
||||||
|
(pluralize ~multi "name")
|
||||||
|
| None, None ->
|
||||||
|
if dune_syntax >= (1, 1) then
|
||||||
|
of_sexp_errorf loc "either the %s or the %s field must be present"
|
||||||
|
(pluralize ~multi "name")
|
||||||
|
(pluralize ~multi "public_name")
|
||||||
|
else
|
||||||
|
of_sexp_errorf loc "field %s is missing"
|
||||||
|
(pluralize ~multi "name")
|
||||||
|
in
|
||||||
let t =
|
let t =
|
||||||
{ names
|
{ names
|
||||||
; link_flags
|
; link_flags
|
||||||
|
@ -1051,7 +1108,10 @@ module Executables = struct
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
let has_public_name =
|
let has_public_name =
|
||||||
List.exists ~f:Option.is_some public_names
|
(* user could omit public names by avoiding the field or writing - *)
|
||||||
|
match public_names with
|
||||||
|
| None -> false
|
||||||
|
| Some pns -> List.exists ~f:(fun (_, n) -> Option.is_some n) pns
|
||||||
in
|
in
|
||||||
let to_install =
|
let to_install =
|
||||||
match Link_mode.Set.best_install_mode t.modes with
|
match Link_mode.Set.best_install_mode t.modes with
|
||||||
|
@ -1073,8 +1133,13 @@ module Executables = struct
|
||||||
| Native | Best -> ".exe"
|
| Native | Best -> ".exe"
|
||||||
| Byte -> ".bc"
|
| Byte -> ".bc"
|
||||||
in
|
in
|
||||||
|
let public_names =
|
||||||
|
match public_names with
|
||||||
|
| None -> List.map names ~f:(fun _ -> (Loc.none, None))
|
||||||
|
| Some pns -> pns
|
||||||
|
in
|
||||||
List.map2 names public_names
|
List.map2 names public_names
|
||||||
~f:(fun (_, name) pub ->
|
~f:(fun (_, name) (_, pub) ->
|
||||||
match pub with
|
match pub with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some pub -> Some ({ Install_conf.
|
| Some pub -> Some ({ Install_conf.
|
||||||
|
@ -1114,35 +1179,40 @@ module Executables = struct
|
||||||
(t, Some { Install_conf. section = Bin; files; package })
|
(t, Some { Install_conf. section = Bin; files; package })
|
||||||
|
|
||||||
let public_name =
|
let public_name =
|
||||||
string >>| function
|
located string >>| fun (loc, s) ->
|
||||||
|
(loc
|
||||||
|
, match s with
|
||||||
| "-" -> None
|
| "-" -> None
|
||||||
| s -> Some s
|
| s -> Some s)
|
||||||
|
|
||||||
let multi =
|
let multi =
|
||||||
record
|
record
|
||||||
(let%map names, public_names =
|
(let%map names, public_names =
|
||||||
map_validate
|
map_validate
|
||||||
(let%map names = field "names" (list (located string))
|
(let%map names = field_o "names" (list (located string))
|
||||||
and pub_names = field_o "public_names" (list public_name) in
|
and pub_names = field_o "public_names" (list public_name) in
|
||||||
(names, pub_names))
|
(names, pub_names))
|
||||||
~f:(fun (names, public_names) ->
|
~f:(fun (names, public_names) ->
|
||||||
match public_names with
|
match names, public_names with
|
||||||
| None -> Ok (names, List.map names ~f:(fun _ -> None))
|
| Some names, Some public_names ->
|
||||||
| Some public_names ->
|
|
||||||
if List.length public_names = List.length names then
|
if List.length public_names = List.length names then
|
||||||
Ok (names, public_names)
|
Ok (Some names, Some public_names)
|
||||||
else
|
else
|
||||||
Error "The list of public names must be of the same \
|
Error "The list of public names must be of the same \
|
||||||
length as the list of names")
|
length as the list of names"
|
||||||
|
| names, public_names -> Ok (names, public_names))
|
||||||
and f = common in
|
and f = common in
|
||||||
f names public_names ~multi:true)
|
f names public_names ~multi:true)
|
||||||
|
|
||||||
let single =
|
let single =
|
||||||
record
|
record
|
||||||
(let%map name = field "name" (located string)
|
(let%map name = field_o "name" (located string)
|
||||||
and public_name = field_o "public_name" string
|
and public_name = field_o "public_name" (located string)
|
||||||
and f = common in
|
and f = common in
|
||||||
f [name] [public_name] ~multi:false)
|
f (Option.map name ~f:List.singleton)
|
||||||
|
(Option.map public_name ~f:(fun (loc, s) ->
|
||||||
|
[loc, Some s]))
|
||||||
|
~multi:false)
|
||||||
end
|
end
|
||||||
|
|
||||||
module Rule = struct
|
module Rule = struct
|
||||||
|
|
|
@ -137,11 +137,13 @@ end
|
||||||
|
|
||||||
module Public_lib : sig
|
module Public_lib : sig
|
||||||
type t =
|
type t =
|
||||||
{ name : string (** Full public name *)
|
{ name : Loc.t * string (** Full public name *)
|
||||||
; package : Package.t (** Package it is part of *)
|
; package : Package.t (** Package it is part of *)
|
||||||
; sub_dir : string option (** Subdirectory inside the installation
|
; sub_dir : string option (** Subdirectory inside the installation
|
||||||
directory *)
|
directory *)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val name : t -> string
|
||||||
end
|
end
|
||||||
|
|
||||||
module Sub_system_info : sig
|
module Sub_system_info : sig
|
||||||
|
|
11
src/lib.ml
11
src/lib.ml
|
@ -988,11 +988,12 @@ module DB = struct
|
||||||
| None ->
|
| None ->
|
||||||
[(conf.name, Resolve_result.Found info)]
|
[(conf.name, Resolve_result.Found info)]
|
||||||
| Some p ->
|
| Some p ->
|
||||||
if p.name = conf.name then
|
let name = Jbuild.Public_lib.name p in
|
||||||
[(p.name, Found info)]
|
if name = conf.name then
|
||||||
|
[(name, Found info)]
|
||||||
else
|
else
|
||||||
[ p.name , Found info
|
[ name , Found info
|
||||||
; conf.name, Redirect (None, p.name)
|
; conf.name, Redirect (None, name)
|
||||||
])
|
])
|
||||||
|> String.Map.of_list
|
|> String.Map.of_list
|
||||||
|> function
|
|> function
|
||||||
|
@ -1003,7 +1004,7 @@ module DB = struct
|
||||||
if name = conf.name ||
|
if name = conf.name ||
|
||||||
match conf.public with
|
match conf.public with
|
||||||
| None -> false
|
| None -> false
|
||||||
| Some p -> name = p.name
|
| Some p -> name = Jbuild.Public_lib.name p
|
||||||
then Some conf.buildable.loc
|
then Some conf.buildable.loc
|
||||||
else None)
|
else None)
|
||||||
with
|
with
|
||||||
|
|
|
@ -78,7 +78,7 @@ module DB = struct
|
||||||
List.filter_map internal_libs ~f:(fun (_dir, lib) ->
|
List.filter_map internal_libs ~f:(fun (_dir, lib) ->
|
||||||
match lib.public with
|
match lib.public with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some p -> Some (p.name, lib.project))
|
| Some p -> Some (Jbuild.Public_lib.name p, lib.project))
|
||||||
|> String.Map.of_list
|
|> String.Map.of_list
|
||||||
|> function
|
|> function
|
||||||
| Ok x -> x
|
| Ok x -> x
|
||||||
|
@ -87,7 +87,8 @@ module DB = struct
|
||||||
List.filter_map internal_libs ~f:(fun (_dir, lib) ->
|
List.filter_map internal_libs ~f:(fun (_dir, lib) ->
|
||||||
match lib.public with
|
match lib.public with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some p -> Option.some_if (name = p.name) lib.buildable.loc)
|
| Some p -> Option.some_if (name = Jbuild.Public_lib.name p)
|
||||||
|
lib.buildable.loc)
|
||||||
with
|
with
|
||||||
| [] | [_] -> assert false
|
| [] | [_] -> assert false
|
||||||
| loc1 :: loc2 :: _ ->
|
| loc1 :: loc2 :: _ ->
|
||||||
|
|
|
@ -77,7 +77,8 @@ let internal_lib_names t =
|
||||||
String.Set.add
|
String.Set.add
|
||||||
(match lib.public with
|
(match lib.public with
|
||||||
| None -> acc
|
| None -> acc
|
||||||
| Some { name; _ } -> String.Set.add acc name)
|
| Some { name = (_, name); _ } ->
|
||||||
|
String.Set.add acc name)
|
||||||
lib.name
|
lib.name
|
||||||
| _ -> acc))
|
| _ -> acc))
|
||||||
|
|
||||||
|
|
|
@ -468,6 +468,14 @@
|
||||||
test-cases/no-installable-mode
|
test-cases/no-installable-mode
|
||||||
(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 no-name-field)
|
||||||
|
(deps (package dune) (source_tree test-cases/no-name-field))
|
||||||
|
(action
|
||||||
|
(chdir
|
||||||
|
test-cases/no-name-field
|
||||||
|
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
|
||||||
|
|
||||||
(alias
|
(alias
|
||||||
(name null-dep)
|
(name null-dep)
|
||||||
(deps (package dune) (source_tree test-cases/null-dep))
|
(deps (package dune) (source_tree test-cases/null-dep))
|
||||||
|
@ -782,6 +790,7 @@
|
||||||
(alias misc)
|
(alias misc)
|
||||||
(alias multiple-private-libs)
|
(alias multiple-private-libs)
|
||||||
(alias no-installable-mode)
|
(alias no-installable-mode)
|
||||||
|
(alias no-name-field)
|
||||||
(alias null-dep)
|
(alias null-dep)
|
||||||
(alias ocaml-config-macro)
|
(alias ocaml-config-macro)
|
||||||
(alias ocaml-syntax)
|
(alias ocaml-syntax)
|
||||||
|
@ -868,6 +877,7 @@
|
||||||
(alias meta-gen)
|
(alias meta-gen)
|
||||||
(alias misc)
|
(alias misc)
|
||||||
(alias no-installable-mode)
|
(alias no-installable-mode)
|
||||||
|
(alias no-name-field)
|
||||||
(alias null-dep)
|
(alias null-dep)
|
||||||
(alias ocaml-config-macro)
|
(alias ocaml-config-macro)
|
||||||
(alias ocaml-syntax)
|
(alias ocaml-syntax)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
(executables (public_names foo bar))
|
|
@ -0,0 +1 @@
|
||||||
|
(lang dune 1.0)
|
|
@ -0,0 +1 @@
|
||||||
|
(lang dune 1.1)
|
|
@ -0,0 +1 @@
|
||||||
|
(executable (public_name foo))
|
|
@ -0,0 +1 @@
|
||||||
|
(executables (public_names bar baz))
|
|
@ -0,0 +1 @@
|
||||||
|
(library (public_name foo))
|
|
@ -0,0 +1,2 @@
|
||||||
|
(lang dune 1.0)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
(library (public_name foo))
|
|
@ -0,0 +1 @@
|
||||||
|
(lang dune 1.1)
|
|
@ -0,0 +1,19 @@
|
||||||
|
the name field can be omitted for libraries when public_name is present
|
||||||
|
$ dune build --root no-name-lib
|
||||||
|
Entering directory 'no-name-lib'
|
||||||
|
|
||||||
|
this isn't possible for older syntax <= (1, 0)
|
||||||
|
$ dune build --root no-name-lib-syntax-1-0
|
||||||
|
File "dune", line 1, characters 0-27:
|
||||||
|
Error: name field cannot be omitted before version 1.1 of the dune language
|
||||||
|
[1]
|
||||||
|
|
||||||
|
executable(s) stanza works the same way
|
||||||
|
|
||||||
|
$ dune build --root no-name-exes
|
||||||
|
Entering directory 'no-name-exes'
|
||||||
|
|
||||||
|
$ dune build --root no-name-exes-syntax-1-0
|
||||||
|
File "dune", line 1, characters 0-36:
|
||||||
|
Error: name field may not be omitted before dune version 1.1
|
||||||
|
[1]
|
Loading…
Reference in New Issue