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:
Rudi Grinberg 2018-07-31 10:15:31 +02:00 committed by GitHub
parent a13325e389
commit 835a44ff1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 150 additions and 36 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 :: _ ->

View File

@ -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))

View File

@ -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)

View File

@ -0,0 +1 @@
(executables (public_names foo bar))

View File

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

View File

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

View File

@ -0,0 +1 @@
(executable (public_name foo))

View File

@ -0,0 +1 @@
(executables (public_names bar baz))

View File

@ -0,0 +1 @@
(library (public_name foo))

View File

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

View File

@ -0,0 +1 @@
(library (public_name foo))

View File

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

View File

@ -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]