2022-03-04 20:32:03 +03:00
|
|
|
(* This file is part of the Catala compiler, a specification language for tax
|
|
|
|
and social benefits computation rules. Copyright (C) 2022 Inria, OCamlPro;
|
|
|
|
contributors: Louis Gesbert <louis.gesbert@ocamlpro.com>
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
|
|
use this file except in compliance with the License. You may obtain a copy of
|
|
|
|
the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
License for the specific language governing permissions and limitations under
|
|
|
|
the License. *)
|
|
|
|
|
2022-11-21 12:46:17 +03:00
|
|
|
open Catala_utils
|
2023-06-28 16:57:52 +03:00
|
|
|
open Cmdliner
|
2022-11-21 12:46:17 +03:00
|
|
|
|
2023-06-28 16:57:52 +03:00
|
|
|
type t = unit Cmdliner.Cmd.t
|
2023-04-13 22:49:16 +03:00
|
|
|
|
2022-03-04 20:32:03 +03:00
|
|
|
let backend_plugins : (string, t) Hashtbl.t = Hashtbl.create 17
|
|
|
|
|
2023-06-28 16:57:52 +03:00
|
|
|
let register info term =
|
|
|
|
let name = String.lowercase_ascii (Cmd.name (Cmd.v info (Term.const ()))) in
|
|
|
|
Hashtbl.replace backend_plugins name
|
|
|
|
(Cmd.v info Term.(term $ Cli.Flags.Global.options))
|
2023-06-15 18:37:52 +03:00
|
|
|
|
|
|
|
let list () = Hashtbl.to_seq_values backend_plugins |> List.of_seq
|
2023-06-28 16:57:52 +03:00
|
|
|
let names () = Hashtbl.to_seq_keys backend_plugins |> List.of_seq
|
2024-02-21 14:06:38 +03:00
|
|
|
let load_failures = Hashtbl.create 17
|
|
|
|
|
|
|
|
let print_failures () =
|
|
|
|
if Hashtbl.length load_failures > 0 then
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.warning "Some plugins could not be loaded:@,%a"
|
2024-02-22 14:14:25 +03:00
|
|
|
(Format.pp_print_seq (fun ppf -> Format.fprintf ppf " - %s"))
|
|
|
|
(Hashtbl.to_seq_values load_failures)
|
2024-02-21 14:06:38 +03:00
|
|
|
|
2022-03-04 20:32:03 +03:00
|
|
|
let load_file f =
|
|
|
|
try
|
|
|
|
Dynlink.loadfile f;
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.debug "Plugin %S loaded" f
|
2023-07-11 19:36:41 +03:00
|
|
|
with
|
|
|
|
| Dynlink.Error (Dynlink.Module_already_loaded s) ->
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.debug "Plugin %S (%s) was already loaded, skipping" f s
|
2024-02-21 14:06:38 +03:00
|
|
|
| Dynlink.Error err ->
|
|
|
|
let msg = Dynlink.error_message err in
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.debug "Could not load plugin %S: %s" f msg;
|
2024-02-21 14:06:38 +03:00
|
|
|
Hashtbl.add load_failures f msg
|
2024-04-10 19:39:30 +03:00
|
|
|
| e -> Message.warning "Could not load plugin %S: %s" f (Printexc.to_string e)
|
2022-03-04 20:32:03 +03:00
|
|
|
|
2023-09-01 18:09:31 +03:00
|
|
|
let load_dir d =
|
2024-04-10 19:39:30 +03:00
|
|
|
Message.debug "Loading plugins from %s" d;
|
2022-03-04 20:32:03 +03:00
|
|
|
let dynlink_exts =
|
|
|
|
if Dynlink.is_native then [".cmxs"] else [".cmo"; ".cma"]
|
|
|
|
in
|
2023-09-01 18:09:31 +03:00
|
|
|
let rec aux d =
|
|
|
|
Array.iter
|
|
|
|
(fun f ->
|
|
|
|
if f.[0] = '.' then ()
|
|
|
|
else
|
|
|
|
let f = Filename.concat d f in
|
2023-09-27 13:58:35 +03:00
|
|
|
match Sys.is_directory f with
|
|
|
|
| true -> aux f
|
|
|
|
| false ->
|
|
|
|
if List.exists (Filename.check_suffix f) dynlink_exts then
|
|
|
|
load_file f
|
|
|
|
| exception Sys_error _ -> ())
|
2023-09-01 18:09:31 +03:00
|
|
|
(Sys.readdir d)
|
|
|
|
in
|
|
|
|
aux d
|