-
Notifications
You must be signed in to change notification settings - Fork 455
OSL handling for {c,cxx}_names #1788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d261067
9d60dda
17f4430
675bce5
eebe359
57f0a70
3e552b5
eb2dd62
2457a84
28dd2ee
dfa7625
479807c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| open Stdune | ||
|
|
||
| module Kind = struct | ||
| type t = | ||
| | C | ||
| | Cxx | ||
|
|
||
| let pp fmt t : unit = | ||
| match t with | ||
| | C -> Format.pp_print_string fmt "c" | ||
| | Cxx -> Format.pp_print_string fmt "cpp" | ||
|
|
||
| let split_extension fn = | ||
| match String.lsplit2 fn ~on:'.' with | ||
| | Some (obj, "c") -> Some (obj, C) | ||
| | Some (obj, "cpp") -> Some (obj, Cxx) | ||
| | _ -> None | ||
|
|
||
| let possible_fns t fn = | ||
| match t with | ||
| | C -> [fn ^ ".c"] | ||
| | Cxx -> [fn ^ ".cpp"] | ||
|
|
||
| module Dict = struct | ||
| type 'a t = | ||
| { c : 'a | ||
| ; cxx : 'a | ||
| } | ||
|
|
||
| let make a = | ||
| { c = a | ||
| ; cxx = a | ||
| } | ||
|
|
||
| let get { c; cxx } = function | ||
| | C -> c | ||
| | Cxx -> cxx | ||
|
|
||
| let add t k v = | ||
| match k with | ||
| | C -> { t with c = v } | ||
| | Cxx -> { t with cxx = v } | ||
|
|
||
| let update t k ~f = | ||
| let v = get t k in | ||
| add t k (f v) | ||
|
|
||
| let merge t1 t2 ~f = | ||
| { c = f t1.c t2.c | ||
| ; cxx = f t1.cxx t2.cxx | ||
| } | ||
| end | ||
| end | ||
|
|
||
| module Source = struct | ||
| type t = | ||
| { kind : Kind.t | ||
| ; path : Path.t | ||
| } | ||
|
|
||
| let kind t = t.kind | ||
| let path t = t.path | ||
| let src_dir t = Path.parent_exn t.path | ||
|
|
||
| let make ~kind ~path = | ||
| { kind | ||
| ; path | ||
| } | ||
| end | ||
|
|
||
| module Sources = struct | ||
| type t = (Loc.t * Source.t) String.Map.t | ||
|
|
||
| let objects (t : t) ~dir ~ext_obj = | ||
| String.Map.keys t | ||
| |> List.map ~f:(fun c -> Path.relative dir (c ^ ext_obj)) | ||
|
|
||
| let split_by_kind t = | ||
| let (c, cxx) = | ||
| String.Map.partition t ~f:(fun (_, s) -> | ||
| match (Source.kind s : Kind.t) with | ||
| | C -> true | ||
| | Cxx -> false) | ||
| in | ||
| {Kind.Dict. c; cxx} | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| open Stdune | ||
|
|
||
| module Kind : sig | ||
| type t = | ||
| | C | ||
| | Cxx | ||
|
|
||
| val pp : t Fmt.t | ||
|
|
||
| val split_extension : string -> (string * t) option | ||
|
|
||
| (** [possible_fns t s] returns the possible filenames given the extension-less | ||
| basenames [s] *) | ||
| val possible_fns : t -> string -> string list | ||
|
|
||
| module Dict : sig | ||
| type kind | ||
| type 'a t = | ||
| { c : 'a | ||
| ; cxx : 'a | ||
| } | ||
|
|
||
| val make : 'a -> 'a t | ||
|
|
||
| val update : 'a t -> kind -> f:('a -> 'a) -> 'a t | ||
|
|
||
| val merge : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t | ||
| end with type kind := t | ||
| end | ||
|
|
||
| module Source : sig | ||
| type t | ||
|
|
||
| val kind : t -> Kind.t | ||
| val path : t -> Path.t | ||
| val src_dir : t -> Path.t | ||
|
|
||
| val make : kind:Kind.t -> path:Path.t -> t | ||
| end | ||
|
|
||
| module Sources : sig | ||
| type t = (Loc.t * Source.t) String.Map.t | ||
|
|
||
| val objects : t -> dir:Path.t -> ext_obj:string -> Path.t list | ||
|
|
||
| val split_by_kind : t -> t Kind.Dict.t | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| open Stdune | ||
| open Dune_file | ||
|
|
||
| module Library = Dune_file.Library | ||
|
|
||
| type t = | ||
| { libraries : C.Sources.t Lib_name.Map.t | ||
| } | ||
|
|
||
| let for_lib t ~dir ~name = | ||
| match Lib_name.Map.find t.libraries name with | ||
| | Some m -> m | ||
| | None -> | ||
| Exn.code_error "C_sources.for_lib" | ||
| [ "name", Lib_name.to_sexp name | ||
| ; "dir", Path.to_sexp dir | ||
| ; "available", Sexp.Encoder.(list Lib_name.to_sexp) | ||
| (Lib_name.Map.keys t.libraries) | ||
| ] | ||
|
|
||
| let empty = | ||
| { libraries = Lib_name.Map.empty | ||
| } | ||
|
|
||
| let c_name, cxx_name = | ||
| let make what ~loc s = | ||
| if match s with | ||
| | "" | "." | ".." -> true | ||
| | _ -> false then | ||
| Errors.fail loc "%S is not a valid %s name." s what | ||
| else | ||
| s | ||
| in | ||
| ( make "C" | ||
| , make "C++" | ||
| ) | ||
|
|
||
| module Eval = struct | ||
| module Value = struct | ||
| type t = string | ||
| type key = string | ||
| let key s = s | ||
| end | ||
|
|
||
| include Ordered_set_lang.Make_loc(String)(Value) | ||
| end | ||
|
|
||
| let load_sources ~dir ~files = | ||
| let init = C.Kind.Dict.make String.Map.empty in | ||
| String.Set.fold files ~init ~f:(fun fn acc -> | ||
| match C.Kind.split_extension fn with | ||
| | None -> acc | ||
| | Some (obj, kind) -> | ||
| let path = Path.relative dir fn in | ||
| C.Kind.Dict.update acc kind ~f:(fun v -> | ||
| String.Map.add v obj (C.Source.make ~kind ~path) | ||
| )) | ||
|
|
||
| let make (d : _ Dir_with_dune.t) | ||
| ~(c_sources : C.Source.t String.Map.t C.Kind.Dict.t) = | ||
| let libs = | ||
| List.filter_map d.data ~f:(fun stanza -> | ||
| match (stanza : Stanza.t) with | ||
| | Library lib -> | ||
| let eval (kind : C.Kind.t) (c_sources : C.Source.t String.Map.t) | ||
| validate osl = | ||
| Eval.eval_unordered osl | ||
| ~parse:(fun ~loc s -> | ||
| let s = validate ~loc s in | ||
| let s' = Filename.basename s in | ||
| if s' <> s then begin | ||
| Errors.warn loc "relative part of stub are no longer \ | ||
| necessary and are ignored." | ||
| end; | ||
| s' | ||
| ) | ||
| ~standard:String.Map.empty | ||
| |> String.Map.map ~f:(fun (loc, s) -> | ||
| match String.Map.find c_sources s with | ||
| | Some source -> (loc, source) | ||
| | None -> | ||
| Errors.fail loc "%s does not exist as a C source. \ | ||
| One of %s must be present" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpicking, but when there is a single element in it would read nicer as: |
||
| s (String.enumerate_or (C.Kind.possible_fns kind s)) | ||
| ) | ||
| in | ||
| let names = | ||
| Option.value ~default:Ordered_set_lang.standard in | ||
| let c = eval C.Kind.C c_sources.c c_name (names lib.c_names) in | ||
| let cxx = eval C.Kind.Cxx c_sources.cxx cxx_name (names lib.cxx_names) in | ||
| let all = String.Map.union c cxx ~f:(fun _ (_loc1, c) (loc2, cxx) -> | ||
| Errors.fail loc2 "%a source file is invalid because %a exists" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error message suggestion: |
||
| Path.pp_in_source (C.Source.path cxx) | ||
| Path.pp_in_source (C.Source.path c) | ||
| ) in | ||
| Some (lib, all) | ||
| | _ -> None | ||
| ) | ||
| in | ||
| let libraries = | ||
| match | ||
| Lib_name.Map.of_list_map libs ~f:(fun (lib, m) -> | ||
| Library.best_name lib, m) | ||
| with | ||
| | Ok x -> x | ||
| | Error (name, _, (lib2, _)) -> | ||
| Errors.fail lib2.buildable.loc | ||
| "Library %a appears for the second time \ | ||
| in this directory" | ||
| Lib_name.pp_quoted name | ||
| in | ||
| let () = | ||
| let rev_map = | ||
| List.concat_map libs ~f:(fun (_, c_sources) -> | ||
| String.Map.values c_sources | ||
| |> List.map ~f:(fun (loc, source) -> | ||
| (C.Source.path source, loc))) | ||
| |> Path.Map.of_list | ||
| in | ||
| match rev_map with | ||
| | Ok _ -> () | ||
| | Error (_, loc1, loc2) -> | ||
| Errors.fail loc2 | ||
| "This c stub is already used in another stanza:@\n\ | ||
| @[<v>%a@]@\n" | ||
| (Fmt.prefix (Fmt.string "- ") Loc.pp_file_colon_line) | ||
| loc1 | ||
| in | ||
| { libraries | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| open Stdune | ||
|
|
||
| type t | ||
|
|
||
| val empty : t | ||
|
|
||
| val for_lib : t -> dir:Path.t -> name:Lib_name.t -> C.Sources.t | ||
|
|
||
| val load_sources | ||
| : dir:Path.t | ||
| -> files:String.Set.t | ||
| -> C.Source.t String.Map.t C.Kind.Dict.t | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these functions deserve a comment to explain what the |
||
|
|
||
| val make | ||
| : Stanza.t list Dir_with_dune.t | ||
| -> c_sources:C.Source.t String.Map.t C.Kind.Dict.t | ||
| -> t | ||
Uh oh!
There was an error while loading. Please reload this page.