Skip to content

Commit

Permalink
Merge pull request #1764 from diml/more-enabled-if
Browse files Browse the repository at this point in the history
Allow the `enabled_if` field in `library` stanzas
  • Loading branch information
rgrinberg authored May 16, 2019
2 parents c4b7311 + 1e59fa4 commit 620e8e8
Show file tree
Hide file tree
Showing 18 changed files with 153 additions and 25 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ unreleased
- Make `dune subst` add a `(version ...)` field to the `dune-project`
file (#2148, @diml)

- Add the `%{os_type}` variable, which is a short-hand for
`%{ocaml-config:os_type}` (#1764, @diml)

- Allow `enabled_if` fields in `library` stanzas, restricted to the
`%{os_type}` variable (#1764, @diml)

1.9.3 (06/05/2019)
------------------

Expand Down
10 changes: 10 additions & 0 deletions doc/dune-files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ to use the :ref:`include_subdirs` stanza.
we were waiting for proper support for virtual libraries. Do not use
in new code, it will be deleted in dune 2.0

- ``(enabled_if <blang expression>)`` allows to conditionally disable
a library. A disabled library cannot be built and will not be
installed. The condition is specified using the blang_, and the
field allows for the ``%{os_type}`` variable, which is expanded to
the type of OS being targeted by the current build. Its value is
the same as the value of the ``os_type`` parameter in the output of
``ocamlc -config``

Note that when binding C libraries, dune doesn't provide special support for
tools such as ``pkg-config``, however it integrates easily with configurator_ by
using ``(c_flags (:include ...))`` and ``(c_library_flags (:include ...))``.
Expand Down Expand Up @@ -1087,6 +1095,8 @@ Dune supports the following variables:
- ``profile`` the profile selected via ``--profile``
- ``context_name`` the name of the context (``default`` or defined in the
workspace file)
- ``os_type`` is the type of the OS the build is targetting. This is
the same as ``ocaml-config:os_type``

In addition, ``(action ...)`` fields support the following special variables:

Expand Down
14 changes: 14 additions & 0 deletions src/blang.ml
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,17 @@ let decode =
and+ decode = decode
in
decode

let rec fold_vars t ~init ~f =
match t with
| Const _ -> init
| Expr sw -> String_with_vars.fold_vars sw ~init ~f
| And l | Or l -> fold_vars_list l ~init ~f
| Compare (_, x, y) ->
String_with_vars.fold_vars y ~f
~init:(String_with_vars.fold_vars x ~f ~init)

and fold_vars_list ts ~init ~f =
match ts with
| [] -> init
| t :: ts -> fold_vars_list ts ~f ~init:(fold_vars t ~init ~f)
2 changes: 2 additions & 0 deletions src/blang.mli
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type t =

val true_ : t

val fold_vars : t -> init:'a -> f:(String_with_vars.Var.t -> 'a -> 'a) -> 'a

val eval
: t
-> dir:Path.t
Expand Down
1 change: 1 addition & 0 deletions src/context.ml
Original file line number Diff line number Diff line change
Expand Up @@ -702,4 +702,5 @@ let lib_config t =
has_native = has_native t
; ext_obj = t.ext_obj
; ext_lib = t.ext_lib
; os_type = t.os_type
}
33 changes: 23 additions & 10 deletions src/dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,13 @@ module Preprocess = struct
]))
end


let enabled_if =
field "enabled_if" ~default:Blang.true_
(Syntax.since Stanza.syntax (1, 4) >>> Blang.decode)
let enabled_if ~since =
let decode =
match since with
| None -> Blang.decode
| Some since -> Syntax.since Stanza.syntax since >>> Blang.decode
in
field "enabled_if" ~default:Blang.true_ decode

module Per_module = struct
include Per_item.Make(Module.Name)
Expand Down Expand Up @@ -896,6 +899,7 @@ module Library = struct
; private_modules : Ordered_set_lang.t option
; stdlib : Stdlib.t option
; special_builtin_support : Special_builtin_support.t option
; enabled_if : Blang.t
}

let decode =
Expand Down Expand Up @@ -956,7 +960,7 @@ module Library = struct
field_o "special_builtin_support"
(Syntax.since Stanza.syntax (1, 10) >>>
Special_builtin_support.decode)
in
and+ enabled_if = enabled_if ~since:(Some (1, 10)) in
let wrapped = Wrapped.make ~wrapped ~implements in
let name =
let open Syntax.Version.Infix in
Expand Down Expand Up @@ -1021,6 +1025,14 @@ module Library = struct
"A library cannot use (self_build_stubs_archive ...) \
and (%s ...) simultaneously." name
in
Blang.fold_vars enabled_if ~init:() ~f:(fun var () ->
match String_with_vars.Var.name var,
String_with_vars.Var.payload var with
| "os_type", None -> ()
| _ ->
Errors.fail (String_with_vars.Var.loc var)
"Only the 'os_type' variable is allowed in the 'enabled_if' \
field of libraries.");
{ name
; public
; synopsis
Expand Down Expand Up @@ -1050,6 +1062,7 @@ module Library = struct
; private_modules
; stdlib
; special_builtin_support
; enabled_if
})

