Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/Roqc/tools/configure/   (Beweissystem des Inria Version 9.1.0©)  Datei vom 15.8.2025 mit Größe 20 kB image not shown  

Quelle  configure.ml   Sprache: SML

 
(************************************************************************)
(*         *      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)         *)
(************************************************************************)

[@@@ocaml.warning "+a"]

(***********************************)
(**  Configuration script for Rocq *)
(***********************************)
open Printf
open Conf
open Util
(* cprintf is shadowed here... *)
open! CmdArgs
open CmdArgs.Prefs

let (/) = Filename.concat

let coq_version = "9.1.0"
let vo_magic = 90100
let is_a_released_version = true

(** Default OCaml binaries *)

type camlexec = { mutable find : string }
let camlexec = { find = "ocamlfind" }

let reset_caml_find c o = c.find <- o

(* Query for the architecture *)
let arch prefs = arch prefs.arch

(** NB: [arch_is_win32] is broader than [os_type_win32], cf. cygwin *)
let arch_is_win32 arch = arch = "win32"

let unix arch = os_type_cygwin || not (arch_is_win32 arch)

(* For cygwin dune doesn't add .exe to the binaries, only under mingw *)
let resolve_binary_suffix arch = if unix arch then "" else ".exe"

(** * Git Precommit Hook *)
let install_precommit_hook prefs =
  let f = ".git/hooks/pre-commit" in
  if dir_exists ".git/hooks" && not (Sys.file_exists f) then begin
    cprintf prefs "Creating pre-commit hook in %s" f;
    let o = open_out f in
    let pr s = fprintf o s in
    pr "#!/bin/sh\n";
    pr "\n";
    pr "if [ -x dev/tools/pre-commit ]; then\n";
    pr " exec dev/tools/pre-commit\n";
    pr "fi\n";
    close_out o;
    Unix.chmod f 0o775
  end

(** * Browser command *)

let browser prefs arch =
  match prefs.browser with
  | Some b -> b
  | None when arch_is_win32 arch -> {|start "%s"|}
  | None when arch = "Darwin" -> {|open "%s"|}
  | _ -> {|xdg-open "%s"|}

(** * OCaml programs *)
module CamlConf = struct
  type t =
    { camlbin : string
    ; caml_version : string
    ; camllib : string
    ; findlib_version : string
    }
end

let resolve_caml () =
  let () =
    try reset_caml_find camlexec (which camlexec.find)
    with Not_found ->
      die (sprintf "Error: cannot find '%s' in your path!\n" camlexec.find ^
           "Please adjust your path or use the -ocamlfind option of ./configure")
  in
  if not (is_executable camlexec.find)
  then die ("Error: cannot find the executable '"^camlexec.find^"'.")
  else
    let findlib_version, _ = run camlexec.find ["query""findlib""-format""%v"in
    let caml_version, _ = run camlexec.find ["ocamlc";"-version"in
    let camllib, _ = run camlexec.find ["printconf";"stdlib"in
    let camlbin = (* TODO beurk beurk beurk *)
      Filename.dirname (Filename.dirname camllib) / "bin/" in
    { CamlConf.camlbin; caml_version; camllib; findlib_version }

(** Caml version as a list of ints [4;0;1] *)
let caml_version_nums { CamlConf.caml_version; _ } =
  generic_version_nums ~name:"the OCaml compiler" caml_version

let check_caml_version prefs caml_version caml_version_nums =
  if caml_version_nums >= [5;0;0] && prefs.nativecompiler <> NativeNo then
    let () = cprintf prefs "Your version of OCaml is %s." caml_version in
    die "You have enabled Rocq's native compiler, however it is not compatible with OCaml >= 5.0.0"
  else if caml_version_nums >= [4;14;0] then
    cprintf prefs "You have OCaml %s. Good!" caml_version
  else
    let () = cprintf prefs "Your version of OCaml is %s." caml_version in
    die "You need OCaml 4.14.0 or later."

let check_findlib_version prefs { CamlConf.findlib_version; _ } =
  let findlib_version_nums = generic_version_nums ~name:"findlib" findlib_version in
  if findlib_version_nums >= [1;9;1] then
    cprintf prefs "You have OCamlfind %s. Good!" findlib_version
  else
    let () = cprintf prefs "Your version of OCamlfind is %s." findlib_version in
    die "You need OCamlfind 1.9.1 or later."

(** Note, these warnings are only used in Rocq Makefile *)
(** Explanation of enabled/disabled warnings:
    4: fragile pattern matching: too common in the code and too annoying to avoid in general
    9: missing fields in a record pattern: too common in the code and not worth the bother
    27: innocuous unused variable: innocuous
    40: constructor or label name used out of scope: gets in the way of putting types in modules
    41: ambiguous constructor or label: too common
    42: disambiguated counstructor or label: too common
    44: "open" shadowing already defined identifier: too common, especially when some are aliases
    45: "open" shadowing a label or constructor: see 44
    48: implicit elimination of optional arguments: too common
    58: "no cmx file was found in path": See https://github.com/ocaml/num/issues/9
    67: "unused functor parameter" seems totally bogus
    68: "This pattern depends on mutable state" no idea what it means, dune builds don't display it
    70: ".ml file without .mli file" bogus warning when used generally
*)


(* Note, we list all warnings to be complete *)
let coq_warnings = "-w -a+1..3-4+5..8-9+10..26-27+28..39-40-41-42+43-44-45+46..47-48+49..57-58+59..66-67-68+69-70"

(* Flags used to compile Rocq and plugins (via coq_makefile) *)
let caml_flags =
  Printf.sprintf "-thread -bin-annot -strict-sequence %s" coq_warnings

(** * Native compiler *)

let msg_byteonly =
  "Only the bytecode version of Rocq will be available."

let msg_no_ocamlopt () =
  warn "Cannot find the OCaml native-code compiler.\n%s" msg_byteonly

let msg_no_dynlink_cmxa prefs =
  warn "Cannot find native-code dynlink library.\n%s" msg_byteonly;
  cprintf prefs "For building a native-code Rocq, you may try to first";
  cprintf prefs "compile and install a dummy dynlink.cmxa (see dev/dynlink.ml)";
  cprintf prefs "and then run ./configure -natdynlink no"

let check_native prefs camlenv =
  let version, _ = tryrun camlexec.find ["opt";"-version"in
  if version = "" then let () = msg_no_ocamlopt () in raise Not_found
  else if fst (tryrun camlexec.find ["query";"dynlink"]) = ""
  then let () = msg_no_dynlink_cmxa prefs in raise Not_found
  else
    let () =
      let { CamlConf.caml_version; _ } = camlenv in
      if version <> caml_version then
        warn "Native and bytecode compilers do not have the same version!"
    in cprintf prefs "You have native-code compilation. Good!"

let best_compiler prefs camlenv =
  try check_native prefs camlenv; "opt" with Not_found -> "byte"

(** * Native dynlink *)

let hasnatdynlink prefs best_compiler = prefs.natdynlink && best_compiler = "opt"

(** * OS dependent libraries *)

(** Zarith library *)

let check_for_zarith prefs =
  let zarith,_ = tryrun camlexec.find ["query";"zarith"in
  let zarith_cmai base = Sys.file_exists (base / "z.cmi") && Sys.file_exists (base / "zarith.cma"in
  let zarith_version, _ = run camlexec.find ["query""zarith""-format""%v"in
  match zarith with
  | ""  ->
    die "Zarith library not installed, required"
  | _ when not (zarith_cmai zarith) ->
    die "Zarith library installed but no development files found (try installing the -dev package)"
  | _   ->
    let zarith_version_int = generic_version_nums ~name:"Zarith" zarith_version in
    if zarith_version_int >= [1;11;0] then
      cprintf prefs "You have the Zarith library %s installed. Good!" zarith_version
    else
      die ("Zarith version 1.11 is required, you have " ^ zarith_version)

(** * Installation directories : bindir, libdir, mandir, docdir, etc *)

(* Source code root *)
let coqsrc = Sys.getcwd ()

(** Variable name, description, ref in prefs, default dir, prefix-relative *)

type path_style =
  | Absolute of string (* Should start with a "/" *)
  | Relative of string (* Should not start with a "/", relative to the prefix *)

type relocatable_path =
  | Relocatable of string
  | NotRelocatable of string

module InstallDir = struct

  type t =
    { var : string
    (** Used as key by [select] (otherwise ignored) *)
    ; msg : string
    (** Description of the directory  *)
    ; uservalue : string option
    (** Value given explictly by the user *)
    ; selfcontainedlayout : path_style
    (** Path style when layout is "local" *)
    ; unixlayout : path_style
    (** Path style for installation *)
    }

  let make var msg uservalue selfcontainedlayout unixlayout =
    { var; msg; uservalue; selfcontainedlayout; unixlayout }

end

let install prefs =
  [ InstallDir.make "COQPREFIX" "Prefix" None (Relative "") (Relative "")
  ; InstallDir.make "COQLIBINSTALL" "the Rocq library" prefs.libdir (Relative "lib/coq"(Relative "lib/coq")
  ; InstallDir.make "CONFIGDIR" "the Rocqide configuration files" prefs.configdir (Relative "config") (Absolute "/etc/xdg/coq")
  ; InstallDir.make "DATADIR" "the Rocqide data files" prefs.datadir (Relative "share/coq") (Relative "share/coq")
  ; InstallDir.make "MANDIR" "the Rocq man pages" prefs.mandir (Relative "share/man") (Relative "share/man")
  ; InstallDir.make "DOCDIR" "documentation prefix path for all Rocq packages" prefs.docdir (Relative "share/doc") (Relative "share/doc")
  ]

let strip_trailing_slash_if_any p =
  if p.[String.length p - 1] = '/' then String.sub p 0 (String.length p - 1) else p

let use_suffix prefix suff =
  match suff with
  | Absolute path -> NotRelocatable path
  | Relative suff ->
  match prefix with
  | Prefix prefix -> NotRelocatable (if suff = "" then prefix else prefix ^ "/" ^ suff)
  | RelocatableInstall -> Relocatable suff

let relativize = function
  (* Turn a global layout based on some prefix to a relative layout *)
  | Relative _ as suffix -> suffix
  | Absolute path -> Relative (String.sub path 1 (String.length path - 1))

let find_suffix prefix path = match prefix with
  | None | Some RelocatableInstall -> Absolute path
  | Some (Prefix p) ->
     let p = strip_trailing_slash_if_any p in
     let lpath = String.length path in
     let lp = String.length p in
     if lpath > lp && String.sub path 0 lp = p then
       Relative (String.sub path (lp+1) (lpath - lp - 1))
     else
       Absolute path

(* This computes the actual effective path for an install directory,
   based on the given prefix; if prefix is absent, it is assumed that
   the profile is "local" *)

let do_one_instdir ~interactive ~prefix ~arch InstallDir.{var; msg; uservalue; selfcontainedlayout; unixlayout} =
  (var,msg),
  match uservalue, prefix with
  | Some d, p -> NotRelocatable d, find_suffix p d
  | None, Some p ->
    let suffix = if (arch_is_win32 arch) then selfcontainedlayout else relativize unixlayout in
    use_suffix p suffix, suffix
  | None, None ->
    let () = if not interactive then die (Printf.sprintf "No installation path given for %s" msg) in
    let suffix = if (unix arch) then unixlayout else selfcontainedlayout in
    let base = if (unix arch) then "/usr/local" else "C:/coq" in
    let dflt = use_suffix (Prefix base) suffix in
    let ppdflt = match dflt with NotRelocatable v -> v | Relocatable _ -> assert false in
    let () = printf "Where should I install %s [%s]? " msg ppdflt in
    let line = read_line () in
    if line = "" then (dflt,suffix) else (NotRelocatable line,find_suffix prefix line)

let install_dirs prefs arch =
  let prefix = prefs.prefix in
  List.map (do_one_instdir ~interactive:prefs.interactive ~prefix ~arch) (install prefs)

let select var install_dirs = List.find (fun ((v,_),_) -> v=var) install_dirs |> snd

module CoqEnv = struct
  (** Rocq core paths, for libraries, documentation, configuration, and data *)
  type t =
    { coqlib : relocatable_path
    ; coqlibsuffix : path_style
    ; docdir : relocatable_path
    ; docdirsuffix : path_style
    ; configdir : relocatable_path
    ; configdirsuffix : path_style
    ; datadir : relocatable_path
    ; datadirsuffix : path_style }
end

let resolve_coqenv install_dirs =
  let coqlib, coqlibsuffix = select "COQLIBINSTALL" install_dirs in
  let docdir, docdirsuffix = select "DOCDIR" install_dirs in
  let configdir, configdirsuffix = select "CONFIGDIR" install_dirs in
  let datadir,datadirsuffix = select "DATADIR" install_dirs in
  { CoqEnv.coqlib; coqlibsuffix; docdir; docdirsuffix
  ; configdir; configdirsuffix; datadir; datadirsuffix }

(** * CC runtime flags *)

(* Note that Rocq's VM requires at least C99-compliant floating-point
   arithmetic; this should be ensured by OCaml's own C flags, which
   set a minimum of [--std=gnu99] ; modern compilers by default assume
   C11 or later, so no explicit [--std=] flags are added by OCaml *)

let cflags_dflt = "-Wall -Wno-unused -g -O2"

let cflags_sse2 = "-msse2 -mfpmath=sse"

(* cflags, sse2_math = *)
let compute_cflags () =
  let _, slurp =
    (* Test SSE2_MATH support <https://stackoverflow.com/a/45667927> *)
    tryrun camlexec.find
      ["ocamlc""-ccopt"; cflags_dflt ^ " -march=native -dM -E " ^ cflags_sse2;
       "-c"; coqsrc/"dev/header.c"in  (* any file *)
  if List.exists (fun line -> starts_with line "#define __SSE2_MATH__ 1") slurp
  then (cflags_dflt ^ " " ^ cflags_sse2, true)
  else (cflags_dflt, false)

(** Test at configure time that no harmful double rounding seems to
    be performed with an intermediate 80-bit representation (x87).

    If this test fails but SSE2_MATH is available, the build can go
    further as Rocq's primitive floats will use it through a dedicated
    external C implementation (instead of relying on OCaml operations)

    If this test fails and SSE2_MATH is not available, abort.
 *)

let check_fmath sse2_math =
  let add = (+.) in
  let b = ldexp 1. 53 in
  let s = add 1. (ldexp 1. (-52)) in
  if (add b s <= b || add b 1. <> b || ldexp 1. (-1074) <= 0.)
     && not sse2_math then
    die "Detected non IEEE-754 compliant architecture (or wrong \
         rounding mode). Use of Float is thus unsafe."

let esc s = if String.contains s ' ' then "\"" ^ s ^ "\"" else s

(** * Summary of the configuration *)

let pr_native = function
  | NativeYes -> "yes" | NativeNo -> "no" | NativeOndemand -> "ondemand"

let print_summary prefs arch camlenv install_dirs browser =
  let { CamlConf.caml_version; camlbin; camllib; _ } = camlenv in
  let pr s = printf s in
  let pr_reloc oc = function
    | NotRelocatable p -> fprintf oc "%s" (esc p)
    | Relocatable p -> fprintf oc "(relocatable prefix)/%s" (esc p)
  in
  pr "\n";
  pr " Architecture : %s\n" arch;
  pr " Sys.os_type : %s\n" Sys.os_type;
  pr " OCaml version : %s\n" caml_version;
  pr " OCaml binaries in : %s\n" (esc camlbin);
  pr " OCaml library in : %s\n" (esc camllib);
  pr " Web browser : %s\n" browser;
  pr " Rocq web site : %s\n" prefs.coqwebsite;
  pr " Bytecode VM enabled : %B\n" prefs.bytecodecompiler;
  pr " Native Compiler enabled : %s\n\n" (pr_native prefs.nativecompiler);
  (pr " Paths where installation is expected by Rocq Makefile:\n";
   List.iter
     (fun ((_,msg),(dir,_)) -> pr " - %s is expected in %a\n" msg pr_reloc dir)
     install_dirs);
  pr "\n";
  pr "If anything is wrong above, please restart './configure'.\n\n";
  pr "*Warning* To compile the system for a new architecture\n";
  pr " don't forget to do a 'make clean' before './configure'.\n"

(** Build the [config/coq_config.ml] file *)
let write_coq_config_ml install_prefix camlenv coqenv caml_flags caml_version_nums arch arch_is_win32 hasnatdynlink browser prefs o =
  let { CoqEnv.coqlib; coqlibsuffix; configdir; configdirsuffix; docdir; docdirsuffix; datadir; datadirsuffix } = coqenv in
  let { CamlConf.caml_version; _ } = camlenv in
  let pr s = fprintf o s in
  let pr_s = pr "let %s = %S\n" in
  let pr_b = pr "let %s = %B\n" in
  let pr_i32 = pr "let %s = %dl\n" in
  let pr_p s o = pr "let %s = %S\n" s
      (match o with Relative s -> s | Absolute s -> s) in
  let pr_reloc s = function
    | NotRelocatable o -> pr "let %s = NotRelocatable %S\n" s o
    | Relocatable o -> pr "let %s = Relocatable %S\n" s o
  in
  let pr_li n l = pr "let %s = [%s]\n" n (String.concat ";" (List.map string_of_int l)) in
  pr "(* DO NOT EDIT THIS FILE: automatically generated by ../configure *)\n";
  pr "(* Exact command that generated this file: *)\n";
  pr "(* %s *)\n\n" (String.concat " " (Array.to_list Sys.argv));
  pr "type relocatable_path = NotRelocatable of string | Relocatable of string\n";
  pr_reloc "install_prefix" install_prefix;
  pr_reloc "coqlib" coqlib;
  pr_reloc "configdir" configdir;
  pr_reloc "datadir" datadir;
  pr_reloc "docdir" docdir;
  pr_p "coqlibsuffix" coqlibsuffix;
  pr_p "configdirsuffix" configdirsuffix;
  pr_p "datadirsuffix" datadirsuffix;
  pr_p "docdirsuffix" docdirsuffix;
  pr_s "ocamlfind" camlexec.find;
  pr_s "caml_flags" caml_flags;
  pr_s "version" coq_version;
  pr_s "caml_version" caml_version;
  pr_li "caml_version_nums" caml_version_nums;
  pr_s "arch" arch;
  pr_b "arch_is_win32" arch_is_win32;
  pr_s "exec_extension" !exe;
  pr_b "has_natdynlink" hasnatdynlink;
  pr_i32 "vo_version" vo_magic;
  pr_s "browser" browser;
  pr_s "wwwcoq" prefs.coqwebsite;
  pr_s "wwwbugtracker" (prefs.coqwebsite ^ "bugs/");
  pr_s "wwwrefman" (prefs.coqwebsite ^ "doc/V" ^ coq_version ^ "/refman/");
  pr_s "wwwstdlib" (prefs.coqwebsite ^ "doc/V" ^ coq_version ^ "/stdlib/");
  pr_b "bytecode_compiler" prefs.bytecodecompiler;
  pr "type native_compiler = NativeOff | NativeOn of { ondemand : bool }\n";
  pr "let native_compiler = %s\n"
    (match prefs.nativecompiler with
     | NativeYes -> "NativeOn {ondemand=false}" | NativeNo -> "NativeOff"
     | NativeOndemand -> "NativeOn {ondemand=true}");

  let core_src_dirs = [ "boot""config""lib""clib""kernel""library";
                        "engine""pretyping""interp""gramlib""parsing""proofs";
                        "tactics""toplevel""printing""ide""stm""vernac" ] in

  let core_src_dirs = List.fold_left (fun acc core_src_subdir -> acc ^ " \"" ^ core_src_subdir ^ "\";\n")
                                    ""
                                    core_src_dirs in

  pr "\nlet core_src_dirs = [\n%s]\n" core_src_dirs;
  pr "\nlet plugins_dirs = [\n";

  let plugins = match open_in "config/plugin_list" with
    | exception Sys_error _ ->
      let plugins =
        try Sys.readdir "plugins"
        with _ -> [||]
      in
      Array.sort compare plugins;
      plugins
    | ch -> Array.of_list (snd (read_lines_and_close ch))
  in
  Array.iter
    (fun f ->
      let f' = "plugins/"^f in
      if Sys.is_directory f' && f.[0] <> '.' then pr " %S;\n" f')
    plugins;
  pr "]\n";

  pr "\nlet all_src_dirs = core_src_dirs @ plugins_dirs\n"

(** Build the config/coq_byte_config.ml file *)
let write_coq_byte_config_ml caml_version_nums o =
  let pr s = fprintf o s in
  pr "let toploop_use_silently ppf f = %s\n"
    (if caml_version_nums >= [4;14;0]
     then "Toploop.use_silently ppf (Toploop.File f)"
     else "Toploop.use_silently ppf f");
  pr "let compenv_handle_exit_with_status_0 f = %s\n"
    (if caml_version_nums >= [4;12;0]
     then "try f () with Compenv.Exit_with_status(0) -> ()"
     else "f ()")

(** Build the [config/dune.c_flags] file *)
let write_dune_c_flags cflags o =
  let pr s = fprintf o s in
  pr "(%s)\n" cflags

(** Build the [config/coq_config.py] file *)
let write_coq_config_py o =
  let pr s = fprintf o s in
  pr "# DO NOT EDIT THIS FILE: automatically generated by ../configure\n";
  pr "version = '%s'\n" coq_version;
  pr "is_a_released_version = %s\n" (if is_a_released_version then "True" else "False")

(* Main configure routine *)
let main () =
  let prefs = CmdArgs.parse_args () in
  Util.debug := prefs.debug;
  let arch = arch prefs in
  let arch_is_win32 = arch_is_win32 arch in
  let exe = resolve_binary_suffix arch in
  Util.exe := exe;
  install_precommit_hook prefs;
  let browser = browser prefs arch in
  let camlenv = resolve_caml () in
  let caml_version_nums = caml_version_nums camlenv in
  check_caml_version prefs camlenv.CamlConf.caml_version caml_version_nums;
  check_findlib_version prefs camlenv;
  let best_compiler = best_compiler prefs camlenv in
  let hasnatdynlink = hasnatdynlink prefs best_compiler in
  check_for_zarith prefs;
  let install_dirs = install_dirs prefs arch in
  let install_prefix = select "COQPREFIX" install_dirs |> fst in
  let coqenv = resolve_coqenv install_dirs in
  let cflags, sse2_math = compute_cflags () in
  check_fmath sse2_math;
  if not prefs.quiet then
    print_summary prefs arch camlenv install_dirs browser;
  write_config_file ~file:"config/coq_config.ml"
    (write_coq_config_ml install_prefix camlenv coqenv caml_flags caml_version_nums arch arch_is_win32 hasnatdynlink browser prefs);
  write_config_file ~file:"config/coq_byte_config.ml" (write_coq_byte_config_ml caml_version_nums);
  write_config_file ~file:"config/dune.c_flags" (write_dune_c_flags cflags);
  write_config_file ~file:"config/coq_config.py" write_coq_config_py;
  ()

let _ =
  main ()

Messung V0.5
C=93 H=93 G=92

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.