diff options
Diffstat (limited to 'sysinit')
| -rw-r--r-- | sysinit/coqargs.ml | 500 | ||||
| -rw-r--r-- | sysinit/coqargs.mli | 106 | ||||
| -rw-r--r-- | sysinit/coqinit.ml | 136 | ||||
| -rw-r--r-- | sysinit/coqinit.mli | 58 | ||||
| -rw-r--r-- | sysinit/coqloadpath.ml | 73 | ||||
| -rw-r--r-- | sysinit/coqloadpath.mli | 16 | ||||
| -rw-r--r-- | sysinit/dune | 7 | ||||
| -rw-r--r-- | sysinit/sysinit.mllib | 4 | ||||
| -rw-r--r-- | sysinit/usage.ml | 112 | ||||
| -rw-r--r-- | sysinit/usage.mli | 28 |
10 files changed, 1040 insertions, 0 deletions
diff --git a/sysinit/coqargs.ml b/sysinit/coqargs.ml new file mode 100644 index 0000000000..c4f12f6bb7 --- /dev/null +++ b/sysinit/coqargs.ml @@ -0,0 +1,500 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +let fatal_error exn = + Topfmt.(in_phase ~phase:ParsingCommandLine print_err_exn exn); + let exit_code = if (CErrors.is_anomaly exn) then 129 else 1 in + exit exit_code + +let error_wrong_arg msg = + prerr_endline msg; exit 1 + +let error_missing_arg s = + prerr_endline ("Error: extra argument expected after option "^s); + prerr_endline "See -help for the syntax of supported options"; + exit 1 + +(******************************************************************************) +(* Imperative effects! This must be fixed at some point. *) +(******************************************************************************) + +let set_debug () = + let () = Exninfo.record_backtrace true in + Flags.debug := true + +(******************************************************************************) + +type native_compiler = Coq_config.native_compiler = + NativeOff | NativeOn of { ondemand : bool } + +type top = TopLogical of Names.DirPath.t | TopPhysical of string + +type option_command = + | OptionSet of string option + | OptionUnset + | OptionAppend of string + +type injection_command = + | OptionInjection of (Goptions.option_name * option_command) + | RequireInjection of (string * string option * bool option) + +type coqargs_logic_config = { + impredicative_set : Declarations.set_predicativity; + indices_matter : bool; + type_in_type : bool; + toplevel_name : top; +} + +type coqargs_config = { + logic : coqargs_logic_config; + rcfile : string option; + coqlib : string option; + enable_VM : bool; + native_compiler : native_compiler; + native_output_dir : CUnix.physical_path; + native_include_dirs : CUnix.physical_path list; + debug : bool; + time : bool; + print_emacs : bool; +} + +type coqargs_pre = { + boot : bool; + load_init : bool; + load_rcfile : bool; + + ml_includes : string list; + vo_includes : Loadpath.vo_path list; + + load_vernacular_list : (string * bool) list; + injections : injection_command list; + + inputstate : string option; +} + +type coqargs_query = + | PrintWhere | PrintConfig + | PrintVersion | PrintMachineReadableVersion + | PrintHelp of Usage.specific_usage + +type coqargs_main = + | Queries of coqargs_query list + | Run + +type coqargs_post = { + memory_stat : bool; +} + +type t = { + config : coqargs_config; + pre : coqargs_pre; + main : coqargs_main; + post : coqargs_post; +} + +let default_toplevel = Names.(DirPath.make [Id.of_string "Top"]) + +let default_native = Coq_config.native_compiler + +let default_logic_config = { + impredicative_set = Declarations.PredicativeSet; + indices_matter = false; + type_in_type = false; + toplevel_name = TopLogical default_toplevel; +} + +let default_config = { + logic = default_logic_config; + rcfile = None; + coqlib = None; + enable_VM = true; + native_compiler = default_native; + native_output_dir = ".coq-native"; + native_include_dirs = []; + debug = false; + time = false; + print_emacs = false; + + (* Quiet / verbosity options should be here *) +} + +let default_pre = { + boot = false; + load_init = true; + load_rcfile = true; + ml_includes = []; + vo_includes = []; + load_vernacular_list = []; + injections = []; + inputstate = None; +} + +let default_queries = [] + +let default_post = { + memory_stat = false; +} + +let default = { + config = default_config; + pre = default_pre; + main = Run; + post = default_post; +} + +(******************************************************************************) +(* Functional arguments *) +(******************************************************************************) +let add_ml_include opts s = + { opts with pre = { opts.pre with ml_includes = s :: opts.pre.ml_includes }} + +let add_vo_include opts unix_path coq_path implicit = + let open Loadpath in + let coq_path = Libnames.dirpath_of_string coq_path in + { opts with pre = { opts.pre with vo_includes = { + unix_path; coq_path; has_ml = false; implicit; recursive = true } :: opts.pre.vo_includes }} + +let add_vo_require opts d p export = + { opts with pre = { opts.pre with injections = RequireInjection (d, p, export) :: opts.pre.injections }} + +let add_load_vernacular opts verb s = + { opts with pre = { opts.pre with load_vernacular_list = (CUnix.make_suffix s ".v",verb) :: opts.pre.load_vernacular_list }} + +let add_set_option opts opt_name value = + { opts with pre = { opts.pre with injections = OptionInjection (opt_name, value) :: opts.pre.injections }} + +(** Options for proof general *) +let set_emacs opts = + let opts = add_set_option opts Printer.print_goal_tag_opt_name (OptionSet None) in + { opts with config = { opts.config with print_emacs = true }} + +let set_logic f oval = + { oval with config = { oval.config with logic = f oval.config.logic }} + +let set_query opts q = + { opts with main = match opts.main with + | Run -> Queries (default_queries@[q]) + | Queries queries -> Queries (queries@[q]) + } + +let warn_deprecated_sprop_cumul = + CWarnings.create ~name:"deprecated-spropcumul" ~category:"deprecated" + (fun () -> Pp.strbrk "Use the \"Cumulative StrictProp\" flag instead.") + +let warn_deprecated_inputstate = + CWarnings.create ~name:"deprecated-inputstate" ~category:"deprecated" + (fun () -> Pp.strbrk "The inputstate option is deprecated and discouraged.") + +let set_inputstate opts s = + warn_deprecated_inputstate (); + { opts with pre = { opts.pre with inputstate = Some s }} + +(******************************************************************************) +(* Parsing helpers *) +(******************************************************************************) +let get_bool ~opt = function + | "yes" | "on" -> true + | "no" | "off" -> false + | _ -> + error_wrong_arg ("Error: yes/no expected after option "^opt) + +let get_int ~opt n = + try int_of_string n + with Failure _ -> + error_wrong_arg ("Error: integer expected after option "^opt) +let get_int_opt ~opt n = + if n = "" then None + else Some (get_int ~opt n) + +let get_float ~opt n = + try float_of_string n + with Failure _ -> + error_wrong_arg ("Error: float expected after option "^opt) + +let interp_set_option opt v old = + let open Goptions in + let opt = String.concat " " opt in + match old with + | BoolValue _ -> BoolValue (get_bool ~opt v) + | IntValue _ -> IntValue (get_int_opt ~opt v) + | StringValue _ -> StringValue v + | StringOptValue _ -> StringOptValue (Some v) + +let set_option = let open Goptions in function + | opt, OptionUnset -> unset_option_value_gen ~locality:OptLocal opt + | opt, OptionSet None -> set_bool_option_value_gen ~locality:OptLocal opt true + | opt, OptionSet (Some v) -> set_option_value ~locality:OptLocal (interp_set_option opt) opt v + | opt, OptionAppend v -> set_string_option_append_value_gen ~locality:OptLocal opt v + +let get_compat_file = function + | "8.14" -> "Coq.Compat.Coq814" + | "8.13" -> "Coq.Compat.Coq813" + | "8.12" -> "Coq.Compat.Coq812" + | "8.11" -> "Coq.Compat.Coq811" + | ("8.10" | "8.9" | "8.8" | "8.7" | "8.6" | "8.5" | "8.4" | "8.3" | "8.2" | "8.1" | "8.0") as s -> + CErrors.user_err ~hdr:"get_compat_file" + Pp.(str "Compatibility with version " ++ str s ++ str " not supported.") + | s -> + CErrors.user_err ~hdr:"get_compat_file" + Pp.(str "Unknown compatibility version \"" ++ str s ++ str "\".") + +let to_opt_key = Str.(split (regexp " +")) + +let parse_option_set opt = + match String.index_opt opt '=' with + | None -> to_opt_key opt, None + | Some eqi -> + let len = String.length opt in + let v = String.sub opt (eqi+1) (len - eqi - 1) in + to_opt_key (String.sub opt 0 eqi), Some v + +let warn_no_native_compiler = + CWarnings.create ~name:"native-compiler-disabled" ~category:"native-compiler" + Pp.(fun s -> strbrk "Native compiler is disabled," ++ + strbrk " -native-compiler " ++ strbrk s ++ + strbrk " option ignored.") + +let get_native_compiler s = + (* We use two boolean flags because the four states make sense, even if + only three are accessible to the user at the moment. The selection of the + produced artifact(s) (`.vo`, `.vio`, `.coq-native`, ...) should be done by + a separate flag, and the "ondemand" value removed. Once this is done, use + [get_bool] here. *) + let n = match s with + | ("yes" | "on") -> NativeOn {ondemand=false} + | "ondemand" -> NativeOn {ondemand=true} + | ("no" | "off") -> NativeOff + | _ -> + error_wrong_arg ("Error: (yes|no|ondemand) expected after option -native-compiler") in + if Coq_config.native_compiler = NativeOff && n <> NativeOff then + let () = warn_no_native_compiler s in + NativeOff + else + n + +(* Main parsing routine *) +(*s Parsing of the command line *) + +let parse_args ~usage ~init arglist : t * string list = + let args = ref arglist in + let extras = ref [] in + let rec parse oval = match !args with + | [] -> + (oval, List.rev !extras) + | opt :: rem -> + args := rem; + let next () = match !args with + | x::rem -> args := rem; x + | [] -> error_missing_arg opt + in + let noval = begin match opt with + + (* Complex options with many args *) + |"-I"|"-include" -> + begin match rem with + | d :: rem -> + args := rem; + add_ml_include oval d + | [] -> error_missing_arg opt + end + |"-Q" -> + begin match rem with + | d :: p :: rem -> + args := rem; + add_vo_include oval d p false + | _ -> error_missing_arg opt + end + |"-R" -> + begin match rem with + | d :: p :: rem -> + args := rem; + add_vo_include oval d p true + | _ -> error_missing_arg opt + end + + (* Options with one arg *) + |"-coqlib" -> + { oval with config = { oval.config with coqlib = Some (next ()) + }} + + |"-compat" -> + add_vo_require oval (get_compat_file (next ())) None (Some false) + + |"-exclude-dir" -> + System.exclude_directory (next ()); oval + + |"-init-file" -> + { oval with config = { oval.config with rcfile = Some (next ()); }} + + |"-inputstate"|"-is" -> + set_inputstate oval (next ()) + + |"-load-vernac-object" -> + add_vo_require oval (next ()) None None + + |"-load-vernac-source"|"-l" -> + add_load_vernacular oval false (next ()) + + |"-load-vernac-source-verbose"|"-lv" -> + add_load_vernacular oval true (next ()) + + |"-mangle-names" -> + let oval = add_set_option oval ["Mangle"; "Names"] (OptionSet None) in + add_set_option oval ["Mangle"; "Names"; "Prefix"] (OptionSet(Some(next ()))) + + |"-profile-ltac-cutoff" -> + Flags.profile_ltac := true; + Flags.profile_ltac_cutoff := get_float ~opt (next ()); + oval + + |"-rfrom" -> + let from = next () in add_vo_require oval (next ()) (Some from) None + + |"-require-import" | "-ri" -> add_vo_require oval (next ()) None (Some false) + + |"-require-export" | "-re" -> add_vo_require oval (next ()) None (Some true) + + |"-require-import-from" | "-rifrom" -> + let from = next () in add_vo_require oval (next ()) (Some from) (Some false) + + |"-require-export-from" | "-refrom" -> + let from = next () in add_vo_require oval (next ()) (Some from) (Some true) + + |"-top" -> + let topname = Libnames.dirpath_of_string (next ()) in + if Names.DirPath.is_empty topname then + CErrors.user_err Pp.(str "Need a non empty toplevel module name"); + { oval with config = { oval.config with logic = { oval.config.logic with toplevel_name = TopLogical topname }}} + + |"-topfile" -> + { oval with config = { oval.config with logic = { oval.config.logic with toplevel_name = TopPhysical (next()) }}} + + |"-w" | "-W" -> + let w = next () in + if w = "none" then add_set_option oval ["Warnings"] (OptionSet(Some w)) + else add_set_option oval ["Warnings"] (OptionAppend w) + + |"-bytecode-compiler" -> + { oval with config = { oval.config with enable_VM = get_bool ~opt (next ()) }} + + |"-native-compiler" -> + let native_compiler = get_native_compiler (next ()) in + { oval with config = { oval.config with native_compiler }} + + | "-set" -> + let opt, v = parse_option_set @@ next() in + add_set_option oval opt (OptionSet v) + + | "-unset" -> + add_set_option oval (to_opt_key @@ next ()) OptionUnset + + |"-native-output-dir" -> + let native_output_dir = next () in + { oval with config = { oval.config with native_output_dir } } + + |"-nI" -> + let include_dir = next () in + { oval with config = {oval.config with native_include_dirs = include_dir :: oval.config.native_include_dirs } } + + (* Options with zero arg *) + |"-test-mode" -> Vernacinterp.test_mode := true; oval + |"-beautify" -> Flags.beautify := true; oval + |"-bt" -> Exninfo.record_backtrace true; oval + |"-config"|"--config" -> set_query oval PrintConfig + |"-debug" -> set_debug (); oval + |"-xml-debug" -> Flags.xml_debug := true; set_debug (); oval + |"-diffs" -> + add_set_option oval Proof_diffs.opt_name @@ OptionSet (Some (next ())) + |"-emacs" -> set_emacs oval + |"-impredicative-set" -> + set_logic (fun o -> { o with impredicative_set = Declarations.ImpredicativeSet }) oval + |"-allow-sprop" -> + add_set_option oval Vernacentries.allow_sprop_opt_name (OptionSet None) + |"-disallow-sprop" -> + add_set_option oval Vernacentries.allow_sprop_opt_name OptionUnset + |"-sprop-cumulative" -> + warn_deprecated_sprop_cumul(); + add_set_option oval Vernacentries.cumul_sprop_opt_name (OptionSet None) + |"-indices-matter" -> set_logic (fun o -> { o with indices_matter = true }) oval + |"-m"|"--memory" -> { oval with post = { memory_stat = true }} + |"-noinit"|"-nois" -> { oval with pre = { oval.pre with load_init = false }} + |"-boot" -> { oval with pre = { oval.pre with boot = true }} + |"-profile-ltac" -> Flags.profile_ltac := true; oval + |"-q" -> { oval with pre = { oval.pre with load_rcfile = false; }} + |"-quiet"|"-silent" -> + Flags.quiet := true; + Flags.make_warn false; + oval + |"-time" -> { oval with config = { oval.config with time = true }} + |"-type-in-type" -> set_logic (fun o -> { o with type_in_type = true }) oval + |"-unicode" -> add_vo_require oval "Utf8_core" None (Some false) + |"-where" -> set_query oval PrintWhere + |"-h"|"-H"|"-?"|"-help"|"--help" -> set_query oval (PrintHelp usage) + |"-v"|"--version" -> set_query oval PrintVersion + |"-print-version"|"--print-version" -> set_query oval PrintMachineReadableVersion + + (* Unknown option *) + | s -> + extras := s :: !extras; + oval + end in + parse noval + in + try + parse init + with any -> fatal_error any + +(* We need to reverse a few lists *) +let parse_args ~usage ~init args = + let opts, extra = parse_args ~usage ~init args in + let opts = + { opts with + pre = { opts.pre with + ml_includes = List.rev opts.pre.ml_includes + ; vo_includes = List.rev opts.pre.vo_includes + ; load_vernacular_list = List.rev opts.pre.load_vernacular_list + ; injections = List.rev opts.pre.injections + } + } in + opts, extra + +(******************************************************************************) +(* Startup LoadPath and Modules *) +(******************************************************************************) +(* prelude_data == From Coq Require Import Prelude. *) +let prelude_data = "Prelude", Some "Coq", Some false + +let injection_commands opts = + if opts.pre.load_init then RequireInjection prelude_data :: opts.pre.injections else opts.pre.injections + +let build_load_path opts = + let ml_path, vo_path = + if opts.pre.boot then [],[] + else + let coqlib = Envars.coqlib () in + Coqloadpath.init_load_path ~coqlib in + ml_path @ opts.pre.ml_includes , + vo_path @ opts.pre.vo_includes + +let dirpath_of_file f = + let ldir0 = + try + let lp = Loadpath.find_load_path (Filename.dirname f) in + Loadpath.logical lp + with Not_found -> Libnames.default_root_prefix + in + let f = try Filename.chop_extension (Filename.basename f) with Invalid_argument _ -> f in + let id = Names.Id.of_string f in + let ldir = Libnames.add_dirpath_suffix ldir0 id in + ldir + +let dirpath_of_top = function + | TopPhysical f -> dirpath_of_file f + | TopLogical dp -> dp diff --git a/sysinit/coqargs.mli b/sysinit/coqargs.mli new file mode 100644 index 0000000000..aef50193f2 --- /dev/null +++ b/sysinit/coqargs.mli @@ -0,0 +1,106 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +val default_toplevel : Names.DirPath.t + +type native_compiler = Coq_config.native_compiler = + NativeOff | NativeOn of { ondemand : bool } + +type top = TopLogical of Names.DirPath.t | TopPhysical of string + +type option_command = + | OptionSet of string option + | OptionUnset + | OptionAppend of string + +type injection_command = + | OptionInjection of (Goptions.option_name * option_command) + (** Set flags or options before the initial state is ready. *) + | RequireInjection of (string * string option * bool option) + (** Require libraries before the initial state is + ready. Parameters follow [Library], that is to say, + [lib,prefix,import_export] means require library [lib] from + optional [prefix] and [import_export] if [Some false/Some true] + is used. *) + +type coqargs_logic_config = { + impredicative_set : Declarations.set_predicativity; + indices_matter : bool; + type_in_type : bool; + toplevel_name : top; +} + +type coqargs_config = { + logic : coqargs_logic_config; + rcfile : string option; + coqlib : string option; + enable_VM : bool; + native_compiler : native_compiler; + native_output_dir : CUnix.physical_path; + native_include_dirs : CUnix.physical_path list; + debug : bool; + time : bool; + print_emacs : bool; +} + +type coqargs_pre = { + boot : bool; + load_init : bool; + load_rcfile : bool; + + ml_includes : CUnix.physical_path list; + vo_includes : Loadpath.vo_path list; + + load_vernacular_list : (string * bool) list; + injections : injection_command list; + + inputstate : string option; +} + +type coqargs_query = + | PrintWhere | PrintConfig + | PrintVersion | PrintMachineReadableVersion + | PrintHelp of Usage.specific_usage + +type coqargs_main = + | Queries of coqargs_query list + | Run + +type coqargs_post = { + memory_stat : bool; +} + +type t = { + config : coqargs_config; + pre : coqargs_pre; + main : coqargs_main; + post : coqargs_post; +} + +(* Default options *) +val default : t + +val parse_args : usage:Usage.specific_usage -> init:t -> string list -> t * string list + +val injection_commands : t -> injection_command list +val build_load_path : t -> CUnix.physical_path list * Loadpath.vo_path list + +val dirpath_of_top : top -> Names.DirPath.t + +(* Common utilities *) + +val get_int : opt:string -> string -> int +val get_int_opt : opt:string -> string -> int option +val get_bool : opt:string -> string -> bool +val get_float : opt:string -> string -> float +val error_missing_arg : string -> 'a +val error_wrong_arg : string -> 'a + +val set_option : Goptions.option_name * option_command -> unit diff --git a/sysinit/coqinit.ml b/sysinit/coqinit.ml new file mode 100644 index 0000000000..16c8389de5 --- /dev/null +++ b/sysinit/coqinit.ml @@ -0,0 +1,136 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +(** GC tweaking *) + +(** Coq is a heavy user of persistent data structures and symbolic ASTs, so the + minor heap is heavily solicited. Unfortunately, the default size is far too + small, so we enlarge it a lot (128 times larger). + + To better handle huge memory consumers, we also augment the default major + heap increment and the GC pressure coefficient. +*) + +let set_gc_policy () = + Gc.set { (Gc.get ()) with + Gc.minor_heap_size = 32*1024*1024 (* 32Mwords x 8 bytes/word = 256Mb *) + ; Gc.space_overhead = 120 + } + +let set_gc_best_fit () = + Gc.set { (Gc.get ()) with + Gc.allocation_policy = 2 (* best-fit *) + ; Gc.space_overhead = 200 + } + +let init_gc () = + try + (* OCAMLRUNPARAM environment variable is set. + * In that case, we let ocamlrun to use the values provided by the user. + *) + ignore (Sys.getenv "OCAMLRUNPARAM") + + with Not_found -> + (* OCAMLRUNPARAM environment variable is not set. + * In this case, we put in place our preferred configuration. + *) + set_gc_policy (); + if Coq_config.caml_version_nums >= [4;10;0] then set_gc_best_fit () else () + +let init_ocaml () = + CProfile.init_profile (); + init_gc (); + Sys.catch_break false (* Ctrl-C is fatal during the initialisation *) + +let init_coqlib opts = match opts.Coqargs.config.Coqargs.coqlib with + | None when opts.Coqargs.pre.Coqargs.boot -> () + | None -> + Envars.set_coqlib ~fail:(fun msg -> CErrors.user_err Pp.(str msg)); + | Some s -> + Envars.set_user_coqlib s + +let print_query opts = let open Coqargs in function + | PrintVersion -> Usage.version () + | PrintMachineReadableVersion -> Usage.machine_readable_version () + | PrintWhere -> + let () = init_coqlib opts in + print_endline (Envars.coqlib ()) + | PrintHelp h -> Usage.print_usage stderr h + | PrintConfig -> + let () = init_coqlib opts in + Envars.print_config stdout Coq_config.all_src_dirs + +let parse_arguments ~parse_extra ~usage ?(initial_args=Coqargs.default) () = + let opts, extras = + Coqargs.parse_args ~usage ~init:initial_args + (List.tl (Array.to_list Sys.argv)) in + let customopts, extras = parse_extra extras in + if not (CList.is_empty extras) then begin + prerr_endline ("Don't know what to do with "^String.concat " " extras); + prerr_endline "See -help for the list of supported options"; + exit 1 + end; + match opts.Coqargs.main with + | Coqargs.Queries q -> List.iter (print_query opts) q; exit 0 + | Coqargs.Run -> opts, customopts + +let print_memory_stat () = + let open Pp in + (* -m|--memory from the command-line *) + Feedback.msg_notice + (str "total heap size = " ++ int (CObj.heap_size_kb ()) ++ str " kbytes" ++ fnl ()); + (* operf-macro interface: + https://github.com/OCamlPro/operf-macro *) + try + let fn = Sys.getenv "OCAML_GC_STATS" in + let oc = open_out fn in + Gc.print_stat oc; + close_out oc + with _ -> () + +let init_runtime opts = + let open Coqargs in + Lib.init (); + init_coqlib opts; + if opts.post.memory_stat then at_exit print_memory_stat; + Mltop.init_known_plugins (); + + (* Configuration *) + Global.set_engagement opts.config.logic.impredicative_set; + Global.set_indices_matter opts.config.logic.indices_matter; + Global.set_check_universes (not opts.config.logic.type_in_type); + Global.set_VM opts.config.enable_VM; + Flags.set_native_compiler (match opts.config.native_compiler with NativeOff -> false | NativeOn _ -> true); + Global.set_native_compiler (match opts.config.native_compiler with NativeOff -> false | NativeOn _ -> true); + + (* Native output dir *) + Nativelib.output_dir := opts.config.native_output_dir; + Nativelib.include_dirs := opts.config.native_include_dirs; + + (* Paths for loading stuff *) + let ml_load_path, vo_load_path = Coqargs.build_load_path opts in + List.iter Mltop.add_ml_dir ml_load_path; + List.iter Loadpath.add_vo_path vo_load_path; + + injection_commands opts + +let require_file (dir, from, exp) = + let mp = Libnames.qualid_of_string dir in + let mfrom = Option.map Libnames.qualid_of_string from in + Flags.silently (Vernacentries.vernac_require mfrom exp) [mp] + +let handle_injection = function + | Coqargs.RequireInjection r -> require_file r + (* | LoadInjection l -> *) + | Coqargs.OptionInjection o -> Coqargs.set_option o + +let start_library ~top injections = + Flags.verbosely Declaremods.start_library top; + List.iter handle_injection injections diff --git a/sysinit/coqinit.mli b/sysinit/coqinit.mli new file mode 100644 index 0000000000..bea2186d81 --- /dev/null +++ b/sysinit/coqinit.mli @@ -0,0 +1,58 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +(** Main etry point to the sysinit component, all other modules are private. + + The following API shoud be called in order, and the first 3 steps only once + since they initialize global data. On the contrary step 4 can be called + many times to init the compilation of a unit. +*) + +(** 1 initialization of OCaml's runtime + + Profiling, GC parameters and signals. Nothing specific to Coq per se, but + the defaults here are good for Coq. + This API should be called up very early, or not at all. *) +val init_ocaml : unit -> unit + +(** 2 parsing of Sys.argv + + This API parses command line options which are known by Coq components. + Ideally it is functional, but some values in the `Flags` modules are set + on the spot instead of being represented as "injection commands" (a field + of Coqargs.t). + + [parse_extra] and [usage] can be used to parse/document more options. *) +val parse_arguments : + parse_extra:(string list -> 'a * string list) -> + usage:Usage.specific_usage -> + ?initial_args:Coqargs.t -> + unit -> + Coqargs.t * 'a + +(** 3 initialization of global runtime data + + All global setup is done here, like COQLIB and the paths for native + compilation. If Coq is used to process multiple libraries, what is set up + here is really global and common to all of them. + + The returned injections are options (as in "Set This Thing" or "Require + that") as specified on the command line. + The prelude is one of these (unless "-nois" is passed). + + This API must be called, typically jsut after parsing arguments. *) +val init_runtime : Coqargs.t -> Coqargs.injection_command list + +(** 4 Start a library (sets options and loads objects like the prelude) + + Given the logical name [top] of the current library and the set of initial + options and required libraries, it starts its processing (see also + Declaremods.start_library) *) +val start_library : top:Names.DirPath.t -> Coqargs.injection_command list -> unit diff --git a/sysinit/coqloadpath.ml b/sysinit/coqloadpath.ml new file mode 100644 index 0000000000..8635345e00 --- /dev/null +++ b/sysinit/coqloadpath.ml @@ -0,0 +1,73 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +open Util +open Pp + +let ( / ) s1 s2 = Filename.concat s1 s2 + +(* Recursively puts `.v` files in the LoadPath *) +let build_stdlib_vo_path ~unix_path ~coq_path = + let open Loadpath in + { unix_path; coq_path ; has_ml = false; implicit = true; recursive = true } + +(* Note we don't use has_ml=true due to #12771 , we need to see if we + should just remove that option *) +let build_userlib_path ~unix_path = + let open Loadpath in + if Sys.file_exists unix_path then + let ml_path = System.all_subdirs ~unix_path |> List.map fst in + let vo_path = + { unix_path + ; coq_path = Libnames.default_root_prefix + ; has_ml = false + ; implicit = false + ; recursive = true + } in + ml_path, [vo_path] + else [], [] + +(* LoadPath for Coq user libraries *) +let init_load_path ~coqlib = + + let open Loadpath in + let user_contrib = coqlib/"user-contrib" in + let xdg_dirs = Envars.xdg_dirs ~warn:(fun x -> Feedback.msg_warning (str x)) in + let coqpath = Envars.coqpath in + let coq_path = Names.DirPath.make [Libnames.coq_root] in + + (* ML includes *) + let plugins_dirs = System.all_subdirs ~unix_path:(coqlib/"plugins") |> List.map fst in + + let contrib_ml, contrib_vo = build_userlib_path ~unix_path:user_contrib in + + let misc_ml, misc_vo = + List.map (fun s -> build_userlib_path ~unix_path:s) (xdg_dirs @ coqpath) |> List.split in + + let ml_loadpath = plugins_dirs @ contrib_ml @ List.concat misc_ml in + let vo_loadpath = + (* current directory (not recursively!) *) + [ { unix_path = "." + ; coq_path = Libnames.default_root_prefix + ; implicit = false + ; has_ml = true + ; recursive = false + } ] @ + + (* then standard library *) + [build_stdlib_vo_path ~unix_path:(coqlib/"theories") ~coq_path] @ + + (* then user-contrib *) + contrib_vo @ + + (* then directories in XDG_DATA_DIRS and XDG_DATA_HOME and COQPATH *) + List.concat misc_vo + in + ml_loadpath, vo_loadpath diff --git a/sysinit/coqloadpath.mli b/sysinit/coqloadpath.mli new file mode 100644 index 0000000000..d853e9ea54 --- /dev/null +++ b/sysinit/coqloadpath.mli @@ -0,0 +1,16 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +(** Standard LoadPath for Coq user libraries; in particular it + includes (in-order) Coq's standard library, Coq's [user-contrib] + folder, and directories specified in [COQPATH] and [XDG_DIRS] *) +val init_load_path + : coqlib:CUnix.physical_path + -> CUnix.physical_path list * Loadpath.vo_path list diff --git a/sysinit/dune b/sysinit/dune new file mode 100644 index 0000000000..04b46fb2a2 --- /dev/null +++ b/sysinit/dune @@ -0,0 +1,7 @@ +(library + (name sysinit) + (public_name coq.sysinit) + (synopsis "Coq's initialization") + (wrapped false) + (libraries coq.vernac) + ) diff --git a/sysinit/sysinit.mllib b/sysinit/sysinit.mllib new file mode 100644 index 0000000000..6e86536648 --- /dev/null +++ b/sysinit/sysinit.mllib @@ -0,0 +1,4 @@ +Usage +Coqloadpath +Coqargs +Coqinit diff --git a/sysinit/usage.ml b/sysinit/usage.ml new file mode 100644 index 0000000000..1831a3f9b2 --- /dev/null +++ b/sysinit/usage.ml @@ -0,0 +1,112 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +let version () = + Printf.printf "The Coq Proof Assistant, version %s (%s)\n" + Coq_config.version Coq_config.date; + Printf.printf "compiled on %s with OCaml %s\n" Coq_config.compile_date Coq_config.caml_version + +let machine_readable_version () = + Printf.printf "%s %s\n" + Coq_config.version Coq_config.caml_version + +(* print the usage of coqtop (or coqc) on channel co *) + +let print_usage_common co command = + output_string co command; + output_string co "Coq options are:\n"; + output_string co +" -I dir look for ML files in dir\ +\n -include dir (idem)\ +\n -R dir coqdir recursively map physical dir to logical coqdir\ +\n -Q dir coqdir map physical dir to logical coqdir\ +\n -top coqdir set the toplevel name to be coqdir instead of Top\ +\n -topfile f set the toplevel name as though compiling f\ +\n -coqlib dir set the coq standard library directory\ +\n -exclude-dir f exclude subdirectories named f for option -R\ +\n\ +\n -boot don't bind the `Coq.` prefix to the default -coqlib dir\ +\n -noinit don't load Coq.Init.Prelude on start \ +\n -nois (idem)\ +\n -compat X.Y provides compatibility support for Coq version X.Y\ +\n\ +\n -load-vernac-source f load Coq file f.v (Load \"f\".)\ +\n -l f (idem)\ +\n -load-vernac-source-verbose f load Coq file f.v (Load Verbose \"f\".)\ +\n -lv f (idem)\ +\n -load-vernac-object lib\ +\n load Coq library lib (Require lib)\ +\n -rfrom root lib load Coq library lib (From root Require lib.)\ +\n -require-import lib, -ri lib\ +\n load and import Coq library lib\ +\n (equivalent to Require Import lib.)\ +\n -require-export lib, -re lib\ +\n load and transitively import Coq library lib\ +\n (equivalent to Require Export lib.)\ +\n -require-import-from root lib, -rifrom root lib\ +\n load and import Coq library lib\ +\n (equivalent to From root Require Import lib.)\ +\n -require-export-from root lib, -refrom root lib\ +\n load and transitively import Coq library lib\ +\n (equivalent to From root Require Export lib.)\ +\n\ +\n -where print Coq's standard library location and exit\ +\n -config, --config print Coq's configuration information and exit\ +\n -v, --version print Coq version and exit\ +\n -print-version print Coq version in easy to parse format and exit\ +\n -list-tags print highlight color tags known by Coq and exit\ +\n\ +\n -quiet unset display of extra information (implies -w \"-all\")\ +\n -w (w1,..,wn) configure display of warnings\ +\n -color (yes|no|auto) configure color output\ +\n -emacs tells Coq it is executed under Emacs\ +\n\ +\n -q skip loading of rcfile\ +\n -init-file f set the rcfile to f\ +\n -bt print backtraces (requires configure debug flag)\ +\n -debug debug mode (implies -bt)\ +\n -xml-debug debug mode and print XML messages to/from coqide\ +\n -diffs (on|off|removed) highlight differences between proof steps\ +\n -noglob do not dump globalizations\ +\n -dump-glob f dump globalizations in file f (to be used by coqdoc)\ +\n -impredicative-set set sort Set impredicative\ +\n -allow-sprop allow using the proof irrelevant SProp sort\ +\n -disallow-sprop forbid using the proof irrelevant SProp sort\ +\n -sprop-cumulative make sort SProp cumulative with the rest of the hierarchy\ +\n -indices-matter levels of indices (and nonuniform parameters) contribute to the level of inductives\ +\n -type-in-type disable universe consistency checking\ +\n -mangle-names x mangle auto-generated names using prefix x\ +\n -set \"Foo Bar\" enable Foo Bar (as Set Foo Bar. in a file)\ +\n -set \"Foo Bar=value\" set Foo Bar to value (value is interpreted according to Foo Bar's type)\ +\n -unset \"Foo Bar\" disable Foo Bar (as Unset Foo Bar. in a file)\ +\n -time display the time taken by each command\ +\n -profile-ltac display the time taken by each (sub)tactic\ +\n -m, --memory display total heap size at program exit\ +\n (use environment variable\ +\n OCAML_GC_STATS=\"/tmp/gclog.txt\"\ +\n for full Gc stats dump)\ +\n -bytecode-compiler (yes|no) enable the vm_compute reduction machine\ +\n -native-compiler (yes|no|ondemand) enable the native_compute reduction machine\ +\n -native-output-dir <directory> set the output directory for native objects\ +\n -nI dir OCaml include directories for the native compiler (default if not set) \ +\n -h, -help, --help print this list of options\ +\n" + +(* print the usage *) + +type specific_usage = { + executable_name : string; + extra_args : string; + extra_options : string; +} + +let print_usage co { executable_name; extra_args; extra_options } = + print_usage_common co ("Usage: " ^ executable_name ^ " <options> " ^ extra_args ^ "\n\n"); + output_string co extra_options diff --git a/sysinit/usage.mli b/sysinit/usage.mli new file mode 100644 index 0000000000..2d1a8e94cc --- /dev/null +++ b/sysinit/usage.mli @@ -0,0 +1,28 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * Copyright INRIA, CNRS and contributors *) +(* <O___,, * (see version control and CREDITS file for authors & dates) *) +(* \VV/ **************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(* * (see LICENSE file for the text of the license) *) +(************************************************************************) + +(** {6 Prints the version number on the standard output. } *) + +val version : unit -> unit +val machine_readable_version : unit -> unit + +(** {6 extra arguments or options to print when asking usage for a + given executable. } *) + +type specific_usage = { + executable_name : string; + extra_args : string; + extra_options : string; +} + +(** {6 Prints the generic part and specific part of usage for a + given executable. } *) + +val print_usage : out_channel -> specific_usage -> unit |
