Commits

camlspotter committed d0f001e

gmaps and gchart examples work now!

  • Participants
  • Parent commits e96c989

Comments (0)

Files changed (15)

+# ==========================
+# OMyMakefile
+# ==========================
+# Useful functions to build OCaml projects
+
+#| A flag to tell that we can use OMyMakefile functions
+WithOMy=true
+
+#| The prefix. Equal to the PREFIX environment variable
+try
+  PREFIX=$(getenv PREFIX)
+default
+  eprintln(Specify PREFIX or prefix environment variable.)
+  exit 1 
+
+# OCaml 
+# ========================================================================
+
+#|Path to the OCaml library directory
+OCAML_WHERE = $(shell ocamlc -where)
+
+#|Version without extensions
+OCAML_VERSION = $(shell ocamlc -version | sed -e 's/^\([0-9.]*\).*/\1/')
+
+#|OMy requires OCamlFind!
+USE_OCAMLFIND = true
+OCAMLFIND_DESTDIR= $(shell ocamlfind printconf destdir)
+
+#|Set NATIVE_ENABLED false locally if a project does not requre opt compilation.
+NATIVE_ENABLED = $(OCAMLOPT_EXISTS)
+NATIVE_SHARED_ENABLED = $(OCAMLOPT_EXISTS)
+BYTE_ENABLED = true
+
+#|The default warning and errors. If you want to use different warning and error switches, use redefine the variable.
+OCAMLFLAGS = -w A-4-9 -warn-error A-4-9
+
+#|Global variable to be defined as empty
+OCAMLPACKAGEFLAGS=
+
+#|Preinstalled libraries which are always available for normal ocaml.
+#
+# You may want to add the required packages which are built and installed out of OMy framework:
+#
+#::
+#
+#   include OMyMakefile
+#   
+#   OCAML_PREINSTALLED_PACKS += llvm # llvm has been installed already, independently
+#   
+#   Subdirs()
+#
+# It includes "findlib" by default. If you want to build findlib in OMy framework, you have to remove it from the list.
+OCAML_PREINSTALLED_PACKS[]= bigarray camlp4 dbm dynlink graphics num num-top stdlib str threads unix findlib compiler-libs compiler-libs.common
+
+#|Redefinition of compiler commands
+public.OCamlC() =
+    value $(OCAMLFIND) $(OCAMLC) $(OCAMLPACKAGEFLAGS) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)\
+              $(OCAMLCFLAGS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES)
+# Why we need "public." ?
+
+public.OCamlOpt() =
+    value $(OCAMLFIND) $(OCAMLOPT) $(OCAMLPACKAGEFLAGS) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)\
+              $(OCAMLOPTFLAGS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES)
+
+if $(and $(not $(NATIVE_ENABLED)) $(not $(BYTE_ENABLED)))
+   err. =
+       extends $(UnbuildableException)
+       message = $(string $"You must turn on either NATIVE_ENABLED or BYTE_ENABLED")
+       raise $(err)
+
+#|Additional implicit rules by file extensions
+# annot, cmt, cmti files
+%.annot %.cmt: %.ml %.cmi
+	$(OCamlC) -c -annot -bin-annot $<
+
+%.spit %.cmti: %.mli 
+	$(OCamlC) -c -bin-annot $<
+
+#|Define OCAML_ANNOT so that ocamlc/ocamlopt automatically create spot/spit/annot/cmt/cmti files, even without -annot/-bin-annot option. This requires a special compiler patch 
+setenv(OCAML_ANNOT, 1)
+
+#|Enable the backtrace
+setenv(OCAMLRUNPARAM, b)
+
+# Common phonies
+# ==================================================================
+.PHONY: all install uninstall clean veryclean
+
+# Directories
+# =====================================================================
+
+#| The build root directory  
+BIG_ROOT=$(dir .)
+
+# Installation mark files
+# =======================================================================
+
+#| To enable the installation mark files, you must define INSTALLED path variable
+# for the mark file directory like INSTALLED=$(BIG_ROOT)/installed and make sure
+# the directory $(INSTALLED) exists. This preparation must be done outside of 
+# this OMyMakefile.
+
+#|Returns the installation mark files of $(packs)
+Installed(packs) = 
+  if $(defined INSTALLED)
+      return $(addprefix $(INSTALLED)/, $(packs))
+  else
+      return $(array)
+
+#|Create md5 sum file of files $(targets)
+CreateCheckSum(pack, targets)=
+    chan=$(fopen $(pack), w)
+    fprintln($(chan), $(string $(targets)))
+    fprintln($(chan), $(string $(digest $(targets))))
+    close($(chan))
+
+#|Create $(Installed $(pack)) file from the digests of $(targets)
+CreateInstalled(pack, targets)=
+    if $(defined INSTALLED)
+        println(dump md5 $(INSTALLED)/$(pack))
+        CreateCheckSum($(INSTALLED)/$(pack), $(targets))
+
+# Packages
+# =========================================================
+
+#| OCaml packages required for compilation. MyCaml* functions automatically add necessary dependencies over packages in $(OCAMLPACKS).
+# 
+# .. note:: They are also required for dependency analysis.
+public.OCAMLPACKS[]=
+
+#| CamlP4 syntax extension packages required for parsing. MyCaml* functions automatically add necessary dependencies over packages in $(CAMLP4PACKS).
+public.CAMLP4PACKS[]=
+
+# Dependencies
+# =========================================================================
+
+#|Returns packages managed by OMy framework
+OMyManagedPackages(packages) =
+   return $(set-diff $(packages), $(OCAML_PREINSTALLED_PACKS))
+
+#|Add dependencies of OCaml compiled files (cmx, cmo, etc.) over $(files).
+#
+# .. note:: These functions introduce implicit rules: *you may need to export it, if you use this function in a local context.*
+OCamlRequire(files) =
+    %.cmx %.cmo %.cmi %.cma %.cmxa %.annot %.spot %.spit %.cmt %.cmti: $(files)
+    export
+
+#|Add dependencies of OCaml compiled files (cmx, cmo, etc.) over $(packages).
+# $(packages) listed in OCAML_PREINSTALLED_PACKS are ignored.
+#
+# .. note:: These functions introduce implicit rules: *you may need to export it, if you use this function in a local context.*
+#
+# .. note:: Usually you do not need to call this function. Use OCAMLPACKS variable instead. 
+OCamlRequirePackages(packages) =
+    required_packs = $(OMyManagedPackages $(packages))
+    if $(defined INSTALLED)
+      %.cmx %.cmo %.cmi %.cma %.cmxa %.annot %.spot %.spit %.cmt %.cmti: $(Installed $(required_packs))
+      export
+    export
+
+#|Add dependencies of OCaml dependency analysis and build over $(packages).
+# Use this for adding dependencies for CamlP4 extensions.
+# $(packages) listed in OCAML_PREINSTALLED_PACKS are ignored.
+#
+# .. note:: These functions introduce implicit rules: *you may need to export it, if you use this function in a local context.*
+#
+# .. note:: Usually you do not need to call this function. Use CAML4PACKS variable instead. 
+OCamlRequireCamlP4Packages(packages) =
+    required_packs = $(OMyManagedPackages $(packages))
+    if $(defined INSTALLED)
+      .SCANNER: scan-ocaml-%: $(Installed $(required_packs))
+      %.cmx %.cmo %.cmi %.cma %.cmxa %.annot %.spot %.spit : $(Installed $(required_packs))
+      export 
+    export
+
+#|``omake xxx.auto.mli`` generates .mli file from xxx.ml 
+%.auto.mli: %.ml
+	$(OCamlC) -i -c $< > $@
+
+# Build rules
+# ==========================================================
+
+# Extend the bundled OCamlPackage with .spot creation
+public.OCamlLibrary(name, files) =
+   # XXX: JYH: these variables should be marked private in 0.9.9
+   protected.name = $(file $(name))
+
+   protected.OFILES   = $(addsuffix $(EXT_OBJ), $(files))
+   protected.CMOFILES = $(addsuffix .cmo, $(files))
+   protected.CMXFILES = $(addsuffix .cmx, $(files))
+
+   protected.CLIB      = $(file $(name)$(EXT_LIB))
+   protected.BYTELIB   = $(file $(name).cma)
+   protected.NATIVELIB = $(file $(name).cmxa)
+   protected.NATIVESHAREDLIB = $(file $(name).cmxs)
+
+   #
+   # Link commands
+   #
+   $(BYTELIB): $(CMOFILES)
+        $(OCAMLFIND) $(OCAMLLINK) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) $(OCAMLCFLAGS) \
+                $(OCAML_LIB_FLAGS) -a -o $@ $(OCamlLinkSort $(CMOFILES))
+
+   $(NATIVELIB) $(CLIB): $(CMXFILES) $(OFILES)
+        $(OCAMLFIND) $(OCAMLOPTLINK) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) $(OCAMLOPTFLAGS) \
+                $(OCAML_LIB_FLAGS) -a -o $(NATIVELIB) $(OCamlLinkSort $(CMXFILES))
+
+   $(NATIVESHAREDLIB): $(CMXFILES) $(OFILES)
+         $(OCAMLFIND) $(OCAMLOPTLINK) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) $(OCAMLOPTFLAGS) \
+                 $(OCAML_LIB_FLAGS) -shared -o $(NATIVESHAREDLIB) $(OCamlLinkSort $(CMXFILES))
+
+   return $(array $(if $(NATIVE_ENABLED), $(NATIVELIB)), \
+                  $(if $(NATIVE_ENABLED), $(CLIB)), \
+                  $(if $(NATIVE_SHARED_ENABLED), $(NATIVESHAREDLIB)), \
+                  $(if $(BYTE_ENABLED), $(BYTELIB)))
+
+# Extend the bundled OCamlPackage with .spot creation
+public.OCamlPackage(name, files) =
+   # XXX: JYH: these variables should be marked private in 0.9.9
+   protected.OFILES   = $(addsuffix $(EXT_OBJ), $(files))
+   protected.CMOFILES = $(addsuffix .cmo, $(files))
+   protected.CMXFILES = $(addsuffix .cmx, $(files))
+
+   protected.OBJ       = $(file $(name)$(EXT_OBJ))
+   protected.CMO       = $(file $(name).cmo)
+   protected.CMX       = $(file $(name).cmx)
+   protected.CMI       = $(file $(name).cmi)
+   protected.MLI       = $(file $(name).mli)
+
+   protected.BYTE_TARGETS   = $(CMO)
+   protected.NATIVE_TARGETS = $(CMX) $(OBJ)
+
+   if $(BYTE_ENABLED)
+      BYTE_TARGETS += $(file $(name).cmt)
+      export
+   else
+      NATIVE_TARGETS += $(file $(name).cmt)
+      export
+   export
+
+   protected.TARGETS = $(CMI)
+   if $(NATIVE_ENABLED)
+       TARGETS += $(NATIVE_TARGETS)
+       export
+
+   if $(BYTE_ENABLED)
+       TARGETS += $(BYTE_TARGETS)
+       export
+
+   #
+   # Link commands
+   #
+   protected.BYTE_DEPS = $(CMOFILES)
+   $(BYTE_TARGETS): $(CMOFILES)
+      section rule
+         if $(or $(NATIVE_ENABLED), $(target-exists $(MLI)))
+             BYTE_DEPS += $(CMI)
+             export
+         else
+             BYTE_TARGETS += $(CMI)
+             export
+         $(BYTE_TARGETS): $(BYTE_DEPS)
+            $(OCAMLFIND) $(OCAMLC) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
+                $(OCAMLCFLAGS) $(OCAML_LIB_FLAGS) -pack -bin-annot -o $(CMO) $(OCamlLinkSort $(CMOFILES))
+
+   protected.NATIVE_DEPS = $(CMXFILES) $(OFILES)
+   $(NATIVE_TARGETS): $(NATIVE_DEPS)
+      section rule
+         if $(target-exists $(MLI))
+            NATIVE_DEPS += $(CMI)
+            export
+         else
+            NATIVE_TARGETS += $(CMI)
+            export
+         $(NATIVE_TARGETS): $(NATIVE_DEPS)
+            $(OCAMLFIND) $(OCAMLOPTLINK) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
+                $(OCAMLOPTFLAGS) $(OCAML_LIB_FLAGS) -pack -bin-annot -o $(CMX) $(OCamlLinkSort $(CMXFILES))
+
+   $(CMI):
+      section rule
+         if $(target-exists $(MLI))
+            $(CMI): $(MLI) :scanner: scan-ocaml-$(name).mli
+                $(OCamlC) -c $<
+         elseif $(NATIVE_ENABLED)
+            $(NATIVE_TARGETS) $(CMI): $(NATIVE_DEPS)
+               $(OCAMLFIND) $(OCAMLOPTLINK) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
+                   $(OCAMLOPTFLAGS) $(OCAML_LIB_FLAGS) -pack -o $(CMX) $(OCamlLinkSort $(CMXFILES))
+         else
+            $(BYTE_TARGETS) $(CMI): $(BYTE_DEPS)
+               $(OCAMLFIND) $(OCAMLC) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) \
+                   $(OCAMLCFLAGS) $(OCAML_LIB_FLAGS) -pack -o $(CMO) $(OCamlLinkSort $(CMOFILES))
+
+   return $(TARGETS)
+
+# Add implicit dependencies over the packages declared in OCAMLPACKS and CAMLP4PACKS
+# If this function is used in a local scope, you may want to export. 
+AddLocalOCamlPackageDependencies() =
+  # We make sure the required libraries are installed
+  OCamlRequirePackages($(OCAMLPACKS)) # must be exported!
+  OCamlRequireCamlP4Packages($(OCAMLPACKS) $(CAMLP4PACKS))
+  export
+
+#| Add a rule for OCaml package $(library_name).cmo, $(library_name).cmx and etc.
+#     library_name
+#         target package name
+#     files
+#         ML module names (without .ml)
+#     cmodules
+#         C source files (without .c)
+#     linkopts
+#         C library link option (without OCaml -cclib options)    
+#
+#  You can specify MyOCamlPackageExtras before using this function to install files out of the scope of this rule.   
+#  
+#  If $(NO_INSTALL) is defined, omake install does not install the package
+#
+#  Example::
+#
+#      MyOCamlPackage(foo, alpha beta, $(EMPTY), $(EMPTY))
+#
+#  Todo: external C library
+MyOCamlPackage(library_name, files, cmodules, linkopts) =
+  AddLocalOCamlPackageDependencies()
+  export # The above thing is local: need to be exported
+
+  CSTUBS=$(addsuffix .o,$(cmodules))
+  CMOS=$(addsuffix .cmo,$(library_name))
+  CMXS=$(addsuffix .cmx,$(library_name))
+  CMA=$(library_name).cma
+  CMXA=$(library_name).cmxa
+
+  if $(not $(defined MyOCamlPackageExtras))
+      MyOCamlPackageExtras[]=
+      export
+
+  CSTUBLIBRARIES=
+  if $(not $(equal $(cmodules), $(EMPTY)))
+      CSTUBLIBRARIES= dll$(library_name).so lib$(library_name).a 
+      export
+
+  # CR jfuruse: I guess we do not need the following
+  # export # export the implicit rule above
+
+  .PHONY: install-lib
+  install-lib: $(library_name).cmo $(library_name).cmx $(library_name).cma $(library_name).cmxa $(MyOCamlPackageExtras)
+
+  $(CMA) $(CMXA) $(library_name).a $(CSTUBLIBRARIES) : $(CSTUBS) $(CMOS) $(CMXS)
+      if $(not $(equal $(cmodules), $(EMPTY)))
+          ocamlmklib -verbose -o $(library_name) $(CSTUBS) $(linkopts) $(CMOS) $(CMXS)
+      else
+          $(OCamlC) -a -o $(CMA) $(CMOS)
+          $(OCamlOpt) -a -o $(CMXA) $(CMXS)
+
+  ## the followings are necessary for packing
+
+  OCAMLPACKAGEFLAGS += -for-pack $(capitalize $(library_name))
+  # export OCAMLPACKAGEFLAGS
+
+  ## build rule
+
+  .DEFAULT: $(OCamlPackage $(library_name), $(files))
+
+  ## clean
+  AutoClean()
+  clean:
+	rm -f $(library_name).spot $(library_name).cmt
+
+  ## install
+
+  # CR jfuruse: x.cmi is required if x.mli does not exist!
+  targets[]=META $(glob i, *.mli) $(library_name).cmi $(library_name).cmo $(library_name).cmx $(library_name).cma $(library_name).cmxa $(library_name).o $(library_name).a $(CSTUBLIBRARIES) $(MyOCamlPackageExtras)
+
+  targets[]+= $(library_name).cmt
+
+  if $(not $(defined NO_INSTALL))
+    if $(defined INSTALLED)
+      $(Installed $(library_name)): $(targets)
+        $(OCAMLFIND) remove $(library_name)
+        section:
+              $(OCAMLFIND) install $(library_name) $(targets)
+              CreateInstalled($(library_name), $(targets))
+
+      install: $(Installed $(library_name))
+
+      uninstall:
+        rm -f $(Installed $(library_name))
+        $(OCAMLFIND) remove $(library_name)
+      export
+    else
+      install: $(targets)
+        $(OCAMLFIND) remove $(library_name)
+        $(OCAMLFIND) install $(library_name) $(targets)
+
+      uninstall:
+	$(OCAMLFIND) remove $(library_name)
+      export
+    export
+
+############################################################## build ocaml exec
+
+#| Add a rule to build a program $(name)
+#      name
+#          Name of the program
+#      files
+#          OCaml module names (without .ml)
+MyOCamlTestProgram(name, files) =
+  AddLocalOCamlPackageDependencies()
+  export # The above thing is local: need to be exported
+
+  $(name).run $(name).opt: $(Installed $(OMyManagedPackages $(OCAMLPACKS)))
+
+  # CR jfuruse: forgot to add the deps over the packages!
+  .DEFAULT: $(OCamlProgram $(name), $(files))
+
+  # The following clean the files twice if MyOCamlPackge coexists,
+  # but who cases ?
+  AutoClean()
+
+#| Add a rule to build a program $(name)
+#      name
+#          Name of the program
+#      files
+#          OCaml module names (without .ml)
+#  In addition to MyOCamlTestProgram, the binary is installed by omake install
+MyOCamlProgram(name, files) =
+  MyOCamlTestProgram($(name), $(files))
+  export # The above thing is local: need to be exported
+
+  if $(not $(defined NO_INSTALL))
+    install: $(name) $(name).run $(name).opt
+      install $(name) $(name).run $(name).opt $(PREFIX)/bin
+    uninstall:
+      rm -f $(PREFIX)/bin/$(name) $(PREFIX)/bin/$(name).run $(PREFIX)/bin/$(name).opt
+    export
+
+#| Add a rule to build a toplevel $(name)
+#      name
+#          Name of the program
+#      files
+#          OCaml module names (without .ml)
+OCamlTop(name, files) =
+   # XXX: JYH: these variables should be marked private in 0.9.9
+   protected.CMOFILES  = $(addsuffix .cmo, $(files))
+   # protected.CMXFILES  = $(addsuffix .cmx, $(files))
+   # protected.OFILES    = $(addsuffix $(EXT_OBJ), $(files))
+
+   protected.CMAFILES  = $(addsuffix .cma,  $(OCAML_LIBS))
+   # protected.CMXAFILES = $(addsuffix .cmxa, $(OCAML_LIBS))
+   protected.ARFILES   = $(addsuffix $(EXT_LIB), $(OCAML_LIBS))
+   protected.CMA_OTHER_FILES = $(addsuffix .cma, $(OCAML_OTHER_LIBS))
+   # protected.CMXA_OTHER_FILES = $(addsuffix .cmxa, $(OCAML_OTHER_LIBS))
+
+   protected.CLIBS = $(addsuffix $(EXT_LIB), $(OCAML_CLIBS))
+
+   protected.name = $(file $(name))
+
+   protected.PROG     = $(file $(name)$(EXE))
+   protected.BYTEPROG = $(file $(name).run)
+   # protected.OPTPROG  = $(file $(name).opt)
+
+   #
+   # Rules to build byte-code and native targets
+   #
+   $(BYTEPROG): $(CMAFILES) $(CMOFILES) $(CLIBS)
+        $(OCAMLFIND) $(OCAMLMKTOP) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS) $(OCAMLCFLAGS)\
+                $(PREFIXED_OCAMLINCLUDES) $(OCAML_BYTE_LINK_FLAGS)\
+                -o $@ $(CMA_OTHER_FILES) $(CMAFILES) $(OCamlLinkSort $(CMOFILES))\
+                $(CLIBS) $(OCAML_LINK_FLAGS)
+
+   $(PROG): $(BYTEPROG)
+        ln-or-cp $< $@
+
+   return $(array $(PROG), $(BYTEPROG))
+
+MyOCamlTop(name, files) =
+  AddLocalOCamlPackageDependencies()
+  export # The above thing is local: need to be exported
+
+  $(name): $(Installed $(OMyManagedPackages $(OCAMLPACKS)))
+
+  # CR jfuruse: forgot to add the deps over the packages!
+  .DEFAULT: $(OCamlTop $(name), $(files))
+
+  # The following clean the files twice if MyOCamlPackge coexists,
+  # but who cases ?
+  AutoClean()
+  export # The above thing is local: need to be exported
+
+  if $(not $(defined NO_INSTALL))
+    install: $(name) $(name).run
+      install $(name) $(name).run $(PREFIX)/bin
+    uninstall:
+      rm -f $(PREFIX)/bin/$(name) $(PREFIX)/bin/$(name).run
+    export
+
+#|  Add rules to build OCaml library $(name)
+#        name
+#            Name of the library
+#        files
+#            OCaml module name (without .ml)
+#
+#   .. note :: Probably you should use MyOCamlPackage
+MyOCamlLibrary(library_name, files) =
+  AddLocalOCamlPackageDependencies()
+  protected.CMIFILES = $(addsuffix .cmi, $(files))
+  targets = $(OCamlLibrary $(library_name), $(files)) $(CMIFILES) $(glob i, *.mli) 
+
+  .DEFAULT: $(targets)
+
+  export # The above thing is local: need to be exported
+
+  if $(not $(defined NO_INSTALL))
+    targets[] += META 
+    if $(defined INSTALLED)
+      $(Installed $(library_name)): $(targets)
+        $(OCAMLFIND) remove $(library_name)
+        section:
+              $(OCAMLFIND) install $(library_name) $(targets)
+              CreateInstalled($(library_name), $(targets))
+
+      install: $(Installed $(library_name))
+
+      uninstall:
+        rm -f $(Installed $(library_name))
+        $(OCAMLFIND) remove $(library_name)
+      export
+    else
+      install: $(targets)
+        $(OCAMLFIND) remove $(library_name)
+        $(OCAMLFIND) install $(library_name) $(targets)
+
+      uninstall:
+	$(OCAMLFIND) remove $(library_name)
+      export
+    export
+
+  # The following clean the files twice if MyOCamlPacakge coexists,
+  # but who cases ?
+  AutoClean()
+
+# Auto clean
+# ====================================================================
+
+#| Install clean command which cleans all the target files exists under the directory. Use with care.
+AutoClean()=
+    .PHONY: clean
+    clean:
+        rm -f $(filter-proper-targets $(ls R, .))
+
+# Subdir traversal
+# =====================================================================
+
+#| Recursively traverse the subdirs except $(dirs)
+Subdirs_except(dirs) =
+  # println(PWD: $(shell pwd))
+
+  # need to export since .SUBDIRS is evaluated in the global scope
+  export VISIT_SUBDIRS
+
+  sub_omakefiles = $(glob i, */OMakefile)
+  subdirs = $(sub_omakefiles.map $(dirname))
+
+  VISIT_SUBDIRS=$(set-diff $(subdirs), $(dirs))
+
+  # println(SUBDIRS: $(string $(VISIT_SUBDIRS)))
+
+  # The rule
+  .SUBDIRS: $(VISIT_SUBDIRS)
+
+#| Recursively traverse all the subdirs
+Subdirs() =
+  Subdirs_except($(array))
+
+#| Recursively traverse the given subdirs $(dirs)
+Subdirs_only(dirs) =
+ .SUBDIRS: $(dirs)
+
+# Dependency dot files for Graphviz
+# ======================================================================
+
+#| Add a rule for ``depend.dot`` for a dependency graph of OCaml files in the current directory
+Dot() =
+	depend.dot: $(ls *.ml *.mli)
+	    $(OCAMLFIND) ocamldoc -I +threads $(OCAMLPACKAGEFLAGS) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) -dot -dot-include-all -dot-reduce $+ -o $@
+
+
+#| filter list
+#  example::
+#     is_url(file) =
+#       match $(file)
+#       case $'://'
+#         return true
+#       default
+#         return false
+# 
+#     DOWNLOAD_URLS[]=$(list_filter $(fun x, $(is_url $(x))), $(URLS))
+list_filter(pred, list) =
+  result=
+  foreach(x, $(list))
+    if $(apply $(pred), $(x))
+      result+=$(x)
+      export
+    export
+  return $(result)
+
+#| Obtain files installed as PACK
+GET_OCAMLFIND_OBJS(pack)=
+    return $(Files $(OCAMLFIND_DESTDIR)/$(pack))
+
+# Misc tools
+# ======================================================================
+
+#|ditto.
+mkdir_if_not_exists(dir) =
+  if $(not $(test -e $(dir))):
+    mkdir $(dir) 
+  return
+
+# Very clean
+# ======================================================================
+
+#| OCaml object files which are not real targets of OMake are not be
+# auto-cleaned away by ``omake clean``. This is not good in some situations
+# at linking.
+WithOCamlVeryClean() =
+    veryclean: 
+        rm -f *.cm* *.annot *.o *.a *.sp[io]t *.so *.exe *.byt *.opt *.run
+
+

