123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301(******************************************************************************)(* OASIS: architecture for building OCaml libraries and applications *)(* *)(* Copyright (C) 2011-2016, Sylvain Le Gall *)(* Copyright (C) 2008-2011, OCamlCore SARL *)(* *)(* This library 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; either version 2.1 of the License, or (at *)(* your option) any later version, with the OCaml static compilation *)(* exception. *)(* *)(* This library 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 file COPYING for more *)(* details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this library; if not, write to the Free Software Foundation, *)(* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *)(******************************************************************************)(* The content of this file started with ocsigen_loader.ml
* from the ocsigen project (http://www.ocsigen.org).
*
* It was:
* Copyright (C) 2008 Stéphane Glondu
*)exceptionDynlink_errorofstring*exnexceptionFindlib_errorofstring*exnexceptionPlugin_not_foundofstring(**/**)(** TODO: Gettext related functions, to be replaced by real ones. *)lets_s=sletf_fmt=""^^fmt(**/**)(* Error formatting *)openPrintflet()=Printexc.register_printer(function|Dynlink_error(s,Dynlink.Errore)->Some(sprintf(f_"Dynlink error while loading '%s': %s")s(Dynlink.error_messagee))|Findlib_error(s,Fl_package_base.No_such_package(s',msg))->letpkg=ifs=s'then"'"^s^"'"elsesprintf(f_"'%s' [while trying to load '%s']")s'sinletadditional=ifmsg=""then""elsesprintf" (%s)"msginSome(sprintf(f_"Findlib package %s not found%s")pkgadditional)|Findlib_error(s,e)->Some(sprintf"Findlib error while handling '%s': %s"s(Printexc.to_stringe))|Plugin_not_foundnm->Some(sprintf(f_"Plugin '%s' not found")nm)|_->None);moduleStringSet=Set.Make(String)(* Loading files *)moduleSetString=Set.Make(String)letfindlib_packages_loaded=refSetString.emptyletadd_findlib_packagee=findlib_packages_loaded:=SetString.adde!findlib_packages_loaded(* Fake object, to keep in the generated program a reference to CamlinternalOO.
*)classfoo=objectendletinitfindlib_packages_loaded=(* TODO: only_once *)List.iteradd_findlib_packagefindlib_packages_loaded;Findlib.init()type'at={system:string;msg:([>`Debug|`Warning|`Error]as'a)->string->unit;}typeentry={findlib_name:string;name:string;synopsis:stringoption;version:stringoption;deprecated:bool;}(* Using Findlib to locate files *)letfindfilestpackage=letrev_split_blankstr=letbuf=Buffer.create13inletlst=ref[]inString.iter(function|' '->ifBuffer.lengthbuf>0thenbeginlst:=Buffer.contentsbuf::!lst;Buffer.clearbufend|c->Buffer.add_charbufc)str;beginmatchBuffer.contentsbufwith|""->()|str->lst:=str::!lstend;!lstintryletpreds=[ifDynlink.is_nativethen"native"else"byte"]inletdeps=List.filter(funa->not(SetString.mema!findlib_packages_loaded))(Findlib.package_deep_ancestorspreds[package])int.msg`Debug(sprintf(f_"Dependencies of %s: %s")package(String.concat", "deps));letrecaux=function|[]->[]|a::tl->letmods=tryletraw=Findlib.package_property("plugin"::preds)a"archive"inList.rev(rev_split_blankraw)withNot_found->begintryletraw=Findlib.package_propertypredsa"archive"inList.rev_map(funfn->(* Replacing .cmx/.cmxa by .cmxs *)ifDynlink.is_native&&(Filename.check_suffixfn"cmx"||Filename.check_suffixfn"cmxa")then(Filename.chop_extensionfn)^".cmxs"elsefn)(rev_split_blankraw)withNot_found->begint.msg`Error(sprintf(f_"Cannot find 'archive' attribute for findlib \
package %s")a);[]endendinletbase=Findlib.package_directoryainadd_findlib_packagea;(List.map(Findlib.resolve_path~base)mods)@(auxtl)inletres=auxdepsint.msg`Debug(sprintf"Object files needed: %s"(String.concat", "res));reswithe->raise(Findlib_error(package,e))moduleSetEntry=Set.Make(structtypet=entryletcomparee1e2=String.comparee1.namee2.nameend)letlistt=letlst=Fl_package_base.list_packages()inletset=List.fold_left(funaccpkg_str->tryletpkg=Fl_package_base.querypkg_strinletpackage_defs=pkg.Fl_package_base.package_defsinletplugin_system=Fl_metascanner.lookup"plugin_system"[]package_defsinletdefault_lookupvar=trySome(Fl_metascanner.lookupvar[]package_defs)withNot_found->Noneinletdefault_lookup_valvardflt=matchdefault_lookupvarwith|Somestr->str|None->dfltinifplugin_system=t.systemthenbeginletdeprecated=letstr=default_lookup_val"plugin_deprecated""false"intrybool_of_stringstrwithInvalid_argument_->t.msg`Warning(sprintf"Field plugin_deprecated of plugin '%s' \
should be true or false, got %s."pkg_strstr);falseinletentry={findlib_name=pkg_str;name=default_lookup_val"plugin_name"pkg_str;synopsis=default_lookup"plugin_synopsis";version=default_lookup"version";deprecated=deprecated;}inifSetEntry.mementryaccthent.msg`Warning(sprintf(f_"Plugin '%s' already defined \
(findlib name: %s; directory: '%s').")entry.namepkg_strpkg.Fl_package_base.package_dir);SetEntry.addentryaccendelsebeginaccendwithe->acc)SetEntry.emptylstinSetEntry.elementssetletloadtnm=(* TODO: critical section. *)letentry=tryList.find(fune->e.name=nm)(listt)withNot_found->raise(Plugin_not_foundnm)inletlst=findfilestentry.findlib_nameintryList.iterDynlink.loadfilelstwithe->raise(Dynlink_error(nm,e))