Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file v1.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742open!Stdune(* we shadow this module on purpose because it's unusable without the build dir
initialized *)modulePath=structendmoduleIo=Io.String_pathletsprintf=Printf.sprintfleteprintf=Printf.eprintflet(^/)=Filename.concatexceptionFatal_errorofstringletdiefmt=Printf.ksprintf(funs->raise(Fatal_errors))fmtletwarnfmt=Printf.ksprintf(funmsg->prerr_endline("Warning: "^msg))fmttypet={name:string;dest_dir:string;ocamlc:string;log:string->unit;mutablecounter:int;ext_obj:string;c_compiler:string;stdlib_dir:string;ccomp_type:string;ocamlc_config:stringString.Map.t;ocamlc_config_cmd:string}letrecrm_rfdir=Array.iter(Sys.readdirdir)~f:(funfn->letfn=dir^/fninifSys.is_directoryfnthenrm_rffnelseUnix.unlinkfn);Unix.rmdirdirmoduleTemp=struct(* Copied from filename.ml and adapted for directories *)letprng=lazy(Random.State.make_self_init())letgen_name~temp_dir~prefix~suffix=letrnd=Random.State.bits(Lazy.forceprng)land0xFFFFFFintemp_dir^/Printf.sprintf"%s%06x%s"prefixrndsuffixletcreate~prefix~suffix~mk=lettemp_dir=Filename.get_temp_dir_name()inletrectry_namecounter=letname=gen_name~temp_dir~prefix~suffixinmatchmknamewith|()->name|exceptionUnix.Unix_error_whencounter<1000->try_name(counter+1)intry_name0letcreate_temp_dir~prefix~suffix=letdir=create~prefix~suffix~mk:(funname->Unix.mkdirname0o700)inat_exit(fun()->rm_rfdir);direndmoduleFlags=structletextract_words=String.extract_wordsletextract_comma_space_separated_words=String.extract_comma_space_separated_wordsletextract_blank_separated_words=String.extract_blank_separated_wordsletwrite_linespaths=Io.write_linespathsletwrite_sexppaths=letsexp=Dune_lang.List(List.maps~f:(funs->Dune_lang.Quoted_strings))inIo.write_filepath(Dune_lang.to_stringsexp)endmoduleFind_in_path=structletpath_sep=ifSys.win32then';'else':'letget_path()=matchSys.getenv"PATH"with|exceptionNot_found->[]|s->String.splits~on:path_sepletexe=ifSys.win32then".exe"else""letprog_not_foundprog=die"Program %s not found in PATH"progletbest_progdirprog=letfn=dir^/prog^".opt"^exeinifSys.file_existsfnthenSomefnelseletfn=dir^/prog^exeinifSys.file_existsfnthenSomefnelseNoneletfind_ocaml_progprog=matchList.find_map(get_path())~f:(fundir->best_progdirprog)with|None->prog_not_foundprog|Somefn->fnletwhichprog=List.find_map(get_path())~f:(fundir->letfn=dir^/prog^exeinOption.some_if(Sys.file_existsfn)fn)endletlogftfmt=Printf.ksprintft.logfmtletgen_idt=letn=t.counterint.counter<-n+1;nletquote_if_needed=letneed_quote=function|' '|'\"'->true|_->falseinfuns->ifString.is_emptys||String.exists~f:need_quotesthenFilename.quoteselsesmoduleProcess=structtyperesult={exit_code:int;stdout:string;stderr:string}letcommand_lineprogargs=String.concat~sep:" "(List.map(prog::args)~f:quote_if_needed)letrun_processt?dir?envprogargs=letprog_command_line=command_lineprogargsinlogft"run: %s"prog_command_line;letn=gen_idtinletcreate_process=letargs=Array.of_list(prog::args)inmatchenvwith|None->Unix.create_processprogargs|Someenv->letenv=Array.of_listenvinUnix.create_process_envprogargsenvinletstdout_fn=t.dest_dir^/sprintf"stdout-%d"ninletstderr_fn=t.dest_dir^/sprintf"stderr-%d"ninletstatus=letrun()=letopenfilef=Unix.openfilef[O_WRONLY;O_CREAT;O_TRUNC;O_SHARE_DELETE]0o666inletstdout=openfilestdout_fninletstderr=openfilestderr_fninletstdin,stdin_w=Unix.pipe()inUnix.closestdin_w;letp=create_processstdinstdoutstderrinUnix.closestdin;Unix.closestdout;Unix.closestderr;let_pid,status=Unix.waitpid[]pinstatusinmatchdirwith|None->run()|Somed->letold_dir=Sys.getcwd()inExn.protect~f:(fun()->Sys.chdird;run())~finally:(fun()->Sys.chdirold_dir)inmatchstatuswith|Unix.WSIGNALEDsignal->die"signal %d killed process: %s"signalprog_command_line|WSTOPPEDsignal->die"signal %d stopped process: %s"signalprog_command_line|WEXITEDexit_code->logft"-> process exited with code %d"exit_code;letstdout=Io.read_filestdout_fninletstderr=Io.read_filestderr_fninlogft"-> stdout:";List.iter(String.split_linesstdout)~f:(logft" | %s");logft"-> stderr:";List.iter(String.split_linesstderr)~f:(logft" | %s");{exit_code;stdout;stderr}(* [cmd] which cannot be quoted (such as [t.c_compiler] which contains some
flags) followed by additional arguments. *)letcommand_argscmdargs=String.concat~sep:" "(cmd::List.mapargs~f:quote_if_needed)letrun_commandt?dir?(env=[])cmd=logft"run: %s"cmd;letn=gen_idtinletstdout_fn=t.dest_dir^/sprintf"stdout-%d"ninletstderr_fn=t.dest_dir^/sprintf"stderr-%d"ninletin_dir=matchdirwith|None->""|Somedir->sprintf"cd %s && "(Filename.quotedir)inletwith_env=matchenvwith|[]->""|_->"env "^String.concat~sep:" "envinletexit_code=Printf.ksprintfSys.command"%s%s %s > %s 2> %s"in_dirwith_envcmd(Filename.quotestdout_fn)(Filename.quotestderr_fn)inletstdout=Io.read_filestdout_fninletstderr=Io.read_filestderr_fninlogft"-> process exited with code %d"exit_code;logft"-> stdout:";List.iter(String.split_linesstdout)~f:(logft" | %s");logft"-> stderr:";List.iter(String.split_linesstderr)~f:(logft" | %s");{exit_code;stdout;stderr}letrun_command_capture_exnt?dir?envcmd=let{exit_code;stdout;stderr}=run_commandt?dir?envcmdinifexit_code<>0thendie"command exited with code %d: %s"exit_codecmdelseifnot(String.is_emptystderr)thendie"command has non-empty stderr: %s"cmdelsestdoutletrun_command_okt?dir?envcmd=(run_commandt?dir?envcmd).exit_code=0letrunt?dir?envprogargs=run_commandt?dir?env(command_lineprogargs)letrun_capture_exnt?dir?envprogargs=run_command_capture_exnt?dir?env(command_lineprogargs)letrun_okt?dir?envprogargs=run_command_okt?dir?env(command_lineprogargs)endletocaml_config_vartvar=String.Map.findt.ocamlc_configvarletocaml_config_var_exntvar=matchString.Map.findt.ocamlc_configvarwith|None->die"variable %S not found in the output of `%s`"vart.ocamlc_config_cmd|Somes->sletread_dot_dune_configurator_file~build_dir=letfile=Stdune.Path.relative(Stdune.Path.of_filename_relative_to_initial_cwdbuild_dir)".dune/configurator"inifnot(Stdune.Path.existsfile)thendie"Cannot find special file produced by dune.";letsexps=Dune_lang.Parser.loadfile~mode:Many_as_oneinletdecode=letopenDune_lang.Decoderinenter(fields(let+ocamlc=field"ocamlc"stringand+ocaml_config_vars=field"ocaml_config_vars"(repeat(pairstringstring))and+_=(* So that we can add more fields in the future with minimal hassle *)leftover_fieldsin(* We assume that dune already checked for duplicates *)letocaml_config_vars=String.Map.of_list_exnocaml_config_varsin(ocamlc,ocaml_config_vars)))inDune_lang.Decoder.parsedecodeUniv_map.emptysexpsletfill_in_fields_that_depends_on_ocamlc_configt=letget=ocaml_config_var_exntinletc_compiler=matchString.Map.findt.ocamlc_config"c_compiler"with|Somec_comp->c_comp^" "^get"ocamlc_cflags"|None->get"bytecomp_c_compiler"in{twithext_obj=get"ext_obj";c_compiler;stdlib_dir=get"standard_library";ccomp_type=get"ccomp_type"}letcreate_from_inside_dune~dest_dir~log~build_dir~name=letdest_dir=matchdest_dirwith|Somedir->dir|None->Temp.create_temp_dir~prefix:"ocaml-configurator"~suffix:""inletocamlc,ocamlc_config=read_dot_dune_configurator_file~build_dirinletocamlc_config_cmd=Process.command_lineocamlc["-config"]infill_in_fields_that_depends_on_ocamlc_config{name;ocamlc;log;dest_dir;counter=0;ocamlc_config;ocamlc_config_cmd;ext_obj="";c_compiler="";stdlib_dir="";ccomp_type=""}letcreate?dest_dir?ocamlc?(log=ignore)name=match(ocamlc,Option.try_with(fun()->Sys.getenv"INSIDE_DUNE"))with|None,Somebuild_dirwhenbuild_dir<>"1"->create_from_inside_dune~dest_dir~log~build_dir~name|_->letdest_dir=matchdest_dirwith|Somedir->dir|None->Temp.create_temp_dir~prefix:"ocaml-configurator"~suffix:""inletocamlc=matchocamlcwith|Somefn->fn|None->Find_in_path.find_ocaml_prog"ocamlc"inletocamlc_config_cmd=Process.command_lineocamlc["-config"]inlett={name;ocamlc;log;dest_dir;counter=0;ext_obj="";c_compiler="";stdlib_dir="";ccomp_type="";ocamlc_config=String.Map.empty;ocamlc_config_cmd}inletocamlc_config=letocamlc_config_output=Process.run_command_capture_exnt~dir:dest_dirocamlc_config_cmd|>String.split_linesinmatchOcaml_config.Vars.of_linesocamlc_config_outputwith|Okx->x|Errormsg->die"Failed to parse the output of '%s':@\n%s"ocamlc_config_cmdmsginfill_in_fields_that_depends_on_ocamlc_config{twithocamlc_config}letneed_to_compile_and_link_separatelyt=(* Vague memory from writing the discover.ml script for Lwt... *)matcht.ccomp_typewith|"msvc"->true|_->falseletcompile_and_link_c_progt?(c_flags=[])?(link_flags=[])code=letdir=t.dest_dir^/sprintf"c-test-%d"(gen_idt)inUnix.mkdirdir0o777;letbase=dir^/"test"inletc_fname=base^".c"inletobj_fname=base^t.ext_objinletexe_fname=base^".exe"inIo.write_filec_fnamecode;logft"compiling c program:";List.iter(String.split_linescode)~f:(logft" | %s");letrun_okargs=Process.run_command_okt~dir(Process.command_argst.c_compilerargs)inletok=ifneed_to_compile_and_link_separatelytthenrun_ok(c_flags@["-I";t.stdlib_dir;"-c";c_fname])&&run_ok("-o"::exe_fname::obj_fname::link_flags)elserun_ok(List.concat[c_flags;["-I";t.stdlib_dir;"-o";exe_fname;c_fname];link_flags])inifokthenOk()elseError()letcompile_c_progt?(c_flags=[])code=letdir=t.dest_dir^/sprintf"c-test-%d"(gen_idt)inUnix.mkdirdir0o777;letbase=dir^/"test"inletc_fname=base^".c"inletobj_fname=base^t.ext_objinIo.write_filec_fnamecode;logft"compiling c program:";List.iter(String.split_linescode)~f:(logft" | %s");letok=Process.run_command_okt~dir(Process.command_argst.c_compiler(c_flags@["-I";t.stdlib_dir;"-o";obj_fname;"-c";c_fname]))inifokthenOkobj_fnameelseError()letc_testt?c_flags?link_flagscode=matchcompile_and_link_c_progt?c_flags?link_flagscodewith|Ok_->true|Error_->falsemoduleC_define=structmoduleType=structtypet=|Switch|Int|Stringletname=function|Switch->"bool"|Int->"int"|String->"string"endmoduleValue=structtypet=|Switchofbool|Intofint|Stringofstringletswitchb=Switchbletinti=Intiendletextract_program?preludeincludesvars=lethas_typet=List.existsvars~f:(fun(_,t')->t=t')inletbuf=Buffer.create1024inletprfmt=Printf.bprintfbuf(fmt^^"\n")inList.iterincludes~f:(pr"#include <%s>");pr"";Option.iterprelude~f:(pr"%s");ifhas_typeType.Intthenpr{|
#define DUNE_ABS(x) ((x >= 0)? x: -(x))
#define DUNE_D0(x) ('0'+(DUNE_ABS(x)/1 )%%10)
#define DUNE_D1(x) ('0'+(DUNE_ABS(x)/10 )%%10), DUNE_D0(x)
#define DUNE_D2(x) ('0'+(DUNE_ABS(x)/100 )%%10), DUNE_D1(x)
#define DUNE_D3(x) ('0'+(DUNE_ABS(x)/1000 )%%10), DUNE_D2(x)
#define DUNE_D4(x) ('0'+(DUNE_ABS(x)/10000 )%%10), DUNE_D3(x)
#define DUNE_D5(x) ('0'+(DUNE_ABS(x)/100000 )%%10), DUNE_D4(x)
#define DUNE_D6(x) ('0'+(DUNE_ABS(x)/1000000 )%%10), DUNE_D5(x)
#define DUNE_D7(x) ('0'+(DUNE_ABS(x)/10000000 )%%10), DUNE_D6(x)
#define DUNE_D8(x) ('0'+(DUNE_ABS(x)/100000000 )%%10), DUNE_D7(x)
#define DUNE_D9(x) ('0'+(DUNE_ABS(x)/1000000000)%%10), DUNE_D8(x)
#define DUNE_SIGN(x) ((x >= 0)? '0': '-')
|};List.iterivars~f:(funi(name,t)->matchtwith|Type.Int->letc_arr_i=letb=Buffer.create8inletis=string_of_intiinfori=0toString.lengthis-1doPrintf.bprintfb"'%c', "is.[i]done;Buffer.contentsbinpr{|
const char s%i[] = {
'B', 'E', 'G', 'I', 'N', '-', %s'-',
DUNE_SIGN((%s)),
DUNE_D9((%s)),
'-', 'E', 'N', 'D'
};
|}ic_arr_inamename|String->pr{|const char *s%i = "BEGIN-%i-" %s "-END";|}iiname|Switch->pr{|
#ifdef %s
const char *s%i = "BEGIN-%i-true-END";
#else
const char *s%i = "BEGIN-%i-false-END";
#endif
|}nameiiii);Buffer.contentsbufletextract_valuesobj_filevars=letvalues=Io.with_lexbuf_from_fileobj_file~f:(Extract_obj.extract[])|>Int.Map.of_list_exninList.mapivars~f:(funi(name,t)->letraw_val=matchInt.Map.findvaluesiwith|None->die"Unable to get value for %s"name|Somev->vinletvalue=matchtwith|Type.Switch->Bool.of_stringraw_val|>Option.map~f:Value.switch|Int->Int.of_stringraw_val|>Option.map~f:Value.int|String->Some(Stringraw_val)inletvalue=matchvaluewith|Somev->v|None->letmsg=sprintf"Unable to read variable %S of type %s. Invalid value %S in %s \
found"name(Type.namet)raw_valobj_fileinraise(Fatal_errormsg)in(name,value))letimportt?prelude?c_flags~includesvars=letprogram=extract_program?prelude("stdio.h"::includes)varsinmatchcompile_c_progt?c_flagsprogramwith|Error_->die"failed to compile program"|Okobj->extract_valuesobjvarsletgen_header_filet~fname?protection_varvars=letprotection_var=matchprotection_varwith|Somev->v|None->String.map(t.name^"_"^Filename.basenamefname)~f:(function|'a'..'z'asc->Char.uppercase_asciic|('A'..'Z'|'0'..'9')asc->c|_->'_')inletvars=List.sortvars~compare:(fun(a,_)(b,_)->String.compareab)inletlines=List.mapvars~f:(fun(name,value)->match(value:Value.t)with|Switchfalse->sprintf"#undef %s"name|Switchtrue->sprintf"#define %s"name|Intn->sprintf"#define %s (%d)"namen|Strings->sprintf"#define %s %S"names)inletlines=List.concat[[sprintf"#ifndef %s"protection_var;sprintf"#define %s"protection_var];lines;["#endif"]]inlogft"writing header file %s"fname;List.iterlines~f:(logft" | %s");lettmp_fname=fname^".tmp"inIo.write_linestmp_fnamelines;Sys.renametmp_fnamefnameendletwhichtprog=logft"which: %s"prog;letx=Find_in_path.whichproginlogft"-> %s"(matchxwith|None->"not found"|Somefn->"found: "^quote_if_neededfn);xmodulePkg_config=structtypenonrect={pkg_config:string;configurator:t}letgetc=Option.map(whichc"pkg-config")~f:(funpkg_config->{pkg_config;configurator=c})typepackage_conf={libs:stringlist;cflags:stringlist}letgen_queryt~package~expr=letc=t.configuratorinletdir=c.dest_dirinletexpr=matchexprwith|Somee->e|None->ifString.existspackage~f:(function|'='|'>'|'<'->true|_->false)thenwarn"Package name %S contains invalid characters. Use \
Pkg_config.query_expr to construct proper queries"package;packageinletenv=matchocaml_config_varc"system"with|Some"macosx"->letopenOption.Oinlet*brew=whichc"brew"inlet+new_pkg_config_path=letprefix=String.trim(Process.run_capture_exnc~dirbrew["--prefix"])inletp=sprintf"%s/opt/%s/lib/pkgconfig"(quote_if_neededprefix)packageinOption.some_if(matchSys.is_directorypwith|s->s|exceptionSys_error_->false)pinlet_PKG_CONFIG_PATH="PKG_CONFIG_PATH"inletpkg_config_path=matchSys.getenv_PKG_CONFIG_PATHwith|s->s^":"|exceptionNot_found->""in[sprintf"%s=%s%s"_PKG_CONFIG_PATHpkg_config_pathnew_pkg_config_path]|_->Noneinletpc_flags="--print-errors"inlet{Process.exit_code;stderr;_}=Process.run_processc~dir?envt.pkg_config[pc_flags;expr]inifexit_code=0thenletrunwhat=matchString.trim(Process.run_capture_exnc~dir?envt.pkg_config[what;package])with|""->[]|s->String.extract_blank_separated_wordssinOk{libs=run"--libs";cflags=run"--cflags"}elseErrorstderrletqueryt~package=Result.to_option@@gen_queryt~package~expr:Noneletquery_exprt~package~expr=Result.to_option@@gen_queryt~package~expr:(Someexpr)letquery_expr_errt~package~expr=gen_queryt~package~expr:(Someexpr)endletmain?(args=[])~namef=letbuild_dir=matchSys.getenv"INSIDE_DUNE"with|exceptionNot_found->die"Configurator scripts must be run with Dune. To manually run a script, \
use $ dune exec."|"1"->die"You seem to be running Dune < 2.3. This version of dune-configurator \
requres at lest dune 2.3."|s->sinletverbose=reffalseinletdest_dir=refNoneinletargs=Arg.align([("-verbose",Arg.Setverbose," be verbose");("-dest-dir",Arg.String(funs->dest_dir:=Somes),"DIR save temporary files to this directory")]@args)inletanons=raise(Arg.Bad(sprintf"don't know what to do with %s"s))inletusage=sprintf"%s [OPTIONS]"(Filename.basenameSys.executable_name)inArg.parseargsanonusage;letlog_db=ref[]inletlogs=log_db:=s::!log_dbinlett=create_from_inside_dune~dest_dir:!dest_dir~log:(if!verbosethenprerr_endlineelselog)~build_dir~nameintryftwithexn->(letbt=Printexc.get_raw_backtrace()inList.iter(List.rev!log_db)~f:(eprintf"%s\n");matchexnwith|Fatal_errormsg->eprintf"Error: %s\n%!"msg;exit1|_->Exn.raise_with_backtraceexnbt)