File gchart/OMakefile

+OCAMLINCLUDES = $(dir . ../lib)
+OCAML_LIBS= ../lib/xJs
+OCamlRequire(../lib/xJs.cmo)
+
+OCAMLPACKS[] = 
+    spotlib_js
+
+OCAMLDEPFLAGS= -syntax camlp4o -package lwt,js_of_ocaml.syntax
+OCAMLPPFLAGS= -syntax camlp4o -package lwt,js_of_ocaml.syntax
+
+FILES[] =
+    chart
+
+MyOCamlJSProgram(chart, $(FILES))

File gchart/chart.ml

+open Spotlib_js.Spot
+open XJs
+open XJs.Std
+open Lwt
+
+let () = GChart.load ()
+
+(* eval_string cannot define a function. i.e.
+
+   eval_string "function drawChart () { ... }"
+
+   has no effect after eval_string.
+*)
+
+module Data = struct
+  let get_line s pos =
+    try 
+      `Line (String.index_from s pos '\n')
+    with
+    | Not_found ->
+        let len = String.length s in
+        if pos < len - 1 then `LineEnd
+        else `EOS
+
+  let iter_by_lines f s =
+    let rec iter pos =
+      match get_line s pos with
+      | `Line pos' -> 
+          f (String.sub s pos (pos' - pos));
+          iter (pos'+1)
+      | `LineEnd -> f (String.sub s pos (String.length s - pos))
+      | `EOS -> ()
+    in
+    iter 0
+
+  let parse_row s =
+    try
+      let pos = String.index s ' ' in
+      let len = String.length s in
+      Some (String.sub s 0 pos,
+            String.sub s (pos + 1) (len - pos - 1))
+    with
+    | _ -> None
+
+  let parse_rows s =
+    let items = ref [] in
+    iter_by_lines (fun s -> 
+      match parse_row s with
+      | None -> ()
+      | Some (x,y) ->
+          begin try
+            items := (int_of_string x, int_of_string y) :: !items
+          with
+          | _ -> ()
+          end) s;
+    !items
+
+  let get url =
+    Http.get url >>= function
+      | None -> return []
+      | Some s -> return (parse_rows s)
+end
+
+let drawChart () = 
+  let visualization = GChart.get () in
+  let data = jsnew (visualization##_DataTable) () in
+  data##addColumn(Js.string "number", Js.string "X");
+  data##addColumn(Js.string "number", Js.string "Y");
+
+  (* eval_string of JavaScript object literal fails *)
+  (* Someone has written a patch for a syntax sugar of Javascript object literal. So wait and see. *)
+  let options = Unsafe.variable "{'title':'Random value distribution', 
+                                  'width':400, 
+                                  'height':300
+                                 }" 
+  in
+
+  let div = match getElementById "chart_div" with
+    | None -> assert false
+    | Some div -> div
+  in
+  let chart = jsnew (visualization##_ScatterChart) (div) in
+  chart##draw(data, options);
+
+  ignore begin
+    Data.get "data.txt" >>= fun rows ->
+
+    data##addRows(Js.array (Array.of_list (List.map (fun (x,y) -> 
+      Js.array [| Obj.magic x;
+                  Obj.magic y; |]) rows)));
+    chart##draw(data, options);
+    return ()
+  end
+
+let () = Google.setOnLoadCallback drawChart

