123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226(* Ocsigen
* http://www.ocsigen.org
* File ocsigen_loader.ml
* Copyright (C) 2008 Stéphane Glondu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)openOcsigen_libexceptionDynlink_errorofstring*exnexceptionFindlib_errorofstring*exnletsection=Lwt_log.Section.make"ocsigen:dynlink"(************************************************************************)(* Translate .cmo/.cma extensions to .cmxs in native mode, and .cmxs
to .cmo (.cma if the file exists) in bytecode mode. *)lettranslate=ifOcsigen_config_static.is_nativethenfunfilename->ifFilename.check_suffixfilename".cmo"||Filename.check_suffixfilename".cma"then(Filename.chop_extensionfilename)^".cmxs"elsefilenameelsefunfilename->ifFilename.check_suffixfilename".cmxs"thenletfilename=Filename.chop_extensionfilenameinletcma=filename^".cma"inifSys.file_existscmathencmaelsefilename^".cmo"elsefilename(************************************************************************)(* Loading files *)letisloaded,addloaded=letset=refString.Set.emptyin((funs->String.Set.mems!set),(funs->set:=String.Set.adds!set))moduleM=Map.Make(String)letinit_functions=refM.emptyletget_init_on_load,set_init_on_load=letinit_on_load=reffalsein((fun()->!init_on_load),(funb->init_on_load:=b))letloadfileprepostforcefile=letfile=translatefileintryifforcethenbeginpre();Lwt_log.ign_info_f~section"Loading %s (will be reloaded every times)"file;begintryDynlink_wrapper.loadfilefile;post()withe->post();raiseeendendelseifnot(isloadedfile)thenbeginpre();Lwt_log.ign_info_f~section"Loading extension %s"file;begintryDynlink_wrapper.loadfilefile;post()withe->post();raiseeend;addloadedfile;endelseLwt_log.ign_info_f~section"Extension %s already loaded"filewith|e->raise(Dynlink_error(file,e))letid()=()letloadfilesprepostforcemodules=letrecaux=function|[]->()|[m]->loadfileprepostforcem|m::q->loadfileididfalsem;auxqinauxmodulesletset_module_init_functionnamef=init_functions:=M.addnamef!init_functions;(* print_endline ("Added init_function for " ^ name); *)(* print_endline ("get_init_on_load: " ^ string_of_bool (get_init_on_load ())); *)ifget_init_on_load()thenf()letinit_moduleprepostforcename=letf=tryM.findname!init_functionswithNot_foundase->raise(Dynlink_error("named module "^name,e))intryifforcethenbeginpre();Lwt_log.ign_info_f~section"Initializing %s (will be initialized every time)"name;begintryf();post()withe->post();raiseeendendelseifnot(isloadedname)thenbeginpre();Lwt_log.ign_info_f~section"Initializing module %s "name;begintryf();post()withe->post();raiseeend;addloadedname;endelseLwt_log.ign_info_f~section"Module %s already initialized."namewith|e->raise(Dynlink_error(name,e))(************************************************************************)(* Manipulating Findlib's search path *)let()=Findlib.init()letocsigen_search_path=ref[]letupdate_search_path()=match!ocsigen_search_pathwith|[]->Findlib.init()|x->Findlib.init~env_ocamlpath:(String.concat":"x)()letget_ocamlpath=Findlib.search_pathletset_ocamlpathlp=ocsigen_search_path:=lp;update_search_path()letadd_ocamlpathp=ocsigen_search_path:=p::!ocsigen_search_path;update_search_path()(************************************************************************)(* Using Findlib to locate files *)letfindfiles=letcmx=Pcre.regexp~flags:[`MULTILINE;`CASELESS]"\\.cmx($| |a)"infunpackage->tryletpreds=[(ifOcsigen_config_static.is_nativethen"native"else"byte");"plugin";"mt"]inletdeps=List.filter(funa->not@@String.Set.memaOcsigen_config_static.builtin_packages)(Findlib.package_deep_ancestorspreds[package])inLwt_log.ign_info_f~section"Dependencies of %s: %s"package(String.concat", "deps);letrecaux=function|[]->[]|a::q->letmods=tryletraw=Findlib.package_propertypredsa"archive"in(* Replacing .cmx/.cmxa by .cmxs *)letraw=Ocsigen_lib.Netstring_pcre.global_replacecmx".cmxs "rawinList.filter((<>)"")(String.split~multisep:true' 'raw)with|Not_found->[]inletbase=Findlib.package_directoryain(List.map(Findlib.resolve_path~base)mods)@(auxq)inletres=auxdepsinLwt_log.ign_info_f~section"Needed: %s"(String.concat", "res);reswith|e->raise(Findlib_error(package,e))(************************************************************************)(* Error formatting *)openPrintflet()=Printexc.register_exn_printer(funf_rec->function|Dynlink_wrapper.Errore->Dynlink_wrapper.error_messagee|Dynlink_error(s,e)->sprintf"Dynlink error while loading %s: %s"s(f_rece)|Findlib_error(s,Fl_package_base.No_such_package(s',msg))->letpkg=ifs=s'thenselsesprintf"%s [while trying to load %s]"s'sinletadditional=ifmsg=""then""elsesprintf" (%s)"msginsprintf"Findlib package %s not found%s: maybe you forgot <findlib path=\"...\"/>?"pkgadditional|Findlib_error(s,e)->sprintf"Findlib error while handling %s: %s"s(f_rece)|e->raisee)