let has_stubs t =
Expand Down Expand Up @@ -1659,7 +1672,7 @@ module Rule = struct
| false, Some mode -> Ok mode
| true, None -> Ok Fallback
| false, None -> Ok Standard)
and+ enabled_if = enabled_if
and+ enabled_if = enabled_if ~since:(Some (1, 4))
in
{ targets
; deps
Expand Down Expand Up @@ -1732,7 +1745,7 @@ module Rule = struct
record
(let+ modules = field "modules" (list string)
and+ mode = Mode.field
and+ enabled_if = enabled_if
and+ enabled_if = enabled_if ~since:(Some (1, 4))
in
{ modules; mode; enabled_if }))
~else_:(
Expand Down Expand Up @@ -1818,7 +1831,7 @@ module Menhir = struct
and+ mode = Rule.Mode.field
and+ infer = field_o_b "infer" ~check:(Syntax.since syntax (2, 0))
and+ menhir_syntax = Syntax.get_exn syntax
and+ enabled_if = enabled_if
and+ enabled_if = enabled_if ~since:(Some (1, 4))
and+ loc = loc
in
let infer =
Expand Down Expand Up @@ -1911,7 +1924,7 @@ module Coq = struct
and+ modules = modules_field "modules"
and+ libraries =
field "libraries" (list (located Lib_name.decode)) ~default:[]
and+ enabled_if = enabled_if
and+ enabled_if = enabled_if ~since:None
in
let name =
let (loc, res) = name in
Expand Down Expand Up @@ -2016,7 +2029,7 @@ module Tests = struct
~default:Executables.Link_mode.Set.default
and+ deps =
field "deps" (Bindings.decode Dep_conf.decode) ~default:Bindings.empty
and+ enabled_if = enabled_if
and+ enabled_if = enabled_if ~since:(Some (1, 4))
and+ action =
field_o
"action"
Expand Down
1 change: 1 addition & 0 deletions src/dune_file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ module Library : sig
; private_modules : Ordered_set_lang.t option
; stdlib : Stdlib.t option
; special_builtin_support : Special_builtin_support.t option
; enabled_if : Blang.t
}