File gchart/data.txt

+<html> <!-- stupid, but firefox tries parsing this data as XML or something! -->
+85 44
+41 82
+0 39
+20 4
+70 21
+85 17
+78 49
+12 15
+6 1
+69 28
+93 89
+23 14
+44 23
+3 96
+70 0
+12 49
+11 55
+97 57
+60 97
+63 83
+99 20
+70 59
+43 84
+46 20
+18 54
+58 88
+51 24
+69 9
+86 76
+22 38
+52 65
+83 19
+40 82
+35 70
+91 36
+24 68
+56 22
+28 35
+33 36
+71 53
+95 69
+92 57
+46 24
+33 78
+89 88
+58 95
+1 93
+13 56
+13 29
+17 0
+71 86
+48 24
+11 36
+32 71
+49 65
+50 31
+58 69
+83 12
+96 1
+61 9
+29 21
+97 81
+76 83
+31 30
+39 54
+14 24
+67 89
+87 68
+26 99
+76 21
+95 93
+63 68
+73 62
+77 36
+23 98
+11 40
+76 38
+70 20
+37 55
+90 88
+7 10
+43 51
+95 4
+61 93
+32 57
+92 53
+31 82
+53 83
+65 7
+45 60
+17 66
+54 51
+45 0
+13 66
+60 67
+18 31
+42 83
+11 29
+68 87
+6 47
+70 7
+46 69
+22 29
+36 51
+41 56
+90 25
+7 52
+10 54
+2 38
+80 38
+18 14
+40 80
+66 91
+20 91
+96 97
+5 53
+24 42
+87 88
+73 36
+63 88
+0 4
+15 4
+64 16
+36 20
+86 34
+88 91
+30 12
+54 46
+55 38
+27 60
+4 32
+67 38
+79 69
+62 72
+11 66
+27 60
+47 71
+1 61
+95 82
+13 69
+94 41
+56 25
+92 34
+40 54
+14 87
+37 78
+85 72
+71 97
+62 86
+77 59
+71 81
+88 89
+46 84
+80 85
+5 42
+59 51
+84 47
+68 51
+51 67
+68 98
+21 81
+18 7
+65 12
+65 98
+19 25
+58 80
+30 63
+17 82
+89 55
+45 44
+67 62
+24 71
+34 71
+48 1
+97 46
+26 36
+63 85
+90 76
+81 20
+81 56
+62 36
+69 16
+86 49
+65 23
+54 46
+28 77
+74 17
+46 58
+71 54
+61 31
+33 63
+23 55
+66 38
+88 3
+5 89
+72 78
+70 46
+99 12
+93 47
+14 88
+69 82
+67 87
+95 31
+36 37
+4 26
+79 34
+78 77
+70 81
+20 18
+33 57
+59 81
+59 20
+90 7
+53 25
+11 38
+55 65
+85 34
+90 9
+98 16
+28 4
+95 54
+70 27
+51 85
+59 42
+44 89
+96 38
+0 37
+90 75
+11 70
+69 69
+87 91
+62 74
+66 87
+63 53
+62 77
+46 99
+68 10
+69 78
+23 76
+97 24
+15 16
+49 57
+41 13
+95 45
+80 98
+87 47
+60 6
+87 53
+80 24
+66 96
+94 9
+4 87
+28 12
+95 71
+66 25
+57 79
+27 8
+90 19
+98 21
+76 15
+55 92
+48 44
+48 23
+35 34
+75 9
+67 29
+7 7
+22 98
+2 47
+29 43
+99 10
+95 41
+59 5
+91 51
+74 56
+27 72
+46 41
+30 10
+10 47
+82 24
+83 92
+36 65
+78 75
+53 65
+58 43
+43 90
+50 22
+93 77
+4 77
+31 19
+98 40
+55 49
+52 14
+39 1
+90 33
+30 8
+2 80
+68 60
+4 76
+0 37
+40 98
+61 1
+39 28
+11 80
+89 61
+39 47
+31 4
+70 38
+52 19
+62 23
+62 60
+74 91
+6 50
+96 96
+76 19
+74 73
+47 15
+43 84
+32 40
+69 63
+17 40
+25 46
+19 91
+98 5
+68 38
+45 31
+92 16
+18 92
+97 68
+33 67
+41 7
+2 73
+93 10
+55 50
+65 60
+60 30
+73 66
+65 53
+6 78
+54 41
+27 76
+0 37
+46 66
+82 39
+14 46
+46 42
+29 43
+55 30
+96 12
+50 37
+94 82
+90 21
+89 54
+65 62
+28 76
+17 25
+81 47
+59 39
+81 83
+28 56
+6 90
+0 99
+9 98
+65 12
+60 73
+55 31
+61 55
+34 4
+3 12
+50 48
+16 41
+93 2
+81 93
+20 99
+56 27
+74 73
+22 64
+74 52
+36 97
+77 52
+85 60
+33 89
+23 94
+45 34
+74 77
+17 2
+29 93
+47 25
+97 69
+88 15
+45 58
+19 32
+68 86
+15 99
+62 79
+42 65
+39 67
+43 74
+20 41
+76 28
+88 42
+96 34
+71 95
+5 21
+29 78
+54 48
+85 70
+48 55
+90 18
+85 53
+15 68
+59 86
+74 97
+31 41
+22 29
+60 97
+1 66
+15 75
+57 5
+72 73
+51 6
+61 70
+12 55
+89 87
+9 33
+2 16
+98 3
+36 26
+32 30
+26 18
+20 42
+42 37
+29 99
+80 29
+23 40
+17 14
+12 44
+24 46
+75 95
+94 3
+61 72
+4 30
+22 8
+99 85
+70 15
+40 28
+10 75
+18 85
+91 37
+57 43
+9 32
+62 88
+27 83
+98 31
+10 51
+64 48
+99 94
+45 81
+21 38
+13 23
+60 73
+20 4
+88 36
+35 85
+48 94
+14 73
+87 70
+39 56
+46 71
+29 83
+22 86
+2 9
+70 75
+2 47
+3 29
+93 93
+60 98
+70 70
+46 52
+75 99
+98 75
+76 9
+91 66
+23 9
+47 41
+91 60
+24 26
+56 99
+46 28
+32 38
+33 54
+57 9
+47 82
+26 47
+62 16
+28 4
+57 47
+36 5
+22 11
+25 31
+11 23
+16 95
+81 21
+46 51
+80 12
+15 16
+22 77
+58 25
+75 43
+73 3
+37 35
+97 46
+83 0
+33 8
+27 11
+52 81
+95 44
+76 51
+58 10
+99 2
+62 19
+80 6
+30 53
+81 72
+10 16
+25 96
+46 8
+24 92
+86 56
+1 57
+90 2
+69 87
+24 77
+84 57
+87 48
+67 61
+94 38
+77 27
+21 66
+29 33
+78 88
+85 49
+66 31
+6 68
+73 73
+99 34
+8 24
+61 58
+63 97
+92 35
+16 99
+62 43
+25 73
+72 86
+41 69
+55 10
+97 64
+38 92
+57 53
+51 63
+83 98
+64 50
+24 63
+29 14
+61 41
+32 72
+86 35
+51 46
+37 4
+99 56
+67 6
+13 51
+25 49
+35 84
+23 70
+19 17
+83 37
+28 58
+21 46
+97 45
+71 82
+59 6
+47 13
+69 12
+47 87
+42 39
+8 4
+41 28
+46 20
+36 90
+93 53
+77 22
+37 0
+92 66
+87 1
+75 48
+58 73
+5 36
+26 14
+35 84
+2 65
+35 69
+30 18
+44 61
+41 23
+80 64
+54 84
+90 35
+81 11
+97 49
+63 35
+17 9
+79 94
+39 55
+87 21
+84 73
+14 3
+88 62
+77 90
+93 87
+24 29
+85 66
+95 40
+47 12
+85 52
+57 62
+55 98
+24 64
+84 81
+39 51
+15 7
+37 25
+10 62
+77 69
+28 14
+18 97
+94 97
+58 0
+8 43
+47 56
+93 59
+23 91
+9 41
+84 23
+84 6
+96 23
+84 71
+92 30
+7 41
+3 66
+1 25
+6 37
+60 77
+41 33
+1 64
+30 63
+46 45
+37 57
+44 20
+29 19
+82 13
+77 78
+21 10
+11 76
+56 2
+54 64
+6 14
+24 7
+93 38
+97 43
+71 64
+35 96
+38 34
+90 0
+3 29
+52 33
+27 71
+39 66
+19 23
+92 5
+48 25
+83 77
+71 68
+87 52
+61 59
+50 22
+87 11
+32 66
+65 12
+99 53
+91 15
+37 58
+87 85
+46 59
+9 24
+19 80
+16 48
+45 43
+49 35
+93 17
+26 4
+38 8
+56 87
+64 78
+43 90
+34 18
+57 29
+79 77
+35 49
+6 83
+14 61
+86 90
+71 42
+42 67
+78 38
+90 81
+63 44
+14 31
+15 41
+54 6
+38 92
+13 74
+81 56
+64 83
+22 17
+78 99
+2 47
+35 69
+71 75
+92 78
+61 25
+36 47
+40 55
+71 33
+87 58
+89 33
+69 48
+16 73
+81 50
+40 47
+50 87
+79 7
+59 77
+12 24
+68 27
+21 92
+38 46
+56 89
+86 76
+14 93
+32 47
+62 65
+22 43
+74 74
+20 40
+66 73
+83 32
+98 63
+58 11
+80 55
+17 72
+97 76
+23 11
+95 51
+52 75
+85 31
+78 13
+91 98
+62 71
+71 39
+3 72
+54 68
+54 62
+41 10
+30 98
+98 16
+49 3
+15 96
+70 18
+5 47
+2 71
+58 55
+76 80
+20 37
+88 48
+74 72
+1 20
+33 10
+72 60
+73 89
+81 47
+58 91
+32 99
+40 5
+0 52
+33 92
+8 65
+25 13
+7 42
+95 52
+50 60
+35 17
+98 32
+47 1
+88 79
+63 81
+49 16
+35 81
+65 35
+87 51
+97 59
+12 23
+9 81
+62 62
+8 8
+1 11
+99 17
+64 6
+91 61
+74 78
+75 10
+86 77
+64 45
+2 56
+66 31
+90 19
+76 85
+92 58
+62 52
+41 87
+12 5
+3 27
+69 10
+81 10
+8 38
+54 1
+21 9
+0 60
+48 26
+93 24
+81 77
+12 38
+51 84
+65 96
+18 64
+76 14
+3 2
+93 82
+87 39
+44 22
+62 62
+91 14
+64 77
+21 83
+57 40
+40 83
+1 1
+90 24
+21 26
+78 63
+7 60
+32 39
+65 89
+40 68
+78 89
+90 59
+86 14
+50 84
+92 42
+84 39
+90 95
+64 70
+0 9
+8 15
+36 19
+94 73
+18 75
+60 79
+77 34
+52 89
+9 29
+35 70
+68 43
+34 82
+67 93
+30 33
+28 17
+70 25
+35 22
+8 13
+0 0
+66 0
+35 78
+11 53
+35 35
+62 57
+69 94
+56 8
+52 49
+56 98
+32 69
+40 27
+53 56
+85 43
+99 38
+38 77
+73 58
+5 15
+15 47
+82 66
+42 81
+78 92
+40 64
+52 57
+11 29
+55 82
+17 79
+41 20
+40 50
+99 38
+30 29
+90 22
+68 5
+27 76
+76 84
+1 41
+87 1
+15 30
+79 90
+99 90
+22 74
+82 40
+63 4
+80 68
+57 71
+66 3
+12 28
+73 64
+74 69
+4 89
+8 19
+9 60
+12 80
+55 28
+13 96
+87 13
+38 55
+16 64
+91 80
+70 54
+74 86
+6 45
+6 74
+71 43
+15 65
+3 0
+52 72
+3 89
+31 9
+64 1
+70 74
+26 71
+57 14
+8 33
+70 4
+51 40
+94 6
+63 16
+90 20
+12 79
+34 15
+67 13
+95 51
+51 85
+70 65
+23 77
+81 30
+2 46
+34 85
+42 96
+80 72
+93 22
+18 5
+57 54
+48 43
+24 79
+29 63
+13 35
+7 81
+56 74
+33 87
+3 24
+72 48
+99 34
+97 25
+94 95
+99 56
+11 95
+58 45
+91 27
+</html>

