Add (modes ...) for executables

This commit is contained in:
Jeremie Dimino 2017-05-29 14:06:52 +01:00
parent b52d778d4c
commit 9f8803af67
6 changed files with 71 additions and 15 deletions

View File

@ -205,10 +205,11 @@ the ``ocamlrun`` virtual machine as well as the byte code. As such you
can always rely on ``<name>.exe`` being available. can always rely on ``<name>.exe`` being available.
Native compilation is considered not available when there is no Native compilation is considered not available when there is no
``ocamlopt`` binary at the same place as where ``ocamlc`` was found. ``ocamlopt`` binary at the same place as where ``ocamlc`` was found,
or when there is a ``(modes (...))`` field not listing ``native``.
``<optional-fields>`` are: ``<optional-fields>`` are:
0
- ``(public_name <public-name>)`` specifies that the executable - ``(public_name <public-name>)`` specifies that the executable
should be installed under that name. It is the same as adding the should be installed under that name. It is the same as adding the
following stanza to your ``jbuild`` file: following stanza to your ``jbuild`` file:
@ -231,6 +232,11 @@ Native compilation is considered not available when there is no
the current stanza. It is interpreted in the same way as the ``(modules the current stanza. It is interpreted in the same way as the ``(modules
...)`` field of `library`_ ...)`` field of `library`_
- ``(modes (<modes>))`` modes (``byte`` and ``native``) which should be built by
default. If the stanza has a ``(public_name ...)`` field and
``native`` is not listed here, the byte-code version will be
installed instead.
- ``(preprocess <preprocess-spec>)`` is the same as the ``(preprocess ...)`` - ``(preprocess <preprocess-spec>)`` is the same as the ``(preprocess ...)``
field of `library`_ field of `library`_

View File

@ -306,8 +306,8 @@ module Gen(P : Params) = struct
in in
let static = stubs_archive lib ~dir in let static = stubs_archive lib ~dir in
let dynamic = dll lib ~dir in let dynamic = dll lib ~dir in
if List.mem Mode.Native ~set:lib.modes && if lib.modes.native &&
List.mem Mode.Byte ~set:lib.modes && lib.modes.byte &&
lib.dynlink lib.dynlink
then begin then begin
(* If we build for both modes and support dynlink, use a single invocation to (* If we build for both modes and support dynlink, use a single invocation to
@ -384,12 +384,13 @@ module Gen(P : Params) = struct
| Executables stuff | | Executables stuff |
+-----------------------------------------------------------------+ *) +-----------------------------------------------------------------+ *)
let build_exe ~js_of_ocaml ~flags ~dir ~requires ~name ~mode ~modules ~dep_graph ~link_flags = let build_exe ~js_of_ocaml ~flags ~dir ~requires ~name ~mode ~modules ~dep_graph
~link_flags ~force_custom_bytecode =
let exe_ext = Mode.exe_ext mode in let exe_ext = Mode.exe_ext mode in
let mode, link_flags, compiler = let mode, link_flags, compiler =
match Context.compiler ctx mode with match force_custom_bytecode, Context.compiler ctx mode with
| Some compiler -> (mode, link_flags, compiler) | false, Some compiler -> (mode, link_flags, compiler)
| None -> (Byte, "-custom" :: link_flags, ctx.ocamlc) | _ -> (Byte, "-custom" :: link_flags, ctx.ocamlc)
in in
let dep_graph = Ml_kind.Dict.get dep_graph Impl in let dep_graph = Ml_kind.Dict.get dep_graph Impl in
let exe = Path.relative dir (name ^ exe_ext) in let exe = Path.relative dir (name ^ exe_ext) in
@ -462,7 +463,8 @@ module Gen(P : Params) = struct
List.iter exes.names ~f:(fun name -> List.iter exes.names ~f:(fun name ->
List.iter Mode.all ~f:(fun mode -> List.iter Mode.all ~f:(fun mode ->
build_exe ~js_of_ocaml:exes.buildable.js_of_ocaml ~flags ~dir ~requires ~name build_exe ~js_of_ocaml:exes.buildable.js_of_ocaml ~flags ~dir ~requires ~name
~mode ~modules ~dep_graph ~link_flags:exes.link_flags)); ~mode ~modules ~dep_graph ~link_flags:exes.link_flags
~force_custom_bytecode:(mode = Native && not exes.modes.native)));
{ Merlin. { Merlin.
requires = real_requires requires = real_requires
; flags = flags.common ; flags = flags.common
@ -770,8 +772,7 @@ module Gen(P : Params) = struct
Install.Entry.make section fn Install.Entry.make section fn
?dst:(Option.map sub_dir ~f:(fun d -> sprintf "%s/%s" d (Path.basename fn))) ?dst:(Option.map sub_dir ~f:(fun d -> sprintf "%s/%s" d (Path.basename fn)))
in in
let byte = List.mem Mode.Byte ~set:lib.modes in let { Mode.Dict. byte; native } = lib.modes in
let native = List.mem Mode.Native ~set:lib.modes in
let if_ cond l = if cond then l else [] in let if_ cond l = if cond then l else [] in
let files = let files =
let modules = let modules =

View File

@ -512,7 +512,7 @@ module Library = struct
; synopsis : string option ; synopsis : string option
; install_c_headers : string list ; install_c_headers : string list
; ppx_runtime_libraries : string list ; ppx_runtime_libraries : string list
; modes : Mode.t list ; modes : Mode.Dict.Set.t
; kind : Kind.t ; kind : Kind.t
; c_flags : Ordered_set_lang.Unexpanded.t ; c_flags : Ordered_set_lang.Unexpanded.t
; c_names : string list ; c_names : string list
@ -544,7 +544,7 @@ module Library = struct
field "library_flags" (list String_with_vars.t) ~default:[] >>= fun library_flags -> field "library_flags" (list String_with_vars.t) ~default:[] >>= fun library_flags ->
field_oslu "c_library_flags" >>= fun c_library_flags -> field_oslu "c_library_flags" >>= fun c_library_flags ->
field "virtual_deps" (list string) ~default:[] >>= fun virtual_deps -> field "virtual_deps" (list string) ~default:[] >>= fun virtual_deps ->
field "modes" (list Mode.t) ~default:Mode.all >>= fun modes -> field "modes" Mode.Dict.Set.t ~default:Mode.Dict.Set.all >>= fun modes ->
field "kind" Kind.t ~default:Kind.Normal >>= fun kind -> field "kind" Kind.t ~default:Kind.Normal >>= fun kind ->
field "wrapped" bool ~default:true >>= fun wrapped -> field "wrapped" bool ~default:true >>= fun wrapped ->
field_b "optional" >>= fun optional -> field_b "optional" >>= fun optional ->
@ -623,6 +623,7 @@ module Executables = struct
{ names : string list { names : string list
; link_executables : bool ; link_executables : bool
; link_flags : string list ; link_flags : string list
; modes : Mode.Dict.Set.t
; buildable : Buildable.t ; buildable : Buildable.t
} }
@ -630,19 +631,28 @@ module Executables = struct
Buildable.v1 >>= fun buildable -> Buildable.v1 >>= fun buildable ->
field "link_executables" bool ~default:true >>= fun link_executables -> field "link_executables" bool ~default:true >>= fun link_executables ->
field "link_flags" (list string) ~default:[] >>= fun link_flags -> field "link_flags" (list string) ~default:[] >>= fun link_flags ->
map_validate (field "modes" Mode.Dict.Set.t ~default:Mode.Dict.Set.all)
~f:(fun modes ->
if Mode.Dict.Set.is_empty modes then
Error "No compilation mode defined."
else
Ok modes)
>>= fun modes ->
let t = let t =
{ names { names
; link_executables ; link_executables
; link_flags ; link_flags
; modes
; buildable ; buildable
} }
in in
let to_install = let to_install =
let ext = if modes.native then ".exe" else ".bc" 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. src = name ^ ".exe"; dst = Some pub })) | Some pub -> Some ({ Install_conf. src = name ^ ext; dst = Some pub }))
|> List.filter_map ~f:(fun x -> x) |> List.filter_map ~f:(fun x -> x)
in in
match to_install with match to_install with

