123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171(************************************************************************)(* * 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) *)(************************************************************************)typeworker={package:string;basename:string;}letget_worker_path{package;basename}=letdir=tryFindlib.package_directorypackagewithFindlib.No_such_package_->Printf.eprintf"Error: Could not find package %s.\n%!"package;exit1inletexe=ifSys.(os_type="Win32"||os_type="Cygwin")then".exe"else""inFilename.concatdir(basename^exe)typeinit_opts={boot:bool;coqlib:stringoption;ml_includes:stringlist;queries:Boot.Usage.querylist;}letdefault_opts={boot=false;coqlib=None;ml_includes=[];queries=[];}letadd_queryqopts={optswithqueries=q::opts.queries}letparse_query=letopenBoot.Usageinfunction|"-config"|"--config"->SomePrintConfig|"-where"->SomePrintWhere|"-v"|"-version"|"--version"->SomePrintVersion|"-print-version"|"--print-version"->SomePrintMachineReadableVersion|_->Noneletrecparse_argsopts=function|[]->opts|"-boot"::rest->parse_args{optswithboot=true}rest|"-coqlib"::lib::rest->parse_args{optswithcoqlib=Somelib}rest|"-I"::ml::rest->parse_args{optswithml_includes=ml::opts.ml_includes}rest|arg::rest->matchparse_queryargwith|Someq->parse_args(add_queryqopts)rest|None->parse_argsoptsrestletparse_argsargs=letopts=parse_argsdefault_optsargsinletopts={optswithml_includes=List.revopts.ml_includes;queries=List.revopts.queries;}inoptsletwith_icfilef=letic=open_infileintryletrc=ficinclose_inic;rcwithe->close_inic;raiseeletparse_env_linel=tryScanf.sscanfl"%[^=]=%S"(funnamevalue->Some(name,value))withScanf.Scan_failure_|End_of_file->None(** We [putenv] instead of wrapping [getenv] calls because the
subprocess also needs the updated env, and usually doesn't have
the env file next to its binary. *)letputenv_from_file~debug()=letbase=Filename.dirnameSys.executable_nameinletf=base^"/coq_environment.txt"intrywith_icf(funic->let()=ifdebugthenPrintf.eprintf"using env vars from %s\n%!"finletreciter()=matchinput_lineicwith|exceptionEnd_of_file->()|l->let()=matchparse_env_linelwith|Some(n,v)->beginmatchSys.getenv_optnwith|None->Unix.putenvnv|Some_->()end|None->()initer()initer())with|Sys_errors->()letmake_ocamlpathenvoptopts=letboot_ml_path=matchenvoptwith|Boot.Env.Boot->[]|Boot.Env.Envcoqenv->Boot.Env.Path.[to_string(relative(Boot.Env.runtimelibcoqenv)"..")]inletenv_ocamlpath=try[Sys.getenv"OCAMLPATH"]withNot_found->[]inletpath=List.concat[opts.ml_includes;boot_ml_path;env_ocamlpath]inletocamlpathsep=ifSys.unixthen":"else";"inString.concatocamlpathseppathletexec_or_create_processprogargv=ifSys.os_type<>"Win32"thenUnix.execvprogargvelseletpid=Unix.create_processprogargvUnix.stdinUnix.stdoutUnix.stderrinifpid=0thenbeginPrintf.eprintf"coqc shim: create_process failed\n%!";exit127end;let_,status=Unix.waitpid[]pidinmatchstatuswith|WEXITEDn|WSIGNALEDn->exitn|WSTOPPED_->(* is there anything sensible to do with WSTOPPED? can it even happen on windows? *)assertfalsetypeopts={debug_shim:bool}letparse_opts=function|"-debug-shim"::rest->{debug_shim=true},rest|args->{debug_shim=false},args(* warning will be produced by the worker *)letwarn_ignored_coqlib()=()letboot_envopts=matchBoot.Env.print_queries_maybe_init~boot:opts.boot~coqlib:opts.coqlib~warn_ignored_coqlibNoneopts.querieswith|Okenv->env|Errormsg->Printf.eprintf"%s\n%!"msg;exit1letinit{debug_shim=debug}args=(* important to putenv before reading OCAMLPATH / ROCQLIB *)let()=putenv_from_file~debug()inletopts=parse_argsargsinletcoqenv=boot_envoptsinlet()=matchopts.querieswith[]->()|_::_->exit0inletenv_ocamlpath=make_ocamlpathcoqenvoptsinlet()=ifdebugthenPrintf.eprintf"OCAMLPATH = %s\n%!"env_ocamlpathinFindlib.init~env_ocamlpath()lettry_run_queries{debug_shim=debug}args=let()=putenv_from_file~debug()inletopts=parse_argsargsinmatchopts.querieswith|[]->false|_::_->let_coqenv=boot_envoptsintrue