File gchart/index.html

+<html>
+  <head>
+    <!--Load the AJAX API-->
+    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+    <script type="text/javascript" src="chart.js"></script>
+  </head>
+
+  <body>
+    <div id="chart_div"></div>
+  </body>
+</html>

File gmaps/OMakefile

+OCAMLINCLUDES = $(dir . ../lib)
+OCAML_LIBS= ../lib/xJs
+OCamlRequire(../lib/xJs.cmo)
+
+OCAMLPACKS[] = 
+    spotlib_js
+
+OCAMLDEPFLAGS= -syntax camlp4o -package lwt,js_of_ocaml.syntax
+OCAMLPPFLAGS= -syntax camlp4o -package lwt,js_of_ocaml.syntax
+
+FILES[] =
+    mymap
+
+MyOCamlJSProgram(mymap, $(FILES))

File gmaps/index.html

+<!DOCTYPE html>
+<html>
+  <head>
+    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+    <style type="text/css">
+      html { height: 100% }
+      body { height: 100%; margin: 0; padding: 0 }
+      #map_canvas { height: 100% }
+    </style>
+    <script type="text/javascript" src="mymap.js"></script>
+  </head>
+  <body>
+    <div id="map_canvas" style="width:100%; height:100%"></div>
+  </body>
+</html>