val has_stubs : t -> bool
Expand Down
18 changes: 12 additions & 6 deletions src/lib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -891,12 +891,16 @@ let rec instantiate db name (info : Lib_info.t) ~stack ~hidden =
let res =
let hidden =
match hidden with
| None ->
Option.some_if
(info.optional &&
not (Result.is_ok t.requires && Result.is_ok t.ppx_runtime_deps))
"optional with unavailable dependencies"
| Some _ -> hidden
| None ->
match info.enabled with
| Normal -> None
| Optional ->
Option.some_if
(not (Result.is_ok t.requires && Result.is_ok t.ppx_runtime_deps))
"optional with unavailable dependencies"
| Disabled_because_of_enabled_if ->
Some "unsatisfied 'enabled_if'"
in
match hidden with
| None -> St_found t
Expand Down Expand Up @@ -1265,7 +1269,9 @@ module Compile = struct
make_lib_deps_info
~user_written_deps:(Lib_info.user_written_deps t.info)
~pps:t.info.pps
~kind:(Lib_deps_info.Kind.of_optional t.info.optional)
~kind:(match t.info.enabled with
| Normal -> Required
| _ -> Optional)
in
let requires_link = lazy (
t.requires >>= closure_with_overlap_checks
Expand Down
1 change: 1 addition & 0 deletions src/lib_config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ type t =
{ has_native : bool
; ext_lib : string
; ext_obj : string
; os_type : string
}
30 changes: 26 additions & 4 deletions src/lib_info.ml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ module Source = struct
| External of 'a
end

module Enabled_status = struct
type t =
| Normal
| Optional
| Disabled_because_of_enabled_if
end

type t =
{ loc : Loc.t
; name : Lib_name.t
Expand All @@ -66,7 +73,7 @@ type t =
; requires : Deps.t
; ppx_runtime_deps : (Loc.t * Lib_name.t) list
; pps : (Loc.t * Lib_name.t) list
; optional : bool
; enabled : Enabled_status.t
; virtual_deps : (Loc.t * Lib_name.t) list
; dune_version : Syntax.Version.t option
; sub_systems : Sub_system_info.t Sub_system_name.Map.t
Expand All @@ -86,7 +93,7 @@ let user_written_deps t =
~f:(fun acc s -> Dune_file.Lib_dep.Direct s :: acc)

let of_library_stanza ~dir
~lib_config:{ Lib_config.has_native; ext_lib; ext_obj}
~lib_config:{ Lib_config.has_native; ext_lib; ext_obj; os_type}
(conf : Dune_file.Library.t) =
let (_loc, lib_name) = conf.name in
let obj_dir =
Expand Down Expand Up @@ -154,6 +161,21 @@ let of_library_stanza ~dir
let main_module_name = Dune_file.Library.main_module_name conf in
let name = Dune_file.Library.best_name conf in
let modes = Dune_file.Mode_conf.Set.eval ~has_native conf.modes in
let enabled =
let enabled_if_result =
Blang.eval conf.enabled_if ~dir ~f:(fun v _ver ->
match String_with_vars.Var.name v,
String_with_vars.Var.payload v with
| "os_type", None -> Some [String os_type]
| _ -> None)
in
if not enabled_if_result then
Enabled_status.Disabled_because_of_enabled_if
else if conf.optional then
Optional
else
Normal
in
{ loc = conf.buildable.loc
; name
; kind = conf.kind
Expand All @@ -164,7 +186,7 @@ let of_library_stanza ~dir
; synopsis = conf.synopsis
; archives
; plugins
; optional = conf.optional
; enabled
; foreign_objects
; foreign_archives
; jsoo_runtime
Expand Down Expand Up @@ -219,7 +241,7 @@ let of_dune_lib dp =
; jsoo_runtime = Lib.jsoo_runtime dp
; jsoo_archive = None
; pps = []
; optional = false
; enabled = Normal
; virtual_deps = []
; dune_version = None
; sub_systems = Lib.sub_systems dp
Expand Down
9 changes: 8 additions & 1 deletion src/lib_info.mli
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ module Source : sig
| External of 'a
end

module Enabled_status : sig
type t =
| Normal
| Optional
| Disabled_because_of_enabled_if
end

type t = private
{ loc : Loc.t
; name : Lib_name.t
Expand All @@ -47,7 +54,7 @@ type t = private
; requires : Deps.t
; ppx_runtime_deps : (Loc.t * Lib_name.t) list
; pps : (Loc.t * Lib_name.t) list
; optional : bool
; enabled : Enabled_status.t
; virtual_deps : (Loc.t * Lib_name.t) list
; dune_version : Syntax.Version.t option
; sub_systems : Sub_system_info.t Sub_system_name.Map.t
Expand Down
2 changes: 2 additions & 0 deletions src/pform.ml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ module Map = struct
; "workspace_root" , values [Value.Dir context.build_dir]
; "context_name" , string (Context.name context)
; "ROOT" , renamed_in ~version:(1, 0) ~new_name:"workspace_root"
; "os_type" , since ~version:(1, 10)
(Var.Values [String context.os_type])
]
in
{ vars =
Expand Down
7 changes: 4 additions & 3 deletions src/scope.ml
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,14 @@ module DB = struct
~f:(fun _name project libs ->
let project = Option.value_exn project in
let libs = Option.value libs ~default:[] in
let db = Lib.DB.create_from_library_stanzas libs
~parent:public_libs ~lib_config in
let db = Lib.DB.create_from_library_stanzas libs ~parent:public_libs
~lib_config in
let root =
Path.append_source build_context_dir (Dune_project.root project) in
Some { project; db; root })

let create ~projects ~context ~installed_libs ~lib_config internal_libs =
let create ~projects ~context ~installed_libs ~lib_config
internal_libs =
let t = Fdecl.create () in
let public_libs = public_libs t ~installed_libs internal_libs in
let by_name =
Expand Down
9 changes: 9 additions & 0 deletions src/string_with_vars.ml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,15 @@ let known_prefix =
| Var v :: _ -> Partial (String.concat ~sep:"" (List.rev acc), v)
in
fun t -> go t.template.parts []
let fold_vars =
let rec loop parts acc f =
match parts with
| [] -> acc
| Text _ :: parts -> loop parts acc f
| Var v :: parts -> loop parts (f v acc) f
in
fun t ~init ~f ->
loop t.template.parts init f

type 'a expander = Var.t -> Syntax.Version.t -> 'a

Expand Down
1 change: 1 addition & 0 deletions src/string_with_vars.mli
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ val known_prefix : t -> known_prefix
val is_suffix : t -> suffix:string -> yes_no_unknown

val is_prefix : t -> prefix:string -> yes_no_unknown
val fold_vars : t -> init:'a -> f:(Var.t -> 'a -> 'a) -> 'a

type 'a expander = Var.t -> Syntax.Version.t -> 'a

Expand Down
19 changes: 19 additions & 0 deletions test/blackbox-tests/test-cases/enabled_if/dune
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,22 @@
(echo "Building file b")
(with-stdout-to b (progn))))
(enabled_if true))

(library
(name foo)
(modules)
(enabled_if false))

(library
(name bar)
(modules)
(libraries foo))

(library
(name baz)
(modules)
(libraries bar))

(rule (with-stdout-to main.ml (echo "")))

(executable (name main) (libraries baz))
2 changes: 1 addition & 1 deletion test/blackbox-tests/test-cases/enabled_if/dune-project
Original file line number Diff line number Diff line change
@@ -1 +1 @@
(lang dune 1.4)
(lang dune 1.10)
Loading

0 comments on commit 620e8e8

Please sign in to comment.