Skip to content

Commit

Permalink
Allow to configure link_flags in env (#5215)
Browse files Browse the repository at this point in the history
- Allow to configure link_flags in env
- duplicate link_flags to handle cxx_default_flags

Signed-off-by: Hugo Heuzard <[email protected]>
  • Loading branch information
hhugo authored Dec 14, 2021
1 parent 1a8df76 commit 44c9a93
Show file tree
Hide file tree
Showing 24 changed files with 229 additions and 18 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ Unreleased
- Delete old `promote-into`, `promote-until-clean` and `promote-until-clean-into`
syntax (#5091, Andrey Mokhov).

- Add link_flags in the env stanza (#5215)

2.9.2 (unreleased)
------------------

Expand Down
3 changes: 3 additions & 0 deletions doc/dune-files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,9 @@ Fields supported in ``<settings>`` are:

- any OCaml flags field. See :ref:`ocaml-flags` for more details.

- ``(link_flags <flags>)`` to specify flags to ocaml when linking an
executable. See :ref:`executables stanza <shared-exe-fields>`.

- ``(c_flags <flags>)`` and ``(cxx_flags <flags>)``
to specify compilation flags for C and C++ stubs, respectively.
See `library`_ for more details.
Expand Down
3 changes: 2 additions & 1 deletion src/dune_rules/cxx_flags.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ let base_cxx_flags ~for_ cc =
| Clang, Compile -> [ "-x"; "c++" ]
| Clang, Link -> [ "-lc++" ]
| Msvc, Compile -> [ "/TP" ]
| _ -> []
| Msvc, Link -> []
| Other _, (Link | Compile) -> []

let preprocessed_filename = "ccomp"

Expand Down
6 changes: 6 additions & 0 deletions src/dune_rules/dune_env.ml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ module Stanza = struct
type config =
{ flags : Ocaml_flags.Spec.t
; foreign_flags : Ordered_set_lang.Unexpanded.t Foreign_language.Dict.t
; link_flags : Link_flags.Spec.t
; env_vars : Env.t
; binaries : File_binding.Unexpanded.t list
; inline_tests : Inline_tests.t option
Expand All @@ -87,6 +88,7 @@ module Stanza = struct
let equal_config
{ flags
; foreign_flags
; link_flags
; env_vars
; binaries
; inline_tests
Expand All @@ -99,6 +101,7 @@ module Stanza = struct
Ocaml_flags.Spec.equal flags t.flags
&& Foreign_language.Dict.equal Ordered_set_lang.Unexpanded.equal
foreign_flags t.foreign_flags
&& Link_flags.Spec.equal link_flags t.link_flags
&& Env.equal env_vars t.env_vars
&& List.equal File_binding.Unexpanded.equal binaries t.binaries
&& Option.equal Inline_tests.equal inline_tests t.inline_tests
Expand All @@ -114,6 +117,7 @@ module Stanza = struct
{ flags = Ocaml_flags.Spec.standard
; foreign_flags =
Foreign_language.Dict.make_both Ordered_set_lang.Unexpanded.standard
; link_flags = Link_flags.Spec.standard
; env_vars = Env.empty
; binaries = []
; inline_tests = None
Expand Down Expand Up @@ -181,6 +185,7 @@ module Stanza = struct
let config =
let+ flags = Ocaml_flags.Spec.decode
and+ foreign_flags = foreign_flags ~since:(Some (1, 7))
and+ link_flags = Link_flags.Spec.decode ~since:(Some (3, 0))
and+ env_vars = env_vars_field
and+ binaries =
field ~default:[] "binaries"
Expand All @@ -194,6 +199,7 @@ module Stanza = struct
and+ format_config = Format_config.field ~since:(2, 8) in
{ flags
; foreign_flags
; link_flags
; env_vars
; binaries
; inline_tests
Expand Down
1 change: 1 addition & 0 deletions src/dune_rules/dune_env.mli
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ module Stanza : sig
type config =
{ flags : Ocaml_flags.Spec.t
; foreign_flags : Ordered_set_lang.Unexpanded.t Foreign_language.Dict.t
; link_flags : Link_flags.Spec.t
; env_vars : Env.t
; binaries : File_binding.Unexpanded.t list
; inline_tests : Inline_tests.t option
Expand Down
6 changes: 3 additions & 3 deletions src/dune_rules/dune_file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1381,7 +1381,7 @@ module Executables = struct

type t =
{ names : (Loc.t * string) list
; link_flags : Ordered_set_lang.Unexpanded.t
; link_flags : Link_flags.Spec.t
; link_deps : Dep_conf.t list
; modes : Loc.t Link_mode.Map.t
; optional : bool
Expand Down Expand Up @@ -1411,7 +1411,7 @@ module Executables = struct
field "link_executables" ~default:true
(Dune_lang.Syntax.deleted_in Stanza.syntax (1, 0) >>> bool)
and+ link_deps = field "link_deps" (repeat Dep_conf.decode) ~default:[]
and+ link_flags = Ordered_set_lang.Unexpanded.field "link_flags"
and+ link_flags = Link_flags.Spec.decode ~since:None
and+ modes =
field "modes" Link_mode.Map.decode
~default:(Link_mode.Map.default_for_exes ~version:dune_version)
Expand Down Expand Up @@ -1941,7 +1941,7 @@ module Tests = struct
String_with_vars.add_user_vars_to_decoding_env (Bindings.var_names deps)
(let* dune_version = Dune_lang.Syntax.get_exn Stanza.syntax in
let+ buildable = Buildable.decode Executable
and+ link_flags = Ordered_set_lang.Unexpanded.field "link_flags"
and+ link_flags = Link_flags.Spec.decode ~since:None
and+ names = names
and+ package = field_o "package" Stanza_common.Pkg.decode
and+ locks =
Expand Down
2 changes: 1 addition & 1 deletion src/dune_rules/dune_file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ module Executables : sig

type t =
{ names : (Loc.t * string) list
; link_flags : Ordered_set_lang.Unexpanded.t
; link_flags : Link_flags.Spec.t
; link_deps : Dep_conf.t list
; modes : Loc.t Link_mode.Map.t
; optional : bool
Expand Down
14 changes: 13 additions & 1 deletion src/dune_rules/env_node.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type t =
; local_binaries : File_binding.Expanded.t list Memo.Lazy.t
; ocaml_flags : Ocaml_flags.t Memo.Lazy.t
; foreign_flags : string list Action_builder.t Foreign_language.Dict.t
; link_flags : Link_flags.t Memo.Lazy.t
; external_env : Env.t Memo.Lazy.t
; bin_artifacts : Artifacts.Bin.t Memo.Lazy.t
; inline_tests : Dune_env.Stanza.Inline_tests.t Memo.Lazy.t
Expand All @@ -36,6 +37,8 @@ let ocaml_flags t = Memo.Lazy.force t.ocaml_flags

let foreign_flags t = t.foreign_flags

let link_flags t = Memo.Lazy.force t.link_flags

let external_env t = Memo.Lazy.force t.external_env

let bin_artifacts t = Memo.Lazy.force t.bin_artifacts
Expand All @@ -58,7 +61,7 @@ let coq t = Memo.Lazy.force t.coq

let make ~dir ~inherit_from ~scope ~config_stanza ~profile ~expander
~expander_for_artifacts ~default_context_flags ~default_env
~default_bin_artifacts =
~default_bin_artifacts ~default_cxx_link_flags =
let open Memo.Build.O in
let config = Dune_env.Stanza.find config_stanza ~profile in
let inherited ~field ~root extend =
Expand Down Expand Up @@ -167,6 +170,14 @@ let make ~dir ~inherit_from ~scope ~config_stanza ~profile ~expander
let foreign_flags =
Foreign_language.Dict.make ~c:(foreign_flags C) ~cxx:(foreign_flags Cxx)
in
let link_flags =
let default_link_flags = Link_flags.default ~default_cxx_link_flags in
inherited ~field:link_flags ~root:default_link_flags (fun link_flags ->
let+ expander = Memo.Lazy.force expander in
let expander = Expander.set_dir expander ~dir in
Link_flags.make ~spec:config.link_flags ~default:link_flags
~eval:(Expander.expand_and_eval_set expander))
in
let menhir_flags =
inherited
~field:(fun t -> Memo.Build.return (menhir_flags t))
Expand Down Expand Up @@ -208,6 +219,7 @@ let make ~dir ~inherit_from ~scope ~config_stanza ~profile ~expander
{ scope
; ocaml_flags
; foreign_flags
; link_flags
; external_env
; bin_artifacts
; local_binaries
Expand Down
3 changes: 3 additions & 0 deletions src/dune_rules/env_node.mli
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ val make :
-> default_context_flags:string list Action_builder.t Foreign_language.Dict.t
-> default_env:Env.t
-> default_bin_artifacts:Artifacts.Bin.t
-> default_cxx_link_flags:string list Action_builder.t
-> t

val scope : t -> Scope.t
Expand All @@ -43,6 +44,8 @@ val js_of_ocaml :

val foreign_flags : t -> string list Action_builder.t Foreign_language.Dict.t

val link_flags : t -> Link_flags.t Memo.Build.t

val local_binaries : t -> File_binding.Expanded.t list Memo.Build.t

val bin_artifacts : t -> Artifacts.Bin.t Memo.Build.t
Expand Down
17 changes: 9 additions & 8 deletions src/dune_rules/exe_rules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -173,18 +173,19 @@ let executables_rules ~sctx ~dir ~expander ~dir_contents ~scope ~compile_info
files directly to improve perf. *)
let link_deps, sandbox = Dep_conf_eval.unnamed ~expander exes.link_deps in
let link_args =
let standard =
let use_standard_cxx_flags =
match Dune_project.use_standard_c_and_cxx_flags project with
| Some true when Buildable.has_foreign_cxx exes.buildable ->
let open Action_builder.O in
let+ flags = Cxx_flags.get_flags ~for_:Link ctx in
List.concat_map flags ~f:(fun f -> [ "-cclib"; f ])
| _ -> Action_builder.return []
| Some true -> Buildable.has_foreign_cxx exes.buildable
| _ -> false
in
let open Action_builder.O in
let link_flags =
link_deps
>>> Expander.expand_and_eval_set expander exes.link_flags ~standard
let* () = link_deps in
let* link_flags =
Action_builder.memo_build
(Super_context.link_flags sctx ~dir exes.link_flags)
in
Link_flags.get ~use_standard_cxx_flags link_flags
in
let+ flags = link_flags
and+ ctypes_cclib_flags =
Expand Down
61 changes: 61 additions & 0 deletions src/dune_rules/link_flags.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
open! Dune_engine
open! Stdune
open Import
open Action_builder.O

(* flags are duplicated because we want to have two sets of default (:standard)
flags. [link_flags_cxx] will be used for executable with foreign_cxx when
[use_standard_cxx_flags] is true *)
type 'a t' =
{ link_flags : 'a
; link_flags_cxx : 'a
}

module Spec = struct
type t = Ordered_set_lang.Unexpanded.t t'

let standard =
let standard = Ordered_set_lang.Unexpanded.standard in
{ link_flags = standard; link_flags_cxx = standard }

let decode ~since =
let open Dune_lang.Decoder in
let check =
Option.map since ~f:(fun since ->
Dune_lang.Syntax.since Stanza.syntax since)
in
let+ flags = Ordered_set_lang.Unexpanded.field "link_flags" ?check in
{ link_flags = flags; link_flags_cxx = flags }

let equal { link_flags; link_flags_cxx } t =
Ordered_set_lang.Unexpanded.equal link_flags t.link_flags
&& Ordered_set_lang.Unexpanded.equal link_flags_cxx t.link_flags_cxx
end

type t = string list Action_builder.t t'

let default ~default_cxx_link_flags =
let link_flags_cxx =
let+ flags = default_cxx_link_flags in
List.concat_map flags ~f:(fun f -> [ "-cclib"; f ])
in
{ link_flags = Action_builder.return []; link_flags_cxx }

let make ~spec ~default ~eval =
let f name x standard = Action_builder.memoize name (eval x ~standard) in
{ link_flags = f "link flags" spec.link_flags default.link_flags
; link_flags_cxx =
f "link flags cxx" spec.link_flags_cxx default.link_flags_cxx
}

let get ~use_standard_cxx_flags (t : t) =
if use_standard_cxx_flags then
t.link_flags_cxx
else
t.link_flags

let dump t =
let+ link_flags = t.link_flags in
List.map
~f:Dune_lang.Encoder.(pair string (list string))
[ ("link_flags", link_flags) ]
32 changes: 32 additions & 0 deletions src/dune_rules/link_flags.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
(** OCaml flags *)
open! Dune_engine

open! Stdune

type t

module Spec : sig
type t

val equal : t -> t -> bool

val decode :
since:Dune_lang.Syntax.Version.t option -> t Dune_lang.Decoder.fields_parser

val standard : t
end

val make :
spec:Spec.t
-> default:t
-> eval:
( Ordered_set_lang.Unexpanded.t
-> standard:string list Action_builder.t
-> string list Action_builder.t)
-> t

val default : default_cxx_link_flags:string list Action_builder.t -> t

val get : use_standard_cxx_flags:bool -> t -> string list Action_builder.t

val dump : t -> Dune_lang.t list Action_builder.t
19 changes: 16 additions & 3 deletions src/dune_rules/super_context.ml
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,11 @@ end = struct
in
extend_expander t ~dir ~expander_for_artifacts)
in
let default_cxx_link_flags = Cxx_flags.get_flags ~for_:Link t.context in
Env_node.make ~dir ~scope ~config_stanza ~inherit_from:(Some inherit_from)
~profile:t.context.profile ~expander ~expander_for_artifacts
~default_context_flags ~default_env:t.context_env
~default_bin_artifacts:t.bin_artifacts
~default_bin_artifacts:t.bin_artifacts ~default_cxx_link_flags

(* Here we jump through some hoops to construct [t] as well as create a
memoization table that has access to [t] and is used in [t.get_node].
Expand Down Expand Up @@ -402,6 +403,12 @@ let foreign_flags t ~dir ~expander ~flags ~language =
in
Action_builder.memoize (sprintf "%s flags" name) flags

let link_flags t ~dir (spec : Link_flags.Spec.t) =
let* expander = Env_tree.expander t.env_tree ~dir in
let+ link_flags = get_node t.env_tree ~dir >>= Env_node.link_flags in
Link_flags.make ~spec ~default:link_flags
~eval:(Expander.expand_and_eval_set expander)

let menhir_flags t ~dir ~expander ~flags =
let t = t.env_tree in
let default =
Expand All @@ -422,6 +429,7 @@ let dump_env t ~dir =
let t = t.env_tree in
let ocaml_flags = get_node t ~dir >>= Env_node.ocaml_flags in
let foreign_flags = get_node t ~dir >>| Env_node.foreign_flags in
let link_flags = get_node t ~dir >>= Env_node.link_flags in
let menhir_flags = get_node t ~dir >>| Env_node.menhir_flags in
let coq_flags = get_node t ~dir >>= Env_node.coq in
let js_of_ocaml = get_node t ~dir >>= Env_node.js_of_ocaml in
Expand All @@ -436,6 +444,9 @@ let dump_env t ~dir =
List.map
~f:Dune_lang.Encoder.(pair string (list string))
[ ("c_flags", c_flags); ("cxx_flags", cxx_flags) ]
and+ link_flags_dump =
let* link_flags = Action_builder.memo_build link_flags in
Link_flags.dump link_flags
and+ menhir_dump =
let+ flags = Action_builder.memo_build_join menhir_flags in
[ ("menhir_flags", flags) ]
Expand All @@ -448,7 +459,8 @@ let dump_env t ~dir =
let* jsoo = Action_builder.memo_build js_of_ocaml in
Js_of_ocaml.Flags.dump jsoo.flags
in
List.concat [ o_dump; c_dump; menhir_dump; coq_dump; jsoo_dump ]
List.concat
[ o_dump; c_dump; link_flags_dump; menhir_dump; coq_dump; jsoo_dump ]

let resolve_program t ~dir ?hint ~loc bin =
let t = t.env_tree in
Expand Down Expand Up @@ -700,11 +712,12 @@ let create ~(context : Context.t) ~host ~projects ~packages ~stanzas =
Code_error.raise
"[expander_for_artifacts] in [default_env] is undefined" [])
in
let default_cxx_link_flags = Cxx_flags.get_flags ~for_:Link context in
let expander = Memo.Lazy.of_val root_expander in
Env_node.make ~dir ~scope ~inherit_from ~config_stanza
~profile:context.profile ~expander ~expander_for_artifacts
~default_context_flags ~default_env:context_env
~default_bin_artifacts:artifacts.bin
~default_bin_artifacts:artifacts.bin ~default_cxx_link_flags
in
Memo.Build.return
(make ~config_stanza:context.env_nodes.context
Expand Down
3 changes: 3 additions & 0 deletions src/dune_rules/super_context.mli
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ val foreign_flags :
-> language:Foreign_language.t
-> string list Action_builder.t

val link_flags :
t -> dir:Path.Build.t -> Link_flags.Spec.t -> Link_flags.t Memo.Build.t

val menhir_flags :
t
-> dir:Path.Build.t
Expand Down
Loading

0 comments on commit 44c9a93

Please sign in to comment.