(************************************************************************) (* * The Rocq Prover / The Rocq 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) *) (************************************************************************)
module Path = struct
type t = string
let relative = Filename.concat let to_string x = x letexists x = Sys.file_exists x
end
(* For now just a pointer to coq/lib (for .vo) and rocq-runtime/lib (for plugins) *) type t =
{ runtimelib: Path.t
; coqlib : Path.t
}
(* This code needs to be refactored, for now it is just what used to be in envvars *)
let use_suffix prefix suffix = if Filename.is_relative suffix then Filename.concat prefix suffix else suffix
let canonical_path_name p = let current = Sys.getcwd () in try
Sys.chdir p; let p' = Sys.getcwd () in
Sys.chdir current;
p' with Sys_error _ -> (* We give up to find a canonical name and just simplify it... *)
Filename.concat current p
let theories_dir = "theories" let plugins_dir = "plugins" let prelude = Filename.concat theories_dir "Init/Prelude.vo"
let find_in_PATH f = match Sys.getenv_opt "PATH"with
| None -> None
| Some paths -> let sep = if Coq_config.arch_is_win32 then';'else':'in let paths = String.split_on_char sep paths in
paths |> List.find_opt (fun path ->
Sys.file_exists (if path = ""then f else Filename.concat path f))
let rocqbin = (* avoid following symlinks if possible (Sys.executable_name followed symlinks) *) if Filename.basename Sys.argv.(0) <> Sys.argv.(0) then (* explicit directory (maybe relative to current dir) *)
canonical_path_name (Filename.dirname Sys.argv.(0)) elsematch find_in_PATH Sys.argv.(0) with
| Some p -> p
| None -> canonical_path_name (Filename.dirname Sys.executable_name)
(** The following only makes sense when executables are running from
source tree (e.g. during build or in local mode). *) let rocqroot = let rec search = function
| [] -> (* couldn't recognize the layout, guess the executable is 1 dir below the root (eg "mybin/rocq") XXX we should search only when we need the root
and produce an error if we can't find it *)
Filename.dirname rocqbin
| path :: rest -> if Sys.file_exists (Filename.concat path "bin") then path else search rest in (* we can be "bin/rocq" or "lib/rocq-runtime/rocqworker"
so rocqbin can be "bin/" or "lib/rocq-runtime/" *) let dirname = Filename.dirname in
search [ dirname rocqbin; dirname @@ dirname rocqbin ]
let relocate = function
| Coq_config.NotRelocatable p -> p
| Coq_config.Relocatable p -> Filename.concat rocqroot p
(** [check_file_else ~dir ~file oth] checks if [file] exists in the installation directory [dir] given relatively to [coqroot], which maybe has been relocated. If the check fails, then [oth ()] is evaluated.
Using file system equality seems well enough for this heuristic *) let check_file_else ~dir ~file oth = let path = use_suffix rocqroot dir in if Sys.file_exists (Filename.concat path file) then path else oth ()
let guess_coqlib () = match Util.getenv_rocq "LIB"with
| Some v -> v
| None ->
check_file_else
~dir:Coq_config.coqlibsuffix
~file:prelude
(fun () -> relocate Coq_config.coqlib)
(* Build layout uses coqlib = coqcorelib
XXX we should be using -boot in build layout so is that dead code? *) let guess_coqcorelib lib = match Util.getenv_rocq_gen ~rocq:"ROCQRUNTIMELIB" ~coq:"COQCORELIB"with
| Some v -> v
| None -> if Sys.file_exists (Path.relative lib plugins_dir) then lib else Path.relative lib "../rocq-runtime"
let fail_lib lib = letopen Printf in
eprintf "File not found: %s\n" lib;
eprintf "The path for Rocq libraries is wrong.\n";
eprintf "Rocq prelude is shipped in the rocq-core package.\n";
eprintf "Please check the ROCQLIB env variable or the -coqlib option.\n";
exit 1
let fail_core plugin = letopen Printf in
eprintf "File not found: %s\n" plugin;
eprintf "The path for Rocq plugins is wrong.\n";
eprintf "Rocq plugins are shipped in the rocq-runtime package.\n";
eprintf "Please check the ROCQRUNTIMELIB env variable.\n";
exit 1
let validate_env ({ runtimelib; coqlib } as env) = let coqlib = Filename.concat coqlib prelude in ifnot (Sys.file_exists coqlib) then fail_lib coqlib; let plugin = Filename.concat runtimelib plugins_dir in ifnot (Sys.file_exists plugin) then fail_core plugin;
env
type maybe_env =
| Env of t
| Boot
let env_ref = ref None
(* Should we fail on double initialization? That seems a way to avoid
mis-use for example when we pass command line arguments *) let init_with ~coqlib = let coqlib = match coqlib with
| None -> guess_coqlib ()
| Some coqlib -> coqlib in let env = validate_env { coqlib; runtimelib = guess_coqcorelib coqlib } in
env_ref := Some (Env env);
env
let initialized () = !env_ref
let ignored_coqlib_msg = "Command line options -boot and -coqlib are incompatible, ignored -coqlib."
let maybe_init ~warn_ignored_coqlib ~boot ~coqlib = match boot, coqlib with
| true, None -> Boot
| false, (None | Some _ as coqlib) ->
(Env (init_with ~coqlib))
| true, Some _ ->
warn_ignored_coqlib ();
Boot
let coqlib { coqlib; _ } = coqlib let runtimelib { runtimelib; _ } = runtimelib let plugins { runtimelib; _ } = Path.relative runtimelib plugins_dir let corelib { coqlib; _ } = Path.relative coqlib theories_dir let user_contrib { coqlib; _ } = Path.relative coqlib "user-contrib" let tool { runtimelib; _ } tool = Path.(relative (relative runtimelib "tools") tool) let revision { runtimelib; _ } = Path.relative runtimelib "revision"
let native_cmi { runtimelib; _ } lib = let install_path = Path.relative runtimelib lib in if Sys.file_exists install_path then
install_path else (* Dune build layout, we need to improve this *) let obj_dir = Format.asprintf ".%s.objs" lib in
Filename.(concat (concat (concat runtimelib lib) obj_dir) "byte")
(** {2 Caml paths} *)
let ocamlfind () = match Util.getenv_opt "OCAMLFIND"with
| None -> Coq_config.ocamlfind
| Some v -> v
let docdir () = (* This assumes implicitly that the suffix is non-trivial *) let path = use_suffix rocqroot Coq_config.docdirsuffix in if Sys.file_exists path then path else relocate Coq_config.docdir
(* Print the configuration information *)
let print_config ?(prefix_var_name="") env f = let coqlib = coqlib env |> Path.to_string in let runtimelib = runtimelib env |> Path.to_string in letopen Printf in
fprintf f "%sCOQLIB=%s/\n" prefix_var_name coqlib;
fprintf f "%sCOQCORELIB=%s/\n" prefix_var_name runtimelib;
fprintf f "%sDOCDIR=%s/\n" prefix_var_name (docdir ());
fprintf f "%sOCAMLFIND=%s\n" prefix_var_name (ocamlfind ());
fprintf f "%sCAMLFLAGS=%s\n" prefix_var_name Coq_config.caml_flags;
fprintf f "%sWARN=%s\n" prefix_var_name "-warn-error +a-3";
fprintf f "%sHASNATDYNLINK=%s\n" prefix_var_name
(if Coq_config.has_natdynlink then"true"else"false");
fprintf f "%sCOQ_SRC_SUBDIRS=%s\n" prefix_var_name (String.concat " " Coq_config.all_src_dirs);
fprintf f "%sCOQ_NATIVE_COMPILER_DEFAULT=%s\n" prefix_var_name
(match Coq_config.native_compiler with
| Coq_config.NativeOn {ondemand=false} -> "yes"
| Coq_config.NativeOff -> "no"
| Coq_config.NativeOn {ondemand=true} -> "ondemand")
let query_getenv = function
| Boot -> assert false
| Env v -> v
let print_query envopt usage : Usage.query -> unit = function
| PrintVersion -> Usage.version ()
| PrintMachineReadableVersion -> Usage.machine_readable_version ()
| PrintWhere -> let env = query_getenv envopt in let coqlib = coqlib env |> Path.to_string in
print_endline coqlib
| PrintHelp -> beginmatch usage with
| Some usage -> Usage.print_usage stderr usage
| None -> assert false end
| PrintConfig -> let env = query_getenv envopt in
print_config env stdout
let query_needs_env : Usage.query -> stringoption = function
| PrintVersion | PrintMachineReadableVersion | PrintHelp -> None
| PrintWhere -> Some "-where"
| PrintConfig -> Some "-config"
let print_queries_maybe_init ~warn_ignored_coqlib ~boot ~coqlib usage = function
| [] -> Ok (maybe_init ~warn_ignored_coqlib ~boot ~coqlib)
| _ :: _ as qs -> let needs_env = CList.find_map query_needs_env qs in let res = match boot, needs_env with
| true, Some q -> Error ("Command line option -boot is not compatible with " ^ q ^ ".")
| true, None -> (* warn_ignored_coqlib if coqlib and boot used together *)
Ok (maybe_init ~warn_ignored_coqlib ~boot ~coqlib)
| false, None -> Ok Boot
| false, Some _ -> Ok (Env (init_with ~coqlib)) in let () = match res with
| Error _ -> ()
| Ok envopt -> List.iter (print_query envopt usage) qs in
res
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.