From 2590ada9cff1b95d66ed00727496642757e43ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Glondu?= Date: Sat, 22 Jul 2023 08:31:11 +0200 Subject: Import not-ocamlfind_0.10+dfsg-1.debian.tar.xz [dgit import tarball not-ocamlfind 0.10+dfsg-1 not-ocamlfind_0.10+dfsg-1.debian.tar.xz] --- changelog | 5 +++++ control | 32 ++++++++++++++++++++++++++++++++ copyright | 33 +++++++++++++++++++++++++++++++++ dirs.in | 2 ++ gbp.conf | 7 +++++++ rules | 17 +++++++++++++++++ source/format | 1 + upstream/metadata | 3 +++ watch | 5 +++++ 9 files changed, 105 insertions(+) create mode 100644 changelog create mode 100644 control create mode 100644 copyright create mode 100644 dirs.in create mode 100644 gbp.conf create mode 100755 rules create mode 100644 source/format create mode 100644 upstream/metadata create mode 100644 watch diff --git a/changelog b/changelog new file mode 100644 index 0000000..99b89f7 --- /dev/null +++ b/changelog @@ -0,0 +1,5 @@ +not-ocamlfind (0.10+dfsg-1) unstable; urgency=medium + + * Initial release (Closes: #1041684) + + -- Stéphane Glondu Sat, 22 Jul 2023 08:31:11 +0200 diff --git a/control b/control new file mode 100644 index 0000000..416e5b2 --- /dev/null +++ b/control @@ -0,0 +1,32 @@ +Source: not-ocamlfind +Section: ocaml +Priority: optional +Maintainer: Debian OCaml Maintainers +Uploaders: + Stéphane Glondu +Build-Depends: + debhelper-compat (= 13), + libcamlp-streams-ocaml-dev, + libfmt-ocaml-dev, + librresult-ocaml-dev, + libocamlgraph-ocaml-dev, + ocaml-findlib, + ocaml, + dh-ocaml +Standards-Version: 4.6.2 +Rules-Requires-Root: no +Vcs-Git: https://salsa.debian.org/ocaml-team/not-ocamlfind.git +Vcs-Browser: https://salsa.debian.org/ocaml-team/not-ocamlfind +Homepage: https://github.com/chetmurthy/not-ocamlfind + +Package: not-ocamlfind +Architecture: any +Depends: + ocaml-findlib, + ${ocaml:Depends}, + ${shlibs:Depends}, + ${misc:Depends} +Provides: ${ocaml:Provides} +Description: front-end to ocamlfind to add a few new commands + The command not-ocamlfind is a pass-thru to ocamlfind, but adds three + new commands: preprocess, reinstall-if-diff and package-graph. diff --git a/copyright b/copyright new file mode 100644 index 0000000..1d4fda8 --- /dev/null +++ b/copyright @@ -0,0 +1,33 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +Files: * +Copyright: © 1999-2014 Gerd Stolpmann +License: MIT + +Files: local-packages/ocamlfind/src/findlib/num_top* +Copyright: © 2003 Stefano Zacchiroli +License: MIT + +Files: debian/* +Copyright: © 2023 Stéphane Glondu +License: MIT + +License: MIT + Permission is hereby granted, free of charge, to any person obtaining + a copy of this document and the "findlib" software (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + . + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + . + The Software is provided ``as is'', without warranty of any kind, express + or implied, including but not limited to the warranties of + merchantability, fitness for a particular purpose and noninfringement. + In no event shall Gerd Stolpmann be liable for any claim, damages or + other liability, whether in an action of contract, tort or otherwise, + arising from, out of or in connection with the Software or the use or + other dealings in the software. diff --git a/dirs.in b/dirs.in new file mode 100644 index 0000000..702ecd0 --- /dev/null +++ b/dirs.in @@ -0,0 +1,2 @@ +usr/bin +@OCamlStdlibDir@ diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..2024d81 --- /dev/null +++ b/gbp.conf @@ -0,0 +1,7 @@ +[DEFAULT] +pristine-tar = True +filter-pristine-tar = True +filter = [ + "local-packages/ocamlfind/doc/ref-html", + "local-packages/ocamlfind/tools/make-package-macosx" + ] diff --git a/rules b/rules new file mode 100755 index 0000000..aadecbe --- /dev/null +++ b/rules @@ -0,0 +1,17 @@ +#!/usr/bin/make -f + +include /usr/share/ocaml/ocamlvars.mk + +DESTDIR := debian/not-ocamlfind + +OCAMLFIND_DESTDIR := $(DESTDIR)$(OCAML_STDLIB_DIR) +export OCAMLFIND_DESTDIR + +%: + dh $@ --with ocaml --no-parallel + +override_dh_auto_configure: + ./configure -bindir /usr/bin -sitelib $(OCAML_STDLIB_DIR) -mandir /usr/share/man -config /etc/ocamlfind.conf -no-custom -no-topfind + +override_dh_auto_install: + dh_auto_install -- OCAMLFIND_BINDIR=$(DESTDIR)/usr/bin diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/upstream/metadata b/upstream/metadata new file mode 100644 index 0000000..8c5c4f1 --- /dev/null +++ b/upstream/metadata @@ -0,0 +1,3 @@ +--- +Bug-Database: https://github.com/chetmurthy/not-ocamlfind/issues +Bug-Submit: https://github.com/chetmurthy/not-ocamlfind/issues/new diff --git a/watch b/watch new file mode 100644 index 0000000..5cfb1a5 --- /dev/null +++ b/watch @@ -0,0 +1,5 @@ +version=4 +opts="searchmode=plain,\ +filenamemangle=s%v?@ANY_VERSION@%@PACKAGE@-$1.tar.xz%" \ +https://api.github.com/repos/chetmurthy/not-ocamlfind/releases?per_page=50 \ +https://api.github.com/repos/[^/]+/[^/]+/tarball/v?@ANY_VERSION@ -- cgit v1.2.3 From ed6ad00516d54c493fc1956c24395d9f76022472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Glondu?= Date: Sat, 22 Jul 2023 08:31:11 +0200 Subject: Import not-ocamlfind_0.10+dfsg.orig.tar.gz [dgit import orig not-ocamlfind_0.10+dfsg.orig.tar.gz] --- .gitignore | 3 + CHANGES | 29 + LICENSE | 27 + META | 4 + Makefile | 33 + README.md | 75 + configure | 4 + frontend.ml | 1647 ++++++++++ fsmod.ORIG.ml | 16 + fsmod.ml | 81 + ...ug-when-installing-with-a-system-compiler.patch | 26 + local-packages/ocamlfind/INSTALL | 187 ++ local-packages/ocamlfind/LICENSE | 22 + local-packages/ocamlfind/Makefile | 152 + local-packages/ocamlfind/Makefile.config | 31 + local-packages/ocamlfind/Makefile.config.pattern | 67 + local-packages/ocamlfind/configure | 788 +++++ local-packages/ocamlfind/doc/DOCINFO | 15 + local-packages/ocamlfind/doc/Makefile | 73 + local-packages/ocamlfind/doc/QUICKSTART | 247 ++ local-packages/ocamlfind/doc/QUICKSTART.xml | 288 ++ local-packages/ocamlfind/doc/README | 470 +++ local-packages/ocamlfind/doc/README.xml | 685 ++++ local-packages/ocamlfind/doc/common.xml | 353 +++ local-packages/ocamlfind/doc/config.xml | 22 + local-packages/ocamlfind/doc/guide-html/TIMESTAMP | 0 local-packages/ocamlfind/doc/guide-html/c161.html | 232 ++ local-packages/ocamlfind/doc/guide-html/c192.html | 300 ++ local-packages/ocamlfind/doc/guide-html/c278.html | 308 ++ local-packages/ocamlfind/doc/guide-html/c37.html | 309 ++ local-packages/ocamlfind/doc/guide-html/c395.html | 204 ++ local-packages/ocamlfind/doc/guide-html/c429.html | 250 ++ local-packages/ocamlfind/doc/guide-html/c74.html | 211 ++ local-packages/ocamlfind/doc/guide-html/index.html | 430 +++ local-packages/ocamlfind/doc/guide-html/p35.html | 184 ++ .../ocamlfind/doc/guide-html/quickstart.html | 278 ++ local-packages/ocamlfind/doc/guide-html/x108.html | 178 ++ local-packages/ocamlfind/doc/guide-html/x119.html | 255 ++ local-packages/ocamlfind/doc/guide-html/x135.html | 213 ++ local-packages/ocamlfind/doc/guide-html/x149.html | 200 ++ local-packages/ocamlfind/doc/guide-html/x180.html | 184 ++ local-packages/ocamlfind/doc/guide-html/x231.html | 302 ++ local-packages/ocamlfind/doc/guide-html/x265.html | 182 ++ local-packages/ocamlfind/doc/guide-html/x274.html | 152 + local-packages/ocamlfind/doc/guide-html/x311.html | 210 ++ local-packages/ocamlfind/doc/guide-html/x326.html | 208 ++ local-packages/ocamlfind/doc/guide-html/x338.html | 199 ++ local-packages/ocamlfind/doc/guide-html/x345.html | 191 ++ local-packages/ocamlfind/doc/guide-html/x352.html | 295 ++ local-packages/ocamlfind/doc/guide-html/x388.html | 172 ++ local-packages/ocamlfind/doc/guide-html/x403.html | 248 ++ local-packages/ocamlfind/doc/guide-html/x421.html | 188 ++ local-packages/ocamlfind/doc/guide-html/x443.html | 170 + local-packages/ocamlfind/doc/guide-html/x449.html | 211 ++ local-packages/ocamlfind/doc/guide-html/x461.html | 384 +++ local-packages/ocamlfind/doc/guide-html/x513.html | 198 ++ local-packages/ocamlfind/doc/guide-html/x524.html | 162 + local-packages/ocamlfind/doc/guide-html/x528.html | 198 ++ local-packages/ocamlfind/doc/guide-html/x81.html | 170 + local-packages/ocamlfind/doc/guide-html/x89.html | 255 ++ local-packages/ocamlfind/doc/readme.dtd | 38 + local-packages/ocamlfind/doc/ref-man/META.5 | 613 ++++ local-packages/ocamlfind/doc/ref-man/TIMESTAMP | 0 .../ocamlfind/doc/ref-man/findlib.conf.5 | 787 +++++ local-packages/ocamlfind/doc/ref-man/ocamlfind.1 | 2853 +++++++++++++++++ local-packages/ocamlfind/doc/ref-man/site-lib.5 | 338 ++ local-packages/ocamlfind/doc/src/findlib.dsl | 24 + local-packages/ocamlfind/doc/src/findlib.sgml | 2476 +++++++++++++++ local-packages/ocamlfind/doc/src/findlib_conf.mod | 427 +++ local-packages/ocamlfind/doc/src/findlib_meta.mod | 420 +++ local-packages/ocamlfind/doc/src/findlib_mli.mod | 181 ++ .../ocamlfind/doc/src/findlib_ocamlfind.mod | 1436 +++++++++ local-packages/ocamlfind/doc/src/findlib_ref.dsl | 24 + local-packages/ocamlfind/doc/src/findlib_ref.sgml | 61 + .../ocamlfind/doc/src/findlib_reference.sgml | 17 + .../ocamlfind/doc/src/findlib_reference.xml | 2153 +++++++++++++ .../ocamlfind/doc/src/findlib_sitelib.mod | 165 + .../ocamlfind/doc/src/findlib_topfind.mod | 333 ++ local-packages/ocamlfind/findlib.conf.in | 2 + local-packages/ocamlfind/itest | 101 + local-packages/ocamlfind/itest-aux/Makefile | 7 + local-packages/ocamlfind/itest-aux/os_type.ml | 2 + local-packages/ocamlfind/itest-aux/ppx.ml | 1 + local-packages/ocamlfind/itest-aux/remdir.ml | 2 + local-packages/ocamlfind/itest-aux/simple.ml | 2 + .../ocamlfind/itest-aux/simple_bigarray.ml | 7 + .../ocamlfind/itest-aux/simple_camlp4.ml | 5 + .../ocamlfind/itest-aux/simple_camltk.ml | 11 + local-packages/ocamlfind/itest-aux/simple_dbm.ml | 10 + .../ocamlfind/itest-aux/simple_graphics.ml | 4 + .../ocamlfind/itest-aux/simple_labltk.ml | 10 + local-packages/ocamlfind/itest-aux/simple_num.ml | 4 + local-packages/ocamlfind/itest-aux/simple_str.ml | 4 + .../ocamlfind/itest-aux/simple_threads.ml | 17 + local-packages/ocamlfind/itest-aux/simple_unix.ml | 4 + local-packages/ocamlfind/mini/README | 104 + local-packages/ocamlfind/mini/ocamlfind-mini | 851 +++++ local-packages/ocamlfind/ocaml-stub | 4 + local-packages/ocamlfind/ocamlfind.install | 6 + local-packages/ocamlfind/ocargs.log | 4 + local-packages/ocamlfind/opam | 39 + .../ocamlfind/site-lib-src/bigarray/META.in | 11 + .../ocamlfind/site-lib-src/bigarray/interfaces.in | 1 + local-packages/ocamlfind/site-lib-src/bytes/META | 4 + .../ocamlfind/site-lib-src/bytes/META.in | 4 + .../ocamlfind/site-lib-src/bytes/interfaces.in | 2 + .../ocamlfind/site-lib-src/camlp4.309/META.in | 95 + .../ocamlfind/site-lib-src/camlp4.310/META.in | 147 + .../ocamlfind/site-lib-src/compiler-libs/META | 45 + .../ocamlfind/site-lib-src/compiler-libs/META.in | 45 + local-packages/ocamlfind/site-lib-src/dbm/META.in | 10 + .../ocamlfind/site-lib-src/dbm/interfaces.in | 1 + local-packages/ocamlfind/site-lib-src/dynlink/META | 8 + .../ocamlfind/site-lib-src/dynlink/META.in | 8 + .../ocamlfind/site-lib-src/dynlink/interfaces.in | 1 + .../ocamlfind/site-lib-src/graphics/META.in | 10 + .../ocamlfind/site-lib-src/graphics/interfaces.in | 2 + .../ocamlfind/site-lib-src/labltk/META.in | 10 + .../ocamlfind/site-lib-src/labltk/interfaces.in | 2 + .../ocamlfind/site-lib-src/num-top/META.in | 6 + local-packages/ocamlfind/site-lib-src/num/META.in | 14 + .../ocamlfind/site-lib-src/num/interfaces.in | 1 + .../ocamlfind/site-lib-src/ocamlbuild/META.in | 8 + .../ocamlfind/site-lib-src/ocamldoc/META | 5 + .../ocamlfind/site-lib-src/ocamldoc/META.in | 5 + .../ocamlfind/site-lib-src/raw_spacetime/META.in | 11 + .../site-lib-src/raw_spacetime/interfaces.in | 1 + .../ocamlfind/site-lib-src/runtime_events/META | 11 + .../ocamlfind/site-lib-src/runtime_events/META.in | 11 + .../site-lib-src/runtime_events/interfaces.in | 1 + local-packages/ocamlfind/site-lib-src/stdlib/META | 9 + .../ocamlfind/site-lib-src/stdlib/META.in | 9 + .../ocamlfind/site-lib-src/stdlib/interfaces.in | 1 + local-packages/ocamlfind/site-lib-src/str/META | 12 + local-packages/ocamlfind/site-lib-src/str/META.in | 12 + .../ocamlfind/site-lib-src/str/interfaces.in | 1 + local-packages/ocamlfind/site-lib-src/threads/META | 37 + .../ocamlfind/site-lib-src/threads/META.in | 37 + .../ocamlfind/site-lib-src/threads/interfaces.in | 2 + local-packages/ocamlfind/site-lib-src/unix/META | 13 + local-packages/ocamlfind/site-lib-src/unix/META.in | 13 + .../ocamlfind/site-lib-src/unix/interfaces.in | 1 + local-packages/ocamlfind/src/bytes/META | 9 + local-packages/ocamlfind/src/bytes/Makefile | 40 + local-packages/ocamlfind/src/bytes/README | 7 + local-packages/ocamlfind/src/bytes/bytes.ml | 36 + .../ocamlfind/src/findlib-toolbox/Makefile | 37 + .../ocamlfind/src/findlib-toolbox/make_wizard.ml | 1559 ++++++++++ .../src/findlib-toolbox/make_wizard.pattern | 494 +++ local-packages/ocamlfind/src/findlib/META | 36 + local-packages/ocamlfind/src/findlib/META.in | 36 + local-packages/ocamlfind/src/findlib/Makefile | 193 ++ local-packages/ocamlfind/src/findlib/depend | 112 + local-packages/ocamlfind/src/findlib/findlib.ml | 524 ++++ local-packages/ocamlfind/src/findlib/findlib.mli | 276 ++ .../ocamlfind/src/findlib/findlib_config.mlp | 25 + local-packages/ocamlfind/src/findlib/fl_args.ml | 104 + local-packages/ocamlfind/src/findlib/fl_dynload.ml | 55 + .../ocamlfind/src/findlib/fl_dynload.mli | 37 + local-packages/ocamlfind/src/findlib/fl_lint.ml | 113 + local-packages/ocamlfind/src/findlib/fl_meta.mll | 90 + .../ocamlfind/src/findlib/fl_metascanner.ml | 310 ++ .../ocamlfind/src/findlib/fl_metascanner.mli | 107 + .../ocamlfind/src/findlib/fl_metatoken.ml | 37 + .../ocamlfind/src/findlib/fl_ocaml_args.ml | 2623 ++++++++++++++++ .../ocamlfind/src/findlib/fl_package_base.ml | 723 +++++ .../ocamlfind/src/findlib/fl_package_base.mli | 181 ++ local-packages/ocamlfind/src/findlib/fl_split.ml | 146 + local-packages/ocamlfind/src/findlib/fl_topo.ml | 344 +++ local-packages/ocamlfind/src/findlib/fl_topo.mli | 42 + local-packages/ocamlfind/src/findlib/frontend.ml | 2683 ++++++++++++++++ local-packages/ocamlfind/src/findlib/num_top.ml | 32 + local-packages/ocamlfind/src/findlib/num_top.mli | 18 + .../ocamlfind/src/findlib/num_top_printers.ml | 17 + .../ocamlfind/src/findlib/num_top_printers.mli | 19 + local-packages/ocamlfind/src/findlib/ocaml_args.ml | 3264 ++++++++++++++++++++ .../ocamlfind/src/findlib/test_parser.ml | 87 + local-packages/ocamlfind/src/findlib/topfind.ml.in | 340 ++ local-packages/ocamlfind/src/findlib/topfind.mli | 122 + local-packages/ocamlfind/src/findlib/topfind_rd0.p | 40 + local-packages/ocamlfind/src/findlib/topfind_rd1.p | 55 + local-packages/ocamlfind/tools/cmd_from_same_dir | 30 + local-packages/ocamlfind/tools/collect_files | 16 + .../ocamlfind/tools/extract_args/Makefile | 10 + .../ocamlfind/tools/extract_args/extract_args.mll | 153 + local-packages/ocamlfind/tools/file_exists | 5 + local-packages/ocamlfind/tools/patch | 28 + local-packages/ocamlfind/tools/safe_camlp4 | 52 + main.ml | 14 + opam | 37 + papr_official.ml | 114 + 191 files changed, 42782 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGES create mode 100644 LICENSE create mode 100644 META create mode 100644 Makefile create mode 100644 README.md create mode 100755 configure create mode 100644 frontend.ml create mode 100644 fsmod.ORIG.ml create mode 100644 fsmod.ml create mode 100644 local-packages/ocamlfind/0001-Fix-bug-when-installing-with-a-system-compiler.patch create mode 100644 local-packages/ocamlfind/INSTALL create mode 100644 local-packages/ocamlfind/LICENSE create mode 100644 local-packages/ocamlfind/Makefile create mode 100644 local-packages/ocamlfind/Makefile.config create mode 100644 local-packages/ocamlfind/Makefile.config.pattern create mode 100755 local-packages/ocamlfind/configure create mode 100644 local-packages/ocamlfind/doc/DOCINFO create mode 100644 local-packages/ocamlfind/doc/Makefile create mode 100644 local-packages/ocamlfind/doc/QUICKSTART create mode 100644 local-packages/ocamlfind/doc/QUICKSTART.xml create mode 100644 local-packages/ocamlfind/doc/README create mode 100644 local-packages/ocamlfind/doc/README.xml create mode 100644 local-packages/ocamlfind/doc/common.xml create mode 100644 local-packages/ocamlfind/doc/config.xml create mode 100644 local-packages/ocamlfind/doc/guide-html/TIMESTAMP create mode 100644 local-packages/ocamlfind/doc/guide-html/c161.html create mode 100644 local-packages/ocamlfind/doc/guide-html/c192.html create mode 100644 local-packages/ocamlfind/doc/guide-html/c278.html create mode 100644 local-packages/ocamlfind/doc/guide-html/c37.html create mode 100644 local-packages/ocamlfind/doc/guide-html/c395.html create mode 100644 local-packages/ocamlfind/doc/guide-html/c429.html create mode 100644 local-packages/ocamlfind/doc/guide-html/c74.html create mode 100644 local-packages/ocamlfind/doc/guide-html/index.html create mode 100644 local-packages/ocamlfind/doc/guide-html/p35.html create mode 100644 local-packages/ocamlfind/doc/guide-html/quickstart.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x108.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x119.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x135.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x149.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x180.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x231.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x265.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x274.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x311.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x326.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x338.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x345.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x352.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x388.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x403.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x421.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x443.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x449.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x461.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x513.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x524.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x528.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x81.html create mode 100644 local-packages/ocamlfind/doc/guide-html/x89.html create mode 100644 local-packages/ocamlfind/doc/readme.dtd create mode 100644 local-packages/ocamlfind/doc/ref-man/META.5 create mode 100644 local-packages/ocamlfind/doc/ref-man/TIMESTAMP create mode 100644 local-packages/ocamlfind/doc/ref-man/findlib.conf.5 create mode 100644 local-packages/ocamlfind/doc/ref-man/ocamlfind.1 create mode 100644 local-packages/ocamlfind/doc/ref-man/site-lib.5 create mode 100644 local-packages/ocamlfind/doc/src/findlib.dsl create mode 100644 local-packages/ocamlfind/doc/src/findlib.sgml create mode 100644 local-packages/ocamlfind/doc/src/findlib_conf.mod create mode 100644 local-packages/ocamlfind/doc/src/findlib_meta.mod create mode 100644 local-packages/ocamlfind/doc/src/findlib_mli.mod create mode 100644 local-packages/ocamlfind/doc/src/findlib_ocamlfind.mod create mode 100644 local-packages/ocamlfind/doc/src/findlib_ref.dsl create mode 100644 local-packages/ocamlfind/doc/src/findlib_ref.sgml create mode 100644 local-packages/ocamlfind/doc/src/findlib_reference.sgml create mode 100644 local-packages/ocamlfind/doc/src/findlib_reference.xml create mode 100644 local-packages/ocamlfind/doc/src/findlib_sitelib.mod create mode 100644 local-packages/ocamlfind/doc/src/findlib_topfind.mod create mode 100644 local-packages/ocamlfind/findlib.conf.in create mode 100755 local-packages/ocamlfind/itest create mode 100644 local-packages/ocamlfind/itest-aux/Makefile create mode 100644 local-packages/ocamlfind/itest-aux/os_type.ml create mode 100644 local-packages/ocamlfind/itest-aux/ppx.ml create mode 100644 local-packages/ocamlfind/itest-aux/remdir.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_bigarray.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_camlp4.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_camltk.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_dbm.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_graphics.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_labltk.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_num.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_str.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_threads.ml create mode 100644 local-packages/ocamlfind/itest-aux/simple_unix.ml create mode 100644 local-packages/ocamlfind/mini/README create mode 100755 local-packages/ocamlfind/mini/ocamlfind-mini create mode 100755 local-packages/ocamlfind/ocaml-stub create mode 100644 local-packages/ocamlfind/ocamlfind.install create mode 100644 local-packages/ocamlfind/ocargs.log create mode 100644 local-packages/ocamlfind/opam create mode 100644 local-packages/ocamlfind/site-lib-src/bigarray/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/bigarray/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/bytes/META create mode 100644 local-packages/ocamlfind/site-lib-src/bytes/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/bytes/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/camlp4.309/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/camlp4.310/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/compiler-libs/META create mode 100644 local-packages/ocamlfind/site-lib-src/compiler-libs/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/dbm/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/dbm/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/dynlink/META create mode 100644 local-packages/ocamlfind/site-lib-src/dynlink/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/dynlink/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/graphics/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/graphics/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/labltk/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/labltk/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/num-top/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/num/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/num/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/ocamlbuild/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/ocamldoc/META create mode 100644 local-packages/ocamlfind/site-lib-src/ocamldoc/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/raw_spacetime/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/raw_spacetime/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/runtime_events/META create mode 100644 local-packages/ocamlfind/site-lib-src/runtime_events/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/runtime_events/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/stdlib/META create mode 100644 local-packages/ocamlfind/site-lib-src/stdlib/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/stdlib/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/str/META create mode 100644 local-packages/ocamlfind/site-lib-src/str/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/str/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/threads/META create mode 100644 local-packages/ocamlfind/site-lib-src/threads/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/threads/interfaces.in create mode 100644 local-packages/ocamlfind/site-lib-src/unix/META create mode 100644 local-packages/ocamlfind/site-lib-src/unix/META.in create mode 100644 local-packages/ocamlfind/site-lib-src/unix/interfaces.in create mode 100644 local-packages/ocamlfind/src/bytes/META create mode 100644 local-packages/ocamlfind/src/bytes/Makefile create mode 100644 local-packages/ocamlfind/src/bytes/README create mode 100644 local-packages/ocamlfind/src/bytes/bytes.ml create mode 100644 local-packages/ocamlfind/src/findlib-toolbox/Makefile create mode 100644 local-packages/ocamlfind/src/findlib-toolbox/make_wizard.ml create mode 100644 local-packages/ocamlfind/src/findlib-toolbox/make_wizard.pattern create mode 100644 local-packages/ocamlfind/src/findlib/META create mode 100644 local-packages/ocamlfind/src/findlib/META.in create mode 100644 local-packages/ocamlfind/src/findlib/Makefile create mode 100644 local-packages/ocamlfind/src/findlib/depend create mode 100644 local-packages/ocamlfind/src/findlib/findlib.ml create mode 100644 local-packages/ocamlfind/src/findlib/findlib.mli create mode 100644 local-packages/ocamlfind/src/findlib/findlib_config.mlp create mode 100644 local-packages/ocamlfind/src/findlib/fl_args.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_dynload.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_dynload.mli create mode 100644 local-packages/ocamlfind/src/findlib/fl_lint.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_meta.mll create mode 100644 local-packages/ocamlfind/src/findlib/fl_metascanner.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_metascanner.mli create mode 100644 local-packages/ocamlfind/src/findlib/fl_metatoken.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_ocaml_args.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_package_base.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_package_base.mli create mode 100644 local-packages/ocamlfind/src/findlib/fl_split.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_topo.ml create mode 100644 local-packages/ocamlfind/src/findlib/fl_topo.mli create mode 100644 local-packages/ocamlfind/src/findlib/frontend.ml create mode 100644 local-packages/ocamlfind/src/findlib/num_top.ml create mode 100644 local-packages/ocamlfind/src/findlib/num_top.mli create mode 100644 local-packages/ocamlfind/src/findlib/num_top_printers.ml create mode 100644 local-packages/ocamlfind/src/findlib/num_top_printers.mli create mode 100644 local-packages/ocamlfind/src/findlib/ocaml_args.ml create mode 100644 local-packages/ocamlfind/src/findlib/test_parser.ml create mode 100644 local-packages/ocamlfind/src/findlib/topfind.ml.in create mode 100644 local-packages/ocamlfind/src/findlib/topfind.mli create mode 100644 local-packages/ocamlfind/src/findlib/topfind_rd0.p create mode 100644 local-packages/ocamlfind/src/findlib/topfind_rd1.p create mode 100755 local-packages/ocamlfind/tools/cmd_from_same_dir create mode 100755 local-packages/ocamlfind/tools/collect_files create mode 100644 local-packages/ocamlfind/tools/extract_args/Makefile create mode 100644 local-packages/ocamlfind/tools/extract_args/extract_args.mll create mode 100755 local-packages/ocamlfind/tools/file_exists create mode 100755 local-packages/ocamlfind/tools/patch create mode 100755 local-packages/ocamlfind/tools/safe_camlp4 create mode 100644 main.ml create mode 100644 opam create mode 100644 papr_official.ml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34bc269 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.cm* +not-ocamlfind +*.exe diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..080860c --- /dev/null +++ b/CHANGES @@ -0,0 +1,29 @@ + +not-ocamlfind 0.10 +--------------------- + +* [30 Mar 2023] in "preprocess", ignore "-for-pack", "-linkall" arguments so we can just replace "ocamlc" with "preprocess" + +not-ocamlfind 0.08 +--------------------- + +* [04 Aug 2021] add better support for syntax predicates. + + formerly, a syntax predicate gets added to "syntax_preds". + + with this patch, "syntax_" prepended to that predicate also gets + added to "predicates". + +not-ocamlfind 0.07.02 +--------------------- + +* [26 Oct 2020] remove dependencies on sexp (too many deps) since they were for debug only + +not-ocamlfind 0.07.01 +--------------------- + +* [13 Oct 2020] added a changelog + + minor fix for ocamlgraph 2.0.0 compatibility. Since ocamlgraph + 1.8.8->2.0.0 is a breaking change, this version of not-ocamlfind + will only work with the newer version of ocamlgraph. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..61cecd9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +This package is a slight modification of sources originally authored +by Gerd Stolpmann, and hence governed by the license on his code. + +================================================================ + +Copyright 1999 by Gerd Stolpmann + +The package "findlib" is copyright by Gerd Stolpmann. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this document and the "findlib" software (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +The Software is provided ``as is'', without warranty of any kind, express +or implied, including but not limited to the warranties of +merchantability, fitness for a particular purpose and noninfringement. +In no event shall Gerd Stolpmann be liable for any claim, damages or +other liability, whether in an action of contract, tort or otherwise, +arising from, out of or in connection with the Software or the use or +other dealings in the software. diff --git a/META b/META new file mode 100644 index 0000000..dbe6aa7 --- /dev/null +++ b/META @@ -0,0 +1,4 @@ +# stub META file for "not-ocamlfind" frontend to "ocamlfind" +requires = "" +version = "0.10" +description = "add-on commands for ocamlfind" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bcc1a5b --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ + +DEBUG= +OCAMLFIND_BINDIR:=$(shell dirname `which ocamlfind`) +PACKAGES = str,unix,fmt,rresult,ocamlgraph,camlp-streams +INC= -I local-packages/ocamlfind/src/findlib findlib.cma + +all: not-ocamlfind papr_official.exe + +not-ocamlfind: fsmod.ml frontend.ml main.ml + (cd local-packages/ocamlfind/ && make) + ocamlfind ocamlc $(DEBUG) $(INC) -package $(PACKAGES) -linkall -linkpkg fsmod.ml frontend.ml main.ml -o not-ocamlfind + +fsmod.ml: fsmod.ORIG.ml + not-ocamlfind preprocess -package camlp5,pa_ppx.deriving_plugins.show,camlp5.pr_o \ + -syntax camlp5o $< > $@.NEW + mv $@.NEW $@ + +papr_official.exe: papr_official.ml + ocamlfind ocamlc $(DEBUG) $(INC) -package str,unix,compiler-libs.common \ + -linkall -linkpkg $< -o $@ + +install: not-ocamlfind + install not-ocamlfind $(OCAMLFIND_BINDIR)/not-ocamlfind + ocamlfind remove not-ocamlfind || true + ocamlfind install not-ocamlfind META papr_official.exe + +uninstall: + rm -f $(OCAMLFIND_BINDIR)/not-ocamlfind + ocamlfind remove not-ocamlfind || true + +clean: + rm -f *.cm* not-ocamlfind *.exe + (cd local-packages/ocamlfind && make clean) diff --git a/README.md b/README.md new file mode 100644 index 0000000..7df1248 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# not-ocamlfind + +Front-end to ocamlfind to add a few new commands + +# Features + +The command `not-ocamlfind` is a pass-thru to `ocamlfind`, but adds three new commands: `preprocess`, `reinstall-if-diff` and `package-graph`. + +### `reinstall-if-diff` + +1. `reinstall-if-diff` does what it says on the label: only reinstalls + (remove then install) if the file-content of the package has + changed. + +A regular `ocamlfind install` command like +``` +ocamlfind install pa_ppx_base -destdir $(DESTDIR)/lib META $(TARGET) pa_ppx_base.cmx pa_ppx_base.cmi +``` +installs a package `pa_ppx_base`, failing if the package is already installed. Rewrite that to +``` +ocamlfind reinstall-if-diff pa_ppx_base -destdir $(DESTDIR)/lib META $(TARGET) pa_ppx_base.cmx pa_ppx_base.cmi +``` +and it checks (a) that the package is already-installed, (b) that the files-to-be-installed are identical in names and checksums to the files already-installed, (c) if not does +``` +ocamlfind remove pa_ppx_base +ocamlfind install pa_ppx_base -destdir $(DESTDIR)/lib META $(TARGET) pa_ppx_base.cmx pa_ppx_base.cmi +``` +and (d) if they are identical in names and checksums, does *nothing*. + +In projects will multiple directories, if each directory locally installs a `findlib` package, then other directories can use those packages; they can also put those packages into their `make depend` dependencies, viz. +``` +EXTERNAL := $(shell $(OCAMLFIND) query -predicates byte $(PACKAGES)) +$(CMO) $(CMI) $(CMX): $(EXTERNAL) +``` + +hence causing rebuilds to occur when other directories have changed. + +### `preprocess` + +A compile command using PPX rewriters +``` +ocamlfind ocamlc -package ounit2,ppx_deriving.show -c test_deriving_show.ml +``` +can be coaxed to produce its preprocessed output by adding "-dsource". But this is messy and ugly, esp. when we might want to use that source for further compilation. It also isn't very helpful when dealing with a multi-stage PPX rewriter sequence. `preprocess` produces the source and does not attempt to compile it; as an added benefit, it prints (to stderr) the commands it executed to produce that source. So you can use this for debugging multi-stage PPX rewriter sequences: +``` +ocamlfind ocamlc -package ounit2,ppx_deriving.show test_deriving_show.ml +``` +Note well that all the options destined only for the compiler, linker, etc, are removed (and henced rejected) for `preprocess`. Only options required for preprocessing are accepted (`-package`, `-syntax`, `-predicates`, `-ppopt`, `-ppxopt`). + +This can work for camlp5 also, but that little bit of documentation is TBD. + +### `package-graph` + +This command outputs a graph in the format accepted by the ``dot`` +command of graphviz. By default you get the package-dependency graph, +with sizes of the archives for each packages as part of the +node-label. If you add ``-dominator-from ``, it will compute +the dominator-tree from that node. and if you add ``-xdot``, it will +automatically invoke ``xdot`` on the graph. Example: +``` +not-ocamlfind package-graph -xdot -package camlp5,ounit2,pa_ppx.here.link -dominator-from pa_ppx.here.link -xdot +``` + +# Installation + +To install `not-ocamlfind` you need a slightly-patched version of +ocamlfind (branch `export-more-cmis`). Until (and unless) this patch +gets integrated into the ocamlfind distribution, we build a local copy +with that patch. So you merely need to: + +``` +./configure +make +make install +``` diff --git a/configure b/configure new file mode 100755 index 0000000..ca940d7 --- /dev/null +++ b/configure @@ -0,0 +1,4 @@ +#!/bin/bash + +(cd local-packages/ocamlfind \ + && ./configure $* ) diff --git a/frontend.ml b/frontend.ml new file mode 100644 index 0000000..b0a6dbc --- /dev/null +++ b/frontend.ml @@ -0,0 +1,1647 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +open Findlib;; + +exception Usage;; +exception Silent_error;; + +type mode = + M_reinstall_if_diff | M_preprocess | M_package_graph | M_passthru +;; + + +type psubst = + Const of string + | Percent of string * modifier + | Lookup of string * modifier + +and modifier = + | Plain + | Plus +;; + +let except e = + let rec except_e = function + [] -> [] + | elem::l -> if e = elem then except_e l else elem::except_e l + in except_e +;; + +let sys_error code arg = + if arg = "" then + Sys_error (Unix.error_message code) + else + Sys_error (arg ^ ": " ^ Unix.error_message code) + + +let slashify s = + match Findlib_config.system with + | "mingw" | "mingw64" | "cygwin" -> + let b = Buffer.create 80 in + String.iter + (function + | '\\' -> Buffer.add_char b '/' + | c -> Buffer.add_char b c + ) + s; + Buffer.contents b + | _ -> + s + + +let out_path ?(prefix="") s = + match Findlib_config.system with + | "mingw" | "mingw64" | "cygwin" -> + let u = slashify s in + prefix ^ + (if String.contains u ' ' then + (* Desperate attempt to fix the space problem in paths. + Note that we invoke commands via Unix.open_process, and + this function already quotes the arguments on win32. + However, for -ccopt arguments, one quoting level seems + to be lost, and we have to add another level to compensate. + E.g. for the list of args + [ -ccopt; -L/my programs/include -L/somewhere ] + we get after out_path + [ -ccopt; "-I/my programs/include -L/somewhere" ] + which actually translates to + -ccopt "\"-I/my programs/include\" \"-L/somewhere\"" + on the command line, i.e. a double-quoted argument. + *) + "\"" ^ u ^ "\"" + else + u + ) + | _ -> + prefix ^ slashify s + + + +let percent_subst ?base spec lookup s = + (* spec = [ "%c", [ "ctext1"; "ctext2"; ... ]; + * "%d", [ "dtext1"; "dtext2"; ... ] ] + * All occurrences of %c in the string s are replaced as specified in spec. + * spec is an association list with the %-notation as keys + * and lists of strings as values. The result is a list of strings containing + * every combination of substituted values. + * + * Support for the %(name) syntax: In this case, the name is taken as + * key for the [lookup] function, which either returns the string value + * or raises Not_found. + * + * "+" modifier: A "+" after "%" causes that Findlib.resolve_path is + * called for the substitution string (e.g. %+c, %+(name)). + * + * Example: + * spec = [ "%a", [ "file1" ] ] + * lookup = function "archive" -> "file2" | _ -> raise Not_found + * Here, %a is substituted by file1, and %(archive) is substituted by + * file2. + * + * ?base: The base parameter for Findlib.resolve_path. + *) + let l = String.length s in + + let fail() = + failwith "bad format string" in + + let parenthesized_name j = + try + if j+1>=l then raise Not_found; + let k = String.index_from s (j+1) ')' in + let name = String.sub s (j+1) (k-j-1) in + (name, k+1) + with Not_found -> + fail() in + + let rec preprocess i j = + if j + if j+1 + prev :: Const "%" :: preprocess (j+2) (j+2) + | '(' -> + let name, j_next = parenthesized_name (j+1) in + prev :: Lookup(name,Plain) :: preprocess j_next j_next + | '+' -> + if j+2 fail() + | '(' -> + let name, j_next = parenthesized_name (j+2) in + prev :: Lookup(name,Plus) :: preprocess j_next j_next + | _ -> + let name = "%" ^ String.make 1 c in + prev :: Percent(name,Plus) :: preprocess (j+3) (j+3) + end + else fail() + | _ -> + let name = "%" ^ String.make 1 c in + prev :: Percent(name,Plain) :: preprocess (j+2) (j+2) + end + else fail() + | _ -> + preprocess i (j+1) + end + else + if i u + | Plus -> plus_subst u in + + let rec subst prefix l = + match l with + [] -> [prefix] + | Const s :: l' -> + subst (prefix ^ s) l' + | Percent(name,modi) :: l' -> + let replacements0 = + try List.assoc name spec + with Not_found -> failwith "bad format string" in + let replacements = + List.map (any_subst modi) replacements0 in + List.flatten + (List.map + (fun replacement -> + subst (prefix ^ replacement) l') + replacements) + | Lookup(name,modi) :: l' -> + let replacement0 = + try lookup name + with Not_found -> "" in + let replacement = + any_subst modi replacement0 in + subst (prefix ^ replacement) l' + in + + subst "" (preprocess 0 0) +;; + + +let rec remove_dups l = + match l with + x :: l' -> + if List.mem x l' then remove_dups l' else x::remove_dups l' + | [] -> [] +;; + +let current = ref 0 +let argv = ref [||] + +let arg n = + if n < Array.length !argv then (!argv).(n) else raise Not_found +;; + +let rec nth0 = function + (0,l) -> l + | (n, h::t) -> nth0 (n-1,t) + | _ -> assert false +;; + +let remaining_args () = nth0 (!current, Array.to_list !argv) ;; + +let escape_if_needed s = + if String.contains s ' ' then "\"" ^ String.escaped s ^ "\"" else s +;; + + +let use_package prefix pkgnames = + (* may raise No_such_package *) + let pdirs = + List.map + (fun pname -> + "-I " ^ out_path(package_directory pname) + ) + pkgnames + in + + print_endline (prefix ^ String.concat " " pdirs) +;; + +let file_contents filename = + let ic = open_in filename in + let inlen = in_channel_length ic in + let s = really_input_string ic inlen in + close_in ic ; + s +;; + +let parse_ldconf contents = + Str.(split (regexp "\n+") contents) +;; + +let read_ldconf filename = + let contents = file_contents filename in + let lines = parse_ldconf contents in + lines +;; + + +let format_ldconf lines new_lines = + let b = Buffer.create 23 in + List.iter + (fun line -> Buffer.add_string b (line ^ "\n")) + (lines @ new_lines) ; + Buffer.contents b +;; + +let is_dll p = + let sfx = Findlib_config.dll_suffix in + sfx <> "" && Filename.check_suffix p sfx +;; + + +let identify_dir d = + match Sys.os_type with + | "Win32" -> + failwith "identify_dir" (* not available *) + | _ -> + let s = Unix.stat d in + (s.Unix.st_dev, s.Unix.st_ino) +;; + + +let conflict_report incpath pkglist = + (* Check whether there are several definitions for packages + * in the current path. We remove duplicate directories first. + * Note that all other checks are not sensitive to duplicate directories. + *) + Fl_package_base.package_conflict_report ~identify_dir (); + + (* Second check whether there are module conflicts *) + let pkgpath = + List.map Findlib.package_directory pkglist in + Fl_package_base.module_conflict_report ~identify_dir (pkgpath @ incpath); + + (* Finally check whether there are multiple DLLs: *) + (* Note: Only the directories mentioned in ld.conf are checked, but not the + * directories in [incpath], and not the directories in CAML_LD_LIBRARY_PATH. + * The idea of this check is to ensure a proper installation, and not to + * complain about the user's special configuration. + *) + let ldconf = ocaml_ldconf() in + if ldconf <> "ignore" then begin + let dll_dirs = remove_dups (read_ldconf ldconf) in + let dll_pairs = + List.flatten + (List.map + (fun dll_dir -> + let files = + try Array.to_list (Sys.readdir dll_dir) + with _ -> + prerr_endline ("ocamlfind: [WARNING] Cannot read directory " ^ + dll_dir ^ " which is mentioned in ld.conf"); + [] + in + List.map + (fun file -> (file, dll_dir)) + (List.filter is_dll files) + ) + dll_dirs + ) in + let dll_hash = Hashtbl.create 50 in + List.iter + (fun (file, dll_dir) -> Hashtbl.add dll_hash file dll_dir) + dll_pairs; + Hashtbl.iter + (fun file dll_dir -> + let locations = Hashtbl.find_all dll_hash file in + if List.length locations > 1 then begin + prerr_endline ("ocamlfind: [WARNING] The DLL " ^ file ^ + " occurs in multiple directories: " ^ dll_dir) + end + ) + dll_hash + end +;; + + +let check_package_list l = + (* may raise No_such_package *) + List.iter + (fun pkg -> + let _ = package_directory pkg in + () + ) + l +;; + + +type verbosity = + | Normal + | Verbose + | Only_show + + +let run_command ?filter verbose cmd args = + let printable_cmd = + cmd ^ " " ^ String.concat " " (List.map escape_if_needed args) in + ( match verbose with + | Normal -> + () + | Verbose -> + print_endline ("+ " ^ printable_cmd); + if filter <> None then + print_string + (" (output of this command is filtered by ocamlfind)\n") + | Only_show -> + print_endline printable_cmd + ); + flush stdout; + + if verbose <> Only_show then ( + let filter_input, cmd_output = + match filter with + None -> Unix.stdin (* dummy *), Unix.stdout + | Some f -> Unix.pipe() + in + + (* Signals: On SIGINT, we wait until the subprocess finishes, and + * die then. This allows us to call interactive commands as subprocesses. + *) + + let old_sigint = + Sys.signal Sys.sigint Sys.Signal_ignore in + + let need_exe = + List.mem Findlib_config.system [ "win32"; "win64"; "mingw"; "mingw64" ] in + + let fixed_cmd = + if need_exe then ( + if Filename.check_suffix cmd ".exe" then cmd else cmd ^ ".exe" + ) + else + cmd in + + let pid = + Unix.create_process + fixed_cmd + (Array.of_list (cmd :: args)) + Unix.stdin + cmd_output + Unix.stderr + in + + begin match filter with + Some filter_fun -> + begin + Unix.close cmd_output; + let ch = Unix.in_channel_of_descr filter_input in + try + while true do + let line = input_line ch in + match filter_fun line with + None -> () (* Suppress line *) + | Some line' -> print_endline line' + done; + assert false + with + End_of_file -> + close_in ch; + flush stdout + end + | None -> () + end; + + let (_,status) = Unix.waitpid [] pid in + Sys.set_signal Sys.sigint old_sigint; + begin + match status with + Unix.WEXITED 0 -> () + | Unix.WEXITED n -> + if verbose = Verbose then + print_string (cmd ^ " returned with exit code " ^ string_of_int n ^ "\n"); + exit n + | Unix.WSIGNALED _ -> + print_string (cmd ^ " got signal and exited\n"); + exit 2 + | Unix.WSTOPPED _ -> + failwith "Your operating system does not work correctly" + end + ) +;; + + +(**************** preprocessor ******************************************) + +let select_pp_packages syntax_preds packages = + if syntax_preds = [] then + (* No syntax predicates, no preprocessor! *) + [] + else + List.filter + (fun pkg -> + let al = try package_property syntax_preds pkg "archive" + with Not_found -> "" in + let w = Fl_split.in_words al in + w <> [] + ) + packages + + +let process_pp_spec syntax_preds packages pp_opts = + (* Returns: pp_command *) + (* may raise No_such_package *) + + (* [packages]: all packages given on the command line. May include + * packages for compilation and for preprocessing. + * + * The difficulty is now that the preprocessor packages may have + * requirements that are non-preprocessor packages. To get exactly + * the preprocessor packages and its requirements, we do: + * + * 1. Determine the subset of [packages] that are preprocessor + * packages by checking whether they have an "archive" for + * [syntax_preds], i.e. the preprocessor packages mentioned + * on the command line = [cl_pp_packages]. + * + * 2. Add their requirements = [pp_packages] + * + * Because the packages are now mixed, we must evaluate for + * [syntax_preds] + "byte". + *) + + (* One packages must now have the variable "preprocessor", usually camlp4 *) + let cl_pp_packages = select_pp_packages syntax_preds packages in + let pp_packages = + package_deep_ancestors syntax_preds cl_pp_packages in + + let preprocessor_cmds = + List.flatten + (List.map (fun pname -> + try + [ pname, + package_property syntax_preds pname "preprocessor" + ] + with + Not_found -> [] + ) + pp_packages + ) + in + + let preprocessor_cmd = + if syntax_preds <> [] then + match preprocessor_cmds with + [] -> + failwith("Using -syntax, but no package is selected specifying \ + a preprocessor as required for -syntax") + | [_, cmd] -> Some cmd + | _ -> + failwith("Several packages are selected that specify \ + preprocessors: " ^ + String.concat ", " + (List.map + (fun (n,v) -> + "package " ^ n ^ " defines `" ^ v ^ "'") + preprocessor_cmds + ) + ) + else + None + in + + let pp_i_options = + List.flatten + (List.map + (fun pkg -> + let pkgdir = package_directory pkg in + [ "-I"; slashify pkgdir ] + ) + pp_packages) in + + let pp_archives = + if preprocessor_cmd = None then + [] + else + List.flatten + (List.map + (fun pkg -> + let al = + try package_property ("byte" :: syntax_preds) pkg "archive" + with Not_found -> "" in + Fl_split.in_words al + ) + pp_packages) in + + match preprocessor_cmd with + None -> [] + | Some cmd -> + let cmd = Str.(split (regexp "[ \t]+") cmd) in + cmd@ + pp_i_options@ + pp_archives@ + pp_opts +;; + +(**************** ppx extensions ****************************************) + +let process_ppx_spec predicates packages ppx_opts = + (* Returns: ppx_commands *) + (* may raise No_such_package *) + + let ppx_packages = + package_deep_ancestors predicates packages in + + let ppx_opts = + List.map + (fun opt -> + match Fl_split.in_words opt with + | pkg :: ((_ :: _) as opts) -> + let exists = + try ignore(package_directory pkg); true + with No_such_package _ -> false in + if not exists then + failwith ("The package named in -ppxopt does not exist: " ^ + pkg); + pkg, opts + | _ -> + failwith "-ppxopt must include package name, e.g. -ppxopt \"foo,-name bar\"" + ) + ppx_opts in + + let meta_ppx_opts = + List.concat + (List.map + (fun pname -> + try + let opts = package_property predicates pname "ppxopt" in + (* Split by whitespace to get (package,options) combinations. + Then, split by commas to get individual options. *) + List.map + (fun opts -> + match Fl_split.in_words opts with + | pkg :: ((_ :: _) as opts) -> + let exists = + try ignore(package_directory pkg); true + with No_such_package _ -> false in + if not exists then + failwith ("The package named in ppxopt variable does not exist: " ^ + pkg ^ " (from " ^ pname ^ ")"); + let base = package_directory pname in + pkg, List.map (resolve_path ~base ~explicit:true) opts + | _ -> + failwith ("ppxopt variable must include package name, e.g. " ^ + "ppxopt=\"foo,-name bar\" (from " ^ pname ^ ")") + ) + (Fl_split.in_words_ws opts) + with Not_found -> [] + ) + ppx_packages + ) in + + List.flatten + (List.map + (fun pname -> + let base = package_directory pname in + let options = + try + List.concat + (List.map (fun (_, opts) -> opts) + (List.filter (fun (pname', _) -> pname' = pname) + (meta_ppx_opts @ ppx_opts))) + with Not_found -> [] + in + try + let preprocessor = + resolve_path + ~base ~explicit:true + (package_property predicates pname "ppx") in + ["-ppx"; String.concat " " (preprocessor :: options)] + with Not_found -> [] + ) + ppx_packages) + +let parse_args + ?(current = current) ?(args = !argv) + ?(align = true) + spec anon usage = + try + Arg.parse_argv + ~current + args + (if align then Arg.align spec else spec) + anon + usage + with + | Arg.Help text -> + print_string text; + exit 0 + | Arg.Bad text -> + prerr_string text; + exit 2 + + + + +(**************** OCAMLC/OCAMLMKTOP/OCAMLOPT subcommands ****************) + +let ppx_invoke1 cmd ~root f = + let open Filename in + let outf = temp_file root "" in + (Printf.sprintf "%s %s %s" cmd f outf, outf) +;; + +let ppx_invoke cmds f = + let open Filename in + let base = basename f in + if not (check_suffix base ".mli" || check_suffix base ".ml") then + failwith "File must end with either .ml or .mli" ; + let (root, suff) = + if check_suffix base ".mli" then + (chop_suffix base ".mli", ".mli") + else (chop_suffix base ".ml", ".ml") in + + let extra_arg = if suff = ".mli" then "-intf" else "-impl" in + let outf0 = temp_file root "" in + let cmd0 = Printf.sprintf "ocamlfind not-ocamlfind/papr_official.exe -binary-output %s %s %s" extra_arg f outf0 in + let (outf, cmdsacc, tmpfiles) = + List.fold_left (fun (inf, cmdsacc, tmpfiles) cmd -> + let (cmd, outf) = ppx_invoke1 ~root cmd inf in + (outf, ((cmd,outf)::cmdsacc), outf::tmpfiles)) + (outf0, [(cmd0, outf0)], [outf0]) cmds in + let cmds = List.rev cmdsacc in + (suff, cmds, outf, tmpfiles) +;; + +let check_rc msg cmd = + Printf.fprintf stderr "%s: %s\n%!" msg cmd ; + match Unix.system cmd with + Unix.WEXITED 0 -> () + | Unix.WEXITED n -> + Printf.fprintf stderr "%s: process exited with status %d\n%!" msg n ; + failwith (Printf.sprintf "%s: failed" msg) + | _ -> failwith (Printf.sprintf "%s: failed with unexpected status" msg) +;; + +let ppx_execute (suff, cmds, outf, tmpfiles) = + cmds |> List.iter (fun (cmd, outf) -> + check_rc "ppx_execute" cmd ; + ) ; + let extra_arg = if suff = ".mli" then "-intf" else "-impl" in + check_rc "format output file" + (Printf.sprintf "ocamlfind not-ocamlfind/papr_official.exe -binary-input %s %s" extra_arg outf) +(* + check_rc "unlink tmpfiles" (Printf.sprintf "rm -f %s" (String.concat " " tmpfiles)) +*) +;; + +type pass_file_t = + Pass of string + | Impl of string (* Forces module implementation: -impl *) + | Intf of string (* Forces module interface: -intf *) + | Cclib of string (* Option for the C linker: -cclib *) +;; + + +let contracted_ocamlmklib_options = + [ "-l"; "-L"; "-R"; "-F"; "-Wl,-rpath,"; "-Wl,-R" ] + (* The ocamlmklib options where the argument is directly attached to the + switch (e.g. -L instead of -L ) + *) + +(************************************************************************) + +let preprocess () = + + (* let destdir = ref (default_location()) in *) + + let pass_files = ref [] in + + let packages = ref [] in + let predicates = ref [] in + + let syntax_preds = ref [] in + let pp_opts = ref [] in + let ppx_opts = ref [] in + let verbose = ref Normal in + + let add_pkg = + Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in + let ignore_for_pack = + Arg.String (fun s -> Fmt.(pf stderr "not-ocamlfind preprocess: ignore -for-pack %s\n%!" s)) in + let ignore_linkall = + Arg.Unit (fun _ -> Fmt.(pf stderr "not-ocamlfind preprocess: ignore -linkall\n%!")) in + let add_pred = + Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in + let add_syntax_pred = + Arg.String (fun s -> begin + syntax_preds := !syntax_preds @ (Fl_split.in_words s) ; + predicates := !predicates @ (List.map (Printf.sprintf "syntax_%s") (Fl_split.in_words s)) ; + end) in + let add_pp_opt = + Arg.String (fun s -> pp_opts := !pp_opts @ [s]) in + let ignore_error = ref false in + + let arg_spec = + [ + "-package", add_pkg, + " Refer to package when compiling"; + "-for-pack", ignore_for_pack, + " Ignored -for-pack option from ocamlc"; + "-linkall", ignore_linkall, + " Ignored -linkall option from ocamlc"; + "-predicates", add_pred, + "

Add predicate

when resolving package properties"; + "-syntax", add_syntax_pred, + "

Use preprocessor with predicate

"; + "-ppopt", add_pp_opt, + " Append option to preprocessor invocation"; + "-ppxopt", Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), + ", Append options to ppx invocation for package "; + "-ignore-error", Arg.Set ignore_error, + " Ignore the 'error' directive in META files"; + "-only-show", Arg.Unit (fun () -> verbose := Only_show), + " Only show the constructed command, but do not exec it\nSTANDARD OPTIONS:"; + "-verbose", Arg.Unit (fun () -> verbose := Verbose), + " Only show the constructed command, but do not exec it\nSTANDARD OPTIONS:"; + ] in + + let (current,args) = + (current, !argv) in + + parse_args + ~current + ~args + arg_spec + (fun s -> pass_files := !pass_files @ [ Pass s]) + ("usage: not-ocamlfind preprocess [options] file ..."); + + (* ---- Start requirements analysis ---- *) + + predicates := "byte" :: !predicates; + + if !syntax_preds <> [] then begin + predicates := "syntax" :: !predicates; + syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; + end; + + (* check packages: *) + check_package_list !packages; + + let eff_packages = + package_deep_ancestors !predicates !packages in + + (* ---- End of requirements analysis ---- *) + + (* Add the pkg_ predicates: *) + predicates := List.map (fun pkg -> "pkg_" ^ pkg) eff_packages @ !predicates; + + (* Check on [warning] directives: *) + List.iter + (fun pkg -> + try + let warning = package_property !predicates pkg "warning" in + prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ + "': " ^ warning) + with + Not_found -> () + ) + eff_packages; + + (* Check on [error] directives: *) + List.iter + (fun pkg -> + try + let error = package_property !predicates pkg "error" in + if !ignore_error then + prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ + "' signals error: " ^ error) + else + failwith ("Error from package `" ^ pkg ^ "': " ^ error) + with + Not_found -> () + ) + eff_packages; + + if !verbose = Verbose then begin + if !syntax_preds <> [] then + print_string ("Effective set of preprocessor predicates: " ^ + String.concat "," !syntax_preds ^ "\n"); + print_string ("Effective set of compiler predicates: " ^ + String.concat "," !predicates ^ "\n"); + end; + + (* initl_file_name: the initialization code inserted at the end of + * the cma/cmo list (initl = init last) + *) + + + let pp_command = + process_pp_spec !syntax_preds !packages !pp_opts + in + + let ppx_commands = + process_ppx_spec !predicates !packages !ppx_opts + in + + let pass_files' = + List.flatten + (List.map + (function + Pass s -> + if s <> "" && s.[0] = '-' + then [ "-"; String.sub s 1 (String.length s - 1) ] + else [ resolve_path s ] + | Impl s -> + [ "-impl"; resolve_path s ] + | Intf s -> + [ "-intf"; resolve_path s ] + | Cclib s -> + [ "-cclib"; s ] + ) + !pass_files) + in + + if pp_command <> [] && ppx_commands <> [] then + prerr_endline("not-ocamlfind: [ERROR] both pp and ppx commands present (cannot preprocess)") ; + + if pp_command <> [] then + let pp_command = pp_command@ pass_files' in + run_command !verbose (List.hd pp_command) (List.tl pp_command) + else begin + let ppx_commands = except "-ppx" ppx_commands in + List.iter (fun f -> + let (suff, cmds, outf, tmpfiles) = ppx_invoke ppx_commands f in + ppx_execute (suff, cmds, outf, tmpfiles) + ) pass_files' ; + + end +;; + +(************************************************************************) + +module PackageGraph = struct +open Graph + +module StringVertex = struct + type t = string + let compare = Stdlib.compare + let hash = Hashtbl.hash + let equal a b = (a = b) + type label = t + let create x = x + let label x = x +end + +module V = StringVertex +module G = Imperative.Digraph.ConcreteBidirectional(V) + +module DotIn = struct + type t = G.t + module V = G.V + module E = G.E + let iter_vertex = G.iter_vertex + let iter_edges_e = G.iter_edges_e + let graph_attributes _ = [] + let default_vertex_attributes _ = [] + let vertex_name v = v + let vertex_attributes _ = [] + let get_subgraph _ = None + + let default_edge_attributes _ = [] + let edge_attributes _ = [] +end +module GDot = Graph.Graphviz.Dot(DotIn) +module DomG = Dominator.Make_graph(struct + include G + let empty () = create () + let add_edge g v1 v2 = + G.add_edge g v1 v2 ; + g + end) + +let to_dot ~dominator_from oc edges = + let g = G.create () in + List.iter (fun (s, dl) -> + List.iter (fun d -> G.add_edge g s d) dl) edges ; + let g = match dominator_from with + Some v -> DomG.(compute_dom_graph g (compute_all g v).dom_tree) + | None -> g in + + GDot.output_graph oc g ; flush oc + +end + +let size_of_package predicates p = + match Findlib.package_directory p, Findlib.package_property predicates p "archive" with + (dir, archives) -> + let archives = Str.(split (regexp " +") archives) in + let archives = List.map (fun a -> Printf.sprintf "%s/%s" dir a) archives in + List.fold_left (fun acc f -> + acc + Unix.(stat f).st_size) 0 archives + | exception Not_found -> + 0 + +let package_graph () = + + let packages = ref [] in + let predicates = ref [] in + let verbose = ref Normal in + + let syntax_preds = ref [] in + + let add_pkg = + Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in + let add_pred = + Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in + let add_syntax_pred = + Arg.String (fun s -> begin + syntax_preds := !syntax_preds @ (Fl_split.in_words s) ; + predicates := !predicates @ (List.map (Printf.sprintf "syntax_%s") (Fl_split.in_words s)) ; + end) in + let ignore_error = ref false in + let dominator_from = ref "" in + let xdot = ref false in + + let arg_spec = + [ + "-package", add_pkg, + " Refer to package when compiling"; + "-predicates", add_pred, + "

Add predicate

when resolving package properties"; + "-syntax", add_syntax_pred, + "

Use preprocessor with predicate

"; + "-dominator-from", Set_string dominator_from, + "

compute dominator graph from this package

"; + "-ignore-error", Arg.Set ignore_error, + " Ignore the 'error' directive in META files"; + "-xdot", Arg.Set xdot, + " invoke ``xdot'' on .dot file"; + "-verbose", Arg.Unit (fun () -> verbose := Verbose), + " Only show the constructed command, but do not exec it\nSTANDARD OPTIONS:"; + ] in + + let (current,args) = + (current, !argv) in + + parse_args + ~current + ~args + arg_spec + (fun s -> failwith (Printf.sprintf "Should not provide any files to the package-graph subcommand (only packages): %s" s)) + ("usage: not-ocamlfind package-graph [options] -package "); + + (* ---- Start requirements analysis ---- *) + + if not (List.mem "native" !predicates) && not (List.mem "byte" !predicates) then + predicates := "byte" :: !predicates; + + if !syntax_preds <> [] then begin + predicates := "syntax" :: !predicates; + syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; + end; + + (* check packages: *) + check_package_list !packages; + + let eff_packages = + package_deep_ancestors !predicates !packages in + + (* ---- End of requirements analysis ---- *) + + (* Check on [warning] directives: *) + List.iter + (fun pkg -> + try + let warning = package_property !predicates pkg "warning" in + prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ + "': " ^ warning) + with + Not_found -> () + ) + eff_packages; + + (* Check on [error] directives: *) + List.iter + (fun pkg -> + try + let error = package_property !predicates pkg "error" in + if !ignore_error then + prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ + "' signals error: " ^ error) + else + failwith ("Error from package `" ^ pkg ^ "': " ^ error) + with + Not_found -> () + ) + eff_packages; + + if !verbose = Verbose then begin + if !syntax_preds <> [] then + print_string ("Effective set of preprocessor predicates: " ^ + String.concat "," !syntax_preds ^ "\n"); + print_string ("Effective set of compiler predicates: " ^ + String.concat "," !predicates ^ "\n"); + end; + + (* initl_file_name: the initialization code inserted at the end of + * the cma/cmo list (initl = init last) + *) + + let package_graph = List.map (fun p -> + (p, package_ancestors !predicates p)) eff_packages in + + let name2vertex = List.map (fun (p,_) -> + let size = size_of_package !predicates p in + let rhs = if size = 0 then + Fmt.(str "\"%s\"" p) + else Fmt.(str "\"%s: %a\"" p bi_byte_size size) in + (p, rhs)) package_graph in +(* + let name2vertex = List.map (fun (p, _) -> (p, Printf.sprintf "\"%s\"" p)) package_graph in +*) + let n2v n = match List.assoc n name2vertex with + v -> v | exception Not_found -> failwith (Printf.sprintf "package %s not in name2vertex map" n) in + + let g2 = List.map (fun (s,dl) -> (n2v s, List.map n2v dl)) package_graph in + let dominator_from = match !dominator_from with "" -> None | s -> Some (n2v s) in + + if !xdot then begin + let tmpfile = Filename.temp_file "graph" ".dot" in + let oc = open_out tmpfile in + PackageGraph.to_dot ~dominator_from:dominator_from oc g2 ; + close_out oc ; + ignore (Unix.system (Printf.sprintf "xdot %s" tmpfile)) ; + ignore (Unix.unlink tmpfile) + end + else + PackageGraph.to_dot ~dominator_from:dominator_from stdout g2 +;; + +(************************************************************************) + +let format_owner_file pkg file = + let outpath = file ^ ".owner" in + let contents = (pkg ^ "\n") in + (outpath, contents) +;; + +let trim_cr s = + let len = String.length s in + if len > 0 && String.get s (len-1) = '\r' then + String.sub s 0 (len-1) + else + s + +let find_owned_files pkg dir = + let files = Array.to_list(Sys.readdir dir) in + List.filter + (fun file -> + let owner_file = + if Filename.check_suffix file ".owner" then + file + else + file ^ ".owner" in + (List.mem owner_file files) && ( + try + let fd = + Unix.openfile (Filename.concat dir owner_file) [Unix.O_RDONLY] 0 in + let f = + Unix.in_channel_of_descr fd in + try + let line = trim_cr (input_line f) in + let is_my_file = (line = pkg) in + close_in f; + is_my_file + with + | End_of_file -> close_in f; false + | exc -> close_in f; raise exc + with + | Unix.Unix_error(Unix.ENOENT,_,_) -> + (* the owner file might have been removed by a package + removal that is being done in parallel + *) + false + | Unix.Unix_error(code, _, arg) -> + raise(sys_error code arg) + ) + ) + files +;; + + + +exception Missing_archives of Fl_metascanner.pkg_expr + +let rec patch_archives pkgdir pkg = + (* First remove all missing files from archive variables: *) + let defs' = + List.map + (fun def -> + if def.Fl_metascanner.def_var = "archive" then ( + let files = Fl_split.in_words def.Fl_metascanner.def_value in + let files' = + List.filter + (fun file -> + let p = Findlib.resolve_path ~base:pkgdir file in + Sys.file_exists p) + files in + { def with + Fl_metascanner.def_value = String.concat " " files' + } + ) + else def + ) + pkg.Fl_metascanner.pkg_defs in + (* Remove empty archive variables: *) + let defs'' = + List.filter + (fun def -> + def.Fl_metascanner.def_var <> "archive" || + Fl_split.in_words def.Fl_metascanner.def_value <> [] + ) + defs' in + (* Return the package or raise Not_found if all archives vanished: *) + let children = + (* Recursive patch, remove all Not_found packages: *) + List.flatten + (List.map + (fun (name, child) -> + try [ name, patch_archives pkgdir child ] + with Missing_archives _ -> [] + ) + pkg.Fl_metascanner.pkg_children) in + let pkg' = + { Fl_metascanner.pkg_defs = defs''; + pkg_children = children + } in + if List.exists (fun def -> def.Fl_metascanner.def_var = "archive") defs'' then + pkg' + else + raise (Missing_archives pkg') +;; + + +let rec patch_pkg pkgdir pkg patches = + match patches with + | [] -> pkg + | (`Version v) :: patches' -> + let def = + { Fl_metascanner.def_var = "version"; + def_flav = `BaseDef; + def_preds = []; + def_value = v + } in + let defs = + List.filter + (fun d -> d.Fl_metascanner.def_var <> "version") + pkg.Fl_metascanner.pkg_defs in + let pkg' = + { pkg with + Fl_metascanner.pkg_defs = def :: defs + } in + patch_pkg pkgdir pkg' patches' + | (`Rmpkg n) :: patches' -> + let children = + List.filter + (fun (name,_) -> name <> n) + pkg.Fl_metascanner.pkg_children in + let pkg' = + { pkg with + Fl_metascanner.pkg_children = children + } in + patch_pkg pkgdir pkg' patches' + | `Archives :: patches' -> + let pkg' = + try patch_archives pkgdir pkg + with + Missing_archives p -> p in + patch_pkg pkgdir pkg' patches' +;; + + +exception Skip_file;; + +type which = Auto | Dll | No_dll;; + +let meta_pkg meta_name = + let f = open_in meta_name in + try + let pkg = Fl_metascanner.parse f in + close_in f; + pkg + with + | Failure s + | Stream.Error s -> + close_in f; + failwith ("Cannot parse '" ^ meta_name ^ "': " ^ s) + +let char_lowercase_ascii c = + (* Char.lowercase_ascii and String.lowercase_ascii first available in + OCaml-4.03, but we want to support earlier versions too + *) + if (c >= 'A' && c <= 'Z') + then Char.unsafe_chr(Char.code c + 32) + else c + +let string_lowercase_ascii = + String.map char_lowercase_ascii + +open Fsmod + +let prepare_remove_package ~destdir ~metadir ~ldconf ~pkgname = + + let meta_dot_pkg = "META." ^ pkgname in + let has_metadir = metadir <> "" in + let pkgdir = Filename.concat destdir pkgname in + let dlldir = Filename.concat destdir Findlib_config.libexec_name in + let have_libexec = Sys.file_exists dlldir in + + (* First remove the META file. If it is already gone, assume that a + parallel running removal removed it already. + *) + + let mods = ref [] in + + let push_rm f = + if Sys.file_exists f then + let digest = Digest.(f |> file |> to_hex) in + mods := (f, FM_delete { name = f; checksum = digest }) :: !mods in + + let push_update f bytes = + if Sys.file_exists f then + let digest = Digest.(f |> file |> to_hex) in + mods := (f, FM_update ({ name = f; checksum = digest}, bytes)) :: !mods in + + if has_metadir then push_rm (Filename.concat metadir meta_dot_pkg) + else push_rm (Filename.concat pkgdir "META") ; + + (* Remove files from libexec directory: *) + if have_libexec then begin + let dll_files = find_owned_files pkgname dlldir in + List.iter + (fun file -> + let absfile = Filename.concat dlldir file in + push_rm absfile + ) + dll_files + end; + + (* Remove the files from the package directory: *) + if Sys.file_exists pkgdir then begin + let files = Sys.readdir pkgdir in + Array.iter (fun f -> + if f <> "META" then + push_rm (Filename.concat pkgdir f)) files; + end + else + prerr_endline("ocamlfind: [WARNING] No such directory: " ^ pkgdir); + + + (* Modify ld.conf *) + if ldconf <> "ignore" && Sys.file_exists ldconf then + begin + let lines = read_ldconf ldconf in + let d = Fl_split.norm_dir pkgdir in + let exists = List.exists (fun p -> Fl_split.norm_dir p = d) lines in + if exists then begin + let lines' = List.filter (fun p -> Fl_split.norm_dir p <> d) lines in + push_update ldconf (format_ldconf lines' []) + end + end; + + (* Check if there is a postremove script: *) + let postremove = Filename.concat destdir "postremove" in + if Sys.file_exists postremove then + failwith "cannot reinstall-if-diff a package with a postremove script" ; + + List.rev !mods +;; + +let prepare_reinstall_if_diff_package () = + let destdir = ref (default_location()) in + let metadir = ref (meta_directory()) in + let ldconf = ref (ocaml_ldconf()) in + let don't_add_directory_directive = ref false in + let pkgname = ref "" in + let auto_files = ref [] in + let dll_files = ref [] in + let nodll_files = ref [] in + let which = ref Auto in + let debug = ref false in + + let keywords = + [ "-destdir", (Arg.String (fun s -> destdir := s)), + (" Set the destination directory (default: " ^ + !destdir ^ ")"); + "-metadir", (Arg.String (fun s -> metadir := s)), + (" Install the META file into this directory (default: "^ + (if !metadir = "" then "none" else !metadir) ^ ")"); + "-ldconf", (Arg.String (fun s -> ldconf := s)), + (" Update this ld.conf file (default: " ^ !ldconf ^ ")"); + "-dont-add-directory-directive", (Arg.Set don't_add_directory_directive), + " never append directory='...' to META"; + "-dll", Arg.Unit (fun () -> which := Dll), + " The following files are DLLs"; + "-nodll", Arg.Unit (fun () -> which := No_dll), + " The following files are not DLLs"; + "-debug", Arg.Set debug, + " Enable massive debug-logging"; + ] in + let errmsg = "usage: ocamlfind reinstall-if-diff [options] ..." in + + let install_args = except "-debug" (List.tl (remaining_args ())) in + parse_args + keywords + (fun s -> + if !pkgname = "" + then pkgname := s + else + if Sys.file_exists s then + match !which with + Auto -> auto_files := s :: !auto_files + | Dll -> dll_files := s :: !dll_files + | No_dll -> nodll_files := s :: !nodll_files + else failwith Fmt.(str "reinstall-if-diff: file (to be installed) %s does not exist" s) + ) + errmsg; + if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); + if not (Fl_split.is_valid_package_name !pkgname) then + failwith "Package names must not contain the character '.'!"; + + if !debug then Fmt.(pf stderr "removal_mods: START\n%!"); + let removal_mods = prepare_remove_package ~destdir:!destdir ~metadir:!metadir ~ldconf:!ldconf ~pkgname:!pkgname in + if !debug then Fmt.(pf stderr "removal_mods:\n%a\n%!" + pp_t_pair_list removal_mods + ) ; + + (* if this file is listed in the removal-mods, then we pretend it doesn't exist; + otherwise we pass it along to Sys.file_exists *) + let file_exists f = + if List.mem_assoc f removal_mods then false + else Sys.file_exists f in + + let read_file f = + match List.assoc f removal_mods with + FM_update (_, contents) -> contents + | _ -> failwith "Internal error: can only read_file on a file that we're going to update" + | exception Not_found -> + failwith "Internal error: can only read_file on a file that we're going to update" in + + let install_mods = ref [] in + let push_install ~srcf ~dstf = + let digest = Digest.(srcf |> file |> to_hex) in + install_mods := (dstf, FM_install { name = srcf; checksum = digest }) :: !install_mods in + + let push_create ~dstf ~contents = + let digest = Digest.(contents |> string |> to_hex) in + install_mods := (dstf, FM_create ({ name = dstf; checksum = digest }, contents)) :: !install_mods in + + let push_update f b = + let digest = Digest.(f |> file |> to_hex) in + install_mods := (f, FM_update ({ name = f; checksum = digest}, b)) :: !install_mods in + + + let pkgdir = Filename.concat !destdir !pkgname in + let dlldir = Filename.concat !destdir Findlib_config.libexec_name in + let has_metadir = !metadir <> "" in + let meta_dot_pkg = "META." ^ !pkgname in + + (* The list of all files to install: *) + let full_list = !auto_files @ !dll_files @ !nodll_files in + (* Check whether there are DLLs: *) + let (l1,l2) = List.partition is_dll !auto_files in + let dll_list = l1 @ !dll_files in + let nodll_list = l2 @ !nodll_files in + let have_libexec = Sys.file_exists dlldir in + let pkgdir_list = if have_libexec then nodll_list else full_list in + let pkgdir_eff_list = + (* The files that will be placed into pkgdir: *) + List.map + (fun f -> + if f = meta_dot_pkg then "META" else f) + (List.filter + (fun f -> + not has_metadir || + (f <> "META" && f <> meta_dot_pkg)) + pkgdir_list) in + + (* Check whether META exists: (And check syntax) *) + let meta_name = + try + List.find + (fun p -> + let b = Filename.basename p in + b = "META" || b = meta_dot_pkg) + nodll_list + with + | Not_found -> + failwith "The META file is missing" in + + (* Check for frequent reasons why installation can go wrong *) + if file_exists (Filename.concat !metadir meta_dot_pkg) then + failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ Filename.concat !metadir meta_dot_pkg ^ " already exists)"); + + if file_exists (Filename.concat pkgdir "META") then + failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ pkgdir ^ "/META already exists)"); + + List.iter + (fun f -> + let f' = Filename.concat pkgdir f in + if file_exists f' then + failwith ("Conflict with file: " ^ f')) + pkgdir_eff_list; + + if have_libexec then begin + List.iter + (fun dll -> + let b = Filename.basename dll in + if file_exists (Filename.concat dlldir b) then + failwith ("Conflict with another package: Library " ^ b ^ + " is already installed"); + ) + dll_list + end; + + (* Now copy the files into the package directory (except META): *) + List.iter + (fun srcf -> + try + let dstf = Filename.concat pkgdir srcf in + if srcf = "META" || srcf = meta_dot_pkg then raise Skip_file ; + if srcf = "postremove" then failwith "cannot reinstall-if-diff a package with a postremove script" ; + if srcf = "postinstall" then failwith "cannot reinstall-if-diff a package with a postinstall script" ; + push_install ~srcf ~dstf + with + Skip_file -> () + ) + pkgdir_list; + + (* Copy the DLLs into the libexec directory if necessary *) + if have_libexec then begin + List.iter + (fun srcf -> + let dstf = Filename.concat pkgdir srcf in + push_install ~srcf ~dstf ; + let (owner_file, contents) = format_owner_file !pkgname + (Filename.concat dlldir (Filename.basename srcf)) in + push_create ~dstf:owner_file ~contents + ) + dll_list + end; + + (* Extend ld.conf if necessary: *) + if dll_list <> [] && !ldconf <> "ignore" && not have_libexec then begin + if Sys.file_exists !ldconf then + begin + let contents = read_file !ldconf in + let lines = parse_ldconf contents in + push_update !ldconf (format_ldconf lines [ pkgdir ]) + end + else + prerr_endline("ocamlfind: [WARNING] You have installed DLLs but there is no ld.conf") + end; + + if dll_list <> [] && have_libexec && !ldconf <> "ignore" then begin + (* Check whether libexec is mentioned in ldconf *) + (* FIXME: We have to be careful with case-insensitive filesystems. + Currently, we only check for Win32, but also OS X may have ci + filesystems. So some better check would be nice. + *) + let lines = read_ldconf !ldconf in + let dlldir_norm = Fl_split.norm_dir dlldir in + let dlldir_norm_lc = string_lowercase_ascii dlldir_norm in + let ci_filesys = (Sys.os_type = "Win32") in + let check_dir d = + let d' = Fl_split.norm_dir d in + (d' = dlldir_norm) || + (ci_filesys && string_lowercase_ascii d' = dlldir_norm_lc) in + if not (List.exists check_dir lines) then + prerr_endline("ocamlfind: [WARNING] You have installed DLLs but the directory " ^ dlldir_norm ^ " is not mentioned in ld.conf"); + end; + + (* Finally, write the META file: *) + let write_meta append_directory dir name = + let contents = file_contents meta_name in + let contents = if append_directory then + contents ^ "\ndirectory=\"" ^ pkgdir ^ "\" # auto-added by ocamlfind\n" + else contents in + push_create ~dstf:(Filename.concat dir name) ~contents + in + if has_metadir then + write_meta true !metadir meta_dot_pkg + else + write_meta false pkgdir "META"; + + let remove_args = ["-destdir"; !destdir; !pkgname] in + (!debug, List.rev !install_mods, install_args, removal_mods, remove_args) +;; + +let same_action (ifname, iact) (rfname, ract) = + if ifname <> rfname then ( + Fmt.(pf stderr "Files %s, %s at same position in sorted list of actions\n%!" + ifname rfname) ; + false + ) + else + match iact, ract with + FM_install {name=s2; checksum=sum2}, FM_delete { name=s1; checksum=sum1} + when sum1=sum2 -> true + | FM_create ({name=s2; checksum=sum2}, _), FM_delete { name=s1; checksum=sum1} + when s1=s2 && sum1=sum2 -> true + | _ -> + Fmt.(pf stderr "File %s has incompatible {install, remove} actions: (%a,%, %a)\n%!" + ifname pp iact pp ract) ; + false +;; + +let is_same (install_mods, removal_mods) = + let imap = List.sort Stdlib.compare install_mods in + let rmap = List.sort Stdlib.compare removal_mods in + let rec rerec = function + ((ifname, iact)::it, (rfname, ract)::rt) -> + if not (same_action (ifname, iact) (rfname, ract)) then false + else rerec (it, rt) + | ([], []) -> true + | _ -> + Fmt.(pf stderr "reinstall-if-diff: remove and install lists have differing lengths\n%!") ; + false + in + rerec (imap, rmap) +;; + +let reinstall_if_diff () = + let (debug, install_mods, install_args, removal_mods, remove_args) = prepare_reinstall_if_diff_package() in + if debug then Fmt.(pf stderr "reinstall_if_diff\ninstall_mods:\n%a\ninstall_args: [%a]\nremoval_mods:\n%a\nremove_args: [%a]\n%!" + pp_t_pair_list install_mods + (list ~sep:(const string " ") string) install_args + pp_t_pair_list removal_mods + (list ~sep:(const string " ") string) remove_args + ) ; + if not (is_same (install_mods, removal_mods)) then begin + run_command Verbose "ocamlfind" ("remove" :: remove_args) ; + run_command Verbose "ocamlfind" ("install" :: install_args) + end +;; + +let passthru () = + run_command Normal "ocamlfind" (List.tl (Array.to_list !argv)) +;; + + +let rec select_mode () = + let k = !current in + let m_string = try arg (k+1) with Not_found -> raise Usage in + let m = + match m_string with + ("reinstall-if-diff") -> incr current; M_reinstall_if_diff + | ("preprocess") -> incr current; M_preprocess + | ("package-graph") -> incr current; M_package_graph + | _ -> M_passthru + in + + m +;; + + +let _main av curr () = + argv := av ; current := curr ; + try + let m = select_mode() in + match m with + M_reinstall_if_diff -> reinstall_if_diff() + | M_preprocess -> preprocess () + | M_package_graph -> package_graph () + | M_passthru -> passthru() + with + Failure f -> + prerr_endline ("ocamlfind: " ^ f); + exit 2 + | Sys_error f -> + prerr_endline ("ocamlfind: " ^ f); + exit 2 + | Findlib.No_such_package(pkg,info) -> + prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' not found" ^ + (if info <> "" then " - " ^ info else "")); + exit 2 + | Findlib.Package_loop pkg -> + prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' requires itself"); + exit 2 + | Silent_error -> + exit 2 +;; + +let main ?(argv = Sys.argv) ?(current = !Arg.current) () = + _main argv current () ;; diff --git a/fsmod.ORIG.ml b/fsmod.ORIG.ml new file mode 100644 index 0000000..d2bf7ed --- /dev/null +++ b/fsmod.ORIG.ml @@ -0,0 +1,16 @@ + +module Pa_ppx_runtime = struct + module Runtime = struct + module Fmt = Fmt + end +end + +type file_t = { name : string ; checksum : string }[@@deriving show] +type t = + FM_delete of file_t + | FM_install of file_t + | FM_update of file_t * string + | FM_create of file_t * string[@@deriving show] + +type t_pair = string * t[@@deriving show] +type t_pair_list = t_pair list[@@deriving show] diff --git a/fsmod.ml b/fsmod.ml new file mode 100644 index 0000000..14b1343 --- /dev/null +++ b/fsmod.ml @@ -0,0 +1,81 @@ + +module Pa_ppx_runtime = + struct + module Runtime = struct module Fmt = Fmt end + end + +type file_t = { name : string; checksum : string }[@@deriving_inline show] + +let rec (pp_file_t : file_t Fmt.t) = + fun (ofmt : Format.formatter) arg -> + (fun ofmt ({name = v_name; checksum = v_checksum} : file_t) -> + let open Pa_ppx_runtime.Runtime.Fmt in + pf ofmt "@[<2>{ @[Fsmod.name =@ %a@];@ @[checksum =@ %a@] }@]" + (fun ofmt arg -> + let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) + v_name + (fun ofmt arg -> + let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) + v_checksum) + ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] +and (show_file_t : file_t -> Stdlib.String.t) = + fun arg -> Format.asprintf "%a" pp_file_t arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] + +[@@@end] +type t = + FM_delete of file_t + | FM_install of file_t + | FM_update of file_t * string + | FM_create of file_t * string[@@deriving_inline show] +let rec (pp : t Fmt.t) = + fun (ofmt : Format.formatter) arg -> + (fun ofmt -> + function + FM_delete v0 -> + let open Pa_ppx_runtime.Runtime.Fmt in + pf ofmt "(@[<2>Fsmod.FM_delete@ %a)@]" pp_file_t v0 + | FM_install v0 -> + let open Pa_ppx_runtime.Runtime.Fmt in + pf ofmt "(@[<2>Fsmod.FM_install@ %a)@]" pp_file_t v0 + | FM_update (v0, v1) -> + let open Pa_ppx_runtime.Runtime.Fmt in + pf ofmt "(@[<2>Fsmod.FM_update@ (@,%a,@ %a@,))@]" pp_file_t v0 + (fun ofmt arg -> + let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) + v1 + | FM_create (v0, v1) -> + let open Pa_ppx_runtime.Runtime.Fmt in + pf ofmt "(@[<2>Fsmod.FM_create@ (@,%a,@ %a@,))@]" pp_file_t v0 + (fun ofmt arg -> + let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) + v1) + ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] +and (show : t -> Stdlib.String.t) = + fun arg -> Format.asprintf "%a" pp arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] +[@@@end] + +type t_pair = string * t[@@deriving_inline show] + +let rec (pp_t_pair : t_pair Fmt.t) = + fun (ofmt : Format.formatter) arg -> + (fun (ofmt : Format.formatter) (v0, v1) -> + let open Pa_ppx_runtime.Runtime.Fmt in + pf ofmt "(@[%a,@ %a@])" + (fun ofmt arg -> + let open Pa_ppx_runtime.Runtime.Fmt in pf ofmt "%S" arg) + v0 pp v1) + ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] +and (show_t_pair : t_pair -> Stdlib.String.t) = + fun arg -> Format.asprintf "%a" pp_t_pair arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] + +[@@@end] +type t_pair_list = t_pair list[@@deriving_inline show] +let rec (pp_t_pair_list : t_pair_list Fmt.t) = + fun (ofmt : Format.formatter) arg -> + (fun (ofmt : Format.formatter) arg -> + let open Pa_ppx_runtime.Runtime.Fmt in + pf ofmt "@[<2>[%a@,]@]" (list ~sep:semi pp_t_pair) arg) + ofmt arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] +and (show_t_pair_list : t_pair_list -> Stdlib.String.t) = + fun arg -> Format.asprintf "%a" pp_t_pair_list arg[@@ocaml.warning "-39"] [@@ocaml.warning "-33"] +[@@@end] diff --git a/local-packages/ocamlfind/0001-Fix-bug-when-installing-with-a-system-compiler.patch b/local-packages/ocamlfind/0001-Fix-bug-when-installing-with-a-system-compiler.patch new file mode 100644 index 0000000..c050899 --- /dev/null +++ b/local-packages/ocamlfind/0001-Fix-bug-when-installing-with-a-system-compiler.patch @@ -0,0 +1,26 @@ +From f53247f546375972789b96c3f612cd7f524bf2aa Mon Sep 17 00:00:00 2001 +From: Louis Gesbert +Date: Mon, 11 Jul 2022 18:12:18 +0200 +Subject: [PATCH] Fix bug when installing with a system compiler + +See https://discuss.ocaml.org/t/problem-installing-ocamlfind-on-latest-ocamlpro-alpine-docker-image/10147 +--- + src/findlib/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/findlib/Makefile b/src/findlib/Makefile +index 84514b6f22..ea23f4a10c 100644 +--- a/src/findlib/Makefile ++++ b/src/findlib/Makefile +@@ -123,7 +123,7 @@ clean: + install: all + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)" + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" +- $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)" ++ test $(INSTALL_TOPFIND) -eq 0 || $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)" + test $(INSTALL_TOPFIND) -eq 0 || $(INSTALLFILE) topfind "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)/" + files=`$(SH) $(TOP)/tools/collect_files $(TOP)/Makefile.config \ + findlib.cmi findlib.mli findlib.cma findlib.cmxa findlib$(LIB_SUFFIX) findlib.cmxs \ +-- +2.35.1 + diff --git a/local-packages/ocamlfind/INSTALL b/local-packages/ocamlfind/INSTALL new file mode 100644 index 0000000..c3a83cc --- /dev/null +++ b/local-packages/ocamlfind/INSTALL @@ -0,0 +1,187 @@ +The installation procedure consists of the steps: + +1) configure the "findlib" library +2) compile "findlib" and the "ocamlfind" frontend of "findlib" +3) install "findlib" and the core library configuration + +Optionally, you can run ./itest after step 2 to check the +configuration. Problems with the configuration are unlikely, however. + +At the end of this file you find notes about MacOS and Windows. + + +---------------------------------------------------------------------- + +STEP 1: DEFAULT CONFIGURATION + +The findlib module and its ocamlfind frontend come with a "configure" +script that should almost always be able to figure out a good +configuration. + +Just type: + + ./configure + +First the linker options for the various core libraries are figured +out, then reasonable installation paths are checked. + +If the results are not ok, you can modify them using the following +options: + + -bindir + + set the location where the ocamlfind command should be + installed. + Default: same location as "ocamlc" + + -mandir + + set the location where the man page should be installed. + Default: a heuristics, and "/usr/local/man" as fallback. + + -sitelib + + set the default "site-lib" directory. + Default: For installations in the /usr hierarchy, + "$stdlib/site-lib", where $stdlib is the location of + Ocaml's standard library. + + For installations in the /opt hierarchy, + "$stdlib/../site-lib", i.e. parallel to $stdlib. + + -config + + set the location of the configuration file. + Default: /../etc/findlib.conf + + -no-topfind + + the "topfind" script is not installed in the standard + library directory. (This is not a good idea in general, + because #use "topfind" will not work when this option + is enabled.) + + -with-toolbox + also compile and install the "toolbox". This requires + that labltk is available. The toolbox contains the + "make_wizard" to easily create findlib-enabled Makefiles. + + -cygpath + Cygwin environment only: If "ocamlc -where" does not + output a Unix-style path, this option can be used + to apply the "cygpath" command to it. Use this option + if you see backslashes or drive letters in Makefile.config. + +ALTERNATIVES: + +If the "configure" script does not work properly (very unlikely), do + + cp Makefile.config.pattern Makefile.config + +and edit Makefile.config by hand. + +If the generated META files do not work, edit them (this is very very unlikely). + +Note: The META files are generated from the META.in files in the same +directories by sed: + + sed -e 's/%%os%%//g' site-lib//META.in + >site-lib//META + +You may invoke sed manually to create different META files, but this +is currently not documented. + + + +---------------------------------------------------------------------- + +STEP 2: COMPILATION + +After configuration has been done, compile with + + make all + +This creates findlib.cma, findlib_mt.cma (the thread-safe version), +and ocamlfind. + +If you have ocamlopt, do also + + make opt + +This creates findlib.cmxa, findlib_mt.cmxa, and ocamlfind_opt. + +---------------------------------------------------------------------- + +STEP 3: INSTALLATION + +Install the findlib library, the ocamlfind frontend, and the core library +configurations with: + + make install + +(A "make uninstall" removes them.) + +With + make clean + +the build directory is cleaned up. + + +OPTIONAL (BUT RECOMMENDED): + +If you want a separate directory for DLLs, create this directory +now: + +mkdir `ocamlfind printconf destdir`/stublibs + +If you do this, you must also tell OCaml that DLLs can be found in +this directory: Add the absolute path of this directory to +the ld.conf file (type "ocamlfind printconf ldconf" to get the +location of the ld.conf file). Every line of this text file lists +one possible directory for DLLs. + +---------------------------------------------------------------------- + +MACOS X: + +Findlib can be installed as described. There is even a script to +create a MacOS X package, use "make package-macosx" to invoke it. As I +do not have access to a Mac box, I cannot test this script, but I +fully trust the author that it works. + +---------------------------------------------------------------------- + +WINDOWS: + +Ocaml for Windows exists in three flavours: + +(1) Ocaml as Cygwin program +(2) Ocaml as Mingw program (i.e. the gcc toolchain is used but + Ocaml is a native Windows program) +(3) Ocaml as VC program + +In all three cases you need Cygwin to build and install findlib, +because "configure" and the Makefile are both Cygwin scripts. The +golden rule to make everything work is this: + +PASS CYGWIN-STYLE PATHS TO CONFIGURE! + +Even in cases (2) and (3)! That means use something like +/cygdrive/c/path and not c:\path when you specify where -bindir, +-config etc. are. The point is that "configure" itself is a Cygwin +script, and therefore expects Cygwin input. At the right moment, the +paths are back-translated to their Windows counterparts. + +Until OCaml 3.08 you must specify whether you have (2) or (3) by +the configure switches + +- "-system mingw" for (2) +- "-system win32" for (3) +- nothing for (1) + +Since OCaml 3.09 this is no longer necessary because "ocamlc -config" +outputs the required information. + +In previous versions of Findlib there was a single switch -cygpath +for both (2) and (3). It is now interpreted as -system mingw (as +it was meant as that). diff --git a/local-packages/ocamlfind/LICENSE b/local-packages/ocamlfind/LICENSE new file mode 100644 index 0000000..5d2bcbe --- /dev/null +++ b/local-packages/ocamlfind/LICENSE @@ -0,0 +1,22 @@ +Copyright 1999 by Gerd Stolpmann + +The package "findlib" is copyright by Gerd Stolpmann. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this document and the "findlib" software (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +The Software is provided ``as is'', without warranty of any kind, express +or implied, including but not limited to the warranties of +merchantability, fitness for a particular purpose and noninfringement. +In no event shall Gerd Stolpmann be liable for any claim, damages or +other liability, whether in an action of contract, tort or otherwise, +arising from, out of or in connection with the Software or the use or +other dealings in the software. diff --git a/local-packages/ocamlfind/Makefile b/local-packages/ocamlfind/Makefile new file mode 100644 index 0000000..f2f1df6 --- /dev/null +++ b/local-packages/ocamlfind/Makefile @@ -0,0 +1,152 @@ +# make all: compile to bytecode +# make opt: compile to native code +# make install: install bytecode and/or native code +#---------------------------------------------------------------------- + +include Makefile.config +-include Makefile.packages + +TOP=. + +.PHONY: all opt install uninstall clean + +all: + for p in $(PARTS); do ( cd src/$$p; $(MAKE) all ) || exit; done + $(MAKE) all-config + +opt: + for p in $(PARTS); do ( cd src/$$p; $(MAKE) opt ) || exit; done + +install: check-installation + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)" + $(MAKE) install-config + for p in $(PARTS); do ( cd src/$$p; $(MAKE) install ); done + $(MAKE) install-meta + test ! -f 'site-lib-src/num-top/META' || { cd src/findlib; $(MAKE) install-num-top; } + test ! -f 'site-lib-src/camlp4/META' || $(INSTALLFILE) tools/safe_camlp4 "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" + $(MAKE) install-doc + +uninstall: check-installation + $(MAKE) uninstall-doc + $(MAKE) uninstall-meta + for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) uninstall ); done + $(MAKE) uninstall-config + +clean: + for p in `cd src; echo *`; do ( cd src/$$p; $(MAKE) clean ); done + (cd itest-aux; $(MAKE) clean) + (cd tools/extract_args; $(MAKE) clean) + rm -f findlib.conf Makefile.packages + +.PHONY: release +release: README + ./release + +README: doc/README + ln -s doc/README . + + +.PHONY: all-config +all-config: findlib.conf + +findlib.conf: findlib.conf.in + USE_CYGPATH="$(USE_CYGPATH)"; \ + export USE_CYGPATH; \ + cat findlib.conf.in | \ + $(SH) tools/patch '@SITELIB@' '$(OCAML_SITELIB)' >findlib.conf + if ./tools/cmd_from_same_dir ocamlc; then \ + echo 'ocamlc="ocamlc.opt"' >>findlib.conf; \ + fi + if ./tools/cmd_from_same_dir ocamlopt; then \ + echo 'ocamlopt="ocamlopt.opt"' >>findlib.conf; \ + fi + if ./tools/cmd_from_same_dir ocamldep; then \ + echo 'ocamldep="ocamldep.opt"' >>findlib.conf; \ + fi + if ./tools/cmd_from_same_dir ocamldoc; then \ + echo 'ocamldoc="ocamldoc.opt"' >>findlib.conf; \ + fi + +.PHONY: install-doc +install-doc: + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1" "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3" "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5" + -$(INSTALLFILE) doc/ref-man/ocamlfind.1 "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1" + -$(INSTALLFILE) doc/ref-man/META.5 doc/ref-man/site-lib.5 doc/ref-man/findlib.conf.5 "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5" + +.PHONY: uninstall-doc +uninstall-doc: + rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man1/ocamlfind.1" + rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3/Findlib.3" + rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man3/Topfind.3" + rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5/META.5" + rm -f "$(DESTDIR)$(prefix)$(OCAMLFIND_MAN)/man5/site-lib.5" + + +.PHONY: check-installation +check-installation: + if [ "$(CHECK_BEFORE_INSTALL)" -eq 1 ]; then \ + for x in camlp4 dbm graphics labltk num ocamlbuild; do \ + if [ -f "$(prefix)$(OCAML_SITELIB)/$$x/META" ]; then \ + if ! grep -Fq '[distributed with Ocaml]' "$(prefix)/$(OCAML_SITELIB)/$$x/META"; then \ + rm -f site-lib-src/$$x/META; \ + fi; \ + fi; \ + done; \ + test -f "site-lib-src/num/META" || rm -f "site-lib-src/num-top/META"; \ + fi + echo 'SITELIB_META =' > Makefile.packages.in + for x in `ls site-lib-src`; do test ! -f "site-lib-src/$$x/META" || echo $$x >> Makefile.packages.in; done + tr '\n' ' ' < Makefile.packages.in > Makefile.packages + rm Makefile.packages.in + +.PHONY: install-meta +install-meta: + for x in $(SITELIB_META); do $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x"; $(INSTALLFILE) site-lib-src/$$x/META "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META.tmp" && mv "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META.tmp" "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x/META"; done + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib"; $(INSTALLFILE) Makefile.packages "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib/Makefile.packages" + +.PHONY: uninstall-meta +uninstall-meta: + for x in $(SITELIB_META); do rm -rf "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$$x"; done + +.PHONY: install-config +install-config: + $(INSTALLDIR) "`dirname \"$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)\"`" + @if [ -f "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" ]; then echo "!!! Keeping old $(DESTDIR)$(prefix)$(OCAMLFIND_CONF) !!!"; fi + test -f "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" || $(INSTALLFILE) findlib.conf "$(DESTDIR)$(prefix)$(OCAMLFIND_CONF)" + +.PHONY: uninstall-config +uninstall-config: + @echo Leaving "$(OCAMLFIND_CONF)" installed, consider manual removal + +.PHONY: interface-lists +interface-lists: + d=`ocamlc -where`; \ + for x in `ls site-lib-src`; do \ + iflist=""; \ + if [ ! -f "site-lib-src/$$x/interfaces.in" ]; then continue; fi; \ + cma_spec=`cat site-lib-src/$$x/interfaces.in`; \ + for cma in $$d/$$cma_spec; do \ + intf=`ocamlobjinfo $$cma | \ + grep 'Unit name:' | \ + sed -e 's/^ Unit name: //' | \ + sort | \ + tr '\n' ' '`; \ + iflist="$$iflist $$intf"; \ + done; \ + echo "$$iflist" >"site-lib-src/$$x/interfaces.out"; \ + done + +###################################################################### +# The following is from Pietro Abata +# to create MacOS X packages. I did not test it, just include it. + +.PHONY: package-macosx + +package-macosx: all opt + $(INSTALLDIR) package-macosx/root + export prefix=`pwd`/package-macosx/root && make install + export VERSION=1.1.2 && sh tools/make-package-macosx + +clean-macosx: + sudo rm -rf package-macosx diff --git a/local-packages/ocamlfind/Makefile.config b/local-packages/ocamlfind/Makefile.config new file mode 100644 index 0000000..ed6da21 --- /dev/null +++ b/local-packages/ocamlfind/Makefile.config @@ -0,0 +1,31 @@ +# Makefile.config written by configure +OCAML_CORE_STDLIB=/home/chet/Hack/Opam-2.1.2/GENERIC/5.0.0~rc1/lib/ocaml +OCAML_CORE_BIN=/home/chet/Hack/Opam-2.1.2/GENERIC/5.0.0~rc1/bin +OCAML_CORE_MAN=/home/chet/Hack/Opam-2.1.2/GENERIC/5.0.0~rc1/man +OCAML_SITELIB=/home/chet/Hack/Opam-2.1.2/GENERIC/5.0.0~rc1/lib/ocaml/site-lib +OCAML_THREADS=posix +OCAMLFIND_BIN=/home/chet/Hack/Opam-2.1.2/GENERIC/5.0.0~rc1/bin +OCAMLFIND_MAN=/home/chet/Hack/Opam-2.1.2/GENERIC/5.0.0~rc1/man +OCAMLFIND_CONF=/home/chet/Hack/Opam-2.1.2/GENERIC/5.0.0~rc1/lib/findlib.conf +OCAMLFIND_OCAMLFLAGS=-I +unix -I +dynlink +OCAMLFIND_ARCHIVES=findlib.cma unix.cma +OCAML_AUTOLINK=true +OCAML_REMOVE_DIRECTORY=1 +EXEC_SUFFIX= +LIB_SUFFIX=.a +CUSTOM=-custom +PARTS=findlib +INSTALL_TOPFIND=1 +USE_CYGPATH=0 +HAVE_NATDYNLINK=1 +VERSION=1.9.5 +ENABLE_TOPFIND_PPXOPT=true +SYSTEM=linux +NUMTOP= +SH= +OPAQUE=-opaque +CHECK_BEFORE_INSTALL=0 +INSTALLDIR = install -d +# change to INSTALLDIR = mkdir -p when BSD install is unavavailable +INSTALLFILE = install -c +# change to INSTALLFILE = cp when BSD install is unavailable diff --git a/local-packages/ocamlfind/Makefile.config.pattern b/local-packages/ocamlfind/Makefile.config.pattern new file mode 100644 index 0000000..bf894e9 --- /dev/null +++ b/local-packages/ocamlfind/Makefile.config.pattern @@ -0,0 +1,67 @@ +# You can manually set up your configuration using this +# pattern. The final name of the file must be "Makefile.config". +# Note that there are other files containing parts of the +# configuration, especially the site-lib/*/META files. +# +#---------------------------------------------------------------------- +# Where the OCAML core is installed: +#---------------------------------------------------------------------- +OCAML_CORE_STDLIB=/usr/local/lib/ocaml +OCAML_CORE_BIN=/usr/local/bin +OCAML_CORE_MAN=/usr/local/man + +#---------------------------------------------------------------------- +# Type of multi-threading support: either vm or posix +# (Note: Since OCaml 3.07, "posix" includes "vm", because a build +# supporting posix also supports vm.) +#---------------------------------------------------------------------- +OCAML_THREADS=vm +#OCAML_THREADS=posix + +#---------------------------------------------------------------------- +# Where the site-lib directory will be +#---------------------------------------------------------------------- +OCAML_SITELIB=/usr/local/lib/ocaml/site-lib + +#---------------------------------------------------------------------- +# Where binaries and manual pages will be installed +#---------------------------------------------------------------------- +OCAMLFIND_BIN=/usr/local/bin +OCAMLFIND_MAN=/usr/local/man + +#---------------------------------------------------------------------- +# The absolute location of the configuration file +#---------------------------------------------------------------------- +OCAMLFIND_CONF=/usr/local/etc/ocamlfind.conf + +#---------------------------------------------------------------------- +# Autolinking is usually on +#---------------------------------------------------------------------- +OCAML_AUTOLINK=true + +#---------------------------------------------------------------------- +# Windows only: set this to .exe +#---------------------------------------------------------------------- +EXEC_SUFFIX= + +#---------------------------------------------------------------------- +# Windows MSVC port: set this to .lib +#---------------------------------------------------------------------- +LIB_SUFFIX=.a + +#---------------------------------------------------------------------- +# Which parts are to be built: findlib, findlib-toolbox (space-separated +# list) +#---------------------------------------------------------------------- +PARTS=findlib findlib-toolbox + +#---------------------------------------------------------------------- +# Whether the "topfind" script is installed in $(OCAML_CORE_STDLIB): +#---------------------------------------------------------------------- +INSTALL_TOPFIND=1 + +#---------------------------------------------------------------------- +# Whether make install should update Makefile.packages just before +# running +#---------------------------------------------------------------------- +CHECK_BEFORE_INSTALL=0 diff --git a/local-packages/ocamlfind/configure b/local-packages/ocamlfind/configure new file mode 100755 index 0000000..71ec745 --- /dev/null +++ b/local-packages/ocamlfind/configure @@ -0,0 +1,788 @@ +#! /bin/sh +# $Id$ +# ---------------------------------------------------------------------- +# + +# Some functions + +#set -x + +version="$(sed -ne 's/^version: *"\(.*\)\.git".*/\1/p' opam)" + +if test -z "$version"; then + echo "Internal error: failed to parse version number from opam file" 1>&2 + exit 1 +fi + +# Remember the old IFS value: +oldifs="$IFS" + + +in_path () { + # Does $1 exist in $PATH? + IFS=":" + for d in $PATH; do + if test -x "$d/$1"; then + IFS="$oldifs" + return 0 + fi + done + IFS="$oldifs" + return 1 +#--- The following is not portable enough: +# if test -x `type -p ls`; then +# # type -p works! +# type -p $1 >/dev/null +# else +# # use 'which' instead +# p=`which $1` +# test -x "$p" +# fi +} + + +get_path () { + IFS=":" + for d in $PATH; do + if test -x "$d/$1"; then + IFS="$oldifs" + echo "$d/$1" + return + fi + done + IFS="$oldifs" +#--- The following is not portable enough: +# if test -x `type -p ls`; then +# # type -p works! +# type -p $1 +# else +# # use 'which' instead +# p=`which $1` +# test -x "$p" && echo $p +# fi +} + + +get_stdlib () { + # Older versions of ocamlc do not accept -where, so there is a fallback + # method: + ocamlc -where 2>/dev/null | tr -d '\015' || { + ocamlc -v | sed -n -e "/Standard library directory/s/.*: \(.*\)/\1/p"; } +} + + +get_lib () { + # $1: name of a library to search for + # $2...: places to test + libname="$1" + while [ "$#" != "0" ]; do + if [ -f "$1/lib${libname}.so" ] || [ -f "$1/lib${libname}.a" ]; then + echo "$1" + return 0 + fi + shift + done + return 1 +} + + +get_lib_file () { + # $1: name of library without "lib" and suffix + # $2: directory + # returns full path of library + if [ -f "$2/lib$1.so" ]; then + echo "$2/lib$1.so" + elif [ -f "$2/lib$1.a" ]; then + echo "$2/lib$1.a" + else + echo "" + fi +} + + +cygpath_to_unix () { + v=$1 + eval "p=\"\$$v\"" + p="`cygpath -w -s \"$p\"`" + p="`cygpath -u \"$p\"`" + eval "$v=\"$p\"" +} + + +###################################################################### +# Here the main program begins: + +###################################################################### +# Interpret the command line + +ocamlfind_bin="" +ocamlfind_man="" +ocaml_sitelib="" +ocamlfind_config="" +with_toolbox=0 +with_topfind=1 +with_camlp4=1 +custom=-custom +system="" +sh="" + +while [ "$#" != "0" ]; do + case "$1" in + -bindir) ocamlfind_bin=$2 + shift 2 + ;; + -mandir) ocamlfind_man=$2 + shift 2 + ;; + -sitelib) ocaml_sitelib=$2 + shift 2 + ;; + -config) ocamlfind_config=$2 + shift 2 + ;; + -no-custom) custom= + shift + ;; + -cygpath) system=mingw + shift + ;; + -system) system=$2 + shift 2 + ;; + -with-toolbox) with_toolbox=1 + shift + ;; + -no-topfind) with_topfind=0 + shift + ;; + -no-camlp4) with_camlp4=0 + shift + ;; + -version) + echo "$version" + exit 0 + ;; + -h|-help|--help) echo "usage: configure [options]" 1>&2 + echo " -bindir path where binaries are installed" 1>&2 + echo " -mandir path where manual pages are installed" 1>&2 + echo " -sitelib path set the location of the site-specific packages" 1>&2 + echo " -config path set the location of the configuration file" 1>&2 + echo " -no-custom don't link in custom runtime mode" 1>&2 + echo " -system override system type (esp. mingw and win32)" 1>&2 + echo " -with-toolbox also build the toolbox" 1>&2 + echo " -no-topfind don't install topfind script into stdlib directory" 1>&2 + echo " -no-camlp4 don't install the camlp4 META file" 1>&2 + exit + ;; + *) echo "configure: run 'configure -h' to get help" 1>&2 + exit 1 + ;; + esac +done + +echo "Welcome to findlib version $version" +echo "Configuring core..." + + +####################################################################### +# inspect the system + +# Some standard Unix tools must be available: + +for tool in sed ocaml ocamlc uname rm make cat dirname basename; do + if in_path $tool; then true; else + echo "configure: $tool not in PATH; this is required" 1>&2 + exit 1 + fi +done + +lib_suffix=`ocamlc -config 2>/dev/null|tr -d '\015'|sed -n -e 's/^ext_lib: //p'` + +# Check for Cygwin: + +exec_suffix= +pure_mingw="no" +mingw_lib= +case `uname` in + CYGWIN*) + exec_suffix=.exe + echo "Cygwin build environment found; using .exe as suffix for binaries" + ;; + MSYS_NT*) + exec_suffix=.exe + echo "MSYS_NT build environment found; using .exe as suffix for binaries" + ;; + MINGW*) + exec_suffix=.exe + pure_mingw="yes" + echo "MinGW build environment found; using .exe as suffix for binaries" + mingw_lib=`get_path gcc` + mingw_lib=`dirname "$mingw_lib"`/../lib + ;; + *) + true ;; +esac + +###################################################################### +# Is the target Win32? + +use_cygpath=0 +# Whether we have to translate Unix paths to/from Windows paths. + +if [ -z "$system" ]; then + system=`ocamlc -config 2>/dev/null|tr -d '\015'|sed -n -e 's/^system: //p'` + # This may be + # - mingw or mingw64 + # - win32 + # - win64 + # - cygwin + # - some other string means Unix + # - empty means ocamlc does not support -config +fi + +case "$system" in + mingw|mingw64) + if [ "$pure_mingw" = "no" ]; then + # CYGWIN + use_cygpath=1 + fi + ;; + win32) use_cygpath=1;; + win64) use_cygpath=1;; +esac + +###################################################################### +# check for presence of /bin/sh + +if [ ! -f /bin/sh ]; then + sh=sh +fi + +###################################################################### +# Find out standard library location + +ocaml_core_stdlib=`get_stdlib` +if [ ! -d "$ocaml_core_stdlib" ]; then + echo "configure: cannot determine ocaml's standard library directory" 1>&2 + exit 1 +fi + +if [ ${use_cygpath} -gt 0 ]; then + cygpath_to_unix ocaml_core_stdlib + # This makes ocaml_core_stdlib a Unix-type path +fi + +# Set site-lib directory: + +if [ -z "$ocaml_sitelib" ]; then + case "$ocaml_core_stdlib" in + /opt/*) ocaml_sitelib=`dirname "${ocaml_core_stdlib}"`/site-lib + ;; + *) ocaml_sitelib="${ocaml_core_stdlib}/site-lib" + ;; + esac +fi + +# Find out the directory where ocamlc is: + +ocamlc=`get_path ocamlc` +ocaml_core_bin=`dirname "${ocamlc}"` + +# Set the directory of ocamlfind: + +test -n "$ocamlfind_bin" || ocamlfind_bin="$ocaml_core_bin" + +# Find the directory for the manual: + +# Fallback: +ocaml_core_man=/usr/local/man + +d="$ocaml_core_bin" +while [ "$d" != '/' ]; do + f=0 + if [ -d "$d/man/man1" ]; then + if [ -f "$d/man/man1/ocamlc.1" ] || + [ -f "$d/man/man1/ocamlc.1.gz" ] || + [ -f "$d/man/man1/ocamlc.1.Z" ]; then + f=1 + fi + else + if [ -d "$d/man/mann" ]; then + if [ -f "$d/man/mann/ocamlc.n" ] || + [ -f "$d/man/mann/ocamlc.n.gz" ] || + [ -f "$d/man/mann/ocamlc.n.Z" ]; then + f=1 + fi + fi + fi + if [ "$f" = "1" ]; then + ocaml_core_man="$d/man" + d="/" + else + d=`dirname "$d"` + fi +done + +# Set the directory for ocamlfind's manuals: + +test -n "$ocamlfind_man" || ocamlfind_man="$ocaml_core_man" + +# Guess the right directory for the configuration file: + +if [ -z "${ocamlfind_config}" ]; then + d="$ocaml_core_bin" + case "$d" in + */bin) + if [ -f `dirname "$d"`/lib/findlib.conf ]; then + ocamlfind_config=`dirname "$d"`/lib/findlib.conf + else + ocamlfind_config=`dirname "$d"`/etc/findlib.conf + fi + ;; + *) + ocamlfind_config=/usr/local/etc/findlib.conf + # Fallback value + ;; + esac +fi + +###################################################################### +# do we have #remove_directory? + +echo "Checking for #remove_directory..." +have_remdir=1 +ocaml itest-aux/remdir.ml >/dev/null 2>/dev/null || have_remdir=0 + +###################################################################### +# Test the threading model + +echo "Testing threading model..." + +if ocamlc -vmthread >/dev/null 2>/dev/null; then + ocaml_threads="vm" +else + ocaml_threads="none" +fi + +if ocamlc -config >/dev/null 2>/dev/null; then + # Good. ocamlc tells us the threading model. + if ocamlc -config | grep 'systhread_supported: true'; then + ocaml_threads="posix" + fi +else + # Old ocamlc do not have -config. + rm -f itest-aux/simple + ocamlc -w a -custom -thread -o itest-aux/simple -I +unix unix.cma threads.cma itest-aux/simple_threads.ml \ + >itest-aux/err.out 2>&1 + output=`cat itest-aux/err.out` + + if [ -z "$output" ]; then + ocaml_threads="posix" + fi +fi + +###################################################################### +# Does this version of OCaml support autolinking? + +# Works for OCaml >= 3.00 on. Because findlib can only be compiled +# with these OCaml versions, we can safely assume that autolinking +# is enabled. + +ocaml_autolink="true" + +###################################################################### +# Does this version of OCaml support DLLs? + +echo "Testing DLLs..." + +have_dlls="yes" + +ocaml -I +unix unix.cma itest-aux/simple.ml >/dev/null || have_dlls="no" + +###################################################################### +# Does this version of OCaml support extension points? + +echo "Testing whether ppxopt can be supported..." + +with_ppxopt=1 +enable_topfind_ppxopt=true + +ocaml -I +compiler-libs itest-aux/ppx.ml >/dev/null || { + with_ppxopt=0 + enable_topfind_ppxopt=false +} + +###################################################################### +# Check for -opaque + +echo "Checking for ocamlc -opaque..." + +opaque="-opaque" +ocamlc -opaque >/dev/null 2>/dev/null || opaque="" + +###################################################################### +# Configure libraries + +check_before_install=0 +findlib_installed_meta='' +if [ -d "${ocaml_sitelib}" ]; then + previous_config="${ocaml_sitelib}/findlib/Makefile.packages" + if [ -f "${previous_config}" ]; then + echo "Querying installation: found list of findlib-generated META files" + eval "$(sed -ne 's/ /,/g' -e 's/^SITELIB_META,*=,*\([^,].*[^,]\),*/findlib_installed_meta="\1"/p' "$previous_config")" + echo "Installation has: $findlib_installed_meta" + else + previous_config='' + check_before_install=1 + echo "Querying installation: META list not found" + echo "make install will double-check installed META files" + fi +else + previous_config='' +fi + +echo "Configuring libraries..." + +# Only succeeds if ${ocaml_sitelib}/$1/META exists and we're **certain** +# it wasn't installed by a previous findlib installation. +is_third_party_META () { + if [ $check_before_install -eq 0 ]; then + if [ -f "${ocaml_sitelib}/$1/META" ]; then + case ",$findlib_installed_meta," in + *,$1,*) + return 1;; + *) + return 0;; + esac + else + return 1 + fi + else + return 1 + fi +} + +check_library () { + if is_third_party_META $1; then + echo "$1: package already present" + # Library is present - exit code is 0 because the library is found + # (e.g. detection for Unix) but we don't actually add it to the + # generated_META list. + return 0 + fi + + if [ -z "$3" ]; then + check_library "$1" "$2" "$1.cmi" + return $? + fi + + package="$1" + if [ -z "$2" ]; then + msg='' + else + msg=" ($2)" + fi + + shift 2 + for file; do + if [ -e "${ocaml_core_stdlib}/${file}" ]; then + package_dir="$(dirname "${file}")" + if [ "${package_dir}" = '.' ]; then + echo "${package}: found" + package_subdir='.' + package_dir='^' + else + package_subdir="${package_dir}" + package_dir="+${package_dir}" + echo "${package}: found (in ${package_dir})" + fi + package_key="$(echo "${package}" | tr - _)" + eval "${package_key}_dir=\"${package_dir}\"" + eval "${package_key}_subdir=\"${package_subdir}\"" + if [ "$package" = 'num' ]; then + generated_META="${generated_META} num num-top" + numtop='num-top' + else + generated_META="${generated_META} ${package}" + fi + return 0 + fi + done + + echo "$package: not present${msg}" + return 1 +} + +generated_META='stdlib' +numtop='' + +if ! check_library unix 'possible since 4.08' unix/unix.cmi unix.cmi; then + echo "configure: ocamlfind requires OCaml's Unix library" 1>&2 + exit 1 +fi + +check_library dynlink '' dynlink/dynlink.cmi dynlink.cmi +check_library bigarray 'possible since 4.08' +check_library compiler-libs '' 'compiler-libs' +check_library dbm 'normal since 4.00' +check_library graphics 'normal since 4.09' +check_library num 'normal since 4.06' +check_library ocamlbuild 'normal since 4.03' ocamlbuild/ocamlbuildlib.cma +check_library ocamldoc '' ocamldoc/odoc.cmi +check_library raw_spacetime 'normal since 4.12' raw_spacetime_lib.cmxa +check_library threads '' threads/thread.cmi vmthreads/thread.cmi; +check_library runtime_events '' runtime_events/runtime_events.cmi + +# Need to know if str and labltk are available for the toolbox +if check_library str 'possible since 4.08' str/str.cmi str.cmi; then + have_str=1 +else + have_str=0 +fi + +if check_library labltk 'normal since 4.02' labltk/labltk.cma; then + have_labltk=1 +else + have_labltk=0 +fi + +# Dynlink check. + +have_natdynlink=0 +natdynlink="" +camlp4_dynlink="" +if [ -f "${ocaml_core_stdlib}/${dynlink_subdir}/dynlink.cmxa" ]; then + have_natdynlink=1 + natdynlink="archive(native) = \"dynlink.cmxa\"" + camlp4_dynlink="dynlink" + echo "native dynlink: found" +else + natdynlink="archive(native) = \"\"" + echo "native dynlink: not found" +fi + +# Check on camlp4: + +if [ $with_camlp4 -eq 0 ]; then + echo "camlp4: disabled" +else if in_path camlp4; then + if is_third_party_META camlp4; then + echo "camlp4: third-party" + fi + camlp4_dir=`camlp4 -where | tr -d '\015'` + if [ ${use_cygpath} -gt 0 ]; then + camlp4_dir=`echo x | env USE_CYGPATH=1 tools/patch x "$camlp4_dir"` + # This makes camlp4_dir a windows path + elif [ "${pure_mingw}" = "yes" ]; then + # Must double the backslahes + camlp4_dir="$(echo "${camlp4_dir}" | sed -e 's;\\;\\\\;g')" + fi + camlp4_version=`camlp4 -v 2>&1` + if [ "$have_dlls" = "yes" ]; then + camlp4_cmd="camlp4" + else + camlp4_cmd="safe_camlp4" + fi + # Check whether 3.09 or 3.10 style: + if camlp4 -loaded-modules >/dev/null 2>/dev/null; then + camlp4style=310 + else + camlp4style=309 + fi + generated_META="${generated_META} camlp4" + rm -rf "site-lib-src/camlp4" + mkdir "site-lib-src/camlp4" + cp "site-lib-src/camlp4.$camlp4style/META.in" "site-lib-src/camlp4/" + echo "camlp4: using $camlp4_cmd, style $camlp4style" +else + with_camlp4=0 + echo "camlp4: not present (normal since OCaml-4.02)" +fi +fi + +# bytes? +# (NB. This is always ours, and it doesn't go into generated_META) + +req_bytes="" +if [ -f "${ocaml_core_stdlib}/bytes.cmi" ] || + [ -f "${ocaml_core_stdlib}/stdlib__bytes.cmi" ] || + [ -f "${ocaml_core_stdlib}/stdlib__Bytes.cmi" ]; then + echo "bytes: found, installing fake library" + lbytes="bytes" + cbytes=0 +else + echo "bytes: not found, installing compat library" + lbytes="" + req_bytes="bytes" + cbytes=1 +fi + + +if [ $with_toolbox -gt 0 ]; then + if [ $have_str -eq 0 ] || [ $have_labltk -eq 0 ]; then + echo "Sorry, toolbox requires str and labltk - omitting toolbox." + with_toolbox=0 + fi +fi + +# Generate the META files now. + +for dir in site-lib-src/*; do + # We do not really know if $dir is a directory. + rm -f $dir/META +done + +for lib in $generated_META $lbytes; do + if="" + if [ -f site-lib-src/$lib/interfaces.out ]; then + if=`cat site-lib-src/$lib/interfaces.out` + fi + sed -e "s|%%os%%|${os}|g" \ + -e "s|%%type_of_threads%%|${ocaml_threads}|g" \ + -e "s|%%camlp4_dir%%|${camlp4_dir}|g" \ + -e "s|%%camlp4_version%%|${camlp4_version}|g" \ + -e "s|%%camlp4_cmd%%|${camlp4_cmd}|g" \ + -e "s|%%camlp4_dynlink%%|${camlp4_dynlink}|g" \ + -e "s|%%interfaces%%|${if}|g" \ + -e "s|%%findlib_version%%|${version}|g" \ + -e "s|%%natdynlink%%|${natdynlink}|g" \ + -e "s|%%dynlink_dir%%|${dynlink_dir}|g" \ + -e "s|%%unix_dir%%|${unix_dir}|g" \ + -e "s|%%str_dir%%|${str_dir}|g" \ + site-lib-src/$lib/META.in > site-lib-src/$lib/META + + echo "Configuration for $lib written to site-lib-src/$lib/META" +done + +for part in `cd src; echo *`; do + if [ -f "src/$part/META.in" ]; then + sed -e "s/@VERSION@/$version/g" \ + -e "s/@REQUIRES@/${req_bytes}/g" \ + src/$part/META.in >src/$part/META + fi +done + +###################################################################### + +printf "Detecting compiler arguments: " + +( cd tools/extract_args && make ) >ocargs.log 2>&1 +if [ "$?" -eq 0 ]; then + printf "(extractor built) " + tools/extract_args/extract_args -o src/findlib/ocaml_args.ml ocamlc ocamlcp ocamloptp ocamlmklib ocamlmktop ocamlopt ocamldep ocamldoc >>ocargs.log 2>&1 + # ocamlbrowser does not work! + if [ $? -eq 0 ]; then + echo "ok" + else + echo "FAILED (see the file ocargs.log for details)" + exit 1 + fi +else + echo "FAILED (see the file ocargs.log for details)" + exit 1 +fi + +###################################################################### +# Write Makefile.config + +parts="findlib" +ocamlfind_ocamlflags="-I +unix -I +dynlink" +ocamlfind_archives="findlib.cma unix.cma" +if [ $with_toolbox -gt 0 ]; then + parts="$parts findlib-toolbox" +fi +if [ $cbytes -gt 0 ]; then + # bytes first, because findlib needs it + parts="bytes $parts" + ocamlfind_ocamlflags="${ocamlfind_archives} -I ../bytes" + ocamlfind_archives="bytes.cma ${ocamlfind_archives}" +fi + +echo "# Makefile.config written by configure" >Makefile.config +echo "OCAML_CORE_STDLIB=${ocaml_core_stdlib}" >>Makefile.config +echo "OCAML_CORE_BIN=${ocaml_core_bin}" >>Makefile.config +echo "OCAML_CORE_MAN=${ocaml_core_man}" >>Makefile.config +echo "OCAML_SITELIB=${ocaml_sitelib}" >>Makefile.config +echo "OCAML_THREADS=${ocaml_threads}" >>Makefile.config +echo "OCAMLFIND_BIN=${ocamlfind_bin}" >>Makefile.config +echo "OCAMLFIND_MAN=${ocamlfind_man}" >>Makefile.config +echo "OCAMLFIND_CONF=${ocamlfind_config}" >>Makefile.config +echo "OCAMLFIND_OCAMLFLAGS=${ocamlfind_ocamlflags}" >>Makefile.config +echo "OCAMLFIND_ARCHIVES=${ocamlfind_archives}" >>Makefile.config +echo "OCAML_AUTOLINK=${ocaml_autolink}" >>Makefile.config +echo "OCAML_REMOVE_DIRECTORY=${have_remdir}" >>Makefile.config +echo "EXEC_SUFFIX=${exec_suffix}" >>Makefile.config +echo "LIB_SUFFIX=${lib_suffix}" >>Makefile.config +echo "CUSTOM=${custom}" >>Makefile.config +echo "PARTS=${parts}" >>Makefile.config +echo "INSTALL_TOPFIND=${with_topfind}" >>Makefile.config +echo "USE_CYGPATH=${use_cygpath}" >>Makefile.config +echo "HAVE_NATDYNLINK=${have_natdynlink}" >>Makefile.config +echo "VERSION=${version}" >>Makefile.config +echo "ENABLE_TOPFIND_PPXOPT=${enable_topfind_ppxopt}" >>Makefile.config +echo "SYSTEM=${system}" >>Makefile.config +echo "NUMTOP=${numtop}" >>Makefile.config +echo "SH=${sh}" >>Makefile.config +if [ "$mingw_lib" != "" ]; then + echo "OCAMLC_FLAGS=-I \"${mingw_lib}\"" >>Makefile.config + echo "OCAMLOPT_FLAGS=-I \"${mingw_lib}\"" >>Makefile.config +fi +echo "OPAQUE=${opaque}" >>Makefile.config +echo "CHECK_BEFORE_INSTALL=${check_before_install}" >>Makefile.config +echo "INSTALLDIR = install -d" >>Makefile.config +echo "# change to INSTALLDIR = mkdir -p when BSD install is unavavailable" >>Makefile.config +echo "INSTALLFILE = install -c" >>Makefile.config +echo "# change to INSTALLFILE = cp when BSD install is unavailable" >>Makefile.config +echo "SITELIB_META=${generated_META}" >Makefile.packages + +# All OK + +echo +echo "About the OCAML core installation:" +echo " Standard library: ${ocaml_core_stdlib}" +echo " Binaries: ${ocaml_core_bin}" +echo " Manual pages: ${ocaml_core_man}" +echo " Multi-threading type: ${ocaml_threads}" +echo "The directory of site-specific packages will be" +echo " site-lib: ${ocaml_sitelib}" +echo "The configuration file is written to:" +echo " findlib config file: ${ocamlfind_config}" +echo "Software will be installed:" +echo " Libraries: in /findlib" +echo " Binaries: ${ocamlfind_bin}" +echo " Manual pages: ${ocamlfind_man}" +if [ $with_topfind -gt 0 ]; then + echo " topfind script: ${ocaml_core_stdlib}" +else + echo " topfind script: omitted" +fi + +if [ $with_ppxopt -gt 0 ]; then + echo "Topfind ppxopt support: yes" +else + echo "Topfind ppxopt support: no" +fi + +if [ $with_toolbox -gt 0 ]; then + echo "Toolbox: yes" +else + echo "Toolbox: no" +fi + +if [ -z "$custom" ]; then + echo "Link custom runtime: no" +else + echo "Link custom runtime: yes" +fi + +if [ $cbytes -gt 0 ]; then + echo "Need bytes compatibility: yes" +else + echo "Need bytes compatibility: no" +fi + +echo +echo "Configuration has been written to Makefile.config" +echo +echo "You can now do 'make all', and optionally 'make opt', to build ocamlfind." + diff --git a/local-packages/ocamlfind/doc/DOCINFO b/local-packages/ocamlfind/doc/DOCINFO new file mode 100644 index 0000000..e5e07dc --- /dev/null +++ b/local-packages/ocamlfind/doc/DOCINFO @@ -0,0 +1,15 @@ +To build the html and manual pages from the SGML sources, you need the +following tools: + +- The DocBook DTD + (http://www.davenport.com) +- James Clark's SGML tools (jade, sx suffice) + (http://www.jclark.com) +- Normal Walsh's DSSSL stylesheets to make the HTML pages + (http://nwalsh.com/docbook/dsssl) +- My db2man tool to make the manual pages + (http://www.ocaml-programming.de/packages) + +The latter also requires Christian Lindig's XML parser +(//http://www.cs.tu-bs.de/softech/people/lindig/software/tony.html). + diff --git a/local-packages/ocamlfind/doc/Makefile b/local-packages/ocamlfind/doc/Makefile new file mode 100644 index 0000000..62a4914 --- /dev/null +++ b/local-packages/ocamlfind/doc/Makefile @@ -0,0 +1,73 @@ +DOCBOOK_HTML = /usr/share/sgml/docbook/stylesheet/dsssl/modular/html +DOCBOOK_PRINT = /usr/share/sgml/docbook/stylesheet/dsssl/modular/print +SRC = $(PWD)/src + +EXPORTED = findlib.mli fl_package_base.mli fl_metascanner.mli \ + fl_dynload.mli topfind.mli + +.PHONY: guide-html ref-html ref-man + +default: guide-html ref-html ref-man README QUICKSTART + +guide-html: guide-html/TIMESTAMP +ref-html: ref-html/TIMESTAMP +ref-man: ref-man/TIMESTAMP + +guide-html/TIMESTAMP: src/*.sgml src/*.mod QUICKSTART.xml common.xml config.xml + mkdir -p guide-html + cd guide-html; \ + rm -f *.htm*; \ + openjade -t sgml -D$(DOCBOOK_HTML) -D$(SRC) findlib.sgml; \ + true + readme -html QUICKSTART.xml >guide-html/quickstart.html + touch guide-html/TIMESTAMP + +ref-html/TIMESTAMP: src/*.sgml src/*.mod common.xml config.xml $(EXPORTED:%=../src/findlib/%) + mkdir -p ref-html + cd ref-html; \ + rm -f *.htm*; \ + openjade -t sgml -D$(DOCBOOK_HTML) -D$(SRC) findlib_ref.sgml; \ + true + mkdir -p ref-html/lib + cd ../src/findlib && \ + ocamldoc -html -d $(PWD)/ref-html/lib -stars -t "The Findlib Library" $(EXPORTED) + touch ref-html/TIMESTAMP + +src/findlib_reference.xml: src/*.sgml src/*.mod + osx -D$(DOCBOOK_HTML) -D$(SRC) \ + findlib_reference.sgml >src/findlib_reference.xml ; \ + true + +ref-man/TIMESTAMP: src/findlib_reference.xml + mkdir -p ref-man + cd ref-man; \ + rm -f *.[0-9] TIMESTAMP; \ + db2man <../src/findlib_reference.xml + touch ref-man/TIMESTAMP + +# Unfortunately, output of ocamldoc -man is too bad to be useful. +# cd ../src/findlib && \ +# ocamldoc -man -man-mini -d $(PWD)/ref-man -man-suffix 3 -stars -t "The Findlib Library" $(EXPORTED) + +.SUFFIXES: .xml .sgml + +.sgml.xml: + sx -xndata $< >$@; true + + + +clean: + rm -rf guide-html guide-man ref-html/TIMESTAMP + rm -f src/*.xml + +distclean: + rm -f src/*.xml + rm -f src/*~ + rm -f *~ + +QUICKSTART: QUICKSTART.xml + readme -text QUICKSTART.xml >QUICKSTART + +README: README.xml + readme -text README.xml >README + diff --git a/local-packages/ocamlfind/doc/QUICKSTART b/local-packages/ocamlfind/doc/QUICKSTART new file mode 100644 index 0000000..582dbb2 --- /dev/null +++ b/local-packages/ocamlfind/doc/QUICKSTART @@ -0,0 +1,247 @@ +****************************************************************************** +QUICKSTART - The most important ways to use findlib +****************************************************************************** + + +============================================================================== +Intro +============================================================================== + +See the file INSTALL for instructions how to build and install findlib. + +============================================================================== +Findlib and the toploop +============================================================================== + +For a number of platforms, OCaml can load bytecode-compiled libraries +dynamically. For these platforms, findlib is very simple to use as explained in +the following. For other platforms, see the paragraph below about "custom +toploops". + +After the toploop has been started, it is possible to load the special findlib +support: [1] + +$ ocaml + Objective Caml version 3.07 + +# #use "topfind";; +Findlib has been successfully loaded. Additional directives: + #require "package";; to load a package + #list;; to list the available packages + #camlp4o;; to load camlp4 (standard syntax) + #camlp4r;; to load camlp4 (revised syntax) + #predicates "p,q,...";; to set these predicates + Topfind.reset();; to force that packages will be reloaded + #thread;; to enable threads + +- : unit = () + +You can now list the available packages: + +# #list;; +bigarray (version: [distributed with Ocaml]) +camlp4 (version: Camlp4 version 3.03 ALPHA) +dbm (version: [distributed with Ocaml]) +dynlink (version: [distributed with Ocaml]) +findlib (version: 0.6) +graphics (version: [distributed with Ocaml]) +labltk (version: [distributed with Ocaml]) +netstring (version: 0.10) +num (version: [distributed with Ocaml]) +stdlib (version: [distributed with Ocaml]) +str (version: [distributed with Ocaml]) +threads (version: [distributed with Ocaml]) +unix (version: [distributed with Ocaml]) +xstrp4 (version: 1.1) + +and load packages by simply typing: + +# #require "netstring";; +Loading /opt/ocaml/lib/unix.cma +Loading /opt/ocaml/lib/str.cma +Loading /opt/ocaml/site-lib/netstring/netstring.cma +Loading /opt/ocaml/site-lib/netstring/netstring_top.cmo + +Findlib takes care to load packages that are required by loaded packages first. +For example, "netstring" uses "unix" and "str" internally, but you do not need +to load them because findlib does it for you. In this example you can also see +that findlib loads netstring_top.cmo containing printers for the toploop. + +You can also enable the Camlp4 parsers by simply typing + +# #camlp4o;; +Loading /opt/ocaml-3.03a/lib/camlp4/camlp4o.cma + Camlp4 Parsing version 3.03 ALPHA + +for the standard syntax or + +# #camlp4r;; +Loading /opt/ocaml-3.03a/lib/camlp4/camlp4r.cma + Camlp4 Parsing version 3.03 ALPHA + +for the revised syntax. (But you cannot switch between the syntaxes.) + +============================================================================== +Custom Toploops +============================================================================== + +For some platforms, OCaml does not implement loading external libraries (e.g. +Cygwin). One has to create a so-called custom toploop that statically links +with these libraries. Example: + +$ ocamlfind ocamlmktop -o mytop -package findlib,unix -linkpkg +$ ./mytop + Objective Caml version 3.07 + +# #use "topfind";; +Findlib has been successfully loaded. Additional directives: + #require "package";; to load a package + #list;; to list the available packages + #camlp4o;; to load camlp4 (standard syntax) + #camlp4r;; to load camlp4 (revised syntax) + #predicates "p,q,...";; to set these predicates + Topfind.reset();; to force that packages will be reloaded + #thread;; to enable threads + +- : unit = () + +Now "#require" works for all libraries referring to the special "unix" +functions. + +============================================================================== +Findlib and scripts +============================================================================== + +The #require directive can also be used in scripts. Example: + +#use "topfind";; +#require "netstring";; + +open Cgi;; +... + +This makes it possible to write scripts that do not contain #directory +directives that are specific for certain installations. + +For Unix environments, you can start scripts directly if you apply the +following trick: + +#! /bin/sh +# (* +exec ocaml "$0" "$@" +*) use "topfind";; +#require "netstring";; + +open Cgi;; +... + +This works wherever OCaml is installed. + +============================================================================== +Compiling programs +============================================================================== + +Assumed you want to compile a program that uses the Netstring package. Do it +the following way: + +$ ocamlfind ocamlc -package netstring -c myprogram.ml + +This way you do not need to add "-I" options to locate Netstring. + +If you want to create an executable, do not forget to add the -linkpkg switch: + +$ ocamlfind ocamlc -o myprogram -package netstring -linkpkg myprogram.cmo + +This switch causes that the mentioned packages are added to the resulting +executable. + +If you want to include several packages, you can either add several "-package" +options, or you can enumerate the packages separated by commas: -package +netstring,labltk. + +============================================================================== +Camlp4 +============================================================================== + +If you add a -syntax option, the compiler will be told to parse the source file +using camlp4: + +$ ocamlfind ocamlc -package netstring -syntax camlp4o -c myprogram.ml + +Use -syntax camlp4o for the standard syntax or -syntax camlp4r for the revised +syntax. + +Additionally, you can mention packages that add new syntax features. The +package xstrp4 is an example of this: + +$ ocamlfind ocamlc -package xstrp4,netstring -syntax camlp4o -c myprogram.ml + +Now you can use the $ notation that is implemented by xstrp4 in the source file +myprogram.ml. + +Note that you can also invoke ocamldep from ocamlfind: + +$ ocamlfind ocamldep -package xstrp4 -syntax camlp4o *.ml *.mli >.depend + +This enables the syntax extensions, too. + +============================================================================== +ocamlbrowser +============================================================================== + +Since findlib-0.7, it is also possible to start ocamlbrowser from ocamlfind. +For example, + +$ ocamlfind browser -package xstrp4 + +adds the correct path specification such that the modules contained in the +package xstrp4 are also displayed. With + +$ ocamlfind browser -all + +all package are added to the path spec. + +============================================================================== +The Makefile wizard +============================================================================== + +There is a wizard that makes it very easy to write Makefiles. Call the wizard +by + +$ ocamlfind findlib/make_wizard + +(the wizard requires that the labltk library is available). A new window pops +up, and by very few clicks you can describe your own library. Finally, a +Makefile is written. + +============================================================================== +There is no magic! +============================================================================== + +Findlib is neither a patch of OCaml nor uses it internal features of the OCaml +programming environment. It is only a convention to install software components +in filesystem hierarchies, a library interpreting this convention, and some +frontend applications making the library useable for you. + +One important consequence is that you can only refer to those software +components that have previously been installed in a way findlib understands. +This convention is beyond the scope of this QUICKSTART guide, see the reference +manual for details. You can always check whether findlib accepts a component as +"findlib package" by the command + +$ ocamlfind list + +(this is the same as the #list directive in the toploop). If the package occurs +in the list, it is found, otherwise not. + + +-------------------------- + +[1] In previous versions, #use "findlib" loaded the library. However, this + caused a name conflict for a certain type of installation. Because of + this, the name of the loader script has been changed to "topfind", but + "findlib", and "ocamlfind" (Debian) are also available for backwards + compatibility. + + + diff --git a/local-packages/ocamlfind/doc/QUICKSTART.xml b/local-packages/ocamlfind/doc/QUICKSTART.xml new file mode 100644 index 0000000..b00a51d --- /dev/null +++ b/local-packages/ocamlfind/doc/QUICKSTART.xml @@ -0,0 +1,288 @@ + + +%common; + + +up'> + + +%config; + +]> + + + + Intro +

See the file INSTALL for instructions how to build and install +findlib.

+ + + + Findlib and the toploop + +

For a number of platforms, OCaml can load bytecode-compiled +libraries dynamically. For these platforms, findlib is very simple to +use as explained in the following. For other platforms, see the paragraph +below about "custom toploops".

+ +

After the toploop has been started, it is possible to load the special +findlib support:In previous versions, #use "findlib" loaded the +library. However, this caused a name conflict for a certain type of +installation. Because of this, the name of the loader script has been changed +to "topfind", but "findlib", and "ocamlfind" (Debian) are also available +for backwards compatibility. + + +$ ocaml + Objective Caml version 3.07 + +# #use "topfind";; +Findlib has been successfully loaded. Additional directives: + #require "package";; to load a package + #list;; to list the available packages + #camlp4o;; to load camlp4 (standard syntax) + #camlp4r;; to load camlp4 (revised syntax) + #predicates "p,q,...";; to set these predicates + Topfind.reset();; to force that packages will be reloaded + #thread;; to enable threads + +- : unit = () + + +You can now list the available packages: + + +# #list;; +bigarray (version: [distributed with Ocaml]) +camlp4 (version: Camlp4 version 3.03 ALPHA) +dbm (version: [distributed with Ocaml]) +dynlink (version: [distributed with Ocaml]) +findlib (version: 0.6) +graphics (version: [distributed with Ocaml]) +labltk (version: [distributed with Ocaml]) +netstring (version: 0.10) +num (version: [distributed with Ocaml]) +stdlib (version: [distributed with Ocaml]) +str (version: [distributed with Ocaml]) +threads (version: [distributed with Ocaml]) +unix (version: [distributed with Ocaml]) +xstrp4 (version: 1.1) + + +and load packages by simply typing: + + +# #require "netstring";; +Loading /opt/ocaml/lib/unix.cma +Loading /opt/ocaml/lib/str.cma +Loading /opt/ocaml/site-lib/netstring/netstring.cma +Loading /opt/ocaml/site-lib/netstring/netstring_top.cmo + + +Findlib takes care to load packages that are required by loaded packages +first. For example, "netstring" uses "unix" and "str" internally, but you +do not need to load them because findlib does it for you. In this example +you can also see that findlib loads netstring_top.cmo containing printers +for the toploop.

+ +

You can also enable the Camlp4 parsers by simply typing + + +# #camlp4o;; +Loading /opt/ocaml-3.03a/lib/camlp4/camlp4o.cma + Camlp4 Parsing version 3.03 ALPHA + + +for the standard syntax or + + +# #camlp4r;; +Loading /opt/ocaml-3.03a/lib/camlp4/camlp4r.cma + Camlp4 Parsing version 3.03 ALPHA + + +for the revised syntax. (But you cannot switch between the syntaxes.) +

+
+ + + Custom Toploops + +

For some platforms, OCaml does not implement loading external +libraries (e.g. Cygwin). One has to create a so-called custom toploop +that statically links with these libraries. Example: + + +$ ocamlfind ocamlmktop -o mytop -package findlib,unix -linkpkg +$ ./mytop + Objective Caml version 3.07 + +# #use "topfind";; +Findlib has been successfully loaded. Additional directives: + #require "package";; to load a package + #list;; to list the available packages + #camlp4o;; to load camlp4 (standard syntax) + #camlp4r;; to load camlp4 (revised syntax) + #predicates "p,q,...";; to set these predicates + Topfind.reset();; to force that packages will be reloaded + #thread;; to enable threads + +- : unit = () + + +Now "#require" works for all libraries referring to the special "unix" +functions. +

+
+ + + Findlib and scripts + +

The #require directive can also be used in scripts. Example: + + +#use "topfind";; +#require "netstring";; + +open Cgi;; +... + + +This makes it possible to write scripts that do not contain #directory +directives that are specific for certain installations.

+ +

For Unix environments, you can start scripts directly if you +apply the following trick: + + +#! /bin/sh +# (* +exec ocaml "$0" "$@" +*) use "topfind";; +#require "netstring";; + +open Cgi;; +... + + +This works wherever OCaml is installed.

+
+ + + Compiling programs + +

Assumed you want to compile a program that uses the Netstring package. +Do it the following way: + + +$ ocamlfind ocamlc -package netstring -c myprogram.ml + + +This way you do not need to add "-I" options to locate Netstring.

+ +

If you want to create an executable, do not forget to add the +-linkpkg switch: + + +$ ocamlfind ocamlc -o myprogram -package netstring -linkpkg myprogram.cmo + + +This switch causes that the mentioned packages are added to the resulting +executable.

+ +

If you want to include several packages, you can either add several +"-package" options, or you can enumerate the packages separated by commas: +-package netstring,labltk.

+
+ + + Camlp4 + +

If you add a -syntax option, the compiler will be told to parse the +source file using camlp4: + + +$ ocamlfind ocamlc -package netstring -syntax camlp4o -c myprogram.ml + + +Use -syntax camlp4o for the standard syntax or -syntax camlp4r for the +revised syntax.

+ +

Additionally, you can mention packages that add new syntax features. +The package xstrp4 is an example of this: + + +$ ocamlfind ocamlc -package xstrp4,netstring -syntax camlp4o -c myprogram.ml + + +Now you can use the $ notation that is implemented by xstrp4 in the +source file myprogram.ml.

+ +

Note that you can also invoke ocamldep from ocamlfind: + + +$ ocamlfind ocamldep -package xstrp4 -syntax camlp4o *.ml *.mli >.depend + + +This enables the syntax extensions, too.

+
+ + + ocamlbrowser +

Since findlib-0.7, it is also possible to start ocamlbrowser from +ocamlfind. For example, + + +$ ocamlfind browser -package xstrp4 + + +adds the correct path specification such that the modules contained in the +package xstrp4 are also displayed. With + + +$ ocamlfind browser -all + + +all package are added to the path spec. +

+
+ + + The Makefile wizard +

There is a wizard that makes it very easy to write Makefiles. Call the +wizard by + +$ ocamlfind findlib/make_wizard + +(the wizard requires that the labltk library is available). A new window +pops up, and by very few clicks you can describe your own library. Finally, +a Makefile is written. +

+
+ + + There is no magic! + +

Findlib is neither a patch of OCaml nor uses it internal features of +the OCaml programming environment. It is only a convention to install +software components in filesystem hierarchies, a library interpreting +this convention, and some frontend applications making the library useable for +you.

+ +

One important consequence is that you can only refer to those +software components that have previously been installed in a way findlib +understands. This convention is beyond the scope of this QUICKSTART guide, +see the reference manual for details. You can always check whether findlib +accepts a component as "findlib package" by the command + + +$ ocamlfind list + + +(this is the same as the #list directive in the toploop). If the package +occurs in the list, it is found, otherwise not.

+
+ + diff --git a/local-packages/ocamlfind/doc/README b/local-packages/ocamlfind/doc/README new file mode 100644 index 0000000..3385211 --- /dev/null +++ b/local-packages/ocamlfind/doc/README @@ -0,0 +1,470 @@ +****************************************************************************** +README - The findlib library manager +****************************************************************************** + + +============================================================================== +Introduction +============================================================================== + +The "findlib" software provides a scheme to manage reusable software components +in the form of libraries, and includes tools that support this scheme. A +library installed as a findlib component is also called a package. The point is +that the findlib scheme allows it to store metainformation about the library, +especially how it can be used in programs. The packages are kept in the +filesystem hierarchy, but the directory structure is defined by findlib, and +there is no way to deviate from this standard. The library contains functions +to look the directory up that stores a package, to query metainformation about +a package, and to retrieve dependency information about multiple packages. +There is also a tool that allows the user to enter queries on the command-line. +In order to simplify compilation and linkage, there are new frontends of the +various OCaml compilers that can directly deal with packages. + +It is important to understand that findlib is not a general-purpose package +manager (like rpm for Linux), and does not support the management of arbitrary +files, but only OCaml libraries. However, there are lots of special functions +for libraries. findlib is more comparable with Gnome's pkg-config and Perl's +MakeMaker, but of course there are language-specific differences. + +The metainformation includes: + +- The necessary command-line arguments to use a library. + +- Dependencies on other packages. + +- Version strings. + +These data can be conditional. Possible conditions are certain environmental +settings, such as whether the bytecode or the native code compiler is used, or +whether the application is multi-threaded. It is also possible that a package +behaves differently when a certain other package is selected. + +There is special support for scripts. It is possible to load libraries into +toploops, including all dependent libraries, with only one command. + +Findlib has been developed since March 1999, and has matured for more than four +years until the release of version 1.0. One of the important questions during +this long period of development was which features are necessary and which not. +The result is a utility that follows still simple concepts, but is flexible +enough to allow even the description of complex libraries and complex +interdependencies. + +============================================================================== +Documentation +============================================================================== + +See the file QUICKSTART for the most important findlib commands. + +There is a User's Guide introducing into the concepts of findlib, especially +explaining how to create packages. + +The Reference Manual describes commands, directory structure, configuration +files, and library routines in detail. + +============================================================================== +Installation +============================================================================== + +See the file INSTALL. + +============================================================================== +Download +============================================================================== + +The current version is announced in the Objective Caml Link Database [1]. + +============================================================================== +Copyright and License Conditions +============================================================================== + +Findlib is copyright 1999-2012 by Gerd Stolpmann. See the file LICENSE for the +MIT/X11 style license conditions. Contact me at gerd@gerd-stolpmann.de in case +of questions. + +============================================================================== +List of Changes +============================================================================== + +- 1.9.5:: fixes a bug in the scripting that slipped into 1.9.4 + +- 1.9.4: Also finds the libraries str.cm(x)a, unix.cm(x)a, and dynlink.cm(x)a + in subdirectories of the OCaml standard library, as needed for OCaml-4.14 + (David Allsopp). + Support for runtime_events (Patrick Ferris) + Fix spelling of "OCaml" everywhere (Marek Kubica) + Work around the deprecation of a POSIX shell feature (Issam Maghni) + Support DESTDIR, and favor the "install" command for installation (Gerd + Stolpmann on suggestion of Thomas Klausner) + +- 1.9.3: Fixes another build problem regarding OCaml-5.00 + +- 1.9.2: Fixes a build problem regarding OCaml-5.00 + +- 1.9.1: Fixes a few install-related issues, like missing files. + +- 1.9: Overhaul how separately installed packages (e.g. num) are handled (by + David Allsopp). + Switch to opam-2.0 file format (by David Allsopp). + Fix an incomaptibility with ocaml-4.13 (by David Allsopp). + Expose the native toplevel (by Louis Gesbert). + Fix an incompatibility with "Jane Street Style" (by Mark Laws). + Switch from m4 to sed (by kit-ty-kate). + +- 1.8.1: Adapted to upcoming ocaml-4.09. + New API Findlib.list_packages' can specify a package prefix. + +- 1.8.0: Fix reinstallation of "num" for OCaml-4.06. + Fix build with OCaml-4.07. + The installation of graphics/META is now optional. + Fix "ocamlfind query -d". + The environment variable OCAMLFIND_IGNORE_DUPS_IN is now interpreted as a + list of directories. + Packages for "ocamlfind query" may now be separated by commas, too. + New "warning" property for packages. + Forgetting to pass -thread/-vmthread only prints a warning now, but doesn't + stop the build. + For dealing with case-sensitive filesystems it is now only tried to match + ASCII characters, but not encoding-dependent characters. + +- 1.7.3: Fix regarding num-top: this library is now also optional, as num. + +- 1.7.2: Trying to protect against failures when several package installs are + done in parallel. + New subpackage "findlib.top" for the toploop (Jeremie Dimino). + The "num" library is now optional. + Shell scripts are started via "sh" command when there is no /bin/sh (ygrek) + +- 1.7.1: added missing file to tarball + +- 1.7.0: New command "ocamlfind printppx" that outputs how the ppx + preprocessor would be called (Hendrik Tews). + Support for the raw_spacetime library that comes with OCaml 4.04 (Gerd + Stolpmann with help from Mark Shinwell). + Require that ocamlc and ocamlc.opt are installed to the same directory for + emitting the "opt" setting in the generated config file - same for + ocamlopt.opt, ocamldep.opt, ocamldoc.opt. + +- 1.6.3:Fix: "ocamlfind printconf" respects the environment variable + OCAMLFIND_CONF (reported by Andre) + Build with -opaque (reported by hhugo) + Preliminary support for native toplevel so far the toplevel is implemented + symmetrically to the bytecode case (this is not correct in vanilla ocaml) + New options: ocamlfind query -qe -qo + +- 1.6.2:Uninstalling findlib no longer uninstalls the ocamlbuild library by + accident (Gabriel Scherer, Edwin Török) + Adding an "ocamldoc" library, providing the cmi's for ocamldoc plugins + (suggested by Armaël Guéneau) + Support for OCaml-4.03: recognize that the new -color option has an argument + (reported by Guillaume Bury) + +- 1.6.1: Just an important doc fix. + +- 1.6.0: Adding support for dynamically loading packages (François Bobot): + new "plugin" variable, new Fl_dynload module. + New command "ocamlfind lint" for checking META files (François Bobot). + Also support MSYS_NT on Windows. Permit spaces in install paths (Christophe + Troestler). + Allow to query the location of the META file of a package: "ocamlfind query + -format '%m'" (Gerd Stolpmann). + Get the install path for the META file of packages: "ocamlfind printconf + metapath" (Gerd Stolpmann). + +- 1.5.6: for MSVC build fixing bad filename suffix (Dmitry Bely). + The switch -only-show did not work as described. (Error report from Bob + Atkey.) + Also support mingw64 as system type (Matthieu Dubuget). + +- 1.5.5: fixes a build problem for BSD systens + +- 1.5.4: New ppxopt META variables (Peter Zotov). + Support for OCAMLFIND_TOOLCHAIN environment variable (Peter Zotov). + +- 1.5.3: The installation of "bytes" respects now $prefix and the configured + destination. + New option -pp for "ocamlfind query", to get preprocessor packages. + Updated the compatibility Bytes module to support extend, init, mapi, + blit_string (Gabriel Scherer). + +- 1.5.2: support for the query formats "%+a" and "%+A". + Fix: the "ppx" property is now also path-expanded when interpreted in a + toploop. + Fix: implicit "ppx" is not path-expanded anymore. + Fix: Build bytes.cmxs only if natdynlink is enabled (Andy Ray). + +- 1.5.1: includes a file that was missing in 1.5 + +- 1.5: Including the "bytes" package that is either a compat package for ocaml + < 4.02 or a fake package for ocaml >= 4.02. The package aims at helping to + support the transition to the new "bytes" type for mutable strings. + Also installing findlib.cmxs if OCaml supports it. + Allowing to disable camlp4 (in prep for OCaml-4.02). + The "ppx" package property can be specified for constructing ppx-type + preprocessors (patches from Peter Zotov). + +- 1.4.1:ocamldoc: The order of -ppopt arguments was changed by ocamlfind, + which is not correct. (Sylvain Le Gall and Jérémie Dimino.) + +- 1.4: Fixed performance bug when many arguments need to be processed (Jérôme + Vouillon). + Auto-configuring ocamldoc.opt if it is found (Christopher Zimmermann). + New config switch -no-custom to prevent that "ocamlfind" is linked in + custom-runtime mode (bytecode only) (Christopher Zimmermann). + The library dbm is no longer part of OCaml, and now optional in findlib + (Ashish Argawal). + Support for ocamloptp. + New function Topfind.log for controlling the verbosity (Jeremie Dimino). + Rewritten Fl_metascanner without camlp4 (patch from Gabriel Scherer) + +- 1.3.3: OCaml-4: using the new #remove_directory directive if present. + Better compatibility with the OCaml version from Homebrew. + +- 1.3.2: Handling of empty arguments (Wojciech Meyer). + Added entry for camlp4.fulllib. + New switch -add for "ocamlfind install" (Hans Ole Rafaelsen). + Further fixes for ocaml-4.00. + Fixing the recognition of double .cmi interface files. + Fixing -dontlink (it is now deeply interpreted). + +- 1.3.1: Fixing a bug with ocamlmklib that slipped through in 1.3.0 + +- 1.3.0: Fixes for ocaml-4.00 (especially topfind). + Emitting an error if the configuration file does not exist. + Emitting a warning if the selected toolchain does not exist. + camlp4 is referenced by "+camlp4" in META. + Including the sources for the documentation in the tarball. + License change (simplification) for num_top_printers.mli. + Fix ocamlmklib wrapper: processing contracted args (like -L/dir) correctly. + Many wrappers get a new option -passrest instructing to pass all remaining + options on the command-line unchanged to the invoked tool. + Prettified -help output. + +- 1.2.8: Adding support for ocamlmklib (B. Meurer's patches) + Fix for win32 in the configure script. + +- 1.2.7: Fix: if a META file defines several packages, and one of the packages + has a broken dependency, ocamlfind used to report all errors even if the + broken packages were not used. This is now changed - broken subpackages are + ignored when they are not needed, in the same way as broken top-level + packages are ignored when not needed. (Thanks to Sylvain Le Gall for + reporting the problem.) + Added -thread and -vmthread switches to "ocamlfind ocamldoc". These actually + only add the right predicates. (Thanks to Vladimir Ivanov for pointing this + problem out.) + Package warnings can be emitted by "ocamlfind ocamldoc". + +- 1.2.6: adding META for ocamlbuild. + Fixes for MinGW/MSYS platform. + Improved messages. + +- 1.2.5: Fix: Again CR deletion... Turns out some OS do not understand '\r' + but only '\015' (thanks to Isaiah Weiner). + Support for Win64 (untested; thanks to David Allsopp). + ocamlfind no longer emits auto-generated -ccopt options. These tend to + accumulate, and it is possible that for large projects the maximum command + line length is exceeded. Current versions of the OCaml compilers do not + need these extra -ccopt anyway, so this code is completely dropped. + +- 1.2.4: Fix: Bigarray needs unix (Thanks to Markus Mottl). + Fix: In the version of camlp4 provided by OCaml 3.11 various libraries do + not contain dynlink anymore. Because of this, dynlink becomes a + prerequisite of camlp4. (Thanks to Martin Jambon). + Attempt: Fixing the space issue for paths (Win32). It is unclear whether it + is solved. (Thanks to Christophe Troestler). + +- 1.2.3: Solving the CR deletion differently, to make OS X happy. + +- 1.2.2: Fix: Problem with CR character (Cygwin) (Thanks to David Allsopp). + Fix: Case-insensitive filesystems (partially solved) (Thanks to David + Allsopp). + Fix: File name with backslashes at the end (Win32; thanks to Dmitry + Grebeniuk). + +- 1.2.1: Fix: Camlp4 rules now activate the stream parser extension + +- 1.2: Fix in build scripts: Prepending $(prefix) when installing safe_camlp4 + (thanks to Daniel Janus) + Non-existing -I directories are ignored (thanks to Nicolas Pouillard) + A script to create a MacOS X package (thanks to Pietro Abate) + Better support for Windows (with help from Robert Roessler and David + Allsopp) + Support for camlp4 on OCaml 3.10 + Fix: "ocamlfind install" with "-patch" option writes now correct META file + for the case that subpackages occur + Adding environment variable OCAMLFIND_IGNORE_DUPS_IN to reduce the number of + warnings ocamlfind emits + +- 1.1.2: Bugfix in the META parser: Backslashes are now correctly parsed. + (Thanks to Martin Jambon for finding this problem.) + Fixes for platforms that do not support dynamic loading of DLLs. + Fixed extraction of camlp4 parameters from packages. + +- 1.1.1: Bugfixes only: Fixed detection of threading model for OCaml 3.09. + Fixed alternate configuration files. + +- 1.1: Automatic detection of standard compiler options. + Liberated the checks whether a package is already installed. + The .opt compilers are entered into findlib.conf if available. + New: "install" has -optional switch for optional files. + New: "install" has -patch-version to patch the version into the installed + META file. + New: "install" has -patch-rmpkg to remove subpackages from the installed + META file. + New: "install" has -patch-archives which removes non-existing files from + "archive" variables. This is experimental. + New: subpackages can be disabled by exists_if. + New: Support for toolchains. + Fix for "remove": -destdir works again. + Fix for "call": CTRL-C works when calling interactive commands. + Fix for preprocessor packages: Dependencies on normal packages are resolved. + +- 1.0.4: Fix: In previous versions, "ocamlmktop" set the "toploop" predicate. + It turned out, however, that the toploops generated in this way did not work + properly. For this reason, "ocamlmktop" does not set "toploop" any more for + link time, but instead a new predicate "create_toploop". When the toploop is + executed, the predicate "toploop" is again added. + +- 1.0.3: Fix: The relative position of "-cclib -l" options on the command + line is preserved. In previous versions, these options were moved to the + beginning of the argument list. This did not work for static link editing; + dynamic link editing was not affected. + Fix: The automatic fixup of "threads" dependencies works again. In the + previous version, this was broken. + Addition: -format '%(name)' for ocamlfind query. + Some minor improvements of the documentation. + +- 1.0.2: Fix: The alternate package layout did not fully work. This is + repaired now, and there are some clarifications about relative directory + paths in the documentation. + +- 1.0.1: Fix: Forgot to install some .cmi files + +- 1.0: It is now possible to divide the description of a package into + subpackages (but there is still only one META file, but with enhanced + syntax). This allows it to describe intra-package dependencies. + Predicates in META files can be negated. + The "error" variable allows you to detect conditions under which the library + would not work, and to generate error messages. + It is possible to refer to archive files installed in other packages. + The set of predicates is extended by "package predicates" after the + dependency analysis, making conditions expressable that depend on whether + other packages are selected. + The "+=" operator in META files adds words to variables rather than setting + them. + The "#thread" directive enables multi-threading in toploops and scripts, if + possible. + The "#predicates" directive simplifies the addition of predicates. + Queries: The format specifier %D prints the description of the package. + -long-format includes the description. Short options -r, -l, -d. + ocamlfind list -describe prints package descriptions. + Support for "ocamlfind ocamldoc". However, the implementation is quite + sloppy. + The configuration file is called "findlib.conf" by default, not + "ocamlfind.conf". + Removal of "ocamlfind guess". + Support for #use "findlib" and #use "ocamlfind" has been removed. The only + remaining way to load findlib is by #use "topfind". + There is no longer a thread-safe version of findlib. The user has to ensure + that only one thread uses findlib (which is usually trivial to achieve). + ocamlmktop: Directories are no longer automatically added to the search + path. This did not work anyway, and this change forces scripts to always + invoke "#require" to load/enable libraries, for better uniformity. + Fixes: num-top works. "ocamlfind ocamlopt -thread" generates a better error + message on non-POSIX systems. "ocamlfind query -descendants" takes + predicates into account (it did not do that in previous versions of + findlib). + +- 0.9: Changes for OCaml 3.07 (-thread, -vmthread). Includes Zack's toploop + printers for bigints. + +- 0.8 - 0.8.1: Renamed a lot of modules to avoid name clashes with OCaml core + modules. Cygwin: Additional option -cygpath for "configure". The man pages + have a NAME section. Bugfix in Makefile wizard. + +- 0.7 - 0.7.2: DLLs: There are now two styles of installation: DLLs can be + installed in the package directories (like before), or in a shared + directory "stublibs". For the first style, there is now an option "ldconf" + that determines whether the ld.conf file is to be updated, and if so, which + file. The latter style is enabled by simply creating a directory "stublibs" + in the site-lib directory. (In the first version the directory was called + "libexec". By user request, the name of the DLL directory has been changed + to "stublibs".) + "ocamlfind install" preserves now the mtime of the files. + "ocamlfind printconf" is more flexible, and easier to call from scripts. + "ocamlfind browser" calls ocamlbrowser with the right -I options. + "ocamlfind query": -descendants implies now -recursive. + "ocamlfind ocamldep": -native-filter and -bytecode-filter for more exact + dependency generation. + There may be now postinstall and postremove scripts. + "ocamlfind pkg/cmd": This syntax can be used to call the program cmd that + is installed in the package directory for pkg. Intended to simplify the + invocation of programs that are installed in package directories and not in + XXX/bin, which may be useful for package- related tools. + Findlib has now a toolbox containing helpful programs besides ocamlfind. + For the beginning, there is a Makefile wizard that can be called by + "ocamlfind findlib/make_wizard". + #use "topfind" instead of #use "findlib" to avoid name clashes in a certain + configuration. #use "findlib" and #use "ocamlfind" are still supported for + backward compatibility if the name clash does not occur. + Fix: bytecode threads work again. (The wrong unix library was linked for + recent OCaml versions.) + Many smaller improvements; the docs have been updated. + +- 0.6 - 0.6.2: Minor changes for Ocaml-3.03-alpha (and later for 3.04). New + #list directive. New: #use "findlib" loads the findlib directives into + every toploop (Ocaml-3.03-alpha). + The file ld.conf is automatically updated when DLLs are installed or + removed. + Fix: /tmp/findlib_initf* no longer overflows. The thread library is now + always the first linked library. + +- 0.5 - 0.5.4: Findlib has now a configuration file (see documentation under + findlib.conf). Much more environment variables. The location of the + standard library is now configurable at runtime. + The package search path can now be selected independently of the package + installation directory. + New commands: ocamlfind list, ocamlfind printconf, ocamlfind guess (See + documentation under ocamlfind) + Optional alternate directory layout: All META files go into a separate + directory (see documentation under site-lib). + Findlib works now only for OCaml 3; support for OCaml 2 has been dropped. + As a consequence, the "configure" script could be simplified; it is no + longer necessary to figure out the linker options. + Improved support for camlp4: New directives #camlp4o and #camlp4r for the + toploop. + ocamlfind now detects whether two selected packages have equally named + toplevel modules, and prints a warning in this case. + There is a downstripped version ocamlfind-mini (see directory "mini"). This + is a one-file script that can be easily distributed with any software. + ocamlfind-mini has reduced functionality, but it is sufficient to compile + and install a library. (But it does not support using a library.) + Support for the Cygwin port of OCaml. + Installation of packages: The file permissions are preserved when files are + installed. However, the umask is applied. The "install" and "remove" + subcommands have better diagnostics. + ocamlfind ocamlmktop: Generates now initialization code for the include + path. You don't need to call your toploop with -I options any more. + Furthermore, this fixes some problems with packages that add printers to + the toploop. + New: ocamlfind ocamldep. ocamlfind is now prepared for the new -pp option + of ocamldep (upcoming Ocaml 3.03). + Installation of findlib: New PREFIX variable in Makefile to install + locally. + Fixes: itest. ocamlfind query -descendants works again. + +- 0.4: Experimental support for camlp4 (see FAQ section in the manual). New + environment variable OCAMLFIND_COMMANDS (see ocamlfind(1)). + +- 0.3 - 0.3.1: Necessary updates for OCaml 3. Bugfix: Findlib did not work for + bytecode threads. The reason was that findlib added the directory of the + stdlib to the search path. Works now. + +Older changes are no longer documented. + + +-------------------------- + +[1] see http://links.camlcity.org + + + diff --git a/local-packages/ocamlfind/doc/README.xml b/local-packages/ocamlfind/doc/README.xml new file mode 100644 index 0000000..c399b02 --- /dev/null +++ b/local-packages/ocamlfind/doc/README.xml @@ -0,0 +1,685 @@ + + +%common; + + +up'> + + +%config; + +]> + + + + Introduction + +

The "findlib" software provides a scheme to manage reusable software +components in the form of libraries, and includes tools that support +this scheme. A library installed as a findlib component is also called +a package. The point is that the findlib scheme allows it to store +metainformation about the library, especially how it can be used in +programs. The packages are kept in the filesystem hierarchy, but the +directory structure is defined by findlib, and there is no way to +deviate from this standard. The library contains functions to look the +directory up that stores a package, to query metainformation about a +package, and to retrieve dependency information about multiple +packages. There is also a tool that allows the user to enter queries +on the command-line. In order to simplify compilation and linkage, +there are new frontends of the various OCaml compilers that can +directly deal with packages. +

+ +

It is important to understand that findlib is not a +general-purpose package manager (like rpm for Linux), and does not +support the management of arbitrary files, but only OCaml libraries. +However, there are lots of special functions for libraries. findlib +is more comparable with Gnome's pkg-config and Perl's MakeMaker, but +of course there are language-specific differences.

+ +

The metainformation includes:

+ +
    +
  • The necessary command-line arguments to use a library.

    +
  • +
  • Dependencies on other packages.

    +
  • +
  • Version strings.

    +
  • +
+ +

These data can be conditional. Possible conditions are certain +environmental settings, such as whether the bytecode or the native code +compiler is used, or whether the application is multi-threaded. It is +also possible that a package behaves differently when a certain other +package is selected.

+ +

There is special support for scripts. It is possible to load +libraries into toploops, including all dependent libraries, with only +one command.

+ +

Findlib has been developed since March 1999, and has matured +for more than four years until the release of version 1.0. One of the +important questions during this long period of development was which +features are necessary and which not. The result is a utility that +follows still simple concepts, but is flexible enough to allow even +the description of complex libraries and complex interdependencies. +

+
+ + + Documentation + +

See the file QUICKSTART for the most important findlib commands.

+ +

There is a User's Guide introducing into the concepts of findlib, +especially explaining how to create packages.

+ +

The Reference Manual describes commands, directory structure, +configuration files, and library routines in detail.

+
+ + + Installation + +

See the file INSTALL.

+
+ + + Download +

+ The current version is announced in the + Objective Caml Link Database. +

+
+ + + Copyright and License Conditions +

+ Findlib is copyright 1999-2012 by Gerd Stolpmann. See the file LICENSE + for the MIT/X11 style license conditions. + + Contact me at gerd@gerd-stolpmann.de in case of questions. +

+
+ + + List of Changes +
    + +
  • +

    1.9.5:: fixes a bug in the scripting that + slipped into 1.9.4

    +
  • + +
  • +

    1.9.4: Also finds the libraries str.cm(x)a, unix.cm(x)a, + and dynlink.cm(x)a in subdirectories of the OCaml standard library, + as needed for OCaml-4.14 (David Allsopp).

    +

    Support for runtime_events (Patrick Ferris)

    +

    Fix spelling of "OCaml" everywhere (Marek Kubica)

    +

    Work around the deprecation of a POSIX shell feature + (Issam Maghni)

    +

    Support DESTDIR, and favor the "install" command for installation + (Gerd Stolpmann on suggestion of Thomas Klausner)

    +
  • + +
  • 1.9.3: Fixes another build problem regarding OCaml-5.00

  • + +
  • 1.9.2: Fixes a build problem regarding OCaml-5.00

  • + +
  • 1.9.1: Fixes a few install-related issues, like missing files.

  • + +
  • +

    1.9: Overhaul how separately installed packages (e.g. num) + are handled (by David Allsopp).

    +

    Switch to opam-2.0 file format (by David Allsopp).

    +

    Fix an incomaptibility with ocaml-4.13 (by David Allsopp).

    +

    Expose the native toplevel (by Louis Gesbert).

    +

    Fix an incompatibility with "Jane Street Style" (by Mark Laws).

    +

    Switch from m4 to sed (by kit-ty-kate).

    +
  • + +
  • +

    1.8.1: Adapted to upcoming ocaml-4.09.

    +

    New API Findlib.list_packages' can specify a package prefix.

    +
  • + +
  • +

    1.8.0: Fix reinstallation of "num" for OCaml-4.06. +

    +

    Fix build with OCaml-4.07.

    +

    The installation of graphics/META is now optional.

    +

    Fix "ocamlfind query -d".

    +

    The environment variable OCAMLFIND_IGNORE_DUPS_IN is now interpreted + as a list of directories.

    +

    Packages for "ocamlfind query" may now be separated by commas, too.

    +

    New "warning" property for packages.

    +

    Forgetting to pass -thread/-vmthread only prints a warning now, + but doesn't stop the build.

    +

    For dealing with case-sensitive filesystems it is now only tried to + match ASCII characters, but not encoding-dependent characters.

    +
  • + +
  • +

    1.7.3: Fix regarding num-top: this library is now also + optional, as num.

    +
  • + +
  • +

    1.7.2: Trying to protect against failures when + several package installs are done in parallel.

    + +

    New subpackage "findlib.top" for the toploop (Jeremie Dimino).

    + +

    The "num" library is now optional.

    + +

    Shell scripts are started via "sh" command when there is no + /bin/sh (ygrek)

    +
  • + +
  • +

    1.7.1: added missing file to tarball

    +
  • + +
  • +

    1.7.0: New command "ocamlfind printppx" that outputs + how the ppx preprocessor would be called (Hendrik Tews).

    +

    Support for the raw_spacetime library that comes with + OCaml 4.04 (Gerd Stolpmann with help from Mark Shinwell).

    +

    Require that ocamlc and ocamlc.opt are installed to the + same directory for emitting the "opt" setting in the generated + config file - same for ocamlopt.opt, ocamldep.opt, ocamldoc.opt.

    +
  • + +
  • +

    1.6.3:Fix: "ocamlfind printconf" respects the + environment variable OCAMLFIND_CONF (reported by Andre)

    +

    Build with -opaque (reported by hhugo)

    +

    Preliminary support for native toplevel so far the toplevel + is implemented symmetrically to the bytecode case (this is not + correct in vanilla ocaml)

    +

    New options: ocamlfind query -qe -qo

    +
  • + +
  • +

    1.6.2:Uninstalling findlib no longer uninstalls the +ocamlbuild library by accident (Gabriel Scherer, Edwin Török)

    +

    Adding an "ocamldoc" library, providing the cmi's for ocamldoc +plugins (suggested by Armaël Guéneau)

    +

    Support for OCaml-4.03: recognize that the new -color option +has an argument (reported by Guillaume Bury)

    +
  • + +
  • +

    1.6.1: Just an important doc fix.

    +
  • + +
  • +

    1.6.0: Adding support for dynamically loading + packages (François Bobot): new "plugin" variable, new + Fl_dynload module.

    +

    New command "ocamlfind lint" for checking META files + (François Bobot).

    +

    Also support MSYS_NT on Windows. Permit spaces in install + paths (Christophe Troestler).

    +

    Allow to query the location of the META file of a package: + "ocamlfind query -format '%m'" (Gerd Stolpmann).

    +

    Get the install path for the META file of packages: + "ocamlfind printconf metapath" (Gerd Stolpmann).

    +
  • + +
  • +

    1.5.6: for MSVC build fixing bad filename suffix + (Dmitry Bely).

    +

    The switch -only-show did not work as described. + (Error report from Bob Atkey.)

    +

    Also support mingw64 as system type (Matthieu Dubuget).

    +
  • + +
  • +

    1.5.5: fixes a build problem for BSD systens

    +
  • + +
  • +

    1.5.4: New ppxopt META variables (Peter Zotov).

    +

    Support for OCAMLFIND_TOOLCHAIN environment variable (Peter Zotov). +

    +
  • + +
  • +

    1.5.3: The installation of "bytes" respects now $prefix and + the configured destination.

    +

    New option -pp for "ocamlfind query", to get preprocessor packages.

    +

    Updated the compatibility Bytes module to support extend, init, mapi, + blit_string (Gabriel Scherer).

    +
  • + +
  • +

    1.5.2: support for the query formats "%+a" and "%+A".

    +

    Fix: the "ppx" property is now also path-expanded when interpreted +in a toploop.

    +

    Fix: implicit "ppx" is not path-expanded anymore.

    +

    Fix: Build bytes.cmxs only if natdynlink is enabled (Andy Ray).

    +
  • +
  • +

    1.5.1: includes a file that was missing in 1.5

    +
  • +
  • +

    1.5: Including the "bytes" package that is either +a compat package for ocaml < 4.02 or a fake package for ocaml >= 4.02. +The package aims at helping to support the transition to the new +"bytes" type for mutable strings.

    +

    Also installing findlib.cmxs if OCaml supports it.

    +

    Allowing to disable camlp4 (in prep for OCaml-4.02).

    +

    The "ppx" package property can be specified for constructing +ppx-type preprocessors (patches from Peter Zotov).

    +
  • + +
  • +

    1.4.1:ocamldoc: The order of -ppopt arguments was +changed by ocamlfind, which is not correct. (Sylvain Le Gall and +Jérémie Dimino.)

    +
  • + +
  • +

    1.4: Fixed performance bug when many arguments +need to be processed (Jérôme Vouillon).

    +

    Auto-configuring ocamldoc.opt if it is found (Christopher +Zimmermann).

    +

    New config switch -no-custom to prevent that "ocamlfind" +is linked in custom-runtime mode (bytecode only) (Christopher +Zimmermann).

    +

    The library dbm is no longer part of OCaml, and now +optional in findlib (Ashish Argawal).

    +

    Support for ocamloptp.

    +

    New function Topfind.log for controlling the verbosity +(Jeremie Dimino).

    +

    Rewritten Fl_metascanner without camlp4 (patch from +Gabriel Scherer)

    +
  • + +
  • +

    1.3.3: OCaml-4: using the new #remove_directory directive + if present.

    +

    Better compatibility with the OCaml version from Homebrew.

    +
  • + +
  • +

    1.3.2: Handling of empty arguments (Wojciech Meyer).

    +

    Added entry for camlp4.fulllib.

    +

    New switch -add for "ocamlfind install" (Hans Ole Rafaelsen).

    +

    Further fixes for ocaml-4.00.

    +

    Fixing the recognition of double .cmi interface files.

    +

    Fixing -dontlink (it is now deeply interpreted).

    +
  • + +
  • +

    1.3.1: Fixing a bug with ocamlmklib that slipped through +in 1.3.0

    +
  • + +
  • +

    1.3.0: Fixes for ocaml-4.00 (especially topfind).

    +

    Emitting an error if the configuration file does not exist.

    +

    Emitting a warning if the selected toolchain does not exist.

    +

    camlp4 is referenced by "+camlp4" in META.

    +

    Including the sources for the documentation in the tarball.

    +

    License change (simplification) for num_top_printers.mli.

    +

    Fix ocamlmklib wrapper: processing contracted args (like -L/dir) correctly.

    +

    Many wrappers get a new option -passrest instructing to pass all +remaining options on the command-line unchanged to the invoked tool.

    +

    Prettified -help output.

    +
  • + +
  • +

    1.2.8: +Adding support for ocamlmklib (B. Meurer's patches)

    +

    Fix for win32 in the configure script.

    +
  • +
  • +

    1.2.7: +Fix: if a META file defines several packages, and one of the packages +has a broken dependency, ocamlfind used to report all errors even if +the broken packages were not used. This is now changed - broken +subpackages are ignored when they are not needed, in the same way as +broken top-level packages are ignored when not needed. (Thanks to +Sylvain Le Gall for reporting the problem.)

    +

    Added -thread and -vmthread switches to "ocamlfind ocamldoc". +These actually only add the right predicates. (Thanks to Vladimir +Ivanov for pointing this problem out.)

    +

    Package warnings can be emitted by "ocamlfind ocamldoc".

    +
  • +
  • +

    1.2.6: adding META for ocamlbuild.

    +

    Fixes for MinGW/MSYS platform.

    +

    Improved messages.

    +
  • +
  • +

    1.2.5: Fix: Again CR deletion... Turns out some OS do not + understand '\r' but only '\015' (thanks to Isaiah Weiner).

    +

    Support for Win64 (untested; thanks to David Allsopp).

    +

    ocamlfind no longer emits auto-generated -ccopt options. These + tend to accumulate, and it is possible that for large projects + the maximum command line length is exceeded. Current versions of + the OCaml compilers do not need these extra -ccopt anyway, so + this code is completely dropped.

    +
  • + +
  • +

    1.2.4: Fix: Bigarray needs unix (Thanks to Markus Mottl).

    +

    Fix: In the version of camlp4 provided by OCaml 3.11 various + libraries do not contain dynlink anymore. Because of this, dynlink + becomes a prerequisite of camlp4. (Thanks to Martin Jambon).

    +

    Attempt: Fixing the space issue for paths (Win32). It is unclear + whether it is solved. (Thanks to Christophe Troestler).

    +
  • + +
  • +

    1.2.3: Solving the CR deletion differently, to + make OS X happy.

    +
  • + +
  • +

    1.2.2: Fix: Problem with CR character (Cygwin) + (Thanks to David Allsopp). +

    +

    Fix: Case-insensitive filesystems (partially solved) + (Thanks to David Allsopp). +

    +

    Fix: File name with backslashes at the end (Win32; + thanks to Dmitry Grebeniuk).

    +
  • + +
  • +

    1.2.1: Fix: Camlp4 rules now activate the +stream parser extension

    +
  • + +
  • +

    1.2: Fix in build scripts: Prepending $(prefix) +when installing safe_camlp4 (thanks to Daniel Janus)

    +

    Non-existing -I directories are ignored +(thanks to Nicolas Pouillard)

    +

    A script to create a MacOS X package (thanks to +Pietro Abate)

    +

    Better support for Windows (with help from Robert +Roessler and David Allsopp)

    +

    Support for camlp4 on OCaml 3.10

    +

    Fix: "ocamlfind install" with "-patch" option writes +now correct META file for the case that subpackages occur

    +

    Adding environment variable OCAMLFIND_IGNORE_DUPS_IN +to reduce the number of warnings ocamlfind emits

    +
  • + +
  • +

    1.1.2: Bugfix in the META parser: Backslashes are now +correctly parsed. (Thanks to Martin Jambon for finding this problem.)

    +

    Fixes for platforms that do not support dynamic loading of +DLLs.

    +

    Fixed extraction of camlp4 parameters from packages.

    +
  • + +
  • +

    1.1.1: Bugfixes only: Fixed detection of threading model +for OCaml 3.09. Fixed alternate configuration files.

    +
  • + +
  • +

    1.1: Automatic detection of standard compiler options.

    + +

    Liberated the checks whether a package is already installed.

    + +

    The .opt compilers are entered into findlib.conf if available.

    + +

    New: "install" has -optional switch for optional files.

    + +

    New: "install" has -patch-version to patch the version into +the installed META file.

    + +

    New: "install" has -patch-rmpkg to remove subpackages from +the installed META file.

    + +

    New: "install" has -patch-archives which removes non-existing +files from "archive" variables. This is experimental.

    + +

    New: subpackages can be disabled by exists_if.

    + +

    New: Support for toolchains.

    + +

    Fix for "remove": -destdir works again.

    + +

    Fix for "call": CTRL-C works when calling interactive commands.

    + +

    Fix for preprocessor packages: Dependencies on normal packages +are resolved.

    + +
  • + +
  • 1.0.4: Fix: In previous versions, "ocamlmktop" +set the "toploop" predicate. It turned out, however, that the toploops +generated in this way did not work properly. For this reason, +"ocamlmktop" does not set "toploop" any more for link time, but +instead a new predicate "create_toploop". When the toploop is +executed, the predicate "toploop" is again added.

    +
  • + +
  • 1.0.3: Fix: The relative position of "-cclib -l" + options on the command line is preserved. In previous versions, +these options were moved to the beginning of the argument list. This +did not work for static link editing; dynamic link editing was not +affected.

    +

    Fix: The automatic fixup of "threads" dependencies +works again. In the previous version, this was broken.

    +

    Addition: -format '%(name)' for ocamlfind query.

    +

    Some minor improvements of the documentation.

    +
  • + +
  • 1.0.2: Fix: The alternate package layout did +not fully work. This is repaired now, and there are some clarifications +about relative directory paths in the documentation.

    +
  • + +
  • 1.0.1: Fix: Forgot to install some .cmi +files

    +
  • + +
  • 1.0: It is now possible to divide the +description of a package into subpackages (but there is still only one +META file, but with enhanced syntax). This allows it to describe +intra-package dependencies.

    + +

    Predicates in META files can be negated.

    + +

    The "error" variable allows you to detect conditions under which +the library would not work, and to generate error messages.

    + +

    It is possible to refer to archive files installed in other +packages.

    + +

    The set of predicates is extended by "package predicates" +after the dependency analysis, making conditions expressable that +depend on whether other packages are selected.

    + +

    The "+=" operator in META files adds words to variables rather +than setting them.

    + +

    The "#thread" directive enables multi-threading in toploops and +scripts, if possible.

    + +

    The "#predicates" directive simplifies the addition of predicates. +

    + +

    Queries: The format specifier %D prints the description of +the package. -long-format includes the description. Short options +-r, -l, -d.

    + +

    ocamlfind list -describe prints package descriptions.

    + +

    Support for "ocamlfind ocamldoc". However, the implementation is +quite sloppy.

    + +

    The configuration file is called "findlib.conf" by default, +not "ocamlfind.conf".

    + +

    Removal of "ocamlfind guess".

    + +

    Support for #use "findlib" and #use "ocamlfind" has been +removed. The only remaining way to load findlib is by #use "topfind".

    + +

    There is no longer a thread-safe version of findlib. The user +has to ensure that only one thread uses findlib (which is usually trivial +to achieve).

    + +

    ocamlmktop: Directories are no longer automatically added +to the search path. This did not work anyway, and this change forces +scripts to always invoke "#require" to load/enable libraries, for +better uniformity.

    + +

    Fixes: num-top works. "ocamlfind ocamlopt -thread" generates +a better error message on non-POSIX systems. "ocamlfind query -descendants" +takes predicates into account (it did not do that in previous versions of +findlib).

    +
  • + +
  • 0.9: Changes for OCaml 3.07 (-thread, + -vmthread). Includes Zack's toploop printers for bigints.

    +
  • + +
  • 0.8 - 0.8.1: Renamed a lot of modules to avoid name + clashes with OCaml core modules. Cygwin: Additional option + -cygpath for "configure". The man pages have a NAME + section. Bugfix in Makefile wizard.

    +
  • + +
  • 0.7 - 0.7.2: DLLs: There are now two styles of + installation: DLLs can be installed in the package + directories (like before), or in a shared directory + "stublibs". For the first style, there is now an option + "ldconf" that determines whether the ld.conf file is to be + updated, and if so, which file. The latter style is enabled + by simply creating a directory "stublibs" in the site-lib + directory. (In the first version the directory was called + "libexec". By user request, the name of the DLL directory + has been changed to "stublibs".)

    + +

    "ocamlfind install" preserves now the mtime of the files.

    + +

    "ocamlfind printconf" is more flexible, and easier to call + from scripts.

    + +

    "ocamlfind browser" calls ocamlbrowser with the right -I + options.

    + +

    "ocamlfind query": -descendants implies now -recursive.

    + +

    "ocamlfind ocamldep": -native-filter and -bytecode-filter for more + exact dependency generation.

    + +

    There may be now postinstall and postremove scripts.

    + +

    "ocamlfind pkg/cmd": This syntax can be used to call the program cmd + that is installed in the package directory for pkg. Intended to + simplify the invocation of programs that are installed in package + directories and not in XXX/bin, which may be useful for package- + related tools.

    + +

    Findlib has now a toolbox containing helpful programs besides + ocamlfind. For the beginning, there is a Makefile wizard that + can be called by "ocamlfind findlib/make_wizard".

    + +

    #use "topfind" instead of #use "findlib" to avoid name clashes + in a certain configuration. #use "findlib" and #use "ocamlfind" + are still supported for backward compatibility if the name clash + does not occur.

    + +

    Fix: bytecode threads work again. (The wrong unix library was + linked for recent OCaml versions.)

    + +

    Many smaller improvements; the docs have been updated.

    +
  • + +
  • 0.6 - 0.6.2: Minor changes for Ocaml-3.03-alpha + (and later for 3.04). New #list directive. New: #use + "findlib" loads the findlib directives into every toploop + (Ocaml-3.03-alpha).

    + +

    The file ld.conf is automatically updated when DLLs are + installed or removed.

    + +

    Fix: /tmp/findlib_initf* no longer overflows. The thread + library is now always the first linked library.

    +
  • + +
  • 0.5 - 0.5.4: Findlib has now a configuration + file (see documentation under findlib.conf). Much more + environment variables. The location of the standard library is + now configurable at runtime. +

    + +

    The package search path can now be selected independently + of the package installation directory.

    + +

    New commands: ocamlfind list, ocamlfind printconf, ocamlfind guess + (See documentation under ocamlfind)

    + +

    Optional alternate directory layout: All META files go into + a separate directory (see documentation under site-lib).

    + +

    Findlib works now only for OCaml 3; support for OCaml 2 has been + dropped. As a consequence, the "configure" script could be + simplified; it is no longer necessary to figure out the + linker options.

    + +

    Improved support for camlp4: New directives #camlp4o and + #camlp4r for the toploop.

    + +

    ocamlfind now detects whether two selected packages have + equally named toplevel modules, and prints a warning in this case.

    + +

    There is a downstripped version ocamlfind-mini (see directory + "mini"). This is a one-file script that can be easily + distributed with any software. ocamlfind-mini has reduced + functionality, but it is sufficient to compile and install a + library. (But it does not support using a library.)

    + +

    Support for the Cygwin port of OCaml.

    + +

    Installation of packages: The file permissions are + preserved when files are installed. However, the umask is + applied. The "install" and "remove" subcommands have better + diagnostics.

    + +

    ocamlfind ocamlmktop: Generates now initialization code for the + include path. You don't need to call your toploop with -I + options any more. Furthermore, this fixes some problems with + packages that add printers to the toploop.

    + +

    New: ocamlfind ocamldep. ocamlfind is now prepared for the new + -pp option of ocamldep (upcoming Ocaml 3.03).

    + +

    Installation of findlib: New PREFIX variable in Makefile to + install locally.

    + +

    Fixes: itest. ocamlfind query -descendants works again.

    +
  • + +
  • 0.4: Experimental support for camlp4 (see FAQ + section in the manual). New environment variable + OCAMLFIND_COMMANDS (see ocamlfind(1)). +

    +
  • + +
  • 0.3 - 0.3.1: Necessary updates for OCaml +3. Bugfix: Findlib did not work for bytecode threads. The reason was +that findlib added the directory of the stdlib to the search +path. Works now. +

    +
  • + +
+

Older changes are no longer documented.

+
+
diff --git a/local-packages/ocamlfind/doc/common.xml b/local-packages/ocamlfind/doc/common.xml new file mode 100644 index 0000000..40a5058 --- /dev/null +++ b/local-packages/ocamlfind/doc/common.xml @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Gerd Stolpmann'> + + diff --git a/local-packages/ocamlfind/doc/config.xml b/local-packages/ocamlfind/doc/config.xml new file mode 100644 index 0000000..6af1260 --- /dev/null +++ b/local-packages/ocamlfind/doc/config.xml @@ -0,0 +1,22 @@ + + + + + + + +%readme:html:previous; +%readme:html:up; +%readme:html:next; +'> + +"> + +%bar;"> + + + \ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/TIMESTAMP b/local-packages/ocamlfind/doc/guide-html/TIMESTAMP new file mode 100644 index 0000000..e69de29 diff --git a/local-packages/ocamlfind/doc/guide-html/c161.html b/local-packages/ocamlfind/doc/guide-html/c161.html new file mode 100644 index 0000000..84d36ac --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/c161.html @@ -0,0 +1,232 @@ + +Dependency analysis of packages
The findlib User's Guide
PrevNext

Chapter 3. Dependency analysis of packages

Querying ancestors

Every package denotes in its META file only the list of direct +ancestors. The theoretical model of the dependency relation is a +directed acyclic graph (DAG), with the packages as vertices and edges +from packages to their direct ancestors. The graph must be acyclic +because OCaml does not allow cyclic dependencies between modules.

What happens if you query something like

ocamlfind query -recursive p1 p2 ... pN

is that the named packages p1 to pN are marked in the graph, and that +repeatedly all direct ancestors of marked packages are marked, too, +until there is not any marked package remaining with an unmarked +ancestor. All marked packages are then printed in topological +order. This simply means that for the printed packages p1 to pM holds +that if pI is printed before pJ then pI is a (possibly indirect) +ancestor of pJ.

The topological order plays a role when the link command is +constructed by "ocamlfind ocamlc", as Ocaml requires that archives +must be linked in topological order. For example, the link statement

ocamlfind ocamlc -o another -package q -linkpkg another.ml

must be turned into the effective command

ocamlc -o another [...more options...] p.cma q.cma another.ml

and not

ocamlc -o another [...more options...] q.cma p.cma another.ml

because there are references from q.cma to p.cma.

In C, there is a similar requirement when linking static archives. The +linker backend ld wants the archives in reversed +topological order, i.e. the deepest ancestor must come last in the +list of linked archives. Because of this, the additional linker +options specified in the "linkopts" variable are passed in reversed +order to the underlying linker. This means that you can refer to C +libraries of ancestor packages of p in C libraries provided in p.

Note that most operating systems do not require any specific order for +dynamically linked C libraries (the exception is, surprise!, AIX).


PrevHomeNext
Linker optionsUpQuerying descendants
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/c192.html b/local-packages/ocamlfind/doc/guide-html/c192.html new file mode 100644 index 0000000..982a1b4 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/c192.html @@ -0,0 +1,300 @@ + +A new frontend for ocamlc
The findlib User's Guide
PrevNext

Chapter 4. A new frontend for ocamlc

Compiling and linking

There are compiler frontends for the four compilers ocamlc, ocamlopt, +ocamlmktop, and ocamlcp. They are simply called by specifying the name +of the compiler as first argument to ocamlfind, i.e.

ocamlfind ocamlc ...arguments...
+ocamlfind ocamlopt ...arguments...
+ocamlfind ocamlmktop ...arguments...
+ocamlfind ocamlcp ...arguments...

In addition to the compiler options handled by the compilers +themselves, the following options are available:

  • -package <name>: Causes that the package <name> is added to +the package list, and that -I options are added for every package, and +all direct or indirect ancestors.

  • -linkpkg: Causes that the archives of the packages in the package list +and all their direct or indirect ancestors are added in topological +order to the command line before the first file to compile or to +link. Packages specified by -dontlink are not linked in, though. +Furthermore, the linker options of these packages are added in +reverse topological order at the end of the command line.

  • -predicates <predicate-list>: The named predicates are included +in the list of predicates. Note that there are some predicates set by +default, see below.

  • -dontlink <name>: Specifies that the package <name> and +all its direct or indirect ancestors should not be linked in.

  • -passopt <opt>: The option <opt> is passed directly to the +underlying compiler. This is especially needed to pass undocumented +options to the compiler.

If you only want to compile, i.e. the -c option is in effect, you +normally only need the -package option.

Depending on the compiler and on the given options, some predicates +are set by default:

  • byte: The predicate "byte" is set when ocamlc, ocamlcp, or ocamlmktop +is used to compile or link.

  • native: The predicate "native" is set when ocamlopt is used to compile +or to link.

  • toploop: The predicate "toploop" is set when a toploop is being executed

  • create_toploop: The predicate "toploop" is set when ocamlmktop is used to +compile or to link a toploop

  • gprof: The predicate "gprof" is set when ocamlopt with -p option is +invoked.

  • mt: The predicate "mt" is set when the -thread or the -vmthread option is in effect.

  • mt_posix: The predicate "mt_posix" is set together with "mt" if the +POSIX thread implementation is selected.

  • mt_vm: The predicate "mt_vm" is set together with "mt" if the bytecode +thread implementation is selected.

  • autolink: The predicate "autolink" is set if the OCaml compiler can perform +automatic linking. This predicate is never set if the -noautolink option is +in effect.


PrevHomeNext
Querying descendantsUpToploops and runtime systems
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/c278.html b/local-packages/ocamlfind/doc/guide-html/c278.html new file mode 100644 index 0000000..fc07768 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/c278.html @@ -0,0 +1,308 @@ + +Complex packages
The findlib User's Guide
PrevNext

Chapter 5. Complex packages

The standard predicates

Settings in the META file have usually the form:

varname ( predname1, predname2, ... ) = "value"

The names in the parantheses are called formal +predicates and express a condition which must hold such +that the value on the right side is selected. When querying +information you can specify a set of actual +predicates that are assumed to be true. There are the +following standard predicates:

  • The "byte" predicate means that the bytecode compiler is used.

  • The "native" predicate means that the native compiler is used.

  • The "toploop" predicate means that the toploop is available in the +linked program.

  • The "mt" predicate means that the program is multi-threaded.

  • The "mt_posix" predicate means that in the case "mt" is set, too, the +POSIX libraries are used to implement threads.

  • The "mt_vm" predicate means that in the case "mt" is set, too, the +VM-based libraries are used to implement threads.

  • The "gprof" predicate means that in the case "native" is set, too, the +program is compiled for profiling

  • The "autolink" predicate indicates that ocamlc is able to perform +automatic linking.

It is possible to have more predicates indicating different +environments; just use them, it is not necessary to declare them +anywhere.

The value which is selected for a variable depends on the set of +assumed predicates. In order to get selected, all formal predicates +must be included in the set of actual predicates; if still +multiple values fulfill this condition, the value with the maximum +number of formal predicates is used; and if still in doubt, the first +of these in the META file is taken.

It is possible to negate a formal predicate: Just prepend a minus +sign to it, e.g. var(p,-q). In this case, it is required that the +negated predicates are false (not contained in the set of actual predicates).

For all variables that are evaluated after the dependency analysis, +findlib adds the so-called package predicates to the set of actual +predicates. For every selected package p the predicate pkg_p +(with the fixed prefix "pkg_") is added. One application of this +are compatibility checks: The special error variable +is evaluated after dependency analysis, but before anything else +is done. For example, to state that package p is incompatible with +package q one can add to the META file of p: + +

error(pkg_q) = "Package p is incompatible with q"
+ +The value of error is printed as message in the +case the condition is true.


PrevHomeNext
Support for gprof-enabled modulesUpDefining additional predicates
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/c37.html b/local-packages/ocamlfind/doc/guide-html/c37.html new file mode 100644 index 0000000..0212e14 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/c37.html @@ -0,0 +1,309 @@ + +Libraries and Packages
The findlib User's Guide
PrevNext

Chapter 1. Libraries and Packages

Reusability is one of the keywords in software engineering +today. It simply means to have source code that can be shared by +several programs. Usually, modules are combined to libraries, and the +library archive files can be linked into programs. As the idea might +be simple, its practical implementation is complex because sharing of +source code has an impact on all steps and phases in software +production. This document only addresses the following administrative +problems:

  • Storing the libraries in file hierarchies

  • Compiling and linking programs using such libraries

  • Managing dependencies between libraries

Objective Caml has a variety of language means to support +reusability. Most important, polymorphic functions can be written +which generalize the types of input arguments and the +type of the result value. There are many examples in the core library +such that I assume that the reader is familiar with this +feature. Second, modules and functors must be mentioned which not only +generalize types of values, but can even generalize structures, +i.e. types with associated operations. Third, the class construct +allows us to adopt the object-oriented techniques of abstraction such +as inheritage and dynamic method lookup.

In the following, we are only analyzing the problem of making and +using libraries from a purely software-technical point of view. This +means, we ignore how to make functions polymorphic, and how to create +functors and classes. Instead, we only look at how to invoke the +OCaml compiler to create, manage, and use libraries. Especially, we +are interested in the administration of systems of libraries that +have dependencies.

One of the complex operations on such a system is the replacement of +a library by a newer version. Because of the strict compatibility +checks of OCaml, it is usually necessary to rebuild and reinstall +all dependent libraries as well. With the help of findlib, one can +find out which are the dependent libraries. (However, findlib does +not provide a framework to rebuild them. For example, the GODI +system includes such a framework.)

The library is also called a "package" when it is seen as a removeable +and replaceable set of files. Findlib requires that there is a +certain directory structure; it is not possible to install the files +at arbitrary places (findlib does not even maintain a file list). +For simplicity, every library is usually stored into its own +directory, i.e. the library archive files and the interface files.

From the perspective of the compiler, the library is made +accessible by adding the package directory to the search path +of the compiler. By doing so, the modules of the library are +added to the namespace universe, and thus can be opened by +modules using them. This means that the approach "one package += one directory" can be naturally translated into language +operations modifying the namespace scope.

When linking a program, it must be specified which link operation is +necessary to use a certain library. Often, only a single archive file +needs to be linked in, but sometimes additional archives or system +libraries must be linked, too. Furthermore, the link operations +often depends on certain conditions, e.g. whether a single- or +multi-threaded program is being created.

The findlib library is my suggestion for a +package manager suitable for Objective Caml. It is a library (stored +as a package itself) which can answer the following questions:

  • If I want to use a package, which is the directory containing +the compiled interfaces and implementations? - The package directory +may vary from system to system, and this feature makes it easier to +write Makefiles that run everywhere. Furthermore, OCaml can load +modules dynamically, and it is not a good practice to compile in the +location of such modules. The better way is to ask findlib where the +module resides today.

  • Which other packages must be linked in, too, if I want to use a +certain package?

  • Which archives need to be linked in, and which compiler options +are necessary?

  • If there is a version of the archive with additional properties, +which file should I use? - Additional properties are at least: +Thread-safety, using POSIX threads, and being gprof-enabled. It is +simple to add more criterions.

Furthermore, there is a frontend for this library called +ocamlfind. It is a command-line interface for the +library, but has also some additional abilities:

  • It can invoke ocamlc, ocamlopt, ocamlmktop, and ocamlcp such +that compiler arguments necessary to use a package or link it in are +automatically added.

  • It can install and uninstall packages.

  • It can find out dependent packages.

As you'll see in the following chapters, the usage of this library is +really simple. If you want only to link in packages written by other +people, you must only change the command that invokes the compiler, +e.g. instead of calling "ocamlc program.ml" invoke "ocamlfind ocamlc +-package name_of_package_to_use -linkpkg program.ml", and you can +refer to the named package within program.ml. If you want to turn your +collection of modules into a package, you need only to write one +adminstrative file (META) containing all extra information such as +required other packages.


PrevHomeNext
User's GuideUpUsing packages
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/c395.html b/local-packages/ocamlfind/doc/guide-html/c395.html new file mode 100644 index 0000000..9d679e5 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/c395.html @@ -0,0 +1,204 @@ + +How to create your own packages
The findlib User's Guide
PrevNext

Chapter 6. How to create your own packages

Installing and removing packages

The ocamlfind command can install and remove packages. For example, +to install a package p containing the files META, m1.cmi, m2.cmi, p.cma, +run + +

ocamlfind install p META m1.cmi m2.cmi p.cma
+ +This installs the files into the default location for new packages +(set in ocamlfind.conf). If you have files that are not always built, +add these after the -optional switch: + +
ocamlfind install p META m1.cmi m2.cmi p.cma -optional p.cmxa p.cmxs
+ +To remove the package, run + +
ocamlfind remove p
+ +Note that every package must have a META file, it is not possible to +omit it.


PrevHomeNext
LintUpChange your Makefile
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/c429.html b/local-packages/ocamlfind/doc/guide-html/c429.html new file mode 100644 index 0000000..df63bf6 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/c429.html @@ -0,0 +1,250 @@ + +FAQs
The findlib User's Guide
PrevNext

Chapter 7. FAQs

Does findlib support the autolink feature of OCaml 3?

Short answer: Findlib is compatible with autolink

The new archive format introduced with OCaml 3 can store the linker options +that are necessary to link an archive. For example: + +

ocamlc -a -o myarchive.cma mymodule.cmo -cclib -lmylibrary
+ +This command does not only create the new archive +myarchive.cma, but it also writes into a special section of +that file that the linker option -cclib -lmylibrary is +necessary to link this archive.

This means for findlib that most of the "linkopts" attributes in META files +have become superflous: The compiler itself already knows the linker options, +we do not need to tell the compiler the options. We could simply leave all +"linkopts" attributes out.

Of course, the "linkopts" feature of findlib still works. This is necessary +because findlib should keep the compatibility with older software, and because +"linkopts" is more powerful (you can have conditional linker options).

If you have software that must run in both OCaml 2 and OCaml 3 environments, +you can make your "linkopts" attribute dependent on the "autolink" +predicate. For example: + +

linkopts = "-cclib -lmylibrary"
+linkopts(autolink) = ""
+ +The findlib installation for OCaml 3 will take the second line which is +reasonable because ocamlc already knows how to link; the installation for +OCaml 2 never sets the "autolink" predicate and therefore uses the first line.


PrevHomeNext
Using the Makefile wizardUpWhy does findlib not automatically include the -custom option if +linked with C code?
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/c74.html b/local-packages/ocamlfind/doc/guide-html/c74.html new file mode 100644 index 0000000..c672d81 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/c74.html @@ -0,0 +1,211 @@ + +Using packages
The findlib User's Guide
PrevNext

Chapter 2. Using packages

Listing the installed packages

You can list which packages are installed by executing + +

ocamlfind list
+ +You will get a list of names and version numbers. You can get a bit +more information by passing the -describe option: + +
ocamlfind list -describe


PrevHomeNext
Libraries and PackagesUpLooking up package directories
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/index.html b/local-packages/ocamlfind/doc/guide-html/index.html new file mode 100644 index 0000000..0843076 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/index.html @@ -0,0 +1,430 @@ + +The findlib User's Guide

The findlib User's Guide

Gerd Stolpmann

Copyright © 1999-2014 Gerd Stolpmann

The "findlib" library provides a scheme to manage reusable software +components (packages), and includes tools that support this +scheme. Packages are collections of OCaml modules for which +metainformation can be stored. The packages are kept in the filesystem +hierarchy, but with strict directory structure. The library contains +functions to look the directory up that stores a package, to query +metainformation about a package, and to retrieve dependency +information about multiple packages. There is also a tool that allows +the user to enter queries on the command-line. In order to simplify +compilation and linkage, there are new frontends of the various OCaml +compilers that can directly deal with packages.

Together with the packages metainformation is stored. This includes a +version string, the archives the package consists of, and additional +linker options. Packages can also be dependent on other +packages. There is a query which finds out all predecessors of a list +of packages and sorts them topologically. The new compiler frontends +do this implicitly.

Metainformation can be conditional, i.e. depend on a set of +predicates. This is mainly used to be able to react on certain +properties of the environment, such as if the bytecode or the native +compiler is invoked, if the application is multi-threaded, and a few +more. If the new compiler frontends are used, most predicates are +found out automatically.

There is special support for scripts. A new directive, "#require", +loads packages into scripts.

Download findlib. This manual describes version 1.5 of the software +package. It can be downloaded at +http://download.camlcity.org/download. The user's guide and the reference manual are included. +Newest releases of "findlib" will be announced in +The OCaml Link +Database.

Quickstart. See also the Quickstart page +for instructions for the most common +cases.

License

This document, and the described software, "findlib", are copyright by +Gerd Stolpmann.

Permission is hereby granted, free of charge, to any person obtaining +a copy of this document and the "findlib" software (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions:

The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software.

The Software is provided ``as is'', without warranty of any kind, express +or implied, including but not limited to the warranties of +merchantability, fitness for a particular purpose and noninfringement. +In no event shall Gerd Stolpmann be liable for any claim, damages or +other liability, whether in an action of contract, tort or otherwise, +arising from, out of or in connection with the Software or the use or +other dealings in the software.


Table of Contents
I. User's Guide
1. Libraries and Packages
2. Using packages
Listing the installed packages
Looking up package directories
How a package directory looks like
Querying information stored in META files
How to compile and link a program that uses a package
Dependencies
Linker options
3. Dependency analysis of packages
Querying ancestors
Querying descendants
4. A new frontend for ocamlc
Compiling and linking
Toploops and runtime systems
Multi-threaded applications
Support for gprof-enabled modules
5. Complex packages
The standard predicates
Defining additional predicates
Appending to variables
Subpackages
Glue code
Plugins
Lint
6. How to create your own packages
Installing and removing packages
Change your Makefile
Using the Makefile wizard
7. FAQs
Does findlib support the autolink feature of OCaml 3?
Why does findlib not automatically include the -custom option if +linked with C code?
Does findlib support linking of applications as well as +packages?
Does Findlib support camlp4?
Does Findlib support ppx-style preprocessors?
Why do some people install the .cmx files?
How do I express conflicts?

  Next
  User's Guide
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/p35.html b/local-packages/ocamlfind/doc/guide-html/p35.html new file mode 100644 index 0000000..93ab443 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/p35.html @@ -0,0 +1,184 @@ + +User's Guide
The findlib User's Guide
PrevNext


PrevHomeNext
The findlib User's Guide Libraries and Packages
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/quickstart.html b/local-packages/ocamlfind/doc/guide-html/quickstart.html new file mode 100644 index 0000000..10d3656 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/quickstart.html @@ -0,0 +1,278 @@ + +
+QUICKSTART - The most important ways to use findlib
+ + + + + +
 up 

QUICKSTART - The most important ways to use findlib

+

+Intro +

+See the file INSTALL for instructions how to build and install +findlib. +

+Findlib and the toploop +

+For a number of platforms, OCaml can load bytecode-compiled +libraries dynamically. For these platforms, findlib is very simple to +use as explained in the following. For other platforms, see the paragraph +below about "custom toploops". +

+After the toploop has been started, it is possible to load the special +findlib support:[1] + +

+$ ocaml
+        Objective Caml version 3.07
+
+# #use "topfind";;
+Findlib has been successfully loaded. Additional directives:
+  #require "package";;      to load a package
+  #list;;                   to list the available packages
+  #camlp4o;;                to load camlp4 (standard syntax)
+  #camlp4r;;                to load camlp4 (revised syntax)
+  #predicates "p,q,...";;   to set these predicates
+  Topfind.reset();;         to force that packages will be reloaded
+  #thread;;                 to enable threads
+
+- : unit = ()
+

+ +You can now list the available packages: + +

+# #list;;
+bigarray            (version: [distributed with Ocaml])
+camlp4              (version: Camlp4 version 3.03 ALPHA)
+dbm                 (version: [distributed with Ocaml])
+dynlink             (version: [distributed with Ocaml])
+findlib             (version: 0.6)
+graphics            (version: [distributed with Ocaml])
+labltk              (version: [distributed with Ocaml])
+netstring           (version: 0.10)
+num                 (version: [distributed with Ocaml])
+stdlib              (version: [distributed with Ocaml])
+str                 (version: [distributed with Ocaml])
+threads             (version: [distributed with Ocaml])
+unix                (version: [distributed with Ocaml])
+xstrp4              (version: 1.1)
+

+ +and load packages by simply typing: + +

+# #require "netstring";;
+Loading /opt/ocaml/lib/unix.cma
+Loading /opt/ocaml/lib/str.cma
+Loading /opt/ocaml/site-lib/netstring/netstring.cma
+Loading /opt/ocaml/site-lib/netstring/netstring_top.cmo
+

+ +Findlib takes care to load packages that are required by loaded packages +first. For example, "netstring" uses "unix" and "str" internally, but you +do not need to load them because findlib does it for you. In this example +you can also see that findlib loads netstring_top.cmo containing printers +for the toploop. +

+You can also enable the Camlp4 parsers by simply typing + +

+# #camlp4o;;
+Loading /opt/ocaml-3.03a/lib/camlp4/camlp4o.cma
+        Camlp4 Parsing version 3.03 ALPHA
+

+ +for the standard syntax or + +

+# #camlp4r;;
+Loading /opt/ocaml-3.03a/lib/camlp4/camlp4r.cma
+        Camlp4 Parsing version 3.03 ALPHA
+

+ +for the revised syntax. (But you cannot switch between the syntaxes.) + +

+Custom Toploops +

+For some platforms, OCaml does not implement loading external +libraries (e.g. Cygwin). One has to create a so-called custom toploop +that statically links with these libraries. Example: + +

+$ ocamlfind ocamlmktop -o mytop -package findlib,unix -linkpkg
+$ ./mytop
+        Objective Caml version 3.07
+ 
+# #use "topfind";;
+Findlib has been successfully loaded. Additional directives:
+  #require "package";;      to load a package
+  #list;;                   to list the available packages
+  #camlp4o;;                to load camlp4 (standard syntax)
+  #camlp4r;;                to load camlp4 (revised syntax)
+  #predicates "p,q,...";;   to set these predicates
+  Topfind.reset();;         to force that packages will be reloaded
+  #thread;;                 to enable threads
+
+- : unit = ()
+

+ +Now "#require" works for all libraries referring to the special "unix" +functions. + +

+Findlib and scripts +

+The #require directive can also be used in scripts. Example: + +

+#use "topfind";;
+#require "netstring";;
+
+open Cgi;;
+...
+

+ +This makes it possible to write scripts that do not contain #directory +directives that are specific for certain installations. +

+For Unix environments, you can start scripts directly if you +apply the following trick: + +

+#! /bin/sh
+# (*
+exec ocaml "$0" "$@"
+*) use "topfind";;
+#require "netstring";;
+
+open Cgi;;
+...
+

+ +This works wherever OCaml is installed. +

+Compiling programs +

+Assumed you want to compile a program that uses the Netstring package. +Do it the following way: + +

+$ ocamlfind ocamlc -package netstring -c myprogram.ml
+

+ +This way you do not need to add "-I" options to locate Netstring. +

+If you want to create an executable, do not forget to add the +-linkpkg switch: + +

+$ ocamlfind ocamlc -o myprogram -package netstring -linkpkg myprogram.cmo
+

+ +This switch causes that the mentioned packages are added to the resulting +executable. +

+If you want to include several packages, you can either add several +"-package" options, or you can enumerate the packages separated by commas: +-package netstring,labltk. +

+Camlp4 +

+If you add a -syntax option, the compiler will be told to parse the +source file using camlp4: + +

+$ ocamlfind ocamlc -package netstring -syntax camlp4o -c myprogram.ml
+

+ +Use -syntax camlp4o for the standard syntax or -syntax camlp4r for the +revised syntax. +

+Additionally, you can mention packages that add new syntax features. +The package xstrp4 is an example of this: + +

+$ ocamlfind ocamlc -package xstrp4,netstring -syntax camlp4o -c myprogram.ml
+

+ +Now you can use the $ notation that is implemented by xstrp4 in the +source file myprogram.ml. +

+Note that you can also invoke ocamldep from ocamlfind: + +

+$ ocamlfind ocamldep -package xstrp4 -syntax camlp4o *.ml *.mli >.depend
+

+ +This enables the syntax extensions, too. +

+ocamlbrowser +

+Since findlib-0.7, it is also possible to start ocamlbrowser from +ocamlfind. For example, + +

+$ ocamlfind browser -package xstrp4
+

+ +adds the correct path specification such that the modules contained in the +package xstrp4 are also displayed. With + +

+$ ocamlfind browser -all
+

+ +all package are added to the path spec. + +

+The Makefile wizard +

+There is a wizard that makes it very easy to write Makefiles. Call the +wizard by +

+$ ocamlfind findlib/make_wizard
+

+(the wizard requires that the labltk library is available). A new window +pops up, and by very few clicks you can describe your own library. Finally, +a Makefile is written. + +

+There is no magic! +

+Findlib is neither a patch of OCaml nor uses it internal features of +the OCaml programming environment. It is only a convention to install +software components in filesystem hierarchies, a library interpreting +this convention, and some frontend applications making the library useable for +you. +

+One important consequence is that you can only refer to those +software components that have previously been installed in a way findlib +understands. This convention is beyond the scope of this QUICKSTART guide, +see the reference manual for details. You can always check whether findlib +accepts a component as "findlib package" by the command + +

+$ ocamlfind list
+

+ +(this is the same as the #list directive in the toploop). If the package +occurs in the list, it is found, otherwise not. +


+
+
[1]
+
In previous versions, #use "findlib" loaded the +library. However, this caused a name conflict for a certain type of +installation. Because of this, the name of the loader script has been changed +to "topfind", but "findlib", and "ocamlfind" (Debian) are also available +for backwards compatibility. +
+
+ + + +
 up 
diff --git a/local-packages/ocamlfind/doc/guide-html/x108.html b/local-packages/ocamlfind/doc/guide-html/x108.html new file mode 100644 index 0000000..81fdd1a --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x108.html @@ -0,0 +1,178 @@ + +Querying information stored in META files
The findlib User's Guide
PrevChapter 2. Using packagesNext

Querying information stored in META files

By setting some options of ocamlfind you can query the variables from +the META files. For example, -long-format (or short -l) selects all +interesting variables:

ocamlfind query -long-format p

This would answer something like:

package:     p
+description: Our super-duper package
+version:     1
+archive(s):
+linkopts:
+location:    /usr/local/lib/ocaml/site-lib/p

The values of the "archive" variable are missing because no predicate +has been set, without further options "ocamlfind query" operates with +an empty set of predicates. To get the bytecode archive, run:

ocamlfind query -long-format -predicates byte p

You can set more than one predicate. It usually does not make sense, but +you could for example select both bytecode and native archives by:

ocamlfind query -long-format -predicates byte,native p

As both settings for "archive" are now equally like, the extraction +mechnism chooses simply the first. The general rule is that the first +most special value is selected.


PrevHomeNext
How a package directory looks likeUpHow to compile and link a program that uses a package
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x119.html b/local-packages/ocamlfind/doc/guide-html/x119.html new file mode 100644 index 0000000..c655269 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x119.html @@ -0,0 +1,255 @@ + +How to compile and link a program that uses a package
The findlib User's Guide
PrevChapter 2. Using packagesNext

How to compile and link a program that uses a package

Now suppose you want to compile a program which calls functions of +your new package p. If prog1.ml, prog2.ml, and prog3.ml are the three +source files the program consists of, compile them with the commands

ocamlfind ocamlc -package p -c prog1.ml
+ocamlfind ocamlc -package p -c prog2.ml
+ocamlfind ocamlc -package p -c prog3.ml

The "ocamlfind ocamlc" invocation is a frontend to "ocamlc". Most +arguments are directly passed to "ocamlc", but there are a few new +options, and often some new options are implicitly added. Here, the +new -package option is used, which adds search paths such that the +modules of package p are found. Effectively, the following direct +ocamlc invocations would be equivalent +[1]:

ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog1.ml
+ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog2.ml
+ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog3.ml

The -I option has the effect that the named directory is also searched +when looking up cmi files. Because of this you can refer directly to +the modules M1 and M2 in the program sources.

In order to link the program use the following command:

ocamlfind ocamlc -o program -package p -linkpkg prog1.cmo prog2.cmo prog3.cmo

The -linkpkg option causes some more arguments to be added to the +constructed ocamlc command. Especially, the name of the archive of p +is extracted from the META file, and automatically inserted before the +prog1.cmo argument. The resulting command looks like[2]:

ocamlc -o program -I /usr/local/lib/ocaml/site-lib/p p.cma prog1.cmo prog2.cmo prog3.cmo

Please note that the bytecode archive p.cma has been selected, and not +the native archive p.cmxa. As it is known that the bytecode compiler +is used, the predicate "byte" is automatically set.

Notes

[1]

If you specify the -verbose option, the constructed +command is printed to the terminal. Actually, there are some more +implicitly added options, especially -ccopt -I<dir> for every +package directory <dir>. This means that you can compile C +programs accessing header files stored in the package directory.

[2]

Again, the actual command contains even some more arguments...


PrevHomeNext
Querying information stored in META filesUpDependencies
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x135.html b/local-packages/ocamlfind/doc/guide-html/x135.html new file mode 100644 index 0000000..de8a756 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x135.html @@ -0,0 +1,213 @@ + +Dependencies
The findlib User's Guide
PrevChapter 2. Using packagesNext

Dependencies

Often packages use other packages themselves. Let q be another package +consisting of the single module M3 which contains references to M1 and +M2. At the first glance, we can ignore this when describing the +package, as we could always add "-package p" and "-package q" options +when compiling programs using q. This solution is not optimal, as the +user of a package must have knowlege about details of the package that +should normally be hidden. When we introduced the notion of packages, +one of the most important properties was that we can replace packages +by improved versions. Imagine that q is replaced by q', but q' uses +not only p but also r. Every program that used q and is now forced to +use q' must be changed (at least in the Makefile) in order to link r, +too. This is clearly not what is intended by packages.

The far better solution is to store dependency information in the META +files. The "requires" variable can list names of packages that are +direct ancestors, i.e. referred directly. (Do not put indirect +ancestors into this variable, for example further packages required by +r when describing q - these are found out automatically.) The META +file of q looks like:

description = "Something that needs p"
+requires = "p"
+version = "1"
+archive(byte) = q.cma
+archive(native) = q.cmxa

If you want to put several package names into "requires", separate +them with commas or spaces.

The "ocamlfind query" command ignores the "requires" value by default, +you must add the -recursive option. In this case, all direct or +indirect ancestors of the packages given on the command line are +selected, too, and printed in topological order. For example, the +command

ocamlfind query -recursive -long-format -predicate byte q

prints two records:

package:     p
+description: Our super-duper package
+version:     1
+archive(s):  p.cma
+linkopts:
+location:    /usr/local/lib/ocaml/site-lib/p
+
+package:     q
+description: Something that needs p
+version:     1
+archive(s):  q.cma
+linkopts:
+location:    /usr/local/lib/ocaml/site-lib/p

Without -recursive, only q would have been printed.

The compiler frontend provided with ocamlfind always works +recursively. In order to compile and link another.ml that uses q, the +following command is sufficient:

ocamlfind ocamlc -o another -package q -linkpkg another.ml

It is not necessary to specify -package p in this statement as the +dependency relation is always used to find out the actually meant +set of packages.


PrevHomeNext
How to compile and link a program that uses a packageUpLinker options
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x149.html b/local-packages/ocamlfind/doc/guide-html/x149.html new file mode 100644 index 0000000..fb4dcd0 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x149.html @@ -0,0 +1,200 @@ + +Linker options
The findlib User's Guide
PrevChapter 2. Using packagesNext

Linker options

Beginning with OCaml 3.00, the compiler itself has an interesting feature +called "automatic linking" that makes the following mechanism superflous in +most cases. Automatic linking means that it is possible to store the linker +options into the cma or cmxa file such that the compiler itself knows which +options are necessary. Of course, the following mechanism still works, and it +is still helpful when conditional linking is required.

OCaml has a C interface which means that C libraries can be linked in +and C functions can be declared as new language primitives. Using such +libraries requires special linker options. Some of the core libraries +distributed with OCaml are partly implemented in C and thus additional +libraries must be specified in the linking phase of the program.

For example, the "str" library providing regular expressions requires +to be linked as follows:

ocamlc -o prog str.cma my_file1.cmo my_file2.cmo -cclib -lstr

The -cclib option passes the following argument directly to the +underlying C linker which has the effect that libstr.a is linked in, +too. The "-cclib -lstr" is directly associated with str.cma as the +latter simply cannot be used without the former. Assume you would +write a META file describing str. That "str.cma" should be linked in +as archive is clear; the "-cclib -lstr" can be specified in another +variable called "linkopts". The META file would look like:

requires = ""
+version = "str from ocaml 2.02"
+archive(byte) = "str.cma"
+archive(native) = "str.cmxa"
+linkopts = "-cclib -lstr"

This has the effect that specifying -linkpkg in one of the compiler +frontends not only chooses one of the archive files, but also extracts +the necessary linker options from the META file. The above example can +also be compiled with:

ocamlfind ocamlc -o prog -package str -linkpkg my_file1.cmo my_file2.cmo

Most people will never write META files with "linkopts" settings. But +this feature is very useful at least for the core libraries such as +str. Because of this, the "findlib" distribution comes with META files +for the core libraries in order to hide the linker options. This +means that you can already use the packages "str", "dbm", "dynlink", +"graphics", "num", "threads", "unix", and "camltk", and that the +appropriate archives and linker options are automatically extracted.


PrevHomeNext
DependenciesUpDependency analysis of packages
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x180.html b/local-packages/ocamlfind/doc/guide-html/x180.html new file mode 100644 index 0000000..24670f6 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x180.html @@ -0,0 +1,184 @@ + +Querying descendants
The findlib User's Guide
PrevChapter 3. Dependency analysis of packagesNext

Querying descendants

It is often useful to find out the descendants of a package, i.e. all +direct or indirect users of the package. There is another "ocamlfind" +subcommand that allows us to query descendants. For example, to get +the direct and indirect users of p, type in

ocamlfind query -descendants p

The set of packages that are possible descendants is determined as +follows: + +

  • All packages located in directories mentioned in the environment +variable OCAMLPATH are candidates. Note that only package directories +containing META files are taken.

  • The packages in the default package directory are candidates, too.

  • If there are two packages with the same name, only the first +counts, i.e. the first in OCAMLPATH, then the one in the default directory.

+ +After this set has been determined, the complete dependency graph is +constructed on it. As the descendants are queried, the dependencies +are read in the inverse way compared with queries of the ancestors.


PrevHomeNext
Dependency analysis of packagesUpA new frontend for ocamlc
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x231.html b/local-packages/ocamlfind/doc/guide-html/x231.html new file mode 100644 index 0000000..fff0942 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x231.html @@ -0,0 +1,302 @@ + +Toploops and runtime systems
The findlib User's Guide
PrevChapter 4. A new frontend for ocamlcNext

Toploops and runtime systems

Dynamic toploops

Recent versions of OCaml support dynamic loading of stub libraries +(but only for the more widely used operating systems). This means +that one can start a toploop by running + +

$ ocaml
+        Objective Caml version 3.07+2
+ 
+# _
+ +and that it is now possible to load .cma archive files referring to +shared C libraries ("DLLs"). In older versions of OCaml this was +not possible and one had to create a so-called custom toploop +with the ocamlmktop command. This method is still supported and +explained below; however, nowadays it is often not necessary to +do so. For the modern way, findlib includes a small script called +"topfind" (i.e. "ocamlfind for the toploop") that can be directly +loaded into the toploop: + +
# #use "topfind";;
+- : unit = ()
+Findlib has been successfully loaded. Additional directives:
+  #require "package";;      to load a package
+  #list;;                   to list the available packages
+  #camlp4o;;                to load camlp4 (standard syntax)
+  #camlp4r;;                to load camlp4 (revised syntax)
+  #predicates "p,q,...";;   to set these predicates
+  Topfind.reset();;         to force that packages will be reloaded
+  #thread;;                 to enable threads
+ 
+- : unit = ()
+# _

A number of additional directives are now available. The "#require" +directive loads additional packages (with all dependencies):

# #require "q1,q2,...,qM";;

"#require" loads the listed packages and all their ancestors in the +right order, but leaves packages out that have already been loaded. +Scripts can now simply load and document which packages are used by a +"#require" directive right at the beginning of the script.

The #list directive lists the available packages as "ocamlfind list" +would do it.

If you need additional predicates, you can set them with #predicates. +Note that this should be done before the first package is loaded in +order to ensure a consistent library system.

The #thread directive enables multi-threading if possible. Note that +this is only supported for installations basing on the POSIX thread +library. (However, if you have only have VM threads, you can still +create a custom toploop supporting threads. See below.) Furthermore, +the #thread directive should be executed before any packages are +loaded.

The #camlp4o and #camlp4r directives load the camlp4 syntax parsers +for the standard and the revised syntax, respectively.

Especially when developing packages, it is sometimes necessary to +reload all dynamically loaded packages in the toploop. This can be +forced by

Topfind.reset();;

which causes the "#require" directive to load all packages again. The +Topfind module implements all the mentioned directives.

Custom toploops

It is very simple to create toploops. In order to make a toploop +executable that includes directly the packages p1,p2,..,pN simply +execute the command

ocamlfind ocamlmktop -o toploop -package p1,p2,...,pN,findlib -linkpkg

(Maybe you have to add the -custom switch.) Note that one of the +packages should be "findlib" itself, because this adds the +additional directives mentioned above, i.e. you can directly use +these directives without #use "topfind" (but running "topfind" +is harmless).

Note that such a toploop includes the code of the packages given +on the commmand line, but that it does not automatically add the +package directories to the search path (in previous versions of +findlib this was tried, but it never really worked). To do so, +you still have to #require the packages.

In order to create a toploop supporting VM-style threads, use the +command + +

ocamlfind ocamlmktop -o toploop -package p1,p2,...,pN,findlib,threads -vmthread -linkpkg
+ +Now the #thread directive will work and enable the access to the +multi-threading modules.

Runtime systems

Building of runtime systems is supported, too. For example, you can run

ocamlfind ocamlc -o runtime -make-runtime -package p1,p2,...,pN -linkpkg

but the problem is which options to specify when a program is linked +for this runtime system. If you executed

ocamlfind ocamlc -o program -use-runtime runtime -package p1,p2,...,pN\
+          -linkpkg m1.cmo ... mM.cmo

it would be tried to link the archives from the packages again into +the bytecode binary. Because of this, it is necessary to suppress +linking in packages of the runtime system when linking binaries for a +runtime system. The -dontlink option can be used for this:

ocamlfind ocamlc -o program -use-runtime runtime -package p1,p2,...,pN\
+          -dontlink p1,p2,...,pN -linkpkg m1.cmo ... mM.cmo

Note that the -package option can enumerate more packages than +-dontlink, and in this case the additional packages are actually +linked in as they are not contained in the runtime system.


PrevHomeNext
A new frontend for ocamlcUpMulti-threaded applications
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x265.html b/local-packages/ocamlfind/doc/guide-html/x265.html new file mode 100644 index 0000000..01b294b --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x265.html @@ -0,0 +1,182 @@ + +Multi-threaded applications
The findlib User's Guide
PrevChapter 4. A new frontend for ocamlcNext

Multi-threaded applications

If an already existing package is planned to be used in a +multi-threaded environment, some language constructs must be replaced +by different ones. For example, global variables must be protected by +locks (mutexes). Because of +this it is common practice to provide two versions of such packages, +one for single-, one for multi-threaded applications (or, another +technique, there is a special add-on module that initializes a +library for multi-threaded usage).

The predicate "mt" should be used to recognize multi-threaded +applications. For example, a package could consist of two archives, +p.cma, and p_mt.cma, where the latter archive is designed for +multi-threaded execution. The META file would contain the following +lines causing that always the appropriate archive is linked:

archive(byte) = "p.cma"
+archive(byte,mt) = "p_mt.cma"

When querying the package database the option "-predicates mt" must be +included in the commands in order to select the appropriate entries.

When compiling or linking it is necessary to specify either the +"-thread" or the "-vmthread" option anyway. The compiler frontends +detects these options, and automatically set the "mt" +predicate. The following command is an example for this; note that the +"threads" package means the standard library of Ocaml providing thread +support:

ocamlfind ocamlc -thread -package threads,p,q -c x.ml

For some operating systems, Ocaml supports the native multithreading +libraries conforming to the POSIX interface. As the linker options are +generally different, another predicate must be set to get these +libraries linked in. The predicate "mt_posix" indicates POSIX +threads while "mt_vm" indicates bytecode (virtual machine) threads.


PrevHomeNext
Toploops and runtime systemsUpSupport for gprof-enabled modules
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x274.html b/local-packages/ocamlfind/doc/guide-html/x274.html new file mode 100644 index 0000000..9111256 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x274.html @@ -0,0 +1,152 @@ + +Support for gprof-enabled modules
The findlib User's Guide
PrevChapter 4. A new frontend for ocamlcNext

Support for gprof-enabled modules

When a program is compiled and linked with ocamlopt, gprof-style +profiling can be enabled by selecting the -p option. This means that +the resulting archives are different, and that it would be useful if +there were another predicate in order to select such archives.

The predicate "gprof" can be used for this. It is automatically set if +the -p option turns on the gprof-mode in an ocamlopt invocation.


PrevHomeNext
Multi-threaded applicationsUpComplex packages
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x311.html b/local-packages/ocamlfind/doc/guide-html/x311.html new file mode 100644 index 0000000..66713f0 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x311.html @@ -0,0 +1,210 @@ + +Defining additional predicates
The findlib User's Guide
PrevChapter 5. Complex packagesNext

Defining additional predicates

Additional predicates can be simply used without any declaration, +i.e. you can freely invent new predicates. One application of them +is to express conditional linkage. For example, one may provide archives +for various conditions, such as a production archive, and a +development archive. A single new predicate, "development", would be +sufficient to express this:

archive(byte) = "p_production.cma"
+archive(byte,development) = "p_development.cma"

When linking, include a "-predicates development" argument in the +compiler command to select the development archive, otherwise the +production archive is taken.

Predicates could also be used to select among several implementations +of the same module. Define simply one predicate per implementation, +e.g. "p_impl1", "p_impl2", and "p_impl3", and specify the archives for +every implementation separately:

archive(byte,p_impl1) = "p_impl1.cma"
+archive(byte,p_impl2) = "p_impl2.cma"
+archive(byte,p_impl3) = "p_impl3.cma"

In the case that the implementations have different dependencies, +simply provide multiple "requires" variables:

requires(p_impl1) = "q"
+requires(p_impl2) = "q,r"
+requires(p_impl3) = "r,s"

Sometimes, the implementations require different linker options. In +this case, define several versions of the "linkopts" variable just +like in the "requires" example.

Note that predicates are global identifiers that can be potentially +applied to every selected package. In the case that a predicate is +only meaningful for a single package, it is common practice to +choose the package name as prefix of the predicate name (e.g. +"netstring_minimum" is a predicate usually only applied to the "netstring" +package).

Predicates could be used to select which features of a library are +linked. For example, + +

archive(byte) = "p_basic.cma"
+archive(byte,p_extension) = "p_basic.cma p_ext.cma"
+ +would add the p_ext.cma archive only if the p_extension predicate +were set. It is considered as bad practice to select +extensions of libraries by predicates. Findlib provides the construct +of subpackages for this purpose.


PrevHomeNext
Complex packagesUpAppending to variables
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x326.html b/local-packages/ocamlfind/doc/guide-html/x326.html new file mode 100644 index 0000000..2294b27 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x326.html @@ -0,0 +1,208 @@ + +Appending to variables
The findlib User's Guide
PrevChapter 5. Complex packagesNext

Appending to variables

The syntax + +

varname ( predname1, predname2, ... ) += "value"
+ +(note the "+=" operator) can be used to append values to variables +depending on whether predicates are true. The "+=" lines in the META +file are evaluated one after the other, and every +line is selected for which the formal predicates are satisfied, +and these lines are added to the current value of the variable. This is +different from the "=" operator where only the most specific +assignment is taken.

The values are considered as space-separated words when they +are appended, i.e. the new words are added to the list of current +words.

For example, in the hypothetic META file + +

var(p) += "a"
+var(p,q) += "b"
+ +the value of var is "a b" if both p and q are true, and the value is +only "a" is only p is true (and the value is empty otherwise). If +the operator "=" had been used, the value would have been only "b" +when both p and q are true.

In the case that there both "=" and "+=" settings for +the same variable, a special algorithm is used: First the most specific +"=" setting is determined, and second all matching "+=" settings are +appended in the order they appear in the file.

Finally, here is a real-world example. Imagine you have an +archive p.cma and a special extension for the toploop, p_top.cma. +Furthermore, there is a special debugging version p_dev.cma that +replaces p.cma during development. You can now simply write + +

archive(byte) = "p.cma"
+archive(byte,development) = "p_dev.cma"
+archive(byte,toploop) += "p_top.cma"
+ +to select either p.cma or p_dev.cma, and append +p_top.cma for toploops to whatever was selected in the first step.


PrevHomeNext
Defining additional predicatesUpSubpackages
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x338.html b/local-packages/ocamlfind/doc/guide-html/x338.html new file mode 100644 index 0000000..34cd860 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x338.html @@ -0,0 +1,199 @@ + +Subpackages
The findlib User's Guide
PrevChapter 5. Complex packagesNext

Subpackages

Sometimes a package consists of several archive files that are closely +related. It is now possible to express dependencies between these +archives by splitting the package into several parts called subpackages. +For example, package p consists of a base archive p_base.cma, and two +extensions p_ext1.cma and p_ext2.cma that both require the base archive +but are independent of each other. This META file expresses this +dependency directly: + +

# META file of package p:
+requires = "p.base"
+
+package "base" (
+  archive(byte) = "p_base.cma"
+)
+
+package "ext1" (
+  requires = "p.base"
+  archive(byte) = "p_ext1.cma"
+)
+
+package "ext2" (
+  requires = "p.base"
+  archive(byte) = "p_ext2.cma"
+)
+ +If installed as package "p", this definition actually defines four +logical packages: "p" (the main package), "p.base", "p.ext1", and +"p.ext2" (the subpackages). These four entities only share the META +file in which they are declared, and the directory where the archive +files are stored, but all other properties can be individually set +for each package. This also means that all package dependencies +must explicitly added by "requires" variables, as there are no +implied dependencies. In this example, the main package and "p.ext1" +and "p.ext2" are all dependent on "p.base".

The users of this installation can refer to all four packages. This +means that + +

ocamlfind ocamlc -package p -linkpkg ...
+ +links only p_base.cma into the final program, while + +
ocamlfind ocamlc -package p.ext1 -linkpkg ...
+ +selects both p_base.cma and p_ext1.cma.


PrevHomeNext
Appending to variablesUpGlue code
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x345.html b/local-packages/ocamlfind/doc/guide-html/x345.html new file mode 100644 index 0000000..845402c --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x345.html @@ -0,0 +1,191 @@ + +Glue code
The findlib User's Guide
PrevChapter 5. Complex packagesNext

Glue code

Imagine we have two packages p and q that are normally +independent, i.e. one can link p without q, and q without p. However, +when both p and q are used in the same program, it is expected that +they cooperate with each other. Of course, this situation can be +modeled with the help of subpackages (a real-world example of this are +p=lablgtk and q=lablgl).

The idea is as follows: p has a subpackage p.for_q that contains +code with special features for q, and q has a subpackage q.use_p that +depends on p, p.for_q, and q, and that contains the code using the +special features of p. Expressed in META files, p would define + +

# META file for p:
+requires = "..."
+archive = "..."
+
+package "for_q" (
+  requires = "p"
+  archive = "..."
+)
+ +and q would define + +
# META file for q:
+requires = "..."
+archive = "..."
+
+package "use_p" (
+  requires = "q,p.for_q"
+  archive = "..."
+)
+ +Of couse, the program using both libraries must explicitly enable +the subpackages by mentioning "q.use_p" on the ocamlfind command line, +otherwise the glue code would be omitted.

Unfortunately, it is not possible to use the package predicates +pkg_p and pkg_q to add archives depending on whether the other +package is also selected. The problem is that the order cannot +be specified, i.e. whether p must be linked first or q.


PrevHomeNext
SubpackagesUpPlugins
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x352.html b/local-packages/ocamlfind/doc/guide-html/x352.html new file mode 100644 index 0000000..8a3f912 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x352.html @@ -0,0 +1,295 @@ + +Plugins
The findlib User's Guide
PrevChapter 5. Complex packagesNext

Plugins

(Since findlib-1.6.)

Plugins are packages that can be loaded at runtime. Plugins are +intended as a mechanism for loading add-on code into +executables. Technically, there is some overlap with the concept of a +"shared library". Note, however, that there is no universal support +for plugins, as it is unimplemented on some platforms, and only +poorly on some others (including x86 in the 32 bit case). Also, there +must always be an explicit "load" statement in the loading executable. +You cannot link an executable directly against plugins.

Preparing a plugin

For bytecode there is no problem to load cma files at runtime. +For native-code, though, you need to convert cmxa files into cmxs +files first:

ocamlopt -shared -linkall -o m.cmxs m.cmxa

As mentioned, be prepared that this command fails on platforms where +plugins are unavailable.

The cmxs files can then be referenced from META. We don't use +the "archive" variable in this case but "plugin":

plugin(byte) = "m.cma"
+plugin(native) = "m.cmxs"

Before findlib-1.6, there was some half-official convention using the +"plugin" predicate. This is still supported, but deprecated:

archive(byte) = "m.cma"
+archive(native,plugin) = "m.cmxs"

Load-time dependencies

Plugins can be, of course, be dependent on other +plugins. You run into a problem, though, when you make a plugin dependent +on a package that doesn't qualify as plugin (i.e. lacks the "plugin" +definition). In this case, the loader simply skips the dependency, +and you cannot load the plugin.

Because of this dependency issue, it is recommended to add the +"plugin" variable to all packages that are installed on a system, +because this does not only allow it to load all packages at runtime, but +also to use these packages as dependency of the actual plugin code.

That said, you just need to add a "requires" directive, e.g. + +

requires = "pkg1"
+plugin(byte) = "m.cma"
+plugin(native) = "m.cmxs"

How to load a plugin

Linking an executable that can load a plugin: An executable +must link the package "findlib.dynload". This does not only add +the loader, but also special initialization code to the executable:

ocamlfind ocamlopt -o program -package findlib.dynload -linkpkg ...

In particular, this records the packages that are already included +into the executable (in-core packages). If a plugin is now dependent +on such a package, this is recognized, and the package is not loaded +(which would not work anyway).

Now, you can load a plugin "foo" with:

Fl_dynload.load_packages ["foo"]

This loads the cma or cmxs files, and runs the initialization code +of all top-level definitions of the included modules.

Of course, you can also call load_packages from +a library if "findlib.dynload" is a required package of the library +package.

Fat plugins

Sometimes it is handy to create plugins that already include all +the required packages. The plugin acts more like a dynamically loadable +executable that already includes whatever it needs. You can create such +a "fat" plugin with: + +

ocamlfind ocamlopt -shared -linkpkg -linkall -o m.cmxs -package p1,p2,p3 m.cmxa
+ +In this case, the "requires" line in the META file should remain empty.

Note, however, that you cannot handle packages this way that are already +linked into the main program, because it is invalid to load a module that +is already part of the main executable. Let's assume that the executable +links in q1, q2, and q3. Then, you need to exclude these packages from the +plugin. The -dont-link option comes handy in this case: + +

ocamlfind ocamlopt -shared -linkpkg -linkall -o m.cmxs -package p1,p2,p3 -dont-link q1,q2,q3 m.cmxa
+ +This excludes q1,q2,q3 even if these packages occur as dependencies of +p1,p2,p3. In this case, though, you need to put q1,q2,q3 into the "requires" +field of META.


PrevHomeNext
Glue codeUpLint
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x388.html b/local-packages/ocamlfind/doc/guide-html/x388.html new file mode 100644 index 0000000..47a06bf --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x388.html @@ -0,0 +1,172 @@ + +Lint
The findlib User's Guide
PrevChapter 5. Complex packagesNext

Lint

(Since findlib-1.6.)

As it has become more and more complicated to write correct META files +there is now some support for recognizing typical problems. Just use + +

ocamlfind lint META
+ +to check the file META in the current directory. The tool reports problematic +lines in META, e.g. + +
archive(byte,plugin) = "oUnit.cma"
+This specification of dynamic loading is deprecated, you should add a "plugin(...)" variable.
+
+archive(native,plugin) = "oUnit.cmxs"
+This specification of dynamic loading is deprecated, you should add a "plugin(...)" variable.


PrevHomeNext
PluginsUpHow to create your own packages
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x403.html b/local-packages/ocamlfind/doc/guide-html/x403.html new file mode 100644 index 0000000..e8aaa69 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x403.html @@ -0,0 +1,248 @@ + +Change your Makefile
The findlib User's Guide
PrevChapter 6. How to create your own packagesNext

Change your Makefile

Here is a commented version of a Makefile that may be used to compile +and link a package. It describes the frequent case that the package +simply consists of a bundle of modules that are dependent on other +packages.

First, some general definitions. NAME is the name of the package. The +OBJECTS variable enumerates the bytecode objects, whereas XOBJECTS +names the native objects. The same naming convention is used for +ARCHIVE and XARCHIVE, specifying the resulting bytecode, resp. native +archive file. The REQUIRES variable lists the names of the packages +that are needed for this package. If you need additional predicates, +put them into the PREDICATES variable.

NAME     = p
+
+OCAMLC   = ocamlfind ocamlc
+OCAMLOPT = ocamlfind ocamlopt
+OCAMLDEP = ocamldep
+
+OBJECTS  = p1.cmo p2.cmo
+XOBJECTS = p1.cmx p2.cmx
+
+ARCHIVE  = $(NAME).cma
+XARCHIVE = $(NAME).cmxa
+SARCHIVE = $(NAME).cmxs
+
+REQUIRES = unix str q r s
+PREDICATES =

The default goal is "all", causing the bytecode archive to be +created. In order to get a native archive, choose "opt" as second goal. +(The ".PHONY" line is a declaration meaningful for GNU-make; "all" and +"opt" are only virtual goals as there no files "all", or "opt" which +is indicated by making them dependents of ".PHONY".)

.PHONY: all opt
+all: $(ARCHIVE)
+opt: $(XARCHIVE) $(SARCHIVE)

The following two rules create the bytecode resp. native archive from +the objects.

$(ARCHIVE): $(OBJECTS)
+        $(OCAMLC) -a -o $(ARCHIVE) -package "$(REQUIRES)" -linkpkg \
+	          -predicates "$(PREDICATES)" $(OBJECTS)
+$(XARCHIVE): $(XOBJECTS)
+        $(OCAMLOPT) -a -o $(XARCHIVE) -package "$(REQUIRES)" -linkpkg \
+	          -predicates "$(PREDICATES)" $(XOBJECTS)
+
+$(SARCHIVE): $(XARCHIVE)
+        $(OCAMLOPT) -shared -o $(SARCHIVE) $(XARCHIVE) || true

Note that the cmxs archive is optional: we just ignore the error +when it cannot be built.

These rules compile the modules independently. The lines similar to +".ml.cmo" must be read: "How to transform files with suffix .ml into +files with suffix .cmo". The corresponding command can refer to the +input file as "$<" and to the output file(s) as "$@".

.SUFFIXES: .cmo .cmi .cmx .ml .mli
+
+.ml.cmo:
+        $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \
+                  -c $<
+.mli.cmi:
+        $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \
+                  -c $<
+.ml.cmx:
+        $(OCAMLOPT) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \
+                  -c $<

The "depend" goal is the file describing the dependencies within the +package; it is created by ocamldep.

depend: *.ml *.mli
+         $(OCAMLDEP) *.ml *.mli >depend
+include depend

The "install" rule is a bit tricky. First it is tested if there is a +native archive to install, and if so, the variable "extra" contains +the corresponding files. The "ocamlfind install" command creates a new +package directory and puts the given files into it.

.PHONY: install uninstall
+install: all
+	 ocamlfind install $(NAME) *.mli *.cmi $(ARCHIVE) META \
+             -optional $(XARCHIVE) $(SARCHIVE)
+
+uninstall:
+         ocamlfind remove $(NAME)

Last but not least a cleanup rule:

.PHONY: clean
+         rm -f *.cmi *.cmo *.cmx *.cma *.cmxa *.a

PrevHomeNext
How to create your own packagesUpUsing the Makefile wizard
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x421.html b/local-packages/ocamlfind/doc/guide-html/x421.html new file mode 100644 index 0000000..54991f4 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x421.html @@ -0,0 +1,188 @@ + +Using the Makefile wizard
The findlib User's Guide
PrevChapter 6. How to create your own packagesNext

Using the Makefile wizard

Especially for beginners, the findlib distribution includes a GUI to +create Makefiles. As this is an optional feature, it must have been +selected when findlib was built (option -with-toolbox). To invoke the +GUI, run the command + +

$ ocamlfind findlib/make_wizard
+ +(Btw, this is the general syntax to run executables installed in +package directories.) The wizard starts, and allows you to describe +your project. When you save the result, not only a "Makefile" is +created, but also the file ".make-wizard" containing the state. +If you later start the wizard again, this file will be automatically +loaded, and you can modify your definition.

The wizard consists of seven (hopefully self-explanatory) pages +you can fill out. The basic idea is that the .ml, .mli, .mly, and .mll +files in the current directory are compiled to a .cma or .cmxa +archive, and that optionally executables are created from this archive +and from additional modules (main programs). This scheme can be both +used for libraries and application programs.

You can choose packages you want to use in your library or +program by clicking at them in a selection box. The camlp4 syntax +parsers can be optionally enabled. The modules to be compiled can +be picked from the current directory, they must be selected in the +right order, however.

The generated "Makefile" defines a number of logical targets +(like "all", "opt", etc) that are explained at the beginning of the +file. The file is fully commented, and not very difficult to understand. +Only traditional Makefile syntax is used, so it is expected that it +works for every version of the "make" utility.

When you build the project, the META file is created +dynamically. If you do not like this, set the variable MAKE_META to +the empty string. (It is a good idea to put such setting into a +second file, and enter the name of this file into the box "Local +extensions in" of the wizard, so you can generate the "Makefile" again +without overwriting your own modifications. This second file can +override the setting in the generated "Makefile".)


PrevHomeNext
Change your MakefileUpFAQs
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x443.html b/local-packages/ocamlfind/doc/guide-html/x443.html new file mode 100644 index 0000000..038269d --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x443.html @@ -0,0 +1,170 @@ + +Why does findlib not automatically include the -custom option if +linked with C code?
The findlib User's Guide
PrevChapter 7. FAQsNext

Why does findlib not automatically include the -custom option if +linked with C code?

Short answer: +Because there are several ways of linking, and findlib is not the +right instance to find out the right way

Recent versions of OCaml support DLLs, at least for some +platforms. Here, the option -custom is not necessary at all, because the +C libraries can be looked up and loaded at runtime. The option -custom +would have the effect of forcing static linking.

But even for platforms without DLL support, there are two +alternatives. One possibility is to use -custom, and the other is to +create runtime systems with -make-runtime, and reference them with +-use-runtime. Fortunately, recent versions of OCaml select now themselves +-custom automatically if -make-runtime is omitted, so findlib needs not to +bother with it.


PrevHomeNext
FAQsUpDoes findlib support linking of applications as well as +packages?
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x449.html b/local-packages/ocamlfind/doc/guide-html/x449.html new file mode 100644 index 0000000..a9e45d4 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x449.html @@ -0,0 +1,211 @@ + +Does findlib support linking of applications as well as +packages?
The findlib User's Guide
PrevChapter 7. FAQsNext

Does findlib support linking of applications as well as +packages?

Short answer: Yes, but it is not very obvious

Applications also depend on other components, they have predicates, sometimes +they need linker options; there seems to be only little difference between +applications (stand-alone programs) and packages. If you want to use the +findlib mechanisms for applications, too, the following trick helps.

The environment variable OCAMLPATH may contain a +colon-separated path of possible sitelib locations. It is allowed to include +"." into the path (Shell commands follow): + +

OCAMLPATH=.
+export OCAMLPATH
+ +This makes ".", i.e. your current directory, another sitelib location. You may +now put the components of your applications into subdirectories together with +META files; the hierarchy might look as follows: + +
./Makefile                          global Makefile
+./localpkg1/META                    first local package directory: Contains META
+./localpkg1/...                     ... and more
+./localpkg2/META                    second local package dir: Contains META
+./localpkg2/...                     ... and more
+...
+ +From findlib's point of view, these directories are now package directories, +and you can refer to them on the command line: + +
ocamlfind ocamlc -o ... -linkpkg -package localpkg1,localpkg2,...
+ +If you do not want subdirectories, you can also refer to the META file in the +same directory by the name ".", e.g.: + +
ocamlfind ocamlc -o ... -linkpkg -package .
+ +In this case, the linking information will be taken from +./META.


PrevHomeNext
Why does findlib not automatically include the -custom option if +linked with C code?UpDoes Findlib support camlp4?
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x461.html b/local-packages/ocamlfind/doc/guide-html/x461.html new file mode 100644 index 0000000..c38e1a7 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x461.html @@ -0,0 +1,384 @@ + + Does Findlib support camlp4? +
The findlib User's Guide
PrevChapter 7. FAQsNext

Does Findlib support camlp4?

Short answer: Yes, but there is only little + documentation.

Since Findlib-0.4, there is some experimental camlp4 support. For +example, the following compiler invocation chooses the revised syntax: + +

ocamlfind ocamlc -syntax camlp4r -package camlp4 -c file.ml
+ + As you can see, camlp4 must be included as package, and the +-syntax option must specify which syntax is selected (either +camlp4o or camlp4r).

If you want to pass additional options to the preprocessor, +you can use the -ppopt option: + +

ocamlfind ocamlc -syntax camlp4r -package camlp4 -ppopt pa_ifdef.cmo -c file.ml
+

From the toploop, the following commands work: + +

$ ocaml
+        Objective Caml version 3.07+2
+ 
+# #use "./topfind";;
+- : unit = ()
+Findlib has been successfully loaded. Additional directives:
+  #require "package";;      to load a package
+  #list;;                   to list the available packages
+  #camlp4o;;                to load camlp4 (standard syntax)
+  #camlp4r;;                to load camlp4 (revised syntax)
+  #predicates "p,q,...";;   to set these predicates
+  Topfind.reset();;         to force that packages will be reloaded
+  #thread;;                 to enable threads
+ 
+- : unit = ()
+# #camlp4o;;            (* or camlp4r *)
+/opt/godi/lib/ocaml/std-lib/camlp4: added to search path
+/opt/godi/lib/ocaml/std-lib/camlp4/camlp4o.cma: loaded
+        Camlp4 Parsing version 3.07+2
+ 
+# _

The concept

If you have a -syntax option on the command line, +ocamlfind will generate a -pp parameter and pass it to the +invoked compiler. This is performed as follows: The specified packages are +inspected under a certain set of predicates, the syntax +predicates. The syntax predicates are syntax, +preprocessor, and the predicates following +-syntax. The predicate syntax simply +means that the -syntax option has been specified. +The predicate preprocessor means that the preprocessor +command is being constructed. The predicates added by +-syntax may be used to distinguish between syntax variants +(currently camlp4o and camlp4r).

The packages are searched for a variable preprocessor; +normally the camlp4 package defines it as (see its META +file): + +

preprocessor = "camlp4 -nolib"
+ +Now that the name of the preprocessor command is known, the arguments of the +command are looked up. The META files are evaluated under the syntax +predicates, and all archive variables are collected and +passed as arguments to the preprocessor. For example, the camlp4 package +defines: + +
archive(syntax,preprocessor,camlp4o) = "pa_o.cmo pa_op.cmo pr_dump.cmo"
+archive(syntax,preprocessor,camlp4r) = "pa_r.cmo pa_rp.cmo pr_dump.cmo"
+ +Note that the predicate preprocessor prevents ocamlfind from +including these archives into the regular list of archives to link.

How to write a META file for your own syntax extension

Suppose you have two archives: pa_myext.cma contains the +extension code of camlp4, and run_myext.cma contains runtime +material that must be present in programs compiled with your extensions. Your +META file should look as follows: + +

requires = "camlp4"
+archive(syntax,toploop) = "pa_myext.cma run_myext.cma"
+archive(syntax,preprocessor) = "pa_myext.cma"
+archive(syntax,byte)    = "run_myext.cma"
+archive(syntax,native)  = "run_myext.cmxa"
+ +You may add dependencies on camlp4o or +camlp4r if you have archives only working for one of the two +syntax variants.

To compile a program using your syntax extension package, one should use: + +

ocamlfind ocamlc -package yourname -syntax variant ...

Example

The package xstrp4 defines a syntax extension allowing +$-substitutions in OCaml strings. Version 1.0 of this package takes advantage +from the new camlp4 support of findlib; you may have a look at it for an +example.

You can find xstrp4 +here.


PrevHomeNext
Does findlib support linking of applications as well as +packages?UpDoes Findlib support ppx-style preprocessors?
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x513.html b/local-packages/ocamlfind/doc/guide-html/x513.html new file mode 100644 index 0000000..e394f7c --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x513.html @@ -0,0 +1,198 @@ + + Does Findlib support ppx-style preprocessors? +
The findlib User's Guide
PrevChapter 7. FAQsNext

Does Findlib support ppx-style preprocessors?

Short answer: Yes, but there is only little + documentation.

Since findlib-1.5, ppx-style preprocessors are supported +to some extent. A package can now define a "ppx" property which is simply +a command to run as preprocessor (the command gets the marshalled AST +as input, and must generate the transformed AST in its output; see the +-ppx option of ocamlc/ocamlopt). A META file can simply look like: + +

ppx = "./command"
+ +when "command" is installed in the package directory (but you can also +omit "./" to search it, and you can prefix it with "@name/" if the command +is taken from another package "name").

For more complex scenarios, additional options or +arguments for the ppx preprocessor can be specified in descendant +packages with the "ppxopt" property. Package "A" might provide a +generic ppx preprocessor with a META file containing + +

ppx = "./generic_ppx"
+ +Package B might instantiate that preprocessor with + +
requires = "A"
+ppxopt = "A,ppx_b.cmo"
+ +In this case "ocamlfind ocamlc -package B" would +add -ppx "path_to_A/genric_ppx ppx_b.cmo" to +the ocamlc invocation. The format of the "ppxopt" property is +specified in the findlib reference manual.

This feature is still a bit experimental.


PrevHomeNext
Does Findlib support camlp4?UpWhy do some people install the .cmx files?
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x524.html b/local-packages/ocamlfind/doc/guide-html/x524.html new file mode 100644 index 0000000..e590331 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x524.html @@ -0,0 +1,162 @@ + +Why do some people install the .cmx files?
The findlib User's Guide
PrevChapter 7. FAQsNext

Why do some people install the .cmx files?

In principle, it is not necessary to install the .cmx +files created by the ocamlopt compiler, as the .a and .cmxa files +already contain the assembly code and all needed auxiliary information. +However, it may be sensible to install the .cmx files, too. They +contain the intermediate code of small functions that are candidates +for inlining, and installing them allows the compiler to do inlining +even across library boundaries. Note that only very small functions +can be inlined at all, and that there are language elements that +prevent inlining (e.g. raising an exception with an argument), so +it makes only sense when the library actually has such functions +and really profits from inlining.

Inlining has also disadvantages: The library can no +longer be replaced by a different version even if the interface +remains exactly the same, because code using the library may have +inlined code of the old version.


PrevHomeNext
Does Findlib support ppx-style preprocessors?UpHow do I express conflicts?
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x528.html b/local-packages/ocamlfind/doc/guide-html/x528.html new file mode 100644 index 0000000..94aae6b --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x528.html @@ -0,0 +1,198 @@ + +How do I express conflicts?
The findlib User's Guide
PrevChapter 7. FAQs 

How do I express conflicts?

A conflict means that a certain combination of packages +and package features will not work. A number of conflict conditions +can be expressed:

  • To state that a package will not work if a certain +predicate is set, use the error variable. For example, +when package p does not work for multi-threaded programs: + +

    error(mt) = "Package p is incompatible with multi-threaded programs"
    + +This works for other standard predicates, too.

  • To state that a package will not work together with +another package, it is possible to make error dependent +on package predicates. For example, when package p does not work +together with q: + +

    error(pkg_q) = "Package p is incompatible with package q"
    + +This also works with subpackages (e.g. pkg_q.q_sub). +

  • If an error is too much, it might be a good idea to + just inform the user about possible problems. In this case + you can emit a warning instead: +

    warning(pkg_q) = "Using package p and q together is a really bad idea"

Note that such error conditions should only be added if there is +absolutely no chance to get the combination of packages and features running. +For example, in the case of multi-threaded programs it is often possible +to add wrappers around unsafe libraries to fix the incompatibility. +

It is not possible to express incompatibilities between package +versions. Such incompatibilities should be detected when software is +installed, not when it is used.


PrevHome 
Why do some people install the .cmx files?Up 
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x81.html b/local-packages/ocamlfind/doc/guide-html/x81.html new file mode 100644 index 0000000..7728d8d --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x81.html @@ -0,0 +1,170 @@ + +Looking up package directories
The findlib User's Guide
PrevChapter 2. Using packagesNext

Looking up package directories

The package manager knows the preferred location for packages (this +location is compiled in), which is usually +/usr/local/lib/ocaml/site-lib. You can ask the package manager where +package p is stored by simply typing

ocamlfind query p

and it will answer something like

/usr/local/lib/ocaml/site-lib/p

There is an environment variable OCAMLPATH which can specify further +directories where packages are stored. (The search order is: first +the directories in OCAMLPATH in turn, then the default path +set in ocamlfind.conf)

Historically, this kind of query was the first and only way of using +ocamlfind, and because of the similiarity to the Unix find command it +got its name. Finding out package locations is a basic but +nethertheless important feature because it hides the details of the +filesystem hierarchy. It is sufficient only to know the name of the +package, and if needed, you can use the lookup mechanism implemented +in ocamlfind to get the concrete directory.


PrevHomeNext
Using packagesUpHow a package directory looks like
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/guide-html/x89.html b/local-packages/ocamlfind/doc/guide-html/x89.html new file mode 100644 index 0000000..3865b63 --- /dev/null +++ b/local-packages/ocamlfind/doc/guide-html/x89.html @@ -0,0 +1,255 @@ + +How a package directory looks like
The findlib User's Guide
PrevChapter 2. Using packagesNext

How a package directory looks like

Let us assume that the package p implements the modules M1 and M2. If +you compile m1.mli and m2.mli you get the corresponding binary files +m1.cmi and m2.cmi describing the interfaces of the modules. Of course, +these cmi files must go into the package directory. It is recommended +to put the source mli files into the directory, too, as they document +the interface.

Another product of the compilation are two cmo files, m1.cmo and +m2.cmo (we assume the bytecode compiler, the native compiler would +create m1.cmx and m2.cmx). It is possible to put these files directly +into the directory, but there is a better way. As it makes only sense +to use both modules (a very common assumption), they should first be +archived by doing

ocamlc -a -o p.cma m1.cmo m2.cmo

The archive p.cma contains both cmo files, and preserves the order of +the files. Assumed that in M2 there is a reference to an entity in M1, +M2 depends on M1 and when linking a program using these modules, M1 +must be mentioned first (e.g. ocamlc m1.cmo m2.cmo +program.ml)[1]. If you create the archive p.cma it contains already +this dependency, and you need not to remember it when linking in the +p.cma.

So far the files m1.cmi, m2.cmi, and p.cma are needed, and m1.mli and +m2.mli are recommended. Usually there is another file in the +directory, META, containing additional information about the package. +In our example, META looks like

description = "Our super-duper package"
+requires = ""
+version = "1"
+archive(byte) = "p.cma"

The variable "requires" contains a list of packages that are +required by this package (the names may be separated by commas or +spaces). As our package, p, does not depend on any other package, this +list is empty. I'll explain what happens with non-empty lists below.

The variable "version" is simply a version string, and "description" +is a short comment on the package.

The variable "archive" denotes the files that have to be +actually linked in if the package is used. This is again a list of +(file) names. In contrast to the other variables, "archive" has a +condition, written in parantheses. This value of "archive" will only +be used if the predicate "byte" is true; this predicate is usually +given if the program is compiled to bytecode. If you have a native +archive, p.cmxa, of the two modules M1 and M2, you can add another +line to META:

archive(native) = "p.cmxa"

The correct value for the "archive" variable is selected upon the +given set of predicates.

Many packages can also be loaded at runtime with the +Fl_dynload module. In this case, though, the +variable "plugin" is used instead of "archive", e.g.

plugin(byte) = "p.cma"
+plugin(native) = "p.cmxs"

(You can create p.cmxs from p.cmxa with +"ocamlopt -shared -linkall -o p.cmxs p.cmxa".) Note that "plugin" is entirely optional.

Notes

[1]

Note that C linkers usually require the reverse +order, but only for archive elements, i.e. files with suffix +.a.


PrevHomeNext
Looking up package directoriesUpQuerying information stored in META files
\ No newline at end of file diff --git a/local-packages/ocamlfind/doc/readme.dtd b/local-packages/ocamlfind/doc/readme.dtd new file mode 100644 index 0000000..8ff6a9f --- /dev/null +++ b/local-packages/ocamlfind/doc/readme.dtd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local-packages/ocamlfind/doc/ref-man/META.5 b/local-packages/ocamlfind/doc/ref-man/META.5 new file mode 100644 index 0000000..13380ec --- /dev/null +++ b/local-packages/ocamlfind/doc/ref-man/META.5 @@ -0,0 +1,613 @@ +.TH "META" "5" "The findlib package manager for OCaml" "User Manual" +.SH "NAME" +.ft R +META - [File that specifies metainformation of OCaml packages]\c +.SH "GRAMMAR" +.ft R +.ft R +.ft B +.nf +\&\ \ \ \ \ \ \ \ \ metafile\ ::=\ entry*\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ entry\ ::=\ assignment\ |\ addition\ |\ subpackage\c +\& +.br +\&\ \ \ \ \ \ \ subpackage\ ::=\ "package"\ pkgname\ '('\ metafile\ ')'\c +\& +.br +\&\ \ \ \ \ \ \ assignment\ ::=\ variable_name\ [\ formal_predicates\ ]\ '='\ \ value\c +\& +.br +\&\ \ \ \ \ \ \ \ \ addition\ ::=\ variable_name\ [\ formal_predicates\ ]\ '+='\ value\c +\& +.br +formal_predicates\ ::=\ '('\ formal_predicate\ {\ ','\ formal_predicate\ }\ ')'\c +\& +.br +\&\ \ \ \ variable_name\ ::=\ name\c +\& +.br +\&\ formal_predicate\ ::=\ name\ |\ '-'\ name\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ name\ ::=\ [\ 'A'-'Z'\ 'a'-'z'\ '0'-'9'\ '_'\ '.'\ ]+\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ pkgname\ ::=\ '"'\ (character\ but\ not\ '.')*\ '"'\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ value\ ::=\ '"'\ character*\ '"'\c +.ft R +.fi +.SH "DESCRIPTION" +.ft R +.ft R +If a package directory contains a file with the fixed name "META" it\c +\& +is interpreted as described here. The file is a sequence of entries\c +\& +following the given grammar; every entry defines a variable under a\c +\& +certain condition given by the list of formal predicates, or it\c +\& +introduces a subpackage.\c +.PP +.ft R +There is a list of predefined variables and a list of standard\c +\& +predicates. These variables define: required packages, description, version\c +\& +information, directories, archive files, and linker options. The\c +\& +predicates denote circumstances of the application of the variables:\c +\& +whether the bytecode or the native compiler is used, if there is a\c +\& +toploop compiled in, details of multi-threading execution, details of\c +\& +profiling. +.SH "DETAILS OF THE FILE FORMAT" +.ft R +.ft R +The file consists of a sequence of entries which must be formed as the\c +\& +grammar prescribes. The lexical tokens are names, values, and\c +\& +interpunctuation like '(', ',' and so on. Note that linefeeds do not\c +\& +play a special role, i.e. an entry definition may be given in more than\c +\& +one line, or several definitions may occur on a single line. There may\c +\& +be comments which begin with '#' and run until the end of the line.\c +.PP +.ft R +Names are sequences of the characters A-Z, a-z, 0-9, or _. Names\c +\& +containing capital letters and names beginning with digits are\c +\& +allowed but not recommended.\c +.PP +.ft R +Values are enclosed between double quotes. Values may contain any\c +\& +character. The characters " and \e must be preceded by backslashes. +.PP +.ft R +Package names must not contain the '.' character because it is used\c +\& +as delimiter of compound names.\c +.SH "MAIN PACKAGES AND SUBPACKAGES" +.ft R +.ft R +The outermost variable assignments and additions belong to the main\c +\& +package. The name of the main package is not defined within META;\c +\& +it is either the name of the directory containing META or the suffix\c +\& +of the META file (if the name of the META file is formed like\c +\& +META.name).\c +.PP +.ft R +The keyword +package\c +\& starts the definition\c +\& +of a subpackage. There must not be two such definitions with the\c +\& +same name. Within the parantheses, the variable assignments and\c +\& +additions refer to the subpackage. It is allowed that a subpackage\c +\& +contains further subpackages.\c +.PP +.ft R +The package name following +package\c +\& +is the local name relative to the main package, i.e. the\c +\& +name of the main package is not mentioned. At all other places,\c +\& +however, the subpackage must be prefixed by the name of the\c +\& +containing package, separated by a '.'.\c +.PP +.ft R +Subpackages are independent of the containing package, except\c +\& +that the subpackage points to the same installation directory as\c +\& +the containing package (i.e. the location of the installation directory\c +\& +is inherited from the containing package).\c +.SH "SEMANTICS OF VARIABLE DEFINITIONS" +.ft R +.ft R +In order to determine the value of a variable, first all assignments\c +\& +are inspected, and the most specific assignment is taken (if there is\c +\& +none, the empty string will be taken as value). In a second step,\c +\& +all additions are gone through one after the other in the order\c +\& +they occur in the file, and the values of all matching additions are\c +\& +appended to the current value. In the following, it is further\c +\& +clarified which assignment is the most specific, which additions\c +\& +actually match, and how the details of the value addition look like.\c +.PP +.ft R +The most specific assignment is selected upon a set of actual\c +\& +predicates, i.e. the set of predicates that are assumed to be true.\c +\& +The predicates occuring in the definitions of assignments and\c +\& +additions are called formal predicates. They may be positive or\c +\& +negative; the latter are prepended by a '-' sign. In order to\c +\& +determine the value after the evaluation of the assignments, the\c +\& +following rules apply: +.PP +.ft R +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +An assignment can only be used if all positive formal\c +\& +predicates are included in the set of actual predicates, and if all\c +\& +negative formal predicates are not included in the set of actual\c +\& +predicates. Such an assignment is called\c +\& +.ft B +applicable\c +.ft R +\&. If there is no such assignment, the\c +\& +variable will have no value. +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +If there is more than one applicable assignment, the definition with\c +\& +the biggest number of formal predicates is selected.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +If there is still more than one applicable assignment, both applicable +\& +and with a maximum number of formal predicates, the definition that is defined\c +\& +first is selected.\c +.RE +.ft R +.PP +.ft R +.ft R +An addition is matching when all positive formal predicates are\c +\& +included in the set of actual predicates, and all negative formal\c +\& +predicates are not included.\c +.PP +.ft R +The value of an addition is appended to the current value with\c +\& +implicit white space as separator.\c +.SH "VARIABLES" +.ft R +.ft R +There is a set of variables with predefined meaning:\c +.PP +.ft R +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The\c +\& +variable "directory" redefines the location of the package\c +\& +directory. Normally, the META file is the first file read in the\c +\& +package directory, and before any other file is read, the "directory"\c +\& +variable is evaluated in order to see if the package directory must be\c +\& +changed. The value of the "directory" variable is determined with an\c +\& +empty set of actual predicates. The value must be either: an absolute\c +\& +path name of the alternate directory, or a path name relative to the\c +\& +stdlib directory of OCaml (written "+path"), or a normal relative path\c +\& +name (without special syntax). In the latter case, the interpretation\c +\& +depends on whether it is contained in a main or sub package, and\c +\& +whether the standard repository layout or the alternate layout is in\c +\& +effect (see +site-lib\c +\& for these terms).\c +\& +For a main package in standard layout the base directory is the\c +\& +directory physically containing the META file, and the relative path\c +\& +is interpreted for this base directory. For a main package in\c +\& +alternate layout the base directory is the directory physically\c +\& +containing the META.pkg files. The base directory for subpackages is\c +\& +the package directory of the containing package. (In the case\c +\& +that a subpackage definition does not have a "directory" setting,\c +\& +the subpackage simply inherits the package directory of the containing\c +\& +package. By writing a "directory" directive one can change this\c +\& +location again.)\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "requires" specifies the list of required packages. The\c +\& +names of the packages must be separated by white space and/or commas.\c +\& +The names must be fully qualified (i.e. when they refer to a subpackage,\c +\& +the names of all containing packages must be prepended, separated by\c +\& +\&'.').\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "description" may include a short description of the\c +\& +package (displayed by +ocamlfind list\c +).\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "version" specifies the version string.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "archive" specifies the list of archive files. These\c +\& +files should be given either as (1) plain names without any directory\c +\& +information; they are only searched in the package directory.\c +\& +(2) Or they have the form "+path" in which case the files are looked up\c +\& +relative to the standard library. (3) Or they have the form "@name/file"\c +\& +in which case the files are looked up in the package directory\c +\& +of another package. (4) Or they are given as absolute paths.\c +.PP +.ft R +The\c +\& +names of the files must be separated by white space and/or commas.\c +\& +In the preprocessor stage, the archive files are passed as extensions\c +\& +to the preprocessor (camlp4) call. In the linker stage (-linkpkg), the archive\c +\& +files are linked. In the compiler stage, the archive files are ignored.\c +.PP +.ft R +Note that "archive" should only be used for archive files that are\c +\& +intended to be included in executables or loaded into toploops. For\c +\& +modules loaded at runtime there is the separate variable "plugin".\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "plugin" specifies the plugin archives of the package.\c +\& +These can be dynamically loaded with the +Fl_dynload\c +\& +module. The plugin archives can have ".cmo", ".cma", or ".cmxs" suffix.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "linkopts" specifies additional linker options.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "error" can be used to signal error conditions. When\c +\& +this variable is applicable, the ocaml compilers are stopped, and\c +\& +an error message is printed. The message is the value of the variable.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "warning" can be used to signal warnings. When\c +\& +this variable is applicable, the warning is printed, but the\c +\& +compilation continues. The message is the value of the variable.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "exists_if" can be used to disable subpackages. The\c +\& +value of "exists_if" is a file; the subpackage is hidden if this\c +\& +file does not exist. You can also enumerate several files, and the\c +\& +subpackage is hidden if none of the files exist.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "ppx" is a command that is added to the compiler invocation\c +\& +via the -ppx option (available since OCaml-4.01). If the command is\c +\& +relative to the current directory (e.g. ./cmd), the command is expected\c +\& +in the package directory. The special forms as defined for "archive"\c +\& +are also available (e.g. @otherpkg/cmd). Additional arguments can be\c +\& +specified on the ocamlfind command line with the -ppxopt option\c +\& +or the "ppxopt" variable.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The variable "ppxopt" is a set of options that are added to the ppx\c +\& +rewriter invocation. The contents of the variable consists of one or\c +\& +several whitespace-separated parts. Every part consists of several\c +\& +comma-separated subparts; the first subpart indicates the package\c +\& +that contains the ppx rewriter invocation, the rest contain the options\c +\& +to be appended. If the option is a path relative to the current directory\c +\& +(e.g. ./foo.cma), the path is expanded relative to the package directory.\c +\& +The special forms as defined for "archive" are also available\c +\& +(e.g. @otherpkg/foo.cma).\c +.RE +.ft R +.PP +.ft R +.ft R +It is possible to define additional variables but there is currently\c +\& +no software interpreting them.\c +.SH "PREDICATES" +.ft R +.ft R +There is a list of standard predicates:\c +.PP +.ft R +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "byte" predicate means that the bytecode compiler is used.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "native" predicate means that the native compiler is used.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "toploop" predicate means that the toploop is available in the\c +\& +linked program. It is only set when the toploop is running, not when\c +\& +the toploop is generated.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "create_toploop" predicate means that a toploop is created (using\c +\& +ocamlmktop).\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "mt" predicate means that the program is multi-threaded.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "mt_posix" predicate means that in the case "mt" is set, too, the\c +\& +POSIX libraries are used to implement threads.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "mt_vm" predicate means that in the case "mt" is set, too, the\c +\& +VM-based libraries are used to implement threads.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "gprof" predicate means that in the case "native" is set, too, the\c +\& +program is compiled for profiling\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "autolink" predicate means that ocamlc can/will perform automatic linking.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "preprocessor" predicate means that the META variables are scanned for\c +\& +preprocessor options.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The "syntax" predicate means that the -syntax option is present on the\c +\& +command line.\c +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +Legacy: The "plugin" predicate could be used in some versions of findlib\c +\& +to select cmxs archives instead of cmxa archives. This use is still possible\c +\& +but discouraged.\c +.RE +.ft R +.PP +.ft R +.ft R +In addition to these predicates, there are package predicates\c +\& +for every package that is finally selected. Of course, this kind of\c +\& +predicate must not be used to select "directory" and "requires"\c +\& +variables, but for the other variables they are perfectly valid.\c +\& +The package predicates have the form "pkg_" plus the name of the\c +\& +package (fully qualified).\c diff --git a/local-packages/ocamlfind/doc/ref-man/TIMESTAMP b/local-packages/ocamlfind/doc/ref-man/TIMESTAMP new file mode 100644 index 0000000..e69de29 diff --git a/local-packages/ocamlfind/doc/ref-man/findlib.conf.5 b/local-packages/ocamlfind/doc/ref-man/findlib.conf.5 new file mode 100644 index 0000000..3a70319 --- /dev/null +++ b/local-packages/ocamlfind/doc/ref-man/findlib.conf.5 @@ -0,0 +1,787 @@ +.TH "findlib.conf" "5" "The findlib package manager for OCaml" "User Manual" +.SH "NAME" +.ft R +findlib.conf - [Configuration of findlib/ocamlfind]\c +.SH "GENERAL" +.ft R +.ft R +There are three possibilities to configure the findlib library:\c +\& +\& +.PP +.ft R +.RS "2m" +.ft R +Build time:\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Before findlib is compiled, a "configure" script is invoked to figure\c +\& +\& out the settings that are most likely to work on the system. Most\c +\& +\& settings are simply entered into text files and can easily be changed\c +\& +\& after installation. The following properties cannot be changed later\c +\& +\& because they are compiled into the resulting binaries:\c +\& +\& +\& +.PP +.ft R +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +The default location of the configuration file findlib.conf. However,\c +\& +\& you can set a different location by the environment variable\c +\& +\& +OCAMLFIND_CONF\c +\&.\c +\& +\& +.RE +.ft R +.sp +.RS "7m" +.ft R +\&\h'-3m'\z\(bu\h'3m'\c +.ft R +Whether the installed OCaml version supports autolinking or not.\c +\& +\& +.RE +.ft R +.PP +.ft R +.RE +.ft R +.sp +.RS "2m" +.ft R +Configuration file findlib.conf:\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +An initial version of this file is generated by the configure script,\c +\& +\& but you are free to modify it later. Most important, this file\c +\& +\& contains the system-wide search path used to look up packages, and the\c +\& +\& default location where to install new packages.\c +\& +\& +.PP +.ft R +All files with the suffix ".conf" found in the directory\c +\& +\& findlib.conf.d are also scanned for parameters.\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +Environment variables:\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The settings of findlib.conf can be overridden by environment variables.\c +\& +\& +.RE +.ft R +.PP +.ft R +Last but not least, several settings can also be passed as\c +\& +command-line options, or by invoking the function\c +\& +Findlib.init\c +\&. +.SH "findlib.conf" +.ft R +.ft R +The directory containing findlib.conf is determined at build time (by\c +\& +running the configure script), the fallback default is\c +\& +/usr/local/etc\c +\&. You can set a different location by\c +\& +changing the environment variable +OCAMLFIND_CONF\c +\& +which must contain the absolute path of findlib.conf.\c +.PP +.ft R +The file has the same syntax as +META\c +, i.e. it consists of a\c +\& +number of lines with the format\c +\& +\& +.PP +.ft R +.ft B +.nf +.ft I +variable\c +.ft B +\&\ =\ "\c +.ft I +value\c +.ft B +"\c +.ft R +.fi +.PP +.ft R +Here is the list of allowed variables:\c +\& +\& +.PP +.ft R +.RS "2m" +.ft R +path\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The search path for META files/package directories. The variable\c +\& +\& enumerates directories which are separated by colons (Windows:\c +\& +\& semicolons), and these directories are tried in turn to find a certain\c +\& +\& package. More exactly, if d is such a directory and p the searched\c +\& +\& package, the search algorithm will first check whether d/p/META\c +\& +\& exists. In this case, this META file is taken, and d/p is the package\c +\& +\& directory. Second, the algorithm tries d/META.p, but the package\c +\& +\& directory must be specified in this META.p file by a\c +\& +\& +directory\c +\& directive.\c +\& +\& +.PP +.ft R +Note that the first found META file is taken, so the order of the\c +\& +\& directories in the search path counts.\c +\& +\& +.PP +.ft R +This variable is required.\c +\& +\& +.PP +.ft R +Example:\c +\& +\& +\& +.PP +.ft R +.ft B +.nf +path\ =\ "/usr/local/lib/ocaml/site-lib:/usr/lib/ocaml/site-lib"\c +.ft R +.fi +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +destdir\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable determines the location where +ocamlfind\c +\& +\& install\c +\& puts the packages by default: If d is this\c +\& +\& directory, and p the package to install, a new subdirectory d/p will\c +\& +\& be created containing all the files of the package.\c +\& +\& +.PP +.ft R +Example:\c +\& +\& +.PP +.ft R +.ft B +.nf +destdir\ =\ "/usr/local/lib/ocaml/site-lib"\c +.ft R +.fi +\& +\& +.PP +.ft R +This variable is required.\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +metadir\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +If set, the command +ocamlfind install\c +\& will put the\c +\& +\& META files of packages into this directory (files are named META.p\c +\& +\& where p=package name); otherwise the META files are put into the\c +\& +\& package directories like any other file.\c +\& +\& +.PP +.ft R +Example:\c +\& +\& +.PP +.ft R +.ft B +.nf +metadir\ =\ "/var/lib/findlib/metaregistry"\c +.ft R +.fi +\& +\& +.PP +.ft R +This variable is optional. It is not used by default.\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +ocamlc\c +,\c +\& +\& +ocamlopt\c +,\c +\& +\& +ocamlcp\c +,\c +\& +\& +ocamlmktop\c +,\c +\& +\& +ocamldoc\c +,\c +\& +\& +ocamldep\c +,\c +\& +\& +ocamlbrowser\c +\& +\& +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +If you want to call other executables than "ocamlc", "ocamlopt",\c +\& +\& "ocamlcp", "ocamlmktop", "ocamldoc", "ocamldep", and\c +\& +\& "ocamlbrowser", you can\c +\& +\& set the names of\c +\& +\& the executables here. The command +ocamlfind\c +\& looks\c +\& +\& into these four variables to determine the names of the compilers to\c +\& +\& call.\c +\& +\& +.PP +.ft R +Example:\c +\& +\& +.PP +.ft R +.ft B +.nf +ocamlc\ \ \ \ \ =\ "ocamlc.opt"\c +\& +.br +ocamlopt\ \ \ =\ "ocamlopt.opt"\c +\& +.br +ocamlcp\ \ \ \ =\ "ocamlcp.opt"\c +\& +.br +ocamlmktop\ =\ "ocamlmktop.opt"\c +.ft R +.fi +\& +\& +.PP +.ft R +This variable is optional. It is not used by default.\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +stdlib\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable determines the location of the standard library. This must\c +\& +\& be the same directory for which the OCaml compilers are configured.\c +\& +\& +.PP +.ft R +This variable is optional. It is not recommend to set this variable\c +\& +\& unless you know what you are doing!\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +ldconf\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable determines the location of the ld.conf file. This must\c +\& +\& be the same file the OCaml compilers read in; it is updated by +\& +\& ocamlfind when installing and removing packages. You can set this\c +\& +\& variable to the special value "\c +ignore\c +" to disable\c +\& +\& the automatic modification of the ld.conf file.\c +\& +\& +.PP +.ft R +If not set, the ld.conf file is assumed to reside in the OCaml\c +\& +\& standard library directory.\c +\& +\& +.PP +.ft R +This variable is optional. It is not recommended to set this variable\c +\& +\& unless you know what you are doing!\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +Toolchains: It is possible to have variants of the original configuration.\c +\& +These variants are called "toolchains" because they are intended to\c +\& +select different compilers, e.g. patched compilers. In order to\c +\& +set a variable for a certain toolchain, use the syntax\c +\& +\& +.PP +.ft R +.ft B +.nf +.ft I +variable\c +.ft B +(\c +.ft I +toolchain\c +.ft B +)\ =\ "\c +.ft I +value\c +.ft B +"\c +.ft R +.fi +\& +\& +For example:\c +\& +\& +.PP +.ft R +.ft B +.nf +ocamlc(mypatch)\ =\ "ocamlc-mypatch"\c +.ft R +.fi +\& +\& +When the toolchain "mypatch" is selected, this compiler will be used instead\c +\& +of the standard one.\c +.PP +.ft R +In order to switch to a certain toolchain, use the -toolchain\c +\& +option of +ocamlfind\c +\&.\c +.SH "Environment" +.ft R +.ft R +A number of environment variables modifies the behaviour of\c +\& +findlib/ocamlfind:\c +\& +\& +.PP +.ft R +.RS "2m" +.ft R +OCAMLFIND_CONF\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable overrides the location of the configuration file\c +\& +\& findlib.conf. It must contain the absolute path name of this file.\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +OCAMLFIND_TOOLCHAIN\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable sets the currently selected toolchain when\c +\& +\& a +-toolchain\c +\& option is not passed\c +\& +\& on the command line.\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +OCAMLPATH\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable may contain an additional search path for package\c +\& +\& directories. It is treated as if the directories were prepended to\c +\& +\& the configuration variable +path\c +\&.\c +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +OCAMLFIND_DESTDIR\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable overrides the configuration variable\c +\& +\& +destdir\c +\&. +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +OCAMLFIND_METADIR\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable overrides the configuration variable\c +\& +\& +metadir\c +\&. +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +OCAMLFIND_COMMANDS\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable overrides the configuration variables\c +\& +\& +ocamlc\c +, +ocamlopt\c +,\c +\& +\& +ocamlcp\c +, +ocamlmktop\c +,\c +\& +\& +ocamldoc\c +, +ocamldep\c +, and/or\c +\& +\& +ocamlbrowser\c +\&. +\& +\& Its value must conform to the syntax\c +\& +\& +\& +.PP +.ft R +.ft B +.nf +ocamlc=\c +.ft I +name\c +.ft B +\&\ ocamlopt=\c +.ft I +name\c +.ft B +\&\ ocamlcp=\c +.ft I +name\c +.ft B +\&\ ocamlmktop=\c +.ft I +name\c +.ft B +\&\ ocamldoc=\c +.ft I +name\c +.ft B +\&\ ocamldep=\c +.ft I +name\c +.ft B +\&\ ocamlbrowser=\c +.ft I +name\c +.ft B +.ft R +.fi +\& +\& +.PP +.ft R +Example:\c +\& +\& +.PP +.ft R +.ft B +.nf +ocamlc=ocamlc-3.00\ ocamlopt=ocamlopt-3.00\ ocamlcp=ocamlcp-3.00\ ocamlmktop=ocamlmktop-3.00\c +.ft R +.fi +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +CAMLLIB\c +\& or +OCAMLLIB\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable overrides the configuration variable\c +\& +\& +stdlib\c +\&. +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +OCAMLFIND_LDCONF\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable overrides the configuration variable\c +\& +\& +ldconf\c +\&. +\& +\& +.RE +.ft R +.PP +.ft R +.ft R +.RS "2m" +.ft R +OCAMLFIND_IGNORE_DUPS_IN\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This variable instructs findlib not to emit warnings that packages\c +\& +\& or module occur several times. The variable must be set to the\c +\& +\& directory where the packages reside that are to be ignored for this\c +\& +\& warning.\c +\& +\& +.RE +.ft R +.PP +.ft R diff --git a/local-packages/ocamlfind/doc/ref-man/ocamlfind.1 b/local-packages/ocamlfind/doc/ref-man/ocamlfind.1 new file mode 100644 index 0000000..ac59463 --- /dev/null +++ b/local-packages/ocamlfind/doc/ref-man/ocamlfind.1 @@ -0,0 +1,2853 @@ +.TH "ocamlfind" "1" "The findlib package manager for OCaml" "User Manual" +.SH "NAME" +.ft R +ocamlfind - [Command-line interface of the Package manager]\c +.SH "SYNOPSIS" +.ft R +.ft R +.ft B +.nf +\&\ \ \ \ \ \ \ ocamlfind\ query\ [-help\ |\ other\ options]\ \c +.ft I +package_name\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamlc\ [-help\ |\ other\ options]\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamlcp\ [-help\ |\ other\ options]\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamlmktop\ [-help\ |\ other\ options]\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamlopt\ [-help\ |\ other\ options]\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamldoc\ [-help\ |\ other\ options]\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamldep\ [-help\ |\ other\ options]\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamlmklib\ [-help\ |\ other\ options]\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ ocamlbrowser\ [-help\ |\ other\ options]\c +\& +.br +\&\ \ \ or:\ ocamlfind\ install\ [-help\ |\ other\ options]\ \c +.ft I +package_name\c +.ft B +\&\ \c +.ft I +file\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ remove\ [-help\ |\ other\ options]\ \c +.ft I +package_name\c +.ft B +\& +.br +\&\ \ \ or:\ ocamlfind\ lint\ \c +.ft I +META\c +.ft B +\& +.br +\&\ \ \ or:\ ocamlfind\ list\ [-describe]\c +\& +.br +\&\ \ \ or:\ ocamlfind\ printppx\ [-help\ |\ other\ options]\ \c +.ft I +package_name\c +.ft B +\&\ ...\c +\& +.br +\&\ \ \ or:\ ocamlfind\ printconf\ [\ variable\ ]\c +\& +.br +\&\ \ \ or:\ ocamlfind\ \c +.ft I +package\c +.ft B +/\c +.ft I +command\c +.ft B +\&\ \c +.ft I +arg\c +.ft B +\&\ ...\c +\& +.br +\& +.br +Optional\ toolchain\ selection\ by:\c +\& +.br +\&\ \ ocamlfind\ -toolchain\ \c +.ft I +name\c +.ft B +\&\ ...\c +.ft R +.fi +.SH "THE 'query' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ query\ [\ -predicates\ \c +.ft I +p\c +.ft B +\&\ \ |\ \c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -format\ \c +.ft I +f\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -long-format\ |\ -l\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -i-format\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -l-format\ |\ \c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -a-format\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -o-format\ |\ \c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -p-format\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -prefix\ \c +.ft I +p\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -separator\ \c +.ft I +s\c +.ft B +\&\ |\ \c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -suffix\ \c +.ft I +s\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -pp\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -descendants\ |\ -d\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -recursive\ \ |\ -r\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -qe\ |\ -qo]\ \c +.ft I +package\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This command looks packages up, sorts them optionally, and\c +\& +prints attributes of them. If the option -recursive (short: -r) is not\c +\& +specified, exactly the packages given on the command line are looked\c +\& +up; if -recursive is present, the packages and all their ancestors, or\c +\& +if -descendants (short: -d) is present, too, all their descendants are printed.\c +.PP +.ft R +Package lookup and the selection of the attributes of the packages can\c +\& +be modified by specifying predicates; without a -predicates option the\c +\& +empty set of predicates is used. Note that even the lookup is\c +\& +influenced by the set of actual predicates as the "requires" variables\c +\& +may be conditional.\c +.PP +.ft R +What is printed about a package depends on the specified format; there\c +\& +are a number of options that modify the format. Some formats denote\c +\& +sets of values (such as -format %a), in which case multiple output\c +\& +records are printed for every package. (It is even possible to specify\c +\& +formats denoting the Cartesian product of sets, such as -format %a%o,\c +\& +but this does not make sense.) Before the first output record the\c +\& +prefix is printed, and the suffix after the last record. Between two\c +\& +records the separator is printed.\c +.SS "Options" +.ft R +.ft R +.RS "2m" +.ft R +-predicates +.ft I +p\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Sets the set of actual predicates. The argument\c +\& +\& +.ft I +p\c +.ft R +\& is a list of predicate names separated\c +\& +\& by commas and/or whitespace. If multiple -predicates options are\c +\& +\& given, the union of all specified sets is effectively used.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-format +.ft I +f\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Sets the format to the string\c +\& +\& +.ft I +f\c +.ft R +\&. Characters preceded by a percent sign\c +\& +\& are interpreted as placeholders; all other characters mean\c +\& +\& themselves. The defined placeholders are listed below.\c +\& +\& The default format is "%d".\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-long-format or -l\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Sets the format such that all relevant variables are printed.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-i-format\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Same as -format "-I %d", i.e. directory options for ocamlc are printed.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-l-format\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Same as -format "-ccopt -L%d", i.e. directory options for the\c +\& +linker backend are printed.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-a-format\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Same as -format "%+a", i.e. archive file names are printed.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-o-format\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Same as -format "%o", i.e. linker options are printed.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-p-format\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Same as -format "%p", i.e. package names are printed.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-prefix +.ft I +p\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Sets the prefix that is printed before the first output record\c +\& +\& to the given string. The default prefix is the empty string.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-suffix +.ft I +s\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Sets the suffix that is printed after the last output record\c +\& +\& to the given string. The default suffix is the empty string.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-separator +.ft I +s\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Sets the separator that is printed between output records to\c +\& +\& the given string. The default separator is a linefeed character.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-recursive or -r\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Not only the packages given on the command line are queried\c +\& +\& but also all ancestors or descendants. If the option -descendants is\c +\& +\& specified, too, the descendants are printed, otherwise the\c +\& +\& ancestors. The packages are topologically sorted.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-descendants -d\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Instead of the ancestors the descendants of the\c +\& +\& given packages are queried. This option implies +-recursive\c +\&.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-pp\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Query preprocessor packages (camlp4 syntax extensions). Normally\c +\& +it is not needed to set -predicates, except you need the archives (then add\c +\& +-predicates byte). This option implies +-recursive\c +\&.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-qe\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Do not print most errors to stderr, just set the exit code\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-qo\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Do not print the regular output.\c +.RE +.ft R +.PP +.ft R +.SS "Placeholders meaningful in the -format option" +.ft R +.ft R +.RS "2m" +.ft R +%%\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by a single percent sign\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%p\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the package name\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%d\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the package directory\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%m\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the path to the META file (new since findlib-1.6)\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%D\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the package description\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%v\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the version string\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%a\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the archive filename. If there is more\c +\& +\& than one archive, a separate output record is printed for every archive.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%+a\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Like %a, but the filenames are converted to absolute\c +\& +\& paths ("+" and "@" notations are resolved)\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%A\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the list of archive filenames.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%+A\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Like %A, but the filenames are converted to absolute\c +\& +\& paths ("+" and "@" notations are resolved)\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%o\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by one linker option. If there is more than\c +\& +\& one option, a separate output record is printed for every option.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%O\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the list of linker options.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +%(\c +.ft I +property\c +.ft R +)\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Replaced by the value of the property named in parentheses,\c +\& +or the empty string if not defined.\c +.RE +.ft R +.PP +.ft R +.SH "THE SUBCOMMANDS 'ocamlc', 'ocamlcp', 'ocamlopt', and 'ocamlmktop'" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ (\ ocamlc\ |\ ocamlcp\ |\ ocamlopt\ |\ ocamlmktop\ )\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ [\ -package\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -linkpkg\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -predicates\ \c +.ft I +pred-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -dontlink\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -syntax\ \c +.ft I +pred-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -ppopt\ \c +.ft I +camlp4-arg\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -ppxopt\ \c +.ft I +package\c +.ft B +,\c +.ft I +arg\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -dllpath-pkg\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -dllpath-all\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -passopt\ \c +.ft I +arg\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -passrest\ \c +.ft I +arg...\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -only-show\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \c +.ft I +standard-option\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \c +.ft I +file\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +These subcommands are drivers for the compilers with the same names,\c +\& +i.e. "ocamlfind ocamlc" is a driver for "ocamlc", and so on. The\c +\& +subcommands understand all documented options of the compilers (here\c +\& +called +.ft I +standard-options\c +.ft R +), but also a few\c +\& +more options. If these subcommands are invoked only with standard\c +\& +options, they behave as if the underlying compiler had been called\c +\& +directly. The extra options modify this.\c +.PP +.ft R +Internally, these subcommands transform the given list of options and\c +\& +file arguments into an invocation of the driven compiler. This\c +\& +transformation only adds options and files, and the relative order of\c +\& +the options and files passed directly is unchanged.\c +.PP +.ft R +If there are -package options, additional directory search specifiers\c +\& +will be included ("-I", and "-ccopt -I"), such that files of all named\c +\& +packages and all ancestors can be found.\c +.PP +.ft R +The -linkpkg option causes that the packages listed in the -package\c +\& +options and all necessary ancestors are linked in. This means that the\c +\& +archive files implementing the packages are inserted into the list of\c +\& +file arguments.\c +.PP +.ft R +As the package database is queried a set of predicates is needed. Most\c +\& +predicates are set automatically, see below, but additional predicates\c +\& +can be given by a -predicates option.\c +.PP +.ft R +If there is a +-syntax\c +\& option, the drivers assume that\c +\& +a preprocessor is to be used. In this case, the preprocessor command\c +\& +is built first in a preprocessor stage, and this command is passed to the\c +\& +compiler using the +-pp\c +\& option. The set of predicates\c +\& +in the preprocessor stage is different from the set in the compiler/linker\c +\& +stage.\c +.SS "Options for compiling and linking" +.ft R +.ft R +Here, only the additional options not interpreted by the compiler but\c +\& +by the driver itself, and options with additional effects are explained.\c +\& +Some options are only meaningful for the preprocessor call, and are\c +\& +explained below.\c +.PP +.ft R +.RS "2m" +.ft R +-package +.ft I +package-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Adds the listed package names to the set of included\c +\& +\& packages. The package names may be separated by commas and/or\c +\& +\& whitespace. In the transformed command, for every package of the set\c +\& +\& of included packages and for any ancestor a directory search option\c +\& +\& is inserted after the already given options. This means that\c +\& +\& "-I" and "-ccopt -I" options are added for every package directory.\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +-linkpkg\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Causes that in the transformed command all archives\c +\& +\& of the packages specified by -packages and all their ancestors are\c +\& +\& added to the file arguments. More precisely, these archives are\c +\& +\& inserted before the first given file argument. Furthermore, "-ccopt\c +\& +\& -L" options for all package directories, and the linker options of\c +\& +\& the selected packages are added, too. Note that the archives are\c +\& +\& inserted in topological order while the linker options are added in\c +\& +\& reverse toplogical order.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-predicates +.ft I +pred-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Adds the given predicates to the set of actual\c +\& +\& predicates. The predicates must be separated by commas and/or\c +\& +\& whitespace. +.RE +.ft R +.sp +.RS "2m" +.ft R +-dontlink +.ft I +package-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This option modifies the behaviour of\c +\& +\& -linkpkg. Packages specified here and all ancestors are not linked\c +\& +\& in. Again the packages are separated by commas and/or whitespace.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-dllpath-pkg +.ft I +package-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +For these packages +-dllpath\c +\& options\c +\& +\& are added to the compiler command. This may be useful when the ld.conf\c +\& +\& file is not properly configured.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-dllpath-all\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +For all linked packages +-dllpath\c +\& options\c +\& +\& are added to the compiler command. This may be useful when the ld.conf\c +\& +\& file is not properly configured.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-passopt +.ft I +arg\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The argument +.ft I +arg\c +.ft R +\& is\c +\& +\& passed directly to the underlying compiler. This is needed to\c +\& +\& specify undocumented compiler options.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-passrest +.ft I +arg...\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +All following arguments +.ft I +arg...\c +.ft R +\& are\c +\& +\& passed directly to the underlying compiler. This is needed to\c +\& +\& specify undocumented compiler options.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-only-show\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Only prints the constructed command (ocamlc/ocamlopt) to\c +\& +\& stdout, but does not execute the command. (This is for the unlikely event\c +\& +\& that you need a wrapper around ocamlfind.)\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-verbose\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This standard option is interpreted by the driver, too.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-thread\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This standard option causes that the predicate "mt"\c +\& +\& is added to the set of actual predicates. If POSIX threads are available,\c +\& +\& the predicate "mt_posix" is selected, too. If only VM threads are\c +\& +\& available, the predicate "mt_vm" is included into the set, and the\c +\& +\& compiler switch is changed into -vmthread.\c +.PP +.ft R +Note that the presence of the "mt" predicate triggers special\c +\& +fixup of the dependency graph (see below).\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-vmthread\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This standard option causes that the predicates "mt"\c +\& +\& and "mt_vm" are added to the set of actual predicates.\c +.PP +.ft R +Note that the presence of the "mt" predicate triggers special\c +\& +fixup of the dependency graph (see below).\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-p\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This standard option of "ocamlopt" causes that the\c +\& +\& predicate "gprof" is added to the set of actual predicates.\c +.RE +.ft R +.PP +.ft R +.SS "Options for preprocessing" +.ft R +.ft R +The options relevant for the preprocessor are the following:\c +.PP +.ft R +.RS "2m" +.ft R +-package +.ft I +package-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +These packages are considered while looking up the\c +\& +\& preprocessor arguments. (It does not cause problems that the same\c +\& +\& -package option is used for this purpose, because the set of predicates\c +\& +\& is different.) It is recommended to mention at least +camlp4\c +\& +\& here if the preprocessor is going to be used.\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +-syntax +.ft I +pred-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +These predicates are assumed to be true in addition\c +\& +\& to the standard preprocessor predicates. See below for a list.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-ppopt +.ft I +camlp4-arg\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This argument is passed to the camlp4 call.\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +-ppxopt +.ft I +package\c +.ft R +,\c +.ft I +arg\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Add +.ft I +arg\c +.ft R +\& to the ppx\c +\& +\& preprocessor invocation specified via the "ppx" property in\c +\& +\& the META file of +.ft I +package\c +.ft R +\&.\c +\& +\& +.RE +.ft R +.PP +.ft R +.SS "Predicates for compiling and linking" +.ft R +.ft R +.RS "2m" +.ft R +byte\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "byte" predicate means that one of the bytecode compilers is\c +\& +used. It is automatically included into the predicate set if the\c +\& +"ocamlc", "ocamlcp", or "ocamlmktop" compiler is used.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +native\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "native" predicate means that the native compiler is used. It is\c +\& +automatically included into the predicate set if the "ocamlopt"\c +\& +compiler is used.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +toploop\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "toploop" predicate means that the toploop is available in the\c +\& +linked program. This predicate is only set when the toploop is actually\c +\& +being executed, not when the toploop is created (this changed in version\c +\& +1.0.4 of findlib).\c +.RE +.ft R +.sp +.RS "2m" +.ft R +create_toploop\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This predicate means that a toploop is being created (using\c +\& +ocamlmktop).\c +.RE +.ft R +.sp +.RS "2m" +.ft R +mt\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "mt" predicate means that the program is multi-threaded. It is\c +\& +automatically included into the predicate set if the -thread option is\c +\& +given. +.RE +.ft R +.sp +.RS "2m" +.ft R +mt_posix\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "mt_posix" predicate means that in the case "mt" is set, too, the\c +\& +POSIX libraries are used to implement threads. "mt_posix" is automatically\c +\& +included into the predicate set if the variable "type_of_threads" in the\c +\& +META description of the "threads" package has the value "posix". This\c +\& +is normally the case if "findlib" is configured for POSIX threads.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +mt_vm\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "mt_vm" predicate means that in the case "mt" is set, too, the\c +\& +VM thread emulation is used to implement multi-threading.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +gprof\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "gprof" predicate means that in the case "native" is set, too, the\c +\& +program is compiled for profiling. It is automatically included into\c +\& +the predicate set if "ocamlopt" is used and the -p option is in\c +\& +effect.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +autolink\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The "autolink" predicate means that ocamlc is able to perform automatic\c +\& +linking. It is automatically included into the predicate set if ocamlc\c +\& +knows automatic linking (from version 3.00), but it is not set if the\c +\& +-noautolink option is set.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +syntax\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This predicate is set if there is a +-syntax\c +\& +\& option. It is set both for the preprocessor and the compiler/linker stage,\c +\& +\& and it can be used to find out whether the preprocessor is enabled or not.\c +\& +\& +.RE +.ft R +.PP +.ft R +.SS "Predicates for preprocessing" +.ft R +.ft R +.RS "2m" +.ft R +preprocessor\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This predicate is always set while looking up the\c +\& +\& preprocessor arguments. It can be used to distinguish between the\c +\& +\& preprocessor stage and the compiler/linker stage.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +syntax\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This predicate is set if there is a +-syntax\c +\& +\& option. It is set both for the preprocessor and the compiler/linker stage,\c +\& +\& and it can be used to find out whether the preprocessor is enabled or not.\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +camlp4o\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This is the reserved predicate for the standard OCaml syntax.\c +\& +\& It can be used in the +-syntax\c +\& predicate list.\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +camlp4r\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +This is the reserved predicate for the revised OCaml syntax.\c +\& +\& It can be used in the +-syntax\c +\& predicate list.\c +\& +\& +.RE +.ft R +.PP +.ft R +.SS "Special behaviour of 'ocamlmktop'" +.ft R +.ft R +As there is a special module +Topfind\c +\& that\c +\& +supports loading of packages in scripts, the "ocamlmktop" subcommand\c +\& +can add initialization code for this module. This extra code is\c +\& +linked into the executable if "findlib" is in the set of effectively\c +\& +linked packages. +.SS "Fixup of the dependency graph for multi-threading" +.ft R +.ft R +For a number of reasons the presence of the "mt" predicate triggers\c +\& +that (1) the package "threads" is added to the list of required packages\c +\& +and (2) the package "threads" becomes prerequisite of all other packages\c +\& +(except of itself and a few hardcoded exceptions). The effect is that\c +\& +the options -thread and -vmthread automatically select the "threads"\c +\& +package, and that "threads" is inserted at the right position in the\c +\& +package list.\c +.SS "Extended file naming" +.ft R +.ft R +At a number of places one can not only refer to files by absolute\c +\& +or relative path names, but also by extended names. These have two\c +\& +major forms: "+\c +.ft I +name\c +.ft R +"\c +\& +refers to the subdirectory +.ft I +name\c +.ft R +\& of the\c +\& +standard library directory, and "@\c +.ft I +name\c +.ft R +"\c +\& +refers to the package directory of the package +.ft I +name\c +.ft R +\&.\c +\& +Both forms can be continued by a path, e.g. "@netstring/netstring_top.cma".\c +.PP +.ft R +You can use extended names: (1) With +-I\c +\& options,\c +\& +(2) as normal file arguments of the compiler, (3) in the +\& +"archive" property of packages.\c +.SS "How to set the names of the compiler executables" +.ft R +.ft R +Normally, the OCaml bytecode compiler can be called under the name\c +\& +ocamlc\c +\&. However, this is not always true; sometimes a\c +\& +different name is chosen.\c +.PP +.ft R +You can instruct ocamlfind to call executables with other names than\c +\& +ocamlc\c +, +ocamlopt\c +,\c +\& +ocamlmktop\c +, and +ocamlcp\c +\&. If present,\c +\& +the environment variable +OCAMLFIND_COMMANDS\c +\& is interpreted\c +\& +as a mapping from the standard names to the actual names of the executables. It\c +\& +must have the following format:\c +\& +\& +.PP +.ft R +.ft B +.nf +.ft I +standardname1\c +.ft B +=\c +.ft I +actualname1\c +.ft B +\&\ \c +.ft I +standardname2\c +.ft B +=\c +.ft I +actualname2\c +.ft B +\&\ ...\c +.ft R +.fi +.PP +.ft R +Example: You may set +OCAMLFIND_COMMANDS\c +\& as follows:\c +\& +\& +.PP +.ft R +.ft B +.nf +OCAMLFIND_COMMANDS='ocamlc=ocamlc-3.00\ ocamlopt=ocamlopt-3.00'\c +\& +.br +export\ OCAMLFIND_COMMANDS\c +.ft R +.fi +.PP +.ft R +Alternatively, you can change the configuration file\c +\& +findlib.conf\c +\&.\c +.SH "THE SUBCOMMAND 'ocamlmklib'" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ ocamlmklib\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ [\ -package\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -predicates\ \c +.ft I +pred-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -dllpath-pkg\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -dllpath-all\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -passopt\ \c +.ft I +arg\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -passrest\ \c +.ft I +arg...\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \c +.ft I +standard-option\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \c +.ft I +file\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This is a wrapper around ocamlmklib, and creates library archives and\c +\& +DLLs. In addition to the standard options, one can use -package to\c +\& +add the search path of packages. Note that no predicates are set by default -\c +\& +the wrapper does not know whether this is about byte or native code linking.\c +.PP +.ft R +This wrapper is mostly provided for completeness.\c +.SH "THE 'ocamldep' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ ocamldep\ [-package\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -syntax\ \c +.ft I +pred-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -ppopt\ \c +.ft I +camlp4-arg\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -passopt\ \c +.ft I +arg\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -passrest\ \c +.ft I +arg...\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -verbose\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \c +.ft I +standard-option\c +.ft B +]\ \c +.ft I +file\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This command is a driver for the tool +ocamldep\c +\& of the\c +\& +OCaml distribution. This driver is only useful in conjunction with\c +\& +the preprocessor camlp4; otherwise it does not provide more functions\c +\& +than +ocamldep\c +\& itself.\c +.SS "Options" +.ft R +.ft R +Here, only the additional options not interpreted by +ocamldep\c +\& +but\c +\& +by the driver itself, and options with additional effects are explained.\c +.PP +.ft R +.RS "2m" +.ft R +-package +.ft I +package-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The packages named here are only used to look up the\c +\& +preprocessor options. The package +camlp4\c +\& should be\c +\& +specified anyway, but further packages that add capabilities to the\c +\& +preprocessor can also be passed.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-syntax +.ft I +pred-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The predicates that are in effect during the look-up\c +\& +of the preprocessor options. At least, either +camlp4o\c +\& +(selecting the normal syntax), or +camlp4r\c +\& (selecting\c +\& +the revised syntax) should be specified.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-ppopt +.ft I +camlp4-arg\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +An option that is passed through to the camlp4 call.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-passopt +.ft I +arg\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +An option that is passed through to the ocamldep call.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-passrest +.ft I +arg...\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +All further arguments are passed down to ocamldep\c +\& +\& unprocessed\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-verbose\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Displays the resulting ocamldep command (for debugging)\c +.RE +.ft R +.PP +.ft R +.SS "Example" +.ft R +.ft R +A typical way of using this driver:\c +\& +\& +.PP +.ft R +.ft B +.nf +ocamlfind\ ocamldep\ -package\ camlp4,xstrp4\ -syntax\ camlp4r\ file1.ml\ file2.ml\c +.ft R +.fi +\& +\& +This command outputs the dependencies of +file1.ml\c +\& and\c +\& +file2.ml\c +, although these modules make use of the\c +\& +syntax extensions provided by +xstrp4\c +\& and are written\c +\& +in revised syntax.\c +.SH "THE 'ocamlbrowser' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ ocamlbrowser\ [-package\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -all\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -passopt\ \c +.ft I +arg\c +.ft B +\&\ \c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ -passrest\ ]\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This driver calls the +ocamlbrowser\c +\& with package options.\c +\& +With +-package\c +, the specified packages are included into\c +\& +the search path of the browser, and the modules of these packages become\c +\& +visible (in addition to the standard library). The option +-all\c +\& causes that all packages are selected that are managed by findlib.\c +.PP +.ft R +As for other drivers, the options +-passopt\c +\& and\c +\& +-passrest\c +\& can be used\c +\& +to pass arguments directly to the +ocamlbrowser\c +\& program.\c +.SH "THE SUBCOMMAND 'ocamldoc'" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ ocamldoc\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ [\ -package\ \c +.ft I +package-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -predicates\ \c +.ft I +pred-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -syntax\ \c +.ft I +pred-name-list\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ -ppopt\ \c +.ft I +camlp4-arg\c +.ft B +\&\ |\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \c +.ft I +standard-option\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \c +.ft I +file\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This subcommand is a driver for ocamldoc. It undestands all options\c +\& +ocamldoc supports plus the mentioned findlib options. Basically,\c +\& +the -package options are translated into -I options, and the selected\c +\& +syntax options are translated into camlp4 options.\c +.SS "Options" +.ft R +.ft R +Here, only the additional options not interpreted by +ocamldep\c +\& +but\c +\& +by the driver itself, and options with additional effects are explained.\c +.PP +.ft R +.RS "2m" +.ft R +-package +.ft I +package-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Adds the listed package names to the set of included\c +\& +\& packages. The package names may be separated by commas and/or\c +\& +\& whitespace. In the transformed command, for every package of the set\c +\& +\& of included packages and for any ancestor a directory search option\c +\& +\& is inserted after the already given options. This means that\c +\& +\& "-I" options are added for every package directory.\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +-predicates +.ft I +pred-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Adds the given predicates to the set of actual\c +\& +\& predicates. The predicates must be separated by commas and/or\c +\& +\& whitespace. +.RE +.ft R +.sp +.RS "2m" +.ft R +-syntax +.ft I +pred-name-list\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +The predicates that are in effect during the look-up\c +\& +of the preprocessor options. At least, either +camlp4o\c +\& +(selecting the normal syntax), or +camlp4r\c +\& (selecting\c +\& +the revised syntax) should be specified.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +-ppopt +.ft I +camlp4-arg\c +.ft R +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +An option that is passed through to the camlp4 call.\c +.RE +.ft R +.PP +.ft R +.SH "THE 'install' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ install\ [\ -destdir\ \c +.ft I +directory\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -metadir\ \c +.ft I +directory\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -ldconf\ \c +.ft I +path\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -dont-add-directory-directive\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -patch-version\ \c +.ft I +string\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -patch-rmpkg\ \c +.ft I +name\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -patch-archives\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -dll\ ]\ [\ -nodll\ ]\ [\ -optional\ ]\ [\ -add\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \c +.ft I +package_name\c +.ft B +\&\ \c +.ft I +file\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This subcommand installs a new package either at the default location\c +\& +(see the variable +destdir\c +\& of\c +\& +findlib.conf\c +), or in the directory\c +\& +specified by the -destdir option. This\c +\& +means that a new package directory is created and that the files on\c +\& +the command line are copied to this directory. It is required that a\c +\& +META\c +\& file is one of the files copied to the target\c +\& +directory.\c +.PP +.ft R +Note that package directories should be flat (no\c +\& +subdirectories). Existing packages are never overwritten.\c +.PP +.ft R +It is possible to have a separate directory for all the META files. If\c +\& +you want that, you have either to set the variable\c +\& +metadir\c +\& of +\& +findlib.conf\c +, or to specify the\c +\& +-metadir option. In this case, the file called META is copied to the\c +\& +specified directory and renamed to META.p (where p is the package\c +\& +name), while all the other files are copied to the package\c +\& +directory as usual. Furthermore, the META file is modified such that the\c +\& +directory\c +\& variable contains the path of the package\c +\& +directory. +.PP +.ft R +The option -dont-add-directory-directive prevents the installer from\c +\& +adding a +directory\c +\& variable.\c +.PP +.ft R +If there are files ending in the suffixes +\&.so\c +\& or\c +\& +\&.dll\c +, the package directory will be added to the\c +\& +DLL configuration file +ld.conf\c +, such that the dynamic\c +\& +loader can find the DLL. The location of this file can be overriden by\c +\& +the -ldconf option. To turn this feature off, use "-ldconf ignore";\c +\& +this causes that the ld.conf file is not modified.\c +.PP +.ft R +However, if there is a stublibs directory in site-lib, the DLLs are not\c +\& +installed in the package directory, but in this directory that is\c +\& +shared by all packages that are installed at the same location.\c +\& +In this case, the configuration file +ld.conf\c +\& is\c +\& +not modified, so you do not need to say "-ldconf ignore" if you\c +\& +prefer this style of installation.\c +.PP +.ft R +The options -dll and -nodll can be used to control exactly which files\c +\& +are considered as DLLs and which not. By default, the mentioned\c +\& +suffix rule is in effect: files ending in ".so" (Unix) or ".dll"\c +\& +(Windows) are DLLs. The switch -dll changes this, and all following\c +\& +files are considered as DLLs, regardless of their suffix. The switch +\& +-nodll expresses that the following files are not DLLs, even if they\c +\& +have a DLL-like suffix. For example, in the following call the files\c +\& +f1 and f2 are handled by the suffix rule; f3 and f4 are DLLs anyway;\c +\& +and f5 and f6 are not DLLs:\c +\& +\& +.PP +.ft R +.ft B +.nf +ocamlfind\ install\ p\ f1\ f2\ -dll\ f3\ f4\ -nodll\ f5\ f6\c +.ft R +.fi +.PP +.ft R +The switch -optional declares that all following files are optional,\c +\& +i.e. the command will not fail if files do not exist.\c +.PP +.ft R +The -patch options may be used to change the contents of the META files\c +\& +while it is being installed. The option -patch-version changes the\c +\& +contents of the top-level "version" variable. The option -patch-rmpkg\c +\& +removes the given subpackage. The option -patch-archives is experimental,\c +\& +in particular it removes all non-existing files from "archive" variables,\c +\& +and even whole subpackages if the archives are missing.\c +.PP +.ft R +The effect of -add is to add further files to an already installed\c +\& +packages.\c +.SH "THE 'remove' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ remove\ [\ -destdir\ \c +.ft I +directory\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -metadir\ \c +.ft I +directory\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ [\ -ldconf\ \c +.ft I +path\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \c +.ft I +package_name\c +.ft B +.ft R +.fi +.SS "Description" +.ft R +.ft R +The package will removed if it is installed at the default location +\& +(see the variable +destdir\c +\& of\c +\& +findlib.conf\c +). If the package\c +\& +resides at a different location, it will not be removed by default;\c +\& +however, you can pass an alternate directory for packages by the\c +\& +-destdir option. (This must be the same directory as specified at\c +\& +installation time.)\c +.PP +.ft R +Note that package directories should be flat (no subdirectories); this\c +\& +subcommand cannot remove deep package directories. +.PP +.ft R +If you have a separate directory for META files, you must either\c +\& +configure this directory by the +metadir\c +\& variable\c +\& +of +findlib.conf\c +, or by specifying\c +\& +the -metadir option.\c +.PP +.ft R +The command does not fail if the package and/or the META\c +\& +file cannot be located. You will get a warning only in this case.\c +.PP +.ft R +If the package directory is mentioned in the +ld.conf\c +\& +configuration file for DLLs, it will be tried to remove this entry\c +\& +from the file. The location of this file can be overriden by\c +\& +the -ldconf option. To turn this feature off, use "-ldconf ignore";\c +\& +this causes that the ld.conf file is not modified.\c +.PP +.ft R +If there is a stublibs directory, it is checked whether the package\c +\& +owns any of the files in this directory, and the owned files will\c +\& +be deleted.\c +.SH "THE 'list' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ list\ [-describe]\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This command lists all packages in the search path. The option -describe\c +\& +outputs the package descriptions, too.\c +.SH "THE 'printppx' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ printppx\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ [\ -predicates\ \c +.ft I +pred-name-list\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ [\ -ppxopt\ \c +.ft I +package\c +.ft B +,\c +.ft I +arg\c +.ft B +\&\ ]\c +\& +.br +\&\ \ \ \ \ \ \ \ \ \ \c +.ft I +package\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This command prints the ppx preprocessor options as they would\c +\& +occur in an OCaml compiler invocation for the packages listed in\c +\& +the command. The output includes one "-ppx" option for each\c +\& +preprocessor. The possible options have the same meaning as for\c +\& +"ocamlfind ocamlc". The option "-predicates" adds assumed\c +\& +predicates and\c +\& +"-ppxopt +.ft I +package\c +.ft R +,\c +.ft I +arg\c +.ft R +"\c +\& +adds "\c +.ft I +arg\c +.ft R +" to the ppx invocation of\c +\& +package +.ft I +package\c +.ft R +\&.\c +.PP +.ft R +The output of "ocamlfind printppx" will contain quotes\c +\& +"\c +"\c +" for ppx commands that contain\c +\& +space-separated arguments. In this case +$(ocamlfind\c +\& +printppx ...)\c +\& won't work as naively expected, because\c +\& +many shells (including bash and dash) perform field splitting on\c +\& +the result of command substitutions without honoring quotes.\c +.SH "THE 'lint' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ lint\ \c +.ft I +file\c +.ft B +.ft R +.fi +.SS "Description" +.ft R +.ft R +Checks the META file, and reports possible problems.\c +.SH "THE 'printconf' SUBCOMMAND" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ printconf\ [\ conf\ |\ path\ |\ destdir\ |\ metadir\ |\ metapath\ |\ stdlib\ |\ ldconf\ ]\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This command prints the effective configuration after reading the\c +\& +configuration file, and after applying the various environment\c +\& +variables overriding settings. When called without arguments, the command\c +\& +prints all configuration options in a human-readable form. When called\c +\& +with an argument, only the value of the requested option is printed without\c +\& +explaining texts:\c +.PP +.ft R +.RS "2m" +.ft R +conf\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Prints the location of the configuration file findlib.conf\c +\& +\& +.RE +.ft R +.sp +.RS "2m" +.ft R +path\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Prints the search path for packages. The members of the\c +\& +\& path are separated by linefeeds.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +destdir\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Prints the location where package are installed and\c +\& +\& removed by default.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +metadir\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Prints the location where META files are installed and\c +\& +\& removed (if the alternative layout is used).\c +.RE +.ft R +.sp +.RS "2m" +.ft R +metapath\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Prints the path where the META file is installed for\c +\& +a fictive package. The name of the package is marked with '%s' in the\c +\& +path. For instance, this command could output "/some/path/%s/META" or\c +\& +"/some/path/META.%s", depending on the layout.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +stdlib\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Prints the location of the standard library.\c +.RE +.ft R +.sp +.RS "2m" +.ft R +ldconf\c +.RE +.ft R +.sp +.RS "7m" +.ft R +.ft R +Prints the location of the ld.conf file\c +.RE +.ft R +.PP +.ft R +.SH "THE SUBCOMMAND CALLING PACKAGE PROGRAMS" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ \c +.ft I +pkg\c +.ft B +/\c +.ft I +cmd\c +.ft B +\&\ \c +.ft I +argument\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +This subcommand is useful to call programs that are installed in\c +\& +package directories. It looks up the directory for +\& +.ft I +pkg\c +.ft R +\& and calls the command named\c +\& +.ft I +cmd\c +.ft R +\& in this directory. The remaining arguments\c +\& +are passed to this command.\c +.PP +.ft R +argv(0) contains the absolute path to the command, and argv(1) and\c +\& +the following argv entries contain the arguments. The working directory\c +\& +is not changed.\c +.PP +.ft R +Example: To call the program "x" that is installed in package "p",\c +\& +with arguments "y" and "z", run:\c +.PP +.ft R +.ft B +.nf +ocamlfind\ p/x\ y\ z\c +.ft R +.fi +.SH "CONFIGURATION FILE, ENVIRONMENT VARIABLES" +.ft R +.ft R +The configuration file and environment variables are documented\c +\& +in the manual page for\c +\& +\& +findlib.conf\c +\&.\c +.SH "HOW TO SET THE TOOLCHAIN" +.ft R +.SS "Synopsis" +.ft R +.ft R +.ft B +.nf +ocamlfind\ -toolchain\ \c +.ft I +name\c +.ft B +\&\ ...\c +.ft R +.fi +.SS "Description" +.ft R +.ft R +The -toolchain option can be given before any other command,\c +\& +e.g.\c +\& +.PP +.ft R +.ft B +.nf +ocamlfind\ -toolchain\ foo\ ocamlc\ -c\ file.ml\c +.ft R +.fi +\& +compiles file.ml with toolchain "foo". By selecting toolchains one\c +\& +can switch to different command sets. For instance, the toolchain\c +\& +"foo" may consist of a patched ocamlc compiler. +\& +See +findlib.conf\c +\& how to\c +\& +configure toolchains.\c diff --git a/local-packages/ocamlfind/doc/ref-man/site-lib.5 b/local-packages/ocamlfind/doc/ref-man/site-lib.5 new file mode 100644 index 0000000..883dbb9 --- /dev/null +++ b/local-packages/ocamlfind/doc/ref-man/site-lib.5 @@ -0,0 +1,338 @@ +.TH "site-lib" "5" "The findlib package manager for OCaml" "User Manual" +.SH "NAME" +.ft R +site-lib - [Location of package directories]\c +.SH "STANDARD LAYOUT" +.ft R +.ft R +.ft B +.nf +\&...somewhere\ in\ the\ filesystem\ hierarchy...\c +\& +.br +\&\ \ \ |\c +\& +.br +\&\ \ \ \e\ \c +\& +.br +\&\ \ \ \ \ site-lib\c +\& +.br +\&\ \ \ \ \ |\c +\& +.br +\&\ \ \ \ \ +-\ (optional)\ stublibs\c +\& +.br +\&\ \ \ \ \ +-\ (optional)\ postinstall\c +\& +.br +\&\ \ \ \ \ +-\ (optional)\ postremove\c +\& +.br +\&\ \ \ \ \ |\c +\& +.br +\&\ \ \ \ \ +-\ \c +.ft I +package1\c +.ft B +\& +.br +\&\ \ \ \ \ |\ \ |\c +\& +.br +\&\ \ \ \ \ |\ \ +-\ META\c +\& +.br +\&\ \ \ \ \ |\ \ +-\ \c +.ft I +archive\ files\c +.ft B +\& +.br +\&\ \ \ \ \ |\ \ +-\ \c +.ft I +interface\ definitions\c +.ft B +\& +.br +\&\ \ \ \ \ |\c +\& +.br +\&\ \ \ \ \ +-\ \c +.ft I +package2\c +.ft B +\& +.br +\&\ \ \ \ \ +\c +\& +.br +\&\ \ \ \ \ :\c +\& +.br +\&\ \ \ \ \ :\c +\& +.br +\&\ \ \ \ \ \e\c +\& +.br +\&\ \ \ \ \ \ \ \ \c +.ft I +packageN\c +.ft B +.ft R +.fi +.SH "DESCRIPTION" +.ft R +.ft R +Every installation of "findlib" has a default location for package\c +\& +directories, which is normally a directory called "site-lib". The\c +\& +location can be set by the configuration variables\c +\& +path\c +\& (used to look up packages), and\c +\& +destdir\c +\& (used to install new packages);\c +\& +see +findlib.conf\c +\&.\c +.PP +.ft R +The name of a package is the name of the package directory. For\c +\& +example, if +destdir=/usr/local/lib/ocaml/site-lib\c +, the\c +\& +package p will be installed in the subdirectory\c +\& +/usr/local/lib/ocaml/site-lib/p\c +\&. This subdirectory\c +\& +must contain the META file and all other files belonging to the package.\c +\& +Package names must not contain the '.' character.\c +.PP +.ft R +The variable +destdir\c +\& specifies the directory for\c +\& +new packages. You can only have one such directory at a time; but of\c +\& +course you can change this directory in findlib.conf. The command\c +\& +ocamlfind install\c +\& puts new packages into this\c +\& +directory; it is recommended to use this command for installation\c +\& +because it ensures that the directory layout is right.\c +.PP +.ft R +For searching packages, findlib uses (only) the variable\c +\& +path\c +\& which may name several locations to look at.\c +.PP +.ft R +For systems with DLL support another directory may exist: stublibs. +\& +If present, findlib will install DLLs into this directory that is\c +\& +shared by all packages at the same site-lib location. Findlib remembers\c +\& +which DLL belongs to which package by special files with the suffix\c +\& +".owner"; e.g. for the DLL "dllpcre.so" there is another file\c +\& +"dllpcre.so.owner" containing the string "pcre", so findlib knows\c +\& +that the package "pcre" owns this DLL. It is not possible that a DLL\c +\& +is owned by several packages.\c +.PP +.ft R +If the stublibs directory does not exist, DLLs are installed regularly\c +\& +in the package directories like any other file.\c +.PP +.ft R +For special needs, a postinstall and/or a postremove script may be\c +\& +installed in the site-lib directory. These scripts are invoked after\c +\& +installation or removal of a package, respectively.\c +.SH "ALTERNATE LAYOUT" +.ft R +.ft R +.ft R +.ft B +.nf +\&...somewhere\ in\ the\ filesystem\ hierarchy...\c +\& +.br +\&\ \ \ |\c +\& +.br +\&\ \ \ \e\ \c +\& +.br +\&\ \ \ \ \ site-lib\c +\& +.br +\&\ \ \ \ \ |\c +\& +.br +\&\ \ \ \ \ +-\ (optional)\ stublibs\c +\& +.br +\&\ \ \ \ \ +-\ (optional)\ postinstall\c +\& +.br +\&\ \ \ \ \ +-\ (optional)\ postremove\c +\& +.br +\&\ \ \ \ \ |\c +\& +.br +\&\ \ \ \ \ +-\ \c +.ft I +package1\c +.ft B +\& +.br +\&\ \ \ \ \ |\ \ |\c +\& +.br +\&\ \ \ \ \ |\ \ +-\ \c +.ft I +archive\ files\c +.ft B +\& +.br +\&\ \ \ \ \ |\ \ +-\ \c +.ft I +interface\ definitions\c +.ft B +\& +.br +\&\ \ \ \ \ |\c +\& +.br +\&\ \ \ \ \ +-\ \c +.ft I +package2\c +.ft B +\& +.br +\&\ \ \ \ \ +\c +\& +.br +\&\ \ \ \ \ :\c +\& +.br +\&\ \ \ \ \ :\c +\& +.br +\&\ \ \ \ \ \e\c +\& +.br +\&\ \ :\ \ \ \ \ \c +.ft I +packageN\c +.ft B +\& +.br +\&\ \ |\c +\& +.br +\&\ \ \e\c +\& +.br +\&\ \ \ \ metaregistry\c +\& +.br +\&\ \ \ \ |\c +\& +.br +\&\ \ \ \ +-\ META.package1\c +\& +.br +\&\ \ \ \ +-\ META.package2\c +\& +.br +\&\ \ \ \ +\c +\& +.br +\&\ \ \ \ :\c +\& +.br +\&\ \ \ \ \e\c +\& +.br +\&\ \ \ \ \ \ \ META.packageN\c +.ft R +.fi +.PP +.ft R +This is an alternate directory layout collecting all META files in one\c +\& +directory. You can configure this layout by setting\c +\& +path\c +\& to the absolute location of\c +\& +metaregistry\c +\&. Findlib recognizes that there are\c +\& +META files in this directory and uses them; it is not necessary to\c +\& +include +site-lib\c +\& into the +path\c +\&.\c +.PP +.ft R +In order to work, the META files must contain a\c +\& +directory\c +\& directive pointing to the corresponding\c +\& +package directory that resides below +site-lib\c +\&.\c +.PP +.ft R +The command +ocamlfind install\c +\& copes with this\c +\& +layout, too. The variable +destdir\c +\& must contain the\c +\& +absolute location of +site-lib\c +, and the variable\c +\& +metadir\c +\& must contain the absolute location of\c +\& +metaregistry\c +\&. Note that +ocamlfind\c +\& +install\c +\& automatically adds a +directory\c +\& +directive to the META file, so you need not do it manually.\c diff --git a/local-packages/ocamlfind/doc/src/findlib.dsl b/local-packages/ocamlfind/doc/src/findlib.dsl new file mode 100644 index 0000000..4b2f063 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib.dsl @@ -0,0 +1,24 @@ + +]> + + + + + +(define %footnotes-at-end% + ;; Should footnotes appear at the end of HTML pages? + #t) + +(define %html-ext% + ;; Default extension for HTML output files + ".html") + +(define %root-filename% + ;; Name for the root HTML document + "index") + + + + + diff --git a/local-packages/ocamlfind/doc/src/findlib.sgml b/local-packages/ocamlfind/doc/src/findlib.sgml new file mode 100644 index 0000000..d2c4752 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib.sgml @@ -0,0 +1,2476 @@ + + + + + + + + %gps.common; +]> + + + +The findlib User's Guide + + + + + Gerd + Stolpmann + + +
+ gerd@gerd-stolpmann.de +
+
+
+
+
+ + +1999-2014Gerd Stolpmann + + + + + +The "findlib" library provides a scheme to manage reusable software +components (packages), and includes tools that support this +scheme. Packages are collections of OCaml modules for which +metainformation can be stored. The packages are kept in the filesystem +hierarchy, but with strict directory structure. The library contains +functions to look the directory up that stores a package, to query +metainformation about a package, and to retrieve dependency +information about multiple packages. There is also a tool that allows +the user to enter queries on the command-line. In order to simplify +compilation and linkage, there are new frontends of the various OCaml +compilers that can directly deal with packages. + + + +Together with the packages metainformation is stored. This includes a +version string, the archives the package consists of, and additional +linker options. Packages can also be dependent on other +packages. There is a query which finds out all predecessors of a list +of packages and sorts them topologically. The new compiler frontends +do this implicitly. + + + +Metainformation can be conditional, i.e. depend on a set of +predicates. This is mainly used to be able to react on certain +properties of the environment, such as if the bytecode or the native +compiler is invoked, if the application is multi-threaded, and a few +more. If the new compiler frontends are used, most predicates are +found out automatically. + + + +There is special support for scripts. A new directive, "#require", +loads packages into scripts. + + + +Download findlib + +This manual describes version &release.findlib; of the software +package. It can be downloaded at + +&url.gps-ocaml-download; +. The user's guide and the reference manual are included. +Newest releases of "findlib" will be announced in +The OCaml Link +Database. + + + + +Quickstart + +See also the Quickstart page +for instructions for the most common +cases. + + + + +License + +This document, and the described software, "findlib", are copyright by +Gerd Stolpmann. + + + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this document and the "findlib" software (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + + + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + + + +The Software is provided ``as is'', without warranty of any kind, express +or implied, including but not limited to the warranties of +merchantability, fitness for a particular purpose and noninfringement. +In no event shall Gerd Stolpmann be liable for any claim, damages or +other liability, whether in an action of contract, tort or otherwise, +arising from, out of or in connection with the Software or the use or +other dealings in the software. + + + +
+ + + + + + + + +User's Guide + + +Libraries and Packages + + Reusability is one of the keywords in software engineering +today. It simply means to have source code that can be shared by +several programs. Usually, modules are combined to libraries, and the +library archive files can be linked into programs. As the idea might +be simple, its practical implementation is complex because sharing of +source code has an impact on all steps and phases in software +production. This document only addresses the following administrative +problems: + + + + + +Storing the libraries in file hierarchies + + + + + +Compiling and linking programs using such libraries + + + + + +Managing dependencies between libraries + + + + + +Objective Caml has a variety of language means to support +reusability. Most important, polymorphic functions can be written +which generalize the types of input arguments and the +type of the result value. There are many examples in the core library +such that I assume that the reader is familiar with this +feature. Second, modules and functors must be mentioned which not only +generalize types of values, but can even generalize structures, +i.e. types with associated operations. Third, the class construct +allows us to adopt the object-oriented techniques of abstraction such +as inheritage and dynamic method lookup. + + + +In the following, we are only analyzing the problem of making and +using libraries from a purely software-technical point of view. This +means, we ignore how to make functions polymorphic, and how to create +functors and classes. Instead, we only look at how to invoke the +OCaml compiler to create, manage, and use libraries. Especially, we +are interested in the administration of systems of libraries that +have dependencies. + + +One of the complex operations on such a system is the replacement of +a library by a newer version. Because of the strict compatibility +checks of OCaml, it is usually necessary to rebuild and reinstall +all dependent libraries as well. With the help of findlib, one can +find out which are the dependent libraries. (However, findlib does +not provide a framework to rebuild them. For example, the GODI +system includes such a framework.) + + + +The library is also called a "package" when it is seen as a removeable +and replaceable set of files. Findlib requires that there is a +certain directory structure; it is not possible to install the files +at arbitrary places (findlib does not even maintain a file list). +For simplicity, every library is usually stored into its own +directory, i.e. the library archive files and the interface files. + + +From the perspective of the compiler, the library is made +accessible by adding the package directory to the search path +of the compiler. By doing so, the modules of the library are +added to the namespace universe, and thus can be opened by +modules using them. This means that the approach "one package += one directory" can be naturally translated into language +operations modifying the namespace scope. + + +When linking a program, it must be specified which link operation is +necessary to use a certain library. Often, only a single archive file +needs to be linked in, but sometimes additional archives or system +libraries must be linked, too. Furthermore, the link operations +often depends on certain conditions, e.g. whether a single- or +multi-threaded program is being created. + + + +The findlib library is my suggestion for a +package manager suitable for Objective Caml. It is a library (stored +as a package itself) which can answer the following questions: + + + + +If I want to use a package, which is the directory containing +the compiled interfaces and implementations? - The package directory +may vary from system to system, and this feature makes it easier to +write Makefiles that run everywhere. Furthermore, OCaml can load +modules dynamically, and it is not a good practice to compile in the +location of such modules. The better way is to ask findlib where the +module resides today. + + + + +Which other packages must be linked in, too, if I want to use a +certain package? + + + + +Which archives need to be linked in, and which compiler options +are necessary? + + + + +If there is a version of the archive with additional properties, +which file should I use? - Additional properties are at least: +Thread-safety, using POSIX threads, and being gprof-enabled. It is +simple to add more criterions. + + + + + + +Furthermore, there is a frontend for this library called +ocamlfind. It is a command-line interface for the +library, but has also some additional abilities: + + + + + +It can invoke ocamlc, ocamlopt, ocamlmktop, and ocamlcp such +that compiler arguments necessary to use a package or link it in are +automatically added. + + + + +It can install and uninstall packages. + + + + +It can find out dependent packages. + + + + + +As you'll see in the following chapters, the usage of this library is +really simple. If you want only to link in packages written by other +people, you must only change the command that invokes the compiler, +e.g. instead of calling "ocamlc program.ml" invoke "ocamlfind ocamlc +-package name_of_package_to_use -linkpkg program.ml", and you can +refer to the named package within program.ml. If you want to turn your +collection of modules into a package, you need only to write one +adminstrative file (META) containing all extra information such as +required other packages. + + + + + + + + +Using packages + + +Listing the installed packages + + +You can list which packages are installed by executing + + +ocamlfind list + + +You will get a list of names and version numbers. You can get a bit +more information by passing the -describe option: + + +ocamlfind list -describe + + + + + + +Looking up package directories + + +The package manager knows the preferred location for packages (this +location is compiled in), which is usually +/usr/local/lib/ocaml/site-lib. You can ask the package manager where +package p is stored by simply typing + + + +ocamlfind query p + + + +and it will answer something like + + + +/usr/local/lib/ocaml/site-lib/p + + + +There is an environment variable OCAMLPATH which can specify further +directories where packages are stored. (The search order is: first +the directories in OCAMLPATH in turn, then the default path +set in ocamlfind.conf) + + + +Historically, this kind of query was the first and only way of using +ocamlfind, and because of the similiarity to the Unix find command it +got its name. Finding out package locations is a basic but +nethertheless important feature because it hides the details of the +filesystem hierarchy. It is sufficient only to know the name of the +package, and if needed, you can use the lookup mechanism implemented +in ocamlfind to get the concrete directory. + + + + + +How a package directory looks like + + +Let us assume that the package p implements the modules M1 and M2. If +you compile m1.mli and m2.mli you get the corresponding binary files +m1.cmi and m2.cmi describing the interfaces of the modules. Of course, +these cmi files must go into the package directory. It is recommended +to put the source mli files into the directory, too, as they document +the interface. + + + +Another product of the compilation are two cmo files, m1.cmo and +m2.cmo (we assume the bytecode compiler, the native compiler would +create m1.cmx and m2.cmx). It is possible to put these files directly +into the directory, but there is a better way. As it makes only sense +to use both modules (a very common assumption), they should first be +archived by doing + + + +ocamlc -a -o p.cma m1.cmo m2.cmo + + + +The archive p.cma contains both cmo files, and preserves the order of +the files. Assumed that in M2 there is a reference to an entity in M1, +M2 depends on M1 and when linking a program using these modules, M1 +must be mentioned first (e.g. ocamlc m1.cmo m2.cmo +program.ml)Note that C linkers usually require the reverse +order, but only for archive elements, i.e. files with suffix +.a.. If you create the archive p.cma it contains already +this dependency, and you need not to remember it when linking in the +p.cma. + + + +So far the files m1.cmi, m2.cmi, and p.cma are needed, and m1.mli and +m2.mli are recommended. Usually there is another file in the +directory, META, containing additional information about the package. +In our example, META looks like + + + +description = "Our super-duper package" +requires = "" +version = "1" +archive(byte) = "p.cma" + + +The variable "requires" contains a list of packages that are +required by this package (the names may be separated by commas or +spaces). As our package, p, does not depend on any other package, this +list is empty. I'll explain what happens with non-empty lists below. + + + +The variable "version" is simply a version string, and "description" +is a short comment on the package. + + +The variable "archive" denotes the files that have to be +actually linked in if the package is used. This is again a list of +(file) names. In contrast to the other variables, "archive" has a +condition, written in parantheses. This value of "archive" will only +be used if the predicate "byte" is true; this predicate is usually +given if the program is compiled to bytecode. If you have a native +archive, p.cmxa, of the two modules M1 and M2, you can add another +line to META: + + + +archive(native) = "p.cmxa" + + + +The correct value for the "archive" variable is selected upon the +given set of predicates. + + +Many packages can also be loaded at runtime with the +Fl_dynload module. In this case, though, the +variable "plugin" is used instead of "archive", e.g. + + +plugin(byte) = "p.cma" +plugin(native) = "p.cmxs" + + +(You can create p.cmxs from p.cmxa with +"ocamlopt -shared -linkall -o p.cmxs p.cmxa".) Note that "plugin" is entirely optional. + + + + +Querying information stored in META files + + +By setting some options of ocamlfind you can query the variables from +the META files. For example, -long-format (or short -l) selects all +interesting variables: + + + +ocamlfind query -long-format p + + + +This would answer something like: + + + +package: p +description: Our super-duper package +version: 1 +archive(s): +linkopts: +location: /usr/local/lib/ocaml/site-lib/p + + + +The values of the "archive" variable are missing because no predicate +has been set, without further options "ocamlfind query" operates with +an empty set of predicates. To get the bytecode archive, run: + + + +ocamlfind query -long-format -predicates byte p + + + +You can set more than one predicate. It usually does not make sense, but +you could for example select both bytecode and native archives by: + + + +ocamlfind query -long-format -predicates byte,native p + + + +As both settings for "archive" are now equally like, the extraction +mechnism chooses simply the first. The general rule is that the first +most special value is selected. + + + + + +How to compile and link a program that uses a package + + +Now suppose you want to compile a program which calls functions of +your new package p. If prog1.ml, prog2.ml, and prog3.ml are the three +source files the program consists of, compile them with the commands + + + +ocamlfind ocamlc -package p -c prog1.ml +ocamlfind ocamlc -package p -c prog2.ml +ocamlfind ocamlc -package p -c prog3.ml + + + +The "ocamlfind ocamlc" invocation is a frontend to "ocamlc". Most +arguments are directly passed to "ocamlc", but there are a few new +options, and often some new options are implicitly added. Here, the +new -package option is used, which adds search paths such that the +modules of package p are found. Effectively, the following direct +ocamlc invocations would be equivalent +If you specify the -verbose option, the constructed +command is printed to the terminal. Actually, there are some more +implicitly added options, especially -ccopt -I<dir> for every +package directory <dir>. This means that you can compile C +programs accessing header files stored in the package directory. +: + + + +ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog1.ml +ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog2.ml +ocamlc -I /usr/local/lib/ocaml/site-lib/p -c prog3.ml + + + +The -I option has the effect that the named directory is also searched +when looking up cmi files. Because of this you can refer directly to +the modules M1 and M2 in the program sources. + + + +In order to link the program use the following command: + + + +ocamlfind ocamlc -o program -package p -linkpkg prog1.cmo prog2.cmo prog3.cmo + + + +The -linkpkg option causes some more arguments to be added to the +constructed ocamlc command. Especially, the name of the archive of p +is extracted from the META file, and automatically inserted before the +prog1.cmo argument. The resulting command looks like +Again, the actual command contains even some more arguments... +: + + + +ocamlc -o program -I /usr/local/lib/ocaml/site-lib/p p.cma prog1.cmo prog2.cmo prog3.cmo + + + +Please note that the bytecode archive p.cma has been selected, and not +the native archive p.cmxa. As it is known that the bytecode compiler +is used, the predicate "byte" is automatically set. + + + + + + +Dependencies + + +Often packages use other packages themselves. Let q be another package +consisting of the single module M3 which contains references to M1 and +M2. At the first glance, we can ignore this when describing the +package, as we could always add "-package p" and "-package q" options +when compiling programs using q. This solution is not optimal, as the +user of a package must have knowlege about details of the package that +should normally be hidden. When we introduced the notion of packages, +one of the most important properties was that we can replace packages +by improved versions. Imagine that q is replaced by q', but q' uses +not only p but also r. Every program that used q and is now forced to +use q' must be changed (at least in the Makefile) in order to link r, +too. This is clearly not what is intended by packages. + + + +The far better solution is to store dependency information in the META +files. The "requires" variable can list names of packages that are +direct ancestors, i.e. referred directly. (Do not put indirect +ancestors into this variable, for example further packages required by +r when describing q - these are found out automatically.) The META +file of q looks like: + + + +description = "Something that needs p" +requires = "p" +version = "1" +archive(byte) = q.cma +archive(native) = q.cmxa + + + +If you want to put several package names into "requires", separate +them with commas or spaces. + + + +The "ocamlfind query" command ignores the "requires" value by default, +you must add the -recursive option. In this case, all direct or +indirect ancestors of the packages given on the command line are +selected, too, and printed in topological order. For example, the +command + + + +ocamlfind query -recursive -long-format -predicate byte q + + + +prints two records: + + + +package: p +description: Our super-duper package +version: 1 +archive(s): p.cma +linkopts: +location: /usr/local/lib/ocaml/site-lib/p + +package: q +description: Something that needs p +version: 1 +archive(s): q.cma +linkopts: +location: /usr/local/lib/ocaml/site-lib/p + + + +Without -recursive, only q would have been printed. + + + +The compiler frontend provided with ocamlfind always works +recursively. In order to compile and link another.ml that uses q, the +following command is sufficient: + + + +ocamlfind ocamlc -o another -package q -linkpkg another.ml + + + +It is not necessary to specify -package p in this statement as the +dependency relation is always used to find out the actually meant +set of packages. + + + + + + +Linker options + + + +Beginning with OCaml 3.00, the compiler itself has an interesting feature +called "automatic linking" that makes the following mechanism superflous in +most cases. Automatic linking means that it is possible to store the linker +options into the cma or cmxa file such that the compiler itself knows which +options are necessary. Of course, the following mechanism still works, and it +is still helpful when conditional linking is required. + + + + +OCaml has a C interface which means that C libraries can be linked in +and C functions can be declared as new language primitives. Using such +libraries requires special linker options. Some of the core libraries +distributed with OCaml are partly implemented in C and thus additional +libraries must be specified in the linking phase of the program. + + + +For example, the "str" library providing regular expressions requires +to be linked as follows: + + + +ocamlc -o prog str.cma my_file1.cmo my_file2.cmo -cclib -lstr + + + +The -cclib option passes the following argument directly to the +underlying C linker which has the effect that libstr.a is linked in, +too. The "-cclib -lstr" is directly associated with str.cma as the +latter simply cannot be used without the former. Assume you would +write a META file describing str. That "str.cma" should be linked in +as archive is clear; the "-cclib -lstr" can be specified in another +variable called "linkopts". The META file would look like: + + + +requires = "" +version = "str from ocaml 2.02" +archive(byte) = "str.cma" +archive(native) = "str.cmxa" +linkopts = "-cclib -lstr" + + + +This has the effect that specifying -linkpkg in one of the compiler +frontends not only chooses one of the archive files, but also extracts +the necessary linker options from the META file. The above example can +also be compiled with: + + + +ocamlfind ocamlc -o prog -package str -linkpkg my_file1.cmo my_file2.cmo + + + +Most people will never write META files with "linkopts" settings. But +this feature is very useful at least for the core libraries such as +str. Because of this, the "findlib" distribution comes with META files +for the core libraries in order to hide the linker options. This +means that you can already use the packages "str", "dbm", "dynlink", +"graphics", "num", "threads", "unix", and "camltk", and that the +appropriate archives and linker options are automatically extracted. + + + + + + + + + +Dependency analysis of packages + + +Querying ancestors + + +Every package denotes in its META file only the list of direct +ancestors. The theoretical model of the dependency relation is a +directed acyclic graph (DAG), with the packages as vertices and edges +from packages to their direct ancestors. The graph must be acyclic +because OCaml does not allow cyclic dependencies between modules. + + + +What happens if you query something like + + + +ocamlfind query -recursive p1 p2 ... pN + + + +is that the named packages p1 to pN are marked in the graph, and that +repeatedly all direct ancestors of marked packages are marked, too, +until there is not any marked package remaining with an unmarked +ancestor. All marked packages are then printed in topological +order. This simply means that for the printed packages p1 to pM holds +that if pI is printed before pJ then pI is a (possibly indirect) +ancestor of pJ. + + + +The topological order plays a role when the link command is +constructed by "ocamlfind ocamlc", as Ocaml requires that archives +must be linked in topological order. For example, the link statement + + + +ocamlfind ocamlc -o another -package q -linkpkg another.ml + + + +must be turned into the effective command + + + +ocamlc -o another [...more options...] p.cma q.cma another.ml + + + +and not + + + +ocamlc -o another [...more options...] q.cma p.cma another.ml + + + +because there are references from q.cma to p.cma. + + + +In C, there is a similar requirement when linking static archives. The +linker backend ld wants the archives in reversed +topological order, i.e. the deepest ancestor must come last in the +list of linked archives. Because of this, the additional linker +options specified in the "linkopts" variable are passed in reversed +order to the underlying linker. This means that you can refer to C +libraries of ancestor packages of p in C libraries provided in p. + + + +Note that most operating systems do not require any specific order for +dynamically linked C libraries (the exception is, surprise!, AIX). + + + + + + +Querying descendants + + +It is often useful to find out the descendants of a package, i.e. all +direct or indirect users of the package. There is another "ocamlfind" +subcommand that allows us to query descendants. For example, to get +the direct and indirect users of p, type in + + + +ocamlfind query -descendants p + + + +The set of packages that are possible descendants is determined as +follows: + + + + +All packages located in directories mentioned in the environment +variable OCAMLPATH are candidates. Note that only package directories +containing META files are taken. + + + + + +The packages in the default package directory are candidates, too. + + + + + +If there are two packages with the same name, only the first +counts, i.e. the first in OCAMLPATH, then the one in the default directory. + + + + +After this set has been determined, the complete dependency graph is +constructed on it. As the descendants are queried, the dependencies +are read in the inverse way compared with queries of the ancestors. + + + + + + + + + + +A new frontend for ocamlc + + +Compiling and linking + + +There are compiler frontends for the four compilers ocamlc, ocamlopt, +ocamlmktop, and ocamlcp. They are simply called by specifying the name +of the compiler as first argument to ocamlfind, i.e. + + + +ocamlfind ocamlc ...arguments... +ocamlfind ocamlopt ...arguments... +ocamlfind ocamlmktop ...arguments... +ocamlfind ocamlcp ...arguments... + + + +In addition to the compiler options handled by the compilers +themselves, the following options are available: + + + + + +-package <name>: Causes that the package <name> is added to +the package list, and that -I options are added for every package, and +all direct or indirect ancestors. + + + + + +-linkpkg: Causes that the archives of the packages in the package list +and all their direct or indirect ancestors are added in topological +order to the command line before the first file to compile or to +link. Packages specified by -dontlink are not linked in, though. +Furthermore, the linker options of these packages are added in +reverse topological order at the end of the command line. + + + + + +-predicates <predicate-list>: The named predicates are included +in the list of predicates. Note that there are some predicates set by +default, see below. + + + + + +-dontlink <name>: Specifies that the package <name> and +all its direct or indirect ancestors should not be linked in. + + + + + + +-passopt <opt>: The option <opt> is passed directly to the +underlying compiler. This is especially needed to pass undocumented +options to the compiler. + + + + + +If you only want to compile, i.e. the -c option is in effect, you +normally only need the -package option. + + + +Depending on the compiler and on the given options, some predicates +are set by default: + + + + + +byte: The predicate "byte" is set when ocamlc, ocamlcp, or ocamlmktop +is used to compile or link. + + + + + +native: The predicate "native" is set when ocamlopt is used to compile +or to link. + + + + + +toploop: The predicate "toploop" is set when a toploop is being executed + + + + + +create_toploop: The predicate "toploop" is set when ocamlmktop is used to +compile or to link a toploop + + + + + + +gprof: The predicate "gprof" is set when ocamlopt with -p option is +invoked. + + + + + +mt: The predicate "mt" is set when the -thread or the -vmthread option is in effect. + + + + + +mt_posix: The predicate "mt_posix" is set together with "mt" if the +POSIX thread implementation is selected. + + + + + +mt_vm: The predicate "mt_vm" is set together with "mt" if the bytecode +thread implementation is selected. + + + + + +autolink: The predicate "autolink" is set if the OCaml compiler can perform +automatic linking. This predicate is never set if the -noautolink option is +in effect. + + + + + + + + + +Toploops and runtime systems + + +Dynamic toploops + + +Recent versions of OCaml support dynamic loading of stub libraries +(but only for the more widely used operating systems). This means +that one can start a toploop by running + + +$ ocaml + Objective Caml version 3.07+2 + +# _ + + +and that it is now possible to load .cma archive files referring to +shared C libraries ("DLLs"). In older versions of OCaml this was +not possible and one had to create a so-called custom toploop +with the ocamlmktop command. This method is still supported and +explained below; however, nowadays it is often not necessary to +do so. For the modern way, findlib includes a small script called +"topfind" (i.e. "ocamlfind for the toploop") that can be directly +loaded into the toploop: + + +# #use "topfind";; +- : unit = () +Findlib has been successfully loaded. Additional directives: + #require "package";; to load a package + #list;; to list the available packages + #camlp4o;; to load camlp4 (standard syntax) + #camlp4r;; to load camlp4 (revised syntax) + #predicates "p,q,...";; to set these predicates + Topfind.reset();; to force that packages will be reloaded + #thread;; to enable threads + +- : unit = () +# _ + + + + +A number of additional directives are now available. The "#require" +directive loads additional packages (with all dependencies): + + + +# #require "q1,q2,...,qM";; + + + +"#require" loads the listed packages and all their ancestors in the +right order, but leaves packages out that have already been loaded. +Scripts can now simply load and document which packages are used by a +"#require" directive right at the beginning of the script. + + + +The #list directive lists the available packages as "ocamlfind list" +would do it. + + +If you need additional predicates, you can set them with #predicates. +Note that this should be done before the first package is loaded in +order to ensure a consistent library system. + + +The #thread directive enables multi-threading if possible. Note that +this is only supported for installations basing on the POSIX thread +library. (However, if you have only have VM threads, you can still +create a custom toploop supporting threads. See below.) Furthermore, +the #thread directive should be executed before any packages are +loaded. + + + +The #camlp4o and #camlp4r directives load the camlp4 syntax parsers +for the standard and the revised syntax, respectively. + + + +Especially when developing packages, it is sometimes necessary to +reload all dynamically loaded packages in the toploop. This can be +forced by + + + +Topfind.reset();; + + + +which causes the "#require" directive to load all packages again. The +Topfind module implements all the mentioned directives. + + + + +Custom toploops + + +It is very simple to create toploops. In order to make a toploop +executable that includes directly the packages p1,p2,..,pN simply +execute the command + + + +ocamlfind ocamlmktop -o toploop -package p1,p2,...,pN,findlib -linkpkg + + + +(Maybe you have to add the -custom switch.) Note that one of the +packages should be "findlib" itself, because this adds the +additional directives mentioned above, i.e. you can directly use +these directives without #use "topfind" (but running "topfind" +is harmless). + + + +Note that such a toploop includes the code of the packages given +on the commmand line, but that it does not automatically add the +package directories to the search path (in previous versions of +findlib this was tried, but it never really worked). To do so, +you still have to #require the packages. + + + +In order to create a toploop supporting VM-style threads, use the +command + + +ocamlfind ocamlmktop -o toploop -package p1,p2,...,pN,findlib,threads -vmthread -linkpkg + + +Now the #thread directive will work and enable the access to the +multi-threading modules. + + + + +Runtime systems + + +Building of runtime systems is supported, too. For example, you can run + + + +ocamlfind ocamlc -o runtime -make-runtime -package p1,p2,...,pN -linkpkg + + + +but the problem is which options to specify when a program is linked +for this runtime system. If you executed + + + +ocamlfind ocamlc -o program -use-runtime runtime -package p1,p2,...,pN\ + -linkpkg m1.cmo ... mM.cmo + + + +it would be tried to link the archives from the packages again into +the bytecode binary. Because of this, it is necessary to suppress +linking in packages of the runtime system when linking binaries for a +runtime system. The -dontlink option can be used for this: + + + +ocamlfind ocamlc -o program -use-runtime runtime -package p1,p2,...,pN\ + -dontlink p1,p2,...,pN -linkpkg m1.cmo ... mM.cmo + + + +Note that the -package option can enumerate more packages than +-dontlink, and in this case the additional packages are actually +linked in as they are not contained in the runtime system. + + + + + + + +Multi-threaded applications + + +If an already existing package is planned to be used in a +multi-threaded environment, some language constructs must be replaced +by different ones. For example, global variables must be protected by +locks (mutexes). Because of +this it is common practice to provide two versions of such packages, +one for single-, one for multi-threaded applications (or, another +technique, there is a special add-on module that initializes a +library for multi-threaded usage). + + + +The predicate "mt" should be used to recognize multi-threaded +applications. For example, a package could consist of two archives, +p.cma, and p_mt.cma, where the latter archive is designed for +multi-threaded execution. The META file would contain the following +lines causing that always the appropriate archive is linked: + + + +archive(byte) = "p.cma" +archive(byte,mt) = "p_mt.cma" + + + +When querying the package database the option "-predicates mt" must be +included in the commands in order to select the appropriate entries. + + + +When compiling or linking it is necessary to specify either the +"-thread" or the "-vmthread" option anyway. The compiler frontends +detects these options, and automatically set the "mt" +predicate. The following command is an example for this; note that the +"threads" package means the standard library of Ocaml providing thread +support: + + + +ocamlfind ocamlc -thread -package threads,p,q -c x.ml + + + +For some operating systems, Ocaml supports the native multithreading +libraries conforming to the POSIX interface. As the linker options are +generally different, another predicate must be set to get these +libraries linked in. The predicate "mt_posix" indicates POSIX +threads while "mt_vm" indicates bytecode (virtual machine) threads. + + + + + + +Support for gprof-enabled modules + + +When a program is compiled and linked with ocamlopt, gprof-style +profiling can be enabled by selecting the -p option. This means that +the resulting archives are different, and that it would be useful if +there were another predicate in order to select such archives. + + + +The predicate "gprof" can be used for this. It is automatically set if +the -p option turns on the gprof-mode in an ocamlopt invocation. + + + + + + + + + +Complex packages + + +The standard predicates + + +Settings in the META file have usually the form: + + + +varname ( predname1, predname2, ... ) = "value" + + + +The names in the parantheses are called formal +predicates and express a condition which must hold such +that the value on the right side is selected. When querying +information you can specify a set of actual +predicates that are assumed to be true. There are the +following standard predicates: + + + + + +The "byte" predicate means that the bytecode compiler is used. + + + + + +The "native" predicate means that the native compiler is used. + + + + + +The "toploop" predicate means that the toploop is available in the +linked program. + + + + + +The "mt" predicate means that the program is multi-threaded. + + + + + +The "mt_posix" predicate means that in the case "mt" is set, too, the +POSIX libraries are used to implement threads. + + + + + +The "mt_vm" predicate means that in the case "mt" is set, too, the +VM-based libraries are used to implement threads. + + + + + +The "gprof" predicate means that in the case "native" is set, too, the +program is compiled for profiling + + + + + +The "autolink" predicate indicates that ocamlc is able to perform +automatic linking. + + + + + + + +It is possible to have more predicates indicating different +environments; just use them, it is not necessary to declare them +anywhere. + + + +The value which is selected for a variable depends on the set of +assumed predicates. In order to get selected, all formal predicates +must be included in the set of actual predicates; if still +multiple values fulfill this condition, the value with the maximum +number of formal predicates is used; and if still in doubt, the first +of these in the META file is taken. + + + +It is possible to negate a formal predicate: Just prepend a minus +sign to it, e.g. var(p,-q). In this case, it is required that the +negated predicates are false (not contained in the set of actual predicates). + + + +For all variables that are evaluated after the dependency analysis, +findlib adds the so-called package predicates to the set of actual +predicates. For every selected package p the predicate pkg_p +(with the fixed prefix "pkg_") is added. One application of this +are compatibility checks: The special error variable +is evaluated after dependency analysis, but before anything else +is done. For example, to state that package p is incompatible with +package q one can add to the META file of p: + + +error(pkg_q) = "Package p is incompatible with q" + + +The value of error is printed as message in the +case the condition is true. + + + + + +Defining additional predicates + + +Additional predicates can be simply used without any declaration, +i.e. you can freely invent new predicates. One application of them +is to express conditional linkage. For example, one may provide archives +for various conditions, such as a production archive, and a +development archive. A single new predicate, "development", would be +sufficient to express this: + + + +archive(byte) = "p_production.cma" +archive(byte,development) = "p_development.cma" + + + +When linking, include a "-predicates development" argument in the +compiler command to select the development archive, otherwise the +production archive is taken. + + + +Predicates could also be used to select among several implementations +of the same module. Define simply one predicate per implementation, +e.g. "p_impl1", "p_impl2", and "p_impl3", and specify the archives for +every implementation separately: + + + +archive(byte,p_impl1) = "p_impl1.cma" +archive(byte,p_impl2) = "p_impl2.cma" +archive(byte,p_impl3) = "p_impl3.cma" + + + +In the case that the implementations have different dependencies, +simply provide multiple "requires" variables: + + + +requires(p_impl1) = "q" +requires(p_impl2) = "q,r" +requires(p_impl3) = "r,s" + + + +Sometimes, the implementations require different linker options. In +this case, define several versions of the "linkopts" variable just +like in the "requires" example. + + + +Note that predicates are global identifiers that can be potentially +applied to every selected package. In the case that a predicate is +only meaningful for a single package, it is common practice to +choose the package name as prefix of the predicate name (e.g. +"netstring_minimum" is a predicate usually only applied to the "netstring" +package). + + + +Predicates could be used to select which features of a library are +linked. For example, + + +archive(byte) = "p_basic.cma" +archive(byte,p_extension) = "p_basic.cma p_ext.cma" + + +would add the p_ext.cma archive only if the p_extension predicate +were set. It is considered as bad practice to select +extensions of libraries by predicates. Findlib provides the construct +of subpackages for this purpose. + + + + + + Appending to variables + +The syntax + + +varname ( predname1, predname2, ... ) += "value" + + +(note the "+=" operator) can be used to append values to variables +depending on whether predicates are true. The "+=" lines in the META +file are evaluated one after the other, and every +line is selected for which the formal predicates are satisfied, +and these lines are added to the current value of the variable. This is +different from the "=" operator where only the most specific +assignment is taken. + + +The values are considered as space-separated words when they +are appended, i.e. the new words are added to the list of current +words. + +For example, in the hypothetic META file + + +var(p) += "a" +var(p,q) += "b" + + +the value of var is "a b" if both p and q are true, and the value is +only "a" is only p is true (and the value is empty otherwise). If +the operator "=" had been used, the value would have been only "b" +when both p and q are true. + +In the case that there both "=" and "+=" settings for +the same variable, a special algorithm is used: First the most specific +"=" setting is determined, and second all matching "+=" settings are +appended in the order they appear in the file. + +Finally, here is a real-world example. Imagine you have an +archive p.cma and a special extension for the toploop, p_top.cma. +Furthermore, there is a special debugging version p_dev.cma that +replaces p.cma during development. You can now simply write + + +archive(byte) = "p.cma" +archive(byte,development) = "p_dev.cma" +archive(byte,toploop) += "p_top.cma" + + +to select either p.cma or p_dev.cma, and append +p_top.cma for toploops to whatever was selected in the first step. + + + + + + Subpackages + + +Sometimes a package consists of several archive files that are closely +related. It is now possible to express dependencies between these +archives by splitting the package into several parts called subpackages. +For example, package p consists of a base archive p_base.cma, and two +extensions p_ext1.cma and p_ext2.cma that both require the base archive +but are independent of each other. This META file expresses this +dependency directly: + + +# META file of package p: +requires = "p.base" + +package "base" ( + archive(byte) = "p_base.cma" +) + +package "ext1" ( + requires = "p.base" + archive(byte) = "p_ext1.cma" +) + +package "ext2" ( + requires = "p.base" + archive(byte) = "p_ext2.cma" +) + + +If installed as package "p", this definition actually defines four +logical packages: "p" (the main package), "p.base", "p.ext1", and +"p.ext2" (the subpackages). These four entities only share the META +file in which they are declared, and the directory where the archive +files are stored, but all other properties can be individually set +for each package. This also means that all package dependencies +must explicitly added by "requires" variables, as there are no +implied dependencies. In this example, the main package and "p.ext1" +and "p.ext2" are all dependent on "p.base". + + + +The users of this installation can refer to all four packages. This +means that + + +ocamlfind ocamlc -package p -linkpkg ... + + +links only p_base.cma into the final program, while + + +ocamlfind ocamlc -package p.ext1 -linkpkg ... + + +selects both p_base.cma and p_ext1.cma. + + + + + + Glue code + +Imagine we have two packages p and q that are normally +independent, i.e. one can link p without q, and q without p. However, +when both p and q are used in the same program, it is expected that +they cooperate with each other. Of course, this situation can be +modeled with the help of subpackages (a real-world example of this are +p=lablgtk and q=lablgl). + +The idea is as follows: p has a subpackage p.for_q that contains +code with special features for q, and q has a subpackage q.use_p that +depends on p, p.for_q, and q, and that contains the code using the +special features of p. Expressed in META files, p would define + + +# META file for p: +requires = "..." +archive = "..." + +package "for_q" ( + requires = "p" + archive = "..." +) + + +and q would define + + +# META file for q: +requires = "..." +archive = "..." + +package "use_p" ( + requires = "q,p.for_q" + archive = "..." +) + + +Of couse, the program using both libraries must explicitly enable +the subpackages by mentioning "q.use_p" on the ocamlfind command line, +otherwise the glue code would be omitted. + + + +Unfortunately, it is not possible to use the package predicates +pkg_p and pkg_q to add archives depending on whether the other +package is also selected. The problem is that the order cannot +be specified, i.e. whether p must be linked first or q. + + + + + + +Plugins + +(Since findlib-1.6.) + + +Plugins are packages that can be loaded at runtime. Plugins are +intended as a mechanism for loading add-on code into +executables. Technically, there is some overlap with the concept of a +"shared library". Note, however, that there is no universal support +for plugins, as it is unimplemented on some platforms, and only +poorly on some others (including x86 in the 32 bit case). Also, there +must always be an explicit "load" statement in the loading executable. +You cannot link an executable directly against plugins. + + +Preparing a plugin + +For bytecode there is no problem to load cma files at runtime. +For native-code, though, you need to convert cmxa files into cmxs +files first: + + +ocamlopt -shared -linkall -o m.cmxs m.cmxa + + +As mentioned, be prepared that this command fails on platforms where +plugins are unavailable. + +The cmxs files can then be referenced from META. We don't use +the "archive" variable in this case but "plugin": + + +plugin(byte) = "m.cma" +plugin(native) = "m.cmxs" + + +Before findlib-1.6, there was some half-official convention using the +"plugin" predicate. This is still supported, but deprecated: + + +archive(byte) = "m.cma" +archive(native,plugin) = "m.cmxs" + + + +Load-time dependencies +Plugins can be, of course, be dependent on other +plugins. You run into a problem, though, when you make a plugin dependent +on a package that doesn't qualify as plugin (i.e. lacks the "plugin" +definition). In this case, the loader simply skips the dependency, +and you cannot load the plugin. + +Because of this dependency issue, it is recommended to add the +"plugin" variable to all packages that are installed on a system, +because this does not only allow it to load all packages at runtime, but +also to use these packages as dependency of the actual plugin code. + +That said, you just need to add a "requires" directive, e.g. + + +requires = "pkg1" +plugin(byte) = "m.cma" +plugin(native) = "m.cmxs" + + + + +How to load a plugin +Linking an executable that can load a plugin: An executable +must link the package "findlib.dynload". This does not only add +the loader, but also special initialization code to the executable: + + +ocamlfind ocamlopt -o program -package findlib.dynload -linkpkg ... + + +In particular, this records the packages that are already included +into the executable (in-core packages). If a plugin is now dependent +on such a package, this is recognized, and the package is not loaded +(which would not work anyway). + +Now, you can load a plugin "foo" with: + + +Fl_dynload.load_packages ["foo"] + + +This loads the cma or cmxs files, and runs the initialization code +of all top-level definitions of the included modules. + +Of course, you can also call load_packages from +a library if "findlib.dynload" is a required package of the library +package. + + +Fat plugins +Sometimes it is handy to create plugins that already include all +the required packages. The plugin acts more like a dynamically loadable +executable that already includes whatever it needs. You can create such +a "fat" plugin with: + + +ocamlfind ocamlopt -shared -linkpkg -linkall -o m.cmxs -package p1,p2,p3 m.cmxa + + +In this case, the "requires" line in the META file should remain empty. + + + +Note, however, that you cannot handle packages this way that are already +linked into the main program, because it is invalid to load a module that +is already part of the main executable. Let's assume that the executable +links in q1, q2, and q3. Then, you need to exclude these packages from the +plugin. The -dont-link option comes handy in this case: + + +ocamlfind ocamlopt -shared -linkpkg -linkall -o m.cmxs -package p1,p2,p3 -dont-link q1,q2,q3 m.cmxa + + +This excludes q1,q2,q3 even if these packages occur as dependencies of +p1,p2,p3. In this case, though, you need to put q1,q2,q3 into the "requires" +field of META. + + + + + + + +Lint + +(Since findlib-1.6.) + + +As it has become more and more complicated to write correct META files +there is now some support for recognizing typical problems. Just use + + +ocamlfind lint META + + +to check the file META in the current directory. The tool reports problematic +lines in META, e.g. + + +archive(byte,plugin) = "oUnit.cma" +This specification of dynamic loading is deprecated, you should add a "plugin(...)" variable. + +archive(native,plugin) = "oUnit.cmxs" +This specification of dynamic loading is deprecated, you should add a "plugin(...)" variable. + + + + + + + + + + +How to create your own packages + + +Installing and removing packages + + +The ocamlfind command can install and remove packages. For example, +to install a package p containing the files META, m1.cmi, m2.cmi, p.cma, +run + + +ocamlfind install p META m1.cmi m2.cmi p.cma + + +This installs the files into the default location for new packages +(set in ocamlfind.conf). If you have files that are not always built, +add these after the -optional switch: + + +ocamlfind install p META m1.cmi m2.cmi p.cma -optional p.cmxa p.cmxs + + +To remove the package, run + + +ocamlfind remove p + + +Note that every package must have a META file, it is not possible to +omit it. + + + + + +Change your Makefile + + +Here is a commented version of a Makefile that may be used to compile +and link a package. It describes the frequent case that the package +simply consists of a bundle of modules that are dependent on other +packages. + + + +First, some general definitions. NAME is the name of the package. The +OBJECTS variable enumerates the bytecode objects, whereas XOBJECTS +names the native objects. The same naming convention is used for +ARCHIVE and XARCHIVE, specifying the resulting bytecode, resp. native +archive file. The REQUIRES variable lists the names of the packages +that are needed for this package. If you need additional predicates, +put them into the PREDICATES variable. + + + +NAME = p + +OCAMLC = ocamlfind ocamlc +OCAMLOPT = ocamlfind ocamlopt +OCAMLDEP = ocamldep + +OBJECTS = p1.cmo p2.cmo +XOBJECTS = p1.cmx p2.cmx + +ARCHIVE = $(NAME).cma +XARCHIVE = $(NAME).cmxa +SARCHIVE = $(NAME).cmxs + +REQUIRES = unix str q r s +PREDICATES = + + + +The default goal is "all", causing the bytecode archive to be +created. In order to get a native archive, choose "opt" as second goal. +(The ".PHONY" line is a declaration meaningful for GNU-make; "all" and +"opt" are only virtual goals as there no files "all", or "opt" which +is indicated by making them dependents of ".PHONY".) + + + +.PHONY: all opt +all: $(ARCHIVE) +opt: $(XARCHIVE) $(SARCHIVE) + + + +The following two rules create the bytecode resp. native archive from +the objects. + + + +$(ARCHIVE): $(OBJECTS) + $(OCAMLC) -a -o $(ARCHIVE) -package "$(REQUIRES)" -linkpkg \ + -predicates "$(PREDICATES)" $(OBJECTS) +$(XARCHIVE): $(XOBJECTS) + $(OCAMLOPT) -a -o $(XARCHIVE) -package "$(REQUIRES)" -linkpkg \ + -predicates "$(PREDICATES)" $(XOBJECTS) + +$(SARCHIVE): $(XARCHIVE) + $(OCAMLOPT) -shared -o $(SARCHIVE) $(XARCHIVE) || true + + + +Note that the cmxs archive is optional: we just ignore the error +when it cannot be built. + + + +These rules compile the modules independently. The lines similar to +".ml.cmo" must be read: "How to transform files with suffix .ml into +files with suffix .cmo". The corresponding command can refer to the +input file as "$<" and to the output file(s) as "$@". + + + +.SUFFIXES: .cmo .cmi .cmx .ml .mli + +.ml.cmo: + $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \ + -c $< +.mli.cmi: + $(OCAMLC) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \ + -c $< +.ml.cmx: + $(OCAMLOPT) -package "$(REQUIRES)" -predicates "$(PREDICATES)" \ + -c $< + + + +The "depend" goal is the file describing the dependencies within the +package; it is created by ocamldep. + + + +depend: *.ml *.mli + $(OCAMLDEP) *.ml *.mli >depend +include depend + + + +The "install" rule is a bit tricky. First it is tested if there is a +native archive to install, and if so, the variable "extra" contains +the corresponding files. The "ocamlfind install" command creates a new +package directory and puts the given files into it. + + + +.PHONY: install uninstall +install: all + ocamlfind install $(NAME) *.mli *.cmi $(ARCHIVE) META \ + -optional $(XARCHIVE) $(SARCHIVE) + +uninstall: + ocamlfind remove $(NAME) + + + +Last but not least a cleanup rule: + + + +.PHONY: clean + rm -f *.cmi *.cmo *.cmx *.cma *.cmxa *.a + + + + + +Using the Makefile wizard + + +Especially for beginners, the findlib distribution includes a GUI to +create Makefiles. As this is an optional feature, it must have been +selected when findlib was built (option -with-toolbox). To invoke the +GUI, run the command + + +$ ocamlfind findlib/make_wizard + + +(Btw, this is the general syntax to run executables installed in +package directories.) The wizard starts, and allows you to describe +your project. When you save the result, not only a "Makefile" is +created, but also the file ".make-wizard" containing the state. +If you later start the wizard again, this file will be automatically +loaded, and you can modify your definition. + +The wizard consists of seven (hopefully self-explanatory) pages +you can fill out. The basic idea is that the .ml, .mli, .mly, and .mll +files in the current directory are compiled to a .cma or .cmxa +archive, and that optionally executables are created from this archive +and from additional modules (main programs). This scheme can be both +used for libraries and application programs. + +You can choose packages you want to use in your library or +program by clicking at them in a selection box. The camlp4 syntax +parsers can be optionally enabled. The modules to be compiled can +be picked from the current directory, they must be selected in the +right order, however. + +The generated "Makefile" defines a number of logical targets +(like "all", "opt", etc) that are explained at the beginning of the +file. The file is fully commented, and not very difficult to understand. +Only traditional Makefile syntax is used, so it is expected that it +works for every version of the "make" utility. + + +When you build the project, the META file is created +dynamically. If you do not like this, set the variable MAKE_META to +the empty string. (It is a good idea to put such setting into a +second file, and enter the name of this file into the box "Local +extensions in" of the wizard, so you can generate the "Makefile" again +without overwriting your own modifications. This second file can +override the setting in the generated "Makefile".) + + + + + + + + + + +FAQs + + +Does findlib support the autolink feature of OCaml 3? + + +Short answer: Findlib is compatible with autolink + + + +The new archive format introduced with OCaml 3 can store the linker options +that are necessary to link an archive. For example: + + +ocamlc -a -o myarchive.cma mymodule.cmo -cclib -lmylibrary + + +This command does not only create the new archive +myarchive.cma, but it also writes into a special section of +that file that the linker option -cclib -lmylibrary is +necessary to link this archive. + + + +This means for findlib that most of the "linkopts" attributes in META files +have become superflous: The compiler itself already knows the linker options, +we do not need to tell the compiler the options. We could simply leave all +"linkopts" attributes out. + + + +Of course, the "linkopts" feature of findlib still works. This is necessary +because findlib should keep the compatibility with older software, and because +"linkopts" is more powerful (you can have conditional linker options). + + + +If you have software that must run in both OCaml 2 and OCaml 3 environments, +you can make your "linkopts" attribute dependent on the "autolink" +predicate. For example: + + +linkopts = "-cclib -lmylibrary" +linkopts(autolink) = "" + + +The findlib installation for OCaml 3 will take the second line which is +reasonable because ocamlc already knows how to link; the installation for +OCaml 2 never sets the "autolink" predicate and therefore uses the first line. + + + + + + + Why does findlib not automatically include the -custom option if +linked with C code? + + Short answer: +Because there are several ways of linking, and findlib is not the +right instance to find out the right way + + Recent versions of OCaml support DLLs, at least for some +platforms. Here, the option -custom is not necessary at all, because the +C libraries can be looked up and loaded at runtime. The option -custom +would have the effect of forcing static linking. + + But even for platforms without DLL support, there are two +alternatives. One possibility is to use -custom, and the other is to +create runtime systems with -make-runtime, and reference them with +-use-runtime. Fortunately, recent versions of OCaml select now themselves +-custom automatically if -make-runtime is omitted, so findlib needs not to +bother with it. + + + + + + + Does findlib support linking of applications as well as +packages? + + +Short answer: Yes, but it is not very obvious + + +Applications also depend on other components, they have predicates, sometimes +they need linker options; there seems to be only little difference between +applications (stand-alone programs) and packages. If you want to use the +findlib mechanisms for applications, too, the following trick helps. + + + +The environment variable OCAMLPATH may contain a +colon-separated path of possible sitelib locations. It is allowed to include +"." into the path (Shell commands follow): + + +OCAMLPATH=. +export OCAMLPATH + + +This makes ".", i.e. your current directory, another sitelib location. You may +now put the components of your applications into subdirectories together with +META files; the hierarchy might look as follows: + + +./Makefile global Makefile +./localpkg1/META first local package directory: Contains META +./localpkg1/... ... and more +./localpkg2/META second local package dir: Contains META +./localpkg2/... ... and more +... + + +From findlib's point of view, these directories are now package directories, +and you can refer to them on the command line: + + +ocamlfind ocamlc -o ... -linkpkg -package localpkg1,localpkg2,... + + +If you do not want subdirectories, you can also refer to the META file in the +same directory by the name ".", e.g.: + + +ocamlfind ocamlc -o ... -linkpkg -package . + + +In this case, the linking information will be taken from +./META. + + + + + + + Does Findlib support camlp4? + + + + Short answer: Yes, but there is only little + documentation. + + + Since Findlib-0.4, there is some experimental camlp4 support. For +example, the following compiler invocation chooses the revised syntax: + + +ocamlfind ocamlc -syntax camlp4r -package camlp4 -c file.ml + + + As you can see, camlp4 must be included as package, and the +-syntax option must specify which syntax is selected (either +camlp4o or camlp4r). + + + If you want to pass additional options to the preprocessor, +you can use the -ppopt option: + + +ocamlfind ocamlc -syntax camlp4r -package camlp4 -ppopt pa_ifdef.cmo -c file.ml + + + + +From the toploop, the following commands work: + + +$ ocaml + Objective Caml version 3.07+2 + +# #use "./topfind";; +- : unit = () +Findlib has been successfully loaded. Additional directives: + #require "package";; to load a package + #list;; to list the available packages + #camlp4o;; to load camlp4 (standard syntax) + #camlp4r;; to load camlp4 (revised syntax) + #predicates "p,q,...";; to set these predicates + Topfind.reset();; to force that packages will be reloaded + #thread;; to enable threads + +- : unit = () +# #camlp4o;; (* or camlp4r *) +/opt/godi/lib/ocaml/std-lib/camlp4: added to search path +/opt/godi/lib/ocaml/std-lib/camlp4/camlp4o.cma: loaded + Camlp4 Parsing version 3.07+2 + +# _ + + + +The concept + +If you have a -syntax option on the command line, +ocamlfind will generate a -pp parameter and pass it to the +invoked compiler. This is performed as follows: The specified packages are +inspected under a certain set of predicates, the syntax +predicates. The syntax predicates are syntax, +preprocessor, and the predicates following +-syntax. The predicate syntax simply +means that the -syntax option has been specified. +The predicate preprocessor means that the preprocessor +command is being constructed. The predicates added by +-syntax may be used to distinguish between syntax variants +(currently camlp4o and camlp4r). + + +The packages are searched for a variable preprocessor; +normally the camlp4 package defines it as (see its META +file): + + +preprocessor = "camlp4 -nolib" + + +Now that the name of the preprocessor command is known, the arguments of the +command are looked up. The META files are evaluated under the syntax +predicates, and all archive variables are collected and +passed as arguments to the preprocessor. For example, the camlp4 package +defines: + + +archive(syntax,preprocessor,camlp4o) = "pa_o.cmo pa_op.cmo pr_dump.cmo" +archive(syntax,preprocessor,camlp4r) = "pa_r.cmo pa_rp.cmo pr_dump.cmo" + + +Note that the predicate preprocessor prevents ocamlfind from +including these archives into the regular list of archives to link. + + + +How to write a META file for your own syntax extension + +Suppose you have two archives: pa_myext.cma contains the +extension code of camlp4, and run_myext.cma contains runtime +material that must be present in programs compiled with your extensions. Your +META file should look as follows: + + +requires = "camlp4" +archive(syntax,toploop) = "pa_myext.cma run_myext.cma" +archive(syntax,preprocessor) = "pa_myext.cma" +archive(syntax,byte) = "run_myext.cma" +archive(syntax,native) = "run_myext.cmxa" + + +You may add dependencies on camlp4o or +camlp4r if you have archives only working for one of the two +syntax variants. + + +To compile a program using your syntax extension package, one should use: + + +ocamlfind ocamlc -package yourname -syntax variant ... + + + + + + Example + +The package xstrp4 defines a syntax extension allowing +$-substitutions in OCaml strings. Version 1.0 of this package takes advantage +from the new camlp4 support of findlib; you may have a look at it for an +example. + +You can find xstrp4 +here. + + + + + + + Does Findlib support ppx-style preprocessors? + + + + Short answer: Yes, but there is only little + documentation. + + Since findlib-1.5, ppx-style preprocessors are supported +to some extent. A package can now define a "ppx" property which is simply +a command to run as preprocessor (the command gets the marshalled AST +as input, and must generate the transformed AST in its output; see the +-ppx option of ocamlc/ocamlopt). A META file can simply look like: + + +ppx = "./command" + + +when "command" is installed in the package directory (but you can also +omit "./" to search it, and you can prefix it with "@name/" if the command +is taken from another package "name"). + + + For more complex scenarios, additional options or +arguments for the ppx preprocessor can be specified in descendant +packages with the "ppxopt" property. Package "A" might provide a +generic ppx preprocessor with a META file containing + + +ppx = "./generic_ppx" + + +Package B might instantiate that preprocessor with + + +requires = "A" +ppxopt = "A,ppx_b.cmo" + + +In this case "ocamlfind ocamlc -package B" would +add -ppx "path_to_A/genric_ppx ppx_b.cmo" to +the ocamlc invocation. The format of the "ppxopt" property is +specified in the findlib reference manual. + + + + This feature is still a bit experimental. + + + + + + Why do some people install the .cmx files? + + In principle, it is not necessary to install the .cmx +files created by the ocamlopt compiler, as the .a and .cmxa files +already contain the assembly code and all needed auxiliary information. +However, it may be sensible to install the .cmx files, too. They +contain the intermediate code of small functions that are candidates +for inlining, and installing them allows the compiler to do inlining +even across library boundaries. Note that only very small functions +can be inlined at all, and that there are language elements that +prevent inlining (e.g. raising an exception with an argument), so +it makes only sense when the library actually has such functions +and really profits from inlining. + + Inlining has also disadvantages: The library can no +longer be replaced by a different version even if the interface +remains exactly the same, because code using the library may have +inlined code of the old version. + + + + + How do I express conflicts? + + A conflict means that a certain combination of packages +and package features will not work. A number of conflict conditions +can be expressed: + + + + To state that a package will not work if a certain +predicate is set, use the error variable. For example, +when package p does not work for multi-threaded programs: + + +error(mt) = "Package p is incompatible with multi-threaded programs" + + +This works for other standard predicates, too. + + + + To state that a package will not work together with +another package, it is possible to make error dependent +on package predicates. For example, when package p does not work +together with q: + + +error(pkg_q) = "Package p is incompatible with package q" + + +This also works with subpackages (e.g. pkg_q.q_sub). + + + + + If an error is too much, it might be a good idea to + just inform the user about possible problems. In this case + you can emit a warning instead: + + + +warning(pkg_q) = "Using package p and q together is a really bad idea" + + + + +Note that such error conditions should only be added if there is +absolutely no chance to get the combination of packages and features running. +For example, in the case of multi-threaded programs it is often possible +to add wrappers around unsafe libraries to fix the incompatibility. + + +It is not possible to express incompatibilities between package +versions. Such incompatibilities should be detected when software is +installed, not when it is used. + + + +
diff --git a/local-packages/ocamlfind/doc/src/findlib_conf.mod b/local-packages/ocamlfind/doc/src/findlib_conf.mod new file mode 100644 index 0000000..3960f1e --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_conf.mod @@ -0,0 +1,427 @@ + + + + findlib.conf + 5 + The findlib package manager for OCaml + + + + findlib.conf + [Configuration of findlib/ocamlfind] + + + + +GENERAL + + +There are three possibilities to configure the findlib library: + + + + Build time: + + Before findlib is compiled, a "configure" script is invoked to figure + out the settings that are most likely to work on the system. Most + settings are simply entered into text files and can easily be changed + after installation. The following properties cannot be changed later + because they are compiled into the resulting binaries: + + + + + The default location of the configuration file findlib.conf. However, + you can set a different location by the environment variable + OCAMLFIND_CONF. + + + + + + Whether the installed OCaml version supports autolinking or not. + + + + + + + + + + Configuration file findlib.conf: + + An initial version of this file is generated by the configure script, + but you are free to modify it later. Most important, this file + contains the system-wide search path used to look up packages, and the + default location where to install new packages. + + + All files with the suffix ".conf" found in the directory + findlib.conf.d are also scanned for parameters. + + + + + + Environment variables: + + The settings of findlib.conf can be overridden by environment variables. + + + + + +Last but not least, several settings can also be passed as +command-line options, or by invoking the function +Findlib.init. + + + + + + + + +findlib.conf + + +The directory containing findlib.conf is determined at build time (by +running the configure script), the fallback default is +/usr/local/etc. You can set a different location by +changing the environment variable OCAMLFIND_CONF +which must contain the absolute path of findlib.conf. + + + +The file has the same syntax as META, i.e. it consists of a +number of lines with the format + + +variable = "value" + + + +Here is the list of allowed variables: + + + + path + + The search path for META files/package directories. The variable + enumerates directories which are separated by colons (Windows: + semicolons), and these directories are tried in turn to find a certain + package. More exactly, if d is such a directory and p the searched + package, the search algorithm will first check whether d/p/META + exists. In this case, this META file is taken, and d/p is the package + directory. Second, the algorithm tries d/META.p, but the package + directory must be specified in this META.p file by a + directory directive. + + + + Note that the first found META file is taken, so the order of the + directories in the search path counts. + + + + This variable is required. + + + + Example: + + +path = "/usr/local/lib/ocaml/site-lib:/usr/lib/ocaml/site-lib" + + + + + + + + + + destdir + + This variable determines the location where ocamlfind + install puts the packages by default: If d is this + directory, and p the package to install, a new subdirectory d/p will + be created containing all the files of the package. + + + Example: + +destdir = "/usr/local/lib/ocaml/site-lib" + + + + + This variable is required. + + + + + + + + + metadir + + If set, the command ocamlfind install will put the + META files of packages into this directory (files are named META.p + where p=package name); otherwise the META files are put into the + package directories like any other file. + + + Example: + +metadir = "/var/lib/findlib/metaregistry" + + + + + This variable is optional. It is not used by default. + + + + + + + + + ocamlc, + ocamlopt, + ocamlcp, + ocamlmktop, + ocamldoc, + ocamldep, + ocamlbrowser + + + If you want to call other executables than "ocamlc", "ocamlopt", + "ocamlcp", "ocamlmktop", "ocamldoc", "ocamldep", and + "ocamlbrowser", you can + set the names of + the executables here. The command ocamlfind looks + into these four variables to determine the names of the compilers to + call. + + + Example: + +ocamlc = "ocamlc.opt" +ocamlopt = "ocamlopt.opt" +ocamlcp = "ocamlcp.opt" +ocamlmktop = "ocamlmktop.opt" + + + + + This variable is optional. It is not used by default. + + + + + + + + stdlib + + This variable determines the location of the standard library. This must + be the same directory for which the OCaml compilers are configured. + + + + This variable is optional. It is not recommend to set this variable + unless you know what you are doing! + + + + + + + + ldconf + + This variable determines the location of the ld.conf file. This must + be the same file the OCaml compilers read in; it is updated by + ocamlfind when installing and removing packages. You can set this + variable to the special value "ignore" to disable + the automatic modification of the ld.conf file. + + + + If not set, the ld.conf file is assumed to reside in the OCaml + standard library directory. + + + + This variable is optional. It is not recommended to set this variable + unless you know what you are doing! + + + + + + + +Toolchains: It is possible to have variants of the original configuration. +These variants are called "toolchains" because they are intended to +select different compilers, e.g. patched compilers. In order to +set a variable for a certain toolchain, use the syntax + + +variable(toolchain) = "value" + + +For example: + + +ocamlc(mypatch) = "ocamlc-mypatch" + + +When the toolchain "mypatch" is selected, this compiler will be used instead +of the standard one. + +In order to switch to a certain toolchain, use the -toolchain +option of ocamlfind. + + + + + + + + + +Environment + + +A number of environment variables modifies the behaviour of +findlib/ocamlfind: + + + + OCAMLFIND_CONF + + This variable overrides the location of the configuration file + findlib.conf. It must contain the absolute path name of this file. + + + + + + + + OCAMLFIND_TOOLCHAIN + + This variable sets the currently selected toolchain when + a -toolchain option is not passed + on the command line. + + + + + + + + OCAMLPATH + + This variable may contain an additional search path for package + directories. It is treated as if the directories were prepended to + the configuration variable path. + + + + + + + + OCAMLFIND_DESTDIR + + This variable overrides the configuration variable + destdir. + + + + + + + + OCAMLFIND_METADIR + + This variable overrides the configuration variable + metadir. + + + + + + + + OCAMLFIND_COMMANDS + This variable overrides the configuration variables + ocamlc, ocamlopt, + ocamlcp, ocamlmktop, + ocamldoc, ocamldep, and/or + ocamlbrowser. + Its value must conform to the syntax + + +ocamlc=name ocamlopt=name ocamlcp=name ocamlmktop=name ocamldoc=name ocamldep=name ocamlbrowser=name + + + + Example: + +ocamlc=ocamlc-3.00 ocamlopt=ocamlopt-3.00 ocamlcp=ocamlcp-3.00 ocamlmktop=ocamlmktop-3.00 + + + + + + + + + + CAMLLIB or OCAMLLIB + + This variable overrides the configuration variable + stdlib. + + + + + + + + OCAMLFIND_LDCONF + + This variable overrides the configuration variable + ldconf. + + + + + + + + OCAMLFIND_IGNORE_DUPS_IN + + This variable instructs findlib not to emit warnings that packages + or module occur several times. The variable must be set to the + directory where the packages reside that are to be ignored for this + warning. + + + + + + + + + + + diff --git a/local-packages/ocamlfind/doc/src/findlib_meta.mod b/local-packages/ocamlfind/doc/src/findlib_meta.mod new file mode 100644 index 0000000..8924f1c --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_meta.mod @@ -0,0 +1,420 @@ + + + + META + 5 + The findlib package manager for OCaml + + + + META + [File that specifies metainformation of OCaml packages] + + + + +GRAMMAR + + metafile ::= entry* + entry ::= assignment | addition | subpackage + subpackage ::= "package" pkgname '(' metafile ')' + assignment ::= variable_name [ formal_predicates ] '=' value + addition ::= variable_name [ formal_predicates ] '+=' value +formal_predicates ::= '(' formal_predicate { ',' formal_predicate } ')' + variable_name ::= name + formal_predicate ::= name | '-' name + name ::= [ 'A'-'Z' 'a'-'z' '0'-'9' '_' '.' ]+ + pkgname ::= '"' (character but not '.')* '"' + value ::= '"' character* '"' + + + + +DESCRIPTION + +If a package directory contains a file with the fixed name "META" it +is interpreted as described here. The file is a sequence of entries +following the given grammar; every entry defines a variable under a +certain condition given by the list of formal predicates, or it +introduces a subpackage. + + + +There is a list of predefined variables and a list of standard +predicates. These variables define: required packages, description, version +information, directories, archive files, and linker options. The +predicates denote circumstances of the application of the variables: +whether the bytecode or the native compiler is used, if there is a +toploop compiled in, details of multi-threading execution, details of +profiling. + + + + +DETAILS OF THE FILE FORMAT + +The file consists of a sequence of entries which must be formed as the +grammar prescribes. The lexical tokens are names, values, and +interpunctuation like '(', ',' and so on. Note that linefeeds do not +play a special role, i.e. an entry definition may be given in more than +one line, or several definitions may occur on a single line. There may +be comments which begin with '#' and run until the end of the line. + + + +Names are sequences of the characters A-Z, a-z, 0-9, or _. Names +containing capital letters and names beginning with digits are +allowed but not recommended. + + + +Values are enclosed between double quotes. Values may contain any +character. The characters " and \ must be preceded by backslashes. + + + +Package names must not contain the '.' character because it is used +as delimiter of compound names. + + + + + +MAIN PACKAGES AND SUBPACKAGES + +The outermost variable assignments and additions belong to the main +package. The name of the main package is not defined within META; +it is either the name of the directory containing META or the suffix +of the META file (if the name of the META file is formed like +META.name). + +The keyword package starts the definition +of a subpackage. There must not be two such definitions with the +same name. Within the parantheses, the variable assignments and +additions refer to the subpackage. It is allowed that a subpackage +contains further subpackages. + +The package name following package +is the local name relative to the main package, i.e. the +name of the main package is not mentioned. At all other places, +however, the subpackage must be prefixed by the name of the +containing package, separated by a '.'. + +Subpackages are independent of the containing package, except +that the subpackage points to the same installation directory as +the containing package (i.e. the location of the installation directory +is inherited from the containing package). + + + + +SEMANTICS OF VARIABLE DEFINITIONS + + +In order to determine the value of a variable, first all assignments +are inspected, and the most specific assignment is taken (if there is +none, the empty string will be taken as value). In a second step, +all additions are gone through one after the other in the order +they occur in the file, and the values of all matching additions are +appended to the current value. In the following, it is further +clarified which assignment is the most specific, which additions +actually match, and how the details of the value addition look like. + + The most specific assignment is selected upon a set of actual +predicates, i.e. the set of predicates that are assumed to be true. +The predicates occuring in the definitions of assignments and +additions are called formal predicates. They may be positive or +negative; the latter are prepended by a '-' sign. In order to +determine the value after the evaluation of the assignments, the +following rules apply: + + + + An assignment can only be used if all positive formal +predicates are included in the set of actual predicates, and if all +negative formal predicates are not included in the set of actual +predicates. Such an assignment is called +applicable. If there is no such assignment, the +variable will have no value. + + + + + +If there is more than one applicable assignment, the definition with +the biggest number of formal predicates is selected. + + + + + +If there is still more than one applicable assignment, both applicable +and with a maximum number of formal predicates, the definition that is defined +first is selected. + + + + +An addition is matching when all positive formal predicates are +included in the set of actual predicates, and all negative formal +predicates are not included. + +The value of an addition is appended to the current value with +implicit white space as separator. + + + + +VARIABLES + + +There is a set of variables with predefined meaning: + + + The +variable "directory" redefines the location of the package +directory. Normally, the META file is the first file read in the +package directory, and before any other file is read, the "directory" +variable is evaluated in order to see if the package directory must be +changed. The value of the "directory" variable is determined with an +empty set of actual predicates. The value must be either: an absolute +path name of the alternate directory, or a path name relative to the +stdlib directory of OCaml (written "+path"), or a normal relative path +name (without special syntax). In the latter case, the interpretation +depends on whether it is contained in a main or sub package, and +whether the standard repository layout or the alternate layout is in +effect (see site-lib for these terms). +For a main package in standard layout the base directory is the +directory physically containing the META file, and the relative path +is interpreted for this base directory. For a main package in +alternate layout the base directory is the directory physically +containing the META.pkg files. The base directory for subpackages is +the package directory of the containing package. (In the case +that a subpackage definition does not have a "directory" setting, +the subpackage simply inherits the package directory of the containing +package. By writing a "directory" directive one can change this +location again.) + + + + +The variable "requires" specifies the list of required packages. The +names of the packages must be separated by white space and/or commas. +The names must be fully qualified (i.e. when they refer to a subpackage, +the names of all containing packages must be prepended, separated by +'.'). + + + + + +The variable "description" may include a short description of the +package (displayed by ocamlfind list). + + + + + +The variable "version" specifies the version string. + + + + + +The variable "archive" specifies the list of archive files. These +files should be given either as (1) plain names without any directory +information; they are only searched in the package directory. +(2) Or they have the form "+path" in which case the files are looked up +relative to the standard library. (3) Or they have the form "@name/file" +in which case the files are looked up in the package directory +of another package. (4) Or they are given as absolute paths. + + +The +names of the files must be separated by white space and/or commas. +In the preprocessor stage, the archive files are passed as extensions +to the preprocessor (camlp4) call. In the linker stage (-linkpkg), the archive +files are linked. In the compiler stage, the archive files are ignored. + + + +Note that "archive" should only be used for archive files that are +intended to be included in executables or loaded into toploops. For +modules loaded at runtime there is the separate variable "plugin". + + + + +The variable "plugin" specifies the plugin archives of the package. +These can be dynamically loaded with the Fl_dynload +module. The plugin archives can have ".cmo", ".cma", or ".cmxs" suffix. + + + + + +The variable "linkopts" specifies additional linker options. + + + + + +The variable "error" can be used to signal error conditions. When +this variable is applicable, the ocaml compilers are stopped, and +an error message is printed. The message is the value of the variable. + + + + + +The variable "warning" can be used to signal warnings. When +this variable is applicable, the warning is printed, but the +compilation continues. The message is the value of the variable. + + + + + +The variable "exists_if" can be used to disable subpackages. The +value of "exists_if" is a file; the subpackage is hidden if this +file does not exist. You can also enumerate several files, and the +subpackage is hidden if none of the files exist. + + + + + +The variable "ppx" is a command that is added to the compiler invocation +via the -ppx option (available since OCaml-4.01). If the command is +relative to the current directory (e.g. ./cmd), the command is expected +in the package directory. The special forms as defined for "archive" +are also available (e.g. @otherpkg/cmd). Additional arguments can be +specified on the ocamlfind command line with the -ppxopt option +or the "ppxopt" variable. + + + + + +The variable "ppxopt" is a set of options that are added to the ppx +rewriter invocation. The contents of the variable consists of one or +several whitespace-separated parts. Every part consists of several +comma-separated subparts; the first subpart indicates the package +that contains the ppx rewriter invocation, the rest contain the options +to be appended. If the option is a path relative to the current directory +(e.g. ./foo.cma), the path is expanded relative to the package directory. +The special forms as defined for "archive" are also available +(e.g. @otherpkg/foo.cma). + + + + + + +It is possible to define additional variables but there is currently +no software interpreting them. + + + + + +PREDICATES + + +There is a list of standard predicates: + + + + + +The "byte" predicate means that the bytecode compiler is used. + + + + + +The "native" predicate means that the native compiler is used. + + + + + +The "toploop" predicate means that the toploop is available in the +linked program. It is only set when the toploop is running, not when +the toploop is generated. + + + + + +The "create_toploop" predicate means that a toploop is created (using +ocamlmktop). + + + + + +The "mt" predicate means that the program is multi-threaded. + + + + + +The "mt_posix" predicate means that in the case "mt" is set, too, the +POSIX libraries are used to implement threads. + + + + + +The "mt_vm" predicate means that in the case "mt" is set, too, the +VM-based libraries are used to implement threads. + + + + + +The "gprof" predicate means that in the case "native" is set, too, the +program is compiled for profiling + + + + + +The "autolink" predicate means that ocamlc can/will perform automatic linking. + + + + + +The "preprocessor" predicate means that the META variables are scanned for +preprocessor options. + + + + +The "syntax" predicate means that the -syntax option is present on the +command line. + + + + +Legacy: The "plugin" predicate could be used in some versions of findlib +to select cmxs archives instead of cmxa archives. This use is still possible +but discouraged. + + + + + +In addition to these predicates, there are package predicates +for every package that is finally selected. Of course, this kind of +predicate must not be used to select "directory" and "requires" +variables, but for the other variables they are perfectly valid. +The package predicates have the form "pkg_" plus the name of the +package (fully qualified). + + + + + diff --git a/local-packages/ocamlfind/doc/src/findlib_mli.mod b/local-packages/ocamlfind/doc/src/findlib_mli.mod new file mode 100644 index 0000000..12fd0d4 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_mli.mod @@ -0,0 +1,181 @@ + + + + Findlib + 3 + The findlib package manager for OCaml + + + + Findlib + [Module for package management] + + + + +SIGNATURE + +module Findlib : + sig + + + + + + + (* Note: This signature is incomplete. See findlib.mli for the + * full signature. + *) + + end + + + + + +PACKAGING + + +The Findlib module is part of the "findlib" package. In order to link +it in, it is sufficient to link "findlib" in, e.g. + + + +ocamlfind ocamlc options -package findlib -linkpkg options + + + +There are archives for the bytecode compiler and for the native +compiler; for single-threaded and for multi-threaded applications, and +there is a special addition for toploops. + + + + + +DESCRIPTION + + +The Findlib module is the primary interface of the findlib library. It +contains functions to lookup packages, to interpret files, and to determine the ancestors of +packages. + + + + +<anchor id="Findlib.package-directory"> +Findlib.package_directory <replaceable>pkg</replaceable> + +val package_directory : string -> string + + +Gets the absolute path of the directory where the package +pkg is stored. The exception Not_found is +raised if the package could not be found. +Other exceptions may occur as file I/O is done. + + + + + + +<anchor id="Findlib.package-property"> +Findlib.package_property <replaceable>predicates</replaceable> +<replaceable>pkg</replaceable> <replaceable>variable</replaceable> + + +val package_property : string list -> string -> string -> string + + +Determines the value of the variable +defined in the file of package +pkg with the given set of +predicates. The exception Not_found is +raised if the package or the variable could not be found. Other +exceptions may occur as file I/O is done. + + +Examples + +Get the value of the "requires" variable of package "p" with an empty +set of predicates: + + +Findlib.package_property [] "p" "requires" + + +Get the value of the "archive" variable of package "p" for +multi-threaded bytecode applications: + + +Findlib.package_property [ "mt"; "byte" ] "p" "archive" + + + + + + + +<anchor id="Findlib.package-ancestors"> +Findlib.package_ancestors <replaceable>predicates</replaceable> + <replaceable>pkg</replaceable> + + +val package_ancestors : string list -> string -> string list + + +Determines the direct ancestors of package +pkg for the set of +predicates. The returned list has no +specific order. The exception Not_found is raised if the package could +not be found. The exception Failure is raised if one of the ancestors +could not be found, or if a circular dependency has been +detected. Other exceptions may occur as file I/O is done. + + + + + + +<anchor id="Findlib.package-deep-ancestors"> +Findlib.package_deep_ancestors <replaceable>predicates</replaceable> + <replaceable>pkglist</replaceable> + + +val package_deep_ancestors : string list -> string list -> string list + + +Determines the list of direct or indirect ancestors of the packages in +pkglist for the set of +predicates. The returned list is +topologically sorted. +The exception Not_found is raised if the package could +not be found. The exception Failure is raised if one of the ancestors +could not be found, or if a circular dependency has been +detected. Other exceptions may occur as file I/O is done. + + + + + + +<anchor id="Findlib.default-location"> +Findlib.default_location () + +val default_location : unit -> string + + +Gets the default location where new packages will be installed. + + + + + + + diff --git a/local-packages/ocamlfind/doc/src/findlib_ocamlfind.mod b/local-packages/ocamlfind/doc/src/findlib_ocamlfind.mod new file mode 100644 index 0000000..2e03a05 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_ocamlfind.mod @@ -0,0 +1,1436 @@ + + + + ocamlfind + 1 + The findlib package manager for OCaml + + + + ocamlfind + [Command-line interface of the Package manager] + + + + +SYNOPSIS + + ocamlfind query [-help | other options] package_name ... + or: ocamlfind ocamlc [-help | other options] file ... + or: ocamlfind ocamlcp [-help | other options] file ... + or: ocamlfind ocamlmktop [-help | other options] file ... + or: ocamlfind ocamlopt [-help | other options] file ... + or: ocamlfind ocamldoc [-help | other options] file ... + or: ocamlfind ocamldep [-help | other options] file ... + or: ocamlfind ocamlmklib [-help | other options] file ... + or: ocamlfind ocamlbrowser [-help | other options] + or: ocamlfind install [-help | other options] package_name file ... + or: ocamlfind remove [-help | other options] package_name + or: ocamlfind lint META + or: ocamlfind list [-describe] + or: ocamlfind printppx [-help | other options] package_name ... + or: ocamlfind printconf [ variable ] + or: ocamlfind package/command arg ... + +Optional toolchain selection by: + ocamlfind -toolchain name ... + + + + + + + +<anchor id="ocamlfind.query"> + THE "query" SUBCOMMAND + + + +Synopsis + +ocamlfind query [ -predicates p | + -format f | + -long-format | -l | + -i-format | + -l-format | + -a-format | + -o-format | + -p-format | + -prefix p | + -separator s | + -suffix s | + -pp | + -descendants | -d | + -recursive | -r + -qe | -qo] package ... + + + + Description + + This command looks packages up, sorts them optionally, and +prints attributes of them. If the option -recursive (short: -r) is not +specified, exactly the packages given on the command line are looked +up; if -recursive is present, the packages and all their ancestors, or +if -descendants (short: -d) is present, too, all their descendants are printed. + + + +Package lookup and the selection of the attributes of the packages can +be modified by specifying predicates; without a -predicates option the +empty set of predicates is used. Note that even the lookup is +influenced by the set of actual predicates as the "requires" variables +may be conditional. + + + +What is printed about a package depends on the specified format; there +are a number of options that modify the format. Some formats denote +sets of values (such as -format %a), in which case multiple output +records are printed for every package. (It is even possible to specify +formats denoting the Cartesian product of sets, such as -format %a%o, +but this does not make sense.) Before the first output record the +prefix is printed, and the suffix after the last record. Between two +records the separator is printed. + + + + +Options + + + +-predicates p +Sets the set of actual predicates. The argument + p is a list of predicate names separated + by commas and/or whitespace. If multiple -predicates options are + given, the union of all specified sets is effectively used. + + + +-format f +Sets the format to the string + f. Characters preceded by a percent sign + are interpreted as placeholders; all other characters mean + themselves. The defined placeholders are listed below. + The default format is "%d". + + + +-long-format or -l +Sets the format such that all relevant variables are printed. + + + +-i-format +Same as -format "-I %d", i.e. directory options for ocamlc are printed. + + + +-l-format +Same as -format "-ccopt -L%d", i.e. directory options for the +linker backend are printed. + + + +-a-format +Same as -format "%+a", i.e. archive file names are printed. + + + +-o-format +Same as -format "%o", i.e. linker options are printed. + + + +-p-format +Same as -format "%p", i.e. package names are printed. + + + +-prefix p +Sets the prefix that is printed before the first output record + to the given string. The default prefix is the empty string. + + + +-suffix s +Sets the suffix that is printed after the last output record + to the given string. The default suffix is the empty string. + + + +-separator s +Sets the separator that is printed between output records to + the given string. The default separator is a linefeed character. + + + +-recursive or -r +Not only the packages given on the command line are queried + but also all ancestors or descendants. If the option -descendants is + specified, too, the descendants are printed, otherwise the + ancestors. The packages are topologically sorted. + + + +-descendants -d +Instead of the ancestors the descendants of the + given packages are queried. This option implies -recursive. + + + +-pp +Query preprocessor packages (camlp4 syntax extensions). Normally +it is not needed to set -predicates, except you need the archives (then add +-predicates byte). This option implies -recursive. + + + +-qe +Do not print most errors to stderr, just set the exit code + + + +-qo +Do not print the regular output. + + + + + + + +Placeholders meaningful in the -format option + + + +%% + Replaced by a single percent sign + + +%p + Replaced by the package name + + +%d + Replaced by the package directory + + +%m + Replaced by the path to the META file (new since findlib-1.6) + + + +%D + Replaced by the package description + + +%v + Replaced by the version string + + +%a + Replaced by the archive filename. If there is more + than one archive, a separate output record is printed for every archive. + + + +%+a + Like %a, but the filenames are converted to absolute + paths ("+" and "@" notations are resolved) + + + +%A + Replaced by the list of archive filenames. + + +%+A + Like %A, but the filenames are converted to absolute + paths ("+" and "@" notations are resolved) + + +%o + Replaced by one linker option. If there is more than + one option, a separate output record is printed for every option. + + + +%O + Replaced by the list of linker options. + + +%(property) + Replaced by the value of the property named in parentheses, +or the empty string if not defined. + + + + + + + + + + +<anchor id="ocamlfind.ocamlc"> + <anchor id="ocamlfind.ocamlcp"> + <anchor id="ocamlfind.ocamlopt"> + <anchor id="ocamlfind.ocamlmktop"> + THE SUBCOMMANDS "ocamlc", "ocamlcp", "ocamlopt", and "ocamlmktop" + + + +Synopsis + +ocamlfind ( ocamlc | ocamlcp | ocamlopt | ocamlmktop ) + [ -package package-name-list | + -linkpkg | + -predicates pred-name-list | + -dontlink package-name-list | + -syntax pred-name-list | + -ppopt camlp4-arg | + -ppxopt package,arg | + -dllpath-pkg package-name-list | + -dllpath-all | + -passopt arg | + -passrest arg... | + -only-show | + standard-option ] + file ... + + + + +Description + + +These subcommands are drivers for the compilers with the same names, +i.e. "ocamlfind ocamlc" is a driver for "ocamlc", and so on. The +subcommands understand all documented options of the compilers (here +called standard-options), but also a few +more options. If these subcommands are invoked only with standard +options, they behave as if the underlying compiler had been called +directly. The extra options modify this. + + + +Internally, these subcommands transform the given list of options and +file arguments into an invocation of the driven compiler. This +transformation only adds options and files, and the relative order of +the options and files passed directly is unchanged. + + + +If there are -package options, additional directory search specifiers +will be included ("-I", and "-ccopt -I"), such that files of all named +packages and all ancestors can be found. + + + +The -linkpkg option causes that the packages listed in the -package +options and all necessary ancestors are linked in. This means that the +archive files implementing the packages are inserted into the list of +file arguments. + + + +As the package database is queried a set of predicates is needed. Most +predicates are set automatically, see below, but additional predicates +can be given by a -predicates option. + + + +If there is a -syntax option, the drivers assume that +a preprocessor is to be used. In this case, the preprocessor command +is built first in a preprocessor stage, and this command is passed to the +compiler using the -pp option. The set of predicates +in the preprocessor stage is different from the set in the compiler/linker +stage. + + + + +Options for compiling and linking + + +Here, only the additional options not interpreted by the compiler but +by the driver itself, and options with additional effects are explained. +Some options are only meaningful for the preprocessor call, and are +explained below. + + + + +-package package-name-list + Adds the listed package names to the set of included + packages. The package names may be separated by commas and/or + whitespace. In the transformed command, for every package of the set + of included packages and for any ancestor a directory search option + is inserted after the already given options. This means that + "-I" and "-ccopt -I" options are added for every package directory. + + + +-linkpkg + Causes that in the transformed command all archives + of the packages specified by -packages and all their ancestors are + added to the file arguments. More precisely, these archives are + inserted before the first given file argument. Furthermore, "-ccopt + -L" options for all package directories, and the linker options of + the selected packages are added, too. Note that the archives are + inserted in topological order while the linker options are added in + reverse toplogical order. + + + +-predicates pred-name-list + Adds the given predicates to the set of actual + predicates. The predicates must be separated by commas and/or + whitespace. + + + +-dontlink package-name-list + This option modifies the behaviour of + -linkpkg. Packages specified here and all ancestors are not linked + in. Again the packages are separated by commas and/or whitespace. + + + +-dllpath-pkg package-name-list + For these packages -dllpath options + are added to the compiler command. This may be useful when the ld.conf + file is not properly configured. + + +-dllpath-all + For all linked packages -dllpath options + are added to the compiler command. This may be useful when the ld.conf + file is not properly configured. + + +-passopt arg + The argument arg is + passed directly to the underlying compiler. This is needed to + specify undocumented compiler options. + + + +-passrest arg... + All following arguments arg... are + passed directly to the underlying compiler. This is needed to + specify undocumented compiler options. + + +-only-show + Only prints the constructed command (ocamlc/ocamlopt) to + stdout, but does not execute the command. (This is for the unlikely event + that you need a wrapper around ocamlfind.) + + + + +-verbose + This standard option is interpreted by the driver, too. + + + +-thread + This standard option causes that the predicate "mt" + is added to the set of actual predicates. If POSIX threads are available, + the predicate "mt_posix" is selected, too. If only VM threads are + available, the predicate "mt_vm" is included into the set, and the + compiler switch is changed into -vmthread. + + Note that the presence of the "mt" predicate triggers special +fixup of the dependency graph (see below). + + + +-vmthread + This standard option causes that the predicates "mt" + and "mt_vm" are added to the set of actual predicates. + + Note that the presence of the "mt" predicate triggers special +fixup of the dependency graph (see below). + + + +-p + This standard option of "ocamlopt" causes that the + predicate "gprof" is added to the set of actual predicates. + + + + + + + + +Options for preprocessing + + +The options relevant for the preprocessor are the following: + + + + +-package package-name-list + These packages are considered while looking up the + preprocessor arguments. (It does not cause problems that the same + -package option is used for this purpose, because the set of predicates + is different.) It is recommended to mention at least camlp4 + here if the preprocessor is going to be used. + + + +-syntax pred-name-list + These predicates are assumed to be true in addition + to the standard preprocessor predicates. See below for a list. + + + + -ppopt camlp4-arg + This argument is passed to the camlp4 call. + + + + -ppxopt package,arg + Add arg to the ppx + preprocessor invocation specified via the "ppx" property in + the META file of package. + + + + + + +Predicates for compiling and linking + + + +byte + + +The "byte" predicate means that one of the bytecode compilers is +used. It is automatically included into the predicate set if the +"ocamlc", "ocamlcp", or "ocamlmktop" compiler is used. + + + + + +native + + +The "native" predicate means that the native compiler is used. It is +automatically included into the predicate set if the "ocamlopt" +compiler is used. + + + + + +toploop + + +The "toploop" predicate means that the toploop is available in the +linked program. This predicate is only set when the toploop is actually +being executed, not when the toploop is created (this changed in version +1.0.4 of findlib). + + + + + +create_toploop + + +This predicate means that a toploop is being created (using +ocamlmktop). + + + + + +mt + + +The "mt" predicate means that the program is multi-threaded. It is +automatically included into the predicate set if the -thread option is +given. + + + + + +mt_posix + + +The "mt_posix" predicate means that in the case "mt" is set, too, the +POSIX libraries are used to implement threads. "mt_posix" is automatically +included into the predicate set if the variable "type_of_threads" in the +META description of the "threads" package has the value "posix". This +is normally the case if "findlib" is configured for POSIX threads. + + + + + +mt_vm + + +The "mt_vm" predicate means that in the case "mt" is set, too, the +VM thread emulation is used to implement multi-threading. + + + + + +gprof + + +The "gprof" predicate means that in the case "native" is set, too, the +program is compiled for profiling. It is automatically included into +the predicate set if "ocamlopt" is used and the -p option is in +effect. + + + + + +autolink + + +The "autolink" predicate means that ocamlc is able to perform automatic +linking. It is automatically included into the predicate set if ocamlc +knows automatic linking (from version 3.00), but it is not set if the +-noautolink option is set. + + + + + + syntax + This predicate is set if there is a -syntax + option. It is set both for the preprocessor and the compiler/linker stage, + and it can be used to find out whether the preprocessor is enabled or not. + + + + + + + + +Predicates for preprocessing + + + + preprocessor + This predicate is always set while looking up the + preprocessor arguments. It can be used to distinguish between the + preprocessor stage and the compiler/linker stage. + + + syntax + This predicate is set if there is a -syntax + option. It is set both for the preprocessor and the compiler/linker stage, + and it can be used to find out whether the preprocessor is enabled or not. + + + + camlp4o + This is the reserved predicate for the standard OCaml syntax. + It can be used in the -syntax predicate list. + + + + camlp4r + This is the reserved predicate for the revised OCaml syntax. + It can be used in the -syntax predicate list. + + + + + + + +Special behaviour of "ocamlmktop" + + As there is a special module Topfind that +supports loading of packages in scripts, the "ocamlmktop" subcommand +can add initialization code for this module. This extra code is +linked into the executable if "findlib" is in the set of effectively +linked packages. + + + + + + +Fixup of the dependency graph for multi-threading +For a number of reasons the presence of the "mt" predicate triggers +that (1) the package "threads" is added to the list of required packages +and (2) the package "threads" becomes prerequisite of all other packages +(except of itself and a few hardcoded exceptions). The effect is that +the options -thread and -vmthread automatically select the "threads" +package, and that "threads" is inserted at the right position in the +package list. + + + + +Extended file naming +At a number of places one can not only refer to files by absolute +or relative path names, but also by extended names. These have two +major forms: "+name" +refers to the subdirectory name of the +standard library directory, and "@name" +refers to the package directory of the package name. +Both forms can be continued by a path, e.g. "@netstring/netstring_top.cma". + + + +You can use extended names: (1) With -I options, +(2) as normal file arguments of the compiler, (3) in the +"archive" property of packages. + + + + + +How to set the names of the compiler executables + + Normally, the OCaml bytecode compiler can be called under the name +ocamlc. However, this is not always true; sometimes a +different name is chosen. + + You can instruct ocamlfind to call executables with other names than +ocamlc, ocamlopt, +ocamlmktop, and ocamlcp. If present, +the environment variable OCAMLFIND_COMMANDS is interpreted +as a mapping from the standard names to the actual names of the executables. It +must have the following format: + + +standardname1=actualname1 standardname2=actualname2 ... + + + +Example: You may set OCAMLFIND_COMMANDS as follows: + + +OCAMLFIND_COMMANDS='ocamlc=ocamlc-3.00 ocamlopt=ocamlopt-3.00' +export OCAMLFIND_COMMANDS + + + +Alternatively, you can change the configuration file +findlib.conf. + + + + + + + +<anchor id="ocamlfind.ocamlmklib"> + THE SUBCOMMAND "ocamlmklib" + + + +Synopsis + +ocamlfind ocamlmklib + [ -package package-name-list | + -predicates pred-name-list | + -dllpath-pkg package-name-list | + -dllpath-all | + -passopt arg | + -passrest arg... | + standard-option ] + file ... + + + + +Description + + +This is a wrapper around ocamlmklib, and creates library archives and +DLLs. In addition to the standard options, one can use -package to +add the search path of packages. Note that no predicates are set by default - +the wrapper does not know whether this is about byte or native code linking. + + + +This wrapper is mostly provided for completeness. + + + + + + + + + + +<anchor id="ocamlfind.ocamldep"> + THE "ocamldep" SUBCOMMAND + + + +Synopsis + +ocamlfind ocamldep [-package package-name-list | + -syntax pred-name-list | + -ppopt camlp4-arg | + -passopt arg | + -passrest arg... | + -verbose | + standard-option] file ... + + + +Description + +This command is a driver for the tool ocamldep of the +OCaml distribution. This driver is only useful in conjunction with +the preprocessor camlp4; otherwise it does not provide more functions +than ocamldep itself. + + + + +Options + + +Here, only the additional options not interpreted by ocamldep +but +by the driver itself, and options with additional effects are explained. + + + + + -package package-name-list + The packages named here are only used to look up the +preprocessor options. The package camlp4 should be +specified anyway, but further packages that add capabilities to the +preprocessor can also be passed. + + + + -syntax pred-name-list + The predicates that are in effect during the look-up +of the preprocessor options. At least, either camlp4o +(selecting the normal syntax), or camlp4r (selecting +the revised syntax) should be specified. + + + + -ppopt camlp4-arg + An option that is passed through to the camlp4 call. + + + + + -passopt arg + An option that is passed through to the ocamldep call. + + + + + -passrest arg... + All further arguments are passed down to ocamldep + unprocessed + + + + + -verbose + Displays the resulting ocamldep command (for debugging) + + + + + + + +Example + +A typical way of using this driver: + + +ocamlfind ocamldep -package camlp4,xstrp4 -syntax camlp4r file1.ml file2.ml + + +This command outputs the dependencies of file1.ml and +file2.ml, although these modules make use of the +syntax extensions provided by xstrp4 and are written +in revised syntax. + + + + + + + + + +<anchor id="ocamlfind.ocamlbrowser"> + THE "ocamlbrowser" SUBCOMMAND + + + +Synopsis + +ocamlfind ocamlbrowser [-package package-name-list | + -all | + -passopt arg + -passrest ] + + + +Description + +This driver calls the ocamlbrowser with package options. +With -package, the specified packages are included into +the search path of the browser, and the modules of these packages become +visible (in addition to the standard library). The option -all causes that all packages are selected that are managed by findlib. + + +As for other drivers, the options -passopt and +-passrest can be used +to pass arguments directly to the ocamlbrowser program. + + + + + + + +<anchor id="ocamlfind.ocamldoc"> + THE SUBCOMMAND "ocamldoc" + + + +Synopsis + +ocamlfind ocamldoc + [ -package package-name-list | + -predicates pred-name-list | + -syntax pred-name-list | + -ppopt camlp4-arg | + standard-option ] + file ... + + + + +Description + + +This subcommand is a driver for ocamldoc. It undestands all options +ocamldoc supports plus the mentioned findlib options. Basically, +the -package options are translated into -I options, and the selected +syntax options are translated into camlp4 options. + + + + +Options + + +Here, only the additional options not interpreted by ocamldep +but +by the driver itself, and options with additional effects are explained. + + + + +-package package-name-list + Adds the listed package names to the set of included + packages. The package names may be separated by commas and/or + whitespace. In the transformed command, for every package of the set + of included packages and for any ancestor a directory search option + is inserted after the already given options. This means that + "-I" options are added for every package directory. + + + + +-predicates pred-name-list + Adds the given predicates to the set of actual + predicates. The predicates must be separated by commas and/or + whitespace. + + + + + -syntax pred-name-list + The predicates that are in effect during the look-up +of the preprocessor options. At least, either camlp4o +(selecting the normal syntax), or camlp4r (selecting +the revised syntax) should be specified. + + + + -ppopt camlp4-arg + An option that is passed through to the camlp4 call. + + + + + + + + + + + + + + +<anchor id="ocamlfind.install"> + THE "install" SUBCOMMAND + + + +Synopsis + +ocamlfind install [ -destdir directory ] + [ -metadir directory ] + [ -ldconf path ] + [ -dont-add-directory-directive ] + [ -patch-version string ] + [ -patch-rmpkg name ] + [ -patch-archives ] + [ -dll ] [ -nodll ] [ -optional ] [ -add ] + package_name file ... + + + + +Description + +This subcommand installs a new package either at the default location +(see the variable destdir of +findlib.conf), or in the directory +specified by the -destdir option. This +means that a new package directory is created and that the files on +the command line are copied to this directory. It is required that a +META file is one of the files copied to the target +directory. + + + +Note that package directories should be flat (no +subdirectories). Existing packages are never overwritten. + + + +It is possible to have a separate directory for all the META files. If +you want that, you have either to set the variable +metadir of +findlib.conf, or to specify the +-metadir option. In this case, the file called META is copied to the +specified directory and renamed to META.p (where p is the package +name), while all the other files are copied to the package +directory as usual. Furthermore, the META file is modified such that the +directory variable contains the path of the package +directory. + + + +The option -dont-add-directory-directive prevents the installer from +adding a directory variable. + + + +If there are files ending in the suffixes .so or +.dll, the package directory will be added to the +DLL configuration file ld.conf, such that the dynamic +loader can find the DLL. The location of this file can be overriden by +the -ldconf option. To turn this feature off, use "-ldconf ignore"; +this causes that the ld.conf file is not modified. + + + +However, if there is a stublibs directory in site-lib, the DLLs are not +installed in the package directory, but in this directory that is +shared by all packages that are installed at the same location. +In this case, the configuration file ld.conf is +not modified, so you do not need to say "-ldconf ignore" if you +prefer this style of installation. + + + +The options -dll and -nodll can be used to control exactly which files +are considered as DLLs and which not. By default, the mentioned +suffix rule is in effect: files ending in ".so" (Unix) or ".dll" +(Windows) are DLLs. The switch -dll changes this, and all following +files are considered as DLLs, regardless of their suffix. The switch +-nodll expresses that the following files are not DLLs, even if they +have a DLL-like suffix. For example, in the following call the files +f1 and f2 are handled by the suffix rule; f3 and f4 are DLLs anyway; +and f5 and f6 are not DLLs: + + +ocamlfind install p f1 f2 -dll f3 f4 -nodll f5 f6 + + + + +The switch -optional declares that all following files are optional, +i.e. the command will not fail if files do not exist. + + + +The -patch options may be used to change the contents of the META files +while it is being installed. The option -patch-version changes the +contents of the top-level "version" variable. The option -patch-rmpkg +removes the given subpackage. The option -patch-archives is experimental, +in particular it removes all non-existing files from "archive" variables, +and even whole subpackages if the archives are missing. + + + +The effect of -add is to add further files to an already installed +packages. + + + + + + + + + + +<anchor id="ocamlfind.remove"> + THE "remove" SUBCOMMAND + + + +Synopsis + +ocamlfind remove [ -destdir directory ] + [ -metadir directory ] + [ -ldconf path ] + package_name + + + + +Description + +The package will removed if it is installed at the default location +(see the variable destdir of +findlib.conf). If the package +resides at a different location, it will not be removed by default; +however, you can pass an alternate directory for packages by the +-destdir option. (This must be the same directory as specified at +installation time.) + + + +Note that package directories should be flat (no subdirectories); this +subcommand cannot remove deep package directories. + + + +If you have a separate directory for META files, you must either +configure this directory by the metadir variable +of findlib.conf, or by specifying +the -metadir option. + + + +The command does not fail if the package and/or the META +file cannot be located. You will get a warning only in this case. + + + +If the package directory is mentioned in the ld.conf +configuration file for DLLs, it will be tried to remove this entry +from the file. The location of this file can be overriden by +the -ldconf option. To turn this feature off, use "-ldconf ignore"; +this causes that the ld.conf file is not modified. + + + +If there is a stublibs directory, it is checked whether the package +owns any of the files in this directory, and the owned files will +be deleted. + + + + + + + + + +<anchor id="ocamlfind.list"> + THE "list" SUBCOMMAND + + + +Synopsis + +ocamlfind list [-describe] + + + + +Description + +This command lists all packages in the search path. The option -describe +outputs the package descriptions, too. + + + + + + + +<anchor id="ocamlfind.printppx"> + THE "printppx" SUBCOMMAND + + + +Synopsis + +ocamlfind printppx + [ -predicates pred-name-list ] + [ -ppxopt package,arg ] + package ... + + + + +Description + +This command prints the ppx preprocessor options as they would +occur in an OCaml compiler invocation for the packages listed in +the command. The output includes one "-ppx" option for each +preprocessor. The possible options have the same meaning as for +"ocamlfind ocamlc". The option "-predicates" adds assumed +predicates and +"-ppxopt package,arg" +adds "arg" to the ppx invocation of +package package. + + + +The output of "ocamlfind printppx" will contain quotes +""" for ppx commands that contain +space-separated arguments. In this case $(ocamlfind +printppx ...) won't work as naively expected, because +many shells (including bash and dash) perform field splitting on +the result of command substitutions without honoring quotes. + + + + + + + +<anchor id="ocamlfind.lint"> + THE "lint" SUBCOMMAND + + + +Synopsis + +ocamlfind lint file + + + + +Description + +Checks the META file, and reports possible problems. + + + + + + + +<anchor id="ocamlfind.printconf"> + THE "printconf" SUBCOMMAND + + + +Synopsis + +ocamlfind printconf [ conf | path | destdir | metadir | metapath | stdlib | ldconf ] + + + + +Description + +This command prints the effective configuration after reading the +configuration file, and after applying the various environment +variables overriding settings. When called without arguments, the command +prints all configuration options in a human-readable form. When called +with an argument, only the value of the requested option is printed without +explaining texts: + + + + + conf + Prints the location of the configuration file findlib.conf + + + + path + Prints the search path for packages. The members of the + path are separated by linefeeds. + + + destdir + Prints the location where package are installed and + removed by default. + + + metadir + Prints the location where META files are installed and + removed (if the alternative layout is used). + + + metapath + Prints the path where the META file is installed for +a fictive package. The name of the package is marked with '%s' in the +path. For instance, this command could output "/some/path/%s/META" or +"/some/path/META.%s", depending on the layout. + + + stdlib + Prints the location of the standard library. + + + + ldconf + Prints the location of the ld.conf file + + + + + + + + + + + +<anchor id="ocamlfind.pkgcmd"> + THE SUBCOMMAND CALLING PACKAGE PROGRAMS + + + +Synopsis + +ocamlfind pkg/cmd argument ... + + + + +Description +This subcommand is useful to call programs that are installed in +package directories. It looks up the directory for +pkg and calls the command named +cmd in this directory. The remaining arguments +are passed to this command. + +argv(0) contains the absolute path to the command, and argv(1) and +the following argv entries contain the arguments. The working directory +is not changed. + +Example: To call the program "x" that is installed in package "p", +with arguments "y" and "z", run: + + +ocamlfind p/x y z + + + + + + + + + CONFIGURATION FILE, ENVIRONMENT VARIABLES + + + The configuration file and environment variables are documented +in the manual page for + findlib.conf. + + + + + + +<anchor id="ocamlfind.toolchain"> + HOW TO SET THE TOOLCHAIN + + + +Synopsis + +ocamlfind -toolchain name ... + + + + +Description +The -toolchain option can be given before any other command, +e.g. + +ocamlfind -toolchain foo ocamlc -c file.ml + +compiles file.ml with toolchain "foo". By selecting toolchains one +can switch to different command sets. For instance, the toolchain +"foo" may consist of a patched ocamlc compiler. +See findlib.conf how to +configure toolchains. + + + + + + + + + diff --git a/local-packages/ocamlfind/doc/src/findlib_ref.dsl b/local-packages/ocamlfind/doc/src/findlib_ref.dsl new file mode 100644 index 0000000..4b2f063 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_ref.dsl @@ -0,0 +1,24 @@ + +]> + + + + + +(define %footnotes-at-end% + ;; Should footnotes appear at the end of HTML pages? + #t) + +(define %html-ext% + ;; Default extension for HTML output files + ".html") + +(define %root-filename% + ;; Name for the root HTML document + "index") + + + + + diff --git a/local-packages/ocamlfind/doc/src/findlib_ref.sgml b/local-packages/ocamlfind/doc/src/findlib_ref.sgml new file mode 100644 index 0000000..0d5ffa1 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_ref.sgml @@ -0,0 +1,61 @@ + + + + + + + + %gps.common; +]> + + + +The findlib Reference Manual + + + + + Gerd + Stolpmann + + +
+ gerd@gerd-stolpmann.de +
+
+
+
+
+ + +1999-2003Gerd Stolpmann + + +
+ + +Commands +&findlibocamlfind; + + + +Files +&findlibmeta; + +&findlibconf; + +&findlibsitelib; + + + +Library + + The findlib library + + The findlib library + + + + +
diff --git a/local-packages/ocamlfind/doc/src/findlib_reference.sgml b/local-packages/ocamlfind/doc/src/findlib_reference.sgml new file mode 100644 index 0000000..2150d52 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_reference.sgml @@ -0,0 +1,17 @@ + + + + + + +]> + + +Reference +&findlibocamlfind; +&findlibmeta; +&findlibconf; +&findlibsitelib; + + diff --git a/local-packages/ocamlfind/doc/src/findlib_reference.xml b/local-packages/ocamlfind/doc/src/findlib_reference.xml new file mode 100644 index 0000000..35a07e9 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_reference.xml @@ -0,0 +1,2153 @@ + +Referenceocamlfind1The findlib package manager for OCamlocamlfind[Command-line interface of the Package manager]SYNOPSIS ocamlfind query [-help | other options] package_name ... + or: ocamlfind ocamlc [-help | other options] file ... + or: ocamlfind ocamlcp [-help | other options] file ... + or: ocamlfind ocamlmktop [-help | other options] file ... + or: ocamlfind ocamlopt [-help | other options] file ... + or: ocamlfind ocamldoc [-help | other options] file ... + or: ocamlfind ocamldep [-help | other options] file ... + or: ocamlfind ocamlmklib [-help | other options] file ... + or: ocamlfind ocamlbrowser [-help | other options] + or: ocamlfind install [-help | other options] package_name file ... + or: ocamlfind remove [-help | other options] package_name + or: ocamlfind lint META + or: ocamlfind list [-describe] + or: ocamlfind printppx [-help | other options] package_name ... + or: ocamlfind printconf [ variable ] + or: ocamlfind package/command arg ... + +Optional toolchain selection by: + ocamlfind -toolchain name ...<ANCHOR +ID="OCAMLFIND.QUERY" +></ANCHOR> + THE "query" SUBCOMMANDSynopsisocamlfind query [ -predicates p | + -format f | + -long-format | -l | + -i-format | + -l-format | + -a-format | + -o-format | + -p-format | + -prefix p | + -separator s | + -suffix s | + -pp | + -descendants | -d | + -recursive | -r + -qe | -qo] package ...Description This command looks packages up, sorts them optionally, and +prints attributes of them. If the option -recursive (short: -r) is not +specified, exactly the packages given on the command line are looked +up; if -recursive is present, the packages and all their ancestors, or +if -descendants (short: -d) is present, too, all their descendants are printed.Package lookup and the selection of the attributes of the packages can +be modified by specifying predicates; without a -predicates option the +empty set of predicates is used. Note that even the lookup is +influenced by the set of actual predicates as the "requires" variables +may be conditional.What is printed about a package depends on the specified format; there +are a number of options that modify the format. Some formats denote +sets of values (such as -format %a), in which case multiple output +records are printed for every package. (It is even possible to specify +formats denoting the Cartesian product of sets, such as -format %a%o, +but this does not make sense.) Before the first output record the +prefix is printed, and the suffix after the last record. Between two +records the separator is printed.Options-predicates pSets the set of actual predicates. The argument + p is a list of predicate names separated + by commas and/or whitespace. If multiple -predicates options are + given, the union of all specified sets is effectively used.-format fSets the format to the string + f. Characters preceded by a percent sign + are interpreted as placeholders; all other characters mean + themselves. The defined placeholders are listed below. + The default format is "%d".-long-format or -lSets the format such that all relevant variables are printed.-i-formatSame as -format "-I %d", i.e. directory options for ocamlc are printed.-l-formatSame as -format "-ccopt -L%d", i.e. directory options for the +linker backend are printed.-a-formatSame as -format "%+a", i.e. archive file names are printed.-o-formatSame as -format "%o", i.e. linker options are printed.-p-formatSame as -format "%p", i.e. package names are printed.-prefix pSets the prefix that is printed before the first output record + to the given string. The default prefix is the empty string.-suffix sSets the suffix that is printed after the last output record + to the given string. The default suffix is the empty string.-separator sSets the separator that is printed between output records to + the given string. The default separator is a linefeed character.-recursive or -rNot only the packages given on the command line are queried + but also all ancestors or descendants. If the option -descendants is + specified, too, the descendants are printed, otherwise the + ancestors. The packages are topologically sorted.-descendants -dInstead of the ancestors the descendants of the + given packages are queried. This option implies -recursive.-ppQuery preprocessor packages (camlp4 syntax extensions). Normally +it is not needed to set -predicates, except you need the archives (then add +-predicates byte). This option implies -recursive.-qeDo not print most errors to stderr, just set the exit code-qoDo not print the regular output.Placeholders meaningful in the -format option%%Replaced by a single percent sign%pReplaced by the package name%dReplaced by the package directory%mReplaced by the path to the META file (new since findlib-1.6)%DReplaced by the package description%vReplaced by the version string%aReplaced by the archive filename. If there is more + than one archive, a separate output record is printed for every archive.%+aLike %a, but the filenames are converted to absolute + paths ("+" and "@" notations are resolved)%AReplaced by the list of archive filenames.%+ALike %A, but the filenames are converted to absolute + paths ("+" and "@" notations are resolved)%oReplaced by one linker option. If there is more than + one option, a separate output record is printed for every option.%OReplaced by the list of linker options.%(property)Replaced by the value of the property named in parentheses, +or the empty string if not defined.<ANCHOR +ID="OCAMLFIND.OCAMLC" +></ANCHOR> + <ANCHOR +ID="OCAMLFIND.OCAMLCP" +></ANCHOR> + <ANCHOR +ID="OCAMLFIND.OCAMLOPT" +></ANCHOR> + <ANCHOR +ID="OCAMLFIND.OCAMLMKTOP" +></ANCHOR> + THE SUBCOMMANDS "ocamlc", "ocamlcp", "ocamlopt", and "ocamlmktop"Synopsisocamlfind ( ocamlc | ocamlcp | ocamlopt | ocamlmktop ) + [ -package package-name-list | + -linkpkg | + -predicates pred-name-list | + -dontlink package-name-list | + -syntax pred-name-list | + -ppopt camlp4-arg | + -ppxopt package,arg | + -dllpath-pkg package-name-list | + -dllpath-all | + -passopt arg | + -passrest arg... | + -only-show | + standard-option ] + file ...DescriptionThese subcommands are drivers for the compilers with the same names, +i.e. "ocamlfind ocamlc" is a driver for "ocamlc", and so on. The +subcommands understand all documented options of the compilers (here +called standard-options), but also a few +more options. If these subcommands are invoked only with standard +options, they behave as if the underlying compiler had been called +directly. The extra options modify this.Internally, these subcommands transform the given list of options and +file arguments into an invocation of the driven compiler. This +transformation only adds options and files, and the relative order of +the options and files passed directly is unchanged.If there are -package options, additional directory search specifiers +will be included ("-I", and "-ccopt -I"), such that files of all named +packages and all ancestors can be found.The -linkpkg option causes that the packages listed in the -package +options and all necessary ancestors are linked in. This means that the +archive files implementing the packages are inserted into the list of +file arguments.As the package database is queried a set of predicates is needed. Most +predicates are set automatically, see below, but additional predicates +can be given by a -predicates option.If there is a -syntax option, the drivers assume that +a preprocessor is to be used. In this case, the preprocessor command +is built first in a preprocessor stage, and this command is passed to the +compiler using the -pp option. The set of predicates +in the preprocessor stage is different from the set in the compiler/linker +stage.Options for compiling and linkingHere, only the additional options not interpreted by the compiler but +by the driver itself, and options with additional effects are explained. +Some options are only meaningful for the preprocessor call, and are +explained below.-package package-name-listAdds the listed package names to the set of included + packages. The package names may be separated by commas and/or + whitespace. In the transformed command, for every package of the set + of included packages and for any ancestor a directory search option + is inserted after the already given options. This means that + "-I" and "-ccopt -I" options are added for every package directory. + -linkpkgCauses that in the transformed command all archives + of the packages specified by -packages and all their ancestors are + added to the file arguments. More precisely, these archives are + inserted before the first given file argument. Furthermore, "-ccopt + -L" options for all package directories, and the linker options of + the selected packages are added, too. Note that the archives are + inserted in topological order while the linker options are added in + reverse toplogical order.-predicates pred-name-listAdds the given predicates to the set of actual + predicates. The predicates must be separated by commas and/or + whitespace. -dontlink package-name-listThis option modifies the behaviour of + -linkpkg. Packages specified here and all ancestors are not linked + in. Again the packages are separated by commas and/or whitespace.-dllpath-pkg package-name-listFor these packages -dllpath options + are added to the compiler command. This may be useful when the ld.conf + file is not properly configured.-dllpath-allFor all linked packages -dllpath options + are added to the compiler command. This may be useful when the ld.conf + file is not properly configured.-passopt argThe argument arg is + passed directly to the underlying compiler. This is needed to + specify undocumented compiler options.-passrest arg...All following arguments arg... are + passed directly to the underlying compiler. This is needed to + specify undocumented compiler options.-only-showOnly prints the constructed command (ocamlc/ocamlopt) to + stdout, but does not execute the command. (This is for the unlikely event + that you need a wrapper around ocamlfind.)-verboseThis standard option is interpreted by the driver, too.-threadThis standard option causes that the predicate "mt" + is added to the set of actual predicates. If POSIX threads are available, + the predicate "mt_posix" is selected, too. If only VM threads are + available, the predicate "mt_vm" is included into the set, and the + compiler switch is changed into -vmthread.Note that the presence of the "mt" predicate triggers special +fixup of the dependency graph (see below).-vmthreadThis standard option causes that the predicates "mt" + and "mt_vm" are added to the set of actual predicates.Note that the presence of the "mt" predicate triggers special +fixup of the dependency graph (see below).-pThis standard option of "ocamlopt" causes that the + predicate "gprof" is added to the set of actual predicates.Options for preprocessingThe options relevant for the preprocessor are the following:-package package-name-listThese packages are considered while looking up the + preprocessor arguments. (It does not cause problems that the same + -package option is used for this purpose, because the set of predicates + is different.) It is recommended to mention at least camlp4 + here if the preprocessor is going to be used. + -syntax pred-name-listThese predicates are assumed to be true in addition + to the standard preprocessor predicates. See below for a list.-ppopt camlp4-argThis argument is passed to the camlp4 call. + -ppxopt package,argAdd arg to the ppx + preprocessor invocation specified via the "ppx" property in + the META file of package. + Predicates for compiling and linkingbyteThe "byte" predicate means that one of the bytecode compilers is +used. It is automatically included into the predicate set if the +"ocamlc", "ocamlcp", or "ocamlmktop" compiler is used.nativeThe "native" predicate means that the native compiler is used. It is +automatically included into the predicate set if the "ocamlopt" +compiler is used.toploopThe "toploop" predicate means that the toploop is available in the +linked program. This predicate is only set when the toploop is actually +being executed, not when the toploop is created (this changed in version +1.0.4 of findlib).create_toploopThis predicate means that a toploop is being created (using +ocamlmktop).mtThe "mt" predicate means that the program is multi-threaded. It is +automatically included into the predicate set if the -thread option is +given. mt_posixThe "mt_posix" predicate means that in the case "mt" is set, too, the +POSIX libraries are used to implement threads. "mt_posix" is automatically +included into the predicate set if the variable "type_of_threads" in the +META description of the "threads" package has the value "posix". This +is normally the case if "findlib" is configured for POSIX threads.mt_vmThe "mt_vm" predicate means that in the case "mt" is set, too, the +VM thread emulation is used to implement multi-threading.gprofThe "gprof" predicate means that in the case "native" is set, too, the +program is compiled for profiling. It is automatically included into +the predicate set if "ocamlopt" is used and the -p option is in +effect.autolinkThe "autolink" predicate means that ocamlc is able to perform automatic +linking. It is automatically included into the predicate set if ocamlc +knows automatic linking (from version 3.00), but it is not set if the +-noautolink option is set.syntaxThis predicate is set if there is a -syntax + option. It is set both for the preprocessor and the compiler/linker stage, + and it can be used to find out whether the preprocessor is enabled or not. + Predicates for preprocessingpreprocessorThis predicate is always set while looking up the + preprocessor arguments. It can be used to distinguish between the + preprocessor stage and the compiler/linker stage.syntaxThis predicate is set if there is a -syntax + option. It is set both for the preprocessor and the compiler/linker stage, + and it can be used to find out whether the preprocessor is enabled or not. + camlp4oThis is the reserved predicate for the standard OCaml syntax. + It can be used in the -syntax predicate list. + camlp4rThis is the reserved predicate for the revised OCaml syntax. + It can be used in the -syntax predicate list. + Special behaviour of "ocamlmktop" As there is a special module Topfind that +supports loading of packages in scripts, the "ocamlmktop" subcommand +can add initialization code for this module. This extra code is +linked into the executable if "findlib" is in the set of effectively +linked packages. Fixup of the dependency graph for multi-threadingFor a number of reasons the presence of the "mt" predicate triggers +that (1) the package "threads" is added to the list of required packages +and (2) the package "threads" becomes prerequisite of all other packages +(except of itself and a few hardcoded exceptions). The effect is that +the options -thread and -vmthread automatically select the "threads" +package, and that "threads" is inserted at the right position in the +package list.Extended file namingAt a number of places one can not only refer to files by absolute +or relative path names, but also by extended names. These have two +major forms: "+name" +refers to the subdirectory name of the +standard library directory, and "@name" +refers to the package directory of the package name. +Both forms can be continued by a path, e.g. "@netstring/netstring_top.cma".You can use extended names: (1) With -I options, +(2) as normal file arguments of the compiler, (3) in the +"archive" property of packages.How to set the names of the compiler executables Normally, the OCaml bytecode compiler can be called under the name +ocamlc. However, this is not always true; sometimes a +different name is chosen. You can instruct ocamlfind to call executables with other names than +ocamlc, ocamlopt, +ocamlmktop, and ocamlcp. If present, +the environment variable OCAMLFIND_COMMANDS is interpreted +as a mapping from the standard names to the actual names of the executables. It +must have the following format: + +standardname1=actualname1 standardname2=actualname2 ...Example: You may set OCAMLFIND_COMMANDS as follows: + +OCAMLFIND_COMMANDS='ocamlc=ocamlc-3.00 ocamlopt=ocamlopt-3.00' +export OCAMLFIND_COMMANDSAlternatively, you can change the configuration file +findlib.conf.<ANCHOR +ID="OCAMLFIND.OCAMLMKLIB" +></ANCHOR> + THE SUBCOMMAND "ocamlmklib"Synopsisocamlfind ocamlmklib + [ -package package-name-list | + -predicates pred-name-list | + -dllpath-pkg package-name-list | + -dllpath-all | + -passopt arg | + -passrest arg... | + standard-option ] + file ...DescriptionThis is a wrapper around ocamlmklib, and creates library archives and +DLLs. In addition to the standard options, one can use -package to +add the search path of packages. Note that no predicates are set by default - +the wrapper does not know whether this is about byte or native code linking.This wrapper is mostly provided for completeness.<ANCHOR +ID="OCAMLFIND.OCAMLDEP" +></ANCHOR> + THE "ocamldep" SUBCOMMANDSynopsisocamlfind ocamldep [-package package-name-list | + -syntax pred-name-list | + -ppopt camlp4-arg | + -passopt arg | + -passrest arg... | + -verbose | + standard-option] file ...DescriptionThis command is a driver for the tool ocamldep of the +OCaml distribution. This driver is only useful in conjunction with +the preprocessor camlp4; otherwise it does not provide more functions +than ocamldep itself.OptionsHere, only the additional options not interpreted by ocamldep +but +by the driver itself, and options with additional effects are explained.-package package-name-listThe packages named here are only used to look up the +preprocessor options. The package camlp4 should be +specified anyway, but further packages that add capabilities to the +preprocessor can also be passed.-syntax pred-name-listThe predicates that are in effect during the look-up +of the preprocessor options. At least, either camlp4o +(selecting the normal syntax), or camlp4r (selecting +the revised syntax) should be specified.-ppopt camlp4-argAn option that is passed through to the camlp4 call.-passopt argAn option that is passed through to the ocamldep call.-passrest arg...All further arguments are passed down to ocamldep + unprocessed-verboseDisplays the resulting ocamldep command (for debugging)ExampleA typical way of using this driver: + +ocamlfind ocamldep -package camlp4,xstrp4 -syntax camlp4r file1.ml file2.ml + +This command outputs the dependencies of file1.ml and +file2.ml, although these modules make use of the +syntax extensions provided by xstrp4 and are written +in revised syntax.<ANCHOR +ID="OCAMLFIND.OCAMLBROWSER" +></ANCHOR> + THE "ocamlbrowser" SUBCOMMANDSynopsisocamlfind ocamlbrowser [-package package-name-list | + -all | + -passopt arg + -passrest ]DescriptionThis driver calls the ocamlbrowser with package options. +With -package, the specified packages are included into +the search path of the browser, and the modules of these packages become +visible (in addition to the standard library). The option -all causes that all packages are selected that are managed by findlib.As for other drivers, the options -passopt and +-passrest can be used +to pass arguments directly to the ocamlbrowser program.<ANCHOR +ID="OCAMLFIND.OCAMLDOC" +></ANCHOR> + THE SUBCOMMAND "ocamldoc"Synopsisocamlfind ocamldoc + [ -package package-name-list | + -predicates pred-name-list | + -syntax pred-name-list | + -ppopt camlp4-arg | + standard-option ] + file ...DescriptionThis subcommand is a driver for ocamldoc. It undestands all options +ocamldoc supports plus the mentioned findlib options. Basically, +the -package options are translated into -I options, and the selected +syntax options are translated into camlp4 options.OptionsHere, only the additional options not interpreted by ocamldep +but +by the driver itself, and options with additional effects are explained.-package package-name-listAdds the listed package names to the set of included + packages. The package names may be separated by commas and/or + whitespace. In the transformed command, for every package of the set + of included packages and for any ancestor a directory search option + is inserted after the already given options. This means that + "-I" options are added for every package directory. + -predicates pred-name-listAdds the given predicates to the set of actual + predicates. The predicates must be separated by commas and/or + whitespace. -syntax pred-name-listThe predicates that are in effect during the look-up +of the preprocessor options. At least, either camlp4o +(selecting the normal syntax), or camlp4r (selecting +the revised syntax) should be specified.-ppopt camlp4-argAn option that is passed through to the camlp4 call.<ANCHOR +ID="OCAMLFIND.INSTALL" +></ANCHOR> + THE "install" SUBCOMMANDSynopsisocamlfind install [ -destdir directory ] + [ -metadir directory ] + [ -ldconf path ] + [ -dont-add-directory-directive ] + [ -patch-version string ] + [ -patch-rmpkg name ] + [ -patch-archives ] + [ -dll ] [ -nodll ] [ -optional ] [ -add ] + package_name file ...DescriptionThis subcommand installs a new package either at the default location +(see the variable destdir of +findlib.conf), or in the directory +specified by the -destdir option. This +means that a new package directory is created and that the files on +the command line are copied to this directory. It is required that a +META file is one of the files copied to the target +directory.Note that package directories should be flat (no +subdirectories). Existing packages are never overwritten.It is possible to have a separate directory for all the META files. If +you want that, you have either to set the variable +metadir of +findlib.conf, or to specify the +-metadir option. In this case, the file called META is copied to the +specified directory and renamed to META.p (where p is the package +name), while all the other files are copied to the package +directory as usual. Furthermore, the META file is modified such that the +directory variable contains the path of the package +directory. +The option -dont-add-directory-directive prevents the installer from +adding a directory variable.If there are files ending in the suffixes .so or +.dll, the package directory will be added to the +DLL configuration file ld.conf, such that the dynamic +loader can find the DLL. The location of this file can be overriden by +the -ldconf option. To turn this feature off, use "-ldconf ignore"; +this causes that the ld.conf file is not modified.However, if there is a stublibs directory in site-lib, the DLLs are not +installed in the package directory, but in this directory that is +shared by all packages that are installed at the same location. +In this case, the configuration file ld.conf is +not modified, so you do not need to say "-ldconf ignore" if you +prefer this style of installation.The options -dll and -nodll can be used to control exactly which files +are considered as DLLs and which not. By default, the mentioned +suffix rule is in effect: files ending in ".so" (Unix) or ".dll" +(Windows) are DLLs. The switch -dll changes this, and all following +files are considered as DLLs, regardless of their suffix. The switch +-nodll expresses that the following files are not DLLs, even if they +have a DLL-like suffix. For example, in the following call the files +f1 and f2 are handled by the suffix rule; f3 and f4 are DLLs anyway; +and f5 and f6 are not DLLs: + +ocamlfind install p f1 f2 -dll f3 f4 -nodll f5 f6The switch -optional declares that all following files are optional, +i.e. the command will not fail if files do not exist.The -patch options may be used to change the contents of the META files +while it is being installed. The option -patch-version changes the +contents of the top-level "version" variable. The option -patch-rmpkg +removes the given subpackage. The option -patch-archives is experimental, +in particular it removes all non-existing files from "archive" variables, +and even whole subpackages if the archives are missing.The effect of -add is to add further files to an already installed +packages.<ANCHOR +ID="OCAMLFIND.REMOVE" +></ANCHOR> + THE "remove" SUBCOMMANDSynopsisocamlfind remove [ -destdir directory ] + [ -metadir directory ] + [ -ldconf path ] + package_nameDescriptionThe package will removed if it is installed at the default location +(see the variable destdir of +findlib.conf). If the package +resides at a different location, it will not be removed by default; +however, you can pass an alternate directory for packages by the +-destdir option. (This must be the same directory as specified at +installation time.)Note that package directories should be flat (no subdirectories); this +subcommand cannot remove deep package directories. If you have a separate directory for META files, you must either +configure this directory by the metadir variable +of findlib.conf, or by specifying +the -metadir option. +The command does not fail if the package and/or the META +file cannot be located. You will get a warning only in this case.If the package directory is mentioned in the ld.conf +configuration file for DLLs, it will be tried to remove this entry +from the file. The location of this file can be overriden by +the -ldconf option. To turn this feature off, use "-ldconf ignore"; +this causes that the ld.conf file is not modified.If there is a stublibs directory, it is checked whether the package +owns any of the files in this directory, and the owned files will +be deleted.<ANCHOR +ID="OCAMLFIND.LIST" +></ANCHOR> + THE "list" SUBCOMMANDSynopsisocamlfind list [-describe]DescriptionThis command lists all packages in the search path. The option -describe +outputs the package descriptions, too.<ANCHOR +ID="OCAMLFIND.PRINTPPX" +></ANCHOR> + THE "printppx" SUBCOMMANDSynopsisocamlfind printppx + [ -predicates pred-name-list ] + [ -ppxopt package,arg ] + package ...DescriptionThis command prints the ppx preprocessor options as they would +occur in an OCaml compiler invocation for the packages listed in +the command. The output includes one "-ppx" option for each +preprocessor. The possible options have the same meaning as for +"ocamlfind ocamlc". The option "-predicates" adds assumed +predicates and +"-ppxopt package,arg" +adds "arg" to the ppx invocation of +package package.The output of "ocamlfind printppx" will contain quotes +""" for ppx commands that contain +space-separated arguments. In this case $(ocamlfind +printppx ...) won't work as naively expected, because +many shells (including bash and dash) perform field splitting on +the result of command substitutions without honoring quotes.<ANCHOR +ID="OCAMLFIND.LINT" +></ANCHOR> + THE "lint" SUBCOMMANDSynopsisocamlfind lint fileDescriptionChecks the META file, and reports possible problems.<ANCHOR +ID="OCAMLFIND.PRINTCONF" +></ANCHOR> + THE "printconf" SUBCOMMANDSynopsisocamlfind printconf [ conf | path | destdir | metadir | metapath | stdlib | ldconf ]DescriptionThis command prints the effective configuration after reading the +configuration file, and after applying the various environment +variables overriding settings. When called without arguments, the command +prints all configuration options in a human-readable form. When called +with an argument, only the value of the requested option is printed without +explaining texts:confPrints the location of the configuration file findlib.conf + pathPrints the search path for packages. The members of the + path are separated by linefeeds.destdirPrints the location where package are installed and + removed by default.metadirPrints the location where META files are installed and + removed (if the alternative layout is used).metapathPrints the path where the META file is installed for +a fictive package. The name of the package is marked with '%s' in the +path. For instance, this command could output "/some/path/%s/META" or +"/some/path/META.%s", depending on the layout.stdlibPrints the location of the standard library.ldconfPrints the location of the ld.conf file<ANCHOR +ID="OCAMLFIND.PKGCMD" +></ANCHOR> + THE SUBCOMMAND CALLING PACKAGE PROGRAMSSynopsisocamlfind pkg/cmd argument ...DescriptionThis subcommand is useful to call programs that are installed in +package directories. It looks up the directory for +pkg and calls the command named +cmd in this directory. The remaining arguments +are passed to this command.argv(0) contains the absolute path to the command, and argv(1) and +the following argv entries contain the arguments. The working directory +is not changed.Example: To call the program "x" that is installed in package "p", +with arguments "y" and "z", run:ocamlfind p/x y z CONFIGURATION FILE, ENVIRONMENT VARIABLES The configuration file and environment variables are documented +in the manual page for + findlib.conf.<ANCHOR +ID="OCAMLFIND.TOOLCHAIN" +></ANCHOR> + HOW TO SET THE TOOLCHAINSynopsisocamlfind -toolchain name ...DescriptionThe -toolchain option can be given before any other command, +e.g. +ocamlfind -toolchain foo ocamlc -c file.ml +compiles file.ml with toolchain "foo". By selecting toolchains one +can switch to different command sets. For instance, the toolchain +"foo" may consist of a patched ocamlc compiler. +See findlib.conf how to +configure toolchains.META5The findlib package manager for OCamlMETA[File that specifies metainformation of OCaml packages]GRAMMAR metafile ::= entry* + entry ::= assignment | addition | subpackage + subpackage ::= "package" pkgname '(' metafile ')' + assignment ::= variable_name [ formal_predicates ] '=' value + addition ::= variable_name [ formal_predicates ] '+=' value +formal_predicates ::= '(' formal_predicate { ',' formal_predicate } ')' + variable_name ::= name + formal_predicate ::= name | '-' name + name ::= [ 'A'-'Z' 'a'-'z' '0'-'9' '_' '.' ]+ + pkgname ::= '"' (character but not '.')* '"' + value ::= '"' character* '"'DESCRIPTIONIf a package directory contains a file with the fixed name "META" it +is interpreted as described here. The file is a sequence of entries +following the given grammar; every entry defines a variable under a +certain condition given by the list of formal predicates, or it +introduces a subpackage.There is a list of predefined variables and a list of standard +predicates. These variables define: required packages, description, version +information, directories, archive files, and linker options. The +predicates denote circumstances of the application of the variables: +whether the bytecode or the native compiler is used, if there is a +toploop compiled in, details of multi-threading execution, details of +profiling. DETAILS OF THE FILE FORMATThe file consists of a sequence of entries which must be formed as the +grammar prescribes. The lexical tokens are names, values, and +interpunctuation like '(', ',' and so on. Note that linefeeds do not +play a special role, i.e. an entry definition may be given in more than +one line, or several definitions may occur on a single line. There may +be comments which begin with '#' and run until the end of the line.Names are sequences of the characters A-Z, a-z, 0-9, or _. Names +containing capital letters and names beginning with digits are +allowed but not recommended.Values are enclosed between double quotes. Values may contain any +character. The characters " and \ must be preceded by backslashes. Package names must not contain the '.' character because it is used +as delimiter of compound names.MAIN PACKAGES AND SUBPACKAGESThe outermost variable assignments and additions belong to the main +package. The name of the main package is not defined within META; +it is either the name of the directory containing META or the suffix +of the META file (if the name of the META file is formed like +META.name).The keyword package starts the definition +of a subpackage. There must not be two such definitions with the +same name. Within the parantheses, the variable assignments and +additions refer to the subpackage. It is allowed that a subpackage +contains further subpackages.The package name following package +is the local name relative to the main package, i.e. the +name of the main package is not mentioned. At all other places, +however, the subpackage must be prefixed by the name of the +containing package, separated by a '.'.Subpackages are independent of the containing package, except +that the subpackage points to the same installation directory as +the containing package (i.e. the location of the installation directory +is inherited from the containing package).SEMANTICS OF VARIABLE DEFINITIONSIn order to determine the value of a variable, first all assignments +are inspected, and the most specific assignment is taken (if there is +none, the empty string will be taken as value). In a second step, +all additions are gone through one after the other in the order +they occur in the file, and the values of all matching additions are +appended to the current value. In the following, it is further +clarified which assignment is the most specific, which additions +actually match, and how the details of the value addition look like. The most specific assignment is selected upon a set of actual +predicates, i.e. the set of predicates that are assumed to be true. +The predicates occuring in the definitions of assignments and +additions are called formal predicates. They may be positive or +negative; the latter are prepended by a '-' sign. In order to +determine the value after the evaluation of the assignments, the +following rules apply: An assignment can only be used if all positive formal +predicates are included in the set of actual predicates, and if all +negative formal predicates are not included in the set of actual +predicates. Such an assignment is called +applicable. If there is no such assignment, the +variable will have no value. If there is more than one applicable assignment, the definition with +the biggest number of formal predicates is selected.If there is still more than one applicable assignment, both applicable +and with a maximum number of formal predicates, the definition that is defined +first is selected.An addition is matching when all positive formal predicates are +included in the set of actual predicates, and all negative formal +predicates are not included.The value of an addition is appended to the current value with +implicit white space as separator.VARIABLESThere is a set of variables with predefined meaning: The +variable "directory" redefines the location of the package +directory. Normally, the META file is the first file read in the +package directory, and before any other file is read, the "directory" +variable is evaluated in order to see if the package directory must be +changed. The value of the "directory" variable is determined with an +empty set of actual predicates. The value must be either: an absolute +path name of the alternate directory, or a path name relative to the +stdlib directory of OCaml (written "+path"), or a normal relative path +name (without special syntax). In the latter case, the interpretation +depends on whether it is contained in a main or sub package, and +whether the standard repository layout or the alternate layout is in +effect (see site-lib for these terms). +For a main package in standard layout the base directory is the +directory physically containing the META file, and the relative path +is interpreted for this base directory. For a main package in +alternate layout the base directory is the directory physically +containing the META.pkg files. The base directory for subpackages is +the package directory of the containing package. (In the case +that a subpackage definition does not have a "directory" setting, +the subpackage simply inherits the package directory of the containing +package. By writing a "directory" directive one can change this +location again.) +The variable "requires" specifies the list of required packages. The +names of the packages must be separated by white space and/or commas. +The names must be fully qualified (i.e. when they refer to a subpackage, +the names of all containing packages must be prepended, separated by +'.'). +The variable "description" may include a short description of the +package (displayed by ocamlfind list). +The variable "version" specifies the version string. +The variable "archive" specifies the list of archive files. These +files should be given either as (1) plain names without any directory +information; they are only searched in the package directory. +(2) Or they have the form "+path" in which case the files are looked up +relative to the standard library. (3) Or they have the form "@name/file" +in which case the files are looked up in the package directory +of another package. (4) Or they are given as absolute paths.The +names of the files must be separated by white space and/or commas. +In the preprocessor stage, the archive files are passed as extensions +to the preprocessor (camlp4) call. In the linker stage (-linkpkg), the archive +files are linked. In the compiler stage, the archive files are ignored.Note that "archive" should only be used for archive files that are +intended to be included in executables or loaded into toploops. For +modules loaded at runtime there is the separate variable "plugin". +The variable "plugin" specifies the plugin archives of the package. +These can be dynamically loaded with the Fl_dynload +module. The plugin archives can have ".cmo", ".cma", or ".cmxs" suffix. +The variable "linkopts" specifies additional linker options.The variable "error" can be used to signal error conditions. When +this variable is applicable, the ocaml compilers are stopped, and +an error message is printed. The message is the value of the variable.The variable "warning" can be used to signal warnings. When +this variable is applicable, the warning is printed, but the +compilation continues. The message is the value of the variable. +The variable "exists_if" can be used to disable subpackages. The +value of "exists_if" is a file; the subpackage is hidden if this +file does not exist. You can also enumerate several files, and the +subpackage is hidden if none of the files exist.The variable "ppx" is a command that is added to the compiler invocation +via the -ppx option (available since OCaml-4.01). If the command is +relative to the current directory (e.g. ./cmd), the command is expected +in the package directory. The special forms as defined for "archive" +are also available (e.g. @otherpkg/cmd). Additional arguments can be +specified on the ocamlfind command line with the -ppxopt option +or the "ppxopt" variable.The variable "ppxopt" is a set of options that are added to the ppx +rewriter invocation. The contents of the variable consists of one or +several whitespace-separated parts. Every part consists of several +comma-separated subparts; the first subpart indicates the package +that contains the ppx rewriter invocation, the rest contain the options +to be appended. If the option is a path relative to the current directory +(e.g. ./foo.cma), the path is expanded relative to the package directory. +The special forms as defined for "archive" are also available +(e.g. @otherpkg/foo.cma).It is possible to define additional variables but there is currently +no software interpreting them.PREDICATESThere is a list of standard predicates:The "byte" predicate means that the bytecode compiler is used.The "native" predicate means that the native compiler is used.The "toploop" predicate means that the toploop is available in the +linked program. It is only set when the toploop is running, not when +the toploop is generated.The "create_toploop" predicate means that a toploop is created (using +ocamlmktop).The "mt" predicate means that the program is multi-threaded.The "mt_posix" predicate means that in the case "mt" is set, too, the +POSIX libraries are used to implement threads.The "mt_vm" predicate means that in the case "mt" is set, too, the +VM-based libraries are used to implement threads.The "gprof" predicate means that in the case "native" is set, too, the +program is compiled for profilingThe "autolink" predicate means that ocamlc can/will perform automatic linking.The "preprocessor" predicate means that the META variables are scanned for +preprocessor options.The "syntax" predicate means that the -syntax option is present on the +command line.Legacy: The "plugin" predicate could be used in some versions of findlib +to select cmxs archives instead of cmxa archives. This use is still possible +but discouraged.In addition to these predicates, there are package predicates +for every package that is finally selected. Of course, this kind of +predicate must not be used to select "directory" and "requires" +variables, but for the other variables they are perfectly valid. +The package predicates have the form "pkg_" plus the name of the +package (fully qualified).findlib.conf5The findlib package manager for OCamlfindlib.conf[Configuration of findlib/ocamlfind]GENERALThere are three possibilities to configure the findlib library: + +Build time: Before findlib is compiled, a "configure" script is invoked to figure + out the settings that are most likely to work on the system. Most + settings are simply entered into text files and can easily be changed + after installation. The following properties cannot be changed later + because they are compiled into the resulting binaries: + + The default location of the configuration file findlib.conf. However, + you can set a different location by the environment variable + OCAMLFIND_CONF. + Whether the installed OCaml version supports autolinking or not. + + Configuration file findlib.conf: An initial version of this file is generated by the configure script, + but you are free to modify it later. Most important, this file + contains the system-wide search path used to look up packages, and the + default location where to install new packages. + All files with the suffix ".conf" found in the directory + findlib.conf.d are also scanned for parameters. + Environment variables: The settings of findlib.conf can be overridden by environment variables. + + +Last but not least, several settings can also be passed as +command-line options, or by invoking the function +Findlib.init. findlib.confThe directory containing findlib.conf is determined at build time (by +running the configure script), the fallback default is +/usr/local/etc. You can set a different location by +changing the environment variable OCAMLFIND_CONF +which must contain the absolute path of findlib.conf.The file has the same syntax as META, i.e. it consists of a +number of lines with the format + +variable = "value"Here is the list of allowed variables: + +path The search path for META files/package directories. The variable + enumerates directories which are separated by colons (Windows: + semicolons), and these directories are tried in turn to find a certain + package. More exactly, if d is such a directory and p the searched + package, the search algorithm will first check whether d/p/META + exists. In this case, this META file is taken, and d/p is the package + directory. Second, the algorithm tries d/META.p, but the package + directory must be specified in this META.p file by a + directory directive. + Note that the first found META file is taken, so the order of the + directories in the search path counts. + This variable is required. + Example: + + path = "/usr/local/lib/ocaml/site-lib:/usr/lib/ocaml/site-lib" + + + +destdir This variable determines the location where ocamlfind + install puts the packages by default: If d is this + directory, and p the package to install, a new subdirectory d/p will + be created containing all the files of the package. + Example: + destdir = "/usr/local/lib/ocaml/site-lib" + This variable is required. + + + +metadir If set, the command ocamlfind install will put the + META files of packages into this directory (files are named META.p + where p=package name); otherwise the META files are put into the + package directories like any other file. + Example: + metadir = "/var/lib/findlib/metaregistry" + This variable is optional. It is not used by default. + + + +ocamlc, + ocamlopt, + ocamlcp, + ocamlmktop, + ocamldoc, + ocamldep, + ocamlbrowser + If you want to call other executables than "ocamlc", "ocamlopt", + "ocamlcp", "ocamlmktop", "ocamldoc", "ocamldep", and + "ocamlbrowser", you can + set the names of + the executables here. The command ocamlfind looks + into these four variables to determine the names of the compilers to + call. + Example: + ocamlc = "ocamlc.opt" +ocamlopt = "ocamlopt.opt" +ocamlcp = "ocamlcp.opt" +ocamlmktop = "ocamlmktop.opt" + This variable is optional. It is not used by default. + + +stdlib This variable determines the location of the standard library. This must + be the same directory for which the OCaml compilers are configured. + This variable is optional. It is not recommend to set this variable + unless you know what you are doing! + + +ldconf This variable determines the location of the ld.conf file. This must + be the same file the OCaml compilers read in; it is updated by + ocamlfind when installing and removing packages. You can set this + variable to the special value "ignore" to disable + the automatic modification of the ld.conf file. + If not set, the ld.conf file is assumed to reside in the OCaml + standard library directory. + This variable is optional. It is not recommended to set this variable + unless you know what you are doing! + Toolchains: It is possible to have variants of the original configuration. +These variants are called "toolchains" because they are intended to +select different compilers, e.g. patched compilers. In order to +set a variable for a certain toolchain, use the syntax + +variable(toolchain) = "value" + +For example: + +ocamlc(mypatch) = "ocamlc-mypatch" + +When the toolchain "mypatch" is selected, this compiler will be used instead +of the standard one.In order to switch to a certain toolchain, use the -toolchain +option of ocamlfind.EnvironmentA number of environment variables modifies the behaviour of +findlib/ocamlfind: + +OCAMLFIND_CONF This variable overrides the location of the configuration file + findlib.conf. It must contain the absolute path name of this file. + + +OCAMLFIND_TOOLCHAIN This variable sets the currently selected toolchain when + a -toolchain option is not passed + on the command line. + + +OCAMLPATH This variable may contain an additional search path for package + directories. It is treated as if the directories were prepended to + the configuration variable path. + + +OCAMLFIND_DESTDIR This variable overrides the configuration variable + destdir. + + +OCAMLFIND_METADIR This variable overrides the configuration variable + metadir. + + +OCAMLFIND_COMMANDS This variable overrides the configuration variables + ocamlc, ocamlopt, + ocamlcp, ocamlmktop, + ocamldoc, ocamldep, and/or + ocamlbrowser. + Its value must conform to the syntax + + ocamlc=name ocamlopt=name ocamlcp=name ocamlmktop=name ocamldoc=name ocamldep=name ocamlbrowser=name + Example: + ocamlc=ocamlc-3.00 ocamlopt=ocamlopt-3.00 ocamlcp=ocamlcp-3.00 ocamlmktop=ocamlmktop-3.00 + + +CAMLLIB or OCAMLLIB This variable overrides the configuration variable + stdlib. + + +OCAMLFIND_LDCONF This variable overrides the configuration variable + ldconf. + + +OCAMLFIND_IGNORE_DUPS_IN This variable instructs findlib not to emit warnings that packages + or module occur several times. The variable must be set to the + directory where the packages reside that are to be ignored for this + warning. + + +site-lib5The findlib package manager for OCamlsite-lib[Location of package directories]STANDARD LAYOUT...somewhere in the filesystem hierarchy... + | + \ + site-lib + | + +- (optional) stublibs + +- (optional) postinstall + +- (optional) postremove + | + +- package1 + | | + | +- META + | +- archive files + | +- interface definitions + | + +- package2 + + + : + : + \ + packageNDESCRIPTIONEvery installation of "findlib" has a default location for package +directories, which is normally a directory called "site-lib". The +location can be set by the configuration variables +path (used to look up packages), and +destdir (used to install new packages); +see findlib.conf.The name of a package is the name of the package directory. For +example, if destdir=/usr/local/lib/ocaml/site-lib, the +package p will be installed in the subdirectory +/usr/local/lib/ocaml/site-lib/p. This subdirectory +must contain the META file and all other files belonging to the package. +Package names must not contain the '.' character.The variable destdir specifies the directory for +new packages. You can only have one such directory at a time; but of +course you can change this directory in findlib.conf. The command +ocamlfind install puts new packages into this +directory; it is recommended to use this command for installation +because it ensures that the directory layout is right.For searching packages, findlib uses (only) the variable +path which may name several locations to look at.For systems with DLL support another directory may exist: stublibs. +If present, findlib will install DLLs into this directory that is +shared by all packages at the same site-lib location. Findlib remembers +which DLL belongs to which package by special files with the suffix +".owner"; e.g. for the DLL "dllpcre.so" there is another file +"dllpcre.so.owner" containing the string "pcre", so findlib knows +that the package "pcre" owns this DLL. It is not possible that a DLL +is owned by several packages.If the stublibs directory does not exist, DLLs are installed regularly +in the package directories like any other file.For special needs, a postinstall and/or a postremove script may be +installed in the site-lib directory. These scripts are invoked after +installation or removal of a package, respectively.ALTERNATE LAYOUT +...somewhere in the filesystem hierarchy... + | + \ + site-lib + | + +- (optional) stublibs + +- (optional) postinstall + +- (optional) postremove + | + +- package1 + | | + | +- archive files + | +- interface definitions + | + +- package2 + + + : + : + \ + : packageN + | + \ + metaregistry + | + +- META.package1 + +- META.package2 + + + : + \ + META.packageNThis is an alternate directory layout collecting all META files in one +directory. You can configure this layout by setting +path to the absolute location of +metaregistry. Findlib recognizes that there are +META files in this directory and uses them; it is not necessary to +include site-lib into the path.In order to work, the META files must contain a +directory directive pointing to the corresponding +package directory that resides below site-lib.The command ocamlfind install copes with this +layout, too. The variable destdir must contain the +absolute location of site-lib, and the variable +metadir must contain the absolute location of +metaregistry. Note that ocamlfind +install automatically adds a directory +directive to the META file, so you need not do it manually. diff --git a/local-packages/ocamlfind/doc/src/findlib_sitelib.mod b/local-packages/ocamlfind/doc/src/findlib_sitelib.mod new file mode 100644 index 0000000..c1fdd87 --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_sitelib.mod @@ -0,0 +1,165 @@ + + + + site-lib + 5 + The findlib package manager for OCaml + + + + site-lib + [Location of package directories] + + + + +STANDARD LAYOUT + +...somewhere in the filesystem hierarchy... + | + \ + site-lib + | + +- (optional) stublibs + +- (optional) postinstall + +- (optional) postremove + | + +- package1 + | | + | +- META + | +- archive files + | +- interface definitions + | + +- package2 + + + : + : + \ + packageN + + + + +DESCRIPTION + +Every installation of "findlib" has a default location for package +directories, which is normally a directory called "site-lib". The +location can be set by the configuration variables +path (used to look up packages), and +destdir (used to install new packages); +see findlib.conf. + + + +The name of a package is the name of the package directory. For +example, if destdir=/usr/local/lib/ocaml/site-lib, the +package p will be installed in the subdirectory +/usr/local/lib/ocaml/site-lib/p. This subdirectory +must contain the META file and all other files belonging to the package. +Package names must not contain the '.' character. + + + +The variable destdir specifies the directory for +new packages. You can only have one such directory at a time; but of +course you can change this directory in findlib.conf. The command +ocamlfind install puts new packages into this +directory; it is recommended to use this command for installation +because it ensures that the directory layout is right. + + + +For searching packages, findlib uses (only) the variable +path which may name several locations to look at. + + + +For systems with DLL support another directory may exist: stublibs. +If present, findlib will install DLLs into this directory that is +shared by all packages at the same site-lib location. Findlib remembers +which DLL belongs to which package by special files with the suffix +".owner"; e.g. for the DLL "dllpcre.so" there is another file +"dllpcre.so.owner" containing the string "pcre", so findlib knows +that the package "pcre" owns this DLL. It is not possible that a DLL +is owned by several packages. + + + +If the stublibs directory does not exist, DLLs are installed regularly +in the package directories like any other file. + + + +For special needs, a postinstall and/or a postremove script may be +installed in the site-lib directory. These scripts are invoked after +installation or removal of a package, respectively. + + + + + + +ALTERNATE LAYOUT + + + +...somewhere in the filesystem hierarchy... + | + \ + site-lib + | + +- (optional) stublibs + +- (optional) postinstall + +- (optional) postremove + | + +- package1 + | | + | +- archive files + | +- interface definitions + | + +- package2 + + + : + : + \ + : packageN + | + \ + metaregistry + | + +- META.package1 + +- META.package2 + + + : + \ + META.packageN + + + + +This is an alternate directory layout collecting all META files in one +directory. You can configure this layout by setting +path to the absolute location of +metaregistry. Findlib recognizes that there are +META files in this directory and uses them; it is not necessary to +include site-lib into the path. + + + +In order to work, the META files must contain a +directory directive pointing to the corresponding +package directory that resides below site-lib. + + + +The command ocamlfind install copes with this +layout, too. The variable destdir must contain the +absolute location of site-lib, and the variable +metadir must contain the absolute location of +metaregistry. Note that ocamlfind +install automatically adds a directory +directive to the META file, so you need not do it manually. + + + + diff --git a/local-packages/ocamlfind/doc/src/findlib_topfind.mod b/local-packages/ocamlfind/doc/src/findlib_topfind.mod new file mode 100644 index 0000000..e35840a --- /dev/null +++ b/local-packages/ocamlfind/doc/src/findlib_topfind.mod @@ -0,0 +1,333 @@ + + + + Topfind + 3 + The findlib package manager for OCaml + + + + Topfind + [Module to load packages into toploops] + + + + +SIGNATURE + +module Topfind : + sig + + + + + + + + + + + end + + + + + +DIRECTIVES + + + + + + + + + + +PACKAGING + + +The Topfind module is part of the "findlib" package. The module +depends on the presence of a toploop. When building a toploop, it is +automatically linked in if "findlib" is linked in, e.g. + + + +ocamlfind ocamlmktop options -package findlib -linkpkg options + + + +When the platform supports DLLs, another possibility to get a toploop +with findlib directives is to load the file "topfind" (normally installed +in the standard library directory): + + + +~ > ocaml + Objective Caml version 3.04 + +# #use "topfind";; +Findlib has been successfully loaded. Additional directives: + #require "package";; to load a package + #list;; to list the available packages + #camlp4o;; to load camlp4 (standard syntax) + #camlp4r;; to load camlp4 (revised syntax) + Topfind.reset();; to force that packages will be reloaded + +- : unit = () +# _ + + + +This works even in scripts (but the startup message is suppressed in this +case). + + + +The module is not thread-safe; if used in a multi-threaded script, all +packgage loading must have happened before the first thread forks. + + + + + +DESCRIPTION + + +The Topfind module contains some functions simplifying package loading +in scripts. Most important, there is a new directive "#require" for +the same purpose. + + + +The Topfind module needs some initialization, in particular the predicates variable needs to be +set, and the packages already compiled into the toploop needs to be +declared by the don't_load +function. If the toploop has been built by , the necessary initialization is +automatically compiled in. + + + + +<anchor id="Topfind.predicates"> +The variable Topfind.predicates + + +val predicates : string list ref + + +The variable contains the set of predicates that is assumed when +packages are loaded. + + + + + +<anchor id="Topfind.add-predicates"> +Topfind.add_predicates <replaceable>predlist</replaceable> + + +val add_predicates : string list -> unit + + +This function adds the passed predicates predlist +to the variable +predicates. + + + + + +<anchor id="Topfind.syntax"> +Topfind.syntax <replaceable>variant</replaceable> + + +val syntax : string -> unit + + +This function emulates the -syntax command line +switch of ocamlfind. + + + + + +<anchor id="Topfind.standard-syntax"> +Topfind.standard_syntax () + + +val standard_syntax : unit -> unit + + +The same as syntax "camlp4o". + + + + + +<anchor id="Topfind.revised-syntax"> +Topfind.revised_syntax () + + +val revised_syntax : unit -> unit + + +The same as syntax "camlp4r". + + + + + +<anchor id="Topfind.dont-load"> +Topfind.don't_load <replaceable>pkglist</replaceable> + + +val don't_load : string list -> unit + + +Declares the packages enumerated in pkglist +as being linked into the toploop. + + + + + +<anchor id="Topfind.dont-load-deeply"> +Topfind.don't_load_deeply <replaceable>pkglist</replaceable> + + +val don't_load_deeply : string list -> unit + + +Declares the packages enumerated in pkglist +and all direct and indirect ancestors as being linked into the toploop. + + + + + +<anchor id="Topfind.load"> +Topfind.load <replaceable>pkglist</replaceable> + + +val load : string list -> unit + + +The packages enumerated in pkglist are +loaded in turn; packages that have already been loaded or that have +been declared as linked in are skipped. + + + + + +<anchor id="Topfind.load-deeply"> +Topfind.load_deeply <replaceable>pkglist</replaceable> + + +val load_deeply : string list -> unit + + +The packages enumerated in pkglist and all +direct or indirect ancestors are loaded in topological order; +packages that have already been loaded or that have +been declared as linked in are skipped. + + + + + +<anchor id="Topfind.reset"> +Topfind.reset () + + +val reset : unit -> unit + + +This function causes that Topfind forgets that any package has already +been loaded. Infomation about packages linked into the toploop remain +intact. The effect of this function is that all dynamically loaded +packages will be loaded again when load, load_deeply functions, or the +#require directive are executed. + + + + + + +<anchor id="Topfind.require"> +#require "<replaceable>package-name-list</replaceable>";; + + +#require "package-name-list";; + + +The argument of the directive is a list of package names, separated by +commas and/or whitespace. The directive has the same effect as load_deeply, i.e. the listed +packages and all +direct or indirect ancestors are loaded in topological order; +packages that have already been loaded or that have +been declared as linked in are skipped. + + + + + +<anchor id="Topfind.camlp4o"> +#camlp4o ;; + + +#camlp4o ;; + + +Selects the standard syntax and loads the camlp4 preprocessor. + + + + + +<anchor id="Topfind.camlp4r"> +#camlp4r ;; + + +#camlp4r ;; + + +Selects the revised syntax and loads the camlp4 preprocessor. + + + + +<anchor id="Topfind.list"> +#list ;; + + +#list ;; + + +Lists the packages that are in the search path. + + + + + + diff --git a/local-packages/ocamlfind/findlib.conf.in b/local-packages/ocamlfind/findlib.conf.in new file mode 100644 index 0000000..261d2c8 --- /dev/null +++ b/local-packages/ocamlfind/findlib.conf.in @@ -0,0 +1,2 @@ +destdir="@SITELIB@" +path="@SITELIB@" diff --git a/local-packages/ocamlfind/itest b/local-packages/ocamlfind/itest new file mode 100755 index 0000000..6aa0137 --- /dev/null +++ b/local-packages/ocamlfind/itest @@ -0,0 +1,101 @@ +#! /bin/sh +# $Id$ +# ---------------------------------------------------------------------- +# + +case `uname` in + CYGWIN*) + execsuffix=.exe ;; + *) + execsuffix= ;; +esac +ocamlfind="src/findlib/ocamlfind${execsuffix}" + +PATH="./tools:$PATH" +export PATH + +check_linkage () { + p=$1 + shift + rm -f itest-aux/simple + $ocamlfind ocamlc -linkall -linkpkg -custom "$@" -o itest-aux/simple itest-aux/simple_$p.ml >itest-aux/err.out 2>&1 + output=`cat itest-aux/err.out | sed -e '/WARNING.*/ d'` + error=0 + if [ -n "$output" ]; then + echo "* When trying to compile with" + echo " $ocamlfind ocamlc -linkall -linkpkg -custom "$@" -o itest-aux/simple itest-aux/simple_$p.ml" + echo " an error has occurred. The error error message has been written" + echo " to itest-aux/err.out." + error=1 + fi + if [ "$error" = "0" ]; then + result=`itest-aux/simple${execsuffix}` + [ "x$result" = "xOK" ] + else + return $error + fi +} + +problems () { + echo "* This test failed. Please check the settings in site-lib-src/$1/META," + echo " especially the 'linkopts' variable, and try again. You can invoke" + echo " this test directly by: ./itest $1" +} + + +do_test () { + case "$1" in + dbm|graphics|num|str|unix|bigarray|labltk) + echo "* Checking linker options for $1 library" + rm -f itest-aux/testdb* + if check_linkage $1 -package $1; then + echo "ok" + else + problems $1 + fi + ;; + threads) + echo "* Checking linker options for threads library" + if check_linkage $1 -package $1 -thread; then + echo "ok" + else + problems $1 + fi + ;; + + camlp4) + echo "* Checking options for camlp4 preprocessor" + if check_linkage $1 -package $1 -syntax camlp4r; then + echo "ok" + else + problems $1 + fi + ;; + + *) + echo "unknown test: $1" + ;; + esac +} + + +OCAMLPATH="./site-lib-src" +export OCAMLPATH + +if [ ! -f "$ocamlfind" ]; then + echo "Sorry, you must first compile the library before you can invoke" 1>&2 + echo "the integration test." 1>&2 + exit 1 +fi + +if [ "$#" = "0" ]; then + for t in unix str dbm graphics num threads bigarray labltk camlp4; do + if [ -f "site-lib-src/$t/META" ]; then + echo "------------------------------------------------------------------------------" + do_test $t + echo + fi + done +else + do_test $1 +fi diff --git a/local-packages/ocamlfind/itest-aux/Makefile b/local-packages/ocamlfind/itest-aux/Makefile new file mode 100644 index 0000000..5b17cf7 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/Makefile @@ -0,0 +1,7 @@ +all: + +clean: + rm -f simple simple.exe *.cmi *.cmo *.cma *.cmx *.o *.obj *.a *.lib + rm -f err.out + rm -f testdb* + diff --git a/local-packages/ocamlfind/itest-aux/os_type.ml b/local-packages/ocamlfind/itest-aux/os_type.ml new file mode 100644 index 0000000..ece0739 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/os_type.ml @@ -0,0 +1,2 @@ +print_endline Sys.os_type +;; diff --git a/local-packages/ocamlfind/itest-aux/ppx.ml b/local-packages/ocamlfind/itest-aux/ppx.ml new file mode 100644 index 0000000..73ce200 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/ppx.ml @@ -0,0 +1 @@ +Toploop.preprocess_phrase;; diff --git a/local-packages/ocamlfind/itest-aux/remdir.ml b/local-packages/ocamlfind/itest-aux/remdir.ml new file mode 100644 index 0000000..2808172 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/remdir.ml @@ -0,0 +1,2 @@ +#remove_directory ".";; + diff --git a/local-packages/ocamlfind/itest-aux/simple.ml b/local-packages/ocamlfind/itest-aux/simple.ml new file mode 100644 index 0000000..5002c72 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple.ml @@ -0,0 +1,2 @@ +print_string "OK\n";; + diff --git a/local-packages/ocamlfind/itest-aux/simple_bigarray.ml b/local-packages/ocamlfind/itest-aux/simple_bigarray.ml new file mode 100644 index 0000000..76e7a55 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_bigarray.ml @@ -0,0 +1,7 @@ +open Bigarray.Array1;; +let a = create Bigarray.int Bigarray.c_layout 4 in +a.{0} <- 5 +;; + +print_endline "OK";; + diff --git a/local-packages/ocamlfind/itest-aux/simple_camlp4.ml b/local-packages/ocamlfind/itest-aux/simple_camlp4.ml new file mode 100644 index 0000000..27b2ac1 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_camlp4.ml @@ -0,0 +1,5 @@ +(* This is revised syntax: *) + +value x = 1; + +print_endline "OK"; diff --git a/local-packages/ocamlfind/itest-aux/simple_camltk.ml b/local-packages/ocamlfind/itest-aux/simple_camltk.ml new file mode 100644 index 0000000..cd7dbdb --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_camltk.ml @@ -0,0 +1,11 @@ +open Tk;; + +let top = openTk() in +Frx_after.idle + closeTk; +mainLoop() +;; + +print_string "OK\n" +;; + diff --git a/local-packages/ocamlfind/itest-aux/simple_dbm.ml b/local-packages/ocamlfind/itest-aux/simple_dbm.ml new file mode 100644 index 0000000..13a6be3 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_dbm.ml @@ -0,0 +1,10 @@ +(try + Sys.remove "itest-aux/testdb.db" +with + _ -> ()); + +let _ = + Dbm.opendbm "itest-aux/testdb" [ Dbm.Dbm_rdwr; Dbm.Dbm_create ] 0o777 in + +print_string "OK\n";; + diff --git a/local-packages/ocamlfind/itest-aux/simple_graphics.ml b/local-packages/ocamlfind/itest-aux/simple_graphics.ml new file mode 100644 index 0000000..0e47fe8 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_graphics.ml @@ -0,0 +1,4 @@ +Graphics.open_graph ""; + +print_string "OK\n";; + diff --git a/local-packages/ocamlfind/itest-aux/simple_labltk.ml b/local-packages/ocamlfind/itest-aux/simple_labltk.ml new file mode 100644 index 0000000..e3ffc00 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_labltk.ml @@ -0,0 +1,10 @@ +open Tk;; + +let _ = openTk() in +update(); +closeTk() +;; + +print_string "OK\n" +;; + diff --git a/local-packages/ocamlfind/itest-aux/simple_num.ml b/local-packages/ocamlfind/itest-aux/simple_num.ml new file mode 100644 index 0000000..36f09d8 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_num.ml @@ -0,0 +1,4 @@ +let _ = Num.num_of_int 5 in + +print_string "OK\n";; + diff --git a/local-packages/ocamlfind/itest-aux/simple_str.ml b/local-packages/ocamlfind/itest-aux/simple_str.ml new file mode 100644 index 0000000..63cdff7 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_str.ml @@ -0,0 +1,4 @@ +let _ = Str.regexp ".*" in + +print_string "OK\n";; + diff --git a/local-packages/ocamlfind/itest-aux/simple_threads.ml b/local-packages/ocamlfind/itest-aux/simple_threads.ml new file mode 100644 index 0000000..73a1933 --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_threads.ml @@ -0,0 +1,17 @@ +let tl = + List.map + (fun _ -> + Thread.create + (fun () -> + for i = 1 to 1000 do + let _ = 1+1 in () + done) + ()) + [ (); (); (); (); () ] + in + + List.iter Thread.join tl +;; + +print_string "OK\n";; + diff --git a/local-packages/ocamlfind/itest-aux/simple_unix.ml b/local-packages/ocamlfind/itest-aux/simple_unix.ml new file mode 100644 index 0000000..bdb373d --- /dev/null +++ b/local-packages/ocamlfind/itest-aux/simple_unix.ml @@ -0,0 +1,4 @@ +let _ = Unix.getpid() in + +print_string "OK\n";; + diff --git a/local-packages/ocamlfind/mini/README b/local-packages/ocamlfind/mini/README new file mode 100644 index 0000000..f2688b5 --- /dev/null +++ b/local-packages/ocamlfind/mini/README @@ -0,0 +1,104 @@ +---------------------------------------------------------------------- +ocamlfind-mini +---------------------------------------------------------------------- + +ocamlfind-mini is an OCaml script that implements a subset of the +full functionality of ocamlfind. It consists only of one file, so it +is easy to distribute it with any software. + +The subset is normally sufficient to compile a library and to +install the library; but it is insufficient to link the library +into an executable. + +---------------------------------------------------------------------- +SUPPORTED OPERATING SYSTEMS: +---------------------------------------------------------------------- + +For Unixes, the script runs out of the box. It uses the ocaml system +found in the command path. + +I think the script also runs in Windows, but I have not yet checked that. +Anyway, you cannot call it directly, but by doing +ocaml ocamlfind-mini ... + +Macintosh is not supported; I don't have enough knowledge for a Mac port. + +---------------------------------------------------------------------- +FUNCTIONALITY: +---------------------------------------------------------------------- + +Overall: The configuration file ocamlfind.conf is ignored. However, +some environment variables are respected (see below). + +A package directory is recognized by checking whether there is a META +file in it. However, the contents of that file are ignored. + +The following subset has been implemented: + +- ocamlfind-mini [ocamlc|ocamlopt|ocamlcp|ocamlmktop] ... + + The -package option works, but you must set the environment variable + OCAMLPATH (see below). + + The options -linkpkg, -predicates, -dontlink, -syntax, -ppopt are + rejected. + + This normally means that you can compile modules as in: + + ocamlfind-mini ocamlc -c -package p1,p2,p3 my_module.ml + + However, you cannot create executables because -linkpkg is not + supported. + + Note that ocamlfind-mini is unable to figure out the prerequisite + packages, so the -package option must enumerate _all_ needed packages. + + Note that ocamlfind-mini does not support the alternate directory + layout where all META files are collected in one directory. + +- ocamlfind-mini install ... + + Installs the files in the package directory for . You must help + ocamlfind-mini by specifying the destination directory: + + * Setting the -destdir option: + + ocamlfind-mini install -destdir ... + + This command installs the new package into /. + + * Setting the OCAMLFIND_DESTDIR variable: + + export OCAMLFIND_DESTDIR= + ocamlfind-mini install ... + + This command installs the new package into /, too. + +- ocamlfind-mini remove + + Removes the package . Again, you must specify the destination + directory by either setting the -destdir option or by setting the + OCAMLFIND_DESTDIR variable. + +---------------------------------------------------------------------- +ENVIRONMENT: +---------------------------------------------------------------------- + +The following variables are supported: + +- OCAMLPATH + + A colon (Win: semicolon)-separated list of directories: + OCAMLPATH=::... + + When ocamlfind-mini searches a package , it checks whether + //META exists for K=1, 2, ... + +- OCAMLFIND_DESTDIR + + The destination directory for "install" and "remove". + +- OCAMLFIND_METADIR + + The destination directory for META files. It is not recommended to set + this variable. diff --git a/local-packages/ocamlfind/mini/ocamlfind-mini b/local-packages/ocamlfind/mini/ocamlfind-mini new file mode 100755 index 0000000..288fa15 --- /dev/null +++ b/local-packages/ocamlfind/mini/ocamlfind-mini @@ -0,0 +1,851 @@ +#! /bin/sh +# (* +exec ocaml "$0" "$@" +*) directory ".";; + +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(**********************************************************************) + +(* Module split, rev. 1.2 *) + +module Split = struct +let in_words s = + (* splits s in words separated by commas and/or whitespace *) + let l = String.length s in + let rec split i j = + if j < l then + match s.[j] with + (' '|'\t'|'\n'|'\r'|',') -> + if i + split i (j+1) + else + if i + if i + split i (j+1) + else + if i ':' + | "Cygwin" -> ';' (* You might want to change this *) + | "Win32" -> ';' + | "MacOS" -> failwith "Findlib: I do not know what is the correct path separator for MacOS. If you can help me, write a mail to gerd@gerd-stolpmann.de" + | _ -> failwith "Findlib: unknown operating system" +;; + + +let path str = + (* split "str" into parts separated by "path_separator" *) + let l = String.length str in + let rec split_up j k = + if k < l then begin + let c = str.[k] in + if c = path_separator then begin + if k - j > 0 then + String.sub str j (k-j) :: split_up (k+1) (k+1) + else + split_up (k+1) (k+1) + end + else + split_up j (k+1) + end + else + if k - j > 0 then + [ String.sub str j (k-j) ] + else + [] + in + split_up 0 0 +;; +end;; + +(**********************************************************************) + + + +exception Usage;; + +type mode = + M_use | M_query | M_install | M_remove | M_compiler of string + | M_printconf | M_guess | M_list +;; + + +let rec remove_dups l = + match l with + x :: l' -> + if List.mem x l' then remove_dups l' else x::remove_dups l' + | [] -> [] +;; + + +let arg n = + if n < Array.length Sys.argv then Sys.argv.(n) else raise Not_found +;; + + +(**********************************************************************) + +let ocaml_stdlib_default = "/usr/local/lib/ocaml";; + +let ocaml_stdlib = + begin + (* Execute "ocamlc -v" and read the stdlib directory *) + let filename = Filename.temp_file "ocamlfind." ".dat" in + let command = "ocamlc -v >" ^ filename in (* SYS *) + let n = Sys.command command in + if n <> 0 then begin + prerr_endline ("ocamlfind-mini: [WARNING] Cannot determine directory of stdlib; using " ^ ocaml_stdlib_default ^ " by default"); + ocaml_stdlib_default + end + else begin + (* Search the line "Standard library directory: " *) + let tag = "Standard library directory: " in + let taglen = String.length tag in + let f = open_in filename in + let dir = ref ocaml_stdlib_default in + try + while true do + let s = input_line f in + if String.length s >= taglen && String.sub s 0 taglen = tag then begin + dir := String.sub s taglen (String.length s - taglen); + raise Exit; + end + done; + assert false + with + Exit -> + close_in f; + (try Sys.remove filename with _ -> ()); + !dir + | End_of_file -> + close_in f; + prerr_endline ("ocamlfind-mini: [WARNING] Cannot determine directory of stdlib; using " ^ ocaml_stdlib_default ^ " by default"); + ocaml_stdlib_default + end + end +;; + + +let ocamlpath = + try + Split.path (Sys.getenv "OCAMLPATH") + with + Not_found -> + (* Use stdlib as default: *) + [ ocaml_stdlib ] +;; + + +let env_destdir = + try Sys.getenv "OCAMLFIND_DESTDIR" with Not_found -> "";; + + +let env_metadir = + try Sys.getenv "OCAMLFIND_METADIR" with Not_found -> "";; + + +let core_packages = + [ "bigarray", ocaml_stdlib; + "dbm", ocaml_stdlib; + "dynlink", ocaml_stdlib; + "graphics", ocaml_stdlib; + "labltk", (Filename.concat ocaml_stdlib "labltk"); + "num", ocaml_stdlib; + "stdlib", ocaml_stdlib; + "str", ocaml_stdlib; + "threads", (Filename.concat ocaml_stdlib "threads"); + "unix", ocaml_stdlib; + ] +;; + + +(**********************************************************************) + +let package_directory pkg = + let rec lookup path = + match path with + | [] -> raise Not_found + | dir :: path' -> + let pkgdir = Filename.concat dir pkg in + let meta = Filename.concat pkgdir "META" in + if Sys.file_exists meta then + pkgdir + else + lookup path' + in + + try + List.assoc pkg core_packages + with + Not_found -> + lookup ocamlpath +;; + + +(**********************************************************************) + +let use_package prefix pkgnames = + let pdirs = + List.map + (fun pname -> + try + "-I " ^ package_directory pname + with + Not_found -> failwith ("Cannot find package " ^ pname ^ " (check environment variable OCAMLPATH)")) + pkgnames + in + + print_endline (prefix ^ String.concat " " pdirs) +;; + + +(**************** OCAMLC/OCAMLMKTOP/OCAMLOPT subcommands ****************) + +type pass_file_t = + Pass of string + | Impl of string + | Intf of string +;; + + +let ocamlc which () = + Arg.current := 1; + + let switches = ref [] in + let pass_options = ref [] in + let pass_files = ref [] in + let incpath = ref [] in + + let packages = ref [] in + + let add_switch name = + Arg.Unit (fun () -> + switches := name :: !switches; + pass_options := !pass_options @ [name]) in + let add_spec_fn name s = + pass_options := !pass_options @ [name; s] in + let add_spec name = Arg.String (add_spec_fn name) in + let add_pkg = + Arg.String (fun s -> packages := !packages @ (Split.in_words s)) in + + + Arg.parse + (List.flatten + [ [ + "-package", add_pkg, + " Refer to package when compiling"; + "-linkpkg", Arg.Unit(fun _ -> raise (Arg.Bad "Not supported: -linkpkg")), + " Link the packages in (NOT SUPPORTED)"; + "-predicates", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -predicates")), + "

Add predicate

when resolving package properties (NOT SUPPORTED)"; + "-dontlink", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -dontlink")), + " Do not link in package and its ancestors (NOT SUPPORTED)"; + "-syntax", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -syntax")), + "

Use preprocessor with predicate

(NOT SUPPORTED)"; + "-ppopt", Arg.String(fun _ -> raise (Arg.Bad "Not supported: -ppopt")), + " Append option to preprocessor invocation (NOT SUPPORTED)"; + "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), + " Pass option directly to ocamlc/opt/mktop\nSTANDARD OPTIONS:"; + + "-a", add_switch "-a", + " Build a library"; + "-c", add_switch "-c", + " Compile only (do not link)"; + "-cc", add_spec "-cc", + " Use as the C compiler and linker"; + "-cclib", add_spec "-cclib", + " Pass option to the C linker"; + "-ccopt", add_spec "-ccopt", + " Pass option to the C compiler and linker"; + ]; + if which = "ocamlopt" then [ + "-compact", add_switch "-compact", + " Optimize code size rather than speed" + ] + else []; + if which <> "ocamlopt" then [ + "-custom", add_switch "-custom", + " Link in custom mode"; + "-g", add_switch "-g", + " Save debugging information"; + ] else []; + [ + "-i", add_switch "-i", + " Print the types"; + "-I", (Arg.String + (fun s -> + incpath := s :: !incpath; + add_spec_fn "-I" s)), + "

Add to the list of include directories"; + "-impl", Arg.String (fun s -> pass_files := !pass_files @ [ Impl s ]), + " Compile as a .ml file"; + ] ; + if which = "ocamlopt" then [ + "-inline", add_spec "-inline", + " Set aggressiveness of inlining to "; + ] else []; + [ + "-intf", Arg.String (fun s -> pass_files := !pass_files @ [ Intf s ]), + " Compile as a .mli file"; + "-intf-suffix", add_spec "-intf-suffix", + " Suffix for interface file (default: .mli)"; + "-intf_suffix", add_spec "-intf_suffix", + " same as -intf-suffix"; + "-labels", add_switch "-labels", + " Use commuting label mode"; + "-linkall", add_switch "-linkall", + " Link all modules, even unused ones"; + ] ; + if which <> "ocamlopt" then [ + "-make-runtime", add_switch "-make-runtime", + " Build a runtime system"; + "-make_runtime", add_switch "-make_runtime", + " same as -make-runtime"; + ] else []; + [ + "-noautolink", add_switch "-noautolink", + " Don't automatically link C libraries specif'd in .cma files"; + "-noassert", add_switch "-noassert", + " Do not compile assertion checks"; + "-o", add_spec "-o", + " Set output file name to "; + "-output-obj", add_switch "-output-obj", + " Output a C object file instead of an executable"; + ]; + if which = "ocamlopt" then [ + "-p", add_switch "-p", + " Compile/link with profiling support for \"gprof\" + (implies -predicates gprof)"; + ] else if which = "ocamlcp" then [ + "-p", add_spec "-p", + " [afilmt] Profile constructs specified by argument: + a Everything + f Function calls + i if ... then ... else + l while, for + m match ... with + t try ... with"; + ] else []; + [ + "-pp", Arg.String (fun s -> add_spec_fn "-pp" s), + " Pipe sources through preprocessor "; + "-rectypes", add_switch "-rectypes", + " Allow arbitrary recursive types"; + ] ; + if which = "ocamlopt" then [ + "-S", add_switch "-S", + " Keep intermediate assembly file"; + ] else []; + [ + "-thread", add_switch "-thread", + " Use thread-safe standard library (implies -predicate mt)"; + "-unsafe", add_switch "-unsafe", + " No bounds checking on array and string access"; + ] ; + if which <> "ocamlopt" then [ + "-use-runtime", add_spec "-use-runtime", + " Generate bytecode for the given runtime system"; + "-use_runtime", add_spec "-use_runtime", + " same as -use-runtime"; + ] else []; + [ + "-v", add_switch "-v", + " Print compiler version number"; + "-verbose", add_switch "-verbose", + " Print calls to external commands"; + "-w", add_spec "-w", + " Enable or disable warnings according to : + A/a enable/disable all warnings + C/c enable/disable suspicious comment + F/f enable/disable partially applied function + M/m enable/disable overriden methods + P/p enable/disable partial match + S/s enable/disable non-unit statement + U/u enable/disable unused match case + V/v enable/disable hidden instance variables + X/x enable/disable all other warnings + default setting is A (all warnings enabled)"; + "-warn-error", add_spec "-warn-error", + " Turn these warnings into errors"; + "-where", add_switch "-where", + " Print standard library directory"; + "-", Arg.String (fun s -> pass_files := !pass_files @ [ Pass s ]), + " Treat as a file name (even if it starts with `-')"; + ] + ]) + (fun s -> pass_files := !pass_files @ [ Pass s]) + ("usage: ocamlfind-mini " ^ which ^ " [options] file ..."); + + begin match which with + "ocamlc" + | "ocamlcp" + | "ocamlmktop" + | "ocamlopt" -> () + | _ -> failwith "unsupported backend" + end; + + let verbose = List.mem "-verbose" !switches in + + (* check packages: *) + List.iter + (fun pkg -> + try + let _ = package_directory pkg in + () + with + Not_found -> + failwith ("package '" ^ pkg ^ "' not found (check environment variable OCAMLPATH)")) + !packages; + + let eff_packages = !packages in + + let eff_packages_dl = + remove_dups (List.map package_directory eff_packages) in + + let stdlibdir = + (* normalized form of the stdlib directory *) + let d = ocaml_stdlib in + if d <> "" & d.[String.length d - 1] = '/' then + String.sub d 0 (String.length d - 1) + else + d + in + let stdlibdirslash = stdlibdir ^ "/" in + + let i_options = + List.flatten + (List.map + (fun pkgdir -> + if pkgdir = stdlibdir or pkgdir = stdlibdirslash then + [] + else + [ "-I"; pkgdir; + "-ccopt"; "-I" ^ pkgdir; ]) + eff_packages_dl) in + + let pass_files' = + List.flatten + (List.map + (function + Pass s -> + if s.[0] = '-' + then [ "-"; String.sub s 1 (String.length s - 1) ] + else [ s ] + | Impl s -> + [ "-impl"; s ] + | Intf s -> + [ "-intf"; s ] + ) + !pass_files) + in + + let arguments = + !pass_options @ + i_options @ + pass_files' + in + + let actual_command = which in + + if verbose then + print_string ("+ " ^ actual_command ^ " " ^ + String.concat " " arguments ^ "\n"); + + flush stdout; + + let argstring = + String.concat " " + (List.map Filename.quote arguments) + in + + let status = Sys.command (actual_command ^ " " ^ argstring) in + + begin + match status with + 0 -> () + | n -> + if verbose then + print_string (actual_command ^ " returned with exit code " ^ string_of_int n ^ "\n"); + exit n + end; +;; + + +(************************************************************************) + +let make_directory dirname = + (* Invoke the mkdir command *) + let cmd = + match Sys.os_type with + "Unix" -> "mkdir" + | "Cygwin" -> "mkdir" (* don't really know *) + | "Win32" -> "md" + | "MacOS" -> failwith "make_directory not implemented for MacOS" + | _ -> failwith "Findlib: unknown operating system" + in + let c = Sys.command (cmd ^ " " ^ Filename.quote dirname) in + if c <> 0 then + failwith ("Cannot make directory " ^ dirname) +;; + + +let remove_directory dirname = + (* Invoke the rmdir command *) + let cmd = + match Sys.os_type with + "Unix" -> "rmdir" + | "Cygwin" -> "rmdir" (* don't really know *) + | "Win32" -> "rd" + | "MacOS" -> failwith "remove_directory not implemented for MacOS" + | _ -> failwith "Findlib: unknown operating system" + in + let c = Sys.command (cmd ^ " " ^ Filename.quote dirname) in + if c <> 0 then + failwith ("Cannot remove directory " ^ dirname) +;; + + +let list_dir dirname = + let rec rd_dir f = + try + let s = input_line f in + if s = "" then rd_dir f else s::rd_dir f + with + End_of_file -> + close_in f; + [] + in + + (* Invoke the ls command *) + let cmd = + match Sys.os_type with + "Unix" -> "ls -1" + | "Cygwin" -> "ls -1" (* don't really know *) + | "Win32" -> "dir /b" + | "MacOS" -> failwith "list_dir not implemented for MacOS" + | _ -> failwith "Findlib: unknown operating system" + in + let filename = Filename.temp_file "ocamlfind." ".dat" in + let fullcmd = cmd ^ " " ^ Filename.quote dirname ^ " >" ^ filename in + let n = Sys.command fullcmd in + if n <> 0 then + failwith ("Cannot execute: " ^ fullcmd); + let f = open_in filename in + let l = rd_dir f in + close_in f; + (try Sys.remove filename with _ -> ()); + l +;; + + +let copy_file ?(rename = (fun name -> name)) ?(append = "") src dstdir = + (* A system-independent function to copy the file src to dstdir *) + let outname = rename (Filename.basename src) in + let ch_in = open_in_bin src in + try + let outpath = Filename.concat dstdir outname in + if Sys.file_exists outpath then + prerr_endline ("ocamlfind-mini: [WARNING] Overwriting file " ^ outpath); + let ch_out = open_out_bin outpath in + try + let buflen = 4096 in + let buf = Bytes.create buflen in + let pos = ref 0 in + let len = ref (input ch_in buf 0 buflen) in + while !len > 0 do + output ch_out buf !pos !len; + len := input ch_in buf !pos buflen; + done; + output_string ch_out append; + close_out ch_out; + close_in ch_in; + prerr_endline("Installed " ^ outpath); + with + exc -> close_out ch_out; raise exc + with + exc -> close_in ch_in; raise exc +;; + + +let install_create_directory pkgname dstdir = + if Sys.file_exists dstdir then + failwith ("Package " ^ pkgname ^ " is already installed; please remove it first"); + make_directory dstdir +;; + + +exception Skip_file;; + +let install_package () = + let destdir = ref (env_destdir) in + let metadir = ref (env_metadir) in + let don't_add_directory_directive = ref false in + let pkgname = ref "" in + let files = ref [] in + + let keywords = + [ "-destdir", (Arg.String (fun s -> destdir := s)), + " Set the destination directory"; + "-metadir", (Arg.String (fun s -> metadir := s)), + " Install the META file into this directory"; + "-dont-add-directory-directive", (Arg.Set don't_add_directory_directive), + " never append directory='...' to META"; + ] in + let errmsg = "usage: ocamlfind-mini install [options] ..." in + + Arg.current := 1; + Arg.parse + keywords + (fun s -> + if !pkgname = "" + then pkgname := s + else files := s :: !files + ) + errmsg; + if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); + + (* Check destdir: *) + if !destdir = "" then + failwith ("No destination directory. Either specify the -destdir option, or set the environment variable OCAMLFIND_DESTDIR"); + if not (Sys.file_exists !destdir) then + failwith ("The destination directory " ^ !destdir ^ " does not exist"); + + (* Check whether META exists: *) + let meta_dot_pkg = "META." ^ !pkgname in + let has_meta = + List.exists + (fun p -> + let b = Filename.basename p in + b = "META" || b = meta_dot_pkg) + !files + in + if not has_meta then + failwith "The META file is missing"; + + (* Check that there is no meta_dot_pkg: *) + if Sys.file_exists (Filename.concat !metadir meta_dot_pkg) then + failwith ("Package " ^ !pkgname ^ " is already installed; please remove it first"); + + (* Create the package directory: *) + let pkgdir = Filename.concat !destdir !pkgname in + install_create_directory !pkgname pkgdir; + + (* Now copy the files into the package directory: *) + let has_metadir = !metadir <> "" in + List.iter + (fun p -> + try + copy_file + ~rename: (fun f -> + if has_metadir then begin + if f = "META" || f = meta_dot_pkg + then raise Skip_file + else f + end + else + if f = meta_dot_pkg then "META" else f) + p + pkgdir + with + Skip_file -> () + ) + !files; + + (* Finally copy META into metadir, if this has been requested *) + if has_metadir then begin + List.iter + (fun p -> + let b = Filename.basename p in + if b = "META" || b = meta_dot_pkg then + copy_file + ~rename: (fun f -> + if f = "META" then meta_dot_pkg else f) + ~append: ("\ndirectory=\"" ^ pkgdir ^ "\" # auto-added by ocamlfind-mini\n") + p + !metadir + ) + !files + end +;; + + +let remove_package () = + let destdir = ref (env_destdir) in + let metadir = ref (env_metadir) in + let pkgname = ref "" in + + let keywords = + [ "-destdir", (Arg.String (fun s -> destdir := s)), + " Set the destination directory"; + "-metadir", (Arg.String (fun s -> metadir := s)), + " Remove the META file from this directory"; + ] in + let errmsg = "usage: ocamlfind-mini remove [options] " in + + Arg.current := 1; + Arg.parse + keywords + (fun s -> + if !pkgname = "" + then pkgname := s + else raise (Arg.Bad "too many arguments") + ) + errmsg; + if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); + + (* Check destdir: *) + if !destdir = "" then + failwith ("No destination directory. Either specify the -destdir option, or set the environment variable OCAMLFIND_DESTDIR"); + if not (Sys.file_exists !destdir) then + failwith ("The destination directory " ^ !destdir ^ " does not exist"); + + let meta_dot_pkg = "META." ^ !pkgname in + let has_metadir = !metadir <> "" in + + (* If there is a metadir, remove the META file from it: *) + if has_metadir then begin + let f = Filename.concat !metadir meta_dot_pkg in + if Sys.file_exists f then begin + Sys.remove f; + prerr_endline ("Removed " ^ f); + end + else + prerr_endline ("ocamlfind-mini: [WARNING] No such file: " ^ f) + end; + + (* Remove the files from the package directory: *) + let pkgdir = Filename.concat !destdir !pkgname in + + if Sys.file_exists pkgdir then begin + let files = list_dir pkgdir in + List.iter (fun f -> Sys.remove (Filename.concat pkgdir f)) files; + remove_directory pkgdir; + prerr_endline ("Removed " ^ pkgdir) + end + else + prerr_endline("ocamlfind-mini: [WARNING] No such directory: " ^ pkgdir); +;; + + +let select_mode() = + let m_string = try arg 1 with Not_found -> raise Usage in + let m = + match m_string with + ("use"|"-use") -> M_use + | ("query"|"-query") -> M_query + | ("install"|"-install") -> M_install + | ("remove"|"-remove") -> M_remove + | ("ocamlc"|"-ocamlc") -> M_compiler "ocamlc" + | ("ocamlcp"|"-ocamlcp") -> M_compiler "ocamlcp" + | ("ocamlmktop"|"-ocamlmktop") -> M_compiler "ocamlmktop" + | ("ocamlopt"|"-ocamlopt") -> M_compiler "ocamlopt" + | ("printconf"|"-printconf") -> M_printconf + | ("guess"|"-guess") -> M_guess + | ("list"|"-list") -> M_list + | _ -> raise Usage + in + + m +;; + + +let sorry() = + prerr_endline "ocamlfind-mini: sorry, this function is not implemented in the reduced version of ocamlfind"; + exit 1 +;; + + +let main() = + try + let m = select_mode() in + let l = Array.length Sys.argv in + let rest = Array.sub Sys.argv 2 (l-2) in + match m with + M_use -> if rest = [| |] then raise Usage; + if rest.(0) = "-p" then begin + if l<4 then raise Usage; + use_package rest.(1) + (List.tl(List.tl(Array.to_list rest))) + end + else + use_package "" (Array.to_list rest) + | M_query -> sorry() + | M_install -> install_package() + | M_remove -> remove_package () + | M_printconf -> sorry() + | M_guess -> sorry() + | M_list -> sorry() + | M_compiler which -> ocamlc which () + with + Usage -> + prerr_endline "usage: ocamlfind-mini ocamlc [-help | other options] ..."; + prerr_endline " or: ocamlfind-mini ocamlcp [-help | other options] ..."; + prerr_endline " or: ocamlfind-mini ocamlmktop [-help | other options] ..."; + prerr_endline " or: ocamlfind-mini ocamlopt [-help | other options] ..."; + prerr_endline " or: ocamlfind-mini install [-help | other options] ..."; + prerr_endline " or: ocamlfind-mini remove [-help | other options] "; + exit 2 + | Failure f -> + prerr_endline ("ocamlfind-mini: " ^ f); + exit 2 +;; + + +try + Sys.catch_break true; + main() +with + any -> + prerr_endline ("Uncaught exception: " ^ Printexc.to_string any); + let raise_again = + try ignore(Sys.getenv "OCAMLFIND_DEBUG"); true + with Not_found -> false + in + if raise_again then raise any; + exit 3 +;; + + +(* ====================================================================== + * History: + * + * $Log: ocamlfind-mini,v $ + * Revision 1.4 2001/03/10 08:15:24 gerd + * -warn-error + * + * Revision 1.3 2001/03/06 20:18:03 gerd + * Option -where. + * + * Revision 1.2 2001/03/04 19:03:56 gerd + * list_dir: deletes the temp file after use + * + * Revision 1.1 2001/03/04 19:01:21 gerd + * Initial revision. + * + *) diff --git a/local-packages/ocamlfind/ocaml-stub b/local-packages/ocamlfind/ocaml-stub new file mode 100755 index 0000000..e5ad990 --- /dev/null +++ b/local-packages/ocamlfind/ocaml-stub @@ -0,0 +1,4 @@ +#!/bin/sh + +BINDIR=$(dirname "$(command -v ocamlc)") +"$BINDIR/ocaml" -I "$OCAML_TOPLEVEL_PATH" "$@" diff --git a/local-packages/ocamlfind/ocamlfind.install b/local-packages/ocamlfind/ocamlfind.install new file mode 100644 index 0000000..295c625 --- /dev/null +++ b/local-packages/ocamlfind/ocamlfind.install @@ -0,0 +1,6 @@ +bin: [ + "src/findlib/ocamlfind" {"ocamlfind"} + "?src/findlib/ocamlfind_opt" {"ocamlfind"} + "?tools/safe_camlp4" +] +toplevel: ["src/findlib/topfind"] diff --git a/local-packages/ocamlfind/ocargs.log b/local-packages/ocamlfind/ocargs.log new file mode 100644 index 0000000..f2bb219 --- /dev/null +++ b/local-packages/ocamlfind/ocargs.log @@ -0,0 +1,4 @@ +ocamllex -o extract_args.ml extract_args.mll +17 states, 566 transitions, table size 2366 bytes +2076 additional bytes used for bindings +ocamlc -o extract_args extract_args.ml diff --git a/local-packages/ocamlfind/opam b/local-packages/ocamlfind/opam new file mode 100644 index 0000000..a008a71 --- /dev/null +++ b/local-packages/ocamlfind/opam @@ -0,0 +1,39 @@ +opam-version: "2.0" +name: "ocamlfind" +version: "1.9.5.git" +license: "MIT" +synopsis: "A library manager for OCaml" +maintainer: "Thomas Gazagnaire " +authors: "Gerd Stolpmann " +homepage: "http://projects.camlcity.org/projects/findlib.html" +bug-reports: "https://github.com/ocaml/ocamlfind/issues" +dev-repo: "git+https://github.com/ocaml/ocamlfind.git" +description: """ +Findlib is a library manager for OCaml. It provides a convention how +to store libraries, and a file format ("META") to describe the +properties of libraries. There is also a tool (ocamlfind) for +interpreting the META files, so that it is very easy to use libraries +in programs and scripts. +""" +build: [ + [ + "./configure" + "-bindir" bin + "-sitelib" lib + "-mandir" man + "-config" "%{lib}%/findlib.conf" + "-no-custom" + "-no-camlp4" {!ocaml:preinstalled & ocaml:version >= "4.02.0"} + "-no-topfind" {ocaml:preinstalled} + ] + [make "all"] + [make "opt"] {ocaml:native} +] +install: [ + [make "install"] + ["install" "-m" "0755" "ocaml-stub" "%{bin}%/ocaml"] {ocaml:preinstalled} +] +depends: [ + "ocaml" {>= "4.00.0"} # ocamlfind uses String.map +] +depopts: ["graphics"] diff --git a/local-packages/ocamlfind/site-lib-src/bigarray/META.in b/local-packages/ocamlfind/site-lib-src/bigarray/META.in new file mode 100644 index 0000000..86dd27a --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/bigarray/META.in @@ -0,0 +1,11 @@ +# Specifications for the "bigarray" library: +requires = "unix" +version = "[distributed with Ocaml]" +description = "Large statically allocated arrays" +directory = "^" +browse_interfaces = "%%interfaces%%" +archive(byte) = "bigarray.cma" +archive(native) = "bigarray.cmxa" +plugin(byte) = "bigarray.cma" +plugin(native) = "bigarray.cmxs" +linkopts = "" diff --git a/local-packages/ocamlfind/site-lib-src/bigarray/interfaces.in b/local-packages/ocamlfind/site-lib-src/bigarray/interfaces.in new file mode 100644 index 0000000..56a108e --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/bigarray/interfaces.in @@ -0,0 +1 @@ +bigarray.cma diff --git a/local-packages/ocamlfind/site-lib-src/bytes/META b/local-packages/ocamlfind/site-lib-src/bytes/META new file mode 100644 index 0000000..690ae48 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/bytes/META @@ -0,0 +1,4 @@ +name="bytes" +version="[distributed with OCaml 4.02 or above]" +description="dummy backward-compatibility package for mutable strings" +requires="" diff --git a/local-packages/ocamlfind/site-lib-src/bytes/META.in b/local-packages/ocamlfind/site-lib-src/bytes/META.in new file mode 100644 index 0000000..690ae48 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/bytes/META.in @@ -0,0 +1,4 @@ +name="bytes" +version="[distributed with OCaml 4.02 or above]" +description="dummy backward-compatibility package for mutable strings" +requires="" diff --git a/local-packages/ocamlfind/site-lib-src/bytes/interfaces.in b/local-packages/ocamlfind/site-lib-src/bytes/interfaces.in new file mode 100644 index 0000000..b33f0c9 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/bytes/interfaces.in @@ -0,0 +1,2 @@ +bytes.cmo + diff --git a/local-packages/ocamlfind/site-lib-src/camlp4.309/META.in b/local-packages/ocamlfind/site-lib-src/camlp4.309/META.in new file mode 100644 index 0000000..92907f0 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/camlp4.309/META.in @@ -0,0 +1,95 @@ +# Specifications for the "camlp4" preprocessor: +requires = "" +version = "[distributed with Ocaml]" +description = "Base for Camlp4 syntax extensions" +directory = "%%camlp4_dir%%" + +# For the toploop: +archive(byte,toploop,camlp4o) = "camlp4o.cma" +archive(byte,toploop,camlp4r) = "camlp4r.cma" + +# Scheme-like syntax: +# Do #predicates "syntax,camlp4scheme", followed by #require "camlp4" +archive(byte,toploop,camlp4scheme) = "camlp4sch.cma" + +# Standard ML-like syntax: +# Do #predicates "syntax,camlp4sml", followed by #require "camlp4" +archive(byte,toploop,camlp4sml) = "gramlib.cma camlp4_top.cma pa_sml.cmo" + +# Lisp-like syntax: +# Do #predicates "syntax,camlp4lisp", followed by #require "camlp4" +archive(byte,toploop,camlp4lisp) = "gramlib.cma camlp4_top.cma pa_lisp.cmo" + +# For the preprocessor itself: +archive(syntax,preprocessor,camlp4o) = "pa_o.cmo pa_op.cmo pr_dump.cmo" +archive(syntax,preprocessor,camlp4r) = "pa_r.cmo pa_rp.cmo pr_dump.cmo" +archive(syntax,preprocessor,camlp4sml) = "pa_sml.cmo pr_dump.cmo" +archive(syntax,preprocessor,camlp4scheme) = "pa_scheme.cmo pr_dump.cmo" +archive(syntax,preprocessor,camlp4lisp) = "pa_lisp.cmo pr_dump.cmo" +preprocessor = "%%camlp4_cmd%% -nolib" + +package "gramlib" ( + requires(toploop) = "camlp4" + version = "[distributed with Ocaml]" + description = "Grammar library to create syntax extensions" + archive(byte) = "gramlib.cma" + archive(byte,toploop) = "" # already contained in camlp4*.cma + archive(native) = "gramlib.cmxa" +) + +package "quotations" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Quotations to create AST nodes" + archive(syntax,preprocessor) = "q_MLast.cmo" + archive(syntax,toploop) = "q_MLast.cmo" +) + +package "phony_quotations" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Phony quotations" + archive(syntax,preprocessor) = "q_phony.cmo" + archive(syntax,toploop) = "q_phony.cmo" +) + +package "extend" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: EXTEND the camlp4 grammar" + archive(syntax,preprocessor) = "pa_extend.cmo" + archive(syntax,toploop) = "pa_extend.cmo" +) + +package "extfun" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Extensible functions" + archive(syntax,preprocessor) = "pa_extfun.cmo" + archive(syntax,toploop) = "pa_extfun.cmo" +) + +package "fstream" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Functional stream parsers" + archive(syntax,preprocessor) = "pa_fstream.cmo" + archive(syntax,toploop) = "pa_fstream.cmo" +) + +package "macro" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Conditional compilation" + archive(syntax,preprocessor) = "pa_macro.cmo" + archive(syntax,toploop) = "pa_macro.cmo" +) + +package "unit_constraints" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Type constraints of type unit (revised syntax only)" + archive(syntax,preprocessor,camlp4r) = "pa_ru.cmo" + archive(syntax,toploop,camlp4r) = "pa_ru.cmo" + error(syntax,-camlp4r) = "Not available" +) diff --git a/local-packages/ocamlfind/site-lib-src/camlp4.310/META.in b/local-packages/ocamlfind/site-lib-src/camlp4.310/META.in new file mode 100644 index 0000000..2449a73 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/camlp4.310/META.in @@ -0,0 +1,147 @@ +# Specifications for the "camlp4" preprocessor: +requires = "" +version = "[distributed with Ocaml]" +description = "Base for Camlp4 syntax extensions" +directory = "+camlp4" + +# For the toploop: +requires(byte,toploop) = "%%camlp4_dynlink%%" +archive(byte,toploop,camlp4o) = "camlp4o.cma" +archive(byte,toploop,camlp4r) = "camlp4r.cma" + +# For the preprocessor itself: +archive(syntax,preprocessor,camlp4o) = "-parser o -parser op -printer p" +archive(syntax,preprocessor,camlp4r) = "-parser r -parser rp -printer p" +preprocessor = "%%camlp4_cmd%%" + +package "lib" ( + requires = "camlp4 %%camlp4_dynlink%%" + version = "[distributed with Ocaml]" + description = "Camlp4 library" + archive(byte) = "camlp4lib.cma" + archive(byte,toploop) = "" # already contained in camlp4*.cma + archive(native) = "camlp4lib.cmxa" +) + +package "gramlib" ( + requires = "camlp4.lib" + version = "[distributed with Ocaml]" + description = "Compatibilty name for camlp4.lib" +) + +# don't use camlp4.lib and camlp4.fulllib together +package "fulllib" ( + requires = "camlp4 %%camlp4_dynlink%%" + version = "[distributed with Ocaml]" + description = "Camlp4 library" + error(pkg_camlp4.lib) = "camlp4.lib and camlp4.fulllib are incompatible" + archive(byte) = "camlp4fulllib.cma" + archive(byte,toploop) = "" # already contained in camlp4*.cma + archive(native) = "camlp4fulllib.cmxa" +) + +package "quotations" ( + version = "[distributed with Ocaml]" + description = "Syntax extension: Quotations to create AST nodes" + requires = "camlp4.quotations.r" # backward compat +# We must have a non-empty archive, otherwise this pkg is ignored +# for constructing the preprocessor command. We can pass -ignore arg +# to camlp4 as dummy argument: + archive(syntax,preprocessor) = "-ignore foo" + package "o" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Quotations to create AST nodes (original syntax)" + archive(syntax,preprocessor) = "-parser Camlp4QuotationCommon -parser Camlp4OCamlOriginalQuotationExpander" + archive(syntax,toploop) = "Camlp4Parsers/Camlp4QuotationCommon.cmo Camlp4Parsers/Camlp4OCamlOriginalQuotationExpander.cmo" + ) + package "r" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Quotations to create AST nodes (revised syntax)" + archive(syntax,preprocessor) = "-parser Camlp4QuotationCommon -parser Camlp4OCamlRevisedQuotationExpander" + archive(syntax,toploop) = "Camlp4Parsers/Camlp4QuotationCommon.cmo Camlp4Parsers/Camlp4OCamlRevisedQuotationExpander.cmo" + ) +) + +package "extend" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: EXTEND the camlp4 grammar" + archive(syntax,preprocessor) = "-parser Camlp4GrammarParser" + archive(syntax,toploop) = "Camlp4Parsers/Camlp4GrammarParser.cmo" +) + +package "listcomprehension" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension for list comprehensions" + archive(syntax,preprocessor) = "-parser Camlp4ListComprehension" + archive(syntax,toploop) = "Camlp4Parsers/Camlp4ListComprehension.cmo" +) + +package "macro" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax extension: Conditional compilation" + archive(syntax,preprocessor) = "-parser Camlp4MacroParser" + archive(syntax,toploop) = "Camlp4Parsers/Camlp4MacroParser.cmo" +) + +package "mapgenerator" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax filter: Traverse data structure (map style)" + archive(syntax,preprocessor) = "-filter Camlp4MapGenerator" + archive(syntax,toploop) = "Camlp4Filters/Camlp4MapGenerator.cmo" +) + +package "foldgenerator" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax filter: Traverse data structure (fold style)" + archive(syntax,preprocessor) = "-filter Camlp4FoldGenerator" + archive(syntax,toploop) = "Camlp4Filters/Camlp4FoldGenerator.cmo" +) + +package "metagenerator" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax filter: Generate AST generator for data structure" + archive(syntax,preprocessor) = "-filter Camlp4MetaGenerator" + archive(syntax,toploop) = "Camlp4Filters/Camlp4MetaGenerator.cmo" +) + +package "locationstripper" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax filter: Remove location info from AST" + archive(syntax,preprocessor) = "-filter Camlp4LocationStripper" + archive(syntax,toploop) = "Camlp4Filters/Camlp4LocationStripper.cmo" +) + +package "tracer" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax filter: Trace execution" + archive(syntax,preprocessor) = "-filter Camlp4Tracer" + archive(syntax,toploop) = "Camlp4Filters/Camlp4Tracer.cmo" +) + +package "exceptiontracer" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax filter: Trace exception execution" + archive(syntax,preprocessor) = "-filter Camlp4ExceptionTracer" + archive(syntax,toploop) = "Camlp4Filters/Camlp4ExceptionTracer.cmo" +) + +package "profiler" ( + requires = "camlp4" + version = "[distributed with Ocaml]" + description = "Syntax filter: Count events during execution" + archive(syntax,preprocessor) = "-filter Camlp4Profiler" + archive(syntax,toploop) = "Camlp4Filters/Camlp4Profiler.cmo" + archive(byte) = "camlp4prof.cmo" + archive(native) = "camlp4prof.cmx" +) diff --git a/local-packages/ocamlfind/site-lib-src/compiler-libs/META b/local-packages/ocamlfind/site-lib-src/compiler-libs/META new file mode 100644 index 0000000..f70902f --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/compiler-libs/META @@ -0,0 +1,45 @@ +# The compiler itself +requires = "" +version = "[distributed with Ocaml]" +description = "compiler-libs support library" +directory= "+compiler-libs" + +package "common" ( + requires = "compiler-libs" + version = "[distributed with Ocaml]" + description = "Common compiler routines" + archive(byte) = "ocamlcommon.cma" + archive(native) = "ocamlcommon.cmxa" +) + +package "bytecomp" ( + requires = "compiler-libs.common" + version = "[distributed with Ocaml]" + description = "Bytecode compiler" + archive(byte) = "ocamlbytecomp.cma" + archive(native) = "ocamlbytecomp.cmxa" +) + +package "optcomp" ( + requires = "compiler-libs.common" + version = "[distributed with Ocaml]" + description = "Native-code compiler" + archive(byte) = "ocamloptcomp.cma" + archive(native) = "ocamloptcomp.cmxa" + exists_if = "ocamloptcomp.cma" +) + +package "toplevel" ( + requires = "compiler-libs.bytecomp" + version = "[distributed with Ocaml]" + description = "Toplevel interactions" + archive(byte) = "ocamltoplevel.cma" +) + +package "native-toplevel" ( + requires = "compiler-libs.optcomp dynlink" + version = "[distributed with Ocaml]" + description = "Toplevel interactions" + archive(native) = "ocamltoplevel.cmxa" + exists_if = "ocamltoplevel.cmxa" +) diff --git a/local-packages/ocamlfind/site-lib-src/compiler-libs/META.in b/local-packages/ocamlfind/site-lib-src/compiler-libs/META.in new file mode 100644 index 0000000..f70902f --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/compiler-libs/META.in @@ -0,0 +1,45 @@ +# The compiler itself +requires = "" +version = "[distributed with Ocaml]" +description = "compiler-libs support library" +directory= "+compiler-libs" + +package "common" ( + requires = "compiler-libs" + version = "[distributed with Ocaml]" + description = "Common compiler routines" + archive(byte) = "ocamlcommon.cma" + archive(native) = "ocamlcommon.cmxa" +) + +package "bytecomp" ( + requires = "compiler-libs.common" + version = "[distributed with Ocaml]" + description = "Bytecode compiler" + archive(byte) = "ocamlbytecomp.cma" + archive(native) = "ocamlbytecomp.cmxa" +) + +package "optcomp" ( + requires = "compiler-libs.common" + version = "[distributed with Ocaml]" + description = "Native-code compiler" + archive(byte) = "ocamloptcomp.cma" + archive(native) = "ocamloptcomp.cmxa" + exists_if = "ocamloptcomp.cma" +) + +package "toplevel" ( + requires = "compiler-libs.bytecomp" + version = "[distributed with Ocaml]" + description = "Toplevel interactions" + archive(byte) = "ocamltoplevel.cma" +) + +package "native-toplevel" ( + requires = "compiler-libs.optcomp dynlink" + version = "[distributed with Ocaml]" + description = "Toplevel interactions" + archive(native) = "ocamltoplevel.cmxa" + exists_if = "ocamltoplevel.cmxa" +) diff --git a/local-packages/ocamlfind/site-lib-src/dbm/META.in b/local-packages/ocamlfind/site-lib-src/dbm/META.in new file mode 100644 index 0000000..f42e437 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/dbm/META.in @@ -0,0 +1,10 @@ +# Specification for the "dbm" library +requires = "" +version = "[distributed with Ocaml]" +description = "Access to NDBM databases" +directory = "^" +browse_interfaces = "%%interfaces%%" +archive(byte) = "dbm.cma" +archive(native) = "dbm.cmxa" +plugin(byte) = "dbm.cma" +plugin(native) = "dbm.cmxs" diff --git a/local-packages/ocamlfind/site-lib-src/dbm/interfaces.in b/local-packages/ocamlfind/site-lib-src/dbm/interfaces.in new file mode 100644 index 0000000..194b097 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/dbm/interfaces.in @@ -0,0 +1 @@ +dbm.cma diff --git a/local-packages/ocamlfind/site-lib-src/dynlink/META b/local-packages/ocamlfind/site-lib-src/dynlink/META new file mode 100644 index 0000000..d9fda09 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/dynlink/META @@ -0,0 +1,8 @@ +# Specifications for the "dynlink" library: +requires = "" +version = "[distributed with Ocaml]" +description = "Dynamic loading and linking of object files" +directory = "+dynlink" +browse_interfaces = "" +archive(byte) = "dynlink.cma" +archive(native) = "dynlink.cmxa" diff --git a/local-packages/ocamlfind/site-lib-src/dynlink/META.in b/local-packages/ocamlfind/site-lib-src/dynlink/META.in new file mode 100644 index 0000000..fc483b8 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/dynlink/META.in @@ -0,0 +1,8 @@ +# Specifications for the "dynlink" library: +requires = "" +version = "[distributed with Ocaml]" +description = "Dynamic loading and linking of object files" +directory = "%%dynlink_dir%%" +browse_interfaces = "%%interfaces%%" +archive(byte) = "dynlink.cma" +%%natdynlink%% diff --git a/local-packages/ocamlfind/site-lib-src/dynlink/interfaces.in b/local-packages/ocamlfind/site-lib-src/dynlink/interfaces.in new file mode 100644 index 0000000..ba9a8e1 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/dynlink/interfaces.in @@ -0,0 +1 @@ +dynlink.cma diff --git a/local-packages/ocamlfind/site-lib-src/graphics/META.in b/local-packages/ocamlfind/site-lib-src/graphics/META.in new file mode 100644 index 0000000..c039d8e --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/graphics/META.in @@ -0,0 +1,10 @@ +# Specifications for the "graphics" library: +requires = "" +version = "[distributed with Ocaml]" +description = "Portable drawing primitives" +directory = "^" +browse_interfaces = "%%interfaces%%" +archive(byte) = "graphics.cma" +archive(native) = "graphics.cmxa" +plugin(byte) = "graphics.cma" +plugin(native) = "graphics.cmxs" diff --git a/local-packages/ocamlfind/site-lib-src/graphics/interfaces.in b/local-packages/ocamlfind/site-lib-src/graphics/interfaces.in new file mode 100644 index 0000000..c01117a --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/graphics/interfaces.in @@ -0,0 +1,2 @@ +graphics.cma + diff --git a/local-packages/ocamlfind/site-lib-src/labltk/META.in b/local-packages/ocamlfind/site-lib-src/labltk/META.in new file mode 100644 index 0000000..efbd3ed --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/labltk/META.in @@ -0,0 +1,10 @@ +# Specifications for the "labltk" library: +requires = "" +version = "[distributed with Ocaml]" +description = "The Tk windowing toolkit" +directory = "+labltk" +browse_interfaces = "%%interfaces%%" +archive(byte) = "labltk.cma" +archive(native) = "labltk.cmxa" +linkopts = "" + diff --git a/local-packages/ocamlfind/site-lib-src/labltk/interfaces.in b/local-packages/ocamlfind/site-lib-src/labltk/interfaces.in new file mode 100644 index 0000000..0f0d0d5 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/labltk/interfaces.in @@ -0,0 +1,2 @@ +labltk/*.cma + diff --git a/local-packages/ocamlfind/site-lib-src/num-top/META.in b/local-packages/ocamlfind/site-lib-src/num-top/META.in new file mode 100644 index 0000000..4f9d9d0 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/num-top/META.in @@ -0,0 +1,6 @@ +# Specification for the "num-top" library add-on: +requires = "num.core" +version = "%%findlib_version%%" +description = "Add-on for num inside toploops" +archive(byte,toploop) = "num_top.cma" + diff --git a/local-packages/ocamlfind/site-lib-src/num/META.in b/local-packages/ocamlfind/site-lib-src/num/META.in new file mode 100644 index 0000000..c47d0d5 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/num/META.in @@ -0,0 +1,14 @@ +# Specification for the "num" library: +requires = "num.core" +requires(toploop) = "num.core,num-top" +version = "[distributed with Ocaml]" +description = "Arbitrary-precision rational arithmetic" +package "core" ( + directory = "^" + version = "[internal]" + browse_interfaces = "%%interfaces%%" + archive(byte) = "nums.cma" + archive(native) = "nums.cmxa" + plugin(byte) = "nums.cma" + plugin(native) = "nums.cmxs" +) diff --git a/local-packages/ocamlfind/site-lib-src/num/interfaces.in b/local-packages/ocamlfind/site-lib-src/num/interfaces.in new file mode 100644 index 0000000..e72911a --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/num/interfaces.in @@ -0,0 +1 @@ +nums.cma diff --git a/local-packages/ocamlfind/site-lib-src/ocamlbuild/META.in b/local-packages/ocamlfind/site-lib-src/ocamlbuild/META.in new file mode 100644 index 0000000..1edcf21 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/ocamlbuild/META.in @@ -0,0 +1,8 @@ +# Specification for the "ocamlbuild" library +requires = "unix" +version = "[distributed with Ocaml]" +description = "ocamlbuild support library" +directory= "^ocamlbuild" +archive(byte) = "ocamlbuildlib.cma" +archive(native) = "ocamlbuildlib.cmxa" + diff --git a/local-packages/ocamlfind/site-lib-src/ocamldoc/META b/local-packages/ocamlfind/site-lib-src/ocamldoc/META new file mode 100644 index 0000000..bbd49f8 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/ocamldoc/META @@ -0,0 +1,5 @@ +# Specification for the "ocamldoc" library +requires = "compiler-libs" +version = "[distributed with Ocaml]" +description = "ocamldoc plugin interface" +directory= "^ocamldoc" diff --git a/local-packages/ocamlfind/site-lib-src/ocamldoc/META.in b/local-packages/ocamlfind/site-lib-src/ocamldoc/META.in new file mode 100644 index 0000000..bbd49f8 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/ocamldoc/META.in @@ -0,0 +1,5 @@ +# Specification for the "ocamldoc" library +requires = "compiler-libs" +version = "[distributed with Ocaml]" +description = "ocamldoc plugin interface" +directory= "^ocamldoc" diff --git a/local-packages/ocamlfind/site-lib-src/raw_spacetime/META.in b/local-packages/ocamlfind/site-lib-src/raw_spacetime/META.in new file mode 100644 index 0000000..58b1df7 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/raw_spacetime/META.in @@ -0,0 +1,11 @@ +# Specifications for the "spacetime" library: +requires = "" +description = "Support library for the spacetime profiler" +version = "[distributed with Ocaml]" +directory = "^" +browse_interfaces = "%%interfaces%%" +archive(byte) = "raw_spacetime_lib.cma" +archive(native) = "raw_spacetime_lib.cmxa" +plugin(byte) = "raw_spacetime_lib.cma" +plugin(native) = "raw_spacetime_lib.cmxs" + diff --git a/local-packages/ocamlfind/site-lib-src/raw_spacetime/interfaces.in b/local-packages/ocamlfind/site-lib-src/raw_spacetime/interfaces.in new file mode 100644 index 0000000..af44828 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/raw_spacetime/interfaces.in @@ -0,0 +1 @@ +raw_spacetime_lib.cma diff --git a/local-packages/ocamlfind/site-lib-src/runtime_events/META b/local-packages/ocamlfind/site-lib-src/runtime_events/META new file mode 100644 index 0000000..ee81017 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/runtime_events/META @@ -0,0 +1,11 @@ +# Specifications for the "runtime_events" library: +requires = "" +description = "Runtime events" +version = "[distributed with OCaml]" +directory = "+runtime_events" +browse_interfaces = "" +archive(byte) = "runtime_events.cma" +archive(native) = "runtime_events.cmxa" +plugin(byte) = "runtime_events.cma" +plugin(native) = "runtime_events.cmxs" + diff --git a/local-packages/ocamlfind/site-lib-src/runtime_events/META.in b/local-packages/ocamlfind/site-lib-src/runtime_events/META.in new file mode 100644 index 0000000..cc81334 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/runtime_events/META.in @@ -0,0 +1,11 @@ +# Specifications for the "runtime_events" library: +requires = "" +description = "Runtime events" +version = "[distributed with OCaml]" +directory = "+runtime_events" +browse_interfaces = "%%interfaces%%" +archive(byte) = "runtime_events.cma" +archive(native) = "runtime_events.cmxa" +plugin(byte) = "runtime_events.cma" +plugin(native) = "runtime_events.cmxs" + diff --git a/local-packages/ocamlfind/site-lib-src/runtime_events/interfaces.in b/local-packages/ocamlfind/site-lib-src/runtime_events/interfaces.in new file mode 100644 index 0000000..b6df842 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/runtime_events/interfaces.in @@ -0,0 +1 @@ +runtime_events.cma diff --git a/local-packages/ocamlfind/site-lib-src/stdlib/META b/local-packages/ocamlfind/site-lib-src/stdlib/META new file mode 100644 index 0000000..f391afc --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/stdlib/META @@ -0,0 +1,9 @@ +# Specifications for the standard library: +# (Only included because of findlib-browser) +requires = "" +description = "Standard library" +version = "[distributed with Ocaml]" +directory = "^" +browse_interfaces = "" + + diff --git a/local-packages/ocamlfind/site-lib-src/stdlib/META.in b/local-packages/ocamlfind/site-lib-src/stdlib/META.in new file mode 100644 index 0000000..a0d2977 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/stdlib/META.in @@ -0,0 +1,9 @@ +# Specifications for the standard library: +# (Only included because of findlib-browser) +requires = "" +description = "Standard library" +version = "[distributed with Ocaml]" +directory = "^" +browse_interfaces = "%%interfaces%%" + + diff --git a/local-packages/ocamlfind/site-lib-src/stdlib/interfaces.in b/local-packages/ocamlfind/site-lib-src/stdlib/interfaces.in new file mode 100644 index 0000000..bed1dcb --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/stdlib/interfaces.in @@ -0,0 +1 @@ +stdlib.cma diff --git a/local-packages/ocamlfind/site-lib-src/str/META b/local-packages/ocamlfind/site-lib-src/str/META new file mode 100644 index 0000000..68783b4 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/str/META @@ -0,0 +1,12 @@ +# Specifications for the "str" library: +requires = "" +description = "Regular expressions and string processing" +version = "[distributed with Ocaml]" +directory = "+str" +browse_interfaces = "" +archive(byte) = "str.cma" +archive(native) = "str.cmxa" +plugin(byte) = "str.cma" +plugin(native) = "str.cmxs" + + diff --git a/local-packages/ocamlfind/site-lib-src/str/META.in b/local-packages/ocamlfind/site-lib-src/str/META.in new file mode 100644 index 0000000..f557229 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/str/META.in @@ -0,0 +1,12 @@ +# Specifications for the "str" library: +requires = "" +description = "Regular expressions and string processing" +version = "[distributed with Ocaml]" +directory = "%%str_dir%%" +browse_interfaces = "%%interfaces%%" +archive(byte) = "str.cma" +archive(native) = "str.cmxa" +plugin(byte) = "str.cma" +plugin(native) = "str.cmxs" + + diff --git a/local-packages/ocamlfind/site-lib-src/str/interfaces.in b/local-packages/ocamlfind/site-lib-src/str/interfaces.in new file mode 100644 index 0000000..e3b926f --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/str/interfaces.in @@ -0,0 +1 @@ +str.cma diff --git a/local-packages/ocamlfind/site-lib-src/threads/META b/local-packages/ocamlfind/site-lib-src/threads/META new file mode 100644 index 0000000..331a5eb --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/threads/META @@ -0,0 +1,37 @@ +# Specifications for the "threads" library: +version = "[distributed with Ocaml]" +description = "Multi-threading" +requires(mt,mt_vm) = "threads.vm" +requires(mt,mt_posix) = "threads.posix" +directory = "^" +type_of_threads = "posix" + +browse_interfaces = "" + +warning(-mt) = "Linking problems may arise because of the missing -thread or -vmthread switch" +warning(-mt_vm,-mt_posix) = "Linking problems may arise because of the missing -thread or -vmthread switch" + +package "vm" ( + # --- Bytecode-only threads: + requires = "unix" + directory = "+vmthreads" + exists_if = "threads.cma" + archive(byte,mt,mt_vm) = "threads.cma" + version = "[internal]" +) + +package "posix" ( + # --- POSIX-threads: + requires = "unix" + directory = "+threads" + exists_if = "threads.cma" + archive(byte,mt,mt_posix) = "threads.cma" + archive(native,mt,mt_posix) = "threads.cmxa" + version = "[internal]" +) + +package "none" ( + error = "threading is not supported on this platform" + version = "[internal]" +) + diff --git a/local-packages/ocamlfind/site-lib-src/threads/META.in b/local-packages/ocamlfind/site-lib-src/threads/META.in new file mode 100644 index 0000000..6ccfb58 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/threads/META.in @@ -0,0 +1,37 @@ +# Specifications for the "threads" library: +version = "[distributed with Ocaml]" +description = "Multi-threading" +requires(mt,mt_vm) = "threads.vm" +requires(mt,mt_posix) = "threads.posix" +directory = "^" +type_of_threads = "%%type_of_threads%%" + +browse_interfaces = "%%interfaces%%" + +warning(-mt) = "Linking problems may arise because of the missing -thread or -vmthread switch" +warning(-mt_vm,-mt_posix) = "Linking problems may arise because of the missing -thread or -vmthread switch" + +package "vm" ( + # --- Bytecode-only threads: + requires = "unix" + directory = "+vmthreads" + exists_if = "threads.cma" + archive(byte,mt,mt_vm) = "threads.cma" + version = "[internal]" +) + +package "posix" ( + # --- POSIX-threads: + requires = "unix" + directory = "+threads" + exists_if = "threads.cma" + archive(byte,mt,mt_posix) = "threads.cma" + archive(native,mt,mt_posix) = "threads.cmxa" + version = "[internal]" +) + +package "none" ( + error = "threading is not supported on this platform" + version = "[internal]" +) + diff --git a/local-packages/ocamlfind/site-lib-src/threads/interfaces.in b/local-packages/ocamlfind/site-lib-src/threads/interfaces.in new file mode 100644 index 0000000..b3c6481 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/threads/interfaces.in @@ -0,0 +1,2 @@ +vmthreads/threads.cma + diff --git a/local-packages/ocamlfind/site-lib-src/unix/META b/local-packages/ocamlfind/site-lib-src/unix/META new file mode 100644 index 0000000..3955cca --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/unix/META @@ -0,0 +1,13 @@ +# Specifications for the "unix" library: +requires = "" +description = "Unix system calls" +version = "[distributed with Ocaml]" +directory = "+unix" +browse_interfaces = "" +archive(byte) = "unix.cma" +archive(native) = "unix.cmxa" +archive(byte,mt_vm) = "vmthreads/unix.cma" +plugin(byte) = "unix.cma" +plugin(native) = "unix.cmxs" +plugin(byte,mt_vm) = "vmthreads/unix.cma" + diff --git a/local-packages/ocamlfind/site-lib-src/unix/META.in b/local-packages/ocamlfind/site-lib-src/unix/META.in new file mode 100644 index 0000000..020c083 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/unix/META.in @@ -0,0 +1,13 @@ +# Specifications for the "unix" library: +requires = "" +description = "Unix system calls" +version = "[distributed with Ocaml]" +directory = "%%unix_dir%%" +browse_interfaces = "%%interfaces%%" +archive(byte) = "unix.cma" +archive(native) = "unix.cmxa" +archive(byte,mt_vm) = "vmthreads/unix.cma" +plugin(byte) = "unix.cma" +plugin(native) = "unix.cmxs" +plugin(byte,mt_vm) = "vmthreads/unix.cma" + diff --git a/local-packages/ocamlfind/site-lib-src/unix/interfaces.in b/local-packages/ocamlfind/site-lib-src/unix/interfaces.in new file mode 100644 index 0000000..5984298 --- /dev/null +++ b/local-packages/ocamlfind/site-lib-src/unix/interfaces.in @@ -0,0 +1 @@ +unix.cma diff --git a/local-packages/ocamlfind/src/bytes/META b/local-packages/ocamlfind/src/bytes/META new file mode 100644 index 0000000..dd96130 --- /dev/null +++ b/local-packages/ocamlfind/src/bytes/META @@ -0,0 +1,9 @@ +name="bytes" +version="[OCaml strictly before 4.02]" +description="backward-compatibility package for mutable strings" +requires="" +browse_interfaces = "String" +archive(byte)="bytes.cma" +archive(native)="bytes.cmxa" +plugin(byte)="bytes.cma" +plugin(native)="bytes.cmxs" diff --git a/local-packages/ocamlfind/src/bytes/Makefile b/local-packages/ocamlfind/src/bytes/Makefile new file mode 100644 index 0000000..dd5b9b9 --- /dev/null +++ b/local-packages/ocamlfind/src/bytes/Makefile @@ -0,0 +1,40 @@ +BYTE_FILES=bytes.cmi bytes.cma +NATIVE_FILES=bytes.cmx bytes$(LIB_SUFFIX) bytes.cmxa +NATIVE_FILES_DYNLINK=bytes.cmxs + +TOP=../.. +include $(TOP)/Makefile.config + +OCAMLC = ocamlc +OCAMLOPT = ocamlopt -g + +build: all opt + +all: + $(OCAMLC) -a -o bytes.cma bytes.ml + +opt: + $(OCAMLOPT) -a -o bytes.cmxa bytes.ml + if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ + $(OCAMLOPT) -shared -o bytes.cmxs bytes.cmxa; \ + fi + +install: all + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes" + $(INSTALLFILE) META $(BYTE_FILES) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes/" + for f in $(NATIVE_FILES) $(NATIVE_FILES_DYNLINK); do if [ -f "$$f" ]; then $(INSTALLFILE) $$f "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes/"; fi; done + +uninstall: + rm -rf "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/bytes" + +# install-self and uninstall-self use ocamlfind already. This is a bit +# questionable here. + +install-self: all + ocamlfind install bytes META $(BYTE_FILES) -optional $(NATIVE_FILES) $(NATIVE_FILES_DYNLINK) + +uninstall-self: + ocamlfind remove bytes + +clean: + ocamlbuild -clean diff --git a/local-packages/ocamlfind/src/bytes/README b/local-packages/ocamlfind/src/bytes/README new file mode 100644 index 0000000..5cd9900 --- /dev/null +++ b/local-packages/ocamlfind/src/bytes/README @@ -0,0 +1,7 @@ +backward-compatibility package for the standard Bytes module of 4.02 + +Starting from 4.02, the OCaml standard library splits String into two +modules, String for now-immutable strings and Bytes for mutable byte +sequences. This package exports a Bytes package mimicking the new +interface to older OCaml version, letting you write code using Bytes +that works with OCaml < 4.02. diff --git a/local-packages/ocamlfind/src/bytes/bytes.ml b/local-packages/ocamlfind/src/bytes/bytes.ml new file mode 100644 index 0000000..127519f --- /dev/null +++ b/local-packages/ocamlfind/src/bytes/bytes.ml @@ -0,0 +1,36 @@ +include String + +let empty = "" +let of_string = copy +let to_string = copy + +let sub_string = sub +let blit_string = blit + +let unsafe_to_string : t -> string = fun s -> s +let unsafe_of_string : string -> t = fun s -> s + +let extend s left right = + (* length of the final string *) + let dstlen = left + length s + right in + (* length of the included portion of the input string *) + let srclen = min 0 left + length s + min 0 right in + let t = create dstlen in + if srclen > 0 then blit s (max 0 (-left)) t (max 0 left) srclen; + t + +let init len f = + let s = create len in + for i = 0 to len - 1 do + set s i (f i); + done; + s + +let mapi f input = + let output = create (length input) in + for i = 0 to length input - 1 do + output.[i] <- f i input.[i]; + done; + output + +let cat = (^) diff --git a/local-packages/ocamlfind/src/findlib-toolbox/Makefile b/local-packages/ocamlfind/src/findlib-toolbox/Makefile new file mode 100644 index 0000000..e8bfdb5 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib-toolbox/Makefile @@ -0,0 +1,37 @@ +TOP=../.. +include $(TOP)/Makefile.config + +.PHONY: all opt install uninstall clean + +all: make_wizard$(EXEC_SUFFIX) + +opt: + true + +make_wizard$(EXEC_SUFFIX): make_wizard.ml + ocamlc -o make_wizard$(EXEC_SUFFIX) -I +unix -I +labltk -I ../findlib \ + unix.cma str.cma labltk.cma findlib.cma make_wizard.ml + +install: + $(INSTALLFILE) make_wizard$(EXEC_SUFFIX) make_wizard.pattern $(DESTDIR)$(prefix)$(OCAML_SITELIB)/findlib/ + +# uninstall: Nothing to do, because the removal of the findlib core also +# deinstalls the make_wizard +uninstall: + true + +# ---------------------------------------------------------------------- + +tree: lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml test_tree.ml + ocamlfind ocamlc -o tree -package labltk,unix,str -linkpkg \ + lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml test_tree.ml + +tree_editor: lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml tree_editor.ml + ocamlfind ocamlc -o tree_editor -package labltk,unix,str -linkpkg \ + lx_spots.mli lx_spots.ml lx_tree.mli lx_tree.ml tree_editor.ml + +# ---------------------------------------------------------------------- + +clean: + rm -f *.cmi *.cmo + rm -f make_wizard$(EXEC_SUFFIX) # tree tree_editor diff --git a/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.ml b/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.ml new file mode 100644 index 0000000..574c23c --- /dev/null +++ b/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.ml @@ -0,0 +1,1559 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + + +open Tk;; +open Widget;; + +(**********************************************************************) +(* GLOBAL VARIABLES *) +(**********************************************************************) + +(* General *) + +let wiz_package_name = ref "";; +let wiz_package_version = ref "";; +let wiz_package_description = ref "";; + +(* Preprocessor *) + +let wiz_enable_camlp4 = ref false;; +let wiz_camlp4_syntax = ref "camlp4o";; +let wiz_camlp4_extensions = ref [];; (* list of package names *) +let wiz_camlp4_selected = ref [];; (* subset of wiz_camlp4_extensions *) +let wiz_camlp4_options = ref "";; + +(* Prerequisites *) + +let wiz_all_packages = ref [];; (* list of package names *) +let wiz_required_packages = ref [];; (* subset of wiz_all_packages *) + +(* Build Library *) + +let wiz_available = ref [];; (* list of module names *) +let wiz_byte_enable = ref true;; +let wiz_nat_enable = ref true;; +let wiz_objects = ref [];; (* subset of wiz_available *) +let wiz_source_suffixes = ref ".ml .mli .mll .mly";; + +(* Build Executables *) + +let wiz_executables = ref [];; (* list of executable names *) +let wiz_exec_objects = (ref [] : (string * (string list ref)) list ref);; + (* an alist: for every executable, the corresponding list of modules is + * stored. + *) +let wiz_exec_native = (ref [] : (string * bool ref) list ref);; + (* an alist: for every executable, whether it is natively compiled or not *) + +(* Generate *) + +let wiz_makefile_name = ref "Makefile";; +let wiz_local_makefile_name = ref "";; +let wiz_make_default = ref "byte" ;; + + +(**********************************************************************) +(* AUXILIARY FUNCTIONS *) +(**********************************************************************) + +let find_pos x l = + let rec find k l = + match l with + h :: l' -> + if x = h then k else find (k+1) l' + | [] -> + raise Not_found + in + find 0 l +;; + + +let rec delete_at k l = + match l with + h :: l' -> if k <= 0 then l' else h :: (delete_at (k-1) l') + | [] -> [] +;; + + +let rec insert_at k x l = + if k <= 0 then + x :: l + else + match l with + h :: l' -> h :: (insert_at (k-1) x l') + | [] -> [] (* insert beyond end *) +;; + + +let rec remove_dups l = + (* Remove duplicate members in a sorted list *) + match l with + x :: (y :: l' as l1) when x = y -> + remove_dups l1 + | x :: l' -> + x :: remove_dups l' + | [] -> + [] +;; + + +(**********************************************************************) +(* SAVE/LOAD STATE *) +(**********************************************************************) + +let save_var name printer out var = + output_string out ("V" ^ name ^ "\n"); + printer out var +;; + +let save_string out var = + (* [var] must not contain linefeeds *) + output_string out ("S" ^ var ^ "\n") +;; + +let save_bool out var = + output_string out ("B" ^ string_of_bool var ^ "\n") +;; + +let save_list printer out var = + output_string out ("L" ^ string_of_int (List.length var) ^ "\n"); + List.iter (printer out) var +;; + +let save_pair lprinter rprinter out (lvar,rvar) = + output_string out "P\n"; + lprinter out lvar; + rprinter out rvar +;; + +let save_ref printer out var = + (* Actually doesn't save the reference! *) + printer out !var +;; + +let save_state out = + save_var "wiz_package_name" save_string out !wiz_package_name; + save_var "wiz_package_version" save_string out !wiz_package_version; + save_var "wiz_package_description" save_string out !wiz_package_description; + save_var "wiz_enable_camlp4" save_bool out !wiz_enable_camlp4; + save_var "wiz_camlp4_syntax" save_string out !wiz_camlp4_syntax; + save_var "wiz_camlp4_extensions" (save_list save_string) out + !wiz_camlp4_extensions; + save_var "wiz_camlp4_selected" (save_list save_string) out + !wiz_camlp4_selected; + save_var "wiz_camlp4_options" save_string out !wiz_camlp4_options; + save_var "wiz_all_packages" (save_list save_string) out + !wiz_all_packages; + save_var "wiz_required_packages" (save_list save_string) out + !wiz_required_packages; + save_var "wiz_available" (save_list save_string) out + !wiz_available; + save_var "wiz_byte_enable" save_bool out !wiz_byte_enable; + save_var "wiz_nat_enable" save_bool out !wiz_nat_enable; + save_var "wiz_objects" (save_list save_string) out + !wiz_objects; + save_var "wiz_source_suffixes" save_string out !wiz_source_suffixes; + save_var "wiz_executables" (save_list save_string) out + !wiz_executables; + save_var "wiz_exec_objects" + (save_list (save_pair save_string (save_ref (save_list save_string)))) + out + !wiz_exec_objects; + save_var "wiz_exec_native" + (save_list (save_pair save_string (save_ref save_bool))) + out + !wiz_exec_native; + save_var "wiz_makefile_name" save_string out !wiz_makefile_name; + save_var "wiz_local_makefile_name" save_string out !wiz_local_makefile_name; + save_var "wiz_make_default" save_string out !wiz_make_default; +;; + +let save() = + let f = open_out ".make-wizard" in + save_state f; + close_out f +;; + +let check_char inch c_expected = + let c = input_char inch in + if c <> c_expected then failwith "Cannot read .make-wizard" +;; + +let load_string inch = + check_char inch 'S'; + let line = input_line inch in + (* prerr_endline ("String = " ^ line); *) + line +;; + +let load_bool inch = + check_char inch 'B'; + bool_of_string(input_line inch) +;; + +let load_list parse inch = + check_char inch 'L'; + let n = int_of_string(input_line inch) in + let l = ref [] in + for i = 1 to n do + l := parse inch :: !l; + done; + List.rev !l +;; + +let load_pair lparse rparse inch = + check_char inch 'P'; + ignore(input_line inch); + let l = lparse inch in + let r = rparse inch in + (l,r) +;; + +let load_ref parse inch = + ref(parse inch) +;; + +let load_var var parse inch = + let value = parse inch in + var := value +;; + +let load_variables spec inch = + try + while true do + try + check_char inch 'V'; + let name = input_line inch in + (* prerr_endline name;*) + let loader = List.assoc name spec in (* or Not_found *) + loader inch + with + Not_found -> + () + done; + assert false + with + End_of_file -> + () +;; + +let load_state inch = + load_variables + [ "wiz_package_name", + (load_var wiz_package_name load_string); + "wiz_package_version", + (load_var wiz_package_version load_string); + "wiz_package_description", + (load_var wiz_package_description load_string); + "wiz_enable_camlp4", + (load_var wiz_enable_camlp4 load_bool); + "wiz_camlp4_syntax", + (load_var wiz_camlp4_syntax load_string); + "wiz_camlp4_extensions", + (load_var wiz_camlp4_extensions (load_list load_string)); + "wiz_camlp4_selected", + (load_var wiz_camlp4_selected (load_list load_string)); + "wiz_camlp4_options", + (load_var wiz_camlp4_options load_string); + "wiz_all_packages", + (load_var wiz_all_packages (load_list load_string)); + "wiz_required_packages", + (load_var wiz_required_packages (load_list load_string)); + "wiz_available", + (load_var wiz_available (load_list load_string)); + "wiz_byte_enable", + (load_var wiz_byte_enable load_bool); + "wiz_nat_enable", + (load_var wiz_nat_enable load_bool); + "wiz_objects", + (load_var wiz_objects (load_list load_string)); + "wiz_source_suffixes", + (load_var wiz_source_suffixes load_string); + "wiz_executables", + (load_var wiz_executables (load_list load_string)); + "wiz_exec_objects", + (load_var wiz_exec_objects (load_list + (load_pair + load_string + (load_ref (load_list load_string))))); + "wiz_exec_native", + (load_var wiz_exec_native (load_list + (load_pair + load_string + (load_ref load_bool)))); + "wiz_makefile_name", + (load_var wiz_makefile_name load_string); + "wiz_local_makefile_name", + (load_var wiz_local_makefile_name load_string); + "wiz_make_default", + (load_var wiz_make_default load_string); + ] + inch +;; + + +let load() = + let f = open_in ".make-wizard" in + load_state f; + close_in f +;; + + +(**********************************************************************) +(* PARSE PATTERN FILE *) +(**********************************************************************) + +type sectiondata = + Sect_const of string + | Sect_var of string + +let section_re = Str.regexp "^\\[\\([A-Za-z_0-9-]+\\)\\]$" ;; +let var_re = Str.regexp "\\[\\([A-Za-z_0-9-]+\\)\\]" ;; + +let parse_pattern inch = + let rec parse_section name sect = + try + let line = input_line inch in + if String.length line >= 2 && line.[0] = '#' && line.[1] = '#' then + (* Comment line *) + parse_section name sect + else + if Str.string_match section_re line 0 then + (* New section begins *) + let name' = Str.matched_group 1 line in + (name, List.rev sect) :: parse_section name' [] + else + (* Normal data region *) + let plist = Str.full_split var_re line in + let slist = + List.map + (function + Str.Text t -> Sect_const t + | Str.Delim d -> Sect_var (String.sub d 1 (String.length d - 2)) + ) + plist @ [ Sect_const "\n" ] in + parse_section name (List.rev slist @ sect) + with + End_of_file -> + [ name, List.rev sect ] + in + + parse_section "_preamble_" [] +;; + +let load_pattern() = + let where = Filename.dirname (Sys.argv.(0)) in + let name = Filename.concat where "make_wizard.pattern" in + let f = open_in name in + let p = parse_pattern f in + close_in f; + p +;; + +(**********************************************************************) +(* MAKEFILE GENERATOR *) +(**********************************************************************) + +let dollar_re = Str.regexp "\\$";; +let meta_re = Str.regexp "[\\\\\\\"]";; + +let mkquote s = + (* Quote "$" *) + Str.global_replace dollar_re "$$" s +;; + +let metaquote s = + (* Quote backslash and double quotes for META files *) + Str.global_replace meta_re "\\\\0" s +;; + +let makemake() = + let b = Buffer.create 1024 in + let sections = load_pattern() in + + let write section vars = + let sectlist = + try List.assoc section sections + with Not_found -> failwith ("Cannot find section: " ^ section) in + List.iter + (function + Sect_const s -> + Buffer.add_string b s + | Sect_var v -> + let s = + try List.assoc v vars + with Not_found -> failwith ("No such variable: " ^ v) in + Buffer.add_string b s + ) + sectlist + in + + let is_byte_exec execname = + try not (!(List.assoc execname !wiz_exec_native)) + with Not_found -> true + in + + let byte_execs = + List.map + fst + (List.filter + (fun (execname,_) -> is_byte_exec execname) + !wiz_exec_objects + ) + in + + let nat_execs = + List.map + fst + (List.filter + (fun (execname,_) -> not(is_byte_exec execname)) + !wiz_exec_objects + ) + in + + let byte_exec_modules = + remove_dups + (List.sort compare + (List.flatten + (List.map + (fun (_, l) -> !l) + (List.filter + (fun (execname, _) -> is_byte_exec execname) + !wiz_exec_objects + ) + ) + ) + ) + in + + let nat_exec_modules = + remove_dups + (List.sort compare + (List.flatten + (List.map + (fun (_, l) -> !l) + (List.filter + (fun (execname, _) -> not(is_byte_exec execname)) + !wiz_exec_objects + ) + ) + ) + ) + in + + let required_packages = + (* magically add "camlp4" if missing *) + if !wiz_enable_camlp4 then ( + ( if not (List.mem "camlp4" !wiz_required_packages) then + [ "camlp4" ] + else + [] + ) @ !wiz_camlp4_selected @ !wiz_required_packages + ) + else + !wiz_required_packages + in + + let variables = + [ "name", + mkquote !wiz_package_name; + "makefile_name", + mkquote !wiz_makefile_name; + "version", + mkquote(metaquote !wiz_package_version); + "description", + mkquote(metaquote !wiz_package_description); + "byte_objects", + String.concat " " (List.map + (fun m -> String.uncapitalize m ^ ".cmo") + !wiz_objects); + "nat_objects", + String.concat " " (List.map + (fun m -> String.uncapitalize m ^ ".cmx") + !wiz_objects); + "byte_executables", + String.concat " " byte_execs; + "byte_exec_objects", + String.concat " " (List.map + (fun m -> String.uncapitalize m ^ ".cmo") + byte_exec_modules); + "nat_executables", + String.concat " " nat_execs; + "nat_exec_objects", + String.concat " " (List.map + (fun m -> String.uncapitalize m ^ ".cmx") + nat_exec_modules); + "prereqs", + String.concat " " required_packages; + "ppopts", + if !wiz_enable_camlp4 then + "-syntax " ^ !wiz_camlp4_syntax ^ + (String.concat " " + (List.map + (fun opt -> " -ppopt " ^ mkquote(Filename.quote opt)) + (Fl_split.in_words_ws !wiz_camlp4_options) + )) + else + ""; + "mtopts", + if List.mem "threads" !wiz_required_packages then "-thread" else ""; + "default_target", + !wiz_make_default; + ] in + + write "intro" variables; + write "def_general" variables; + if !wiz_byte_enable then write "def_byte_archive" variables; + if !wiz_nat_enable then write "def_native_archive" variables; + write "def_byte_exec" variables; + write "def_nat_exec" variables; + write "def_props" variables; + write "def_tools" variables; + write "rules" variables; + write "default_target" variables; + write "suffix_rules" variables; + write "generate" variables; + List.iter + (fun (execname, modlist) -> + let switches = + if is_byte_exec execname then + "-bytecode-filter" + else + "-native-filter" in + let deptargets = + String.concat " " (List.map + (fun m -> + let m' = String.uncapitalize m in + m' ^ ".ml " ^ m' ^ ".mli") + !modlist) in + write "makemake_exec" ( [ "switches", switches; + "execname", execname; + "deptargets", deptargets ] @ variables ) + ) + !wiz_exec_objects; + write "byte" variables; + write "opt" variables; + if !wiz_byte_enable then write "byte_archive" variables; + if !wiz_nat_enable then write "native_archive" variables; + List.iter + (fun (execname, modlist) -> + if is_byte_exec execname then begin + let execobjs = + String.concat " " (List.map + (fun m -> String.uncapitalize m ^ ".cmo") + !modlist) in + write "byte_exec" ( ["execname", execname; + "execobjs", execobjs ] @ variables ) + end + ) + !wiz_exec_objects; + List.iter + (fun (execname, modlist) -> + if not (is_byte_exec execname) then begin + let execobjs = + String.concat " " (List.map + (fun m -> String.uncapitalize m ^ ".cmx") + !modlist) in + write "nat_exec" ( ["execname", execname; + "execobjs", execobjs ] @ variables ) + end + ) + !wiz_exec_objects; + write "clean" variables; + write "install" variables; + + if !wiz_local_makefile_name<> "" && + Sys.file_exists !wiz_local_makefile_name then + begin + write "local" variables; + let f = open_in !wiz_local_makefile_name in + try + while true do + let s = input_line f in + Buffer.add_string b s; + Buffer.add_char b '\n'; + done; + assert false + with + End_of_file -> + close_in f + end; + + Buffer.contents b +;; + +(**********************************************************************) +(* GUI *) +(**********************************************************************) + +let headline_font = "-*-helvetica-bold-r-normal-*-*-140-*-*-*-*-iso8859-1" ;; +let font = "-*-helvetica-medium-r-normal-*-*-120-*-*-*-*-iso8859-1" ;; + +(**********************************************************************) + +let top = ref Widget.default_toplevel;; +let topframe = ref Widget.dummy;; +let screens = ref [];; +let current_screen = ref 0;; + +let ( !! ) = fun x -> !(!x);; + +let add_screen func = + screens := !screens @ [ func ] +;; + +let add_headline frame text = + let s1 = Frame.create ~height:15 frame in + let w = Label.create ~text ~font:headline_font ~anchor:`W frame in + let s2 = Frame.create ~height:10 frame in + pack [ s1 ]; + pack ~anchor:`W [ w ]; + pack [ s2 ] +;; + +let add_para frame text = + let s1 = Frame.create ~height:5 frame in + let w = Message.create ~padx:0 ~text ~font ~anchor:`W ~width:(pixels (`Pt 400.0)) frame in + let s2 = Frame.create ~height:5 frame in + pack [ s1 ]; + pack ~anchor:`W [ w ]; + pack [ s2 ] +;; + + +let dialog ~parent ~title ~message ~buttons ?(default = (-1)) () = + (* Like Dialog.create, but our own style. *) + let popup = Toplevel.create parent in + Wm.title_set popup title; + Wm.transient_set popup ~master:(Winfo.toplevel parent); + add_headline popup title; + add_para popup message; + let f_buttons = Frame.create popup in + let n = ref 0 in + let r = ref (-1) in + List.iter + (fun text -> + let k = !n in + let b = + Button.create ~font ~text ~command:(fun () -> r := k; destroy popup) + f_buttons in + (* --- Default buttons not yet supported because of deficiency in + * labltk: + if k = default then Button.configure ~default:`Active b; + *) + pack ~side:`Left [b]; + incr n; + ) + buttons; + pack [f_buttons]; + Grab.set popup; + Tkwait.window popup; + !r +;; + + +let ask_and_save frame = + let reply = + dialog ~parent:frame ~title:"Save .make-wizard?" + ~message:"Do you want to save the current state in the file .make-wizard?" + ~buttons:["Yes"; "No"; "Cancel"] + ~default:0 + () + in + if reply = 0 then save(); + reply < 2 +;; + + +let string_tv ?(onchange = fun () -> ()) frame v = + let textvariable = Textvariable.create ~on:frame () in + Textvariable.set textvariable !v; + let rec set_handle() = + Textvariable.handle textvariable + ~callback:(fun () -> + v := Textvariable.get textvariable; + onchange(); + set_handle()); + in + set_handle(); + textvariable +;; + + +let bool_tv ?(onchange = fun () -> ()) frame v = + let textvariable = Textvariable.create ~on:frame () in + Textvariable.set textvariable (if !v then "1" else "0"); + let rec set_handle() = + Textvariable.handle textvariable + ~callback:(fun () -> + v := Textvariable.get textvariable = "1"; + onchange(); + set_handle()); + in + set_handle(); + textvariable +;; + + +let label_box frame box = + let sub = Frame.create frame in + let row = ref 0 in + List.iter + (fun (l, v) -> + let label = Label.create ~font ~text:l ~anchor:`E sub in + let textvariable = string_tv frame v in + let var = Entry.create ~font ~textvariable ~width:40 sub in + grid ~row:!row ~column:0 ~sticky:"e" [ label ]; + grid ~row:!row ~column:1 ~sticky:"w" [ var ]; + incr row; + ) + box; + pack ~anchor:`W [ sub ] +;; + + +let scrolled_listbox ?(click = fun _ _ -> ()) ?(context = fun _ _ -> ()) + ?(separator = true) ?(height = 8) frame = + let f = Frame.create frame in + let lb = Listbox.create ~selectmode:`Multiple ~width:20 ~height + ~exportselection:false f in + let sb = Scrollbar.create ~orient:`Vertical + ~command:(Listbox.yview lb) + f in + Listbox.configure ~yscrollcommand:(Scrollbar.set sb) ~font lb; + let sep = Frame.create ~width:30 f in + pack ~side:`Left [ lb ]; + pack ~side:`Left ~fill:`Y [ sb ]; + if separator then pack ~side:`Left [ sep ]; + + bind ~events:[ `ButtonPressDetail 1 ] ~fields:[ `MouseY ] + ~action:(fun einfo -> + let `Num row = Listbox.nearest lb ~y:(einfo.Tk.ev_MouseY) in + Timer.set ~ms:0 ~callback:(fun () -> click lb row) + ) + lb; + bind ~events:[ `ButtonPressDetail 3 ] ~fields:[ `MouseY ] + ~action:(fun einfo -> + let `Num row = Listbox.nearest lb ~y:(einfo.Tk.ev_MouseY) in + Timer.set ~ms:0 ~callback:(fun () -> context lb row) + ) + lb; + + (f, lb) +;; + + +let listbox_select lb selection = + Listbox.selection_clear lb ~first:(`Num 0) ~last:`End; + for i = 0 to Listbox.size lb do + let s = Listbox.get lb (`Num i) in + if List.mem s selection then + Listbox.selection_set lb ~first:(`Num i) ~last:(`Num i) + done +;; + + +let listbox_get_selection lb = + List.map + (fun index -> Listbox.get lb ~index) + (Listbox.curselection lb) +;; + + +let indented_cond_frame frame enablers = + (* Returns a subframe of [frame] that is only mapped if the boolean + * variable [!enable] is true. [enable_text] is the text for the + * checkbox that toggles [!enable]. + *) + let onchange_enable = ref (fun () -> ()) in + + List.iter + (fun (enable, enable_text) -> + let enable_tv = bool_tv + ~onchange:(fun () -> !onchange_enable()) + frame enable in + let cb = Checkbutton.create + ~font ~text:enable_text ~variable:enable_tv frame in + pack ~anchor:`W [cb]; + ) + enablers; + + let is_enabled() = + let p = ref false in + List.iter (fun (enable, _) -> p := !p || !enable) enablers; + !p + in + + let frame' = Frame.create frame in + let indent = Frame.create ~width:30 frame' in + let frame'' = Frame.create frame' in + pack ~anchor:`W [frame']; + + let frame''_is_packed = ref false in + let frame''_pack b = + if b <> !frame''_is_packed then begin + if b then + pack ~side:`Left [indent; frame''] + else + Pack.forget [ frame'' ]; + frame''_is_packed := b + end + in + frame''_pack (is_enabled()); + onchange_enable := (fun () -> frame''_pack (is_enabled())); + frame'' +;; + + +let double_listbox frame available objects scan = + let boxes = Frame.create frame in + let (f_left,lb_left) = scrolled_listbox boxes in + let (f_right,lb_right) = scrolled_listbox ~separator:false boxes in + let f_buttons = Frame.create boxes in + let b_add = Button.create ~font ~text:"Add >>" f_buttons in + let b_del = Button.create ~font ~text:"<< Del" f_buttons in + let b_up = Button.create ~font ~text:"Up ^" f_buttons in + let b_down= Button.create ~font ~text:"Down v" f_buttons in + let b_scan= Button.create ~font ~text:"Rescan" f_buttons in + let f_sep = Frame.create ~width:30 boxes in + pack ~fill:`X [ b_add; b_del; b_up; b_down; b_scan ]; + pack ~side:`Left [ coe f_left; coe f_buttons; coe f_sep; coe f_right ]; + pack [ boxes ]; + + let update() = + let still_available = (* available - objects *) + List.filter (fun m -> not (List.mem m !!objects)) !!available in + Listbox.delete lb_left ~first:(`Num 0) ~last:`End; + Listbox.insert lb_left ~index:`End ~texts:still_available; + Listbox.delete lb_right ~first:(`Num 0) ~last:`End; + Listbox.insert lb_right ~index:`End ~texts:!!objects; + in + + let rescan() = + !available := scan(); + update() + in + + let add() = + if Listbox.curselection lb_left = [] then begin + let popup = Toplevel.create frame in + Wm.title_set popup "Add File"; + Wm.transient_set popup ~master:(Winfo.toplevel frame); + add_headline popup "Add File"; + add_para popup "Enter the name of the module to add. Note that you can also select the modules in the left box and press 'Add' to quickly move the modules to the right box."; + + let modname = ref "" in + label_box popup [ "Name of new module: ", modname ]; + + let p_buttons = Frame.create popup in + let b_ok = Button.create ~font ~text:"OK" + ~command:(fun () -> + if !modname <> "" then + !objects := !!objects @ [ !modname ]; + update(); + destroy popup) p_buttons in + let b_cancel = Button.create ~font ~text:"Cancel" + ~command:(fun () -> destroy popup) p_buttons in + pack ~side:`Left [b_ok; b_cancel]; + + add_para popup ""; + + pack [p_buttons]; + end + else begin + let items = + List.map + (fun index -> Listbox.get lb_left ~index) + (Listbox.curselection lb_left) + in + !objects := !!objects @ items; + update() + end + in + + let del() = + if Listbox.curselection lb_right = [] then begin + ignore + (dialog + ~parent:!top + ~title:"Nothing selected" + ~message:"Please select the modules you want to delete in the right box!" + ~buttons:[ "OK" ] + ~default:0 + ()) + end + else begin + let items = + List.map + (fun index -> Listbox.get lb_right ~index) + (Listbox.curselection lb_right) + in + !objects := List.filter (fun m -> not (List.mem m items)) !!objects; + update() + end + in + + let move_dlg() = + ignore + (dialog + ~parent:!top + ~title:"Bad Selection" + ~message:"Please select the (single) module you want to move in the right box!" + ~buttons:[ "OK" ] + ~default:0 + ()) + in + + let move g () = + if List.length (Listbox.curselection lb_right) <> 1 then + move_dlg() + else begin + let index = List.hd (Listbox.curselection lb_right) in + let `Num n = index in + let n' = g n in + if n' >= 0 && n' < List.length !!objects then begin + let item = Listbox.get lb_right ~index:(index :> Tk.listbox_index) in + !objects := delete_at n !!objects; + !objects := insert_at n' item !!objects; + update(); + Listbox.selection_set lb_right ~first:(`Num n') ~last:(`Num n'); + end + end + in + + if !!available = [] then rescan() else update(); + Button.configure ~command:add b_add; + Button.configure ~command:del b_del; + Button.configure ~command:(move pred) b_up; + Button.configure ~command:(move succ) b_down; + Button.configure ~command:rescan b_scan; + + (* Returns the [update] function *) + update +;; + + +let redraw() = + destroy !topframe; + let f = Frame.create !top in + let f1 = Frame.create ~width:5 f in + let f2 = Frame.create f in + let f3 = Frame.create ~width:5 f in + pack ~expand:true ~fill:`Y [f]; + pack ~side:`Left [f1]; + pack ~side:`Left ~fill:`Y [f2]; + pack ~side:`Left [f3]; + let func = List.nth !screens !current_screen in + topframe := coe f; + func f2 +;; + + +let footer frame = + let box = Frame.create frame in + pack ~side:`Bottom ~fill:`X [box]; + let sep1 = Frame.create ~height:15 box in + let b = Frame.create ~height:1 ~background:`Black box in + let sep2 = Frame.create ~height:15 box in + pack [ sep1 ]; + pack ~fill:`X ~expand:true [b]; + pack [ sep2 ]; + + let f = Frame.create box in + let m1 = Frame.create f in + pack ~fill:`X ~expand:true ~side:`Left [ m1 ]; + let prev_b = + Button.create ~font ~text:"Previous" ~state:`Disabled + ~command:(fun () -> decr current_screen; redraw()) m1 in + pack ~side:`Left [prev_b]; + if !current_screen > 0 then + Button.configure ~state:`Normal prev_b; + let m2 = Frame.create f in + let k = ref 0 in + List.iter + (fun scr -> + let k' = !k in + let b = + Button.create ~font ~text:(string_of_int (!k+1)) + ~command:(fun () -> current_screen := k'; redraw()) m2 in + if k' = !current_screen then + Button.configure + ~background:`Blue ~activebackground:`Blue ~foreground:`White b; + pack ~side:`Left [b]; + incr k + ) + !screens; + pack ~side:`Left [m2]; + let m3 = Frame.create f in + pack ~fill:`X ~expand:true ~side:`Left [ m3 ]; + let next_b = + Button.create ~font ~text:"Next" ~state:`Disabled + ~command:(fun () -> incr current_screen; redraw()) m3 in + pack ~side:`Right [next_b]; + if !current_screen < List.length !screens - 1 then + Button.configure ~state:`Normal next_b; + pack ~fill:`X [ f ] +;; + + +(**********************************************************************) + +let first_time = ref true;; + +let intro_screen frame = + add_headline frame "The Makefile and META wizard"; + add_para frame "This wizard helps you creating Makefiles and META \ +files for simple projects. It assumes that all your source files \ +reside in a single directory, and that all source files are OCaml \ +files (no support for mixed OCaml/C projects). ocamllex, ocamlyacc, \ +and camlp4 are supported."; + add_para frame "The wizard generates a Makefile, and the Makefile \ +produces the META file. The Makefile is not perfect, and is not the ideal \ +choice for everybody, but it is a starting point for your project. \ +You can later fine-tune the contents of the Makefile by adding your own rules, \ +and by overriding the definitions. The Makefile is commented, and not \ +overly complicated."; + add_para frame "The settings you enter here can be stored in a file \ +containing the state of the wizard. This file is called .make-wizard. \ +It is recommended to use this feature to save the state between the \ +wizard sessions."; + (* "" *) + + footer frame; + update(); + + if !first_time && Sys.file_exists ".make-wizard" then begin + match dialog ~parent:frame ~title:"Load .make-wizard?" + ~message:"Do you want to load the file .make-wizard, and continue your last session?" + ~buttons:[ "Yes, please load the file"; "No, start with empty fields" ] + ~default:0 + () + with + 0 -> load() + | _ -> () + end; + first_time := false; + +;; + + +add_screen intro_screen;; + +(**********************************************************************) + +let general_screen frame = + add_headline frame "General"; + add_para frame "Please enter the name of the package, the version number, \ +and the description first. The name must be a single, alphanumeric string \ +(including _ and -). The version is an arbitrary string, like the description. \ +All fields are mandatory."; (* "" *) + + label_box frame + [ "Package name: ", wiz_package_name; + "Package version: ", wiz_package_version; + "Package description: ", wiz_package_description ]; + footer frame +;; + +add_screen general_screen;; + +(**********************************************************************) + +let pkginfo lb row = (* when the user right-clicks at a listbox row *) + let pkg = Listbox.get lb (`Num row) in + let version = + try Findlib.package_property [] pkg "version" with Not_found -> "N/A" in + let description = + try Findlib.package_property [] pkg "description" with Not_found -> "N/A" + in + let popup = Toplevel.create !top in + Wm.transient_set popup ~master:(Winfo.toplevel !top); + let f = Frame.create popup in + let title = "About " ^ pkg ^ " (" ^ version ^ ")" in + add_headline f title; + Wm.title_set popup title; + add_para f ("Description: " ^ description); + add_para f "Modules:"; + let click sublb _ = + Listbox.selection_clear sublb ~first:(`Num 0) ~last:`End in + let (f_sublb, sublb) = scrolled_listbox ~click f in + let modules = + try + Fl_split.in_words + (Findlib.package_property [] pkg "browse_interfaces") + with + Not_found -> + let dir = Findlib.package_directory pkg in + let files = Array.to_list(Sys.readdir dir) in + List.map + (fun name -> + String.capitalize (Filename.chop_suffix name ".cmi")) + (List.filter + (fun name -> + Filename.check_suffix name ".cmi") + files + ) + in + Listbox.insert sublb ~index:`End ~texts:modules; + pack ~anchor:`W [ f_sublb ]; + pack ~anchor:`W [ f ]; + let close = Button.create ~text:"Close" ~font + ~command:(fun () -> destroy popup) f_sublb in + pack ~anchor:`Nw ~fill:`X [close] +;; + +(**********************************************************************) + +let preprocessor_scan_extensions() = + (* Find out all packages with a "preprocessor" predicate *) + let packages = Fl_package_base.list_packages() in + let plist = + List.filter + (fun pkg -> + try + let _ = + Findlib.package_property [ "preprocessor"; "syntax" ] pkg "archive" + in true + with + Not_found -> false + ) + packages in + (* Add all selected extensions, if they do not occur yet: *) + let plist' = + List.filter + (fun pkg -> + not (List.mem pkg plist) + ) + !wiz_camlp4_selected in + List.sort Pervasives.compare (plist @ plist') +;; + + +let preprocessor_screen frame = + add_headline frame "Preprocessing"; + add_para frame "Here you can specify whether your source files are \ +preprocessed by camlp4. Simply skip this page if you do not want to \ +invoke a preprocessor, or if you don't know what this means."; (* "" *) + + let frame'' = indented_cond_frame frame + [ wiz_enable_camlp4, "Enable camlp4" ] in + + let tv = string_tv frame'' wiz_camlp4_syntax in + let rb_o = Radiobutton.create + ~font ~text:"Standard syntax" ~variable:tv ~value:"camlp4o" + frame'' in + let rb_r = Radiobutton.create + ~font ~text:"Revised syntax" ~variable:tv ~value:"camlp4r" + frame'' in + pack ~anchor:`W [rb_o; rb_r]; + + add_para frame'' "Use the following packaged syntax extensions (click the \ +right mouse button to find out more about a package):"; (* "" *) + + if !wiz_camlp4_extensions = [] then + wiz_camlp4_extensions := preprocessor_scan_extensions(); + + let click lb row = (* when the user clicks at a listbox row *) + wiz_camlp4_selected := listbox_get_selection lb; + in + + let (f_lb,lb) = scrolled_listbox ~click ~context:pkginfo frame'' in + Listbox.insert lb ~index:`End ~texts:!wiz_camlp4_extensions; + listbox_select lb !wiz_camlp4_selected; + pack ~anchor:`W [f_lb]; + + let rescan = Button.create ~text:"Rescan" ~font + ~command:(fun () -> + wiz_camlp4_extensions := preprocessor_scan_extensions(); + Listbox.delete lb ~first:(`Num 0) ~last:`End; + Listbox.insert lb ~index:`End ~texts:!wiz_camlp4_extensions; + listbox_select lb !wiz_camlp4_selected; + ) + f_lb in + let clear = Button.create ~text:"Clear" ~font + ~command:(fun () -> + wiz_camlp4_selected := []; + listbox_select lb []) + f_lb in + + pack ~anchor:`Nw ~fill:`X [ rescan; clear ]; + + add_para frame'' "Specify here further options to the camlp4 invocation. \ +For example, you can load camlp4 modules like pa_ifdef.cmo, and pass the -D \ +options to it."; (* "" *) + + label_box frame'' [ "Camlp4 options: ", wiz_camlp4_options ]; + + footer frame +;; + +add_screen preprocessor_screen;; + +(**********************************************************************) + +let prerequisites_scan_packages() = + (* Find out all packages *) + List.sort Pervasives.compare (Fl_package_base.list_packages()) +;; + + +let prerequisites_screen frame = + add_headline frame "Prerequisites"; + add_para frame "If your modules use packages, you can specify these \ +prerequisites here. It is sufficient to select the packages on which \ +your modules depend directly. Indirect dependencies can be resolved \ +by findlib automatically. Click the right mouse button to find out \ +more about a package."; (* "" *) + + if !wiz_all_packages = [] then + wiz_all_packages := prerequisites_scan_packages(); + + let click lb row = (* when the user clicks at a listbox row *) + wiz_required_packages := listbox_get_selection lb; + in + + let (f_lb,lb) = scrolled_listbox ~height:18 ~click ~context:pkginfo frame in + Listbox.insert lb ~index:`End ~texts:!wiz_all_packages; + listbox_select lb !wiz_required_packages; + pack ~anchor:`W [f_lb]; + + let rescan = Button.create ~text:"Rescan" ~font + ~command:(fun () -> + wiz_all_packages := prerequisites_scan_packages(); + Listbox.delete lb ~first:(`Num 0) ~last:`End; + Listbox.insert lb ~index:`End ~texts:!wiz_all_packages; + listbox_select lb !wiz_required_packages; + ) + f_lb in + let clear = Button.create ~text:"Clear" ~font + ~command:(fun () -> + wiz_required_packages := []; + listbox_select lb []) + f_lb in + + pack ~anchor:`Nw ~fill:`X [ rescan; clear ]; + + footer frame +;; + +add_screen prerequisites_screen;; + +(**********************************************************************) + +let buildlib_scan_modules() = + let files = Array.to_list(Sys.readdir ".") in + let suffixes = Fl_split.in_words_ws !wiz_source_suffixes in + let files' = + List.filter + (fun f -> + List.exists (Filename.check_suffix f) suffixes + ) + files in + let files'' = + List.map + (fun f -> + String.capitalize (Filename.chop_extension f) + ) + files' in + remove_dups (List.sort Pervasives.compare files'') +;; + + +let buildlib_screen frame = + add_headline frame "Build Library"; + add_para frame "The next question is how to build the library, i.e. the \ +cma or cmxa archive. It is recommended to create such an archive even if \ +the real target of the build process is an executable, because you can load \ +it into the toploop at once. However, make sure that you do not put the \ +main program of the executable into the archive, as it is usually stripped \ +off from the executable, and nothing would happen when you start it."; +(* + add_para frame "You can select whether you want to create only a bytecode \ +archive, a native archive, or both. In the latter case, the simplest way \ +is to begin with the bytecode archive, and to copy your specification to \ +the native box by pressing the button \"Like bytecode\"."; + add_para frame "If you do not want to create an archive at all, \ +skip this page."; +*) +(* "" *) + + let frame' = indented_cond_frame frame + [ wiz_byte_enable, "Enable bytecode archive"; + wiz_nat_enable, "Enable native archive"; ] in + add_para frame' "Move the available modules to the right-hand box in the required order."; + + let update = + double_listbox frame' (ref wiz_available) (ref wiz_objects) buildlib_scan_modules in + + add_para frame "By default, only the suffixes .ml, .mli, .mll, and .mly are used to recognize source code files. You can add here additional suffixes (this requires that you extend the Makefile by your own rules)."; + + label_box frame [ "Source code suffixes: ", wiz_source_suffixes ]; + + footer frame +;; + +add_screen buildlib_screen;; + +(**********************************************************************) + +let enter_name parent followup = + let popup = Toplevel.create parent in + let title = "New Executable" in + Wm.transient_set popup ~master:(Winfo.toplevel parent); + Wm.title_set popup title; + let frame = Frame.create popup in + pack [frame]; + add_headline frame title; + add_para frame "Of course, the new executable must have a name."; + let name = ref "" in + label_box frame [ "Name: ", name ]; + pack [ Frame.create ~height:10 frame ]; + let buttons = Frame.create frame in + let ok_b = Button.create ~font ~text:"OK" + ~command:(fun () -> destroy popup; followup !name) buttons in + let cancel_b = Button.create ~font ~text:"Cancel" + ~command:(fun () -> destroy popup) buttons in + pack ~side:`Left [ ok_b; cancel_b ]; + pack [buttons] +;; + + +let buildexec_screen frame = + add_headline frame "Build Executables"; + add_para frame "You can specify the executables to build in the following \ +way. Press \"New\" and enter the name of the excutable, then add the modules \ +to link in the box that appears. The cma/cmxa archive from the previous \ +screen is linked anyway, so its modules cannot be selected again."; + add_para frame "Leave the list of executables empty if you do not want to \ +build any."; + (* "" *) + + let update_listbox = ref (fun () -> ()) in + let show = ref (fun _ -> ()) in + let hide = ref (fun _ -> ()) in + + let click lb row = + let name = Listbox.get lb ~index:(`Num row) in + !show name + in + + let newexec() = + enter_name + frame + (fun name -> + (* This function is called after the user pressed "OK" *) + if List.mem name !wiz_executables then begin + (* It is not allowed to enter the same name twice *) + ignore( + dialog ~parent:frame ~title:"Already exists" + ~message:"This name already exists!" ~buttons:["OK"] ()) + end + else begin + wiz_executables := + List.sort Pervasives.compare (name :: !wiz_executables); + wiz_exec_objects := (name, ref []) :: !wiz_exec_objects; + wiz_exec_native := (name, ref false) :: !wiz_exec_native; + !update_listbox(); + !show name + end + ) + in + + let remexec lb () = + let sel = listbox_get_selection lb in + if sel = [] then begin + ignore( + dialog ~parent:frame ~title:"Nothing selected" + ~message:"Select the executable to remove first!" ~buttons:["OK"] ()) + end + else begin + wiz_executables := + List.filter (fun n -> not (List.mem n sel)) !wiz_executables; + wiz_exec_objects := + List.filter (fun (n,_) -> not (List.mem n sel)) !wiz_exec_objects; + wiz_exec_native := + List.filter (fun (n,_) -> not (List.mem n sel)) !wiz_exec_native; + !update_listbox(); + !hide() + end + in + + let (f_lb,lb) = scrolled_listbox ~click ~height:3 frame in + Listbox.configure ~selectmode:`Single lb; + Listbox.insert lb ~index:`End ~texts:!wiz_executables; + pack ~anchor:`W [f_lb]; + + let new_b = + Button.create ~font ~text:"New" ~command:newexec f_lb in + let remove_b = + Button.create ~font ~text:"Remove" ~command:(remexec lb) f_lb in + + pack ~anchor:`Nw ~fill:`X [ new_b; remove_b ]; + + let f1 = Frame.create frame in + pack [f1]; + let frame' = Frame.create f1 in + let frame'_packed = ref false in + let modbox_available = ref (ref []) in + let modbox_objects = ref (ref []) in + let modbox_scan() = + let mlist = buildlib_scan_modules() in + List.filter + (fun m -> not (List.mem m !wiz_objects)) mlist + in + add_para frame' "Move the available modules to the right-hand box in the required order."; + let update_modbox = + double_listbox frame' modbox_available modbox_objects modbox_scan in + + add_para frame' "Select the type of the executable:"; + let radio = Frame.create frame' in + let type_ref = ref false in + let type_ref_ref = ref type_ref in + let type_tv = bool_tv + ~onchange:(fun () -> !type_ref_ref := !type_ref) + frame' type_ref in + let byte_r = Radiobutton.create ~font ~text:"Bytecode executable" + ~variable:type_tv ~value:"0" radio in + let nat_r = Radiobutton.create ~font ~text:"Native executable" + ~variable:type_tv ~value:"1" radio in + pack ~side:`Left [byte_r; nat_r ]; + pack ~anchor:`W [radio]; + let update_radio() = + Textvariable.set type_tv (if !!type_ref_ref then "1" else "0") + in + + footer frame; + + update_listbox := (fun () -> + Listbox.delete lb ~first:(`Num 0) ~last:`End; + Listbox.insert lb ~index:`End ~texts:!wiz_executables; + ); + show := (fun name -> + let k = find_pos name !wiz_executables in + Listbox.selection_clear lb ~first:( `Num 0 ) ~last:`End; + Listbox.selection_set lb ~first:(`Num k) ~last:(`Num k); + if not !frame'_packed then ( + pack [frame']; + frame'_packed := true; + ); + modbox_objects := List.assoc name !wiz_exec_objects; + type_ref_ref := List.assoc name !wiz_exec_native; + update_modbox(); + update_radio() + ); + hide := (fun () -> + if !frame'_packed then ( + Pack.forget [frame']; + frame'_packed := false; + ); + ) +;; + +add_screen buildexec_screen;; + +(**********************************************************************) + +let generate_screen frame = + add_headline frame "Generate Makefile"; + add_para frame "Finally, the Makefile can be generated from your inputs. \ +You can set the name of the Makefile to a non-standard name. Furthermore, \ +you can specify a second file that will be appended to the generated Makefile, \ +this is useful to extend the Makefile rules by your own additions."; + (* "" *) + + label_box frame [ "Name of Makefile: ", wiz_makefile_name; + "Local extensions in: ", wiz_local_makefile_name ; + "Default target of 'make': ", wiz_make_default; + ]; + + add_para frame ""; + + let show_b = + Button.create ~font ~text:"Show Makefile" + ~command:(fun () -> + let maketext = makemake() in + let popup = Toplevel.create frame in + Wm.title_set popup "Generated Makefile"; + add_headline popup "Generated Makefile"; + let t = Text.create ~width:80 ~height:25 popup in + pack [t]; + Text.insert ~index:(`End,[]) ~text:maketext t; + ) + frame in + let save_b = + Button.create ~font ~text:"Save Makefile" + ~command:(fun () -> + let maketext = makemake() in + let cont = + not (Sys.file_exists !wiz_makefile_name) || ( + dialog ~parent:frame ~title:"File already exists" + ~message:("The file " ^ !wiz_makefile_name ^ + " already exists. Overwrite?") + ~buttons:[ "OK"; "Cancel" ] () = 0) in + if cont then begin + let f = open_out !wiz_makefile_name in + output_string f maketext; + close_out f + end + ) + frame in + + pack [show_b; save_b]; + + add_headline frame "Quit"; + + add_para frame "The following button quits the wizard. You are asked whether you want to save the state first."; + + let quit_b = + Button.create ~font ~text:"Finish & Quit" + ~command:(fun () -> + if ask_and_save frame then destroy !top) + frame in + + + + pack [show_b; quit_b]; + + footer frame +;; + +add_screen generate_screen;; + + +(**********************************************************************) + +Findlib.init(); +top := openTk(); +(* current_screen := 5; *) +Wm.title_set !top "findlib/make-wizard"; +Wm.protocol_set !top ~name:"WM_DELETE_WINDOW" + ~command:(fun () -> if ask_and_save !top then destroy !top); +Toplevel.configure ~width:(pixels(`Pt 450.0)) + ~height:(pixels (`Pt 650.0)) (Winfo.toplevel !top); +Pack.propagate_set !top false; +topframe := coe(Frame.create !top); +redraw(); +mainLoop();; + + +(* ====================================================================== + * History: + * + * $Log: make_wizard.ml,v $ + * Revision 1.3 2002/09/22 20:12:35 gerd + * Renamed modules (prefix fl_) + * + * Revision 1.2 2002/07/29 19:52:23 gerd + * Fixes for OCaml 3.05 + * + * Revision 1.1 2002/05/26 14:09:07 gerd + * Renaming + * + * Revision 1.1 2002/05/05 20:40:26 gerd + * Initial revision + * + * + *) diff --git a/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.pattern b/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.pattern new file mode 100644 index 0000000..90116e9 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib-toolbox/make_wizard.pattern @@ -0,0 +1,494 @@ +## $Id$ +## ---------------------------------------------------------------------- +## + +## This is the pattern for the Makefile. It consists of several sections, +## every section begins with [name] on a single line, and ends where the +## next section starts. Inside the sections, variables are written as +## [name], too. +## Comments that must not be copied to the output file begin with two +## hash marks. + +[intro] +# ---------------------------------------------------------------------- +# How to build the package [name]: +# ---------------------------------------------------------------------- +# +# make: Same as "make all" +# make all: Normally "make byte", but can also be set to "make opt" +# make byte: Makes the bytecode archive and the bytecode executables +# make opt: Makes the native archive and the native executable +# make install: Install all installable files as package +# make uninstall: Uninstall the package +# make clean: Delete all files that can be remade +# +# The usual order of invocation is: +# - make byte +# - (optionally) make opt +# - make install +# - make clean +# +# You may want to give the -s option if you do not want to see the details +# of the build process (e.g. make -s all). +# +# ---------------------------------------------------------------------- +# Important for developers +# ---------------------------------------------------------------------- +# +# This Makefile writes a copy of itself with appended dependencies. +# The copy is usually stored in the file .make-wizard.[makefile_name]. +# If you want to invoke "make" for targets where the dependencies are +# involved, you have to specify -f .make-wizard.[makefile_name] on +# the command line, e.g. +# +# make -f .make-wizard.[makefile_name] sample.cmo +# +# Otherwise, the dependencies are ignored, and you get errors that are +# hard to explain. +# +# If you want to modify this Makefile, it is a good idea to put the +# modifications into a second file, and to enable the local Makefile +# extension in the wizard. This effects that the modifications are appended +# to this Makefile, so you can add rules and override variables without +# coming into conflict with the wizard. + +[def_general] +# ---------------------------------------------------------------------- +# Definitions +# ---------------------------------------------------------------------- + +NAME = [name] +# The name of the package. + +MFNAME = [makefile_name] +# The name of this Makefile. (You must change this definition if you rename +# the Makefile!) + +MF2NAME = .make-wizard.$(MFNAME) +# The name of the generated Makefile (a copy of this Makefile plus the +# dependencies) + +TEMPNAME = .make-wizard.temps +# The name of a file containing the names of temporary files + +VERSION = [version] +# The version of this package + +DESCRIPTION = [description] +# The description of this package + +GENERATOR_EXTS = .mll .mly +# These suffixes indicate that a generator must be called for them + +MAKE_META = _meta +# Make the META file by this rule. (An empty definition turns META generation +# off.) + +INSTALL = _findlib_install +# Which rule to use for installation + +UNINSTALL = _findlib_uninstall +# Which rule to use for deinstallation + +MAKEMAKE_HOOK = +# Set this to the name of a rule to add your own definitions to $(MF2NAME) + + +## The def_byte_archive section is only included if the byte archive is +## enabled: + +[def_byte_archive] +BYTE_ARCHIVE = $(NAME).cma +# The name of the resulting bytecode archive. + +BYTE_OBJECTS = [byte_objects] +# The cmo objects that are linked together, and are put into the byte archive. + +BYTE_FILES = $(BYTE_OBJECTS) $(BYTE_OBJECTS:.cmo=.cmi) $(BYTE_ARCHIVE) +# The files that are generated in order to make the byte archive. Note +# that .ml and .mli files are missing that are generated from +# .mly and .mll files. + +BYTE_INST = $(BYTE_OBJECTS:cmo=cmi) $(BYTE_OBJECTS:.cmo=.mli) $(BYTE_ARCHIVE) +# The files that will be installed after the byte archive is made. Not +# every file exists. + + +## The def_native_archive section is only included if the native archive is +## enabled: + +[def_native_archive] +NAT_ARCHIVE = $(NAME).cmxa +# The name of the resulting native archive. + +NAT_OBJECTS = [nat_objects] +# The cmx objects that are linked together, and are put into the native archive. + +NAT_FILES = $(NAT_OBJECTS) $(NAT_OBJECTS:.cmx=.o) $(NAT_OBJECTS:.cmo=.cmi) \ + $(NAT_ARCHIVE) $(NAT_ARCHIVE:.cmxa=.a) +# The files that are generated in order to make the native archive. Note +# that .ml and .mli files are missing that are generated from +# .mly and .mll files. + +NAT_INST = $(NAT_OBJECTS:.cmo=.cmi) $(NAT_OBJECTS:.cmo=.mli) $(NAT_ARCHIVE) \ + $(NAT_ARCHIVE:.cmxa=.a) +# The files that will be installed after the native archive is made. Not +# every file exists. + + +[def_byte_exec] +BYTE_EXEC_TARGETS = [byte_executables] +# The list of bytecode executables. + +BYTE_EXEC_OBJECTS = [byte_exec_objects] +# The list of cmo modules that are linked into bytecode executables + +BYTE_EXEC_FILES = $(BYTE_EXEC_OBJECTS) $(BYTE_EXEC_OBJECTS:.cmo=.cmi) \ + $(BYTE_EXEC_TARGETS) +# The list of files that are generated in order to make the bytecode +# executables. Note that .ml and .mli files are missing that are generated +# from .mly and .mll files. + +BYTE_EXEC_INST = $(BYTE_EXEC_TARGETS) +# The files to install as bytecode executables. + + +[def_nat_exec] +NAT_EXEC_TARGETS = [nat_executables] +# The list of native executables. + +NAT_EXEC_OBJECTS = [nat_exec_objects] +# The list of cmx modules that are linked into native executables + +NAT_EXEC_FILES = $(NAT_EXEC_OBJECTS) $(NAT_EXEC_OBJECTS:.cmx=.cmi) \ + $(NAT_EXEC_OBJECTS:.cmx=.o) $(NAT_EXEC_TARGETS) +# The list of files that are generated in order to make the native +# executables. Note that .ml and .mli files are missing that are generated +# from .mly and .mll files. + +NAT_EXEC_INST = $(NAT_EXEC_TARGETS) +# The files to install as native executables. + + +[def_props] +PREREQUISITES = [prereqs] +# The required packages. + +PPOPTS = [ppopts] +# Preprocessor options. + +MTOPTS = [mtopts] +# Multi-threading options + +INCOPTS = +# -I options (currently unused, but this may change in the future) + +OTHER_INST = META +# Files to install that are not mentioned in the other XXX_INST variables + +#TASKBYTELINKOPTS = -custom +# Uncomment this line to create stand-alone executables + +[def_tools] +# Tools and tasks: "Tools" are the commands to call, and "tasks" are the tools +# to use for certain situations. + +OCAMLFIND = ocamlfind +OCAMLLEX = ocamllex +OCAMLYACC = ocamlyacc +OCAMLDEP = $(OCAMLFIND) ocamldep +OCAMLC = $(OCAMLFIND) ocamlc +OCAMLCP = $(OCAMLFIND) ocamlcp +OCAMLOPT = $(OCAMLFIND) ocamlopt +# +# These are the tools. + +TASKLEX = $(OCAMLLEX) $(TASKLEXOPTS) +TASKYACC = $(OCAMLYACC) $(TASKYACCOPTS) +TASKDEP = $(OCAMLDEP) $(INCOPTS) $(PPOPTS) -package "$(PREREQUISITES)" $(TASKDEPOPTS) +TASKCI = $(OCAMLC) $(INCOPTS) $(PPOPTS) -package "$(PREREQUISITES)" -c $(TASKCIOPTS) +TASKBYTECO = $(OCAMLC) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -c -g $(TASKBYTECOOPTS) +TASKBYTELINK = $(OCAMLC) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -linkpkg $(TASKBYTELINKOPTS) +TASKBYTEAR = $(OCAMLC) -a $(TASKBYTEAROPTS) +TASKNATCO = $(OCAMLOPT) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -c $(TASKNATCOOPTS) +TASKNATLINK = $(OCAMLOPT) $(INCOPTS) $(PPOPTS) $(MTOPTS) -package "$(PREREQUISITES)" -linkpkg $(TASKNATLINKOPTS) +TASKNATAR = $(OCAMLOPT) -a $(TASKNATAROPTS) +TASKINSTALL = $(OCAMLFIND) install $(NAME) $(TASKINSTALLOPTS) +TASKREMOVE = $(OCAMLFIND) remove $(NAME) $(TASKREMOVEOPTS) +# +# These are the tasks. The names mean the following: +# TASKLEX: Used to create a lexer +# TASKYACC: Used to create a parser +# TASKDEP: Used to analyze the dependencies +# TASKCI: Used to compile interface files +# TASKBYTECO, TASKNATCO: Used to compile implementation files +# TASKBYTELINK, TASKNATLINK: Used to create executables +# TASKBYTEAR, TASKNATAR: Used to create archives +# TASKINSTALL: Used to install the package +# TASKREMOVE: Used to remove the package +# INCOPTS: -I options +# PPOPTS: Options to specify the preprocessor +# MTOPTS: -thread (if necessary) +# NATONLY: -native (if necessary) +# For every task , there is a variable for task-specific options OPTS. + + +[rules] +# ---------------------------------------------------------------------- +# Rules +# ---------------------------------------------------------------------- + + +[default_target] +.PHONY: all +all: [default_target] + + +[suffix_rules] +# The suffix rules: They specify how to make a file ending in suffix X from +# a source file ending in suffix Y. For every suffix rule, there is a task +# defining what to do. + +.SUFFIXES: .ml .mli .cmo .cmx .cmi .mll .mly + +.mli.cmi: + @echo "" + $(TASKCI) $< + +.ml.cmo: + @echo "" + $(TASKBYTECO) $< + +.ml.cmx: + @echo "" + $(TASKNATCO) $< + +# The generator rules record the generated files: The "grep" checks whether +# the filename already occurs in $(TEMPNAME), and the "echo" appends the +# filename when missing. + +.mll.ml: + @echo "" + $(TASKLEX) $< + touch $(TEMPNAME) + grep -F -x -q -e "$@" $(TEMPNAME) || echo "$@" >>$(TEMPNAME) + +.mly.ml: + @echo "" + $(TASKYACC) $< + touch $(TEMPNAME) + grep -F -x -q -e "$@" $(TEMPNAME) || echo "$@" >>$(TEMPNAME) + +# The _dummy rule does nothing: + +_dummy: + : + +[generate] +# The following rule checks which lex and yacc targets exist, and calls +# MAKE recursively. + +.PHONY: _meta +_meta: + @echo "" + echo "name = \"$(NAME)\"" >META + echo "version = \"$(VERSION)\"" >>META + echo "description = \"$(DESCRIPTION)\"" >>META + echo "requires = \"$(PREREQUISITES)\"" >>META + test -z "$(BYTE_ARCHIVE)" || \ + echo "archive(byte) = \"$(BYTE_ARCHIVE)\"" >>META + test -z "$(NAT_ARCHIVE)" || \ + echo "archive(native) = \"$(NAT_ARCHIVE)\"" >>META + +.PHONY: _generator +_generator: $(MAKE_META) + @echo "" + targets=$$( \ + { \ + for obj in _dummy $(BYTE_OBJECTS) $(BYTE_EXEC_OBJECTS); do \ + test "_dummy" != "$$obj" || continue; \ + for ext in $(GENERATOR_EXTS); do \ + if [ -f "$${obj%.cmo}$$ext" ]; then \ + echo "$${obj%.cmo}.ml"; \ + fi; \ + done; \ + done && \ + for obj in _dummy $(NAT_OBJECTS) $(NAT_EXEC_OBJECTS); do \ + test "_dummy" != "$$obj" || continue; \ + for ext in $(GENERATOR_EXTS); do \ + if [ -f "$${obj%.cmx}$$ext" ]; then \ + echo "$${obj%.cmx}.ml"; \ + fi; \ + done; \ + done; \ + } | sort | uniq \ + ) && \ + { test -z "$$targets" || $(MAKE) -f $(MFNAME) $$targets; } + +# The following rule calls ocamldep for the right files, and creates +# a file that consists of the contents of this Makefile, and of the output +# of ocamldep. + +.PHONY: _makemake +_makemake: _generator + @echo "" + cat $(MFNAME) >$(MF2NAME) + test -z "$(MAKEMAKE_HOOK)" || $(MAKE) -f $(MFNAME) $(MAKEMAKE_HOOK) + echo "# ---------------------------------------- dependencies:" >>$(MF2NAME) + targets=$$( \ + { \ + nat=-native-filter && \ + byte=-bytecode-filter && \ + for obj in _dummy $(BYTE_OBJECTS); do \ + test "_dummy" != "$$obj" || continue; \ + echo "$${obj%.cmo}.ml"; \ + echo "$${obj%.cmo}.mli"; \ + nat=""; \ + done && \ + for obj in _dummy $(NAT_OBJECTS); do \ + test "_dummy" != "$$obj" || continue; \ + echo "$${obj%.cmx}.ml"; \ + echo "$${obj%.cmx}.mli"; \ + byte=""; \ + done; \ + echo "$$byte $$nat"; \ + } | sort | uniq \ + ) && \ + $(TASKDEP) $$targets >>$(MF2NAME) +## The following section is appended to _makemake for every executable: +[makemake_exec] + echo "# --- dependencies for [execname]:" >>$(MF2NAME) + $(TASKDEP) [switches] [deptargets] >>$(MF2NAME) +## Begin next section immediately to avoid empty lines: +[dummy] + +[byte] + + +.PHONY: byte +byte: _byte + +.PHONY: _byte +_byte: _makemake + @echo "" + if [ -n "$(BYTE_ARCHIVE)" ]; then \ + $(MAKE) -f $(MF2NAME) $(BYTE_ARCHIVE); \ + fi + if [ -n "$(BYTE_EXEC_TARGETS)" ]; then \ + $(MAKE) -f $(MF2NAME) $(BYTE_EXEC_TARGETS); \ + fi + @echo "" + + +[opt] +.PHONY: opt +opt: _opt + +.PHONY: _opt +_opt: _makemake + @echo "" + if [ -n "$(NAT_ARCHIVE)" ]; then \ + $(MAKE) -f $(MF2NAME) $(NAT_ARCHIVE); \ + fi + if [ -n "$(NAT_EXEC_TARGETS)" ]; then \ + $(MAKE) -f $(MF2NAME) $(NAT_EXEC_TARGETS); \ + fi + @echo "" + + +[byte_archive] +$(BYTE_ARCHIVE): $(BYTE_OBJECTS) + @echo "" + $(TASKBYTEAR) -o $(BYTE_ARCHIVE) $(BYTE_OBJECTS) + + +[native_archive] +$(NAT_ARCHIVE): $(NAT_OBJECTS) + @echo "" + $(TASKNATAR) -o $(NAT_ARCHIVE) $(NAT_OBJECTS) + + +## The following section is included for every bytecode executable again. + +[byte_exec] +[execname]: $(BYTE_ARCHIVE) [execobjs] + @echo "" + $(TASKBYTELINK) -o [execname] $(BYTE_ARCHIVE) [execobjs] + + +[nat_exec] +[execname]: $(NAT_ARCHIVE) [execobjs] + @echo "" + $(TASKNATLINK) -o [execname] $(NAT_ARCHIVE) [execobjs] + + +[clean] +.PHONY: clean +clean: + @echo "" + touch $(TEMPNAME) + rm -f $(BYTE_FILES) $(NAT_FILES) $(BYTE_EXEC_FILES) $(NAT_EXEC_FILES) + rm -f $(MF2NAME) + cat $(TEMPNAME) | xargs rm -f + rm -f $(TEMPNAME) + +.PHONY: CLEAN +CLEAN: clean + +.PHONY: distclean +distclean: clean + + +[install] +.PHONY: install +install: $(INSTALL) + +.PHONY: _findlib_install +_findlib_install: + @echo "" + files=$$( \ + for f in $(BYTE_INST) $(NAT_INST) $(BYTE_EXEC_INST) $(NAT_EXEC_INST) $(OTHER_INST); do \ + if [ -f "$$f" ]; then echo $$f; fi; \ + done; \ + ) && \ + $(TASKINSTALL) $$files + +.PHONY: uninstall +uninstall: $(UNINSTALL) + +.PHONY: _findlib_uninstall +_findlib_uninstall: + @echo "" + $(TASKREMOVE) + +# The following rules just print some variables. + +.PHONY: _print_name +_print_name: + echo "$(NAME)" + +.PHONY: _print_version +_print_version: + echo "$(VERSION)" + +[local] +# ---------------------------------------------------------------------- +# Local additions +# ---------------------------------------------------------------------- + +[trailer] +## ====================================================================== +## History: +## +## $Log: make_wizard.pattern,v $ +## Revision 1.2 2003/01/13 00:37:45 gerd +## Bugfix NATIVE_ARCHIVE ==> NAT_ARCHIVE (reported by +## Matt Gushee) +## +## Revision 1.1 2002/05/26 14:09:07 gerd +## Renaming +## +## Revision 1.1 2002/05/05 20:40:26 gerd +## Initial revision +## +## diff --git a/local-packages/ocamlfind/src/findlib/META b/local-packages/ocamlfind/src/findlib/META new file mode 100644 index 0000000..ce39190 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/META @@ -0,0 +1,36 @@ +# specifications for "findlib": +description = "Package manager" +requires = "findlib.internal" +requires(toploop) += "findlib.top" +requires(create_toploop) += "findlib.top" +version = "1.9.5" + +package "internal" ( + version = "1.9.5" + description = "Package manager" + requires = "" + archive(byte) = "findlib.cma" + archive(native) = "findlib.cmxa" + plugin(byte) = "findlib.cma" + plugin(native) = "findlib.cmxs" +) + +package "dynload" ( + version = "1.9.5" + description = "Package manager dynamic loader" + requires = "findlib dynlink" + archive(byte) = "findlib_dynload.cma" + archive(native) = "findlib_dynload.cmxa" +#Even if it strange and discouraged to dynload this package + plugin(byte) = "findlib_dynload.cma" + plugin(native) = "findlib_dynload.cmxs" + linkopts = "-linkall" +) + +package "top" ( + version = "1.9.5" + description = "Package manager toplevel support" + requires = "findlib.internal" + archive(byte) = "findlib_top.cma" + archive(native) = "findlib_top.cmxa" +) diff --git a/local-packages/ocamlfind/src/findlib/META.in b/local-packages/ocamlfind/src/findlib/META.in new file mode 100644 index 0000000..6b473c0 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/META.in @@ -0,0 +1,36 @@ +# specifications for "findlib": +description = "Package manager" +requires = "findlib.internal" +requires(toploop) += "findlib.top" +requires(create_toploop) += "findlib.top" +version = "@VERSION@" + +package "internal" ( + version = "@VERSION@" + description = "Package manager" + requires = "@REQUIRES@" + archive(byte) = "findlib.cma" + archive(native) = "findlib.cmxa" + plugin(byte) = "findlib.cma" + plugin(native) = "findlib.cmxs" +) + +package "dynload" ( + version = "@VERSION@" + description = "Package manager dynamic loader" + requires = "findlib dynlink" + archive(byte) = "findlib_dynload.cma" + archive(native) = "findlib_dynload.cmxa" +#Even if it strange and discouraged to dynload this package + plugin(byte) = "findlib_dynload.cma" + plugin(native) = "findlib_dynload.cmxs" + linkopts = "-linkall" +) + +package "top" ( + version = "@VERSION@" + description = "Package manager toplevel support" + requires = "findlib.internal" + archive(byte) = "findlib_top.cma" + archive(native) = "findlib_top.cmxa" +) diff --git a/local-packages/ocamlfind/src/findlib/Makefile b/local-packages/ocamlfind/src/findlib/Makefile new file mode 100644 index 0000000..ea23f4a --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/Makefile @@ -0,0 +1,193 @@ +# make all: compile to bytecode +# make opt: compile to native code +# make install: install bytecode and/or native code +# +# See Makefile.config for configurable variables. +# Runtime configurations might also be necessary in the site-lib/*/META +# files. +#---------------------------------------------------------------------- + +TOP=../.. +include $(TOP)/Makefile.config + +NAME = findlib + +# Need compiler-libs since ocaml-4.00 +OCAMLC = ocamlc -I +compiler-libs +OCAMLOPT = ocamlopt -I +compiler-libs -g +OCAMLDEP = ocamldep +OCAMLLEX = ocamllex +#CAMLP4O = camlp4 pa_o.cmo pa_op.cmo pr_o.cmo -- +#CAMLP4O = camlp4 pa_o.cmo pa_op.cmo pr_dump.cmo -- + + +OBJECTS = findlib_config.cmo fl_split.cmo fl_metatoken.cmo fl_meta.cmo \ + fl_metascanner.cmo fl_topo.cmo fl_package_base.cmo \ + findlib.cmo fl_args.cmo fl_lint.cmo +TOBJECTS = topfind.cmo + +XOBJECTS = $(OBJECTS:.cmo=.cmx) +TXOBJECTS = topfind.cmx + +OCAMLFIND_OBJECTS = ocaml_args.cmo frontend.cmo +OCAMLFIND_XOBJECTS = ocaml_args.cmx frontend.cmx + +# OCAMLFIND_ARCHIVES: set in Makefile.config +OCAMLFIND_XARCHIVES = $(OCAMLFIND_ARCHIVES:.cma=.cmxa) + +NUMTOP_OBJECTS = num_top_printers.cmo num_top.cmo + +DYNLOAD_OBJECTS = fl_dynload.cmo +DYNLOAD_XOBJECTS = $(DYNLOAD_OBJECTS:.cmo=.cmx) + + +all: ocamlfind$(EXEC_SUFFIX) findlib.cma findlib_top.cma topfind $(NUMTOP) \ + findlib_dynload.cma + +opt: ocamlfind_opt$(EXEC_SUFFIX) findlib.cmxa findlib_top.cmxa topfind \ + findlib_dynload.cmxa + +num-top: num_top.cma + +ocamlfind$(EXEC_SUFFIX): findlib.cma $(OCAMLFIND_OBJECTS) + $(OCAMLC) $(CUSTOM) -o ocamlfind$(EXEC_SUFFIX) -g $(OCAMLFIND_ARCHIVES) \ + $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_OBJECTS) + +ocamlfind_opt$(EXEC_SUFFIX): findlib.cmxa $(OCAMLFIND_XOBJECTS) + $(OCAMLOPT) -o ocamlfind_opt$(EXEC_SUFFIX) $(OCAMLFIND_XARCHIVES) \ + $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) $(OCAMLFIND_XOBJECTS) + +test_parser$(EXEC_SUFFIX): fl_metascanner.cmx test_parser.cmx fl_metatoken.cmx fl_meta.cmx + $(OCAMLOPT) -o test_parser$(EXEC_SUFFIX) fl_meta.cmx fl_metatoken.cmx fl_metascanner.cmx test_parser.cmx + +findlib.cma: $(OBJECTS) + $(OCAMLC) -a -o findlib.cma $(OBJECTS) + +findlib_top.cma: $(TOBJECTS) + $(OCAMLC) -a -o findlib_top.cma $(TOBJECTS) + +findlib.cmxa: $(XOBJECTS) + $(OCAMLOPT) -a -o findlib.cmxa $(XOBJECTS) + if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ + $(OCAMLOPT) -shared -o findlib.cmxs $(XOBJECTS); \ + fi + +findlib_top.cmxa: $(TXOBJECTS) + $(OCAMLOPT) -a -o findlib_top.cmxa $(TXOBJECTS) + if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ + $(OCAMLOPT) -shared -o findlib_top.cmxs $(TXOBJECTS); \ + fi + +findlib_dynload.cma: $(DYNLOAD_OBJECTS) + $(OCAMLC) -a -o findlib_dynload.cma $(DYNLOAD_OBJECTS) + +findlib_dynload.cmxa: $(DYNLOAD_XOBJECTS) + $(OCAMLOPT) -a -o findlib_dynload.cmxa $(DYNLOAD_XOBJECTS) + if [ $(HAVE_NATDYNLINK) -gt 0 ]; then \ + $(OCAMLOPT) -shared -o findlib_dynload.cmxs $(DYNLOAD_XOBJECTS); \ + fi + +findlib_config.ml: findlib_config.mlp $(TOP)/Makefile.config + USE_CYGPATH="$(USE_CYGPATH)"; \ + export USE_CYGPATH; \ + cat findlib_config.mlp | \ + $(SH) $(TOP)/tools/patch '@CONFIGFILE@' '$(OCAMLFIND_CONF)' | \ + $(SH) $(TOP)/tools/patch '@STDLIB@' '$(OCAML_CORE_STDLIB)' | \ + sed -e 's;@AUTOLINK@;$(OCAML_AUTOLINK);g' \ + -e 's;@SYSTEM@;$(SYSTEM);g' \ + >findlib_config.ml + +topfind.ml: topfind.ml.in + if [ "$(ENABLE_TOPFIND_PPXOPT)" = "true" ]; then \ + cp topfind.ml.in topfind.ml; \ + else \ + sed -e '/PPXOPT_BEGIN/,/PPXOPT_END/ d' topfind.ml.in \ + > topfind.ml ; \ + fi + +topfind: topfind_rd$(OCAML_REMOVE_DIRECTORY).p + USE_CYGPATH="$(USE_CYGPATH)"; \ + export USE_CYGPATH; \ + cat topfind_rd$(OCAML_REMOVE_DIRECTORY).p | \ + $(SH) $(TOP)/tools/patch '@SITELIB@' '$(OCAML_SITELIB)' \ + >topfind + +num_top.cma: $(NUMTOP_OBJECTS) + $(OCAMLC) -a -o num_top.cma $(NUMTOP_OBJECTS) + +clean: + rm -f *.cmi *.cmo *.cma *.cmx *.a *.lib *.o *.obj *.cmxa \ + fl_meta.ml findlib_config.ml findlib.mml topfind.ml topfind \ + ocamlfind$(EXEC_SUFFIX) ocamlfind_opt$(EXEC_SUFFIX) + +install: all + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)" + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)" + test $(INSTALL_TOPFIND) -eq 0 || $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)" + test $(INSTALL_TOPFIND) -eq 0 || $(INSTALLFILE) topfind "$(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)/" + files=`$(SH) $(TOP)/tools/collect_files $(TOP)/Makefile.config \ + findlib.cmi findlib.mli findlib.cma findlib.cmxa findlib$(LIB_SUFFIX) findlib.cmxs \ + findlib_config.cmi findlib_config.ml topfind.cmi topfind.mli \ + fl_args.cmi fl_lint.cmi fl_meta.cmi fl_split.cmi fl_topo.cmi ocaml_args.cmi \ + fl_package_base.mli fl_package_base.cmi fl_metascanner.mli fl_metascanner.cmi \ + fl_metatoken.cmi findlib_top.cma findlib_top.cmxa findlib_top$(LIB_SUFFIX) findlib_top.cmxs \ + findlib_dynload.cma findlib_dynload.cmxa findlib_dynload$(LIB_SUFFIX) findlib_dynload.cmxs fl_dynload.mli fl_dynload.cmi \ + META` && \ + $(INSTALLFILE) $$files "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)/" + f="ocamlfind$(EXEC_SUFFIX)"; { test -f ocamlfind_opt$(EXEC_SUFFIX) && f="ocamlfind_opt$(EXEC_SUFFIX)"; }; \ + $(INSTALLFILE) $$f "$(DESTDIR)$(prefix)$(OCAMLFIND_BIN)/ocamlfind$(EXEC_SUFFIX)" + # the following "if" block is only needed for 4.00beta2 + if [ $(OCAML_REMOVE_DIRECTORY) -eq 0 -a -f "$(OCAML_CORE_STDLIB)/compiler-libs/topdirs.cmi" ]; then \ + cd "$(OCAML_CORE_STDLIB)/compiler-libs/"; \ + $(INSTALLFILE) topdirs.cmi toploop.cmi "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME)/"; \ + fi + +install-num-top: + $(INSTALLDIR) "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/num-top" + $(INSTALLFILE) num_top.cma num_top.cmi num_top_printers.cmi \ + "$(DESTDIR)$(prefix)$(OCAML_SITELIB)/num-top/" + +# Note: uninstall-num-top is part of the removal of the META files. + +uninstall: + rm -f $(DESTDIR)$(prefix)$(OCAML_CORE_STDLIB)/findlib + rm -rf $(DESTDIR)$(prefix)$(OCAML_SITELIB)/$(NAME) + rm -f $(DESTDIR)$(prefix)$(OCAMLFIND_BIN)/ocamlfind$(EXEC_SUFFIX) + + +depend: *.ml *.mli fl_meta.ml fl_metascanner.ml findlib_config.ml topfind.ml + $(OCAMLDEP) *.ml *.mli >depend + +# Some 'make' implementations require that .SUFFIXES must occur before +# the first suffix rule. (E.g. AIX) +.SUFFIXES: .mll .cmo .cmi .cmx .ml .mli .mml +# .src + +.mml.cmo: + $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -g -vmthread -c -impl $< + +.mml.cmx: + $(OCAMLOPT) $(OPAQUE) $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -thread -c -impl $< + +.ml.cmx: + $(OCAMLOPT) $(OPAQUE) $(OCAMLOPT_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $< + +.ml.cmo: + $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -g -c $< + +.mli.cmi: + $(OCAMLC) $(OPAQUE) $(OCAMLC_FLAGS) $(OCAMLFIND_OCAMLFLAGS) -c $< + +#.src.ml: +# $(CAMLP4O) -impl $< -o $@ + +# Solaris make does not like the suffix rule .mll.ml, +# so I replaced it by its single application: +fl_meta.ml: fl_meta.mll + $(OCAMLLEX) fl_meta.mll + +# Don't remove fl_metascanner.ml: +.PRECIOUS: fl_metascanner.ml + +include depend + diff --git a/local-packages/ocamlfind/src/findlib/depend b/local-packages/ocamlfind/src/findlib/depend new file mode 100644 index 0000000..6eef2d3 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/depend @@ -0,0 +1,112 @@ +findlib.cmo : \ + fl_split.cmo \ + fl_package_base.cmi \ + fl_metascanner.cmi \ + findlib_config.cmo \ + findlib.cmi +findlib.cmx : \ + fl_split.cmx \ + fl_package_base.cmx \ + fl_metascanner.cmx \ + findlib_config.cmx \ + findlib.cmi +findlib.cmi : +findlib_config.cmo : +findlib_config.cmx : +fl_args.cmo : +fl_args.cmx : +fl_dynload.cmo : \ + fl_split.cmo \ + findlib.cmi \ + fl_dynload.cmi +fl_dynload.cmx : \ + fl_split.cmx \ + findlib.cmx \ + fl_dynload.cmi +fl_dynload.cmi : +fl_lint.cmo : \ + fl_metascanner.cmi +fl_lint.cmx : \ + fl_metascanner.cmx +fl_meta.cmo : \ + fl_metatoken.cmo +fl_meta.cmx : \ + fl_metatoken.cmx +fl_metascanner.cmo : \ + fl_metatoken.cmo \ + fl_meta.cmo \ + fl_metascanner.cmi +fl_metascanner.cmx : \ + fl_metatoken.cmx \ + fl_meta.cmx \ + fl_metascanner.cmi +fl_metascanner.cmi : \ + fl_metatoken.cmo +fl_metatoken.cmo : +fl_metatoken.cmx : +fl_ocaml_args.cmo : +fl_ocaml_args.cmx : +fl_package_base.cmo : \ + fl_topo.cmi \ + fl_split.cmo \ + fl_metascanner.cmi \ + fl_package_base.cmi +fl_package_base.cmx : \ + fl_topo.cmx \ + fl_split.cmx \ + fl_metascanner.cmx \ + fl_package_base.cmi +fl_package_base.cmi : \ + fl_metascanner.cmi +fl_split.cmo : +fl_split.cmx : +fl_topo.cmo : \ + fl_topo.cmi +fl_topo.cmx : \ + fl_topo.cmi +fl_topo.cmi : +frontend.cmo : \ + ocaml_args.cmo \ + fl_split.cmo \ + fl_package_base.cmi \ + fl_metascanner.cmi \ + fl_lint.cmo \ + fl_args.cmo \ + findlib_config.cmo \ + findlib.cmi +frontend.cmx : \ + ocaml_args.cmx \ + fl_split.cmx \ + fl_package_base.cmx \ + fl_metascanner.cmx \ + fl_lint.cmx \ + fl_args.cmx \ + findlib_config.cmx \ + findlib.cmx +num_top.cmo : \ + num_top.cmi +num_top.cmx : \ + num_top.cmi +num_top.cmi : +num_top_printers.cmo : \ + num_top_printers.cmi +num_top_printers.cmx : \ + num_top_printers.cmi +num_top_printers.cmi : +ocaml_args.cmo : +ocaml_args.cmx : +test_parser.cmo : \ + fl_metascanner.cmi +test_parser.cmx : \ + fl_metascanner.cmx +topfind.cmo : \ + fl_split.cmo \ + fl_package_base.cmi \ + findlib.cmi \ + topfind.cmi +topfind.cmx : \ + fl_split.cmx \ + fl_package_base.cmx \ + findlib.cmx \ + topfind.cmi +topfind.cmi : diff --git a/local-packages/ocamlfind/src/findlib/findlib.ml b/local-packages/ocamlfind/src/findlib/findlib.ml new file mode 100644 index 0000000..dc9b2b4 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/findlib.ml @@ -0,0 +1,524 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +module StrSet = Set.Make(String) + +exception No_such_package + = Fl_package_base.No_such_package + + +exception Package_loop + = Fl_package_base.Package_loop + +type formal_pred = + [ `Pred of string + | `NegPred of string + ] + +let init_called = ref false ;; + +let conf_config_file = ref "";; +let conf_default_location = ref "";; +let conf_meta_directory = ref "";; +let conf_search_path = ref [];; +let conf_command = ref [];; +let conf_stdlib = ref "";; +let conf_ldconf = ref "";; +let conf_ignore_dups_in = ref ([] : string list);; + +let ocamlc_default = "ocamlc";; +let ocamlopt_default = "ocamlopt";; +let ocamlcp_default = "ocamlcp";; +let ocamloptp_default = "ocamloptp";; +let ocamlmklib_default = "ocamlmklib";; +let ocamlmktop_default = "ocamlmktop";; +let ocamldep_default = "ocamldep";; +let ocamlbrowser_default = "ocamlbrowser";; +let ocamldoc_default = "ocamldoc";; + + +let init_manually + ?(ocamlc_command = ocamlc_default) + ?(ocamlopt_command = ocamlopt_default) + ?(ocamlcp_command = ocamlcp_default) + ?(ocamloptp_command = ocamloptp_default) + ?(ocamlmklib_command = ocamlmklib_default) + ?(ocamlmktop_command = ocamlmktop_default) + ?(ocamldep_command = ocamldep_default) + ?(ocamlbrowser_command = ocamlbrowser_default) + ?(ocamldoc_command = ocamldoc_default) + ?ignore_dups_in + ?(ignore_dups_in_list = []) + ?(stdlib = Findlib_config.ocaml_stdlib) + ?(ldconf = Findlib_config.ocaml_ldconf) + ?(config = Findlib_config.config_file) + ~install_dir + ~meta_dir + ~search_path () = + conf_command := [ `ocamlc, ocamlc_command; + `ocamlopt, ocamlopt_command; + `ocamlcp, ocamlcp_command; + `ocamloptp, ocamloptp_command; + `ocamlmklib, ocamlmklib_command; + `ocamlmktop, ocamlmktop_command; + `ocamldep, ocamldep_command; + `ocamlbrowser, ocamlbrowser_command; + `ocamldoc, ocamldoc_command; + ]; + conf_config_file := config; + conf_search_path := search_path; + conf_default_location := install_dir; + conf_meta_directory := meta_dir; + conf_stdlib := stdlib; + conf_ldconf := ldconf; + conf_ignore_dups_in := + ( match ignore_dups_in with + | None -> [] + | Some d -> [d] + ) @ ignore_dups_in_list; + Fl_package_base.init !conf_search_path stdlib !conf_ignore_dups_in; + init_called := true +;; + + +let command_names cmd_spec = + try + let cmd_list = Fl_split.in_words cmd_spec in + List.map + (fun cmd_setting -> + try + (* cmd_setting: formal_name=actual_name *) + let l = String.length cmd_setting in + let n = String.index cmd_setting '=' in + let cmd_formal_name = String.sub cmd_setting 0 n in + let cmd_actual_name = String.sub cmd_setting (n+1) (l-n-1) in + cmd_formal_name, cmd_actual_name + with + Not_found -> + prerr_endline ("Warning: Please check the environment variable OCAMLFIND_COMMANDS"); + "", "" + ) + cmd_list + with + Not_found -> + [] +;; + +let auto_config_file() = + let p = + ( try Sys.getenv "OCAMLFIND_CONF" with Not_found -> "") in + if p = "" then Findlib_config.config_file else p + + +let init + ?env_ocamlpath ?env_ocamlfind_destdir ?env_ocamlfind_metadir + ?env_ocamlfind_commands ?env_ocamlfind_ignore_dups_in + ?env_ocamlfind_ignore_dups_in_list ?env_camllib ?env_ldconf + ?config ?toolchain () = + + let config_file = + match config with + Some f -> f + | None -> auto_config_file() + in + + let configd_file = + config_file ^ ".d" in + + let vars_of_file f = + let ch = open_in f in + try + let vars = + (Fl_metascanner.parse ch).Fl_metascanner.pkg_defs in + close_in ch; + vars + with + | error -> close_in ch; raise error in + + let vars_of_dir d = + let files = Array.to_list (Sys.readdir d) in + List.flatten + (List.map + (fun file -> + if Filename.check_suffix file ".conf" then + vars_of_file (Filename.concat d file) + else + [] + ) + files) + in + + let config_preds = + match toolchain with + | None -> (try [Sys.getenv "OCAMLFIND_TOOLCHAIN"] with Not_found -> []) + | Some p -> [p] in + + let sys_ocamlc, sys_ocamlopt, sys_ocamlcp, sys_ocamloptp, sys_ocamlmklib, + sys_ocamlmktop, sys_ocamldep, sys_ocamlbrowser, sys_ocamldoc, + sys_search_path, sys_destdir, sys_metadir, sys_stdlib, sys_ldconf = + ( + let config_vars = + if config_file <> "" && + not(Sys.file_exists config_file) && not(Sys.file_exists configd_file) + then + failwith("Config file not found - neither " ^ + config_file ^ " nor the directory " ^ + configd_file); + if Sys.file_exists config_file then + vars_of_file config_file + else + [] in + let configd_vars = + if Sys.file_exists configd_file then + vars_of_dir configd_file + else + [] in + let vars = config_vars @ configd_vars in + if vars <> [] then ( + let found = ref false in + let lookup name default = + let explicit_preds = + List.for_all + (fun p -> Fl_metascanner.predicate_exists p vars) + config_preds in + found := !found || explicit_preds; + try + Fl_metascanner.lookup name config_preds vars + with Not_found -> default + in + let config_tuple = + ( (lookup "ocamlc" ocamlc_default), + (lookup "ocamlopt" ocamlopt_default), + (lookup "ocamlcp" ocamlcp_default), + (lookup "ocamloptp" ocamloptp_default), + (lookup "ocamlmklib" ocamlmklib_default), + (lookup "ocamlmktop" ocamlmktop_default), + (lookup "ocamldep" ocamldep_default), + (lookup "ocamlbrowser" ocamlbrowser_default), + (lookup "ocamldoc" ocamldoc_default), + Fl_split.path (lookup "path" ""), + (lookup "destdir" ""), + (lookup "metadir" "none"), + (lookup "stdlib" Findlib_config.ocaml_stdlib), + (lookup "ldconf" Findlib_config.ocaml_ldconf) + ) in + if not !found && config_preds <> [] then + prerr_endline("ocamlfind: [WARNING] Undefined toolchain: " ^ + String.concat "" config_preds); + config_tuple + ) + else + ( ocamlc_default, ocamlopt_default, ocamlcp_default, ocamloptp_default, + ocamlmklib_default, + ocamlmktop_default, ocamldep_default, ocamlbrowser_default, + ocamldoc_default, + [], + "", + "none", + Findlib_config.ocaml_stdlib, + Findlib_config.ocaml_ldconf + ) + ) + in + + let env_commands = + match env_ocamlfind_commands with + Some x -> command_names x + | None -> command_names (try Sys.getenv "OCAMLFIND_COMMANDS" + with Not_found -> "") + in + let env_destdir = + match env_ocamlfind_destdir with + Some x -> x + | None -> + try Sys.getenv "OCAMLFIND_DESTDIR" with Not_found -> "" + in + let env_metadir = + match env_ocamlfind_metadir with + Some x -> x + | None -> + try Sys.getenv "OCAMLFIND_METADIR" with Not_found -> "" + in + let env_search_path = + Fl_split.path + (match env_ocamlpath with + Some x -> x + | None -> + try Sys.getenv "OCAMLPATH" with Not_found -> "" + ) + in + let env_stdlib = + match env_camllib with + Some x -> x + | None -> + ( try Sys.getenv "OCAMLLIB" + with + Not_found -> + (try Sys.getenv "CAMLLIB" with Not_found -> "" ) + ) + in + let env_ldconf = + match env_ldconf with + Some x -> x + | None -> + try Sys.getenv "OCAMLFIND_LDCONF" with Not_found -> "" + in + let ignore_dups_in_list = + match env_ocamlfind_ignore_dups_in, env_ocamlfind_ignore_dups_in_list with + | Some x0, Some l -> x0 :: l + | None, Some l -> l + | Some x0, None -> [x0] + | None, None -> + try Fl_split.path (Sys.getenv "OCAMLFIND_IGNORE_DUPS_IN") + with Not_found -> [] in + + let ocamlc, ocamlopt, ocamlcp, ocamloptp, ocamlmklib, ocamlmktop, + ocamldep, ocamlbrowser, ocamldoc, + search_path, destdir, metadir, stdlib, ldconf = + (try List.assoc "ocamlc" env_commands with Not_found -> sys_ocamlc), + (try List.assoc "ocamlopt" env_commands with Not_found -> sys_ocamlopt), + (try List.assoc "ocamlcp" env_commands with Not_found -> sys_ocamlcp), + (try List.assoc "ocamloptp" env_commands with Not_found -> sys_ocamloptp), + (try List.assoc "ocamlmklib" env_commands with Not_found -> sys_ocamlmklib), + (try List.assoc "ocamlmktop" env_commands with Not_found -> sys_ocamlmktop), + (try List.assoc "ocamldep" env_commands with Not_found -> sys_ocamldep), + (try List.assoc "ocamlbrowser" env_commands with Not_found -> sys_ocamlbrowser), + (try List.assoc "ocamldoc" env_commands with Not_found -> sys_ocamldoc), + (env_search_path @ sys_search_path), + (if env_destdir = "" then sys_destdir else env_destdir), + (if env_metadir = "" then sys_metadir else env_metadir), + (if env_stdlib = "" then sys_stdlib else env_stdlib), + (if env_ldconf = "" then sys_ldconf else env_ldconf) + in + + init_manually + ~ocamlc_command: ocamlc + ~ocamlopt_command: ocamlopt + ~ocamlcp_command: ocamlcp + ~ocamloptp_command: ocamloptp + ~ocamlmklib_command: ocamlmklib + ~ocamlmktop_command: ocamlmktop + ~ocamldep_command: ocamldep + ~ocamlbrowser_command: ocamlbrowser + ~ocamldoc_command: ocamldoc + ~ignore_dups_in_list + ~stdlib: stdlib + ~ldconf: ldconf + ~config: config_file + ~install_dir: destdir + ~meta_dir: metadir + ~search_path: search_path + () +;; + + +let lazy_init() = + if not !init_called then init() + +let config_file() = + lazy_init(); + !conf_config_file;; + + +let default_location() = + lazy_init(); + !conf_default_location;; + + +let meta_directory() = + lazy_init(); + if !conf_meta_directory = "none" then "" else !conf_meta_directory;; + + +let search_path() = + lazy_init(); + !conf_search_path;; + + +let command which = + lazy_init(); + try + List.assoc which !conf_command + with + Not_found -> assert false +;; + + +let ocaml_stdlib() = + lazy_init(); + !conf_stdlib;; + + +let ocaml_ldconf() = + lazy_init(); + !conf_ldconf;; + +let ignore_dups_in() = + lazy_init(); + !conf_ignore_dups_in;; + +let package_directory pkg = + lazy_init(); + (Fl_package_base.query pkg).Fl_package_base.package_dir +;; + + +let package_meta_file pkg = + lazy_init(); + (Fl_package_base.query pkg).Fl_package_base.package_meta +;; + + +let package_property_2 predlist pkg propname = + lazy_init(); + let l = Fl_package_base.query pkg in + Fl_metascanner.lookup_2 propname predlist l.Fl_package_base.package_defs +;; + + +let package_property predlist pkg propname = + lazy_init(); + let l = Fl_package_base.query pkg in + Fl_metascanner.lookup propname predlist l.Fl_package_base.package_defs +;; + + +let package_ancestors predlist pkg = + lazy_init(); + Fl_package_base.requires predlist pkg +;; + + +let package_deep_ancestors predlist pkglist = + lazy_init(); + Fl_package_base.requires_deeply predlist pkglist +;; + + +let resolve_path ?base ?(explicit=false) p = + lazy_init(); + if p = "" then "" else ( + match p.[0] with + '^' | '+' -> + let stdlibdir = Fl_split.norm_dir (ocaml_stdlib()) in + Filename.concat + stdlibdir + (String.sub p 1 (String.length p - 1)) + | '@' -> + (* Search slash *) + ( try + let k = String.index p '/' in (* or Not_found *) + let pkg = String.sub p 1 (k-1) in + let p' = String.sub p (k+1) (String.length p - k - 1) in + let pkgdir = package_directory pkg in + Filename.concat pkgdir p' + with + Not_found -> + let pkg = String.sub p 1 (String.length p - 1) in + package_directory pkg + ) + | _ -> + ( match base with + None -> p + | Some b -> + if Filename.is_relative p && + (not explicit || not (Filename.is_implicit p)) + then + Filename.concat b p + else + p + ) + ) +;; + + +let list_packages ?(tab = 20) ?(descr = false) ch = + lazy_init(); + let packages = Fl_package_base.list_packages() in + let packages_sorted = List.sort compare packages in + + List.iter + (fun p -> + let v_string = + try + let v = package_property [] p "version" in + "(version: " ^ v ^ ")" + with + Not_found -> "(version: n/a)" + in + let descr_string = + try package_property [] p "description" + with Not_found -> "(no description)" in + let spaces1 = String.make (max 1 (tab-String.length p)) ' ' in + let spaces2 = String.make tab ' ' in + + if descr then ( + output_string ch (p ^ spaces1 ^ descr_string ^ "\n"); + output_string ch (spaces2 ^ v_string ^ "\n") + ) + else + output_string ch (p ^ spaces1 ^ v_string ^ "\n"); + ) + packages_sorted +;; + +let list_packages' ?prefix () = + lazy_init(); + Fl_package_base.list_packages ?prefix () + + +type rectype = + | Record_core + | Record_load + +let rec_core = ref StrSet.empty +let rec_load = ref StrSet.empty +let rec_preds = ref [] + +let record_package (rt:rectype) (p:string) = + match rt with + | Record_core -> + rec_core := StrSet.add p !rec_core + | Record_load -> + rec_load := StrSet.add p !rec_load + +let recorded_packages rt = + match rt with + | Record_core -> + StrSet.elements !rec_core + | Record_load -> + StrSet.elements (StrSet.diff !rec_load !rec_core) + +let reset_recordings() = + rec_load := StrSet.empty + +let type_of_recorded_package p = + if StrSet.mem p !rec_core then + Record_core + else + if StrSet.mem p !rec_load then + Record_load + else + raise Not_found + +let is_recorded_package p = + try ignore(type_of_recorded_package p); true with Not_found -> false + + +let rm_preds = + [ "create_toploop"; "toploop"; "executable"; "plugin"; "autolink"; + "preprocessor"; "syntax" ] + +let rm_preds_set = + List.fold_right StrSet.add rm_preds StrSet.empty + +let record_package_predicates preds = + let preds' = + List.filter (fun p -> not(StrSet.mem p rm_preds_set)) preds in + rec_preds := preds' + +let recorded_predicates() = + !rec_preds + diff --git a/local-packages/ocamlfind/src/findlib/findlib.mli b/local-packages/ocamlfind/src/findlib/findlib.mli new file mode 100644 index 0000000..b6073fa --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/findlib.mli @@ -0,0 +1,276 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(** The primary findlib interface + * + * The Findlib module is the primary interface of the findlib library. It + * contains functions to look up packages, to interpret META + * files, and to determine the ancestors of packages. + * + * This module must be initialized before it can be used: Call either + * [init] or [init_manually] for this. + *) + +exception No_such_package of string * string + (** First arg is the package name not found, second arg contains additional + * info for the user + *) + +exception Package_loop of string + (** A package is required by itself. The arg is the name of the + * package + *) + + +type formal_pred = + [ `Pred of string (** Positive occurence of a formal predicate var *) + | `NegPred of string (** Negative occurence of a formal predicate var *) + ] + (** A formal predicate as it occurs in a package definition *) + +val init : + ?env_ocamlpath: string -> + ?env_ocamlfind_destdir: string -> + ?env_ocamlfind_metadir: string -> + ?env_ocamlfind_commands: string -> + ?env_ocamlfind_ignore_dups_in: string -> + ?env_ocamlfind_ignore_dups_in_list: string list -> + ?env_camllib: string -> + ?env_ldconf: string -> + ?config: string -> + ?toolchain: string -> + unit -> + unit + (** Initializes the library from the configuration file and the environment. + * By default the + * function reads the file specified at compile time, but you can also + * pass a different file name in the [config] argument. + * Furthermore, the environment variables OCAMLPATH, OCAMLFIND_DESTDIR, + * OCAMLFIND_COMMANDS, OCAMLFIND_IGNORE_DUPS_IN, and CAMLLIB are interpreted. + * By default, the function takes + * the values found in the environment, but you can pass different values + * using the [env_*] arguments. By setting these values to empty strings + * they are no longer considered. + * The result of the initialization is determined as follows: + * - The default installation directory is the env variable OCAMLFIND_DESTDIR + * (if present and non-empty), and otherwise the variable [destdir] of the + * configuration file. + * - The installation directory for META files is read from the env + * variable OCAMLFIND_METADIR (if present and non-empty), and otherwise + * from the variable [metadir] of the configuration file, and otherwise + * no such directory is used. + * The special value ["none"] turns this feature off. + * - The search path is the concatenation of the env variable OCAMLPATH + * and the variable [path] of the config file + * - The executables of (ocamlc|ocamlopt|ocamlcp|ocamlmklib|ocamlmktop) are + * determined as follows: if the env variable OCAMLFIND_COMMANDS is set + * and non-empty, its contents specify the executables. Otherwise, if the + * config file variables [ocamlc], [ocamlopt], [ocamlcp], [ocamlmklib] and + * [ocamlmktop] are set, their contents specify the executables. Otherwise, + * the obvious default values are chosen: ["ocamlc"] for [ocamlc], + * ["ocamlopt"] for [ocamlopt], and so on. + * - The directory of the standard library is the value of the environment + * variable CAMLLIB (or OCAMLLIB), or if unset or empty, the value of + * the configuration variable [stdlib], or if unset the built-in location + * - The [ld.conf] file (configuring the dynamic loader) is the value of + * the environment variable OCAMLFIND_LDCONF, or if unset or empty, the + * value of the configuration variable [ldconf], or if unset the + * built-in location. + * - The ocamlfind tool doesn't emit warnings about double cmi files + * for the directories listed in OCAMLFIND_IGNORE_DUPS_IN. Since + * findlib-1.8 this variable is interpreted as colon-separated path. + * (Before, only one directory could be given.) If the variable is not + * set there are no exceptions, and the warnings are always printed. + * Note that both the parameters [env_ocamlfind_ignore_dups_in] (a + * single directory) and [env_ocamlfind_ignore_dups_in_list] (a list + * of directories) override the default. + *) + + +val init_manually : + ?ocamlc_command: string -> (* default: "ocamlc" *) + ?ocamlopt_command: string -> (* default: "ocamlopt" *) + ?ocamlcp_command: string -> (* default: "ocamlcp" *) + ?ocamloptp_command: string -> (* default: "ocamloptp" *) + ?ocamlmklib_command: string -> (* default: "ocamlmklib" *) + ?ocamlmktop_command: string -> (* default: "ocamlmktop" *) + ?ocamldep_command: string -> (* default: "ocamldep" *) + ?ocamlbrowser_command: string -> (* default: "ocamlbrowser" *) + ?ocamldoc_command: string -> (* default: "ocamldoc" *) + ?ignore_dups_in:string -> (* default: None *) + ?ignore_dups_in_list:string list -> (* default: [] *) + ?stdlib: string -> (* default: taken from Findlib_config *) + ?ldconf: string -> + ?config: string -> + install_dir: string -> + meta_dir: string -> + search_path: string list -> + unit -> + unit + (** This is an alternate way to initialize the library directly. + * Environment variables and configuration files are ignored. The + * parameter [config] just sets the file name reported by the + * [config_file] function below. + *) + + +val config_file : unit -> string + (** The location of the configuration file *) + +val default_location : unit -> string + (** Get the default installation directory for packages *) + +val meta_directory : unit -> string + (** Get the META installation directory for packages. + * Returns [""] if no such directory is configured. + *) + +val search_path : unit -> string list + (** Get the search path for packages *) + +val command : [ `ocamlc | `ocamlopt | `ocamlcp | `ocamloptp | `ocamlmklib + | `ocamlmktop | `ocamldep | `ocamlbrowser | `ocamldoc + ] -> + string + (** Get the name/path of the executable *) + +val ocaml_stdlib : unit -> string + (** Get the directory of the standard library *) + +val ocaml_ldconf : unit -> string + (** Get the file name of [ld.conf] *) + +val package_directory : string -> string + (** Get the absolute path of the directory where the given package is + * stored. + * + * Raises [No_such_package] if the package cannot be found. + *) + +val package_meta_file : string -> string + (** Get the absolute path of the META file of the given package *) + +val ignore_dups_in : unit -> string list + (** If [Some d], duplicate packages below [d] are ignored, and do not + * produce warnings. (Only affects the generation of warnings.) + * + * Since findlib-1.8 this configuration is a list. Before, it was a + * [string option]. + *) + +val package_property : string list -> string -> string -> string + (** [package_property predlist pkg propname]: + * Looks up the property [propname] of package [pkg] under the assumption + * that the predicates in [predlist] are true. + * + * Raises [No_such_package] if the package, and [Not_found] if the property + * cannot be found. + * + * EXAMPLES: + * - [package_property [] "p" "requires":] + * get the value of the [requires] clause of package [p] + * - [package_property [ "mt"; "byte" ] "p" "archive":] + * get the value of the [archive] property of package [p] for multi- + * threaded bytecode applications. + *) + +val package_property_2 : string list -> string -> string -> + string * formal_pred list + (** [package_property_2 predlist pkg propname]: This returns two values + [(v, preds)]. The first one, [v], is computed as in [package_property]. + The other list, [preds], contains the predicates that actually had to + be set or not set in order to select the particular variable definition. + *) + + +val package_ancestors : string list -> string -> string list + (** [package_ancestors predlist pkg:] + * Determines the direct ancestors of package [pkg] under the assumption + * that the predicates in [predlist] are true, i.e. the names of the + * packages required by [pkg]. + * The returned list is unsorted. + * + * Raises [No_such_package] if the package [pkg] or one of its ancestors + * could not be found. + *) + +val package_deep_ancestors : string list -> string list -> string list + (** [package_deep_ancestors predlist pkglist:] + * determines the list of direct or indirect ancestors of the packages + * named in [pkglist] under the assumption that the predicates in [predlist] + * are true. + * + * The returned list is topologically sorted: The first element is the + * deepest ancestor; the last element is one of [pkglist]. + * + * Raises [No_such_package] if one of the packages in [pkglist] or one of + * the ancestors cannot be found. Raises [Package_loop] if there is a + * cyclic dependency. + *) + +val resolve_path : ?base:string -> ?explicit:bool -> string -> string + (** Resolves findlib notation in filename paths. The notation + * [ +name/path ] can be used to refer to the subdirectory [name] + * of the standard library directory; the continuation [ /path ] is + * optional. The notation [ \@name/path ] can be used to refer to + * the directory of the package [name]; the continuation [ /path ] + * is optional. For these two notations, absolute paths are returned. + * + * @param base When the function is applied on a relative path, the + * [base] path is prepended. Otherwise, the path is returned as + * it is. + * @param explicit Changes the meaning of [base] so that only paths + * count as relative that include at least one slash. + *) + +val list_packages : ?tab:int -> ?descr:bool -> out_channel -> unit + (** Prints the list of available packages to the [out_channel]. + * + * @param tab The tabulator width, by default 20 + * @param descr Whether package descriptions are printed. Default: false + *) + +val list_packages' : ?prefix:string -> unit -> string list + (** Returns the (unsorted) list of all packages. + * + * @param prefix Limit to the packages that starts with it. Default: unlimited + *) + +(** Managing dynamically loaded packages *) + +(** This is a registry of packages that are available in-core. This is both + used for toploops and for plugins. + *) + +type rectype = + | Record_core (** The package is part of the executable core *) + | Record_load (** The package has been dynamically loaded *) + +val record_package : rectype -> string -> unit + (** Record this package *) + +val record_package_predicates : string list -> unit + (** Record the predicates to be used for package loading. Certain predicates + are automatically filtered out if inappropriate. A call of + [record_package_predicates] replaces the set of predicates that was + installed beforehand. + *) + +val recorded_packages : rectype -> string list + (** The list of packages recorded with [record_package] *) + +val is_recorded_package : string -> bool + (** Whether there is a recording for this package *) + +val type_of_recorded_package : string -> rectype + (** Returns the type, or raises [Not_found] *) + +val recorded_predicates : unit -> string list + (** The most recent version of the recorded predicate list *) + +val reset_recordings : unit -> unit + (** Removes all [Record_load] packages from the list of recordings. + This forces that the packages are loaded again. + *) diff --git a/local-packages/ocamlfind/src/findlib/findlib_config.mlp b/local-packages/ocamlfind/src/findlib/findlib_config.mlp new file mode 100644 index 0000000..3177de6 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/findlib_config.mlp @@ -0,0 +1,25 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +let config_file = "@CONFIGFILE@";; + +let ocaml_stdlib = "@STDLIB@";; + +let ocaml_ldconf = Filename.concat ocaml_stdlib "ld.conf";; + +let ocaml_has_autolinking = @AUTOLINK@;; + +let libexec_name = "stublibs";; + +let system = "@SYSTEM@";; +(* - "mingw", "mingw64", "win32", "cygwin", "linux_elf", ... *) + +let dll_suffix = + match Sys.os_type with + | "Unix" | "BeOS" -> ".so" + | "Win32" | "Cygwin" -> ".dll" + | "MacOS" -> "" (* don't know *) + | _ -> failwith "Unknown Sys.os_type" +;; diff --git a/local-packages/ocamlfind/src/findlib/fl_args.ml b/local-packages/ocamlfind/src/findlib/fl_args.ml new file mode 100644 index 0000000..2bca50c --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_args.ml @@ -0,0 +1,104 @@ +(* $Id$ *) + +(* Rewrite a list of arguments args (from Sys.args) so that contracted + options like -L are transformed to -L , and become parseable + by Arg. + *) + +let make_ht (l:string list) = + let ht = Hashtbl.create 10 in + List.iter (fun x -> Hashtbl.add ht x ()) l; + ht + +let is_prefix s1 s2 = + let l1 = String.length s1 in + let l2 = String.length s2 in + l2 >= l1 && String.sub s2 0 l1 = s1 + +let rewrite_contracted_args spec contracted_opts args = + let args = Array.to_list args in + let switches = + List.map + (fun (name,kind,text) -> name) + (List.filter + (fun (name,kind,text) -> + match kind with + | Arg.Unit _ + | Arg.Set _ + | Arg.Clear _ -> true + | Arg.Tuple _ -> + failwith + "Fl_args.rewrite_for_contracted_args: Arg.Tuple unsupported" + | _ -> false + ) + spec + ) in + let unary_opts = + List.map + (fun (name,kind,text) -> name) + (List.filter + (fun (name,kind,text) -> + match kind with + | Arg.String _ + | Arg.Set_string _ + | Arg.Int _ + | Arg.Set_int _ + | Arg.Float _ + | Arg.Set_float _ -> true + | _ -> false + ) + spec + ) in + let rest_opts = + List.map + (fun (name,kind,text) -> name) + (List.filter + (fun (name,kind,text) -> + match kind with + | Arg.Rest _ -> true + | _ -> false + ) + spec + ) in + + let sw_ht = make_ht switches in + let unary_ht = make_ht unary_opts in + let rest_ht = make_ht rest_opts in + + let rec rewrite (args:string list) = + match args with + | arg :: args_rest when Hashtbl.mem sw_ht arg -> + arg :: rewrite args_rest + | arg :: args_rest when Hashtbl.mem rest_ht arg -> + args + | arg1 :: arg2 :: args_rest when Hashtbl.mem unary_ht arg1 -> + arg1 :: arg2 :: rewrite args_rest + | arg :: args_rest -> + ( try + let args1 = expand arg contracted_opts in + let args2 = rewrite args_rest in + args1 @ args2 + with + | Not_found -> + arg :: rewrite args_rest + ) + | [] -> + [] + + and expand arg olo = + match olo with + | olo1 :: olo_rest -> + if is_prefix olo1 arg then + let p = String.length olo1 in + let l = String.length arg in + [ olo1; + String.sub arg p (l-p) + ] + else + expand arg olo_rest + | [] -> + raise Not_found + + in + + Array.of_list (rewrite args) diff --git a/local-packages/ocamlfind/src/findlib/fl_dynload.ml b/local-packages/ocamlfind/src/findlib/fl_dynload.ml new file mode 100644 index 0000000..ece81fe --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_dynload.ml @@ -0,0 +1,55 @@ +(* $Id$ *) + +(* Utilities for loading dynamically packages *) + +open Printf + +let load_pkg ~debug pkg = + if not (Findlib.is_recorded_package pkg) then ( + if debug then + eprintf "[DEBUG] Fl_dynload: about to load: %s\n%!" pkg; + (* Determine the package directory: *) + let d = Findlib.package_directory pkg in + (* First try the new "plugin" variable: *) + let preds = Findlib.recorded_predicates() in + let archive = + try + Findlib.package_property preds pkg "plugin" + with + | Not_found -> + (* Legacy: use "archive" but require that the predicate + "plugin" is mentioned in the definition + *) + try + let v, fpreds = + Findlib.package_property_2 ("plugin"::preds) pkg "archive" in + let need_plugin = + List.mem "native" preds in + if need_plugin && not (List.mem (`Pred "plugin") fpreds) then + "" + else + v + with Not_found -> "" in + (* Split the plugin/archive property and resolve the files: *) + let files = Fl_split.in_words archive in + if debug then + eprintf "[DEBUG] Fl_dynload: files=%S\n%!" archive; + List.iter + (fun file -> + if debug then + eprintf "[DEBUG] Fl_dynload: loading %S\n%!" file; + let file = Findlib.resolve_path ~base:d file in + Dynlink.loadfile file + ) files; + Findlib.record_package Findlib.Record_load pkg + ) + else + if debug then + eprintf "[DEBUG] Fl_dynload: not loading: %s\n%!" pkg + + +let load_packages ?(debug=false) pkgs = + let preds = Findlib.recorded_predicates() in + let eff_pkglist = + Findlib.package_deep_ancestors preds pkgs in + List.iter (load_pkg ~debug) eff_pkglist diff --git a/local-packages/ocamlfind/src/findlib/fl_dynload.mli b/local-packages/ocamlfind/src/findlib/fl_dynload.mli new file mode 100644 index 0000000..56282fb --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_dynload.mli @@ -0,0 +1,37 @@ +(* $Id$ *) + +(** Utilities for loading dynamically packages *) + +val load_packages : ?debug:bool -> string list -> unit +(** Load the given packages and all their dependencies dynamically. Packages + already loaded or already in-core are not loaded again. The predicates + are taken from {!Findlib.recorded_predicates}, which are normally the + predicates from the link-time of the executable. + + In order to initialize this module correctly, you need to link the + executable in a special way. This is done by including "findlib.dynload" + in the [ocamlfind] command, e.g. + + {[ ocamlfind ocamlopt -o program -package findlib.dynload -linkpkg m.ml ]} + + It is not sufficient to just link [findlib_dynload.cm(x)a] into the + executable. The above command adds special initialization code that + (a) records the predicates and (b) records the packages already present + in the executable. Also [-linkall] is implicitly added. + + The dynamic package loader works both for bytecode and native code. + The META files of the packages need to specify the cma or cmxs files + in the following way: + + - First, the "plugin" variable is checked (instead of "archive"), e.g. + {[ +plugin(byte) = "my_plugin.cma" +plugin(native) = "my_plugin.cmxs" + ]} + This is the preferred style. + - Second, for bytecode only, the normal "archive" variable is + also accepted if "plugin" is not present. (Because bytecode archives + can normally be dynamically loaded without special preparation.) + - Third, for native-code only, the "archive(plugin)" variable + is also accepted. This is for legacy packages. + *) diff --git a/local-packages/ocamlfind/src/findlib/fl_lint.ml b/local-packages/ocamlfind/src/findlib/fl_lint.ml new file mode 100644 index 0000000..160cdfb --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_lint.ml @@ -0,0 +1,113 @@ +(* $Id$ -*- tuareg -*- + * ---------------------------------------------------------------------- + * + *) + +open Fl_metascanner + +module Have = struct + module T = struct + type mode = [`Byte | `Native | `Toploop | `Preprocessor | `Ppx_driver] + type t = [ + `Mode of [ `TooMany | `None] + (** problem in the number of mode (byte,native,syntax,...) + in the variable *) + | `Archive of [`Plugin|`NoPlugin] * mode + (** archive(plugin,...) or archive(...)) *) + | `Plugin of [`Plugin|`NoPlugin] * mode + (** plugin(...) *) + | `Description + | `Requires + | `Version + ] + let compare = compare + end + include T + module Set = Set.Make(T) + module Map = Map.Make(T) +end + +let scan_def acc def = + let add have = Have.Map.add have def acc in + let has_plugin_pred = List.mem (`Pred "plugin") def.def_preds in + let plugin = if has_plugin_pred then `Plugin else `NoPlugin in + let modes = [ "byte", `Byte; + "native", `Native; + "toploop", `Toploop; + "preprocessor", `Preprocessor; + "ppx_driver", `Ppx_driver + ] in + let modes = + List.filter + (fun (p,_) -> List.mem (`Pred p) def.def_preds) + modes + in + let modes = List.map snd modes in + match def.def_var, modes with + (** For archive the modes are used in multiple ways, so we can't + check exhaustiveness or presence. + *) + | "plugin", [] -> add (`Mode(`None)) + | "plugin", _::_::_ -> add (`Mode(`TooMany)) + + | "archive", [mode] -> add (`Archive(plugin,mode)) + | "plugin", [mode] -> add (`Plugin(plugin,mode)) + | "description", _ -> add `Description + | "requires", _ -> add `Requires + | "version", _ -> add `Version + | _ -> acc + + +let warn_def ~warned pkg = + let haves = + List.fold_left scan_def Have.Map.empty pkg.pkg_defs + in + let mem x = Have.Map.mem x haves in + let find x = Have.Map.find x haves in + let warning fmt = warned := true; Printf.printf fmt in + let if_ ?has ?(has_not=[]) msg = + match has, has_not with + | Some has, [] when mem has -> + warning "%a%s\n\n" print_def (find has) msg; + | Some has, has_not when mem has && not (List.exists mem has_not) -> + warning "%a%s\n\n" print_def (find has) msg; + | None, has_not when not (List.exists mem has_not) -> + warning "%s\n\n" msg; + | _ -> () + in + if_ ~has_not:[`Description] + "You should add a description."; + if_ ~has_not:[`Version] + "You should add a version."; + if_ ~has_not:[`Requires] + "You should add the required libraries. You can silent this \ + warning by using the empty string."; + if_ ~has:(`Mode(`TooMany)) + "This variable should have only one mode + (\"byte\", \"native\")."; + if_ ~has:(`Mode(`None)) + "This variable should have at least the predicate \ + \"byte\" or \"native\"."; + let with_mode mode = + if_ ~has:(`Plugin (`Plugin,mode)) + "You must not add the predicate \"plugin\" to the variable \ + \"plugin\"."; + if_ ~has:(`Archive (`Plugin,mode)) ~has_not:[`Plugin (`NoPlugin,mode)] + "This specification of dynamic loading is deprecated, you should add a \ + \"plugin(...)\" variable."; + if_ ~has:(`Archive (`NoPlugin,mode)) + ~has_not:[`Plugin (`NoPlugin,mode);`Archive (`Plugin,mode)] + "This variable indicates how to link statically, you should add a \ + \"plugin(...)\" variable for linking dynamically."; + in + with_mode `Byte; + with_mode `Native + +let warn pkg = + let warned = ref false in + let rec aux pkg = + warn_def ~warned pkg; + List.iter (fun (_,pkg) -> aux pkg) pkg.pkg_children; + in + aux pkg; + !warned diff --git a/local-packages/ocamlfind/src/findlib/fl_meta.mll b/local-packages/ocamlfind/src/findlib/fl_meta.mll new file mode 100644 index 0000000..b0737a1 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_meta.mll @@ -0,0 +1,90 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +{ open Fl_metatoken } + +rule token = + parse [ 'A'-'Z' 'a'-'z' '_' '0'-'9' '.' ]+ + { + Name (Lexing.lexeme lexbuf) + } + + | '(' + { + LParen + } + + | ')' + { + RParen + } + + | "+=" + { + PlusEqual + } + + | '=' + { + Equal + } + + | '-' + { + Minus + } + + | ',' + { + Comma + } + + | '"' [^ '"' '\\' ]* ( ( "\\\\" | "\\\"" ) [^ '"' '\\' ]* )* '"' + { + let s1 = Lexing.lexeme lexbuf in + let s2 = String.sub s1 1 (String.length s1 - 2) in + let l2 = String.length s2 in + let b = Buffer.create 80 in + let rec fill i = + if i Buffer.add_char b s2.[i+1]; fill (i+2) + | c -> Buffer.add_char b c; fill (i+1) in + fill 0; + String (Buffer.contents b) + } + + | [ ' ' '\t' '\r' ] + { + Space + } + + | '\n' + { + Newline + } + + | '#' [^ '\n']* '\n' + { + Newline + } + + | '#' [^ '\n']* eof + { + Eof + } + + | eof + { + Eof + } + + | _ + { + Unknown + } + +{} + diff --git a/local-packages/ocamlfind/src/findlib/fl_metascanner.ml b/local-packages/ocamlfind/src/findlib/fl_metascanner.ml new file mode 100644 index 0000000..2dff2bd --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_metascanner.ml @@ -0,0 +1,310 @@ +(* $Id$ -*- tuareg -*- + * ---------------------------------------------------------------------- + * + *) +open Fl_metatoken + +open Printf + +type formal_pred = [ | `Pred of string | `NegPred of string ] + +type flavour = [ | `BaseDef | `Appendix ] + +type pkg_definition = + { def_var : string; def_flav : flavour; def_preds : formal_pred list; + def_value : string + } + +type pkg_expr = + { pkg_defs : pkg_definition list; pkg_children : (string * pkg_expr) list + } + +exception Error of string + +let string_of_preds pl = + let print = function | `Pred n -> n | `NegPred n -> "-" ^ n + in + if pl = [] + then "" + else "(" ^ ((String.concat "," (List.map print pl)) ^ ")") + + +let scan_lexing buf = + (* transform an in_channel to a token stream; 'Space' tokens are left + * out. + *) + let (line_ref, pos0_ref, eof_found) = ((ref 1), (ref 0), (ref false)) + in + fun () -> + let rec next line pos0 = + let t = Fl_meta.token buf + in + match t with + | Space -> next line pos0 + | Newline -> next (line + 1) (Lexing.lexeme_end buf) + | Eof -> (eof_found := true; produce line pos0 Eof) + | _ -> produce line pos0 t + and produce line pos0 t = + (line_ref := line; + pos0_ref := pos0; + let pos = (Lexing.lexeme_start buf) - pos0 in (line, pos, t)) + in + if !eof_found + then produce !line_ref !pos0_ref Eof + else next !line_ref !pos0_ref + +let scan ch = scan_lexing (Lexing.from_channel ch) + +let parse_lexing lexbuf = + let rec mk_set l = + match l with + | x :: l' -> if List.mem x l' then mk_set l' else x :: (mk_set l') + | [] -> [] in + let error_msg msg line col = + Printf.sprintf "%s at line %d position %d" msg line col in + let next_token = scan_lexing lexbuf in + let raise_err error_fun line col = + raise (Error (error_fun line col)) in + let get_tok test error_fun = + let (line, col, tok) = next_token () + in + match test tok with + | None -> raise_err error_fun line col + | Some result -> result in + let get_rule rule arg error_fmt line col = + try rule arg with | Error _ -> raise_err error_fmt line col in + let rec parse_all need_rparen = + match next_token () with + | (line, col, Name "package") -> + let n = + get_tok string_tok + (error_msg "String literal expected after 'package'") in + let () = + get_tok (const_tok LParen) (error_msg "'(' expected after string") in + let subpkg = + get_rule parse_all true + (error_msg "Error in subpackage definition") line col in + let rest = parse_all need_rparen + in + { + pkg_defs = rest.pkg_defs; + pkg_children = (n, subpkg) :: rest.pkg_children; + } + | (line, col, Name n) -> + let (args, flav, value) = + get_rule parse_properties () + (error_msg "Error in 'name = value' clause") line col in + let rest = parse_all need_rparen in (* TODO: Check args *) + let args' = List.sort compare (mk_set args) in + let def = + { + def_var = n; + def_flav = flav; + def_preds = args'; + def_value = value; + } + in + { + pkg_defs = def :: rest.pkg_defs; + pkg_children = rest.pkg_children; + } + | (line, col, Eof) -> + (if need_rparen + then + raise_err + (Printf.sprintf "Unexpected end of file in line %d position %d") + line col + else (); + { pkg_defs = []; pkg_children = []; }) + | (line, col, RParen) -> + (if not need_rparen + then + raise_err + (Printf.sprintf "Unexpected end of file in line %d position %d") + line col + else (); + { pkg_defs = []; pkg_children = []; }) + | (line, col, _) -> + raise_err (error_msg "Expected 'name = value' clause") line col + and parse_properties () = + match next_token () with + | (line, col, LParen) -> + let arg1 = parse_argument () in + let args = parse_arguments () in + let flav = parse_flavour () in + let s = + get_tok string_tok (error_msg "Expected string constant after '='") + in ((arg1 :: args), flav, s) + | (line, col, Equal) -> + let s = + get_tok string_tok + (error_msg "'=' must be followed by a string constant") + in ([], `BaseDef, s) + | (line, col, PlusEqual) -> + let s = + get_tok string_tok + (error_msg "'+=' must be followed by a string constant") + in ([], `Appendix, s) + | (line, col, _) -> + raise_err (error_msg "Expected a '=' or a '(arguments,...)=' clause") + line col + and parse_arguments () = + match next_token () with + | (line, col, Comma) -> + let arg = parse_argument () in + let args = parse_arguments () in arg :: args + | (_, _, RParen) -> [] + | (line, col, _) -> + raise_err (error_msg "Another predicate or a ')' expected") line col + and parse_argument () = + match next_token () with + | (line, col, Name n) -> `Pred n + | (line, col, Minus) -> + let n = get_tok name_tok (error_msg "Name expected after '-'") + in `NegPred n + | (line, col, _) -> + raise_err (error_msg "Name or -Name expected") line col + and parse_flavour () = + match next_token () with + | (line, col, Equal) -> `BaseDef + | (line, col, PlusEqual) -> `Appendix + | (line, col, _) -> raise_err (error_msg "'+' or '+=' expected") line col in + let rec check_defs p l = + match l with + | [] -> () + | def :: l' -> + (List.iter + (fun def' -> + if + (def.def_var = def'.def_var) && + ((def.def_preds = def'.def_preds) && + ((def.def_flav = `BaseDef) && (def'.def_flav = `BaseDef))) + then + (let prefix = + if p = "" then "" else "In subpackage " ^ (p ^ ": ") in + let args = string_of_preds def.def_preds + in + raise + (Error + (prefix ^ + ("Double definition of '" ^ + (def.def_var ^ (args ^ "'")))))) + else ()) + l'; + check_defs p l') in + let rec check_pkg p pkg = + (check_defs p pkg.pkg_defs; + let l = ref [] + in + List.iter + (fun (n, subpkg) -> + let p' = if p = "" then n else p ^ ("." ^ n) + in + (if List.mem n !l + then + raise + (Error ("Double definition for subpackage " ^ p')) + else (); + if String.contains n '.' + then + raise + (Error + ("Subpackage name must not contain '.': \"" ^ + (n ^ "\""))) + else (); + check_pkg p' subpkg; + l := n :: !l)) + pkg.pkg_children) + in + try let pkg = parse_all false in (check_pkg "" pkg; pkg) + with | Error "" -> raise (Error "Syntax Error") + +let parse ch = parse_lexing (Lexing.from_channel ch) + +let escape s = (* no Str available :-( *) + let b = Buffer.create (String.length s) + in + (for k = 0 to (String.length s) - 1 do + (match s.[k] with + | '\\' -> Buffer.add_string b "\\\\" + | '"' -> Buffer.add_string b "\\\"" + | c -> Buffer.add_char b c) + done; + Buffer.contents b) + +let print_def f def = + let format_pred = function | `Pred s -> s | `NegPred s -> "-" ^ s in + fprintf f "%s%s %s \"%s\"\n" def.def_var + (match def.def_preds with + | [] -> "" + | l -> "(" ^ ((String.concat "," (List.map format_pred l)) ^ ")")) + (match def.def_flav with | `BaseDef -> "=" | `Appendix -> "+=") + (escape def.def_value) + + +let rec print f pkg = + (List.iter (print_def f) pkg.pkg_defs; + List.iter + (fun (name, child) -> + (fprintf f "\npackage \"%s\" (\n" (escape name); + print f child; + fprintf f ")\n")) + pkg.pkg_children) + +let rec remove_dups l = + (* FIXME: O(n^2) *) + match l with + x :: l' -> + if List.mem x l' then remove_dups l' else x::remove_dups l' + | [] -> [] + +let lookup_2 name predicate_list def = + let fulfills actual_preds formal_preds = + List.for_all + (function + | `Pred n -> List.mem n predicate_list + | `NegPred n -> not (List.mem n predicate_list)) + formal_preds in + let rec search_base best_n best_value l = + match l with + | [] -> if best_n >= 0 then best_value else raise Not_found + | def :: l' -> + if + (name = def.def_var) && + ((def.def_flav = `BaseDef) && + ((fulfills predicate_list def.def_preds) && + ((List.length def.def_preds) > best_n))) + then search_base + (List.length def.def_preds) + (def.def_value, def.def_preds) + l' + else search_base best_n best_value l' in + let rec search_appdx l = + match l with + | [] -> [] + | def :: l' -> + if + (name = def.def_var) && + ((def.def_flav = `Appendix) && + (fulfills predicate_list def.def_preds)) + then (def.def_value, def.def_preds) :: (search_appdx l') + else search_appdx l' in + let value_a, preds_a = search_base (-1) ("",[]) def in + let additions = search_appdx def in + let values_b = List.map fst additions in + let preds_b = List.flatten (List.map snd additions) in + let value = String.concat " " (value_a :: values_b) in + let preds = remove_dups (preds_a @ preds_b) in + (value, preds) + +let lookup name predicate_list def = + fst(lookup_2 name predicate_list def) + +let predicate_exists p defs = + List.exists + (fun def -> + List.exists (function | `Pred n -> n = p | `NegPred n -> n = p) + def.def_preds) + defs + + diff --git a/local-packages/ocamlfind/src/findlib/fl_metascanner.mli b/local-packages/ocamlfind/src/findlib/fl_metascanner.mli new file mode 100644 index 0000000..903f4f8 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_metascanner.mli @@ -0,0 +1,107 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(** Parses META files *) + +open Fl_metatoken + +type formal_pred = + [ `Pred of string (** Positive occurence of a formal predicate var *) + | `NegPred of string (** Negative occurence of a formal predicate var *) + ] + +type flavour = + [ `BaseDef + | `Appendix + ] + (** [`BaseDef] refers to META definitions using the "=" operator, + * and [`Appendix] refers to definitions using the "+=" operator. + *) + +type pkg_definition = + { def_var : string; (** The name of the defined variable *) + def_flav : flavour; (** The flavour of the definition *) + def_preds : formal_pred list; (** The formal predicates of the def *) + def_value : string; (** The value assigned to the variable *) + } + (** A [pkg_definition] is expressed by the syntax + * {[ var(p1,p2,...) = "value" ]} (flavour `BaseDef), + * or the syntax + * {[ var(p1,p2,...) += "value" ]} (flavour `Appendix) + * in the META file. The list of predicates may be omitted. Predicates + * may be negated by using "-", e.g. "-x". + *) + +type pkg_expr = + { pkg_defs : pkg_definition list; + pkg_children : (string * pkg_expr) list; + } + (** A value of type [pkg_expr] denotes the contents of a META file. + * The component [pkg_defs] are the variable definitions. + * The component [pkg_children] contains + * the definitions of the subpackages. + *) + +exception Error of string + + +val parse : in_channel -> pkg_expr + (** [parse ch:] + * scans and parses the file connected with channel [ch]. The file must + * have a syntax compatible with the META format. The return value + * contains the found definitions for the package and all subpackages. + * + * [exception Error of string:] is + * raised on syntax errors. The string explains the error. + *) + +val parse_lexing : Lexing.lexbuf -> pkg_expr + + +val print_def : out_channel -> pkg_definition -> unit + (** [print_def ch def]: + * Outputs the definition to a channel. + *) + +val print : out_channel -> pkg_expr -> unit + (** [print ch expr]: + * Outputs the package expression to a channel. + *) + + +val lookup : + string -> string list -> pkg_definition list -> string + (** [lookup variable_name predicate_list def]: + * + * Returns the value of [variable_name] in [def] under the assumption + * that the predicates in [predicate_list] hold, but no other predicates. + * + * The rules are as follows: In the step (A), only the [`BaseDef] + * definitions are considered. The first base definition is determined where + * all predicates are satisfied and that has the longest predicate list. + * In the step (B) only the [`Appendix] definitions are considered. + * All definitions are determined where all predicates are satisfied. + * The final result is the concatenation of the single result of (A) + * and all results of (B) (in the order they are defined). A space + * character is inserted between two concatenated strings. + * + * When step (A) does not find any matching definition, the exception + * [Not_found] is raised. + *) + + +val lookup_2 : + string -> string list -> pkg_definition list -> string * formal_pred list + (** Like [lookup], but also returns the list of predicates that had to + be considered to select the particular variable definition. + *) + + +val predicate_exists : + string -> pkg_definition list -> bool + (** [predicate_exists variable_name def]: + + Whether [variable_name] is explicitly mentioned in [def]. + *) diff --git a/local-packages/ocamlfind/src/findlib/fl_metatoken.ml b/local-packages/ocamlfind/src/findlib/fl_metatoken.ml new file mode 100644 index 0000000..6a2483f --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_metatoken.ml @@ -0,0 +1,37 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + + +type token = + Name of string + | LParen + | RParen + | Equal + | PlusEqual + | Minus + | Comma + | String of string + | Space + | Newline + | Eof + | Unknown +;; + + +let name_tok = function + | Name s -> Some s + | _ -> None + +let string_tok = function + | String s -> Some s + | _ -> None + +let const_tok constant tok = + match constant with + | Name _ | String _ -> failwith "expect: only for constant tokens" + | LParen | RParen | Equal | PlusEqual | Minus + | Comma | Space | Newline | Eof | Unknown -> + if constant = tok then Some () + else None diff --git a/local-packages/ocamlfind/src/findlib/fl_ocaml_args.ml b/local-packages/ocamlfind/src/findlib/fl_ocaml_args.ml new file mode 100644 index 0000000..f1d38c5 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_ocaml_args.ml @@ -0,0 +1,2623 @@ +let ocamlc_spec = Some [ + "-a", + false, + " Build a library"; + + "-alert", + true, + " Enable or disable alerts according to :\n + enable alert \n - disable alert \n ++ treat as fatal error"; + + "--", + true, + " treat as non-fatal\n @ enable and treat it as fatal error\n can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-annot", + false, + " Save information in .annot"; + + "-assume-require", + true, + " for linking, assume is required and already looked up"; + + "-bin-annot", + false, + " Save typedtree in .cmt"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + " Use as the C compiler and linker"; + + "-cclib", + true, + " Pass option to the C linker"; + + "-ccopt", + true, + " Pass option to the C compiler and linker"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compat-32", + false, + " Check that generated bytecode can run on 32-bit platforms"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-custom", + false, + " Link in custom mode"; + + "-dllib", + true, + " Use the dynamically-loaded library "; + + "-dllpath", + true, + " Add to the run-time search path for shared libraries"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + " Generate code that can later be `packed' with\n ocamlc -pack -o .cmo"; + + "-g", + false, + " Save debugging information"; + + "-stop-after", + true, + "{parsing|typing} Stop after the given compilation pass."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + " Add to the list of include directories"; + + "-impl", + true, + " Compile as a .ml file"; + + "-intf", + true, + " Compile as a .mli file"; + + "-intf-suffix", + true, + " Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + " (deprecated) same as -intf-suffix"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-make-runtime", + false, + " Build a runtime system with given C objects and libraries"; + + "-make_runtime", + false, + " (deprecated) same as -make-runtime"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-check-prims", + false, + " Do not check runtime for primitives"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautoliblink", + false, + " Do not automatically link OCaml libraries specified in .cma files"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cma files"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nopervasives", + false, + " (undocumented)"; + + "-o", + true, + " Set output file name to "; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + " Opens the module before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-output-complete-exe", + false, + " Output a self-contained executable, including runtime and C stubs"; + + "-pack", + false, + " Package the given .cmo files into one .cmo"; + + "-pp", + true, + " Pipe sources through preprocessor "; + + "-ppx", + true, + " Pipe abstract syntax trees through preprocessor "; + + "-plugin", + true, + " (no longer supported)"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-require", + true, + " Add to the list of required libraries"; + + "-runtime-variant", + true, + " Use the variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-safe-string", + false, + " (was set when configuring the compiler)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-use-runtime", + true, + " Generate bytecode for the given runtime system"; + + "-use_runtime", + true, + " (deprecated) same as -use-runtime"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + " Enable or disable warnings according to :\n + enable warnings in \n - disable warnings in \n @ enable warnings in and treat them as errors\n can be:\n a single warning number\n .. a range of consecutive warning numbers\n a predefined set\n default setting is \"+a-4-6-7-9-27-29-30-32..42-44-45-48-50-60-66-67\""; + + "-warn-error", + true, + " Enable or disable error status for warnings according\n to . See option -w for the syntax of .\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + " Treat as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + " (advanced, see manual section 9.2.)"; + + "-use-prims", + true, + " (undocumented)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-dinstr", + false, + " (undocumented)"; + + "-dcamlprimc", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into .dump"; + + "-args", + true, + " Read additional newline-terminated command line arguments\n from "; + + "-args0", + true, + " Read additional null character terminated command line arguments\nfrom "; + + "-depend", + true, + " Compute dependencies (use 'ocamlc -depend -help' for details)"; + +];; + +let ocamlcp_spec = Some [ + "-P", + true, + "[afilmt] Profile constructs specified by argument (default fm):\n a Everything\n f Function calls and method calls\n i if ... then ... else\n l while and for loops\n m match ... with\n t try ... with"; + + "-p", + true, + "[afilmt] Same as option -P"; + + "-a", + false, + " Build a library"; + + "-alert", + true, + " Enable or disable alerts according to :\n + enable alert \n - disable alert \n ++ treat as fatal error"; + + "--", + true, + " treat as non-fatal\n @ enable and treat it as fatal error\n can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-annot", + false, + " Save information in .annot"; + + "-assume-require", + true, + " for linking, assume is required and already looked up"; + + "-bin-annot", + false, + " Save typedtree in .cmt"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + " Use as the C compiler and linker"; + + "-cclib", + true, + " Pass option to the C linker"; + + "-ccopt", + true, + " Pass option to the C compiler and linker"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compat-32", + false, + " Check that generated bytecode can run on 32-bit platforms"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-custom", + false, + " Link in custom mode"; + + "-dllib", + true, + " Use the dynamically-loaded library "; + + "-dllpath", + true, + " Add to the run-time search path for shared libraries"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + " Generate code that can later be `packed' with\n ocamlc -pack -o .cmo"; + + "-g", + false, + " Save debugging information"; + + "-stop-after", + true, + "{parsing|typing} Stop after the given compilation pass."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + " Add to the list of include directories"; + + "-impl", + true, + " Compile as a .ml file"; + + "-intf", + true, + " Compile as a .mli file"; + + "-intf-suffix", + true, + " Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + " (deprecated) same as -intf-suffix"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-make-runtime", + false, + " Build a runtime system with given C objects and libraries"; + + "-make_runtime", + false, + " (deprecated) same as -make-runtime"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-check-prims", + false, + " Do not check runtime for primitives"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautoliblink", + false, + " Do not automatically link OCaml libraries specified in .cma files"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cma files"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nopervasives", + false, + " (undocumented)"; + + "-o", + true, + " Set output file name to "; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + " Opens the module before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-output-complete-exe", + false, + " Output a self-contained executable, including runtime and C stubs"; + + "-pack", + false, + " Package the given .cmo files into one .cmo"; + + "-pp", + true, + " Pipe sources through preprocessor "; + + "-ppx", + true, + " Pipe abstract syntax trees through preprocessor "; + + "-plugin", + true, + " (no longer supported)"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-require", + true, + " Add to the list of required libraries"; + + "-runtime-variant", + true, + " Use the variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-safe-string", + false, + " (was set when configuring the compiler)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-use-runtime", + true, + " Generate bytecode for the given runtime system"; + + "-use_runtime", + true, + " (deprecated) same as -use-runtime"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + " Enable or disable warnings according to :\n + enable warnings in \n - disable warnings in \n @ enable warnings in and treat them as errors\n can be:\n a single warning number\n .. a range of consecutive warning numbers\n a predefined set\n default setting is \"+a-4-6-7-9-27-29-30-32..42-44-45-48-50-60-66-67\""; + + "-warn-error", + true, + " Enable or disable error status for warnings according\n to . See option -w for the syntax of .\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + " Treat as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + " (advanced, see manual section 9.2.)"; + + "-use-prims", + true, + " (undocumented)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-dinstr", + false, + " (undocumented)"; + + "-dcamlprimc", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into .dump"; + + "-args", + true, + " Read additional newline-terminated command line arguments\n from "; + + "-args0", + true, + " Read additional null character terminated command line arguments\nfrom "; + +];; + +let ocamloptp_spec = None;; + +let ocamlmklib_spec = Some [ + "-args", + true, + " Read additional newline-terminated command line arguments\n from "; + + "-args0", + true, + " Read additional null character terminated command line\n arguments from "; + + "-cclib", + true, + " C library passed to ocamlc -a or ocamlopt -a only"; + + "-ccopt", + true, + " C option passed to ocamlc -a or ocamlopt -a only"; + + "-custom", + false, + " Disable dynamic loading"; + + "-g", + false, + " Build with debug information"; + + "-dllpath", + true, + " Add to the run-time search path for DLLs"; + + "-F", + true, + " Specify a framework directory (MacOSX)"; + + "-framework", + true, + " Use framework (MacOSX)"; + + "-h", + false, + " Same as -help"; + + "-I", + true, + " Add to the path searched for OCaml object files"; + + "-failsafe", + false, + " fall back to static linking if DLL construction failed"; + + "-ldopt", + true, + " C option passed to the shared linker only"; + + "-linkall", + false, + " Build OCaml archive with link-all behavior"; + + "-l", + true, + " Specify a dependent C library"; + + "-L", + true, + " Add to the path searched for C libraries"; + + "-ocamlc", + true, + " Use in place of \"ocamlc\""; + + "-ocamlcflags", + true, + " Pass to ocamlc"; + + "-ocamlopt", + true, + " Use in place of \"ocamlopt\""; + + "-ocamloptflags", + true, + " Pass to ocamlopt"; + + "-o", + true, + " Generated OCaml library is named .cma or .cmxa"; + + "-oc", + true, + " Generated C library is named dll.so or lib.a"; + + "-require", + true, + " Add to the list of required OCaml libraries"; + + "-rpath", + true, + " Same as -dllpath "; + + "-R", + true, + " Same as -rpath"; + + "-verbose", + false, + " Print commands before executing them"; + + "-v", + false, + " same as -verbose"; + + "-version", + false, + " Print version and exit"; + + "-vnum", + false, + " Print version number and exit"; + + "-Wl,-rpath,", + true, + " Same as -dllpath "; + + "-Wl,-rpath", + false, + "-Wl, Same as -dllpath "; + + "-Wl,-R", + true, + " Same as -dllpath "; + +];; + +let ocamlmktop_spec = Some [ + "-a", + false, + " Build a library"; + + "-alert", + true, + " Enable or disable alerts according to :\n + enable alert \n - disable alert \n ++ treat as fatal error"; + + "--", + true, + " treat as non-fatal\n @ enable and treat it as fatal error\n can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-annot", + false, + " Save information in .annot"; + + "-assume-require", + true, + " for linking, assume is required and already looked up"; + + "-bin-annot", + false, + " Save typedtree in .cmt"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + " Use as the C compiler and linker"; + + "-cclib", + true, + " Pass option to the C linker"; + + "-ccopt", + true, + " Pass option to the C compiler and linker"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compat-32", + false, + " Check that generated bytecode can run on 32-bit platforms"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-custom", + false, + " Link in custom mode"; + + "-dllib", + true, + " Use the dynamically-loaded library "; + + "-dllpath", + true, + " Add to the run-time search path for shared libraries"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + " Generate code that can later be `packed' with\n ocamlc -pack -o .cmo"; + + "-g", + false, + " Save debugging information"; + + "-stop-after", + true, + "{parsing|typing} Stop after the given compilation pass."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + " Add to the list of include directories"; + + "-impl", + true, + " Compile as a .ml file"; + + "-intf", + true, + " Compile as a .mli file"; + + "-intf-suffix", + true, + " Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + " (deprecated) same as -intf-suffix"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-make-runtime", + false, + " Build a runtime system with given C objects and libraries"; + + "-make_runtime", + false, + " (deprecated) same as -make-runtime"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-check-prims", + false, + " Do not check runtime for primitives"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautoliblink", + false, + " Do not automatically link OCaml libraries specified in .cma files"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cma files"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nopervasives", + false, + " (undocumented)"; + + "-o", + true, + " Set output file name to "; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + " Opens the module before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-output-complete-exe", + false, + " Output a self-contained executable, including runtime and C stubs"; + + "-pack", + false, + " Package the given .cmo files into one .cmo"; + + "-pp", + true, + " Pipe sources through preprocessor "; + + "-ppx", + true, + " Pipe abstract syntax trees through preprocessor "; + + "-plugin", + true, + " (no longer supported)"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-require", + true, + " Add to the list of required libraries"; + + "-runtime-variant", + true, + " Use the variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-safe-string", + false, + " (was set when configuring the compiler)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-use-runtime", + true, + " Generate bytecode for the given runtime system"; + + "-use_runtime", + true, + " (deprecated) same as -use-runtime"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + " Enable or disable warnings according to :\n + enable warnings in \n - disable warnings in \n @ enable warnings in and treat them as errors\n can be:\n a single warning number\n .. a range of consecutive warning numbers\n a predefined set\n default setting is \"+a-4-6-7-9-27-29-30-32..42-44-45-48-50-60-66-67\""; + + "-warn-error", + true, + " Enable or disable error status for warnings according\n to . See option -w for the syntax of .\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + " Treat as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + " (advanced, see manual section 9.2.)"; + + "-use-prims", + true, + " (undocumented)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-dinstr", + false, + " (undocumented)"; + + "-dcamlprimc", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into .dump"; + + "-args", + true, + " Read additional newline-terminated command line arguments\n from "; + + "-args0", + true, + " Read additional null character terminated command line arguments\nfrom "; + + "-depend", + true, + " Compute dependencies (use 'ocamlc -depend -help' for details)"; + +];; + +let ocamlopt_spec = Some [ + "-fPIC", + false, + " Generate position-independent machine code (default)"; + + "-fno-PIC", + false, + " Generate position-dependent machine code"; + + "-a", + false, + " Build a library"; + + "-alert", + true, + " Enable or disable alerts according to :\n + enable alert \n - disable alert \n ++ treat as fatal error"; + + "--", + true, + " treat as non-fatal\n @ enable and treat it as fatal error\n can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-afl-instrument", + false, + "Enable instrumentation for afl-fuzz"; + + "-afl-inst-ratio", + false, + "Configure percentage of branches instrumented\n (advanced, see afl-fuzz docs for AFL_INST_RATIO)"; + + "-annot", + false, + " Save information in .annot"; + + "-assume-require", + true, + " for linking, assume is required and already looked up"; + + "-bin-annot", + false, + " Save typedtree in .cmt"; + + "-inline-branch-factor", + true, + "|=[,...] Estimate the probability of a branch being cold as 1/(1+n) (used for inlining) (default 0.10)"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + " Use as the C compiler and linker"; + + "-cclib", + true, + " Pass option to the C linker"; + + "-ccopt", + true, + " Pass option to the C compiler and linker"; + + "-clambda-checks", + false, + " Instrument clambda code with closure and field access checks (for debugging the compiler)"; + + "-Oclassic", + false, + " Make inlining decisions at function definition time rather than at the call site (replicates previous behaviour of the compiler)"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compact", + false, + " Optimize code size rather than speed"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + " Generate code that can later be `packed' with\n ocamlopt -pack -o .cmx"; + + "-g", + false, + " Record debugging information for exception backtrace"; + + "-function-sections", + false, + " Generate each function in a separate section if target supports it"; + + "-stop-after", + true, + "{parsing|typing|scheduling} Stop after the given compilation pass."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + " Add to the list of include directories"; + + "-impl", + true, + " Compile as a .ml file"; + + "-inline", + true, + "|=[,...] Aggressiveness of inlining (default 1.25, higher numbers mean more aggressive)"; + + "-inline-toplevel", + true, + "|=[,...] Aggressiveness of inlining at toplevel (higher numbers mean more aggressive)"; + + "-inline-alloc-cost", + true, + "|=[,...] The cost of not removing an allocation during inlining (default 7, higher numbers more costly)"; + + "-inline-branch-cost", + true, + "|=[,...] The cost of not removing a conditional during inlining (default 5, higher numbers more costly)"; + + "-inline-call-cost", + true, + "|=[,...] The cost of not removing a call during inlining (default 5, higher numbers more costly)"; + + "-inline-prim-cost", + true, + "|=[,...] The cost of not removing a primitive during inlining (default 3, higher numbers more costly)"; + + "-inline-indirect-cost", + true, + "|=[,...] The cost of not removing an indirect call during inlining (default 4, higher numbers more costly)"; + + "-inline-lifting-benefit", + true, + "|=[,...] The benefit of lifting definitions to toplevel during inlining (default 1300, higher numbers more beneficial)"; + + "-inlining-report", + false, + " Emit `..inlining' file(s) (one per round) showing the inliner's decisions"; + + "-insn-sched", + false, + " Run the instruction scheduling pass (default)"; + + "-intf", + true, + " Compile as a .mli file"; + + "-intf-suffix", + true, + " Suffix for interface files (default: .mli)"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-inline-max-depth", + true, + "|=[,...] Maximum depth of search for inlining opportunities inside inlined functions (default 1)"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-linscan", + false, + " Use the linear scan register allocator"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-float-const-prop", + false, + " Deactivate constant propagation for floating-point operations"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautoliblink", + false, + " Do not automatically link OCaml libraries specified in .cmxa files"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cmxa files"; + + "-nodynlink", + false, + " Enable optimizations for code that will not be dynlinked"; + + "-no-insn-sched", + false, + " Do not run the instruction scheduling pass"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nopervasives", + false, + " (undocumented)"; + + "-no-unbox-free-vars-of-closures", + false, + " Do not unbox variables that will appear inside function closures"; + + "-no-unbox-specialised-args", + false, + " Do not unbox arguments to which functions have been specialised"; + + "-o", + true, + " Set output file name to "; + + "-O2", + false, + " Apply increased optimization for speed"; + + "-O3", + false, + " Apply aggressive optimization for speed (may significantly increase code size and compilation time)"; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + " Opens the module before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-p", + false, + " (no longer supported)"; + + "-pack", + false, + " Package the given .cmx files into one .cmx"; + + "-plugin", + true, + " (no longer supported)"; + + "-pp", + true, + " Pipe sources through preprocessor "; + + "-ppx", + true, + " Pipe abstract syntax trees through preprocessor "; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-require", + true, + " Add to the list of required libraries"; + + "-remove-unused-arguments", + false, + " Remove unused function arguments"; + + "-rounds", + true, + " Repeat tree optimization and inlining phases this many times (default 1). Rounds are numbered starting from zero."; + + "-runtime-variant", + true, + " Use the variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-S", + false, + " Keep intermediate assembly file"; + + "-safe-string", + false, + " (was set when configuring the compiler)"; + + "-shared", + false, + " Produce a dynlinkable plugin"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unbox-closures", + false, + " Pass free variables via specialised arguments rather than closures"; + + "-unbox-closures-factor", + true, + " 0> Scale the size threshold above which unbox-closures will slow down indirect calls rather than duplicating a function (default 10)"; + + "-inline-max-unroll", + true, + "|=[,...] Unroll recursive functions at most this many times (default 0)"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + " Enable or disable warnings according to :\n + enable warnings in \n - disable warnings in \n @ enable warnings in and treat them as errors\n can be:\n a single warning number\n .. a range of consecutive warning numbers\n a predefined set\n default setting is \"+a-4-6-7-9-27-29-30-32..42-44-45-48-50-60-66-67\""; + + "-warn-error", + true, + " Enable or disable error status for warnings according\n to . See option -w for the syntax of .\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + " Treat as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + " (advanced, see manual section 9.2.)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-drawclambda", + false, + " (undocumented)"; + + "-dclambda", + false, + " (undocumented)"; + + "-dflambda", + false, + " Print Flambda terms"; + + "-drawflambda", + false, + " Print Flambda terms after closure conversion"; + + "-dflambda-invariants", + false, + " Check Flambda invariants around each pass"; + + "-dflambda-no-invariants", + false, + " Do not Check Flambda invariants around each pass"; + + "-dflambda-let", + true, + " Print when the given Flambda [Let] is created"; + + "-dflambda-verbose", + false, + " Print Flambda terms including around each pass"; + + "-dcmm", + false, + " (undocumented)"; + + "-dsel", + false, + " (undocumented)"; + + "-dcombine", + false, + " (undocumented)"; + + "-dcse", + false, + " (undocumented)"; + + "-dlive", + false, + " (undocumented)"; + + "-davail", + false, + " Print register availability info when printing liveness"; + + "-drunavail", + false, + " Run register availability pass (for testing only; needs -g)"; + + "-dspill", + false, + " (undocumented)"; + + "-dsplit", + false, + " (undocumented)"; + + "-dinterf", + false, + " (undocumented)"; + + "-dprefer", + false, + " (undocumented)"; + + "-dalloc", + false, + " (undocumented)"; + + "-dreload", + false, + " (undocumented)"; + + "-dscheduling", + false, + " (undocumented)"; + + "-dlinear", + false, + " (undocumented)"; + + "-dinterval", + false, + " (undocumented)"; + + "-dstartup", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into .dump"; + + "-dump-pass", + false, + " Record transformations performed by these passes:\n unbox-closures unbox-specialised-args unbox-free-vars-of-closures\n remove-free-vars-equal-to-args remove-unused-arguments unused-arguments"; + + "-args", + true, + " Read additional newline-terminated command line arguments\n from "; + + "-args0", + true, + " Read additional null character terminated command line arguments\nfrom "; + + "-depend", + true, + " Compute dependencies (use 'ocamlopt -depend -help' for details)"; + +];; + +let ocamldep_spec = Some [ + "-absname", + false, + " Show absolute filenames in error messages"; + + "-all", + false, + " Generate dependencies on all files"; + + "-allow-approx", + false, + " Fallback to a lexer-based approximation on unparsable files"; + + "-as-map", + false, + " Omit delayed dependencies for module aliases (-no-alias-deps -w -49)"; + + "-debug-map", + false, + " Dump the delayed dependency map for each map file"; + + "-I", + true, + " Add to the list of include directories"; + + "-impl", + true, + " Process as a .ml file"; + + "-intf", + true, + " Process as a .mli file"; + + "-map", + true, + " Read and propagate delayed dependencies to following files"; + + "-ml-synonym", + true, + " Consider as a synonym of the .ml extension"; + + "-mli-synonym", + true, + " Consider as a synonym of the .mli extension"; + + "-modules", + false, + " Print module dependencies in raw form (not suitable for make)"; + + "-native", + false, + " Generate dependencies for native-code only (no .cmo files)"; + + "-bytecode", + false, + " Generate dependencies for bytecode-code only (no .cmx files)"; + + "-one-line", + false, + " Output one line per file, regardless of the length"; + + "-open", + true, + " Opens the module before typing"; + + "-plugin", + true, + " (no longer supported)"; + + "-pp", + true, + " Pipe sources through preprocessor "; + + "-ppx", + true, + " Pipe abstract syntax trees through preprocessor "; + + "-require", + true, + " Add to the list of required libraries"; + + "-shared", + false, + " Generate dependencies for native plugin files (.cmxs targets)"; + + "-slash", + false, + " (Windows) Use forward slash / instead of backslash \\ in file paths"; + + "-sort", + false, + " Sort files according to their dependencies"; + + "-version", + false, + " Print version and exit"; + + "-vnum", + false, + " Print version number and exit"; + + "-args", + true, + " Read additional newline separated command line arguments \n from "; + + "-args0", + true, + " Read additional NUL separated command line arguments from \n "; + +];; + +let ocamldoc_spec = Some [ + "-absname", + false, + " Show absolute filenames in error messages"; + + "-alert", + true, + " Enable or disable alerts according to :\n + enable alert \n - disable alert \n ++ treat as fatal error"; + + "--", + true, + " treat as non-fatal\n @ enable and treat it as fatal error\n can be 'all' to refer to all alert names"; + + "-I", + true, + " Add to the list of include directories"; + + "-impl", + true, + " Compile as a .ml file"; + + "-intf", + true, + " Compile as a .mli file"; + + "-intf-suffix", + true, + " Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + " (deprecated) same as -intf-suffix"; + + "-labels", + false, + " Use commuting label mode"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-open", + true, + " Opens the module before typing"; + + "-pp", + true, + " Pipe sources through preprocessor "; + + "-ppx", + true, + " Pipe abstract syntax trees through preprocessor "; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-require", + true, + " Add to the list of required libraries"; + + "-safe-string", + false, + " (was set when configuring the compiler)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe-string", + false, + " (option not available)"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + " Enable or disable warnings according to :\n + enable warnings in \n - disable warnings in \n @ enable warnings in and treat them as errors\n can be:\n a single warning number\n .. a range of consecutive warning numbers\n a predefined set\n default setting is \"+a-4-6-7-9-27-29-30-32..42-44-45-48-50-60-66-67\""; + + "-", + true, + " Treat as a file name (even if it starts with `-')"; + + "-initially-opened-module", + true, + " Name of the module that is initially opened"; + + "-lib", + true, + " Name of the library namespace for a prefixed library.Note: very experimental."; + + "-text", + true, + " Consider as a .txt file"; + + "-warn-error", + false, + " Treat ocamldoc warnings as errors"; + + "-show-missed-crossref", + false, + " Show missed cross-reference opportunities"; + + "-hide-warnings", + false, + " do not print ocamldoc warnings"; + + "-o", + true, + " Set the output file name, used by texi, latex and dot generators\n\t\t(default is ocamldoc.out)\n\t\tor the prefix of index files for the HTML generator\n\t\t(default is index)"; + + "-d", + true, + " Generate files in directory , rather than in current\n\t\tdirectory (for man and HTML generators)"; + + "-sort", + false, + " Sort the list of top modules before generating the documentation"; + + "-no-stop", + false, + " Do not stop at (**/**) comments"; + + "-no-custom-tags", + false, + " Do not allow custom @-tags"; + + "-stars", + false, + " Remove beginning blanks of comment lines, until the first '*'"; + + "-inv-merge-ml-mli", + false, + " Inverse implementations and interfaces when merging"; + + "-no-module-constraint-filter", + false, + "Do not filter module elements using module type constraints"; + + "-keep-code", + false, + " Always keep code when available\n"; + + "-dump", + true, + " Dump collected information into "; + + "-load", + true, + " Load information from ; may be used several times\n"; + + "-t", + true, + " Use <title> as title for the generated documentation"; + + "-intro", + true, + "<file> Use content of <file> as ocamldoc text to use as introduction\n\t\t(HTML, LaTeX and TeXinfo only)"; + + "-hide", + true, + "<M1,M2.M3,...> Hide the given complete module names in generated doc"; + + "-m", + true, + "<options> specify merge options between .mli and .ml\n\t\t<options> can be one or more of the following characters:\n\t\td merge description\n\t\ta merge @author\n\t\tv merge @version\n\t\tl merge @see\n\t\ts merge @since\n\t\tb merge @before\n\t\to merge @deprecated\n\t\tp merge @param\n\t\te merge @raise\n\t\tr merge @return\n\t\tc merge custom @-tags\n\t\tA merge all\n\n *** choosing a generator ***\n"; + + "-html", + false, + " Generate HTML documentation"; + + "-latex", + false, + " Generate LaTeX documentation"; + + "-texi", + false, + " Generate TeXinfo documentation"; + + "-man", + false, + " Generate man pages"; + + "-dot", + false, + " Generate dot code of top modules dependencies"; + + "-customdir", + false, + "Display custom generators standard directory and exit"; + + "-i", + true, + "<dir> Add the given directory to the search path for custom\n\t\tgenerators"; + + "-g", + true, + "<file.cm[o|a|xs]> Load file defining a new documentation generator\n\n *** HTML options ***\n"; + + "-all-params", + false, + " Display the complete list of parameters for functions and\n\t\tmethods (HTML only)"; + + "-css-style", + true, + "<file> Use content of <file> as CSS style definition (HTML only)"; + + "-index-only", + false, + " Generate index files only (HTML only)"; + + "-colorize-code", + false, + " Colorize code even in documentation pages (HTML only)"; + + "-short-functors", + false, + " Use short form to display functor types (HTML only)"; + + "-charset", + true, + "<s> Add information about character encoding being s\n\t\t(default is iso-8859-1)\n\n *** LaTeX options ***\n"; + + "-noheader", + false, + " Suppress header in generated documentation\n\t\t(LaTeX and TeXinfo only)"; + + "-notrailer", + false, + " Suppress trailer in generated documentation\n\t\t(LaTeX and TeXinfo only)"; + + "-sepfiles", + false, + " Generate one file per toplevel module (LaTeX only)"; + + "-latextitle", + false, + "n,style Associate {n } to the given sectioning style\n\t\t(e.g. 'section') in the latex output (LaTeX only)\n\t\tDefault sectioning is:\n\t\t 0 -> section\n\t\t 1 -> section\n\t\t 2 -> subsection\n\t\t 3 -> subsubsection\n\t\t 4 -> paragraph\n\t\t 5 -> subparagraph"; + + "-latex-value-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of values.\n\t\t(default is \"val:\")"; + + "-latex-type-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of types.\n\t\t(default is \"type:\")"; + + "-latex-exception-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of exceptions.\n\t\t(default is \"exception:\")"; + + "-latex-attribute-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of attributes.\n\t\t(default is \"val:\")"; + + "-latex-method-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of methods.\n\t\t(default is \"method:\")"; + + "-latex-module-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of modules.\n\t\t(default is \"module:\")"; + + "-latex-module-type-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of module types.\n\t\t(default is \"moduletype:\")"; + + "-latex-class-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of classes.\n\t\t(default is \"class:\")"; + + "-latex-class-type-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of class types.\n\t\t(default is \"classtype:\")"; + + "-notoc", + false, + " Do not generate table of contents (LaTeX only)\n\n *** texinfo options ***\n"; + + "-noindex", + false, + " Do not build index for Info files (TeXinfo only)"; + + "-esc8", + false, + " Escape accentuated characters in Info files (TeXinfo only)"; + + "-texinfotitle", + false, + "n,style Associate {n } to the given sectioning style\n\t\t(e.g. 'section') in the texInfo output (TeXinfo only)\n\t\tDefault sectioning is:\n\t\t 0 -> @chapter , @majorheading \n\t\t 1 -> @chapter , @majorheading \n\t\t 2 -> @section , @heading \n\t\t 3 -> @subsection , @subheading \n\t\t 4 -> @subsubsection , @subsubheading "; + + "-info-section", + false, + " Specify section of Info directory (TeXinfo only)"; + + "-info-entry", + false, + " Specify Info directory entry (TeXinfo only)\n\n *** dot options ***\n"; + + "-dot-colors", + true, + " <c1,c2,...,cn>\n\t\tUse colors c1,c1,...,cn in the dot output\n\t\t(default list is darkturquoise,darkgoldenrod2,cyan,green,\n\t\tmagenta,yellow,burlywood1,aquamarine,floralwhite,lightpink,\n\t\tlightblue,mediumturquoise,salmon,slategray3)"; + + "-dot-include-all", + false, + " Include all modules in the dot output, not only the\n\t\tmodules given on the command line"; + + "-dot-types", + false, + " Generate dependency graph for types instead of modules"; + + "-dot-reduce", + false, + " Perform a transitive reduction on the selected dependency graph\n\t\tbefore the dot output\n\n *** man pages options ***\n"; + + "-man-mini", + false, + " Generate man pages only for modules, module types, classes\n\t\tand class types (man only)"; + + "-man-suffix", + true, + "<suffix> Use <suffix> for man page files (default is 3o) (man only)\n"; + + "-man-section", + true, + "<section> Use <section> in man page files (default is 3) (man only)\n"; + +];; + diff --git a/local-packages/ocamlfind/src/findlib/fl_package_base.ml b/local-packages/ocamlfind/src/findlib/fl_package_base.ml new file mode 100644 index 0000000..b81ec4e --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_package_base.ml @@ -0,0 +1,723 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +open Fl_metascanner + +exception No_such_package of string * string + (* (name, reason) *) + +type package = + { package_name : string; + package_dir : string; + package_meta : string; + package_defs : Fl_metascanner.pkg_definition list; + package_priv : package_priv + } +and package_priv = + { mutable missing_reqs : (string * string) list; + (* If non-empty the package is broken. This may be set by + add_all_relations, and should be checked before using the + package later. Each element corresponds to No_such_package. + *) + } +;; + + +module Fl_metaentry = + struct + type t = package + type id_t = string + let id m = m.package_name + end +;; + + +module Fl_metastore = + Fl_topo.Make(Fl_metaentry) +;; + + +module StringSet = Set.Make(String);; + + +let has_prefix s pref = + String.length s >= String.length pref && + String.sub s 0 (String.length pref) = pref +;; + + +let ocamlpath = ref [];; +let ocamlstdlib = ref "";; + +let conf_ignore_dups_in = ref ([] : string list) + +let store = Fl_metastore.create();; + (* We collect here only nodes, but no relations. First copy [store] + * and put relations into the copy. + *) + + +let init path stdlib ignore_dups_in = + ocamlpath := path; + ocamlstdlib := stdlib; + conf_ignore_dups_in := ignore_dups_in +;; + + +let packages_in_meta_file ?(directory_required = false) + ~name:package_name ~dir:package_dir ~meta_file () = + (* Parses the META file whose name is [meta_file]. In [package_name], the + * name of the main package must be passed. [package_dir] is the + * directory associated with the package by default (i.e. before + * it is overriden by the "directory" directive). + * + * directory_required: If true, a "directory" directive is necessary. + * + * Returns the [package] records found in this file. The "directory" + * directive is already applied. + *) + let rec flatten_meta pkg_name_prefix pkg_dir (pkg_name_component,pkg_expr) = + (* Turns the recursive [pkg_expr] into a flat list of [package]s. + * [pkg_dir] is the default package directory. [pkg_name_prefix] is + * the name prefix to prepend to the fully qualified package name, or + * "". [pkg_name_component] is the local package name. + *) + (* Determine the final package directory: *) + let d = + (* The value of "directory", or "" if not applicable *) + try + lookup "directory" [] pkg_expr.pkg_defs + with + Not_found -> + if pkg_name_prefix="" && directory_required then + failwith ("The `directory' directive is required in this META definition"); + + "" + in + let d' = + if d = "" then + pkg_dir + else + match d.[0] with + | '^' + | '+' -> + let rest = String.sub d 1 (String.length d - 1) in + if rest = "" then + !ocamlstdlib + else + Filename.concat !ocamlstdlib rest + | _ -> + if Filename.is_relative d then + Filename.concat pkg_dir d + else + d + in + let p_name = + if pkg_name_prefix = "" then + pkg_name_component + else + pkg_name_prefix ^ "." ^ pkg_name_component in + let p = + { package_name = p_name; + package_dir = d'; + package_meta = meta_file; + package_defs = pkg_expr.pkg_defs; + package_priv = { missing_reqs = [] } + } in + (* Check for exists_if: *) + let p_exists = + try + let def = + List.find (fun def -> def.def_var = "exists_if") p.package_defs in + let files = Fl_split.in_words def.def_value in + List.exists + (fun file -> Sys.file_exists (Filename.concat d' file)) + files + with Not_found -> true in + + if p_exists then + p :: (List.flatten + (List.map (flatten_meta p_name d') pkg_expr.pkg_children)) + else + [] + in + + let ch = open_in meta_file in + try + let pkg_expr = Fl_metascanner.parse ch in + let packages = flatten_meta "" package_dir (package_name, pkg_expr) in + close_in ch; + packages + with + Failure s -> + close_in ch; + failwith ("While parsing '" ^ meta_file ^ "': " ^ s) + | Fl_metascanner.Error s -> + close_in ch; + failwith ("While parsing '" ^ meta_file ^ "': " ^ s) + | any -> + close_in ch; + raise any +;; + + +let query package_name = + + let package_name_comps = Fl_split.package_name package_name in + if package_name_comps = [] then invalid_arg "Fl_package_base.query"; + let main_name = List.hd package_name_comps in + + let process_file_and_lookup ?directory_required package_dir meta_file = + let packages = + packages_in_meta_file + ?directory_required ~name:main_name ~dir:package_dir ~meta_file () in + let p = + ( try + List.find + (fun p -> p.package_name = package_name) + packages + with + Not_found -> + raise (No_such_package (package_name, "")) + ) in + List.iter (Fl_metastore.add store) packages; + p + in + + let rec run_ocamlpath path = + match path with + [] -> raise(No_such_package(package_name, "")) + | dir :: path' -> + let package_dir = Filename.concat dir main_name in + let meta_file_1 = Filename.concat package_dir "META" in + let meta_file_2 = Filename.concat dir ("META." ^ main_name) in + if Sys.file_exists meta_file_1 then + process_file_and_lookup package_dir meta_file_1 + else + if Sys.file_exists meta_file_2 then + process_file_and_lookup ~directory_required:true dir meta_file_2 + (* Note: It is allowed to have relative "directory" directives. + * The base directory is [dir] in this case. + *) + else + run_ocamlpath path' + in + + try + Fl_metastore.find store package_name + with + Not_found -> + run_ocamlpath !ocamlpath +;; + + +exception Package_loop of string + (* A package is required by itself. The arg is the name of the + * package + *) + + +let fixup_thread_needed_1 predlist = + (* When the thread fixup is required to apply, 1st criterion *) + List.mem "mt" predlist +;; + + +let fixup_thread_needed_2 pkg = + (* When the thread fixup is required to apply, 2nd criterion *) + (pkg <> "unix" && pkg <> "threads" && not (has_prefix pkg "threads.")) +;; + + +let fixup_thread_base predlist pkg = + (* Add the package "threads" if required *) + if fixup_thread_needed_1 predlist && fixup_thread_needed_2 pkg then + [ "threads" ] + else + [] +;; + + +let query_requirements ~preds:predlist package_name = + (* Part of [requires] implementation: Load all required packages, but + * do not add relations + *) + let m = query package_name in + (* may raise No_such_package *) + let r = + try Fl_metascanner.lookup "requires" predlist m.package_defs + with Not_found -> "" + in + let ancestors = Fl_split.in_words r @ + fixup_thread_base predlist package_name in + List.iter + (fun p -> + try + let _ = query p in (* may raise No_such_package *) + () + with + No_such_package(pname,_) -> + raise(No_such_package(pname, "required by `" ^ package_name ^ "'")) + ) + ancestors; + ancestors +;; + + +let add_relations s ancestors package_name = + (* Part of [requires] implementation: Adds the relations from [package_name] + * to [ancestors]. Target store is [s]. + *) + List.iter + (fun p -> + try + Fl_metastore.let_le s p package_name (* add relation *) + with + | Fl_topo.Inconsistent_ordering -> + raise(Package_loop p) + | Not_found -> + (* A relation to a package not part of [s]. We ignore it here. *) + () + ) + ancestors +;; + + +let add_all_relations predlist s = + (* Adds all relations for the packages currently defined in [s]. + Note that missing requirements are not reported immediately (we do + not know here which part of the graph [s] is really accessed), and + instead the error is added to the missing_reqs field, where + it should be checked before used. + *) + let pkgs = ref [] in + Fl_metastore.iter_up + (fun p -> pkgs := p :: !pkgs) + s; + + List.iter + (fun p -> + let pkg = p.package_name in + try + let pkg_ancestors = query_requirements predlist pkg in + add_relations s pkg_ancestors pkg + with + | No_such_package(n,reason) -> + p.package_priv.missing_reqs <- + (n,reason) :: p.package_priv.missing_reqs + ) + !pkgs +;; + + +let fixup_thread_deps s = + (* All packages (except "threads", "threads.*", and "unix") are made + * dependent on "threads" + *) + let pkgs = ref [] in + Fl_metastore.iter_up + (fun p -> pkgs := p.package_name :: !pkgs) + s; + + List.iter + (fun pkg -> + if fixup_thread_needed_2 pkg then ( + try + Fl_metastore.let_le s "threads" pkg (* add relation *) + with + Not_found -> + (* Because "threads" does not exist! Normally this is an + * error, because "threads" is also magically added by + * query_requirements. However, there are situations + * where it cannot be expected that required packages + * are loaded, so ignore this case. + *) + () + ) + ) + !pkgs +;; + + +let requires ~preds:predlist package_name = + (* returns names of packages required by [package_name], the fully qualified + * name of the package. It is checked that the packages really exist. + * [predlist]: list of true predicates + * May raise [No_such_package] or [Package_loop]. + *) + let ancestors = query_requirements predlist package_name in + let store' = Fl_metastore.copy store in (* work with a copy *) + add_relations store' ancestors package_name; + if List.mem "mt" predlist then fixup_thread_deps store'; + ancestors +;; + + +let requires_deeply ~preds:predlist package_list = + (* returns names of packages required by the packages in [package_list], + * either directly or indirectly. + * It is checked that the packages really exist. + * The list of names is sorted topologically; first comes the deepest + * ancestor. + * [predlist]: list of true predicates + * - raises [Not_found] if there is no 'package' + * - raises [Failure] if some of the ancestors do not exist + *) + + let pkgset = ref StringSet.empty in + + let rec query_packages pkglist = + match pkglist with + pkg :: pkglist' -> + if not(StringSet.mem pkg !pkgset) then begin + let pkg_ancestors = query_requirements predlist pkg in + pkgset := StringSet.add pkg !pkgset; + query_packages pkg_ancestors + end; + query_packages pkglist' + | [] -> + () + in + + (* First query for all packages, such that they are loaded: *) + query_packages package_list; + + (* Now make a copy of the store, and add the relations: *) + let store' = Fl_metastore.copy store in + add_all_relations predlist store'; + if List.mem "mt" predlist then fixup_thread_deps store'; + + (* Finally, iterate through the graph. Note that the graph may + * contain more members than required, so we have to test explicitly + * whether the packages are contained in pkgset. + *) + + let l = ref [] in + + Fl_metastore.iter_up_at + (fun m -> + if StringSet.mem m.package_name !pkgset then ( + if m.package_priv.missing_reqs <> [] then ( + let (n,reason) = List.hd m.package_priv.missing_reqs in + raise(No_such_package(n,reason)) + ); + l := m.package_name :: !l + ) + ) + store' + package_list; + + List.rev !l +;; + + +(**********************************************************************) + +(* The following two functions do not use !ocamlpath, because there may + * be duplicates in it. + *) + +let package_definitions ~search_path package_name = + (* Return all META files defining this [package_name] that occur in the + * directories mentioned in [search_path] + *) + + let package_name_comps = Fl_split.package_name package_name in + if package_name_comps = [] then invalid_arg "Fl_package_base.package_definitions"; + let main_name = List.hd package_name_comps in + + let rec run_ocamlpath path = + match path with + [] -> [] + | dir :: path' -> + let package_dir = Filename.concat dir main_name in + let meta_file_1 = Filename.concat package_dir "META" in + let meta_file_2 = Filename.concat dir ("META." ^ main_name) in + if Sys.file_exists meta_file_1 then + meta_file_1 :: run_ocamlpath path' + else + if Sys.file_exists meta_file_2 then + meta_file_2 :: run_ocamlpath path' + else + run_ocamlpath path' + in + run_ocamlpath search_path +;; + + +let in_report_search_path identify_dir d = + (* Whether package dir d is to be considered for generating reports. + d is sorted out when the ignore_dups_in option is set + *) + List.for_all + (fun id -> + try identify_dir d <> identify_dir id + with _ -> Fl_split.norm_dir d <> Fl_split.norm_dir id + ) + !conf_ignore_dups_in +;; + + +let package_conflict_report_1 identify_dir () = + let remove_dups_from_path p = + (* Removes directories which are physically the same from the path [p], + * and returns the shortened path + *) + + let dir_identity = Hashtbl.create 20 in + + let rec remove p = + match p with + d :: p' -> + begin try + let id = identify_dir d in (* may raise exceptions *) + if Hashtbl.mem dir_identity id then + remove p' + else begin + Hashtbl.add dir_identity id (); + d :: (remove p') + end + with error -> + (* Don't know anything, so the "directory" remains in the path *) + d :: (remove p') + end + | [] -> + [] + in + + remove p + in + + (* If we have ignore_dups_in this directory is removed from our search + path first + *) + let search_path0 = + List.filter (in_report_search_path identify_dir) !ocamlpath in + + (* Now eliminate all duplicates *) + let search_path = + remove_dups_from_path search_path0 in + + Fl_metastore.iter_up + (fun pkg -> + (* Check only main packages: *) + let package_name_comps = Fl_split.package_name pkg.package_name in + match package_name_comps with + [_] -> + (* pkg is a main package *) + ( let c = package_definitions search_path pkg.package_name in + match c with + [] + | [_] -> + () + | _ -> + Printf.eprintf "findlib: [WARNING] Package %s has multiple definitions in %s\n" + pkg.package_name + (String.concat ", " c) + ) + | _ -> + () + ) + store; + flush stderr +;; + + +let package_conflict_report ?identify_dir () = + match identify_dir with + None -> package_conflict_report_1 (fun s -> s) () + | Some f -> package_conflict_report_1 f () +;; + +let check_prefix ?prefix f = + match prefix with + | None -> true + | Some prefix -> + let len = String.length prefix in + String.length f >= len && String.sub f 0 len = prefix + +let load_base ?prefix () = + (* Ensures that the cache is completely filled with every package + * of the system that match prefix + *) + let list_directory d = + try + Array.to_list(Sys.readdir d) + with + Sys_error msg -> + prerr_endline ("findlib: [WARNING] cannot read directory " ^ msg); + [] + in + + let process_file ?directory_required main_name package_dir meta_file = + try + let _ = Fl_metastore.find store main_name in + (* Note: If the main package is already loaded into the graph, we + * do not even look at the subpackages! + *) + () + with + Not_found -> + let packages = + try + packages_in_meta_file + ?directory_required ~name:main_name ~dir:package_dir ~meta_file () + with + Failure s -> + prerr_endline ("findlib: [WARNING] " ^ s); [] + in + List.iter (Fl_metastore.add store) packages; + (* Nothing evil can happen! *) + in + + let rec run_ocamlpath path = + match path with + [] -> () + | dir :: path' -> + let files = list_directory dir in + List.iter + (fun f -> + if check_prefix ?prefix f + then + (* If f/META exists: Add package f *) + let package_dir = Filename.concat dir f in + let meta_file_1 = Filename.concat package_dir "META" in + if Sys.file_exists meta_file_1 then + process_file f package_dir meta_file_1 + else + (* If f is META.pkgname: Add package pkgname *) + (* We skip over filenames ending in '~' *) + if String.length f >= 6 && String.sub f 0 5 = "META." && + String.sub f (String.length f - 1) 1 <> "~" then begin + let name = String.sub f 5 (String.length f - 5) in + let meta_file_2 = Filename.concat dir f in + process_file ~directory_required:true name dir meta_file_2 + end; + ) + files; + run_ocamlpath path' + in + + run_ocamlpath !ocamlpath +;; + + +let list_packages ?prefix () = + load_base ?prefix (); + + let l = ref [] in + + Fl_metastore.iter_up + (fun m -> + if check_prefix ?prefix m.package_name then + l := m.package_name :: !l + ) + store; + + !l +;; + + +let package_users ~preds pl = + (* Check that all packages in [pl] really exist, or raise No_such_package: *) + List.iter + (fun p -> let _ = query p in ()) + pl; + load_base(); + let store' = Fl_metastore.copy store in + add_all_relations preds store'; + if List.mem "mt" preds then fixup_thread_deps store'; + + let l = ref [] in + + Fl_metastore.iter_down_at + (fun m -> + if m.package_priv.missing_reqs <> [] then ( + let (n,reason) = List.hd m.package_priv.missing_reqs in + raise(No_such_package(n,reason)) + ); + l := m.package_name :: !l + ) + store' + pl; + + !l +;; + + +let module_conflict_report_1 identify_dir incpath = + (* Find any *.cmi files occurring twice in incpath. + *) + let dir_of_module = Hashtbl.create 100 in + let dirs = ref [] in + + let examine_dir d = + try + let d = Fl_split.norm_dir d in + let d_id = identify_dir d in + + (* Is d new? *) + if not (List.mem d_id !dirs) then begin + dirs := d_id :: !dirs; + (* Yes: Get all files ending in .cmi *) + try + let d_all = Array.to_list(Sys.readdir d) in (* or Sys_error *) + let d_cmi = + List.filter + (fun n -> Filename.check_suffix n ".cmi") + d_all in + (* Add the modules to dir_of_module: *) + List.iter + (fun m -> + try + let entry = Hashtbl.find dir_of_module m in (* or Not_found *) + entry := d :: !entry + with + Not_found -> + Hashtbl.add dir_of_module m (ref [d]) + ) + d_cmi + with + Sys_error msg -> + prerr_endline ("findlib: [WARNING] cannot read directory " ^ msg) + end + with + | _ -> () (* identify_dir fails *) + in + + let print_report() = + Hashtbl.iter + (fun m dlist -> + match !dlist with + [] + | [_] -> + () + | _ -> + Printf.eprintf "findlib: [WARNING] Interface %s occurs in several directories: %s\n" + m + (String.concat ", " !dlist) + ) + dir_of_module + in + + (* If we have ignore_dups_in this directory is removed from our search + path first + *) + let incpath1 = + List.filter (in_report_search_path identify_dir) incpath in + + + List.iter examine_dir incpath1; + + print_report(); + flush stderr +;; + + +let module_conflict_report ?identify_dir incpath = + match identify_dir with + None -> module_conflict_report_1 (fun s -> s) incpath + | Some f -> module_conflict_report_1 f incpath +;; diff --git a/local-packages/ocamlfind/src/findlib/fl_package_base.mli b/local-packages/ocamlfind/src/findlib/fl_package_base.mli new file mode 100644 index 0000000..3e54b8a --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_package_base.mli @@ -0,0 +1,181 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(** Direct access to the package graph and package files *) + +type package = + { package_name : string; + (** The fully qualified package name, i.e. for subpackages the + * names of the containing packages are prepended and the name + * components are separated by '.' + *) + package_dir : string; + (** The directory where to lookup package files *) + package_meta : string; + (** The path to the META file *) + package_defs : Fl_metascanner.pkg_definition list; + (** The definitions in the META file *) + package_priv : package_priv; + (** Private part of the definition *) + } + (** The definition of a package *) + +and package_priv + + +val init : string list -> string -> string list -> unit + (** This function must be called before [Fl_package_base] can be used. + * The first string corresponds to the [OCAMLPATH] setting, the second + * string is the location of the standard library. The second is the + * list of directories with ignored duplicate cmi files. + * + * This function is called by {!Findlib.init} and {!Findlib.init_manually}, + * so it is already sufficient to initialize the [Findlib] module. + *) + + +(** {1 The package graph} *) + +(** The functions in this section operate on a representation of the + * package graph in memory. The graph is usually only partially available, + * as only packages are loaded that are queried for. + *) + + +exception No_such_package of string * string + (** First arg is the package name not found, second arg contains additional + * info for the user. - This is the same exception as in [Findlib]. + *) + +exception Package_loop of string + (** A package is required by itself. The arg is the name of the + * package. - This is the same exception as in [Findlib]. + *) + +val query : string -> package + (** Returns the [package] definition for the fully-qualified package name, + * or raises [No_such_package]. It is allowed to query for subpackages. + * + * This function loads package definitions into the graph kept in memory. + *) + +val requires : preds:string list -> string -> string list + (** Analyzes the direct requirements of the package whose name is passed as + * second argument under the assumption that the predicates [preds] + * hold. The function returns the names of the required packages. + * It is checked whether these packages exist. + * + * If there is the "mt" predicate, missing dependencies on "threads" + * are silently added. + * + * The function may raise [No_such_package] or [Package_loop]. + * + * This function loads package definitions into the graph kept in memory. + *) + +val requires_deeply : preds:string list -> string list -> string list + (** Analyzes the direct or indirect requirements of the packages whose names + * are passed as second argument under the assumption that the predicates + * [preds] hold. The function returns the names of the required packages. + * It is checked whether these packages exist. + * + * If there is the "mt" predicate, missing dependencies on "threads" + * are silently added. + * + * The function may raise [No_such_package] or [Package_loop]. + * + * This function loads package definitions into the graph kept in memory. + *) + +val package_conflict_report : + ?identify_dir:(string -> 'a) -> unit -> unit + (** Checks whether there are several META files for the same main + * packages. Complaints are printed to stderr. + * + * Only packages in the loaded part of the package graph are checked (i.e. + * packages for which there was a query). + * + * It is recommended to pass the ~identify_dir function whose task + * it is to return a unique value for every existing directory. + * For example, + * {[ fun d -> + * let s = Unix.stat d in + * (s.Unix.st_dev, s.Unix.st_ino) + * ]} + * could be an implementation for this function. The default is + * the identity (and not this nice implementation to avoid dependencies + * on the Unix module). + *) + +val module_conflict_report : ?identify_dir:(string -> 'a) -> string list -> unit + (** Checks whether there are cmi files for the same modules. The + * directories passed as first argument are checked. (Note: + * Neither the '+' nor the '@' notation are recognized.) + * Complaints about double cmi files are printed to stderr. + * + * @param identify_dir See [package_conflict_report]. + *) + +val load_base : ?prefix:string -> unit -> unit + (** Ensures that the complete package graph is loaded into memory. + * This is a time-consuming operation. Warnings may be printed to + * stderr. + * + * @param prefix Limit to the packages that starts with it. Default: unlimited + *) + +val list_packages : ?prefix:string -> unit -> string list + (** Ensures that the complete package graph is loaded into memory + * (like [load_base]), and returns the (unsorted) list of all + * packages. + * + * @param prefix Limit to the packages that starts with it. Default: unlimited + *) + +val package_users : preds:string list -> string list -> string list + (** Ensures that the complete package graph is loaded into memory + * (like [load_base]), and determines the packages using one of + * the packages passed as second argument. The [preds] are assumed + * for the evaluation of the [requires] directives. + * The returned list is sorted in ascending order. + * + * If there is the "mt" predicate, missing dependencies on "threads" + * are silently added. + * + * Raises [No_such_package] if one of the passed packages cannot + * be found. + *) + + +(** {1 Parsing META files} *) + +(** The functions in this section access directly files and directories. + * The package graph is unknown. + *) + +val packages_in_meta_file : + ?directory_required:bool -> + name:string -> dir:string -> meta_file:string -> unit -> package list + (** Parses the META file whose name is [meta_file]. In [name], the + * name of the main package must be passed. [dir] is the + * directory associated with the package by default (i.e. before + * it is overriden by the "directory" directive). + * + * Returns the package records found in this file. The "directory" + * directive is already applied. + * + * @param directory_required If true, it is checked whether there is a + * "directory" directive in the main package. If this directive is missing, + * the function will fail. + *) + +val package_definitions : search_path:string list -> string -> string list + (** Return all META files defining this package that occur in the + * directories mentioned in [search_path]. The package name must be + * fully-qualified. For simplicity, however, only the name of the main + * package is taken into account (so it is a good idea to call this + * function only for main packages). + *) + diff --git a/local-packages/ocamlfind/src/findlib/fl_split.ml b/local-packages/ocamlfind/src/findlib/fl_split.ml new file mode 100644 index 0000000..8600458 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_split.ml @@ -0,0 +1,146 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + + +let in_words s = + (* splits s in words separated by commas and/or whitespace *) + let l = String.length s in + let rec split i j = + if j < l then + match s.[j] with + (' '|'\t'|'\n'|'\r'|',') -> + if i<j then (String.sub s i (j-i)) :: (split (j+1) (j+1)) + else split (j+1) (j+1) + | _ -> + split i (j+1) + else + if i<j then [ String.sub s i (j-i) ] else [] + in + split 0 0 +;; + + +let in_words_ws s = + (* splits s in words separated by whitespace *) + let l = String.length s in + let rec split i j = + if j < l then + match s.[j] with + (' '|'\t'|'\n'|'\r') -> + if i<j then (String.sub s i (j-i)) :: (split (j+1) (j+1)) + else split (j+1) (j+1) + | _ -> + split i (j+1) + else + if i<j then [ String.sub s i (j-i) ] else [] + in + split 0 0 +;; + + +let package_name s = + (* splits s in words separated by dots. + * As a special case, when s="." the package "." is returned. + *) + let l = String.length s in + let rec split i j = + if j < l then + match s.[j] with + '.' -> + if i<j then (String.sub s i (j-i)) :: (split (j+1) (j+1)) + else split (j+1) (j+1) + | _ -> + split i (j+1) + else + if i<j then [ String.sub s i (j-i) ] else [] + in + if s="." then + ["."] + else + split 0 0 +;; + + +let is_valid_package_name s = + (* Use this only for installation/deinstallation of packages! *) + not(String.contains s '.') +;; + + +let path_separator = + match Sys.os_type with + | "Unix" | "BeOS" -> ':' + | "Cygwin" -> ';' (* You might want to change this *) + | "Win32" -> ';' + | "MacOS" -> failwith "Findlib: I do not know what is the correct path separator for MacOS. If you can help me, write a mail to gerd@gerd-stolpmann.de" + | _ -> failwith "Findlib: unknown operating system" +;; + + +let path str = + (* split "str" into parts separated by "path_separator" *) + let l = String.length str in + let rec split_up j k = + if k < l then begin + let c = str.[k] in + if c = path_separator then begin + if k - j > 0 then + String.sub str j (k-j) :: split_up (k+1) (k+1) + else + split_up (k+1) (k+1) + end + else + split_up j (k+1) + end + else + if k - j > 0 then + [ String.sub str j (k-j) ] + else + [] + in + split_up 0 0 +;; + + +let norm_dir s = + (* Converts the file name of the directory [d] to the normal form. + * For Unix, the '/' characters at the end are removed, and multiple + * '/' are deleted. + * For Windows, all '/' characters are converted to '\'. Two + * backslashes at the beginning are tolerated. + *) + let b = Buffer.create 80 in + let l = String.length s in + let norm_dir_unix() = + Buffer.add_char b s.[0]; + for k = 1 to l - 1 do + let c = s.[k] in + if not ((c = '/' && s.[k-1] = '/') || (c = '/' && k = l-1)) then + Buffer.add_char b c + done + in + let is_slash = + function + | '/' | '\\' -> true + | _ -> false in + let norm_dir_win() = + if l >= 1 && s.[0] = '/' then + Buffer.add_char b '\\' else Buffer.add_char b s.[0]; + if l >= 2 && s.[1] = '/' then + Buffer.add_char b '\\' else Buffer.add_char b s.[1]; + for k = 2 to l - 1 do + let c = s.[k] in + if is_slash c then ( + if not (is_slash s.[k-1] || k = l-1) then + Buffer.add_char b '\\' + ) else + Buffer.add_char b c + done + in + match Sys.os_type with + "Unix" | "BeOS" | "Cygwin" -> norm_dir_unix(); Buffer.contents b + | "Win32" -> norm_dir_win(); Buffer.contents b + | _ -> failwith "This os_type is not supported" +;; diff --git a/local-packages/ocamlfind/src/findlib/fl_topo.ml b/local-packages/ocamlfind/src/findlib/fl_topo.ml new file mode 100644 index 0000000..aa291fa --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_topo.ml @@ -0,0 +1,344 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(* TODO: + * - Use a hashtable in 'find' + * - implement le_than with an 'iter' like method + *) + + +(**********************************************************************) + + +module type IdentifiedType = + sig + type t + type id_t + val id : t -> id_t + end + +exception Inconsistent_ordering + +module type S = + sig + type key + type el_t + type t + val create : unit -> t + val add : t -> el_t -> unit + val let_le : t -> key -> key -> unit + val find : t -> key -> el_t + val le_than : t -> key -> key -> bool + val key : el_t -> key + val iter_up : (el_t -> unit) -> t -> unit + val iter_down : (el_t -> unit) -> t -> unit + val iter_up_at : (el_t -> unit) -> t -> key list -> unit + val iter_down_at : (el_t -> unit) -> t -> key list -> unit + + val clear : t -> unit + val replace : t -> key -> el_t -> unit + val delete : t -> key -> unit + + val copy : t -> t + end + + +(**********************************************************************) + +module Make(H: IdentifiedType) = + struct + + type key = H.id_t + + type el_t = H.t + + type 'a node = + { mutable content : 'a; + mutable smaller : 'a node list; + mutable bigger : 'a node list; + mutable mark : bool; (* used in 'iter' *) + (* mutable ppmark : bool *) (* used in 'private_property' *) + } + + type t = + { mutable cnt : el_t node list; + mutable lock : bool + } + + let copy ord = + (* This operation is quite expensive when the graph has already + * relations. In findlib, this case is avoided, and is here only + * implemented for completeness. + *) + let ord' = + { cnt = List.map (fun n -> { n with + smaller = []; + bigger = []; + mark = false }) ord.cnt; + lock = false + } in + let combined_list = List.combine ord.cnt ord'.cnt in + let lookup_node n = + (* Find the new node corresponding to old node n *) + try List.assq n combined_list + with Not_found -> assert false + in + List.iter2 + (fun n n' -> + (* n: old node, n': new node *) + let smaller = List.map lookup_node n.smaller in + let bigger = List.map lookup_node n.bigger in + n'.smaller <- smaller; + n'.bigger <- bigger; + ) + ord.cnt + ord'.cnt; + ord' + + + let rec delete_all p l = + match l with + x::l' -> + if p x then delete_all p l' else x :: delete_all p l' + | [] -> [] + + + (******************************************************************) + + let create () = { cnt = []; lock = false } + + let clear ordering = + ordering.cnt <- []; + ordering.lock <- false + + (******************************************************************) + + let add ordering x = + (* Is there already a node with the same key? *) + let k = H.id x in + if List.exists (fun y -> H.id y.content = k) ordering.cnt then + raise Inconsistent_ordering; + + (* Ok, add the node to the list *) + let nx = { content = x; + smaller = []; + bigger = []; + mark = false + } in + ordering.cnt <- nx :: ordering.cnt + + + (******************************************************************) + + let find_node ordering kx = + let rec search l = + match l with + [] -> raise Not_found + | y :: l' -> if H.id y.content = kx then y else search l' + in + search ordering.cnt + + + let find ordering kx = (find_node ordering kx).content + + (******************************************************************) + + let replace ordering kx x' = + let x = find_node ordering kx in + x.content <- x' + + (******************************************************************) + + let delete ordering kx = + let x = find_node ordering kx in + ordering.cnt <- delete_all (fun a -> a == x) ordering.cnt; + List.iter + (fun x -> + x.smaller <- delete_all (fun a -> a == x) x.smaller; + x.bigger <- delete_all (fun a -> a == x) x.bigger) + ordering.cnt + + + (******************************************************************) + + let le_than ordering kx ky = + (* Find x, y: *) + let x = find_node ordering kx in + let y = find_node ordering ky in + + let rec search x1 = + if x1 == y then + true + else + List.exists search x1.bigger + + in + search x + + (******************************************************************) + + let let_le ordering kx ky = + (* Find x, y: *) + let x = find_node ordering kx in + let y = find_node ordering ky in + + (* If already done just return (this is an idempotent function) *) + if not (List.memq x y.smaller) then begin + + (* let x <= y. This is only allowed if not (y <= x) *) + if le_than ordering ky kx then + raise Inconsistent_ordering; + + (* Ok, add the relation *) + x.bigger <- y :: x.bigger; + y.smaller <- x :: y.smaller + end + + (******************************************************************) + + let key x = H.id x + + (******************************************************************) + + let iter upwards f ordering = + + let in_direction n = + if upwards then n.bigger else n.smaller in + + let against_direction n = + if upwards then n.smaller else n.bigger in + + (* the following is written as if for iter_up. *) + + let rec find_biggest ordlist = + (* find biggest, non-marked node *) + match ordlist with + [] -> raise Not_found + | nx :: ordlist' -> if not nx.mark && in_direction nx = [] + then nx + else find_biggest ordlist' + in + + let rec run_up n = + (* iterate over all nodes <= x and return their number *) + + let rec run_up_list l = + match l with + [] -> 0 + | x :: l' -> run_up x + run_up_list l' + in + + if n.mark then + (* have already visited this node *) + 0 + else + let u = run_up_list (against_direction n) in + n.mark <- true; + f n.content; + u + 1 + in + + (* Lock *) + if ordering.lock then + failwith "iter_up: recursive application not allowed"; + ordering.lock <- true; + + (* clear all marks *) + List.iter (fun nx -> nx.mark <- false) ordering.cnt; + + (* Catch exceptions *) + + try + (* while there is a biggest node... *) + let c = ref 0 in (* counter *) + while !c < List.length ordering.cnt do + + (* Find a biggest node *) + let n_biggest = find_biggest ordering.cnt in + + (* run through the graph *) + c := !c + run_up n_biggest + + done; + + (* unlock *) + ordering.lock <- false + + with + any -> (* unlock, too *) + ordering.lock <- false; + raise any + + + let iter_up = iter true + let iter_down = iter false + + + (******************************************************************) + + let iter_at upwards f ordering startpoints = + +(* + let in_direction n = + if upwards then n.bigger else n.smaller in + *) + + let against_direction n = + if upwards then n.smaller else n.bigger in + + (* the following is written as if for iter_up. *) + + let rec run_up n = + (* iterate over all nodes <= x and return their number *) + + let rec run_up_list l = + match l with + [] -> 0 + | x :: l' -> run_up x + run_up_list l' + in + + if n.mark then + (* have already visited this node *) + 0 + else + let u = run_up_list (against_direction n) in + n.mark <- true; + f n.content; + u + 1 + in + + (* Lock *) + if ordering.lock then + failwith "iter_up: recursive application not allowed"; + ordering.lock <- true; + + (* clear all marks *) + List.iter (fun nx -> nx.mark <- false) ordering.cnt; + + (* Catch exceptions *) + + try + + List.iter + (fun start -> + let _ = run_up (find_node ordering start) in ()) + startpoints; + + (* unlock *) + ordering.lock <- false + + with + any -> (* unlock, too *) + ordering.lock <- false; + raise any + + + let iter_up_at = iter_at true + let iter_down_at = iter_at false + + + (******************************************************************) + + end diff --git a/local-packages/ocamlfind/src/findlib/fl_topo.mli b/local-packages/ocamlfind/src/findlib/fl_topo.mli new file mode 100644 index 0000000..aaf1782 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/fl_topo.mli @@ -0,0 +1,42 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(* The type topo.t is a partially ordered relation. You can add an element + * by giving all descendents ... + *) + +module type IdentifiedType = + sig + type t + type id_t + val id : t -> id_t + end + +exception Inconsistent_ordering + +module type S = + sig + type key + type el_t + type t + val create : unit -> t + val add : t -> el_t -> unit + val let_le : t -> key -> key -> unit + val find : t -> key -> el_t + val le_than : t -> key -> key -> bool + val key : el_t -> key + val iter_up : (el_t -> unit) -> t -> unit + val iter_down : (el_t -> unit) -> t -> unit + val iter_up_at : (el_t -> unit) -> t -> key list -> unit + val iter_down_at : (el_t -> unit) -> t -> key list -> unit + val clear : t -> unit + val replace : t -> key -> el_t -> unit + val delete : t -> key -> unit + val copy : t -> t + end + +module Make(H: IdentifiedType): + (S with type el_t = H.t + and type key = H.id_t) diff --git a/local-packages/ocamlfind/src/findlib/frontend.ml b/local-packages/ocamlfind/src/findlib/frontend.ml new file mode 100644 index 0000000..983f74b --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/frontend.ml @@ -0,0 +1,2683 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +open Findlib;; + +exception Usage;; +exception Silent_error;; + +type mode = + M_use | M_query | M_install | M_remove | M_compiler of string | M_dep + | M_printconf | M_list | M_browser | M_call of (string*string) + | M_doc | M_lint | M_printppx +;; + + +type psubst = + Const of string + | Percent of string * modifier + | Lookup of string * modifier + +and modifier = + | Plain + | Plus +;; + +let sys_error code arg = + if arg = "" then + Sys_error (Unix.error_message code) + else + Sys_error (arg ^ ": " ^ Unix.error_message code) + + +let slashify s = + match Findlib_config.system with + | "mingw" | "mingw64" | "cygwin" -> + let b = Buffer.create 80 in + String.iter + (function + | '\\' -> Buffer.add_char b '/' + | c -> Buffer.add_char b c + ) + s; + Buffer.contents b + | _ -> + s + + +let out_path ?(prefix="") s = + match Findlib_config.system with + | "mingw" | "mingw64" | "cygwin" -> + let u = slashify s in + prefix ^ + (if String.contains u ' ' then + (* Desperate attempt to fix the space problem in paths. + Note that we invoke commands via Unix.open_process, and + this function already quotes the arguments on win32. + However, for -ccopt arguments, one quoting level seems + to be lost, and we have to add another level to compensate. + E.g. for the list of args + [ -ccopt; -L/my programs/include -L/somewhere ] + we get after out_path + [ -ccopt; "-I/my programs/include -L/somewhere" ] + which actually translates to + -ccopt "\"-I/my programs/include\" \"-L/somewhere\"" + on the command line, i.e. a double-quoted argument. + *) + "\"" ^ u ^ "\"" + else + u + ) + | _ -> + prefix ^ slashify s + + + +let percent_subst ?base spec lookup s = + (* spec = [ "%c", [ "ctext1"; "ctext2"; ... ]; + * "%d", [ "dtext1"; "dtext2"; ... ] ] + * All occurrences of %c in the string s are replaced as specified in spec. + * spec is an association list with the %-notation as keys + * and lists of strings as values. The result is a list of strings containing + * every combination of substituted values. + * + * Support for the %(name) syntax: In this case, the name is taken as + * key for the [lookup] function, which either returns the string value + * or raises Not_found. + * + * "+" modifier: A "+" after "%" causes that Findlib.resolve_path is + * called for the substitution string (e.g. %+c, %+(name)). + * + * Example: + * spec = [ "%a", [ "file1" ] ] + * lookup = function "archive" -> "file2" | _ -> raise Not_found + * Here, %a is substituted by file1, and %(archive) is substituted by + * file2. + * + * ?base: The base parameter for Findlib.resolve_path. + *) + let l = String.length s in + + let fail() = + failwith "bad format string" in + + let parenthesized_name j = + try + if j+1>=l then raise Not_found; + let k = String.index_from s (j+1) ')' in + let name = String.sub s (j+1) (k-j-1) in + (name, k+1) + with Not_found -> + fail() in + + let rec preprocess i j = + if j<l then begin + match s.[j] with + '%' -> + if j+1<l then begin + let prev = Const(String.sub s i (j-i)) in + let c = s.[j+1] in + match c with + '%' -> + prev :: Const "%" :: preprocess (j+2) (j+2) + | '(' -> + let name, j_next = parenthesized_name (j+1) in + prev :: Lookup(name,Plain) :: preprocess j_next j_next + | '+' -> + if j+2<l then begin + let c = s.[j+2] in + match c with + | '%' | '+' -> fail() + | '(' -> + let name, j_next = parenthesized_name (j+2) in + prev :: Lookup(name,Plus) :: preprocess j_next j_next + | _ -> + let name = "%" ^ String.make 1 c in + prev :: Percent(name,Plus) :: preprocess (j+3) (j+3) + end + else fail() + | _ -> + let name = "%" ^ String.make 1 c in + prev :: Percent(name,Plain) :: preprocess (j+2) (j+2) + end + else fail() + | _ -> + preprocess i (j+1) + end + else + if i<j then + [Const(String.sub s i (j-i))] + else + [] + in + + let plus_subst u = + String.concat + " " + (List.map + (Findlib.resolve_path ?base) + (Fl_split.in_words u)) in + + let any_subst modi u = + match modi with + | Plain -> u + | Plus -> plus_subst u in + + let rec subst prefix l = + match l with + [] -> [prefix] + | Const s :: l' -> + subst (prefix ^ s) l' + | Percent(name,modi) :: l' -> + let replacements0 = + try List.assoc name spec + with Not_found -> failwith "bad format string" in + let replacements = + List.map (any_subst modi) replacements0 in + List.flatten + (List.map + (fun replacement -> + subst (prefix ^ replacement) l') + replacements) + | Lookup(name,modi) :: l' -> + let replacement0 = + try lookup name + with Not_found -> "" in + let replacement = + any_subst modi replacement0 in + subst (prefix ^ replacement) l' + in + + subst "" (preprocess 0 0) +;; + + +let rec remove_dups l = + match l with + x :: l' -> + if List.mem x l' then remove_dups l' else x::remove_dups l' + | [] -> [] +;; + + +let arg n = + if n < Array.length Sys.argv then Sys.argv.(n) else raise Not_found +;; + + +let escape_if_needed s = + if String.contains s ' ' then "\"" ^ String.escaped s ^ "\"" else s +;; + + +let use_package prefix pkgnames = + (* may raise No_such_package *) + let pdirs = + List.map + (fun pname -> + "-I " ^ out_path(package_directory pname) + ) + pkgnames + in + + print_endline (prefix ^ String.concat " " pdirs) +;; + + +let read_ldconf filename = + let lines = ref [] in + let f = open_in filename in + try + while true do + let line = input_line f in + if line <> "" then + lines := line :: !lines + done; + assert false + with + End_of_file -> + close_in f; + List.rev !lines + | other -> + close_in f; + raise other +;; + + +let write_ldconf filename lines new_lines = + let f = open_out filename in + try + List.iter + (fun line -> output_string f (line ^ "\n")) + (lines @ new_lines); + close_out f; + prerr_endline("Updated " ^ filename); + with + Sys_error e -> + prerr_endline ("ocamlfind: [WARNING] Cannot write " ^ filename); + prerr_endline ("Reason: " ^ e); + prerr_endline ("This file contains the directories with DLLs."); + if new_lines <> [] then begin + prerr_endline ("It is recommended to add the following line(s) to this file:"); + List.iter prerr_endline new_lines + end +;; + + +let is_dll p = + let sfx = Findlib_config.dll_suffix in + sfx <> "" && Filename.check_suffix p sfx +;; + + +let identify_dir d = + match Sys.os_type with + | "Win32" -> + failwith "identify_dir" (* not available *) + | _ -> + let s = Unix.stat d in + (s.Unix.st_dev, s.Unix.st_ino) +;; + + +let conflict_report incpath pkglist = + (* Check whether there are several definitions for packages + * in the current path. We remove duplicate directories first. + * Note that all other checks are not sensitive to duplicate directories. + *) + Fl_package_base.package_conflict_report ~identify_dir (); + + (* Second check whether there are module conflicts *) + let pkgpath = + List.map Findlib.package_directory pkglist in + Fl_package_base.module_conflict_report ~identify_dir (pkgpath @ incpath); + + (* Finally check whether there are multiple DLLs: *) + (* Note: Only the directories mentioned in ld.conf are checked, but not the + * directories in [incpath], and not the directories in CAML_LD_LIBRARY_PATH. + * The idea of this check is to ensure a proper installation, and not to + * complain about the user's special configuration. + *) + let ldconf = ocaml_ldconf() in + if ldconf <> "ignore" then begin + let dll_dirs = remove_dups (read_ldconf ldconf) in + let dll_pairs = + List.flatten + (List.map + (fun dll_dir -> + let files = + try Array.to_list (Sys.readdir dll_dir) + with _ -> + prerr_endline ("ocamlfind: [WARNING] Cannot read directory " ^ + dll_dir ^ " which is mentioned in ld.conf"); + [] + in + List.map + (fun file -> (file, dll_dir)) + (List.filter is_dll files) + ) + dll_dirs + ) in + let dll_hash = Hashtbl.create 50 in + List.iter + (fun (file, dll_dir) -> Hashtbl.add dll_hash file dll_dir) + dll_pairs; + Hashtbl.iter + (fun file dll_dir -> + let locations = Hashtbl.find_all dll_hash file in + if List.length locations > 1 then begin + prerr_endline ("ocamlfind: [WARNING] The DLL " ^ file ^ + " occurs in multiple directories: " ^ dll_dir) + end + ) + dll_hash + end +;; + + +let check_package_list l = + (* may raise No_such_package *) + List.iter + (fun pkg -> + let _ = package_directory pkg in + () + ) + l +;; + + +type verbosity = + | Normal + | Verbose + | Only_show + + +let run_command ?filter verbose cmd args = + let printable_cmd = + cmd ^ " " ^ String.concat " " (List.map escape_if_needed args) in + ( match verbose with + | Normal -> + () + | Verbose -> + print_endline ("+ " ^ printable_cmd); + if filter <> None then + print_string + (" (output of this command is filtered by ocamlfind)\n") + | Only_show -> + print_endline printable_cmd + ); + flush stdout; + + if verbose <> Only_show then ( + let filter_input, cmd_output = + match filter with + None -> Unix.stdin (* dummy *), Unix.stdout + | Some f -> Unix.pipe() + in + + (* Signals: On SIGINT, we wait until the subprocess finishes, and + * die then. This allows us to call interactive commands as subprocesses. + *) + + let old_sigint = + Sys.signal Sys.sigint Sys.Signal_ignore in + + let need_exe = + List.mem Findlib_config.system [ "win32"; "win64"; "mingw"; "mingw64" ] in + + let fixed_cmd = + if need_exe then ( + if Filename.check_suffix cmd ".exe" then cmd else cmd ^ ".exe" + ) + else + cmd in + + let pid = + Unix.create_process + fixed_cmd + (Array.of_list (cmd :: args)) + Unix.stdin + cmd_output + Unix.stderr + in + + begin match filter with + Some filter_fun -> + begin + Unix.close cmd_output; + let ch = Unix.in_channel_of_descr filter_input in + try + while true do + let line = input_line ch in + match filter_fun line with + None -> () (* Suppress line *) + | Some line' -> print_endline line' + done; + assert false + with + End_of_file -> + close_in ch; + flush stdout + end + | None -> () + end; + + let (_,status) = Unix.waitpid [] pid in + Sys.set_signal Sys.sigint old_sigint; + begin + match status with + Unix.WEXITED 0 -> () + | Unix.WEXITED n -> + if verbose = Verbose then + print_string (cmd ^ " returned with exit code " ^ string_of_int n ^ "\n"); + exit n + | Unix.WSIGNALED _ -> + print_string (cmd ^ " got signal and exited\n"); + exit 2 + | Unix.WSTOPPED _ -> + failwith "Your operating system does not work correctly" + end + ) +;; + + +(**************** preprocessor ******************************************) + +let select_pp_packages syntax_preds packages = + if syntax_preds = [] then + (* No syntax predicates, no preprocessor! *) + [] + else + List.filter + (fun pkg -> + let al = try package_property syntax_preds pkg "archive" + with Not_found -> "" in + let w = Fl_split.in_words al in + w <> [] + ) + packages + + +let process_pp_spec syntax_preds packages pp_opts = + (* Returns: pp_command *) + (* may raise No_such_package *) + + (* [packages]: all packages given on the command line. May include + * packages for compilation and for preprocessing. + * + * The difficulty is now that the preprocessor packages may have + * requirements that are non-preprocessor packages. To get exactly + * the preprocessor packages and its requirements, we do: + * + * 1. Determine the subset of [packages] that are preprocessor + * packages by checking whether they have an "archive" for + * [syntax_preds], i.e. the preprocessor packages mentioned + * on the command line = [cl_pp_packages]. + * + * 2. Add their requirements = [pp_packages] + * + * Because the packages are now mixed, we must evaluate for + * [syntax_preds] + "byte". + *) + + (* One packages must now have the variable "preprocessor", usually camlp4 *) + let cl_pp_packages = select_pp_packages syntax_preds packages in + let pp_packages = + package_deep_ancestors syntax_preds cl_pp_packages in + + let preprocessor_cmds = + List.flatten + (List.map (fun pname -> + try + [ pname, + package_property syntax_preds pname "preprocessor" + ] + with + Not_found -> [] + ) + pp_packages + ) + in + + let preprocessor_cmd = + if syntax_preds <> [] then + match preprocessor_cmds with + [] -> + failwith("Using -syntax, but no package is selected specifying \ + a preprocessor as required for -syntax") + | [_, cmd] -> Some cmd + | _ -> + failwith("Several packages are selected that specify \ + preprocessors: " ^ + String.concat ", " + (List.map + (fun (n,v) -> + "package " ^ n ^ " defines `" ^ v ^ "'") + preprocessor_cmds + ) + ) + else + None + in + + let pp_i_options = + List.flatten + (List.map + (fun pkg -> + let pkgdir = package_directory pkg in + [ "-I"; slashify pkgdir ] + ) + pp_packages) in + + let pp_archives = + if preprocessor_cmd = None then + [] + else + List.flatten + (List.map + (fun pkg -> + let al = + try package_property ("byte" :: syntax_preds) pkg "archive" + with Not_found -> "" in + Fl_split.in_words al + ) + pp_packages) in + + match preprocessor_cmd with + None -> [] + | Some cmd -> + ["-pp"; + cmd ^ " " ^ + String.concat " " (List.map Filename.quote pp_i_options) ^ " " ^ + String.concat " " (List.map Filename.quote pp_archives) ^ " " ^ + String.concat " " (List.map Filename.quote pp_opts)] +;; + +(**************** ppx extensions ****************************************) + +let process_ppx_spec predicates packages ppx_opts = + (* Returns: ppx_commands *) + (* may raise No_such_package *) + + let ppx_packages = + package_deep_ancestors predicates packages in + + let ppx_opts = + List.map + (fun opt -> + match Fl_split.in_words opt with + | pkg :: ((_ :: _) as opts) -> + let exists = + try ignore(package_directory pkg); true + with No_such_package _ -> false in + if not exists then + failwith ("The package named in -ppxopt does not exist: " ^ + pkg); + pkg, opts + | _ -> + failwith "-ppxopt must include package name, e.g. -ppxopt \"foo,-name bar\"" + ) + ppx_opts in + + let meta_ppx_opts = + List.concat + (List.map + (fun pname -> + try + let opts = package_property predicates pname "ppxopt" in + (* Split by whitespace to get (package,options) combinations. + Then, split by commas to get individual options. *) + List.map + (fun opts -> + match Fl_split.in_words opts with + | pkg :: ((_ :: _) as opts) -> + let exists = + try ignore(package_directory pkg); true + with No_such_package _ -> false in + if not exists then + failwith ("The package named in ppxopt variable does not exist: " ^ + pkg ^ " (from " ^ pname ^ ")"); + let base = package_directory pname in + pkg, List.map (resolve_path ~base ~explicit:true) opts + | _ -> + failwith ("ppxopt variable must include package name, e.g. " ^ + "ppxopt=\"foo,-name bar\" (from " ^ pname ^ ")") + ) + (Fl_split.in_words_ws opts) + with Not_found -> [] + ) + ppx_packages + ) in + + List.flatten + (List.map + (fun pname -> + let base = package_directory pname in + let options = + try + List.concat + (List.map (fun (_, opts) -> opts) + (List.filter (fun (pname', _) -> pname' = pname) + (meta_ppx_opts @ ppx_opts))) + with Not_found -> [] + in + try + let preprocessor = + resolve_path + ~base ~explicit:true + (package_property predicates pname "ppx") in + ["-ppx"; String.concat " " (preprocessor :: options)] + with Not_found -> [] + ) + ppx_packages) + +(**************** Generic argument processing *************************) + +let merge_native_arguments native_spec f_unit f_string f_special_list = + List.map + (fun (switch_name, switch_has_arg, help_text) -> + let f = + try + List.assoc switch_name f_special_list + with + Not_found -> + if switch_has_arg then + f_string switch_name + else + f_unit switch_name in + (switch_name, f, help_text) + ) + native_spec +;; + + +let parse_args + ?(current = Arg.current) ?(args = Sys.argv) + ?(align = true) + spec anon usage = + try + Arg.parse_argv + ~current + args + (if align then Arg.align spec else spec) + anon + usage + with + | Arg.Help text -> + print_string text; + exit 0 + | Arg.Bad text -> + prerr_string text; + exit 2 + + +(************************* format expansion *************************) + + +let expand predicates eff_packages format = + (* may raise No_such_package *) + + (* format: + * %p package name + * %d package directory + * %m META file + * %D description + * %v version + * %a archive file(s) + * %A archive files as single string + * %o link option(s) + * %O link options as single string + *) + + List.flatten + (List.map + (fun pkg -> + let dir = package_directory pkg in + (* May raise No_such_package *) + let spec = + [ "%p", [pkg]; + "%d", [out_path dir]; + "%m", [out_path (package_meta_file pkg)]; + "%D", [try package_property predicates pkg "description" + with Not_found -> "[n/a]"]; + "%v", [try package_property predicates pkg "version" + with Not_found -> "[unspecified]"]; + "%a", Fl_split.in_words + (try package_property predicates pkg "archive" + with Not_found -> ""); + "%A", [String.concat " " + (Fl_split.in_words + (try package_property predicates pkg "archive" + with Not_found -> ""))]; + "%o", Fl_split.in_words_ws + (try package_property predicates pkg "linkopts" + with Not_found -> ""); + "%O", [String.concat " " + (Fl_split.in_words_ws + (try package_property predicates pkg "linkopts" + with Not_found -> ""))]; + ] + in + let lookup = package_property predicates pkg in + percent_subst ~base:dir spec lookup format) + eff_packages) +;; + + +let help_format() = + print_endline + "Formats for -format strings: + + %p package name + %d package directory + %m META file + %D description + %v version + %a archive file(s) + %+a archive file(s), converted to absolute paths + %A archive files as single string + %+A archive files as single string, converted to absolute paths + %o link option(s) + %O link options as single string + %(name) the value of the property <name> + %+(name) the value of the property <name>, converted to absolute paths + (like <archive>)"; + flush stdout + + + +(************************** QUERY SUBCOMMAND ***************************) + +let query_package () = + + let long_format = + "package: %p\ndescription: %D\nversion: %v\narchive(s): %A\nlinkopts: %O\nlocation: %d\n" in + let i_format = + "-I %d" in + let l_format = + if Findlib_config.system = "win32" || Findlib_config.system = "win64" then + (* Microsoft toolchain *) + "-ccopt \"/link /libpath:%d\"" + else + "-ccopt -L%d" in + let a_format = + "%+a" in + let o_format = + "%o" in + let p_format = + "%p" in + + let predicates = ref [] in + let format = ref "%d" in + let separator = ref "\n" in + let prefix = ref "" in + let suffix = ref "\n" in + let recursive = ref false in + let descendants = ref false in + let pp = ref false in + let qe = ref false in + let qo = ref false in + + let packages = ref [] in + + let append_predicate s = + let pl = Fl_split.in_words s in + predicates := !predicates @ pl + in + + + parse_args + [ "-predicates", Arg.String append_predicate, + " specifies comma-separated list of assumed predicates"; + "-format", Arg.String (fun s -> format := s), + "<fmt> specifies the output format"; + "-separator", Arg.String (fun s -> separator := s), + " specifies the string that separates multiple answers"; + "-prefix", Arg.String (fun s -> prefix := s), + "<p> a string printed before the first answer"; + "-suffix", Arg.String (fun s -> suffix := s), + "<s> a string printed after the last answer"; + "-recursive", Arg.Set recursive, + " select direct and indirect ancestors/descendants, too"; + "-r", Arg.Set recursive, + " same as -recursive"; + "-descendants", Arg.Unit (fun () -> descendants := true; recursive := true), + " query descendants instead of ancestors; implies -recursive"; + "-d", Arg.Unit (fun () -> descendants := true; recursive := true), + " same as -descendants"; + "-pp", Arg.Unit (fun () -> pp := true; recursive := true), + " get preprocessor pkgs (predicates are taken as syntax preds)"; + "-long-format", Arg.Unit (fun () -> format := long_format), + " specifies long output format"; + "-l", Arg.Unit (fun () -> format := long_format), + " same as -long-format"; + "-i-format", Arg.Unit (fun () -> format := i_format), + " prints -I options for ocamlc"; + "-l-format", Arg.Unit (fun () -> format := l_format), + " prints -ccopt -L options for ocamlc"; + "-a-format", Arg.Unit (fun () -> format := a_format), + " prints names of archives to be linked in for ocamlc"; + "-o-format", Arg.Unit (fun () -> format := o_format), + " prints link options for ocamlc"; + "-p-format", Arg.Unit (fun () -> format := p_format), + " prints package names"; + "-help-format", Arg.Unit help_format, + " lists the supported formats for -format"; + "-qe", Arg.Set qe, + " do not print most errors, just set the exit code"; + "-qo", Arg.Set qo, + " do not print regular output"; + ] + (fun p -> packages := !packages @ Fl_split.in_words p) +"usage: ocamlfind query [ -predicates <p> | -format <f> | + -long-format | -i-format | + -l-format | -a-format | + -o-format | -p-format | + -prefix <p> | -suffix <s> | + -separator <s> | + -descendants | -recursive ] package ..."; + + ignore(config_file()); (* ensure findlib is initialized *) + try + let predicates1 = + if !pp then + "preprocessor" :: "syntax" :: !predicates + else + !predicates in + let packages1 = + if !pp then + let predicates2 = + List.filter (fun p -> p <> "byte" && p <> "native") predicates1 in + select_pp_packages predicates2 !packages + else + !packages in + let eff_packages = + if !recursive then begin + if !descendants then + Fl_package_base.package_users predicates1 packages1 + else + package_deep_ancestors predicates1 packages1 + end + else + packages1 + in + + let answers = expand predicates1 eff_packages !format in + + if not !qo then ( + print_string !prefix; + print_string (String.concat !separator answers); + print_string !suffix; + ) + with + ( Findlib.No_such_package _ + | Failure _ + | Sys_error _ + ) when !qe -> raise Silent_error +;; + + +(**************** OCAMLC/OCAMLMKTOP/OCAMLOPT subcommands ****************) + +type pass_file_t = + Pass of string + | Impl of string (* Forces module implementation: -impl <file> *) + | Intf of string (* Forces module interface: -intf <file> *) + | Cclib of string (* Option for the C linker: -cclib <opt> *) +;; + + +let contracted_ocamlmklib_options = + [ "-l"; "-L"; "-R"; "-F"; "-Wl,-rpath,"; "-Wl,-R" ] + (* The ocamlmklib options where the argument is directly attached to the + switch (e.g. -L<path> instead of -L <path>) + *) + + +let ocamlc which () = + + (* let destdir = ref (default_location()) in *) + + let switches = ref [] in + let pass_options = ref [] in + let pass_files = ref [] in + let incpath = ref [] in + let only_show = ref false in + + let dll_pkgs = ref [] in + let dll_pkgs_all = ref false in + + let linkpkg = ref false in + + let packages = ref [] in + let predicates = ref [] in + let dontlink = ref [] in + + let syntax_preds = ref [] in + let pp_opts = ref [] in + let ppx_opts = ref [] in + let pp_specified = ref false in + + let type_of_threads = + try package_property [] "threads" "type_of_threads" + with Not_found -> "ignore" + in + let threads_default = + match type_of_threads with + "posix" -> `POSIX_threads + | "vm" -> `VM_threads + | _ -> `None + in + let threads = ref `None in + let support_threads() = + if threads_default = `None then + failwith "threading is not supported on this platform" in + + let add_switch name = + Arg.Unit (fun () -> + switches := name :: !switches; + pass_options := !pass_options @ [name]) in + let add_spec_fn name s = + pass_options := !pass_options @ [name; s] in + let add_spec name = + Arg.String (add_spec_fn name) in + let add_contracted_spec_fn name s = + pass_options := !pass_options @ [name ^ s] in + let add_contracted_spec name = + Arg.String (add_contracted_spec_fn name) in + let add_pkg = + Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in + let add_pred = + Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in + let add_dontlink = + Arg.String (fun s -> dontlink := !dontlink @ (Fl_split.in_words s)) in + let add_syntax_pred = + Arg.String (fun s -> syntax_preds := !syntax_preds @ (Fl_split.in_words s)) in + let add_pp_opt = + Arg.String (fun s -> pp_opts := !pp_opts @ [s]) in + let add_dll_pkg = + Arg.String (fun s -> dll_pkgs := !dll_pkgs @ (Fl_split.in_words s)) in + let ignore_error = ref false in + + let native_spec_opt = + match which with + | "ocamlc" -> Ocaml_args.ocamlc_spec + | "ocamlcp" -> Ocaml_args.ocamlcp_spec + | "ocamlmklib" -> Ocaml_args.ocamlmklib_spec + | "ocamlmktop" -> Ocaml_args.ocamlmktop_spec + | "ocamlopt" -> Ocaml_args.ocamlopt_spec + | "ocamloptp" -> Ocaml_args.ocamloptp_spec + | _ -> None in + let native_spec = + match native_spec_opt with + | None -> failwith ("Not supported in your configuration: " ^ which) + | Some s -> s in + + let arg_spec = + List.flatten + [ [ + "-package", add_pkg, + "<name> Refer to package when compiling"; + "-linkpkg", Arg.Set linkpkg, + " Link the packages in"; + "-predicates", add_pred, + "<p> Add predicate <p> when resolving package properties"; + "-dontlink", add_dontlink, + "<name> Do not link in package <name> and its ancestors"; + "-syntax", add_syntax_pred, + "<p> Use preprocessor with predicate <p>"; + "-ppopt", add_pp_opt, + "<opt> Append option <opt> to preprocessor invocation"; + "-ppxopt", Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), + "<pkg>,<opts> Append options <opts> to ppx invocation for package <pkg>"; + "-dllpath-pkg", add_dll_pkg, + "<pkg> Add -dllpath for this package"; + "-dllpath-all", Arg.Set dll_pkgs_all, + " Add -dllpath for all linked packages"; + "-ignore-error", Arg.Set ignore_error, + " Ignore the 'error' directive in META files"; + "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), + "<opt> Pass option <opt> directly to ocamlc/opt/mklib/mktop"; + "-passrest", Arg.Rest (fun s -> pass_options := !pass_options @ [s]), + " Pass all remaining options directly"; + "-only-show", Arg.Set only_show, + " Only show the constructed command, but do not exec it\nSTANDARD OPTIONS:"; + ]; + + merge_native_arguments + native_spec + add_switch + add_spec + ( + [ "-cclib", + Arg.String (fun s -> pass_files := !pass_files @ [ Cclib s ]); + + "-I", (Arg.String + (fun s -> + let s = resolve_path s in + if Sys.file_exists s then incpath := s :: !incpath; (* reverted below *) + add_spec_fn "-I" (slashify s) )); + + "-impl", + Arg.String (fun s -> pass_files := !pass_files @ [ Impl(slashify s) ]); + + "-intf", + Arg.String (fun s -> pass_files := !pass_files @ [ Intf(slashify s) ]); + + "-pp", + Arg.String (fun s -> pp_specified := true; add_spec_fn "-pp" s); + + "-thread", + Arg.Unit (fun _ -> support_threads(); threads := threads_default); + + "-vmthread", + Arg.Unit (fun _ -> support_threads(); threads := `VM_threads); + + "-", + Arg.String (fun s -> pass_files := !pass_files @ [ Pass s ]); + + ] @ + if which = "ocamlmklib" then + List.map + (fun opt -> + (opt, add_contracted_spec opt) + ) + contracted_ocamlmklib_options + else + [] + ) + ] in + + let (current,args) = + if which = "ocamlmklib" then + (* Special processing for -L, -R etc. *) + let c = !(Arg.current) in + let l = Array.length Sys.argv in + let args1 = Array.sub Sys.argv (c+1) (l-c-1) in + let args2 = + Array.append + [| Sys.argv.(0) |] + (Fl_args.rewrite_contracted_args + arg_spec + contracted_ocamlmklib_options + args1 + ) in + (ref 0, args2) + else + (Arg.current, Sys.argv) in + + parse_args + ~current + ~args + arg_spec + (fun s -> pass_files := !pass_files @ [ Pass s]) + ("usage: ocamlfind " ^ which ^ " [options] file ..."); + + (* ---- Start requirements analysis ---- *) + + begin match which with + "ocamlc" -> predicates := "byte" :: !predicates; + | "ocamlcp" -> predicates := "byte" :: !predicates; + | "ocamlmklib" -> predicates := "byte" :: "native" :: !predicates; + | "ocamlmktop" -> predicates := "byte" :: "create_toploop" :: !predicates; + | "ocamlopt" -> predicates := "native" :: !predicates; + | "ocamloptp" -> predicates := "native" :: !predicates; + | _ -> failwith "unsupported backend" + end; + + incpath := List.rev !incpath; + + ( match !threads with + `None -> + () + + | `VM_threads -> + if which = "ocamlopt" then + failwith "ocamlopt does not support multi-threaded programs for your configuration"; + pass_options := !pass_options @ [ "-vmthread" ]; + predicates := "mt" :: "mt_vm" :: !predicates; + + | `POSIX_threads -> + pass_options := !pass_options @ [ "-thread" ]; + predicates := "mt" :: "mt_posix" :: !predicates; + ); + + if List.mem "-p" !switches then + predicates := "gprof" :: !predicates; + + if Findlib_config.ocaml_has_autolinking && + not (List.mem "-noautolink" !switches) + then + predicates := "autolink" :: !predicates; + + if !syntax_preds <> [] then begin + predicates := "syntax" :: !predicates; + syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; + end; + + let verbose = + if List.mem "-verbose" !switches then Verbose else + if !only_show then Only_show else + Normal in + + if !pp_specified && !syntax_preds <> [] then + prerr_endline("ocamlfind: [WARNING] -pp overrides the effect of -syntax partly"); + + (* check packages: *) + check_package_list !packages; + check_package_list !dontlink; + + let eff_packages = + package_deep_ancestors !predicates !packages in + + let eff_dontlink = + package_deep_ancestors !predicates !dontlink in + + let eff_link = + List.flatten + (List.map + (fun pkg -> if List.mem pkg eff_dontlink then [] else [pkg]) + eff_packages) in + + + let eff_packages_dl = + remove_dups (List.map package_directory eff_packages) in + + let eff_link_dl = + remove_dups (List.map package_directory eff_link) in + + (* Conflict report: *) + conflict_report (!incpath @ ["."; Findlib.ocaml_stdlib() ]) eff_packages; + + (* ---- End of requirements analysis ---- *) + + (* Add the pkg_<name> predicates: *) + predicates := List.map (fun pkg -> "pkg_" ^ pkg) eff_packages @ !predicates; + + (* Check on [warning] directives: *) + List.iter + (fun pkg -> + try + let warning = package_property !predicates pkg "warning" in + prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ + "': " ^ warning) + with + Not_found -> () + ) + eff_packages; + + (* Check on [error] directives: *) + List.iter + (fun pkg -> + try + let error = package_property !predicates pkg "error" in + if !ignore_error then + prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ + "' signals error: " ^ error) + else + failwith ("Error from package `" ^ pkg ^ "': " ^ error) + with + Not_found -> () + ) + eff_packages; + + if verbose = Verbose then begin + if !syntax_preds <> [] then + print_string ("Effective set of preprocessor predicates: " ^ + String.concat "," !syntax_preds ^ "\n"); + print_string ("Effective set of compiler predicates: " ^ + String.concat "," !predicates ^ "\n"); + end; + + let stdlibdir = Fl_split.norm_dir (Findlib.ocaml_stdlib()) in + let threads_dir = Filename.concat stdlibdir "threads" in + let vmthreads_dir = Filename.concat stdlibdir "vmthreads" in + + let create_toploop = + List.mem "create_toploop" !predicates && List.mem "findlib" eff_link in + let have_dynload = + List.mem "findlib.dynload" eff_link in + let initl_file_needed = + create_toploop || have_dynload in + + let initl_file_name = + if initl_file_needed then + Filename.temp_file "findlib_initl" ".ml" + else + "" + in + + (* initl_file_name: the initialization code inserted at the end of + * the cma/cmo list (initl = init last) + *) + + if initl_file_needed then begin + (* Generate initializer for "findlib_top.cma" *) + let initl = open_out_gen + [Open_wronly; Open_trunc; Open_text] + 0o777 + initl_file_name in + try + List.iter + (fun pkg -> + Printf.fprintf + initl + "let () = Findlib.record_package Findlib.Record_core %S;;\n" + pkg + ) + eff_packages; + output_string initl + ("let () = Findlib.record_package_predicates [" ^ + String.concat ";" + (List.map + (fun pred -> "\"" ^ String.escaped pred ^ "\"") + !predicates + ) ^ + "];;\n"); + close_out initl; + with + any -> + close_out initl; + Sys.remove initl_file_name; + raise any + end; + + if initl_file_needed && verbose <> Only_show then + at_exit + (fun () -> + let tr f x = try f x with _ -> () in + tr Sys.remove initl_file_name; + tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmi"); + tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmo"); + ); + + let exclude_list = [ stdlibdir; threads_dir; vmthreads_dir ] in + (* Don't generate -I options for these directories because there is + * also some magic in ocamlc/ocamlopt that would not work otherwise + *) + + let i_options = + List.flatten + (List.map + (fun pkgdir -> + let npkgdir = Fl_split.norm_dir pkgdir in + if List.mem npkgdir exclude_list then + [] + else + [ "-I"; slashify pkgdir; + (* "-ccopt"; out_path ~prefix:"-I" pkgdir; -- see comment *) + ]) + eff_packages_dl) in + (* We no longer emit -ccopt options, because ocamlc/ocamlopt already + do that for each -I if the C compiler needs to be invoked + (so far I tracked it, ocamlc/ocamlopt have always done this, even + back in 1996). + *) + + let l_options = [] in + (* Also, no longer -ccopt -L options. Current ocamlc/ocamlopt do that + for each -I option passed to them anyway, so we can omit that here. + See ocaml change (quite old, but I was not aware of it): + http://camlcvs.inria.fr/cgi-bin/cvsweb/ocaml/asmcomp/asmlink.ml.diff?r1=1.38;r2=1.39 + *) +(* + let l_options = + List.flatten + (List.map + (fun pkgdir -> + let npkgdir = Fl_split.norm_dir pkgdir in + if List.mem npkgdir exclude_list then + [] + else + if Findlib_config.system = "win32" || Findlib_config.system = "win64" then + (* Microsoft toolchain *) + [ "-ccopt"; out_path ~prefix:"/link /libpath:" pkgdir ] + else + [ "-ccopt"; out_path ~prefix:"-L" pkgdir; ]) + eff_link_dl) in + *) + + let archives = + List.flatten + (List.map + (fun pkg -> + let al = try package_property !predicates pkg "archive" + with Not_found -> "" in + let al_ext = + if have_dynload && pkg = "findlib.dynload" then + [ initl_file_name ] + else + [] in + let pkg_dir = + if pkg = "threads" then (* MAGIC *) + match !threads with + `None -> stdlibdir + | `VM_threads -> vmthreads_dir + | `POSIX_threads -> threads_dir + else + package_directory pkg in + let pkg_dir = slashify pkg_dir in + List.map + (fun arch -> + resolve_path ~base:pkg_dir arch) + (Fl_split.in_words al @ al_ext) + ) + eff_link) + @ + (if create_toploop then + [ initl_file_name ] + else + [] + ) + in + + let linkopts = + List.flatten + (List.map + (fun pkg -> + let ol = try package_property !predicates pkg "linkopts" + with Not_found -> "" in + Fl_split.in_words_ws ol) + (List.rev eff_link)) in + + let pp_command = + if !pp_specified then + [] + else + process_pp_spec !syntax_preds !packages !pp_opts + in + + let ppx_commands = + process_ppx_spec !predicates !packages !ppx_opts + in + + let pass_files' = + List.flatten + (List.map + (function + Pass s -> + if s <> "" && s.[0] = '-' + then [ "-"; String.sub s 1 (String.length s - 1) ] + else [ resolve_path s ] + | Impl s -> + [ "-impl"; resolve_path s ] + | Intf s -> + [ "-intf"; resolve_path s ] + | Cclib s -> + [ "-cclib"; s ] + ) + !pass_files) + in + + let dll_dirs = + remove_dups + ((List.map package_directory !dll_pkgs) @ + (if !dll_pkgs_all then eff_link_dl else [])) in + + let dll_options = + List.flatten + (List.map + (fun pkg -> ["-dllpath"; slashify pkg] ) + dll_dirs) in + + let mklib_options = + ["-ocamlc"; Findlib.command `ocamlc; + "-ocamlopt"; Findlib.command `ocamlopt] in + + let arguments = + (if which = "ocamlmklib" then mklib_options else []) @ + !pass_options @ (* other options from the command line *) + i_options @ (* Generated -I options from package analysis *) + pp_command @ (* Optional preprocessor command *) + ppx_commands @ (* Optional ppx extension commands *) + (if !linkpkg then l_options else []) @ (* Generated -ccopt -L options *) + (if !linkpkg then archives else []) @ (* Gen file names to link *) + pass_files' @ (* File names from cmd line *) + (if !linkpkg then linkopts else []) @ (* Generated link options *) + dll_options (* Generated -dllpath options *) + in + + let actual_command = + match which with + "ocamlc" -> Findlib.command `ocamlc + | "ocamlopt" -> Findlib.command `ocamlopt + | "ocamlcp" -> Findlib.command `ocamlcp + | "ocamlmklib" -> Findlib.command `ocamlmklib + | "ocamlmktop" -> Findlib.command `ocamlmktop + | "ocamloptp" -> Findlib.command `ocamloptp + | _ -> assert false + in + + run_command verbose actual_command arguments +;; + + +(************************************************************************) + +let ocamldoc() = + + let packages = ref [] in + let predicates = ref [] in + let syntax_preds = ref [] in + let pp_opts = ref [] in + let ppx_opts = ref [] in + let pp_specified = ref false in + + let verbose = ref Normal in + + let options = ref [] in + + let native_spec = + match Ocaml_args.ocamldoc_spec with + | None -> failwith "Not supported in your configuration: ocamldoc" + | Some s -> s in + + parse_args + ~align:false + ( Arg.align + [ "-package", + Arg.String (fun s -> + packages := !packages @ Fl_split.in_words s), + "<name> Add this package to the search path"; + + "-predicates", + Arg.String (fun s -> + predicates := !predicates @ Fl_split.in_words s), + "<p> Add predicate <p> when calculating dependencies"; + + "-syntax", + Arg.String (fun s -> + syntax_preds := !syntax_preds @ Fl_split.in_words s), + "<p> Use preprocessor with predicate <p>"; + + "-ppopt", + Arg.String (fun s -> pp_opts := !pp_opts @ [s]), + "<opt> Append option <opt> to preprocessor invocation"; + + "-ppxopt", + Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), + "<pkg>,<opts> Append options <opts> to ppx invocation for package <pkg>"; + + "-thread", + Arg.Unit (fun () -> predicates := "mt" :: "mt_posix" :: !predicates), + " Assume kernel multi-threading when doing dependency analyses"; + + "-vmthread", + Arg.Unit (fun () -> predicates := "mt" :: "mt_vm" :: !predicates), + " Assume bytecode multi-threading when doing dependency analyses"; + + "-passopt", + Arg.String (fun s -> options := !options @ [s]), + "<opt> Pass this option directly to ocamldoc"; + + "-passrest", + Arg.Rest (fun s -> options := !options @ [s]), + " Pass all remaining options directly to ocamldoc"; + + "-only-show", + Arg.Unit (fun () -> verbose := Only_show), + " Only show the constructed command but do not exec it"; + + "-verbose", + Arg.Unit (fun () -> verbose := Verbose), + " Be verbose\nSTANDARD OPTIONS:"; + ] + @ + ( merge_native_arguments + native_spec + (fun s -> + Arg.Unit (fun () -> + options := !options @ [s])) + (fun s -> + Arg.String (fun arg -> + options := !options @ [s; arg])) + [ "-v", Arg.Unit (fun () -> verbose := Verbose); + "-pp", Arg.String (fun s -> + pp_specified := true; + options := !options @ ["-pp"; s]); + ] + ) + ) + (fun s -> options := !options @ [s]) + "usage: ocamlfind ocamldoc <options> <files>..."; + + check_package_list !packages; + + if !syntax_preds <> [] then ( + predicates := "syntax" :: !predicates; + syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; + ); + + if !verbose = Verbose then begin + if !syntax_preds <> [] then + print_string ("Effective set of preprocessor predicates: " ^ + String.concat "," !syntax_preds ^ "\n"); + print_string ("Effective set of compiler predicates: " ^ + String.concat "," !predicates ^ "\n"); + end; + + if !pp_specified && !syntax_preds <> [] then + prerr_endline("Warning: -pp overrides the effect of -syntax partly"); + + let pp_command = + if !pp_specified then + [] + else + process_pp_spec !syntax_preds !packages !pp_opts + in + + let ppx_commands = + process_ppx_spec !predicates !packages !ppx_opts + in + + let eff_packages = + package_deep_ancestors !predicates !packages in + + (* Check on [error] directives (turned into warnings): *) + List.iter + (fun pkg -> + try + let error = package_property !predicates pkg "error" in + prerr_endline("ocamlfind: [WARNING] Package `" ^ pkg ^ + "' signals error: " ^ error) + with + Not_found -> () + ) + eff_packages; + + let eff_packages_dl = + remove_dups (List.map package_directory eff_packages) in + + let arguments = + (List.flatten (List.map (fun d -> [ "-I"; slashify d ]) eff_packages_dl)) @ + pp_command @ + ppx_commands @ + !options in + + let actual_command = Findlib.command `ocamldoc in + + run_command !verbose actual_command arguments +;; + + +(************************************************************************) + +(* From ocamldep source code: *) +let depends_on_char, continuation_char = + match Sys.os_type with + | "Unix" | "BeOS" | "Win32" | "Cygwin" -> ':', '\\' + | "MacOS" -> '\196', '\182' + | _ -> assert false +;; + + +let suppress_targets suffix = + (* If [line] begins with "target: dependencies ...", and [target] is a + * file name ending in [suffix], this line is suppressed, and all + * follow-up lines. + *) + let do_suppress = ref false in + fun line -> + let target = + try + let k = String.index_from line 0 depends_on_char in (* or Not_found *) + let target_string = String.sub line 0 k in + if String.contains target_string ' ' then raise Not_found; + Some target_string + with + Not_found -> None + in + begin match target with + Some target_string -> + do_suppress := Filename.check_suffix target_string suffix; + | None -> + () + end; + if !do_suppress then + None + else + Some line +;; + + +let ocamldep () = + + let switches = ref [] in + let pass_options = ref [] in + let pass_files = ref [] in + + let packages = ref [] in + let predicates = ref [] in + let syntax_preds = ref [] in + let pp_opts = ref [] in + let ppx_opts = ref [] in + let pp_specified = ref false in + + let verbose = ref Normal in + let native_filter = ref false in + let bytecode_filter = ref false in + + let add_switch name = + Arg.Unit (fun () -> + switches := name :: !switches; + pass_options := !pass_options @ [name]) in + let add_spec_fn name s = + pass_options := !pass_options @ [name; s] in + let add_spec name = Arg.String (add_spec_fn name) in + let add_pred = + Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in + let add_syntax_pred = + Arg.String (fun s -> syntax_preds := !syntax_preds @ (Fl_split.in_words s)) in + let add_pp_opt = + Arg.String (fun s -> pp_opts := !pp_opts @ [s]) in + let add_pkg = + Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in + + let native_spec = + match Ocaml_args.ocamldep_spec with + | None -> failwith "Not supported in your configuration: ocamldep" + | Some s -> s in + + parse_args + ( [ + "-syntax", add_syntax_pred, + "<p> Use preprocessor with predicate <p>"; + "-package", add_pkg, + "<p> Add preprocessor package <p>"; + "-predicates", add_pred, + "<p> Add predicate <p> when calculating dependencies"; + "-ppopt", add_pp_opt, + "<opt> Append option <opt> to preprocessor invocation"; + "-ppxopt", Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]), + "<pkg>,<opts> Append options <opts> to ppx invocation for package <pkg>"; + "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), + "<opt> Pass option <opt> directly to ocamlc/opt/mktop"; + "-passrest", Arg.Rest (fun s -> pass_options := !pass_options @ [s]), + " Pass all remaining options directly"; + "-native-filter", Arg.Set native_filter, + " Output only dependencies for native code (implies -native)"; + "-bytecode-filter", Arg.Set bytecode_filter, + " Output only dependencies for bytecode"; + "-only-show", Arg.Unit (fun () -> verbose := Only_show), + " Only show the constructed command but do not exec it"; + + "-verbose", Arg.Unit (fun () -> verbose := Verbose), + " Print calls to external commands\nSTANDARD OPTIONS:"; + ] + @ + ( merge_native_arguments + native_spec + add_switch + add_spec + [ "-I", + Arg.String (fun s -> add_spec_fn "-I" (slashify (resolve_path s))); + + "-pp", Arg.String (fun s -> pp_specified := true; + add_spec_fn "-pp" s); + ] + ) + ) + (fun s -> pass_files := !pass_files @ [ s]) + ("usage: ocamlfind ocamldep [options] file ..."); + + check_package_list !packages; + + if !native_filter && !bytecode_filter then + failwith "The options -native-filter and -bytecode-filter are incompatible"; + + if !native_filter && not (List.mem "-native" !switches) then + pass_options := "-native" :: !pass_options; + + if !syntax_preds <> [] then + syntax_preds := "preprocessor" :: "syntax" :: !syntax_preds; + + if !verbose = Verbose && !syntax_preds <> [] then + print_string ("Effective set of preprocessor predicates: " ^ + String.concat "," !syntax_preds ^ "\n"); + + if !pp_specified && !syntax_preds <> [] then + prerr_endline("Warning: -pp overrides the effect of -syntax partly"); + + let pp_command = + if !pp_specified then + [] + else + process_pp_spec !syntax_preds !packages !pp_opts + in + + let ppx_commands = + process_ppx_spec !predicates !packages !ppx_opts + in + + let arguments = + !pass_options @ + pp_command @ + ppx_commands @ + !pass_files + in + + let actual_command = Findlib.command `ocamldep in + let filter = + if !native_filter then + (* Suppress when target is ".cmo": *) + Some (suppress_targets ".cmo") + else + if !bytecode_filter then + (* Suppress when target is ".cmx": *) + Some (suppress_targets ".cmx") + else + None + in + + run_command ?filter !verbose actual_command arguments +;; + + +(************************************************************************) + +let ocamlbrowser () = + (* let switches = ref [] in *) + let pass_options = ref [] in + let add_all = ref false in + + let packages = ref [] in + +(* + let add_switch name = + Arg.Unit (fun () -> + switches := name :: !switches; + pass_options := !pass_options @ [name]) in + *) + let add_spec_fn name s = + pass_options := !pass_options @ [name; s] in +(* let add_spec name = Arg.String (add_spec_fn name) in *) + let add_pkg = + Arg.String (fun s -> packages := !packages @ (Fl_split.in_words s)) in + + parse_args + [ + "-I", Arg.String (fun s -> add_spec_fn "-I" (slashify(resolve_path s))), + "<dir> Add <dir> to the list of include directories"; + "-all", Arg.Set add_all, + " Add all packages to include path"; + "-package", add_pkg, + "<p> Add package <p> to include path"; + "-passopt", Arg.String (fun s -> pass_options := !pass_options @ [s]), + "<opt> Pass option <opt> directly to ocamlbrowser"; + "-passrest", Arg.Rest (fun s -> pass_options := !pass_options @ [s]), + " Pass all remaining options directly"; + ] + (fun s -> raise (Arg.Bad ("Unexpected argument: " ^ s))) + ("usage: ocamlfind ocamlbrowser [options] file ..."); + + if !add_all then packages := Fl_package_base.list_packages(); + check_package_list !packages; + + let arguments = + !pass_options @ + (List.flatten + (List.map + (fun pkg -> + let dir = Findlib.package_directory pkg in + [ "-I"; slashify dir ] + ) + !packages + ) + ) + in + + let actual_command = Findlib.command `ocamlbrowser in + + run_command Normal actual_command arguments +;; + + +(************************************************************************) + + +let copy_file ?(rename = (fun name -> name)) ?(append = "") src dstdir = + (* A system-independent function to copy the file src to dstdir *) + let outname = rename (Filename.basename src) in + let ch_in = open_in_bin src in + (* Determine the permissions of the file: the permissions of the + * user bits are extended to all groups (user, group, world bits), + * and the umask is applied to the result. + * Furthermore, the mtime of the file is preserved. This seems to be + * important for BSD-style archives (otherwise the system is confused + * and wants that ranlib is run again). For simplicity, the atime is + * set to the mtime, too. + *) + let s = Unix.stat src in + let perm = s.Unix.st_perm in + let user_perm = (perm land 0o700) lsr 6 in + let perm' = user_perm lor (user_perm lsl 3) lor (user_perm lsl 6) in + try + let outpath = Filename.concat dstdir outname in + if Sys.file_exists outpath then + prerr_endline ("ocamlfind: [WARNING] Overwriting file " ^ outpath); + let ch_out = open_out_gen + [Open_wronly; Open_creat; Open_trunc; Open_binary] + perm' + outpath in + try + let buflen = 4096 in + let buf = Bytes.create buflen in + let pos = ref 0 in + let len = ref (input ch_in buf 0 buflen) in + while !len > 0 do + output ch_out buf !pos !len; + len := input ch_in buf !pos buflen; + done; + output_string ch_out append; + close_out ch_out; + close_in ch_in; + Unix.utimes outpath s.Unix.st_mtime s.Unix.st_mtime; + + prerr_endline("Installed " ^ outpath); + with + exc -> close_out ch_out; raise exc + with + exc -> close_in ch_in; raise exc +;; + + +let install_create_directory pkgname dstdir = + try + Unix.mkdir dstdir 0o777 + with + Unix.Unix_error(Unix.EEXIST,_,_) -> + () + | Unix.Unix_error(Unix.ENOENT,_,_) + | Unix.Unix_error(Unix.ENOTDIR,_,_) -> + failwith ("Bad configuration: Cannot mkdir " ^ dstdir ^ " because a path component does not exist or is not a directory") + | Unix.Unix_error(e,_,_) -> + failwith ("Cannot mkdir " ^ dstdir ^ ": " ^ + Unix.error_message e) +;; + + +let create_owner_file pkg file = + let outpath = file ^ ".owner" in + let f = open_out outpath in + try + output_string f (pkg ^ "\n"); + close_out f; + prerr_endline("Installed " ^ outpath); + with + exc -> close_out f; raise exc +;; + +let trim_cr s = + let len = String.length s in + if len > 0 && String.get s (len-1) = '\r' then + String.sub s 0 (len-1) + else + s + +let find_owned_files pkg dir = + let files = Array.to_list(Sys.readdir dir) in + List.filter + (fun file -> + let owner_file = + if Filename.check_suffix file ".owner" then + file + else + file ^ ".owner" in + (List.mem owner_file files) && ( + try + let fd = + Unix.openfile (Filename.concat dir owner_file) [Unix.O_RDONLY] 0 in + let f = + Unix.in_channel_of_descr fd in + try + let line = trim_cr (input_line f) in + let is_my_file = (line = pkg) in + close_in f; + is_my_file + with + | End_of_file -> close_in f; false + | exc -> close_in f; raise exc + with + | Unix.Unix_error(Unix.ENOENT,_,_) -> + (* the owner file might have been removed by a package + removal that is being done in parallel + *) + false + | Unix.Unix_error(code, _, arg) -> + raise(sys_error code arg) + ) + ) + files +;; + + + +exception Missing_archives of Fl_metascanner.pkg_expr + +let rec patch_archives pkgdir pkg = + (* First remove all missing files from archive variables: *) + let defs' = + List.map + (fun def -> + if def.Fl_metascanner.def_var = "archive" then ( + let files = Fl_split.in_words def.Fl_metascanner.def_value in + let files' = + List.filter + (fun file -> + let p = Findlib.resolve_path ~base:pkgdir file in + Sys.file_exists p) + files in + { def with + Fl_metascanner.def_value = String.concat " " files' + } + ) + else def + ) + pkg.Fl_metascanner.pkg_defs in + (* Remove empty archive variables: *) + let defs'' = + List.filter + (fun def -> + def.Fl_metascanner.def_var <> "archive" || + Fl_split.in_words def.Fl_metascanner.def_value <> [] + ) + defs' in + (* Return the package or raise Not_found if all archives vanished: *) + let children = + (* Recursive patch, remove all Not_found packages: *) + List.flatten + (List.map + (fun (name, child) -> + try [ name, patch_archives pkgdir child ] + with Missing_archives _ -> [] + ) + pkg.Fl_metascanner.pkg_children) in + let pkg' = + { Fl_metascanner.pkg_defs = defs''; + pkg_children = children + } in + if List.exists (fun def -> def.Fl_metascanner.def_var = "archive") defs'' then + pkg' + else + raise (Missing_archives pkg') +;; + + +let rec patch_pkg pkgdir pkg patches = + match patches with + | [] -> pkg + | (`Version v) :: patches' -> + let def = + { Fl_metascanner.def_var = "version"; + def_flav = `BaseDef; + def_preds = []; + def_value = v + } in + let defs = + List.filter + (fun d -> d.Fl_metascanner.def_var <> "version") + pkg.Fl_metascanner.pkg_defs in + let pkg' = + { pkg with + Fl_metascanner.pkg_defs = def :: defs + } in + patch_pkg pkgdir pkg' patches' + | (`Rmpkg n) :: patches' -> + let children = + List.filter + (fun (name,_) -> name <> n) + pkg.Fl_metascanner.pkg_children in + let pkg' = + { pkg with + Fl_metascanner.pkg_children = children + } in + patch_pkg pkgdir pkg' patches' + | `Archives :: patches' -> + let pkg' = + try patch_archives pkgdir pkg + with + Missing_archives p -> p in + patch_pkg pkgdir pkg' patches' +;; + + +exception Skip_file;; + +type which = Auto | Dll | No_dll;; + +let meta_pkg meta_name = + let f = open_in meta_name in + try + let pkg = Fl_metascanner.parse f in + close_in f; + pkg + with + | Failure s + | Fl_metascanner.Error s -> + close_in f; + failwith ("Cannot parse '" ^ meta_name ^ "': " ^ s) + +let char_lowercase_ascii c = + (* Char.lowercase_ascii and String.lowercase_ascii first available in + OCaml-4.03, but we want to support earlier versions too + *) + if (c >= 'A' && c <= 'Z') + then Char.unsafe_chr(Char.code c + 32) + else c + +let string_lowercase_ascii = + String.map char_lowercase_ascii + + +let install_package () = + let destdir = ref (default_location()) in + let metadir = ref (meta_directory()) in + let ldconf = ref (ocaml_ldconf()) in + let don't_add_directory_directive = ref false in + let pkgname = ref "" in + let auto_files = ref [] in + let dll_files = ref [] in + let nodll_files = ref [] in + let which = ref Auto in + let add_files = ref false in + let optional = ref false in + let patches = ref [] in + + let keywords = + [ "-destdir", (Arg.String (fun s -> destdir := s)), + ("<path> Set the destination directory (default: " ^ + !destdir ^ ")"); + "-metadir", (Arg.String (fun s -> metadir := s)), + ("<path> Install the META file into this directory (default: "^ + (if !metadir = "" then "none" else !metadir) ^ ")"); + "-ldconf", (Arg.String (fun s -> ldconf := s)), + ("<path> Update this ld.conf file (default: " ^ !ldconf ^ ")"); + "-dont-add-directory-directive", (Arg.Set don't_add_directory_directive), + " never append directory='...' to META"; + "-dll", Arg.Unit (fun () -> which := Dll), + " The following files are DLLs"; + "-nodll", Arg.Unit (fun () -> which := No_dll), + " The following files are not DLLs"; + "-add", Arg.Unit (fun () -> add_files := true), + " Add files to the package"; + "-optional", Arg.Set optional, + " The following files are optional"; + "-patch-version", Arg.String (fun s -> patches := !patches @ [`Version s]), + "<v> Set the package version to <v>"; + "-patch-rmpkg", Arg.String (fun s -> patches := !patches @ [`Rmpkg s]), + "<n> Remove the subpackage <n>"; + "-patch-archives", Arg.Unit (fun () -> patches := !patches @ [`Archives]), + " Remove non-existing archives"; + ] in + let errmsg = "usage: ocamlfind install [options] <package_name> <file> ..." in + + parse_args + keywords + (fun s -> + if !pkgname = "" + then pkgname := s + else + if not !optional || Sys.file_exists s then + match !which with + Auto -> auto_files := s :: !auto_files + | Dll -> dll_files := s :: !dll_files + | No_dll -> nodll_files := s :: !nodll_files + ) + errmsg; + if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); + if not (Fl_split.is_valid_package_name !pkgname) then + failwith "Package names must not contain the character '.'!"; + + let pkgdir = Filename.concat !destdir !pkgname in + let dlldir = Filename.concat !destdir Findlib_config.libexec_name in + let has_metadir = !metadir <> "" in + let meta_dot_pkg = "META." ^ !pkgname in + + (* The list of all files to install: *) + let full_list = !auto_files @ !dll_files @ !nodll_files in + (* Check whether there are DLLs: *) + let (l1,l2) = List.partition is_dll !auto_files in + let dll_list = l1 @ !dll_files in + let nodll_list = l2 @ !nodll_files in + let have_libexec = Sys.file_exists dlldir in + let pkgdir_list = if have_libexec then nodll_list else full_list in + let pkgdir_eff_list = + (* The files that will be placed into pkgdir: *) + List.map + (fun f -> + if f = meta_dot_pkg then "META" else f) + (List.filter + (fun f -> + not has_metadir || + (f <> "META" && f <> meta_dot_pkg)) + pkgdir_list) in + + (* Check whether META exists: (And check syntax) *) + let meta_name = + try + List.find + (fun p -> + let b = Filename.basename p in + b = "META" || b = meta_dot_pkg) + nodll_list + with + | Not_found -> + if !add_files then ( + let m1 = Filename.concat !metadir meta_dot_pkg in + let m2 = Filename.concat pkgdir "META" in + if Sys.file_exists m1 then + m1 + else + if Sys.file_exists m2 then + m2 + else + failwith "Cannot find META in package dir" + ) + else + failwith "The META file is missing" in + + let meta_pkg = meta_pkg meta_name in + + if not !add_files then ( + (* Check for frequent reasons why installation can go wrong *) + if Sys.file_exists (Filename.concat !metadir meta_dot_pkg) then + failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ Filename.concat !metadir meta_dot_pkg ^ " already exists)"); + + if Sys.file_exists (Filename.concat pkgdir "META") then + failwith ("Package " ^ !pkgname ^ " is already installed\n - (file " ^ pkgdir ^ "/META already exists)"); + ); + List.iter + (fun f -> + let f' = Filename.concat pkgdir f in + if Sys.file_exists f' then + failwith ("Conflict with file: " ^ f')) + pkgdir_eff_list; + + if have_libexec then begin + List.iter + (fun dll -> + let b = Filename.basename dll in + if Sys.file_exists (Filename.concat dlldir b) then + failwith ("Conflict with another package: Library " ^ b ^ + " is already installed"); + ) + dll_list + end; + + (* Create the package directory: *) + install_create_directory !pkgname pkgdir; + + (* Now copy the files into the package directory (except META): *) + List.iter + (fun p -> + try + copy_file + ~rename: (fun f -> + if f = "META" || f = meta_dot_pkg then + raise Skip_file + else + f) + p + pkgdir + with + Skip_file -> () + ) + pkgdir_list; + + (* Copy the DLLs into the libexec directory if necessary *) + if have_libexec then begin + List.iter + (fun p -> + copy_file p dlldir; + create_owner_file !pkgname + (Filename.concat dlldir (Filename.basename p)) + ) + dll_list + end; + + (* Extend ld.conf if necessary: *) + if dll_list <> [] && !ldconf <> "ignore" && not have_libexec then begin + if Sys.file_exists !ldconf then + begin + let lines = read_ldconf !ldconf in + write_ldconf !ldconf lines [ pkgdir ] + end + else + prerr_endline("ocamlfind: [WARNING] You have installed DLLs but there is no ld.conf") + end; + + if dll_list <> [] && have_libexec && !ldconf <> "ignore" then begin + (* Check whether libexec is mentioned in ldconf *) + (* FIXME: We have to be careful with case-insensitive filesystems. + Currently, we only check for Win32, but also OS X may have ci + filesystems. So some better check would be nice. + *) + let lines = read_ldconf !ldconf in + let dlldir_norm = Fl_split.norm_dir dlldir in + let dlldir_norm_lc = string_lowercase_ascii dlldir_norm in + let ci_filesys = (Sys.os_type = "Win32") in + let check_dir d = + let d' = Fl_split.norm_dir d in + (d' = dlldir_norm) || + (ci_filesys && string_lowercase_ascii d' = dlldir_norm_lc) in + if not (List.exists check_dir lines) then + prerr_endline("ocamlfind: [WARNING] You have installed DLLs but the directory " ^ dlldir_norm ^ " is not mentioned in ld.conf"); + end; + + (* Finally, write the META file: *) + let write_meta append_directory dir name = + (* If there are patches, write the patched META, else copy the file: *) + if !patches = [] then + copy_file + ~rename:(fun _ -> name) + ?append:(if append_directory then + Some("\ndirectory=\"" ^ pkgdir ^ + "\" # auto-added by ocamlfind\n") + else + None) + meta_name + dir + else ( + let p = Filename.concat dir name in + let patched_pkg = patch_pkg pkgdir meta_pkg !patches in + let out = open_out p in + Fl_metascanner.print out patched_pkg; + if append_directory then + output_string out ("\ndirectory=\"" ^ pkgdir ^ + "\" # auto-added by ocamlfind\n"); + close_out out; + prerr_endline ("Installed " ^ p); + ) + in + if not !add_files then ( + if has_metadir then + write_meta true !metadir meta_dot_pkg + else + write_meta false pkgdir "META"; + ); + + (* Check if there is a postinstall script: *) + let postinstall = Filename.concat !destdir "postinstall" in + if Sys.file_exists postinstall then + run_command Verbose postinstall [ slashify !destdir; !pkgname ] +;; + + +let reserved_names = [ Findlib_config.libexec_name; "postinstall"; "postremove" ];; + +let remove_package () = + let destdir = ref (default_location()) in + let destdir_set = ref false in + let metadir = ref (meta_directory()) in + let ldconf = ref (ocaml_ldconf()) in + let pkgname = ref "" in + + let keywords = + [ "-destdir", (Arg.String (fun s -> destdir := s; destdir_set := true)), + ("<path> Set the destination directory (default: " ^ + !destdir ^ ")"); + "-metadir", (Arg.String (fun s -> metadir := s)), + ("<path> Remove the META file from this directory (default: " ^ + (if !metadir = "" then "none" else !metadir) ^ ")"); + "-ldconf", (Arg.String (fun s -> ldconf := s)), + ("<path> Update this ld.conf file (default: " ^ !ldconf ^ ")"); + ] in + let errmsg = "usage: ocamlfind remove [options] <package_name>" in + + parse_args + keywords + (fun s -> + if !pkgname = "" + then pkgname := s + else raise (Arg.Bad "too many arguments") + ) + errmsg; + if !pkgname = "" then (Arg.usage keywords errmsg; exit 1); + if List.mem !pkgname reserved_names then + failwith ("You are not allowed to remove this thing by ocamlfind!"); + if not (Fl_split.is_valid_package_name !pkgname) then + failwith "Package names must not contain the character '.'!"; + + let meta_dot_pkg = "META." ^ !pkgname in + let has_metadir = !metadir <> "" in + let pkgdir = Filename.concat !destdir !pkgname in + let dlldir = Filename.concat !destdir Findlib_config.libexec_name in + let have_libexec = Sys.file_exists dlldir in + + (* Warn if there is another package with the same name: *) + let other_pkgdir = + try Findlib.package_directory !pkgname with No_such_package _ -> "" in + if other_pkgdir <> "" && not !destdir_set then begin + (* Is pkgdir = other_pkgdir? - We check physical identity: *) + try + let s_other_pkgdir = Unix.stat other_pkgdir in + try + let s_pkgdir = Unix.stat pkgdir in + if (s_pkgdir.Unix.st_dev <> s_other_pkgdir.Unix.st_dev) || + (s_pkgdir.Unix.st_ino <> s_other_pkgdir.Unix.st_ino) + then + prerr_endline("ocamlfind: [WARNING] You are removing the package from " ^ pkgdir ^ " but the currently visible package is at " ^ other_pkgdir ^ "; you may want to specify the -destdir option"); + with + Unix.Unix_error(Unix.ENOENT,_,_) -> + prerr_endline("ocamlfind: [WARNING] You are trying to remove the package from " ^ pkgdir ^ " but the currently visible package is at " ^ other_pkgdir ^ "; you may want to specify the -destdir option"); + with + Unix.Unix_error(_,_,_) -> () (* ignore, it's only a warning *) + end; + + (* First remove the META file. If it is already gone, assume that a + parallel running removal removed it already. + *) + + (* If there is a metadir, remove the META file from it: *) + let meta_removal_ok = + if has_metadir then ( + let f = Filename.concat !metadir meta_dot_pkg in + try + Unix.unlink f; + prerr_endline ("Removed " ^ f); + true + with + | Unix.Unix_error(Unix.ENOENT,_,_) -> + prerr_endline ("ocamlfind: [WARNING] No such file: " ^ f); + false + | Unix.Unix_error(code, _, arg) -> + raise(sys_error code arg) + ) else + let f = Filename.concat pkgdir "META" in + try + Unix.unlink f; + prerr_endline ("Removed " ^ f); + true + with + | Unix.Unix_error(Unix.ENOENT,_,_) -> + prerr_endline ("ocamlfind: [WARNING] No such file: " ^ f); + false + | Unix.Unix_error(code, _, arg) -> + raise(sys_error code arg) in + + if meta_removal_ok then ( + + (* Remove files from libexec directory: *) + if have_libexec then begin + let dll_files = find_owned_files !pkgname dlldir in + List.iter + (fun file -> + let absfile = Filename.concat dlldir file in + Sys.remove absfile; + prerr_endline ("Removed " ^ absfile) + ) + dll_files + end; + + (* Remove the files from the package directory: *) + if Sys.file_exists pkgdir then begin + let files = Sys.readdir pkgdir in + Array.iter (fun f -> Sys.remove (Filename.concat pkgdir f)) files; + Unix.rmdir pkgdir; + prerr_endline ("Removed " ^ pkgdir) + end + else + prerr_endline("ocamlfind: [WARNING] No such directory: " ^ pkgdir); + + (* Modify ld.conf *) + if !ldconf <> "ignore" then begin + if Sys.file_exists !ldconf then + begin + let lines = read_ldconf !ldconf in + let d = Fl_split.norm_dir pkgdir in + let exists = List.exists (fun p -> Fl_split.norm_dir p = d) lines in + if exists then begin + let lines' = List.filter (fun p -> Fl_split.norm_dir p <> d) lines in + write_ldconf !ldconf lines' [] + end + end + end; + + (* Check if there is a postremove script: *) + let postremove = Filename.concat !destdir "postremove" in + if Sys.file_exists postremove then + run_command Verbose postremove [ slashify !destdir; !pkgname ] + ) +;; + + +let list_packages() = + + let descr = ref false in + + let keywords = + [ "-describe", Arg.Set descr, + " Output package descriptions"; + ] in + let errmsg = "usage: ocamlfind list [options]" in + + parse_args + keywords + (fun _ -> Arg.usage keywords errmsg; exit 1) + errmsg; + + Findlib.list_packages ~descr:!descr stdout; + Fl_package_base.package_conflict_report ~identify_dir () +;; + + +let print_configuration() = + let dir s = + if Sys.file_exists s then + s + else + s ^ " (not found)" + in + + let var = ref None in + let errmsg = "usage: ocamlfind printconf (conf|path|destdir|metadir|metapath|stdlib|ldconf)" in + + parse_args + [] + (fun s -> + if !var <> None then raise(Arg.Bad "Unexpected argument"); + match s with + ("conf" | "path" | "destdir" | "metadir" | "metapath" | "stdlib" | "ldconf") -> + var := Some s + | _ -> + raise(Arg.Bad "Bad argument"); + ) + errmsg; + + match !var with + None -> + print_endline "Effective configuration:"; + Printf.printf "Configuration file:\n %s\n" + (dir (Findlib.config_file())); + Printf.printf "Search path:\n"; + List.iter + (fun p -> Printf.printf " %s\n" (dir p)) + (Findlib.search_path()); + Printf.printf "Packages will be installed in/removed from:\n %s\n" + (dir (Findlib.default_location())); + Printf.printf "META files will be installed in/removed from:\n %s\n" + (let md = Findlib.meta_directory() in + if md = "" then "the corresponding package directories" else dir md + ); + Printf.printf "The standard library is assumed to reside in:\n %s\n" + (Findlib.ocaml_stdlib()); + Printf.printf "The ld.conf file can be found here:\n %s\n" + (Findlib.ocaml_ldconf()); + flush stdout + | Some "conf" -> + print_endline (Findlib.config_file()) + | Some "path" -> + List.iter print_endline (Findlib.search_path()) + | Some "destdir" -> + print_endline (Findlib.default_location()) + | Some "metadir" -> + print_endline (Findlib.meta_directory()) + | Some "metapath" -> + let mdir = Findlib.meta_directory() in + let ddir = Findlib.default_location() in + print_endline + (if mdir <> "" then mdir ^ "/META.%s" else ddir ^ "/%s/META") + | Some "stdlib" -> + print_endline (Findlib.ocaml_stdlib()) + | Some "ldconf" -> + print_endline (Findlib.ocaml_ldconf()) + | _ -> + assert false +;; + + +let ocamlcall pkg cmd = + let dir = package_directory pkg in + let path = Filename.concat dir cmd in + begin + try Unix.access path [ Unix.X_OK ] + with + Unix.Unix_error (Unix.ENOENT, _, _) -> + failwith ("Cannot find command: " ^ path) + | Unix.Unix_error (Unix.EACCES, _, _) -> + failwith ("Cannot execute: " ^ path) + | other -> + Unix.handle_unix_error (fun () -> raise other) () + end; + let args = Array.to_list (Array.sub Sys.argv 2 (Array.length Sys.argv -2)) in + run_command Normal path args +;; + +(** lint META file *) +let lint () = + + let meta_files = Queue.create () in + + parse_args + ~align:false + ( Arg.align [ + ]) + (fun s -> if Sys.file_exists s + then Queue.add s meta_files + else raise(Arg.Bad (Printf.sprintf "%s: file doesn't exists" s))) + "usage: ocamlfind lint <options> <files>..."; + + let error = + Queue.fold (fun error file -> + let pkg = meta_pkg file in + let error = Fl_lint.warn pkg || error in + error + ) false meta_files in + exit (if error then 1 else 0) +;; + + +(** print ppx options *) +let print_ppx () = + + let packages = ref [] in + let predicates = ref [] in + let ppx_opts = ref [] in + + let add_pred = + Arg.String (fun s -> predicates := !predicates @ (Fl_split.in_words s)) in + let add_ppx_opt = + Arg.String (fun s -> ppx_opts := !ppx_opts @ [s]) in + + parse_args + [ "-predicates", add_pred, + " specifies comma-separated list of assumed predicates"; + "-ppxopt", add_ppx_opt, + "<pkg>,<opts> Append options <opts> to ppx invocation for package <pkg>"; + ] + (fun p -> packages := !packages @ [p]) +"usage: ocamlfind printppx [options] package ..."; + + let ppx_commands = + process_ppx_spec !predicates !packages !ppx_opts + in + print_endline (String.concat " " (List.map escape_if_needed ppx_commands)) +;; + + +let rec select_mode () = + let k = !Arg.current in + let m_string = try arg (k+1) with Not_found -> raise Usage in + let m = + match m_string with + ("use"|"-use") -> incr Arg.current; M_use + | ("query"|"-query") -> incr Arg.current; M_query + | ("install"|"-install") -> incr Arg.current; M_install + | ("remove"|"-remove") -> incr Arg.current; M_remove + | ("ocamlc"|"-ocamlc"|"c") -> incr Arg.current; M_compiler "ocamlc" + | ("ocamlcp"|"-ocamlcp"|"cp") -> incr Arg.current; M_compiler "ocamlcp" + | ("ocamloptp"|"-ocamloptp"|"optp") -> incr Arg.current; M_compiler "ocamloptp" + | ("ocamlmklib"|"-ocamlmklib"|"mklib") -> incr Arg.current; M_compiler "ocamlmklib" + | ("ocamlmktop"|"-ocamlmktop"|"mktop") -> incr Arg.current; M_compiler "ocamlmktop" + | ("ocamlopt"|"-ocamlopt"|"opt") -> incr Arg.current; M_compiler "ocamlopt" + | ("ocamldep"|"-ocamldep"|"dep") -> incr Arg.current; M_dep + | ("ocamlbrowser"|"-ocamlbrowser"|"browser") -> incr Arg.current; M_browser + | ("ocamldoc"|"-ocamldoc"|"doc") -> incr Arg.current; M_doc + | ("printconf"|"-printconf") -> incr Arg.current; M_printconf + | ("list"|"-list") -> incr Arg.current; M_list + | ("lint"|"-lint") -> incr Arg.current; M_lint + | ("printppx"|"-printppx") -> incr Arg.current; M_printppx + | "-toolchain" -> + let t = try arg (k+2) with Not_found -> raise Usage in + Findlib.init ~toolchain:t (); + Arg.current := k+2; + select_mode() + | s when String.contains m_string '/' -> + incr Arg.current; + let k = String.index m_string '/' in + let pkg = String.sub m_string 0 k in + let cmd = String.sub m_string (k+1) (String.length m_string - k - 1) in + M_call(pkg,cmd) + | _ -> raise Usage + in + + m +;; + + +let main() = + try + let m = select_mode() in + let l = Array.length Sys.argv in + let k = !Arg.current in + let rest = Array.sub Sys.argv (k+1) (l-k-1) in + match m with + M_use -> if rest = [| |] then raise Usage; + if rest.(0) = "-p" then begin + if l<4 then raise Usage; + use_package rest.(1) + (List.tl(List.tl(Array.to_list rest))) + end + else + use_package "" (Array.to_list rest) + | M_query -> query_package () + | M_install -> install_package() + | M_remove -> remove_package () + | M_printconf -> print_configuration () + | M_list -> list_packages() + | M_dep -> ocamldep() + | M_browser -> ocamlbrowser() + | M_doc -> ocamldoc() + | M_call(pkg,cmd) -> ocamlcall pkg cmd + | M_compiler which -> ocamlc which () + | M_lint -> lint() + | M_printppx -> print_ppx() + with + Usage -> + prerr_endline "Usage: ocamlfind query [-help | other options] <package_name> ..."; + prerr_endline " or: ocamlfind ocamlc [-help | other options] <file> ..."; + prerr_endline " or: ocamlfind ocamlcp [-help | other options] <file> ..."; + prerr_endline " or: ocamlfind ocamlmklib [-help | other options] <file> ..."; + prerr_endline " or: ocamlfind ocamlmktop [-help | other options] <file> ..."; + if Ocaml_args.ocamlopt_spec <> None then + prerr_endline " or: ocamlfind ocamlopt [-help | other options] <file> ..."; + if Ocaml_args.ocamloptp_spec <> None then + prerr_endline " or: ocamlfind ocamloptp [-help | other options] <file> ..."; + prerr_endline " or: ocamlfind ocamldep [-help | other options] <file> ..."; + prerr_endline " or: ocamlfind ocamlbrowser [-help | other options]"; + prerr_endline " or: ocamlfind ocamldoc [-help | other options] <file> ..."; + prerr_endline " or: ocamlfind install [-help | other options] <package_name> <file> ..."; + prerr_endline " or: ocamlfind remove [-help | other options] <package_name>"; + prerr_endline " or: ocamlfind printppx [-help | other options] <package_name> ..."; + prerr_endline " or: ocamlfind printconf [-help] [variable]"; + prerr_endline " or: ocamlfind lint [-help] <file>"; + prerr_endline " or: ocamlfind list"; + prerr_endline " or: ocamlfind pkg/cmd arg ..."; + prerr_endline "Select toolchain with:"; + prerr_endline " ocamlfind -toolchain <t> <command>"; + prerr_endline "Abbreviations:"; + prerr_endline " e.g. ocamlfind opt instead of ocamlfind ocamlopt"; + exit 2 + | Failure f -> + prerr_endline ("ocamlfind: " ^ f); + exit 2 + | Sys_error f -> + prerr_endline ("ocamlfind: " ^ f); + exit 2 + | Findlib.No_such_package(pkg,info) -> + prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' not found" ^ + (if info <> "" then " - " ^ info else "")); + exit 2 + | Findlib.Package_loop pkg -> + prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' requires itself"); + exit 2 + | Silent_error -> + exit 2 +;; + + +try + Sys.catch_break true; + main() +with + any -> + prerr_endline ("Uncaught exception: " ^ Printexc.to_string any); + let raise_again = + try ignore(Sys.getenv "OCAMLFIND_DEBUG"); true + with Not_found -> false + in + if raise_again then raise any; + exit 3 +;; diff --git a/local-packages/ocamlfind/src/findlib/num_top.ml b/local-packages/ocamlfind/src/findlib/num_top.ml new file mode 100644 index 0000000..947d486 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/num_top.ml @@ -0,0 +1,32 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +let print_outcome = false +let error_fmt = Format.err_formatter + +let printers = [ + "Num_top_printers.nat_printer"; + "Num_top_printers.big_int_printer"; + "Num_top_printers.ratio_printer"; + "Num_top_printers.num_printer"; +] + +let eval_phrase s = + let lexbuf = Lexing.from_string s in + let phrase = !Toploop.parse_toplevel_phrase lexbuf in + Toploop.execute_phrase print_outcome error_fmt phrase + +let install_all () = + List.fold_left + (fun outcome phrase -> + outcome && eval_phrase (Printf.sprintf "#install_printer %s;;" phrase)) + true printers + +let _ = + if not (install_all ()) then begin + Format.fprintf error_fmt + "Something weird appened while installing Num library printers"; + Format.pp_print_flush error_fmt () + end diff --git a/local-packages/ocamlfind/src/findlib/num_top.mli b/local-packages/ocamlfind/src/findlib/num_top.mli new file mode 100644 index 0000000..1022570 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/num_top.mli @@ -0,0 +1,18 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(** + Load this module in the toplevel to install printers for the following types + defined in the "num" library: + - Nat.nat + - Big_int.big_int + - Ratio.ratio + - Num.num + + No functions exported. + + Copyright (C) 2003 Stefano Zacchiroli <zack@debian.org> +*) + diff --git a/local-packages/ocamlfind/src/findlib/num_top_printers.ml b/local-packages/ocamlfind/src/findlib/num_top_printers.ml new file mode 100644 index 0000000..80b0cf7 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/num_top_printers.ml @@ -0,0 +1,17 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +let nat_printer fmt v = + Format.fprintf fmt "<nat %s>" (Nat.string_of_nat v) + +let big_int_printer fmt v = + Format.fprintf fmt "<big_int %s>" (Big_int.string_of_big_int v) + +let ratio_printer fmt v = + Format.fprintf fmt "<ratio %s>" (Ratio.string_of_ratio v) + +let num_printer fmt v = + Format.fprintf fmt "<num %s>" (Num.string_of_num v) + diff --git a/local-packages/ocamlfind/src/findlib/num_top_printers.mli b/local-packages/ocamlfind/src/findlib/num_top_printers.mli new file mode 100644 index 0000000..44566db --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/num_top_printers.mli @@ -0,0 +1,19 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(** + Printers for types defined in the "num" library. Meant to be used as printers + in the ocaml toplevel. See num_top.mli. + + Copyright (C) 2003 Stefano Zacchiroli <zack@debian.org> + + Released under the same terms as findlib. +*) + +val nat_printer : Format.formatter -> Nat.nat -> unit +val big_int_printer : Format.formatter -> Big_int.big_int -> unit +val ratio_printer : Format.formatter -> Ratio.ratio -> unit +val num_printer: Format.formatter -> Num.num -> unit + diff --git a/local-packages/ocamlfind/src/findlib/ocaml_args.ml b/local-packages/ocamlfind/src/findlib/ocaml_args.ml new file mode 100644 index 0000000..d84a45d --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/ocaml_args.ml @@ -0,0 +1,3264 @@ +let ocamlc_spec = Some [ + "-a", + false, + " Build a library"; + + "-alert", + true, + "<list> Enable or disable alerts according to <list>:\n +<alertname> enable alert <alertname>\n -<alertname> disable alert <alertname>\n ++<alertname> treat <alertname> as fatal error"; + + "--", + true, + "<alertname> treat <alertname> as non-fatal\n @<alertname> enable <alertname> and treat it as fatal error\n <alertname> can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-annot", + false, + " (deprecated) Save information in <filename>.annot"; + + "-bin-annot", + false, + " Save typedtree in <filename>.cmt"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + "<command> Use <command> as the C compiler and linker"; + + "-cclib", + true, + "<opt> Pass option <opt> to the C linker"; + + "-ccopt", + true, + "<opt> Pass option <opt> to the C compiler and linker"; + + "-cmi-file", + true, + "<file> Use the <file> interface file to type-check"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compat-32", + false, + " Check that generated bytecode can run on 32-bit platforms"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, without a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-custom", + false, + " Link in custom mode"; + + "-dllib", + true, + "<lib> Use the dynamically-loaded library <lib>"; + + "-dllpath", + true, + "<dir> Add <dir> to the run-time search path for shared libraries"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + "<ident> Generate code that can later be `packed' with\n ocamlc -pack -o <ident>.cmo"; + + "-g", + false, + " Save debugging information"; + + "-stop-after", + true, + "{parsing|typing} Stop after the given compilation pass."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + "<dir> Add <dir> to the list of include directories"; + + "-impl", + true, + "<file> Compile <file> as a .ml file"; + + "-intf", + true, + "<file> Compile <file> as a .mli file"; + + "-intf-suffix", + true, + "<string> Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + "<string> (deprecated) same as -intf-suffix"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-make-runtime", + false, + " Build a runtime system with given C objects and libraries"; + + "-make_runtime", + false, + " (deprecated) same as -make-runtime"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-check-prims", + false, + " Do not check runtime for primitives"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cma files"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nocwd", + false, + " Do not implicitly add the current directory to the load path"; + + "-nopervasives", + false, + " (undocumented)"; + + "-o", + true, + "<file> Set output file name to <file>"; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + "<module> Opens the module <module> before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-output-complete-exe", + false, + " Output a self-contained executable, including runtime and C stubs"; + + "-pack", + false, + " Package the given .cmo files into one .cmo"; + + "-pp", + true, + "<command> Pipe sources through preprocessor <command>"; + + "-ppx", + true, + "<command> Pipe abstract syntax trees through preprocessor <command>"; + + "-plugin", + true, + "<plugin> (no longer supported)"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-runtime-variant", + true, + "<str> Use the <str> variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-safe-string", + false, + " (default unconditionally since 5.0)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-use-runtime", + true, + "<file> Generate bytecode for the given runtime system"; + + "-use_runtime", + true, + "<file> (deprecated) same as -use-runtime"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + "<list> Enable or disable warnings according to <list>:\n +<spec> enable warnings in <spec>\n -<spec> disable warnings in <spec>\n @<spec> enable warnings in <spec> and treat them as errors\n <spec> can be:\n <num> a single warning number\n <num1>..<num2> a range of consecutive warning numbers\n <letter> a predefined set\n default setting is \"+a-4-7-9-27-29-30-32..42-44-45-48-50-60-66..70\""; + + "-warn-error", + true, + "<list> Enable or disable error status for warnings according\n to <list>. See option -w for the syntax of <list>.\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + "<file> Treat <file> as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + "<n> (advanced, see manual section 13.2.)"; + + "-use-prims", + true, + "<file> (undocumented)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-dshape", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-dinstr", + false, + " (undocumented)"; + + "-dcamlprimc", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into <target>.dump"; + + "-dump-dir", + true, + "<dir> dump output like -dlambda into <dir>/<target>.dump"; + + "-args", + true, + "<file> Read additional newline-terminated command line arguments\n from <file>"; + + "-args0", + true, + "<file> Read additional null character terminated command line arguments\nfrom <file>"; + + "-depend", + true, + "<options> Compute dependencies (use 'ocamlc -depend -help' for details)"; + +];; + +let ocamlcp_spec = Some [ + "-P", + true, + "[afilmt] Profile constructs specified by argument (default fm):\n a Everything\n f Function calls and method calls\n i if ... then ... else\n l while and for loops\n m match ... with\n t try ... with"; + + "-p", + true, + "[afilmt] Same as option -P"; + + "-a", + false, + " Build a library"; + + "-alert", + true, + "<list> Enable or disable alerts according to <list>:\n +<alertname> enable alert <alertname>\n -<alertname> disable alert <alertname>\n ++<alertname> treat <alertname> as fatal error"; + + "--", + true, + "<alertname> treat <alertname> as non-fatal\n @<alertname> enable <alertname> and treat it as fatal error\n <alertname> can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-annot", + false, + " (deprecated) Save information in <filename>.annot"; + + "-bin-annot", + false, + " Save typedtree in <filename>.cmt"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + "<command> Use <command> as the C compiler and linker"; + + "-cclib", + true, + "<opt> Pass option <opt> to the C linker"; + + "-ccopt", + true, + "<opt> Pass option <opt> to the C compiler and linker"; + + "-cmi-file", + true, + "<file> Use the <file> interface file to type-check"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compat-32", + false, + " Check that generated bytecode can run on 32-bit platforms"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, without a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-custom", + false, + " Link in custom mode"; + + "-dllib", + true, + "<lib> Use the dynamically-loaded library <lib>"; + + "-dllpath", + true, + "<dir> Add <dir> to the run-time search path for shared libraries"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + "<ident> Generate code that can later be `packed' with\n ocamlc -pack -o <ident>.cmo"; + + "-g", + false, + " Save debugging information"; + + "-stop-after", + true, + "{parsing|typing} Stop after the given compilation pass."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + "<dir> Add <dir> to the list of include directories"; + + "-impl", + true, + "<file> Compile <file> as a .ml file"; + + "-intf", + true, + "<file> Compile <file> as a .mli file"; + + "-intf-suffix", + true, + "<string> Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + "<string> (deprecated) same as -intf-suffix"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-make-runtime", + false, + " Build a runtime system with given C objects and libraries"; + + "-make_runtime", + false, + " (deprecated) same as -make-runtime"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-check-prims", + false, + " Do not check runtime for primitives"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cma files"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nocwd", + false, + " Do not implicitly add the current directory to the load path"; + + "-nopervasives", + false, + " (undocumented)"; + + "-o", + true, + "<file> Set output file name to <file>"; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + "<module> Opens the module <module> before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-output-complete-exe", + false, + " Output a self-contained executable, including runtime and C stubs"; + + "-pack", + false, + " Package the given .cmo files into one .cmo"; + + "-pp", + true, + "<command> Pipe sources through preprocessor <command>"; + + "-ppx", + true, + "<command> Pipe abstract syntax trees through preprocessor <command>"; + + "-plugin", + true, + "<plugin> (no longer supported)"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-runtime-variant", + true, + "<str> Use the <str> variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-safe-string", + false, + " (default unconditionally since 5.0)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-use-runtime", + true, + "<file> Generate bytecode for the given runtime system"; + + "-use_runtime", + true, + "<file> (deprecated) same as -use-runtime"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + "<list> Enable or disable warnings according to <list>:\n +<spec> enable warnings in <spec>\n -<spec> disable warnings in <spec>\n @<spec> enable warnings in <spec> and treat them as errors\n <spec> can be:\n <num> a single warning number\n <num1>..<num2> a range of consecutive warning numbers\n <letter> a predefined set\n default setting is \"+a-4-7-9-27-29-30-32..42-44-45-48-50-60-66..70\""; + + "-warn-error", + true, + "<list> Enable or disable error status for warnings according\n to <list>. See option -w for the syntax of <list>.\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + "<file> Treat <file> as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + "<n> (advanced, see manual section 13.2.)"; + + "-use-prims", + true, + "<file> (undocumented)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-dshape", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-dinstr", + false, + " (undocumented)"; + + "-dcamlprimc", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into <target>.dump"; + + "-dump-dir", + true, + "<dir> dump output like -dlambda into <dir>/<target>.dump"; + + "-args", + true, + "<file> Read additional newline-terminated command line arguments\n from <file>"; + + "-args0", + true, + "<file> Read additional null character terminated command line arguments\nfrom <file>"; + +];; + +let ocamloptp_spec = Some [ + "-P", + true, + "[afilmt] Profile constructs specified by argument (default fm):\n a Everything\n f Function calls and method calls\n i if ... then ... else\n l while and for loops\n m match ... with\n t try ... with"; + + "-a", + false, + " Build a library"; + + "-alert", + true, + "<list> Enable or disable alerts according to <list>:\n +<alertname> enable alert <alertname>\n -<alertname> disable alert <alertname>\n ++<alertname> treat <alertname> as fatal error"; + + "--", + true, + "<alertname> treat <alertname> as non-fatal\n @<alertname> enable <alertname> and treat it as fatal error\n <alertname> can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-afl-instrument", + false, + "Enable instrumentation for afl-fuzz"; + + "-afl-inst-ratio", + false, + "Configure percentage of branches instrumented\n (advanced, see afl-fuzz docs for AFL_INST_RATIO)"; + + "-annot", + false, + " (deprecated) Save information in <filename>.annot"; + + "-bin-annot", + false, + " Save typedtree in <filename>.cmt"; + + "-inline-branch-factor", + true, + "<n>|<round>=<n>[,...] Estimate the probability of a branch being cold as 1/(1+n) (used for inlining) (default 0.10)"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + "<command> Use <command> as the C compiler and linker"; + + "-cclib", + true, + "<opt> Pass option <opt> to the C linker"; + + "-ccopt", + true, + "<opt> Pass option <opt> to the C compiler and linker"; + + "-cmi-file", + true, + "<file> Use the <file> interface file to type-check"; + + "-clambda-checks", + false, + " Instrument clambda code with closure and field access checks (for debugging the compiler)"; + + "-Oclassic", + false, + " Make inlining decisions at function definition time rather than at the call site (replicates previous behaviour of the compiler)"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compact", + false, + " Optimize code size rather than speed"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, without a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + "<ident> Generate code that can later be `packed' with\n ocamlopt -pack -o <ident>.cmx"; + + "-g", + false, + " Record debugging information for exception backtrace"; + + "-function-sections", + false, + " Generate each function in a separate section if target supports it"; + + "-stop-after", + true, + "{parsing|typing|scheduling|emit} Stop after the given compilation pass."; + + "-save-ir-after", + true, + "{scheduling} Save intermediate representation after the given compilation pass(may be specified more than once)."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + "<dir> Add <dir> to the list of include directories"; + + "-impl", + true, + "<file> Compile <file> as a .ml file"; + + "-inline", + true, + "<n>|<round>=<n>[,...] Aggressiveness of inlining (default 1.25, higher numbers mean more aggressive)"; + + "-inline-toplevel", + true, + "<n>|<round>=<n>[,...] Aggressiveness of inlining at toplevel (higher numbers mean more aggressive)"; + + "-inline-alloc-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing an allocation during inlining (default 7, higher numbers more costly)"; + + "-inline-branch-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing a conditional during inlining (default 5, higher numbers more costly)"; + + "-inline-call-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing a call during inlining (default 5, higher numbers more costly)"; + + "-inline-prim-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing a primitive during inlining (default 3, higher numbers more costly)"; + + "-inline-indirect-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing an indirect call during inlining (default 4, higher numbers more costly)"; + + "-inline-lifting-benefit", + true, + "<n>|<round>=<n>[,...] The benefit of lifting definitions to toplevel during inlining (default 1300, higher numbers more beneficial)"; + + "-inlining-report", + false, + " Emit `.<round>.inlining' file(s) (one per round) showing the inliner's decisions"; + + "-insn-sched", + false, + " Run the instruction scheduling pass (default)"; + + "-intf", + true, + "<file> Compile <file> as a .mli file"; + + "-intf-suffix", + true, + "<string> Suffix for interface files (default: .mli)"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-inline-max-depth", + true, + "<n>|<round>=<n>[,...] Maximum depth of search for inlining opportunities inside inlined functions (default 1)"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-linscan", + false, + " Use the linear scan register allocator"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-float-const-prop", + false, + " Deactivate constant propagation for floating-point operations"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cmxa files"; + + "-nodynlink", + false, + " Enable optimizations for code that will not be dynlinked"; + + "-no-insn-sched", + false, + " Do not run the instruction scheduling pass"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nocwd", + false, + " Do not implicitly add the current directory to the load path"; + + "-nopervasives", + false, + " (undocumented)"; + + "-no-unbox-free-vars-of-closures", + false, + " Do not unbox variables that will appear inside function closures"; + + "-no-unbox-specialised-args", + false, + " Do not unbox arguments to which functions have been specialised"; + + "-o", + true, + "<file> Set output file name to <file>"; + + "-O2", + false, + " Apply increased optimization for speed"; + + "-O3", + false, + " Apply aggressive optimization for speed (may significantly increase code size and compilation time)"; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + "<module> Opens the module <module> before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-p", + false, + " (no longer supported)"; + + "-pack", + false, + " Package the given .cmx files into one .cmx"; + + "-plugin", + true, + "<plugin> (no longer supported)"; + + "-pp", + true, + "<command> Pipe sources through preprocessor <command>"; + + "-ppx", + true, + "<command> Pipe abstract syntax trees through preprocessor <command>"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-remove-unused-arguments", + false, + " Remove unused function arguments"; + + "-rounds", + true, + "<n> Repeat tree optimization and inlining phases this many times (default 1). Rounds are numbered starting from zero."; + + "-runtime-variant", + true, + "<str> Use the <str> variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-S", + false, + " Keep intermediate assembly file"; + + "-safe-string", + false, + " (default unconditionally since 5.0)"; + + "-shared", + false, + " Produce a dynlinkable plugin"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unbox-closures", + false, + " Pass free variables via specialised arguments rather than closures"; + + "-unbox-closures-factor", + true, + "<n > 0> Scale the size threshold above which unbox-closures will slow down indirect calls rather than duplicating a function (default 10)"; + + "-inline-max-unroll", + true, + "<n>|<round>=<n>[,...] Unroll recursive functions at most this many times (default 0)"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + "<list> Enable or disable warnings according to <list>:\n +<spec> enable warnings in <spec>\n -<spec> disable warnings in <spec>\n @<spec> enable warnings in <spec> and treat them as errors\n <spec> can be:\n <num> a single warning number\n <num1>..<num2> a range of consecutive warning numbers\n <letter> a predefined set\n default setting is \"+a-4-7-9-27-29-30-32..42-44-45-48-50-60-66..70\""; + + "-warn-error", + true, + "<list> Enable or disable error status for warnings according\n to <list>. See option -w for the syntax of <list>.\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + "<file> Treat <file> as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + "<n> (advanced, see manual section 13.2.)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-dshape", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-drawclambda", + false, + " (undocumented)"; + + "-dclambda", + false, + " (undocumented)"; + + "-dcmm-invariants", + false, + " Extra sanity checks on Cmm"; + + "-dflambda", + false, + " Print Flambda terms"; + + "-drawflambda", + false, + " Print Flambda terms after closure conversion"; + + "-dflambda-invariants", + false, + " Check Flambda invariants around each pass"; + + "-dflambda-no-invariants", + false, + " Do not Check Flambda invariants around each pass"; + + "-dflambda-let", + true, + "<stamp> Print when the given Flambda [Let] is created"; + + "-dflambda-verbose", + false, + " Print Flambda terms including around each pass"; + + "-dcmm", + false, + " (undocumented)"; + + "-dsel", + false, + " (undocumented)"; + + "-dcombine", + false, + " (undocumented)"; + + "-dcse", + false, + " (undocumented)"; + + "-dlive", + false, + " (undocumented)"; + + "-dspill", + false, + " (undocumented)"; + + "-dsplit", + false, + " (undocumented)"; + + "-dinterf", + false, + " (undocumented)"; + + "-dprefer", + false, + " (undocumented)"; + + "-dalloc", + false, + " (undocumented)"; + + "-dreload", + false, + " (undocumented)"; + + "-dscheduling", + false, + " (undocumented)"; + + "-dlinear", + false, + " (undocumented)"; + + "-dinterval", + false, + " (undocumented)"; + + "-dstartup", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into <target>.dump"; + + "-dump-dir", + true, + "<dir> dump output like -dlambda into <dir>/<target>.dump"; + + "-dump-pass", + false, + " Record transformations performed by these passes: "; + + "-args", + true, + "<file> Read additional newline-terminated command line arguments\n from <file>"; + + "-args0", + true, + "<file> Read additional null character terminated command line arguments\nfrom <file>"; + +];; + +let ocamlmklib_spec = Some [ + "-args", + true, + "<file> Read additional newline-terminated command line arguments\n from <file>"; + + "-args0", + true, + "<file> Read additional null character terminated command line\n arguments from <file>"; + + "-cclib", + true, + "<lib> C library passed to ocamlc -a or ocamlopt -a only"; + + "-ccopt", + true, + "<opt> C option passed to ocamlc -a or ocamlopt -a only"; + + "-custom", + false, + " Disable dynamic loading"; + + "-g", + false, + " Build with debug information"; + + "-dllpath", + true, + "<dir> Add <dir> to the run-time search path for DLLs"; + + "-F", + true, + "<dir> Specify a framework directory (MacOSX)"; + + "-framework", + true, + "<name> Use framework <name> (MacOSX)"; + + "-h", + false, + " Same as -help"; + + "-I", + true, + "<dir> Add <dir> to the path searched for OCaml object files"; + + "-failsafe", + false, + " fall back to static linking if DLL construction failed"; + + "-ldopt", + true, + "<opt> C option passed to the shared linker only"; + + "-linkall", + false, + " Build OCaml archive with link-all behavior"; + + "-l", + true, + "<lib> Specify a dependent C library"; + + "-L", + true, + "<dir> Add <dir> to the path searched for C libraries"; + + "-ocamlc", + true, + "<cmd> Use <cmd> in place of \"ocamlc\""; + + "-ocamlcflags", + true, + "<opt> Pass <opt> to ocamlc"; + + "-ocamlopt", + true, + "<cmd> Use <cmd> in place of \"ocamlopt\""; + + "-ocamloptflags", + true, + "<opt> Pass <opt> to ocamlopt"; + + "-o", + true, + "<name> Generated OCaml library is named <name>.cma or <name>.cmxa"; + + "-oc", + true, + "<name> Generated C library is named dll<name>.so or lib<name>.a"; + + "-rpath", + true, + "<dir> Same as -dllpath <dir>"; + + "-R", + true, + "<dir> Same as -rpath"; + + "-verbose", + false, + " Print commands before executing them"; + + "-v", + false, + " same as -verbose"; + + "-version", + false, + " Print version and exit"; + + "-vnum", + false, + " Print version number and exit"; + + "-Wl,-rpath,", + true, + "<dir> Same as -dllpath <dir>"; + + "-Wl,-rpath", + false, + "-Wl,<dir> Same as -dllpath <dir>"; + + "-Wl,-R", + true, + "<dir> Same as -dllpath <dir>"; + +];; + +let ocamlmktop_spec = Some [ + "-a", + false, + " Build a library"; + + "-alert", + true, + "<list> Enable or disable alerts according to <list>:\n +<alertname> enable alert <alertname>\n -<alertname> disable alert <alertname>\n ++<alertname> treat <alertname> as fatal error"; + + "--", + true, + "<alertname> treat <alertname> as non-fatal\n @<alertname> enable <alertname> and treat it as fatal error\n <alertname> can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-annot", + false, + " (deprecated) Save information in <filename>.annot"; + + "-bin-annot", + false, + " Save typedtree in <filename>.cmt"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + "<command> Use <command> as the C compiler and linker"; + + "-cclib", + true, + "<opt> Pass option <opt> to the C linker"; + + "-ccopt", + true, + "<opt> Pass option <opt> to the C compiler and linker"; + + "-cmi-file", + true, + "<file> Use the <file> interface file to type-check"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compat-32", + false, + " Check that generated bytecode can run on 32-bit platforms"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, without a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-custom", + false, + " Link in custom mode"; + + "-dllib", + true, + "<lib> Use the dynamically-loaded library <lib>"; + + "-dllpath", + true, + "<dir> Add <dir> to the run-time search path for shared libraries"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + "<ident> Generate code that can later be `packed' with\n ocamlc -pack -o <ident>.cmo"; + + "-g", + false, + " Save debugging information"; + + "-stop-after", + true, + "{parsing|typing} Stop after the given compilation pass."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + "<dir> Add <dir> to the list of include directories"; + + "-impl", + true, + "<file> Compile <file> as a .ml file"; + + "-intf", + true, + "<file> Compile <file> as a .mli file"; + + "-intf-suffix", + true, + "<string> Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + "<string> (deprecated) same as -intf-suffix"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-make-runtime", + false, + " Build a runtime system with given C objects and libraries"; + + "-make_runtime", + false, + " (deprecated) same as -make-runtime"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-check-prims", + false, + " Do not check runtime for primitives"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cma files"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nocwd", + false, + " Do not implicitly add the current directory to the load path"; + + "-nopervasives", + false, + " (undocumented)"; + + "-o", + true, + "<file> Set output file name to <file>"; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + "<module> Opens the module <module> before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-output-complete-exe", + false, + " Output a self-contained executable, including runtime and C stubs"; + + "-pack", + false, + " Package the given .cmo files into one .cmo"; + + "-pp", + true, + "<command> Pipe sources through preprocessor <command>"; + + "-ppx", + true, + "<command> Pipe abstract syntax trees through preprocessor <command>"; + + "-plugin", + true, + "<plugin> (no longer supported)"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-runtime-variant", + true, + "<str> Use the <str> variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-safe-string", + false, + " (default unconditionally since 5.0)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-use-runtime", + true, + "<file> Generate bytecode for the given runtime system"; + + "-use_runtime", + true, + "<file> (deprecated) same as -use-runtime"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + "<list> Enable or disable warnings according to <list>:\n +<spec> enable warnings in <spec>\n -<spec> disable warnings in <spec>\n @<spec> enable warnings in <spec> and treat them as errors\n <spec> can be:\n <num> a single warning number\n <num1>..<num2> a range of consecutive warning numbers\n <letter> a predefined set\n default setting is \"+a-4-7-9-27-29-30-32..42-44-45-48-50-60-66..70\""; + + "-warn-error", + true, + "<list> Enable or disable error status for warnings according\n to <list>. See option -w for the syntax of <list>.\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + "<file> Treat <file> as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + "<n> (advanced, see manual section 13.2.)"; + + "-use-prims", + true, + "<file> (undocumented)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-dshape", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-dinstr", + false, + " (undocumented)"; + + "-dcamlprimc", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into <target>.dump"; + + "-dump-dir", + true, + "<dir> dump output like -dlambda into <dir>/<target>.dump"; + + "-args", + true, + "<file> Read additional newline-terminated command line arguments\n from <file>"; + + "-args0", + true, + "<file> Read additional null character terminated command line arguments\nfrom <file>"; + + "-depend", + true, + "<options> Compute dependencies (use 'ocamlc -depend -help' for details)"; + +];; + +let ocamlopt_spec = Some [ + "-fPIC", + false, + " Generate position-independent machine code (default)"; + + "-fno-PIC", + false, + " Generate position-dependent machine code"; + + "-a", + false, + " Build a library"; + + "-alert", + true, + "<list> Enable or disable alerts according to <list>:\n +<alertname> enable alert <alertname>\n -<alertname> disable alert <alertname>\n ++<alertname> treat <alertname> as fatal error"; + + "--", + true, + "<alertname> treat <alertname> as non-fatal\n @<alertname> enable <alertname> and treat it as fatal error\n <alertname> can be 'all' to refer to all alert names"; + + "-absname", + false, + " Show absolute filenames in error messages"; + + "-afl-instrument", + false, + "Enable instrumentation for afl-fuzz"; + + "-afl-inst-ratio", + false, + "Configure percentage of branches instrumented\n (advanced, see afl-fuzz docs for AFL_INST_RATIO)"; + + "-annot", + false, + " (deprecated) Save information in <filename>.annot"; + + "-bin-annot", + false, + " Save typedtree in <filename>.cmt"; + + "-inline-branch-factor", + true, + "<n>|<round>=<n>[,...] Estimate the probability of a branch being cold as 1/(1+n) (used for inlining) (default 0.10)"; + + "-c", + false, + " Compile only (do not link)"; + + "-cc", + true, + "<command> Use <command> as the C compiler and linker"; + + "-cclib", + true, + "<opt> Pass option <opt> to the C linker"; + + "-ccopt", + true, + "<opt> Pass option <opt> to the C compiler and linker"; + + "-cmi-file", + true, + "<file> Use the <file> interface file to type-check"; + + "-clambda-checks", + false, + " Instrument clambda code with closure and field access checks (for debugging the compiler)"; + + "-Oclassic", + false, + " Make inlining decisions at function definition time rather than at the call site (replicates previous behaviour of the compiler)"; + + "-color", + true, + "{auto|always|never} Enable or disable colors in compiler messages\n The following settings are supported:\n auto use heuristics to enable colors only if supported\n always enable colors\n never disable colors\n The default setting is 'auto', and the current heuristic\n checks that the TERM environment variable exists and is\n not empty or \"dumb\", and that isatty(stderr) holds.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_COLOR environment variable."; + + "-error-style", + true, + "{contextual|short} Control the way error messages and warnings are printed\n The following settings are supported:\n short only print the error and its location\n contextual like \"short\", but also display the source code\n snippet corresponding to the location of the error\n The default setting is 'contextual'.\n If the option is not specified, these setting can alternatively\n be set through the OCAML_ERROR_STYLE environment variable."; + + "-compact", + false, + " Optimize code size rather than speed"; + + "-config", + false, + " Print configuration values and exit"; + + "-config-var", + false, + " Print the value of a configuration variable, without a newline, and exit\n (print nothing and exit with error value if the variable does not exist)"; + + "-dtypes", + false, + " (deprecated) same as -annot"; + + "-for-pack", + true, + "<ident> Generate code that can later be `packed' with\n ocamlopt -pack -o <ident>.cmx"; + + "-g", + false, + " Record debugging information for exception backtrace"; + + "-function-sections", + false, + " Generate each function in a separate section if target supports it"; + + "-stop-after", + true, + "{parsing|typing|scheduling|emit} Stop after the given compilation pass."; + + "-save-ir-after", + true, + "{scheduling} Save intermediate representation after the given compilation pass(may be specified more than once)."; + + "-i", + false, + " Print inferred interface"; + + "-I", + true, + "<dir> Add <dir> to the list of include directories"; + + "-impl", + true, + "<file> Compile <file> as a .ml file"; + + "-inline", + true, + "<n>|<round>=<n>[,...] Aggressiveness of inlining (default 1.25, higher numbers mean more aggressive)"; + + "-inline-toplevel", + true, + "<n>|<round>=<n>[,...] Aggressiveness of inlining at toplevel (higher numbers mean more aggressive)"; + + "-inline-alloc-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing an allocation during inlining (default 7, higher numbers more costly)"; + + "-inline-branch-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing a conditional during inlining (default 5, higher numbers more costly)"; + + "-inline-call-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing a call during inlining (default 5, higher numbers more costly)"; + + "-inline-prim-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing a primitive during inlining (default 3, higher numbers more costly)"; + + "-inline-indirect-cost", + true, + "<n>|<round>=<n>[,...] The cost of not removing an indirect call during inlining (default 4, higher numbers more costly)"; + + "-inline-lifting-benefit", + true, + "<n>|<round>=<n>[,...] The benefit of lifting definitions to toplevel during inlining (default 1300, higher numbers more beneficial)"; + + "-inlining-report", + false, + " Emit `.<round>.inlining' file(s) (one per round) showing the inliner's decisions"; + + "-insn-sched", + false, + " Run the instruction scheduling pass (default)"; + + "-intf", + true, + "<file> Compile <file> as a .mli file"; + + "-intf-suffix", + true, + "<string> Suffix for interface files (default: .mli)"; + + "-keep-docs", + false, + " Keep documentation strings in .cmi files"; + + "-no-keep-docs", + false, + " Do not keep documentation strings in .cmi files (default)"; + + "-keep-locs", + false, + " Keep locations in .cmi files (default)"; + + "-no-keep-locs", + false, + " Do not keep locations in .cmi files"; + + "-labels", + false, + " Use commuting label mode"; + + "-linkall", + false, + " Link all modules, even unused ones"; + + "-inline-max-depth", + true, + "<n>|<round>=<n>[,...] Maximum depth of search for inlining opportunities inside inlined functions (default 1)"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-linscan", + false, + " Use the linear scan register allocator"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-no-float-const-prop", + false, + " Deactivate constant propagation for floating-point operations"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-noautolink", + false, + " Do not automatically link C libraries specified in .cmxa files"; + + "-nodynlink", + false, + " Enable optimizations for code that will not be dynlinked"; + + "-no-insn-sched", + false, + " Do not run the instruction scheduling pass"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nocwd", + false, + " Do not implicitly add the current directory to the load path"; + + "-nopervasives", + false, + " (undocumented)"; + + "-no-unbox-free-vars-of-closures", + false, + " Do not unbox variables that will appear inside function closures"; + + "-no-unbox-specialised-args", + false, + " Do not unbox arguments to which functions have been specialised"; + + "-o", + true, + "<file> Set output file name to <file>"; + + "-O2", + false, + " Apply increased optimization for speed"; + + "-O3", + false, + " Apply aggressive optimization for speed (may significantly increase code size and compilation time)"; + + "-opaque", + false, + " Does not generate cross-module optimization information\n (reduces necessary recompilation on module change)"; + + "-open", + true, + "<module> Opens the module <module> before typing"; + + "-output-obj", + false, + " Output an object file instead of an executable"; + + "-output-complete-obj", + false, + " Output an object file, including runtime, instead of an executable"; + + "-p", + false, + " (no longer supported)"; + + "-pack", + false, + " Package the given .cmx files into one .cmx"; + + "-plugin", + true, + "<plugin> (no longer supported)"; + + "-pp", + true, + "<command> Pipe sources through preprocessor <command>"; + + "-ppx", + true, + "<command> Pipe abstract syntax trees through preprocessor <command>"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-remove-unused-arguments", + false, + " Remove unused function arguments"; + + "-rounds", + true, + "<n> Repeat tree optimization and inlining phases this many times (default 1). Rounds are numbered starting from zero."; + + "-runtime-variant", + true, + "<str> Use the <str> variant of the run-time system"; + + "-with-runtime", + false, + "Include the runtime system in the generated program (default)"; + + "-without-runtime", + false, + "Do not include the runtime system in the generated program."; + + "-S", + false, + " Keep intermediate assembly file"; + + "-safe-string", + false, + " (default unconditionally since 5.0)"; + + "-shared", + false, + " Produce a dynlinkable plugin"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unbox-closures", + false, + " Pass free variables via specialised arguments rather than closures"; + + "-unbox-closures-factor", + true, + "<n > 0> Scale the size threshold above which unbox-closures will slow down indirect calls rather than duplicating a function (default 10)"; + + "-inline-max-unroll", + true, + "<n>|<round>=<n>[,...] Unroll recursive functions at most this many times (default 0)"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe", + false, + " Do not compile bounds checking on array and string access"; + + "-unsafe-string", + false, + " (option not available)"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + "<list> Enable or disable warnings according to <list>:\n +<spec> enable warnings in <spec>\n -<spec> disable warnings in <spec>\n @<spec> enable warnings in <spec> and treat them as errors\n <spec> can be:\n <num> a single warning number\n <num1>..<num2> a range of consecutive warning numbers\n <letter> a predefined set\n default setting is \"+a-4-7-9-27-29-30-32..42-44-45-48-50-60-66..70\""; + + "-warn-error", + true, + "<list> Enable or disable error status for warnings according\n to <list>. See option -w for the syntax of <list>.\n Default setting is \"-a+31\""; + + "-warn-help", + false, + " Show description of warning numbers"; + + "-where", + false, + " Print location of standard library and exit"; + + "-", + true, + "<file> Treat <file> as a file name (even if it starts with `-')"; + + "-match-context-rows", + true, + "<n> (advanced, see manual section 13.2.)"; + + "-dno-unique-ids", + false, + " (undocumented)"; + + "-dunique-ids", + false, + " (undocumented)"; + + "-dno-locations", + false, + " (undocumented)"; + + "-dlocations", + false, + " (undocumented)"; + + "-dsource", + false, + " (undocumented)"; + + "-dparsetree", + false, + " (undocumented)"; + + "-dtypedtree", + false, + " (undocumented)"; + + "-dshape", + false, + " (undocumented)"; + + "-drawlambda", + false, + " (undocumented)"; + + "-dlambda", + false, + " (undocumented)"; + + "-drawclambda", + false, + " (undocumented)"; + + "-dclambda", + false, + " (undocumented)"; + + "-dcmm-invariants", + false, + " Extra sanity checks on Cmm"; + + "-dflambda", + false, + " Print Flambda terms"; + + "-drawflambda", + false, + " Print Flambda terms after closure conversion"; + + "-dflambda-invariants", + false, + " Check Flambda invariants around each pass"; + + "-dflambda-no-invariants", + false, + " Do not Check Flambda invariants around each pass"; + + "-dflambda-let", + true, + "<stamp> Print when the given Flambda [Let] is created"; + + "-dflambda-verbose", + false, + " Print Flambda terms including around each pass"; + + "-dcmm", + false, + " (undocumented)"; + + "-dsel", + false, + " (undocumented)"; + + "-dcombine", + false, + " (undocumented)"; + + "-dcse", + false, + " (undocumented)"; + + "-dlive", + false, + " (undocumented)"; + + "-dspill", + false, + " (undocumented)"; + + "-dsplit", + false, + " (undocumented)"; + + "-dinterf", + false, + " (undocumented)"; + + "-dprefer", + false, + " (undocumented)"; + + "-dalloc", + false, + " (undocumented)"; + + "-dreload", + false, + " (undocumented)"; + + "-dscheduling", + false, + " (undocumented)"; + + "-dlinear", + false, + " (undocumented)"; + + "-dinterval", + false, + " (undocumented)"; + + "-dstartup", + false, + " (undocumented)"; + + "-dtimings", + false, + " Print timings information for each pass"; + + "-dprofile", + false, + " Print performance information for each pass\n The columns are: time alloc top-heap absolute-top-heap."; + + "-dump-into-file", + false, + " dump output like -dlambda into <target>.dump"; + + "-dump-dir", + true, + "<dir> dump output like -dlambda into <dir>/<target>.dump"; + + "-dump-pass", + false, + " Record transformations performed by these passes:\n unbox-closures unbox-specialised-args unbox-free-vars-of-closures\n remove-free-vars-equal-to-args remove-unused-arguments unused-arguments"; + + "-args", + true, + "<file> Read additional newline-terminated command line arguments\n from <file>"; + + "-args0", + true, + "<file> Read additional null character terminated command line arguments\nfrom <file>"; + + "-depend", + true, + "<options> Compute dependencies (use 'ocamlopt -depend -help' for details)"; + +];; + +let ocamldep_spec = Some [ + "-absname", + false, + " Show absolute filenames in error messages"; + + "-all", + false, + " Generate dependencies on all files"; + + "-allow-approx", + false, + " Fallback to a lexer-based approximation on unparsable files"; + + "-as-map", + false, + " Omit delayed dependencies for module aliases (-no-alias-deps -w -49)"; + + "-debug-map", + false, + " Dump the delayed dependency map for each map file"; + + "-I", + true, + "<dir> Add <dir> to the list of include directories"; + + "-nocwd", + false, + " Do not add current working directory to the list of include directories"; + + "-impl", + true, + "<f> Process <f> as a .ml file"; + + "-intf", + true, + "<f> Process <f> as a .mli file"; + + "-map", + true, + "<f> Read <f> and propagate delayed dependencies to following files"; + + "-ml-synonym", + true, + "<e> Consider <e> as a synonym of the .ml extension"; + + "-mli-synonym", + true, + "<e> Consider <e> as a synonym of the .mli extension"; + + "-modules", + false, + " Print module dependencies in raw form (not suitable for make)"; + + "-native", + false, + " Generate dependencies for native-code only (no .cmo files)"; + + "-bytecode", + false, + " Generate dependencies for bytecode-code only (no .cmx files)"; + + "-one-line", + false, + " Output one line per file, regardless of the length"; + + "-open", + true, + "<module> Opens the module <module> before typing"; + + "-plugin", + true, + "<plugin> (no longer supported)"; + + "-pp", + true, + "<cmd> Pipe sources through preprocessor <cmd>"; + + "-ppx", + true, + "<cmd> Pipe abstract syntax trees through preprocessor <cmd>"; + + "-shared", + false, + " Generate dependencies for native plugin files (.cmxs targets)"; + + "-slash", + false, + " (Windows) Use forward slash / instead of backslash \\ in file paths"; + + "-no-slash", + false, + " (Windows) Preserve any backslash \\ in file paths"; + + "-sort", + false, + " Sort files according to their dependencies"; + + "-version", + false, + " Print version and exit"; + + "-vnum", + false, + " Print version number and exit"; + + "-args", + true, + "<file> Read additional newline separated command line arguments \n from <file>"; + + "-args0", + true, + "<file> Read additional NUL separated command line arguments from \n <file>"; + +];; + +let ocamldoc_spec = Some [ + "-absname", + false, + " Show absolute filenames in error messages"; + + "-alert", + true, + "<list> Enable or disable alerts according to <list>:\n +<alertname> enable alert <alertname>\n -<alertname> disable alert <alertname>\n ++<alertname> treat <alertname> as fatal error"; + + "--", + true, + "<alertname> treat <alertname> as non-fatal\n @<alertname> enable <alertname> and treat it as fatal error\n <alertname> can be 'all' to refer to all alert names"; + + "-I", + true, + "<dir> Add <dir> to the list of include directories"; + + "-impl", + true, + "<file> Compile <file> as a .ml file"; + + "-intf", + true, + "<file> Compile <file> as a .mli file"; + + "-intf-suffix", + true, + "<string> Suffix for interface files (default: .mli)"; + + "-intf_suffix", + true, + "<string> (deprecated) same as -intf-suffix"; + + "-labels", + false, + " Use commuting label mode"; + + "-modern", + false, + " (deprecated) same as -labels"; + + "-alias-deps", + false, + " Do record dependencies for module aliases"; + + "-no-alias-deps", + false, + " Do not record dependencies for module aliases"; + + "-app-funct", + false, + " Activate applicative functors"; + + "-no-app-funct", + false, + " Deactivate applicative functors"; + + "-noassert", + false, + " Do not compile assertion checks"; + + "-nolabels", + false, + " Ignore non-optional labels in types"; + + "-nostdlib", + false, + " Do not add default directory to the list of include directories"; + + "-nocwd", + false, + " Do not implicitly add the current directory to the load path"; + + "-open", + true, + "<module> Opens the module <module> before typing"; + + "-pp", + true, + "<command> Pipe sources through preprocessor <command>"; + + "-ppx", + true, + "<command> Pipe abstract syntax trees through preprocessor <command>"; + + "-principal", + false, + " Check principality of type inference"; + + "-no-principal", + false, + " Do not check principality of type inference (default)"; + + "-rectypes", + false, + " Allow arbitrary recursive types"; + + "-no-rectypes", + false, + " Do not allow arbitrary recursive types (default)"; + + "-safe-string", + false, + " (default unconditionally since 5.0)"; + + "-short-paths", + false, + " Shorten paths in types"; + + "-strict-sequence", + false, + " Left-hand part of a sequence must have type unit"; + + "-no-strict-sequence", + false, + " Left-hand part of a sequence need not have type unit (default)"; + + "-strict-formats", + false, + " Reject invalid formats accepted by legacy implementations\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should always use this flag\n to detect invalid formats so you can fix them.)"; + + "-no-strict-formats", + false, + " Accept invalid formats accepted by legacy implementations (default)\n (Warning: Invalid formats may behave differently from\n previous OCaml versions, and will become always-rejected\n in future OCaml versions. You should never use this flag\n and instead fix invalid formats.)"; + + "-thread", + false, + " (deprecated) same as -I +threads"; + + "-unboxed-types", + false, + " unannotated unboxable types will be unboxed"; + + "-no-unboxed-types", + false, + " unannotated unboxable types will not be unboxed (default)"; + + "-unsafe-string", + false, + " (option not available)"; + + "-v", + false, + " Print compiler version and location of standard library and exit"; + + "-verbose", + false, + " Print calls to external commands"; + + "-version", + false, + " Print version and exit"; + + "--version", + false, + " Print version and exit"; + + "-vmthread", + false, + " (no longer supported)"; + + "-vnum", + false, + " Print version number and exit"; + + "-w", + true, + "<list> Enable or disable warnings according to <list>:\n +<spec> enable warnings in <spec>\n -<spec> disable warnings in <spec>\n @<spec> enable warnings in <spec> and treat them as errors\n <spec> can be:\n <num> a single warning number\n <num1>..<num2> a range of consecutive warning numbers\n <letter> a predefined set\n default setting is \"+a-4-7-9-27-29-30-32..42-44-45-48-50-60-66..70\""; + + "-", + true, + "<file> Treat <file> as a file name (even if it starts with `-')"; + + "-initially-opened-module", + true, + "<module> Name of the module that is initially opened"; + + "-lib", + true, + "<module> Name of the library namespace for a prefixed library.Note: very experimental."; + + "-text", + true, + "<file> Consider <file> as a .txt file"; + + "-warn-error", + false, + " Treat ocamldoc warnings as errors"; + + "-show-missed-crossref", + false, + " Show missed cross-reference opportunities"; + + "-hide-warnings", + false, + " do not print ocamldoc warnings"; + + "-o", + true, + "<file> Set the output file name, used by texi, latex and dot generators\n\t\t(default is ocamldoc.out)\n\t\tor the prefix of index files for the HTML generator\n\t\t(default is index)"; + + "-d", + true, + "<dir> Generate files in directory <dir>, rather than in current\n\t\tdirectory (for man and HTML generators)"; + + "-sort", + false, + " Sort the list of top modules before generating the documentation"; + + "-no-stop", + false, + " Do not stop at (**/**) comments"; + + "-no-custom-tags", + false, + " Do not allow custom @-tags"; + + "-stars", + false, + " Remove beginning blanks of comment lines, until the first '*'"; + + "-inv-merge-ml-mli", + false, + " Inverse implementations and interfaces when merging"; + + "-no-module-constraint-filter", + false, + "Do not filter module elements using module type constraints"; + + "-keep-code", + false, + " Always keep code when available\n"; + + "-dump", + true, + "<file> Dump collected information into <file>"; + + "-load", + true, + "<file> Load information from <file> ; may be used several times\n"; + + "-t", + true, + "<title> Use <title> as title for the generated documentation"; + + "-intro", + true, + "<file> Use content of <file> as ocamldoc text to use as introduction\n\t\t(HTML, LaTeX and TeXinfo only)"; + + "-hide", + true, + "<M1,M2.M3,...> Hide the given complete module names in generated doc"; + + "-m", + true, + "<options> specify merge options between .mli and .ml\n\t\t<options> can be one or more of the following characters:\n\t\td merge description\n\t\ta merge @author\n\t\tv merge @version\n\t\tl merge @see\n\t\ts merge @since\n\t\tb merge @before\n\t\to merge @deprecated\n\t\tp merge @param\n\t\te merge @raise\n\t\tr merge @return\n\t\tc merge custom @-tags\n\t\tA merge all\n\n *** choosing a generator ***\n"; + + "-html", + false, + " Generate HTML documentation"; + + "-latex", + false, + " Generate LaTeX documentation"; + + "-texi", + false, + " Generate TeXinfo documentation"; + + "-man", + false, + " Generate man pages"; + + "-dot", + false, + " Generate dot code of top modules dependencies"; + + "-customdir", + false, + "Display custom generators standard directory and exit"; + + "-i", + true, + "<dir> Add the given directory to the search path for custom\n\t\tgenerators"; + + "-g", + true, + "<file.cm[o|a|xs]> Load file defining a new documentation generator\n\n *** HTML options ***\n"; + + "-all-params", + false, + " Display the complete list of parameters for functions and\n\t\tmethods (HTML only)"; + + "-css-style", + true, + "<file> Use content of <file> as CSS style definition (HTML only)"; + + "-index-only", + false, + " Generate index files only (HTML only)"; + + "-colorize-code", + false, + " Colorize code even in documentation pages (HTML only)"; + + "-short-functors", + false, + " Use short form to display functor types (HTML only)"; + + "-charset", + true, + "<s> Add information about character encoding being s\n\t\t(default is iso-8859-1)"; + + "-nonavbar", + false, + " Do not include the navigation bar (HTML only)\n\n *** LaTeX options ***\n"; + + "-noheader", + false, + " Suppress header in generated documentation\n\t\t(LaTeX and TeXinfo only)"; + + "-notrailer", + false, + " Suppress trailer in generated documentation\n\t\t(LaTeX and TeXinfo only)"; + + "-sepfiles", + false, + " Generate one file per toplevel module (LaTeX only)"; + + "-latextitle", + false, + "n,style Associate {n } to the given sectioning style\n\t\t(e.g. 'section') in the latex output (LaTeX only)\n\t\tDefault sectioning is:\n\t\t 0 -> section\n\t\t 1 -> section\n\t\t 2 -> subsection\n\t\t 3 -> subsubsection\n\t\t 4 -> paragraph\n\t\t 5 -> subparagraph"; + + "-latex-value-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of values.\n\t\t(default is \"val:\")"; + + "-latex-type-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of types.\n\t\t(default is \"type:\")"; + + "-latex-exception-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of exceptions.\n\t\t(default is \"exception:\")"; + + "-latex-attribute-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of attributes.\n\t\t(default is \"val:\")"; + + "-latex-method-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of methods.\n\t\t(default is \"method:\")"; + + "-latex-module-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of modules.\n\t\t(default is \"module:\")"; + + "-latex-module-type-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of module types.\n\t\t(default is \"moduletype:\")"; + + "-latex-class-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of classes.\n\t\t(default is \"class:\")"; + + "-latex-class-type-prefix", + true, + "<string>\n\t\tUse <string> as prefix for the LaTeX labels of class types.\n\t\t(default is \"classtype:\")"; + + "-notoc", + false, + " Do not generate table of contents (LaTeX only)\n\n *** texinfo options ***\n"; + + "-noindex", + false, + " Do not build index for Info files (TeXinfo only)"; + + "-esc8", + false, + " Escape accentuated characters in Info files (TeXinfo only)"; + + "-texinfotitle", + false, + "n,style Associate {n } to the given sectioning style\n\t\t(e.g. 'section') in the texInfo output (TeXinfo only)\n\t\tDefault sectioning is:\n\t\t 0 -> @chapter , @majorheading \n\t\t 1 -> @chapter , @majorheading \n\t\t 2 -> @section , @heading \n\t\t 3 -> @subsection , @subheading \n\t\t 4 -> @subsubsection , @subsubheading "; + + "-info-section", + false, + " Specify section of Info directory (TeXinfo only)"; + + "-info-entry", + false, + " Specify Info directory entry (TeXinfo only)\n\n *** dot options ***\n"; + + "-dot-colors", + true, + " <c1,c2,...,cn>\n\t\tUse colors c1,c1,...,cn in the dot output\n\t\t(default list is darkturquoise,darkgoldenrod2,cyan,green,\n\t\tmagenta,yellow,burlywood1,aquamarine,floralwhite,lightpink,\n\t\tlightblue,mediumturquoise,salmon,slategray3)"; + + "-dot-include-all", + false, + " Include all modules in the dot output, not only the\n\t\tmodules given on the command line"; + + "-dot-types", + false, + " Generate dependency graph for types instead of modules"; + + "-dot-reduce", + false, + " Perform a transitive reduction on the selected dependency graph\n\t\tbefore the dot output\n\n *** man pages options ***\n"; + + "-man-mini", + false, + " Generate man pages only for modules, module types, classes\n\t\tand class types (man only)"; + + "-man-suffix", + true, + "<suffix> Use <suffix> for man page files (default is 3o) (man only)\n"; + + "-man-section", + true, + "<section> Use <section> in man page files (default is 3) (man only)\n"; + +];; + diff --git a/local-packages/ocamlfind/src/findlib/test_parser.ml b/local-packages/ocamlfind/src/findlib/test_parser.ml new file mode 100644 index 0000000..717b74e --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/test_parser.ml @@ -0,0 +1,87 @@ +let with_open_in file func = + let chan = open_in file in + let result = + try func chan + with exn -> close_in chan; raise exn + in + close_in chan; result +;; + +type test_mode = Compare_both | Only of (old_or_new * int) +and old_or_new = Old | New + +let read_file file = + let buf = Buffer.create 100 in + with_open_in file (fun ch -> + try while true do Buffer.add_string buf (input_line ch) done + with End_of_file -> ()); + Buffer.contents buf + +let test mode file = + match mode with + | Compare_both -> + let ast1 = with_open_in file Fl_metascanner.parse in + let ast2 = with_open_in file Fl_metascanner.parse2 in + Printf.printf "%s tested %s\n" file (if ast1 = ast2 then "OK" else "FAIL") + | Only (old_or_new, niter) -> + let content = read_file file in + for i = 1 to niter do + let parse = match old_or_new with + | Old -> Fl_metascanner.parse_lexing + | New -> Fl_metascanner.parse2_lexing in + ignore (parse (Lexing.from_string content)) + done + +let rec explore mode path = + if Sys.is_directory path then + let traverse file = explore mode (Filename.concat path file) in + Array.iter traverse (Sys.readdir path) + else if Filename.basename path = "META" then + test mode path + +let () = + let test_mode, targets = (* command-line option handling *) + let only_old = ref false in + let only_new = ref false in + let niter = ref 1 in + let targets = ref [] in + let usage = "test_parser <options> <path> <path> ....\n \ + recursively traverse paths and compare the two parsers \ + on each file named META" + in + let options = [ + ("--niter", Arg.Set_int niter, "iterate the parser for performance comparison (only in --only-old or --only-new modes)"); + ("--only-old", Arg.Set only_old, "only test the old parser"); + ("--only-new", Arg.Set only_new, "only test the new parser"); + ] in + let action path = targets := path :: !targets in + Arg.parse options action usage; + let quit_with_usage () = Arg.usage options usage; exit 1 in + let test_mode = + match !only_old, !only_new with + | false, false -> Compare_both + | false, true -> Only (New, !niter) + | true, false -> Only (Old, !niter) + | true, true -> + prerr_endline "--only-only and --new-only cannot be \ + both set at the same time"; + quit_with_usage (); + in + if !targets = [] then quit_with_usage (); + test_mode, !targets + in + let traverse path = + if Sys.file_exists path then explore test_mode path + else Printf.eprintf "Error: path %s does not exist and was ignored.\n" path + in + List.iter traverse targets + + + + + + + + + + diff --git a/local-packages/ocamlfind/src/findlib/topfind.ml.in b/local-packages/ocamlfind/src/findlib/topfind.ml.in new file mode 100644 index 0000000..8d12631 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/topfind.ml.in @@ -0,0 +1,340 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +let predicates = ref ("toploop" :: Findlib.recorded_predicates());; + (* We also want things like "syntax" here which are not allowed in + Findlib, hence we maintain our own list + *) + +let directories = ref [ Findlib.ocaml_stdlib() ];; + + +(* Note: Sys.interactive is always _true_ during toploop startup. + * When a script is executed, it is set to false just before the + * script starts. This is important for ocamlmktop-generated toploops: + * For initialization code linked into the toploop, Sys.interactive + * is _true_. It is set to false just before the script starts. + *) + +let real_toploop = + !Sys.interactive;; + +let log = ref (if real_toploop then prerr_endline else ignore) + +let rec remove_dups l = + match l with + x :: l' -> + if List.mem x l' then remove_dups l' else x::remove_dups l' + | [] -> [] +;; + +let add_predicates pl = + predicates := remove_dups (pl @ !predicates); + Findlib.record_package_predicates !predicates;; + +let syntax s = + add_predicates [ "syntax"; s ];; + +let standard_syntax () = syntax "camlp4o";; +let revised_syntax () = syntax "camlp4r";; + + +let add_dir d = + let d = Fl_split.norm_dir d in + if not (List.mem d !directories) then begin + Topdirs.dir_directory d; + directories := d :: !directories; + !log (d ^ ": added to search path") + end +;; + +let exec_string s = + let l = Lexing.from_string s in + let ph = !Toploop.parse_toplevel_phrase l in +(* PPXOPT_BEGIN *) + let ph = Toploop.preprocess_phrase Format.err_formatter ph in +(* PPXOPT_END *) + let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in + try + Toploop.execute_phrase false fmt ph + with + _ -> false +;; + +let load pkglist = + List.iter + (fun pkg -> + let _stdlibdir = Findlib.ocaml_stdlib() in + let loaded = + Findlib.is_recorded_package pkg && + Findlib.type_of_recorded_package pkg = Findlib.Record_load in + let incore = + Findlib.is_recorded_package pkg && + Findlib.type_of_recorded_package pkg = Findlib.Record_core in + if not loaded then begin + (* Determine the package directory: *) + let d = Findlib.package_directory pkg in + add_dir d; + (* Leave pkg out if mentioned in !forbidden *) + if not incore then begin + (* Determine the 'archive' property: *) + let archive = + try Findlib.package_property !predicates pkg "archive" + with + Not_found -> "" + in + (* Split the 'archive' property and load the files: *) + let archives = Fl_split.in_words archive in + List.iter + (fun arch -> + let arch' = Findlib.resolve_path ~base:d arch in + !log (arch' ^ ": loaded"); + Topdirs.dir_load + Format.std_formatter arch') + archives; + (* Determine the 'ppx' property: *) + let ppx = + try + Some(Findlib.resolve_path + ~base:d ~explicit:true + (Findlib.package_property !predicates pkg "ppx") + ) + with Not_found -> None + and ppxopts = + try + List.map + (fun opt -> + match Fl_split.in_words opt with + | pkg :: opts -> + pkg, + List.map + (Findlib.resolve_path ~base:d ~explicit:true) opts + | _ -> assert false) + (Fl_split.in_words_ws + (Findlib.package_property !predicates pkg "ppxopt")) + with Not_found -> [] in + (* Feed the 'ppx' property into the toplevel. To remain compatible + with pre-4.01 OCaml, construct and execute a phrase instead of directly + altering Clflags. *) + begin match ppx with + | Some ppx -> + + + begin try + match Hashtbl.find Toploop.directive_table "ppx" with + | Toploop.Directive_string fn -> + fn ppx; !log (ppx ^ ": activated") + | _ -> assert false + with Not_found -> + failwith "Package defines a ppx preprocessor, but OCaml is too old. \ + Use OCaml >= 4.02.0 for ppx support." + end + | None -> () + end; + (* Feed the 'ppxopt' property into the toplevel. *) + match ppxopts with + | [] -> () + | _ -> +(* PPXOPT_BEGIN *) + List.iter + (fun (pkg, opts) -> + ignore (exec_string ("[@@@findlib.ppxopt " ^ + (String.concat ", " + (List.map (Printf.sprintf "%S") (pkg :: opts))) ^ + "];;")); + !log (pkg ^ ": " ^ (String.concat " " opts) ^ + ": option added")) + ppxopts +(* +(* PPXOPT_END *) + failwith "Package defines a ppx preprocessor option, but OCaml is too old. \ + Use OCaml >=4.02.1 for ppxopt support." +(* PPXOPT_BEGIN *) +*) +(* PPXOPT_END *) + end; + (* The package is loaded: *) + Findlib.record_package Findlib.Record_load pkg + end) + pkglist +;; + + +let load_deeply pkglist = + (* Get the sorted list of ancestors *) + let eff_pkglist = + Findlib.package_deep_ancestors !predicates pkglist in + List.iter (fun pkg -> + try let error = Findlib.package_property !predicates pkg "error" in + failwith ("Error from package `" ^ pkg ^ "': " ^ error) + with Not_found -> ()) eff_pkglist ; + (* Load the packages in turn: *) + load eff_pkglist +;; + + +let check_existence pkglist = + List.iter + (fun pkg -> + let _ = Findlib.package_directory pkg in () + ) + pkglist +;; + + +let don't_load pkglist = + check_existence pkglist; + List.iter (Findlib.record_package Findlib.Record_core) pkglist +;; + + +let don't_load_deeply pkglist = + (* Check if packages exist: *) + check_existence pkglist; + (* Get the sorted list of ancestors *) + let eff_pkglist = + Findlib.package_deep_ancestors !predicates pkglist in + (* Add this to the list of core packages: *) + List.iter (Findlib.record_package Findlib.Record_core) eff_pkglist +;; + + +let reset() = + Findlib.reset_recordings() +;; + + +let have_mt_support() = + Findlib.package_property [] "threads" "type_of_threads" = "posix" +;; + + +let load_mt_support() = + (* Load only if package "threads" is not yet loaded. *) + if not(Findlib.is_recorded_package "threads") then ( + (* This works only for POSIX threads. *) + if have_mt_support() then ( + add_predicates ["mt"; "mt_posix"]; + add_dir (Filename.concat (Findlib.ocaml_stdlib()) "threads"); + load_deeply ["unix"]; + load_deeply ["threads"]; + ) + else ( + failwith "It is not possible to load support for vmthreads dynamically. Use\n +'ocamlfind ocamlmktop -o vmtop -package threads,findlib -linkpkg -vmthread'\n +to create a toploop with integrated vmthreads library." + ) + ) +;; + + +let list_packages() = + Findlib.list_packages stdout; + flush stdout +;; + + +let protect f arg = + try + let _ = f arg in () + with + Failure s -> + print_endline s + | Fl_package_base.No_such_package(pkg, reason) -> + print_endline ("No such package: " ^ pkg ^ + (if reason <> "" then " - " ^ reason else "")) + | Fl_package_base.Package_loop pkg -> + print_endline ("Package requires itself: " ^ pkg) +;; + + +(* Add "#require" directive: *) + +Hashtbl.add + Toploop.directive_table + "require" + (Toploop.Directive_string + (fun s -> + protect load_deeply (Fl_split.in_words s) + )) +;; + +(* Add "#predicates" directive: *) +Hashtbl.add + Toploop.directive_table + "predicates" + (Toploop.Directive_string + (fun s -> + protect add_predicates (Fl_split.in_words s) + )) +;; + + +(* Add "#camlp4o" directive: *) + +Hashtbl.add + Toploop.directive_table + "camlp4o" + (Toploop.Directive_none + (fun () -> + protect (fun () -> + standard_syntax(); + load_deeply ["camlp4"]) () + )) +;; + +(* Add "#camlp4r" directive: *) + +Hashtbl.add + Toploop.directive_table + "camlp4r" + (Toploop.Directive_none + (fun () -> + protect (fun () -> + revised_syntax(); + load_deeply ["camlp4"]) () + )) +;; + + +(* Add "#list" directive: *) + +Hashtbl.add + Toploop.directive_table + "list" + (Toploop.Directive_none + (fun () -> + protect list_packages () + )) +;; + + +(* Add "#thread" directive: *) + +Hashtbl.add + Toploop.directive_table + "thread" + (Toploop.Directive_none + (fun () -> + protect load_mt_support () + )) +;; + + +let announce() = + if real_toploop then begin + (* Assume we are in a toploop and not a script *) + let msg_thread = + " #thread;; to enable threads\n" in + print_endline + ("Findlib has been successfully loaded. Additional directives:\n" ^ + " #require \"package\";; to load a package\n" ^ + " #list;; to list the available packages\n" ^ + " #camlp4o;; to load camlp4 (standard syntax)\n" ^ + " #camlp4r;; to load camlp4 (revised syntax)\n" ^ + " #predicates \"p,q,...\";; to set these predicates\n" ^ + " Topfind.reset();; to force that packages will be reloaded\n" ^ + (if have_mt_support() then msg_thread else "")) + end ;; diff --git a/local-packages/ocamlfind/src/findlib/topfind.mli b/local-packages/ocamlfind/src/findlib/topfind.mli new file mode 100644 index 0000000..f311200 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/topfind.mli @@ -0,0 +1,122 @@ +(* $Id$ + * ---------------------------------------------------------------------- + * + *) + +(** Load packages from toploops and scripts + * + * The [Topfind] module is part of the [findlib] package. The module + * depends on the presence of a toploop. When building a toploop, it is + * automatically linked in if "findlib" is linked in, e.g. + * {[ + * ocamlfind ocamlmktop ...options... -package findlib -linkpkg + * ]} + * + * When the platform supports DLLs, another possibility to get a toploop + * with findlib directives is to load the file "topfind" (normally installed + * in the standard library directory): + * {[ + * $ ocaml + * Objective Caml version 3.04 + * # #use "topfind";; + * Findlib has been successfully loaded. Additional directives: + * #require "package";; to load a package + * #list;; to list the available packages + * #camlp4o;; to load camlp4 (standard syntax) + * #camlp4r;; to load camlp4 (revised syntax) + * Topfind.reset();; to force that packages will be reloaded + * ~ : unit = () + * # _ + * ]} + * + * This works even in scripts (but the startup message is suppressed in this + * case). + * + * The module is not thread-safe; if used in a multi-threaded script, all + * packgage loading must have happened before the first thread forks. + * + * The Topfind module contains some functions simplifying package loading + * in scripts. Most important, there is a new directive [#require] for + * the same purpose (see below). + * + * The [Topfind] module needs some initialization, in particular the + * [predicates] variable needs to be + * set, and the packages already compiled into the toploop needs to be + * declared by the [don't_load] + * function. If the toploop has been built by [ocamlfind], + * the necessary initialization is + * automatically compiled in. + *) + +(** {1 Directives} + * + * This module also defines the following directives for the toploop: + * + * - [#require "<package>"] + * loads the package (and if necessary the prerequisites of the package) + * - [#camlp4o] + * loads camlp4 and selects standard syntax + * - [#camlp4r] + * loads camlp4 and selects revised syntax + * - [#list] + * lists the available packages (calls external command "ocamlfind") + * - [#thread] + * enables multi-threading if possible + * - [#predicates "p1,p2,..."] + * adds these predicates + *) + +(** {1 Functions and variables} *) + +val predicates : string list ref + (** The list of predicates used for package loading *) + +val add_predicates : string list -> unit + (** Adds predicates to the list of predicates *) + +val syntax : string -> unit + (** Emulates the [-syntax] option *) + +val standard_syntax : unit -> unit + (** Adds predicates that select the standard syntax. Same as + * [syntax "camlp4o"] + *) + +val revised_syntax : unit -> unit + (** Adds predicates that select the revised syntax. Same as + * [syntax "camlp4r"] + *) + +val don't_load : string list -> unit + (** The packages named in pkglist are added to the list of packages which + * are already loaded. + *) + +val don't_load_deeply : string list -> unit + (** The packages named in pkglist and all direct and indirect ancestors + * are added to the list of packages which are already loaded. + *) + +val load : string list -> unit + (** The packages from the passed package list are loaded, from left to + * right, but packages that have already been loaded are left out. + *) + +val load_deeply : string list -> unit + (** The packages from the passed package list and all direct or indirect + * ancestors are loaded in topological order. Packages that have already + * been loaded are left out. + *) + +val reset : unit -> unit + (** All entries in the list of loaded packages that have been added by + * [load] or [load_deeply] functions are removed from this list. This + * means that if you execute the same [load] or [load_deeply] functions + * again, the packages will be reloaded. + *) + +val announce : unit -> unit + (** Output the startup message *) + +val log : (string -> unit) ref + (** Function used to log messages from this module. *) diff --git a/local-packages/ocamlfind/src/findlib/topfind_rd0.p b/local-packages/ocamlfind/src/findlib/topfind_rd0.p new file mode 100644 index 0000000..b00a6f8 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/topfind_rd0.p @@ -0,0 +1,40 @@ +(* $Id$ -*- tuareg -*- *) + +(* For Ocaml-3.03 and up, so you can do: #use "topfind" and get a + * working findlib toploop. + *) + +#directory "@SITELIB@/findlib";; + (* OCaml-4.00 requires to have #directory before we load anything *) + +(* First test whether findlib_top is already loaded. If not, load it now. + * The test works by executing the toplevel phrase "Topfind.reset" and + * checking whether this causes an error. + *) +let exec_test s = + let l = Lexing.from_string s in + let ph = !Toploop.parse_toplevel_phrase l in + let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in + try + Toploop.execute_phrase false fmt ph + with + _ -> false +in + +if not(exec_test "Topfind.reset;;") then ( + Topdirs.dir_load Format.err_formatter "@SITELIB@/findlib/findlib.cma"; + Topdirs.dir_load Format.err_formatter "@SITELIB@/findlib/findlib_top.cma"; +);; + +(* Old: *) +(* #load "@SITELIB@/findlib/findlib.cma";; *) +(* #load "@SITELIB@/findlib/findlib_top.cma";; *) + + +(* The following is always executed. It is harmless if findlib was already + * initialized + *) + +Topfind.add_predicates [ "byte"; "toploop" ]; +Topfind.don't_load ["findlib"]; +Topfind.announce();; diff --git a/local-packages/ocamlfind/src/findlib/topfind_rd1.p b/local-packages/ocamlfind/src/findlib/topfind_rd1.p new file mode 100644 index 0000000..a365c23 --- /dev/null +++ b/local-packages/ocamlfind/src/findlib/topfind_rd1.p @@ -0,0 +1,55 @@ +(* $Id$ -*- tuareg -*- *) + +(* For Ocaml-3.03 and up, so you can do: #use "topfind" and get a + * working findlib toploop. + *) + +#directory "@SITELIB@/findlib";; + (* OCaml-4.00 requires to have #directory before we load anything *) + +#directory "+compiler-libs";; + (* For OCaml-4.00. This directory will be later removed from path *) + +(* First test whether findlib_top is already loaded. If not, load it now. + * The test works by executing the toplevel phrase "Topfind.reset" and + * checking whether this causes an error. + *) +let exec_test s = + let l = Lexing.from_string s in + let ph = !Toploop.parse_toplevel_phrase l in + let fmt = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in + try + Toploop.execute_phrase false fmt ph + with + _ -> false +in +let is_native = + (* one of the few observable differences... *) + Gc.((get()).stack_limit) = 0 in +let suffix = + if is_native then "cmxs" else "cma" in +if not(exec_test "Topfind.reset;;") then ( + Topdirs.dir_load Format.err_formatter ("@SITELIB@/findlib/findlib." ^ suffix); + Topdirs.dir_load Format.err_formatter ("@SITELIB@/findlib/findlib_top." ^ suffix); +); +;; + +#remove_directory "+compiler-libs";; + +(* Old: *) +(* #load "@SITELIB@/findlib/findlib.cma";; *) +(* #load "@SITELIB@/findlib/findlib_top.cma";; *) + + +(* The following is always executed. It is harmless if findlib was already + * initialized + *) + +let is_native = + (* one of the few observable differences... *) + Gc.((get()).stack_limit) = 0 in +let pred = + if is_native then "native" else "byte" in +Topfind.add_predicates [ pred; "toploop" ]; +Topfind.don't_load ["findlib"]; +Topfind.announce();; diff --git a/local-packages/ocamlfind/tools/cmd_from_same_dir b/local-packages/ocamlfind/tools/cmd_from_same_dir new file mode 100755 index 0000000..cf7a923 --- /dev/null +++ b/local-packages/ocamlfind/tools/cmd_from_same_dir @@ -0,0 +1,30 @@ +#! /bin/sh + +# Check whether ocamlc and ocamlc.opt are installed in the same +# directory (or whatever command names are passed as $1). + +get_path () { + IFS=":" + for d in $PATH; do + if test -x "$d/$1"; then + IFS="$oldifs" + echo "$d/$1" + return + fi + done + IFS="$oldifs" +#--- The following is not portable enough: +# if test -x `type -p ls`; then +# # type -p works! +# type -p $1 +# else +# # use 'which' instead +# p=`which $1` +# test -x "$p" && echo $p +# fi +} + +p1="$(get_path "$1").opt" +p2="$(get_path "$1.opt")" + +[ "X$p1" = "X$p2" ] diff --git a/local-packages/ocamlfind/tools/collect_files b/local-packages/ocamlfind/tools/collect_files new file mode 100755 index 0000000..b8aacbf --- /dev/null +++ b/local-packages/ocamlfind/tools/collect_files @@ -0,0 +1,16 @@ +#! /bin/sh +# +# $Id$ +# ---------------------------------------------------------------------- +# +# usage: collect_files file ... +# +# Prints the names of the files passed as arguments which actually +# exist and are regular files. + +for x in "$@"; do + if [ -f "$x" ]; then + echo "$x" + fi +done + diff --git a/local-packages/ocamlfind/tools/extract_args/Makefile b/local-packages/ocamlfind/tools/extract_args/Makefile new file mode 100644 index 0000000..4ba6aeb --- /dev/null +++ b/local-packages/ocamlfind/tools/extract_args/Makefile @@ -0,0 +1,10 @@ +all: extract_args + +extract_args.ml: extract_args.mll + ocamllex -o extract_args.ml extract_args.mll + +extract_args: extract_args.ml + ocamlc -o extract_args extract_args.ml + +clean: + rm -f *.cmo *.cmi *.cma extract_args extract_args.ml diff --git a/local-packages/ocamlfind/tools/extract_args/extract_args.mll b/local-packages/ocamlfind/tools/extract_args/extract_args.mll new file mode 100644 index 0000000..ae931e6 --- /dev/null +++ b/local-packages/ocamlfind/tools/extract_args/extract_args.mll @@ -0,0 +1,153 @@ +(* $Id$ *) + +(* Runs ocamlc -help and extract the command-line signature *) + +{ +open Printf +} + +let whitespace = [ ' ' '\t' ] + +rule get_switch = parse +| whitespace* ('-' [ '-' 'a'-'z' 'A'-'Z' '0'-'9' '_' ',' ]+ as switch_name) + whitespace? (_* as help_text) eof + {Some (switch_name, help_text)} +| whitespace* '-' whitespace+ (_* as help_text) eof + {Some ("-", help_text)} +| _? + {None} + +and has_argument = parse +| whitespace* [ '<' '[' '{' ] + {true} +| _? + {false} + +{ +let read_lines file = + let f = open_in file in + let lines = ref [] in + try + while true do + lines := input_line f :: !lines + done; + assert false + with + | End_of_file -> + close_in f; + List.rev !lines + | error -> + close_in f; + raise error +;; + + +let get_help cmd = + let temp_file = + Filename.temp_file "findlib" ".txt" in + let help_out = + try + let code = + Sys.command (sprintf "%s -help >%s 2>&1" + cmd + (Filename.quote temp_file)) in + if code <> 0 then + raise Not_found; (* Assume command does not exist! *) + let lines = read_lines temp_file in + Sys.remove temp_file; + lines + with error -> + Sys.remove temp_file; raise error in + help_out +;; + + +let get_switch s = get_switch (Lexing.from_string s) +let has_argument s = has_argument (Lexing.from_string s) + + +let rec extract_signature lines = + match lines with + | [] -> + [] + | line :: lines' -> + match get_switch line with + | Some (switch_name, help_text) -> + let has_arg = has_argument help_text in + let help_lines, lines'' = extract_help_continuation lines' in + let help_text' = String.concat "\n" (help_text :: help_lines) in + let r = + (switch_name, has_arg, help_text') in + r :: extract_signature lines'' + | None -> + extract_signature lines' + +and extract_help_continuation lines = + match lines with + | [] -> + ( [], [] ) + | line :: lines' -> + if get_switch line <> None then + ( [], lines ) + else + let help_lines, lines'' = extract_help_continuation lines' in + (line :: help_lines, lines'') +;; + + +let rm_help_switch switches = + List.filter + (fun (name, _, _) -> + name <> "-help" && name <> "--help") + switches +;; + + +let output_some_signature f name switches = + fprintf f "let %s_spec = Some [\n" name; + List.iter + (fun (switch_name, has_arg, help_text) -> + fprintf f " \"%s\",\n" (String.escaped switch_name); + fprintf f " %b,\n" has_arg; + fprintf f " \"%s\";\n\n" (String.escaped help_text) + ) + switches; + fprintf f "];;\n\n" +;; + + +let output_none f name = + fprintf f "let %s_spec = None;;\n\n" name +;; + + +let main() = + let f = ref stdout in + let progs = ref [] in + Arg.parse + [ "-o", Arg.String (fun s -> f := open_out s), + "<file> Save generated module to this file"; + ] + (fun arg -> progs := arg :: !progs) + "usage: extract_args <options> <command> ..."; + + progs := List.rev !progs; + + List.iter + (fun prog -> + try + let help_lines = get_help prog in (* or Not_found *) + let switches = rm_help_switch (extract_signature help_lines) in + output_some_signature !f prog switches + with + Not_found -> + output_none !f prog + ) + !progs; + + close_out !f +;; + + +main();; +} diff --git a/local-packages/ocamlfind/tools/file_exists b/local-packages/ocamlfind/tools/file_exists new file mode 100755 index 0000000..3a76b58 --- /dev/null +++ b/local-packages/ocamlfind/tools/file_exists @@ -0,0 +1,5 @@ +#! /bin/sh + +# Approximation of: test -e $1 + +test -d "$1" -o -f "$1" diff --git a/local-packages/ocamlfind/tools/patch b/local-packages/ocamlfind/tools/patch new file mode 100755 index 0000000..7d31ca4 --- /dev/null +++ b/local-packages/ocamlfind/tools/patch @@ -0,0 +1,28 @@ +#! /bin/sh + +# Usage: patch @VARIABLE@ value +# Environment variable USE_CYGPATH is honoured. + +varname="$1" +varvalue="$2" + +if [ "${USE_CYGPATH}" = "1" ]; then + #varvalue="$(echo "$varvalue" | sed -e 's;/;\\;g')" + varvalue="$(cygpath -w -l "$varvalue")" + varvalue="$(echo "$varvalue" | sed -e 's;\\;\\\\\\\\;g')" + # e.g. c:\file is transformed to c:\\\\file +else + case `uname` in + MINGW*) + varvalue="$(echo "$varvalue" | sed -e 's;\\;\\\\\\\\;g')" + # Convert the first letter drive to DOS style (naive). + # This is necessary because OCaml uses DOS paths even if + # run under MSYS. + varvalue="$(echo "$varvalue" | sed -e 's;^/\([a-z]\)/;\1:/;g')" + ;; + esac +fi + +sed -e 's;'"$varname"';'"$varvalue"';g' +# e.g. c:\\\\file is parsed by sed as c:\\file which is correct for the +# ocaml string diff --git a/local-packages/ocamlfind/tools/safe_camlp4 b/local-packages/ocamlfind/tools/safe_camlp4 new file mode 100755 index 0000000..a5a0f56 --- /dev/null +++ b/local-packages/ocamlfind/tools/safe_camlp4 @@ -0,0 +1,52 @@ +#! /bin/sh + +# Call camlp4 with fallback method if dynamic loading is not supported + +dl_string="dynamic loading not supported on this platform" +fn_string="The external function .* is not available" + +tmp_stderr="tmp.safe_camlp4_stderr.$$" +tmp_camlp4="tmp.safe_camlp4_camlp4.$$" + +trap "rm -f $tmp_stderr $tmp_camlp4" 0 + +print_stderr=1 +code=0 + +camlp4 "$@" 2>$tmp_stderr || { + code=$? + grep "$dl_string" $tmp_stderr >/dev/null 2>&1; t1=$? + grep "$fn_string" $tmp_stderr >/dev/null 2>&1; t2=$? + if [ $t1 -eq 0 -o $t2 -eq 0 ]; then + # Fallback: + print_stderr=0 + cp4_mods="" + cp4_args="" + i=0 + for arg in "$@"; do + if [ $i -gt 0 ]; then + cp4_mods="$cp4_mods -I $arg" + cp4_args="$cp4_args -I $arg" + i=0 + else + case "$arg" in + *.cma|*.cmo) + cp4_mods="$cp4_mods $arg" ;; + -I) + i=1 ;; + *) + cp4_args="$cp4_args $arg" ;; + esac + fi + done + mkcamlp4 -o $tmp_camlp4 $cp4_mods || exit + ./$tmp_camlp4 $cp4_args || exit + code=0 + fi +} + +if [ $print_stderr -gt 0 ]; then + cat $tmp_stderr >&2 +fi + +exit $code diff --git a/main.ml b/main.ml new file mode 100644 index 0000000..949c9f7 --- /dev/null +++ b/main.ml @@ -0,0 +1,14 @@ + +try + Sys.catch_break true; + Frontend.main() +with + any -> + prerr_endline ("Uncaught exception: " ^ Printexc.to_string any); + let raise_again = + try ignore(Sys.getenv "OCAMLFIND_DEBUG"); true + with Not_found -> false + in + if raise_again then raise any; + exit 3 +;; diff --git a/opam b/opam new file mode 100644 index 0000000..489065c --- /dev/null +++ b/opam @@ -0,0 +1,37 @@ +opam-version: "2.0" +synopsis: "A small frontend for ocamlfind that adds a few useful commands" +license: "MIT" +maintainer: "Chet Murthy <chetsky@gmail.com>" + +(* Gerd wrote most of this code; I just modified it (and probably +introduced bugs. This is to silence opam *) + +authors: "Chet Murthy <chetsky@gmail.com>" +homepage: "https://github.com/chetmurthy/not-ocamlfind" +bug-reports: "Chet Murthy <chetsky@gmail.com>" +depends: [ + "ocamlfind" {>= "1.8.0"} + "camlp-streams" + "conf-m4" {build} + "fmt" {>= "0.8.8"} + "rresult" {>= "0.6.0"} + "ocamlgraph" {>= "2.0.0"} + "conf-which" +] +depexts: [ + [ + "xdot" + ] {os-family = "debian"} +] +build: [ + ["./configure" "-bindir" bin "-sitelib" lib "-mandir" man "-config" "%{lib}%/findlib.conf" "-no-custom" "-no-topfind" {preinstalled}] + [make "all"] +] +install: [make "install"] +dev-repo: "git+https://github.com/chetmurthy/not-ocamlfind" +url { + src: "" + checksum: [ + "sha512=" + ] +} diff --git a/papr_official.ml b/papr_official.ml new file mode 100644 index 0000000..1fd3964 --- /dev/null +++ b/papr_official.ml @@ -0,0 +1,114 @@ + +let rec sep_last = + function + [] -> failwith "sep_last" + | [hd] -> hd, [] + | hd :: tl -> let (l, tl) = sep_last tl in l, hd :: tl + +let input_magic ic magic = + let maglen = String.length magic in + let b = Bytes.create maglen in really_input ic b 0 maglen; Bytes.to_string b + +let input_implem ic = + if Config.ast_impl_magic_number <> + input_magic ic Config.ast_impl_magic_number + then + failwith "input_implem: bad magic number" + else let _ = input_value ic in (input_value ic : Parsetree.structure) + +let input_interf ic = + if Config.ast_intf_magic_number <> + input_magic ic Config.ast_intf_magic_number + then + failwith "input_interf: bad magic number" + else let _ = input_value ic in (input_value ic : Parsetree.signature) + +let output_magic oc magic = output_string oc magic + +let output_interf fname oc (pt : Parsetree.signature) = + output_string oc Config.ast_intf_magic_number; + output_value oc fname; + output_value oc pt; + flush oc + +let output_implem fname oc (pt : Parsetree.structure) = + output_string oc Config.ast_impl_magic_number; + output_value oc fname; + output_value oc pt; + flush oc + +let parse_interf fname ic = + let lb = Lexing.from_channel ic in + Location.init lb fname; Parse.interface lb + +let parse_implem fname ic = + let lb = Lexing.from_channel ic in + Location.init lb fname; Parse.implementation lb + +let print_interf oc v = + let ofmt = Format.formatter_of_out_channel oc in + Pprintast.signature ofmt v; Format.pp_print_flush ofmt () + +let print_implem oc v = + let ofmt = Format.formatter_of_out_channel oc in + Pprintast.structure ofmt v; Format.pp_print_flush ofmt () + +let binary_input = ref false +let binary_output = ref false +let files = ref [] +let filetype = ref None + +let set_impl s = filetype := Some "-impl" +let set_intf s = filetype := Some "-intf" + +let passthru paf prf ic oc = (ic |> paf) |> prf oc + +let papr_official () = + Arg. + (parse + ["-binary-input", Set binary_input, " binary input"; + "-binary-output", Set binary_output, " binary output"; + "-impl", Unit set_impl, " implementation"; + "-intf", Unit set_intf, " interface"] + (fun s -> files := s :: !files) "papr_official: usage"); + let open_or opener ifminus = + function + "-" -> ifminus, "" + | f -> opener f, f + in + let ((ic, ifile), (oc, _)) = + match List.rev !files with + [] -> (stdin, ""), (stdout, "") + | [ifile] -> open_or open_in stdin ifile, (stdout, "") + | [ifile; ofile] -> + open_or open_in stdin ifile, open_or open_out stdout ofile + | _ -> failwith "too many filenames provided" + in + begin match !filetype, !binary_input, !binary_output with + Some "-impl", true, true -> + failwith "cannot have both binary input and output" + | Some "-impl", true, false -> passthru input_implem print_implem ic oc + | Some "-impl", false, true -> + passthru (parse_implem ifile) (output_implem ifile) ic oc + | Some "-impl", false, false -> + passthru (parse_implem ifile) print_implem ic oc + | Some "-intf", true, true -> + failwith "cannot have both binary input and output" + | Some "-intf", true, false -> passthru input_interf print_interf ic oc + | Some "-intf", false, true -> + passthru (parse_interf ifile) (output_interf ifile) ic oc + | Some "-intf", false, false -> + passthru (parse_interf ifile) print_interf ic oc + | _ -> failwith "unrecognized filetype" + end; + close_out oc; + close_in ic + +let _ = papr_official () + +(* +;;; Local Variables: *** +;;; mode:tuareg *** +;;; End: *** + +*) -- cgit v1.2.3