123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899moduleOptions=Optionsletoutput_structure(channel:out_channel)(s:Parsetree.structure)=letfmt=Format.formatter_of_out_channelchannelinPprintast.structurefmts;Format.pp_print_flushfmt()typecompiler={command:string;archive_option:string;archive_suffix:string;}letcompiler:compiler=ifDynlink.is_nativethen{command="ocamlopt";archive_option="-shared";archive_suffix=".cmxs";}else{command="ocamlc";archive_option="-a";archive_suffix=".cma";}letrectry_commands~verboselist=matchlistwith|[]->assertfalse|(command,args)::tl->letcommand_line=Filename.quote_commandcommandargsinifverbosethenprerr_endlinecommand_line;matchSys.commandcommand_linewith|0->()|127whentl<>[]->try_commands~verbosetl|exit_code->Location.raise_errorf~loc:!Ast_helper.default_loc"@[Unable@ to@ compile@ preprocessor:@ command-line@ \"%s\"@ \
failed@ with@ exit-code@ %d@]@."(String.escapedcommand_line)exit_codeletcompile(options:Options.t)(source_filename:string)(object_filename:string):unit=letflags=options.flags@List.concat_map(fundirectory->["-I";directory])options.directories@["-I";"+compiler-libs";"-w";"-40";compiler.archive_option;source_filename;"-o";object_filename]inletpreutils_cmi="metapp_preutils.cmi"inletapi_cmi="metapp_api.cmi"inletdune_preutils_path="preutils/.metapp_preutils.objs/byte/"inletdune_api_path="api/.metapp_api.objs/byte/"inlet(flags,packages)=ifSys.file_existspreutils_cmi&&Sys.file_existsapi_cmithen(flags,options.packages)elseifSys.file_exists(Filename.concatdune_preutils_pathpreutils_cmi)&&Sys.file_exists(Filename.concatdune_api_pathapi_cmi)then(["-I";dune_preutils_path;"-I";dune_api_path]@flags,options.packages)else(flags,["metapp.preutils";"metapp.api"]@options.packages)inletcommands=matchpackageswith|[]->[(compiler.command^".opt",flags);(compiler.command,flags)]|_->[("ocamlfind",[compiler.command;"-package";String.concat","packages]@flags)]intry_commands~verbose:options.verbosecommands(* Code taken from pparse.ml (adapted for a channel instead of a filename to use
open_temp_file), because Pparse.write_ast is introduced in OCaml 4.04.0. *)letwrite_ast(plainsource:bool)(channel:out_channel)(structure:Parsetree.structure):unit=ifplainsourcethenoutput_structurechannelstructureelsebeginoutput_stringchannelConfig.ast_impl_magic_number;output_valuechannel!Location.input_name;output_valuechannelstructureendletcompile_and_load(options:Options.t)(structure:Parsetree.structure):unit=let(source_filename,channel)=Filename.open_temp_file"metapp"".ml"inFun.protect(fun()->Fun.protect(fun()->write_astoptions.plainsourcechannelstructure)~finally:(fun()->close_outchannel);letobject_filename=Filename.remove_extensionsource_filename^compiler.archive_suffixincompileoptionssource_filenameobject_filename;Fun.protect(fun()->Dynlink.loadfileobject_filename)~finally:(fun()->Sys.removeobject_filename))~finally:(fun()->Sys.removesource_filename)