123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367letsrc=Logs.Src.create"uniq.cfg"leterror_msgffmt=Fmt.kstr(funmsg->Error(`Msgmsg))fmtmoduleLog=(valLogs.src_logsrc:Logs.LOG)typecfg={version:string;standard_library_default:Fpath.t;standard_library:Fpath.t;ccomp_type:string;c_compiler:string;ocamlc_cflags:stringlist;ocamlc_cppflags:stringlist;ocamlopt_cflags:stringlist;ocamlopt_cppflags:stringlist;bytecode_c_compiler:stringlist;native_c_compiler:stringlist;bytecomp_c_libraries:stringlist;native_c_libraries:stringlist;native_pack_linker:stringlist;native_compiler:bool(* false *);architecture:string;model:string;int_size:int;word_size:int;system:string;asm:string;asm_cfi_supported:bool;with_frame_pointers:bool;ext_exe:string;ext_obj:string;ext_asm:string;ext_lib:string;ext_dll:string;os_type:string;default_executable_name:string;systhread_supported:bool;host:string;target:string;flambda:bool;safe_string:bool;default_safe_string:bool;flat_float_array:bool;function_sections:bool;afl_instrument:bool;windows_unicode:bool;supports_shared_libraries:bool;native_dynlink:bool(* false *);naked_pointers:bool;compression_supported:bool(* false *);exec_magic_number:string;cmi_magic_number:string;cmo_magic_number:string;cma_magic_number:string;cmx_magic_number:string;cmxa_magic_number:string;ast_impl_magic_number:string;ast_intf_magic_number:string;cmxs_magic_number:string;cmt_magic_number:string;linear_magic_number:string}typesrc=Fpath.ttypet=src*cfgtype_value=|String:stringvalue|Bool:boolvalue|Int:intvalue|List:string*'avalue->'alistvalue|Path:Fpath.tvalueletparse_outputstr=letfoldaccstr=matchString.split_on_char':'strwith|[key;value]->(String.trimkey,String.trimvalue)::acc|_->accinList.fold_leftfold[](String.split_on_char'\n'str)letdummy=Fpath.v"DXctMfpDO2nK3GsVGSQ5Ig=="letparse_field:typea.default:a->?or_fail:(unit->a)->string->avalue->(string*string)list->a=fun~default?or_failkeytfields->match(List.assoc_optkeyfields,t,or_fail)with|None,_,None->default|Somevalue,String,_->value|Some("true"|"1"),Bool,_->true|Some("false"|"0"),Bool,_->false|Somestr,List(sep,String),_->Astring.String.cuts~empty:false~sepstr|Some_,Bool,None->default|Somestr,Path,or_fail->ifSys.is_directorystrthenFpath.(to_dir_path(vstr))elseifSys.file_existsstrthenFpath.vstrelseOption.fold~none:default~some:(funfn->fn())or_fail|Somestr,Int,or_fail->begintryint_of_stringstrwith_->Option.fold~none:default~some:(funfn->fn())or_failend|_,_,None->default|_,_,Someor_fail->or_fail()let[@ocamlformat"disable"]parsestr=letfields=parse_outputstrinletversion=parse_field~default:Sys.ocaml_version"version"Stringfieldsinletstandard_library_default=parse_field~or_fail:(fun()->failwith"OCaml standard library not found")~default:dummy"standard_library_default"Pathfieldsinletstandard_library=parse_field~default:standard_library_default"standard_library"Pathfieldsinletccomp_type=parse_field~default:"cc""ccomp_type"Stringfieldsinletc_compiler=parse_field~default:"cc""c_compiler"Stringfieldsinletocamlc_cflags=parse_field~default:[]"ocamlc_cflags"(List(" ",String))fieldsinletocamlc_cppflags=parse_field~default:[]"ocamlc_cppflags"(List(" ",String))fieldsinletocamlopt_cflags=parse_field~default:[]"ocamlopt_cflags"(List(" ",String))fieldsinletocamlopt_cppflags=parse_field~default:[]"ocamlopt_cppflags"(List(" ",String))fieldsinletbytecode_c_compiler=parse_field~default:[]"bytecode_c_compiler"(List(" ",String))fieldsinletnative_c_compiler=parse_field~default:[]"native_c_compiler"(List(" ",String))fieldsinletbytecomp_c_libraries=parse_field~default:[]"bytecomp_c_libraries"(List(" ",String))fieldsinletnative_c_libraries=parse_field~default:[]"native_c_libraries"(List(" ",String))fieldsinletnative_pack_linker=parse_field~default:[]"native_pack_linker"(List(" ",String))fieldsinletnative_compiler=parse_field~default:false"native_compiler"Boolfieldsinletarchitecture=parse_field~default:"unknown""architecture"Stringfieldsinletmodel=parse_field~default:"default""model"Stringfieldsinletint_size=parse_field~default:Sys.int_size"int_size"Intfieldsinletword_size=parse_field~default:Sys.word_size"word_size"Intfieldsinletsystem=parse_field~default:"unknown""system"Stringfieldsinletasm=parse_field~default:"as""asm"Stringfieldsinletasm_cfi_supported=parse_field~default:false"asm_cfi_supported"Boolfieldsinletwith_frame_pointers=parse_field~default:false"with_frame_pointers"Boolfieldsinletext_exe=parse_field~default:"""ext_exe"Stringfieldsinletext_obj=parse_field~default:".o""ext_obj"Stringfieldsinletext_asm=parse_field~default:".s""ext_asm"Stringfieldsinletext_lib=parse_field~default:".a""ext_lib"Stringfieldsinletext_dll=parse_field~default:".dll""ext_dll"Stringfieldsinletos_type=parse_field~default:Sys.os_type"os_type"Stringfieldsinletdefault_executable_name=parse_field~default:"a.out""default_executable_name"Stringfieldsinletsysthread_supported=parse_field~default:false"systhread_supported"Boolfieldsinlethost=parse_field~default:"unknown""host"Stringfieldsinlettarget=parse_field~default:"unknown""target"Stringfieldsinletflambda=parse_field~default:false"flambda"Boolfieldsinletsafe_string=parse_field~default:false"safe_string"Boolfieldsinletdefault_safe_string=parse_field~default:false"default_safe_string"Boolfieldsinletflat_float_array=parse_field~default:false"flat_float_array"Boolfieldsinletfunction_sections=parse_field~default:false"function_sections"Boolfieldsinletafl_instrument=parse_field~default:false"afl_instrument"Boolfieldsinletwindows_unicode=parse_field~default:false"windows_unicode"Boolfieldsinletsupports_shared_libraries=parse_field~default:false"supports_shared_libraries"Boolfieldsinletnative_dynlink=parse_field~default:false"native_dynlink"Boolfieldsinletnaked_pointers=parse_field~default:false"naked_pointers"Boolfieldsinletcompression_supported=parse_field~default:false"compression_supported"Boolfieldsinletexec_magic_number=parse_field~default:Misc.Magic_number.(raw_kindExec)"exec_magic_number"Stringfieldsinletcmi_magic_number=parse_field~default:Misc.Magic_number.(raw_kindCmi)"cmi_magic_number"Stringfieldsinletcmo_magic_number=parse_field~default:Misc.Magic_number.(raw_kindCmo)"cmo_magic_number"Stringfieldsinletcma_magic_number=parse_field~default:Misc.Magic_number.(raw_kindCma)"cma_magic_number"Stringfieldsinletcmx_magic_number=parse_field~default:Misc.Magic_number.(raw_kind(Cmx{flambda}))"cmx_magic_number"Stringfieldsinletcmxa_magic_number=parse_field~default:Misc.Magic_number.(raw_kind(Cmxa{flambda}))"cmxa_magic_number"Stringfieldsinletast_impl_magic_number=parse_field~default:Misc.Magic_number.(raw_kindAst_impl)"ast_impl_magic_number"Stringfieldsinletast_intf_magic_number=parse_field~default:Misc.Magic_number.(raw_kindAst_intf)"ast_intf_magic_number"Stringfieldsinletcmxs_magic_number=parse_field~default:Misc.Magic_number.(raw_kindCmxs)"cmxs_magic_number"Stringfieldsinletcmt_magic_number=parse_field~default:Misc.Magic_number.(raw_kindCmt)"cmt_magic_number"Stringfieldsinletlinear_magic_number=parse_field~default:"Caml1999""linear_magic_number"StringfieldsinOk{version;standard_library_default;standard_library;ccomp_type;c_compiler;ocamlc_cflags;ocamlc_cppflags;ocamlopt_cflags;ocamlopt_cppflags;bytecode_c_compiler;native_c_compiler;bytecomp_c_libraries;native_c_libraries;native_pack_linker;native_compiler;architecture;model;int_size;word_size;system;asm;asm_cfi_supported;with_frame_pointers;ext_exe;ext_obj;ext_asm;ext_lib;ext_dll;os_type;default_executable_name;systhread_supported;host;target;flambda;safe_string;default_safe_string;flat_float_array;function_sections;afl_instrument;windows_unicode;supports_shared_libraries;native_dynlink;naked_pointers;compression_supported;exec_magic_number;cmi_magic_number;cmo_magic_number;cma_magic_number;cmx_magic_number;cmxa_magic_number;ast_impl_magic_number;ast_intf_magic_number;cmxs_magic_number;cmt_magic_number;linear_magic_number}let(<?>)fn0fn1=matchfn0()withOk_asv->v|Error_->fn1()letfrom?env?toolchaincompiler()=let(let*)=Result.bindinletwhere=Bos.Cmd.(v"which"%compiler)inletwhere=Bos.OS.Cmd.run_out?envwhereinlet*where=Bos.OS.Cmd.out_string~trim:truewhereinmatchwherewith|str,(_,`Exited0)->letwhere=Fpath.vstrinLog.debug(funm->m"use %a as the OCaml compiler"Fpath.ppwhere);letconfig=matchtoolchainwith|None->Bos.Cmd.(vcompiler%"-config")|Somet->Bos.Cmd.(v"ocamlfind"%"-toolchain"%t%compiler%"-config")inletconfig=Bos.OS.Cmd.run_out?envconfiginbeginmatchBos.OS.Cmd.out_string~trim:trueconfigwith|Ok(cfg,(_,`Exited0))->let*cfg=parsecfginOk(where,cfg)|_->error_msgf"%s: impossible to get configuration"compilerend|_->error_msgf"which: impossible to find %s"compilerletv?env()=from?env"ocamlc"<?>from?env"ocamlopt"moduleValue=structtype'at='avalueletstring=Stringletlist?(sep=" ")v=List(sep,v)letbool=Boolletint=Intletpath=Pathendletnormalizestr=Astring.String.map(function'-'->'_'|chr->chr)strletcast:typeab.avalue->a->bvalue->boption=funuvaluev->match(u,v,value)with|Bool,Bool,v->Somev|Int,Int,v->Somev|Path,Path,v->Somev|String,String,v->Somev|List(_,String),List(_,String),v->Somev|Bool,Int,true->Some1|Bool,Int,false->Some0|Bool,String,true->Some"true"|Bool,String,false->Some"false"|Bool,List(_,String),true->Some["true"]|Bool,List(_,String),false->Some["false"]|Path,String,v->Some(Fpath.to_stringv)|Path,List(_,String),v->Some[Fpath.to_stringv]|List(sep,String),String,v->Some(String.concatsepv)|Int,String,v->Some(string_of_intv)|String,Int,v->begintrySome(int_of_stringv)with_->Noneend|Int,Bool,0->Somefalse|Int,Bool,_->Sometrue|String,Path,v->begintrySome(Fpath.vv)with_->Noneend|_->Noneletget:typea.?native:booloption->t->key:string->avalue->aoption=fun?(native=None)(_,cfg)~keyt->match(normalizekey,t)with|"version",String->Somecfg.version|"standard_library_default",t->castPathcfg.standard_library_defaultt|"standard_library",t->castPathcfg.standard_library_defaultt|"ccomp_type",String->Somecfg.ccomp_type|("c_compiler"|"CC"),String->Somecfg.c_compiler|"CFLAGS",List(_,String)->ifcfg.ocamlc_cflags=cfg.ocamlopt_cflags||Option.fold~none:false~some:Fun.(negateid)nativethenSomecfg.ocamlc_cflagselseifOption.value~default:falsenativethenSomecfg.ocamlopt_cflagselseNone|"CPPFLAGS",List(_,String)->ifcfg.ocamlc_cppflags=cfg.ocamlopt_cppflags||Option.fold~none:false~some:Fun.(negateid)nativethenSomecfg.ocamlc_cflagselseifOption.value~default:falsenativethenSomecfg.ocamlopt_cflagselseNone|"ocamlc_cflags",List(_,String)->Somecfg.ocamlc_cflags|"ocamlc_cppflags",List(_,String)->Somecfg.ocamlc_cppflags|"ocamlopt_cflags",List(_,String)->Somecfg.ocamlopt_cflags|"ocamlopt_cppflags",List(_,String)->Somecfg.ocamlopt_cppflags|"bytecode_c_compiler",List(_,String)->Somecfg.bytecode_c_compiler|"native_c_compiler",List(_,String)->Somecfg.native_c_compiler|"bytecomp_c_libraries",List(_,String)->Somecfg.bytecomp_c_libraries|"native_c_libraries",List(_,String)->Somecfg.native_c_libraries|"native_pack_linker",List(_,String)->Somecfg.native_pack_linker|"native_compiler",t->castBoolcfg.native_compilert|"architecture",String->Somecfg.architecture|"model",String->Somecfg.model|"int_size",t->castIntcfg.int_sizet|"word_size",t->castIntcfg.word_sizet|"system",String->Somecfg.system|"asm",String->Somecfg.asm|"asm_cfi_supported",t->castBoolcfg.asm_cfi_supportedt|"with_frame_pointers",t->castBoolcfg.with_frame_pointerst|"ext_exe",String->Somecfg.ext_exe|"ext_obj",String->Somecfg.ext_obj|"ext_asm",String->Somecfg.ext_asm|"ext_lib",String->Somecfg.ext_lib|"ext_dll",String->Somecfg.ext_dll|"os_type",String->Somecfg.os_type|"default_executable_name",String->Somecfg.default_executable_name|"systhread_supported",Bool->Somecfg.systhread_supported|"host",String->Somecfg.host|"target",String->Somecfg.target|"flambda",t->castBoolcfg.flambdat|"safe_string",t->castBoolcfg.safe_stringt|"default_safe_string",t->castBoolcfg.default_safe_stringt|"flat_float_array",t->castBoolcfg.flat_float_arrayt|"function_sections",t->castBoolcfg.function_sectionst|"afl_instrument",t->castBoolcfg.afl_instrumentt|"windows_unicode",t->castBoolcfg.windows_unicodet|"supports_shared_libraries",t->castBoolcfg.supports_shared_librariest|"native_dynlink",t->castBoolcfg.native_dynlinkt|"naked_pointers",t->castBoolcfg.naked_pointerst|"compression_supported",t->castBoolcfg.compression_supportedt|"exec_magic_number",String->Somecfg.exec_magic_number|"cmi_magic_number",String->Somecfg.cmi_magic_number|"cmo_magic_number",String->Somecfg.cmo_magic_number|"cma_magic_number",String->Somecfg.cma_magic_number|"cmx_magic_number",String->Somecfg.cmx_magic_number|"cmxa_magic_number",String->Somecfg.cmxa_magic_number|"ast_impl_magic_number",String->Somecfg.ast_impl_magic_number|"ast_intf_magic_number",String->Somecfg.ast_intf_magic_number|"cmxs_magic_number",String->Somecfg.cmxs_magic_number|"cmt_magic_number",String->Somecfg.cmt_magic_number|"linear_magic_number",String->Somecfg.linear_magic_number|_->None