File gmaps/mymap.ml

+open Spotlib_js.Spot
+open XJs
+open XJs.Std
+
+let drawMap () = 
+  let maps = GMaps.get () in
+  (* The variable "google" must be referred in the function. 
+     Map API is loaded lazyily
+     and the variable google is not available before the loading is finished. *)
+
+  let latlng = GMaps.latlng maps in
+
+  let mapOptions = 
+    let open GMaps.MapOptions in
+    run &  center (latlng 1.306044 103.9047)
+        ++ zoom 15
+        ++ mapTypeId GMaps.MapTypeId.ROADMAP
+  in
+      
+  let div = match getElementById "map_canvas" with
+    | None -> assert false
+    | Some div -> div
+  in
+  let themap = GMaps.map maps div mapOptions in
+
+  let markerOptions = 
+    let open GMaps.MarkerOptions in
+    run &  position (latlng 1.306044 103.9047)
+        ++ map themap
+        ++ title (!$ "hello world")
+  in
+  let marker = GMaps.marker maps markerOptions in 
+  ignore marker
+
+let () = Unsafe.set_variable "initialize" drawMap
+
+let () = set_onload (fun () ->
+  GMaps.load 
+    ~callback:"initialize" 
+    ~sensor:false 
+    ~key:"AIzaSyCzkJ0D1W9_nZROV296_TMnpbGEZa4hGcE" ())
+
+  
 open Spotlib_js.Spot
 
 module OptionFields = struct