View File

@ -47,4 +47,32 @@ module Dict = struct
{ byte = f a.byte b.byte { byte = f a.byte b.byte
; native = f a.native b.native ; native = f a.native b.native
} }
module Set = struct
type nonrec t = bool t
let all =
{ byte = true
; native = true
}
let to_list t =
let l = [] in
let l = if t.native then Native :: l else l in
let l = if t.byte then Byte :: l else l in
l
let of_list l =
{ byte = List.mem Byte ~set:l
; native = List.mem Native ~set:l
}
let t sexp = of_list (Sexp.Of_sexp.list t sexp)
let is_empty t = not (t.byte || t.native)
let iter t ~f =
if t.byte then f Byte;
if t.native then f Native
end
end end

View File

@ -28,4 +28,14 @@ module Dict : sig
val of_func : (mode:mode -> 'a) -> 'a t val of_func : (mode:mode -> 'a) -> 'a t
val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t
module Set : sig
type nonrec t = bool t
val t : t Sexp.Of_sexp.t
val all : t
val is_empty : t -> bool
val to_list : t -> mode list
val of_list : mode list -> t
val iter : t -> f:(mode -> unit) -> unit
end
end with type mode := t end with type mode := t

View File

@ -88,7 +88,8 @@ let build_module sctx ?sandbox ~dynlink ~js_of_ocaml ~flags m ~dir ~dep_graph
let src = Module.cm_file m ~dir Cm_kind.Cmo in let src = Module.cm_file m ~dir Cm_kind.Cmo in
SC.add_rules sctx (Js_of_ocaml_rules.build_cm sctx ~dir ~js_of_ocaml ~src) SC.add_rules sctx (Js_of_ocaml_rules.build_cm sctx ~dir ~js_of_ocaml ~src)
let build_modules sctx ~dynlink ~js_of_ocaml ~flags ~dir ~dep_graph ~modules ~requires ~alias_module = let build_modules sctx ~dynlink ~js_of_ocaml ~flags ~dir ~dep_graph ~modules ~requires
~alias_module =
let cmi_requires = let cmi_requires =
Build.memoize "cmi library dependencies" Build.memoize "cmi library dependencies"
(requires (requires