+  module type S = sig
+    type key 
+    type value
+    type t = (key * value) list
+    type options
+    val empty : options
+    val (++) : options -> options -> options
+    val make : key -> ('a -> value) -> 'a -> options
+    val run : options -> t
+  end
+
   module Make(A : sig
     type key
     type value
   end) = struct
-    open A
-    type kvs = (key * value) list
-    type options = kvs -> kvs
+    include A
+    type t = (key * value) list
+    type options = t -> t
     let empty = id
     let (++) = ( ** )
     let make k f v0 kvs = (k, f v0) :: kvs

File lib/base.mli

 val set_onload : (unit -> unit) -> unit
 
 module OptionFields : sig
-  module Make(A : sig
-    type key
+
+  module type S = sig
+    type key 
     type value
-  end) : sig
-    open A
-    type kvs = (key * value) list
+    type t = (key * value) list
     type options
     val empty : options
     val (++) : options -> options -> options
     val make : key -> ('a -> value) -> 'a -> options
-    val run : options -> kvs
+    val run : options -> t
   end
+
+  module Make(A : sig
+    type key
+    type value
+  end) : S with type key = A.key and type value = A.value
 end
 
 module StringOptionFields : sig
-  type kvs = (string * string) list
+  type t = (string * string) list
   type options
   val empty : options
   val (++) : options -> options -> options
   val make : string -> ('a -> string) -> 'a -> options
-  val run : options -> kvs
+  val run : options -> t
 end

File lib/gChart.ml

 include Visualization
 
 let load () = 
-  Google.load !$"visualization" !$"1.0" 
+  Google.load_api !$"visualization" !$"1.0" 
   & Unsafe.variable "{'packages':['corechart']}"
 
 (** [load ()] must be done before [get ()] *)
 let get () : t Js.t = Unsafe.variable "google.visualization"
-
-

File lib/gMaps.ml

 end 
 
 module MapOptions = struct
-  type t
   include OptionFields.Make(struct type key = string type value = Unsafe.any end)
   let center (v : LatLng.t Js.t)  = make "center" Unsafe.inject v
   let zoom   (v : int)            = make "zoom"   Unsafe.inject v
 end
 
 module MarkerOptions = struct
-  type t
   include OptionFields.Make(struct type key = string type value = Unsafe.any end)
   let position (v : LatLng.t Js.t)  = make "position" Unsafe.inject v
   let map      (v : Map.t Js.t)     = make "map"      Unsafe.inject v
   method _Marker : (MarkerOptions.t -> Marker.t Js.t) constr readonly_prop
 end
 
-let load ?sensor ?callback key = 
+let load ~sensor ~key ?callback () = 
   let q = 
     URL.make_query 
     & List.filter_map (fun (k,v) -> Option.map ~f:(fun v -> (k, v)) v)
       [ "key", Some key;
-        "sensor", Option.map ~f:(function true -> "true" | false -> "false") sensor;
+        "sensor", Some ((function true -> "true" | false -> "false") sensor);
         "callback", Option.map ~f:id callback]
   in
   Base.load_script (Printf.sprintf "http://maps.googleapis.com/maps/api/js?%s" q)

File lib/gMaps.mli

+open Js
+open Std
+
+module MapTypeId : sig
+  type t = HYBIRD | ROADMAP | SATELLITE | TERRAIN
+  val to_js : t -> Unsafe.any
+end
+
+module LatLng : sig 
+  class type t = object end 
+end
+
+module MapOptions : sig
+  include Base.OptionFields.S with type key = string and type value = Unsafe.any
+  val center : LatLng.t Js.t -> options
+  val zoom : int -> options
+  val mapTypeId : MapTypeId.t -> options
+end
+
+module Map : sig class type t = object  end end
+
+module MarkerOptions : sig
+  include Base.OptionFields.S with type key = string and type value = Unsafe.any
+  val position : LatLng.t Js.t -> options
+  val map : Map.t Js.t -> options
+  val title : string_t -> options
+end
+
+module Marker : sig class type t = object  end end
+
+class type t = object
+  method _LatLng : (float -> float -> LatLng.t Js.t) constr readonly_prop
+  method _Map : (Dom_html.element Js.t -> MapOptions.t -> Map.t Js.t) constr
+    readonly_prop
+  method _Marker : (MarkerOptions.t -> Marker.t Js.t) constr readonly_prop
+end
+
+val load : sensor:bool -> key: string -> ?callback:string -> unit -> unit
+val get : unit -> t Js.t
+val latlng : t Js.t -> float -> float -> LatLng.t Js.t
+val map : t Js.t -> Dom_html.element Js.t -> MapOptions.t -> Map.t Js.t
+val marker : t Js.t -> MarkerOptions.t -> Marker.t Js.t

File lib/google.ml

 let get_google : unit -> t Js.t = fun () -> Unsafe.variable "google"
 (** The variable "google" may not exist when API loading is delayed *)
 
-let load : string_t -> string_t -> 'option Js.t -> unit = 
+let load_api : string_t -> string_t -> 'option Js.t -> unit = 
   fun name version option -> (get_google()) ## load (name, version, option)
 
 let setOnLoadCallback f = (get_google()) ## setOnLoadCallback (f)

File lib/google.mli

 end
 
 val get_google : unit -> t Js.t
-val load : string_t -> string_t -> 'option Js.t -> unit
+(** Get the variable "google" *)
+
+val load_api : string_t -> string_t -> 'option Js.t -> unit
+(** Load a specific Google API.
+    The Loader API must be loaded beforehand by
+    <script type="text/javascript" src="https://www.google.com/jsapi"/>
+*)
+
 val setOnLoadCallback : (unit -> unit) -> unit
+(* Each API, such as Google Maps and Google Chart are provided
+   in each module like GMaps or GChart. *)
+