pax_global_header00006660000000000000000000000064145406143720014520gustar00rootroot0000000000000052 comment=25359508dc521e741b88b883bce88191c70f8037 ocamlbuild-0.14.3/000077500000000000000000000000001454061437200137205ustar00rootroot00000000000000ocamlbuild-0.14.3/.depend000066400000000000000000000402411454061437200151610ustar00rootroot00000000000000bin/ocamlbuild.cmo : \ plugin-lib/ocamlbuild_unix_plugin.cmi \ bin/ocamlbuild.cmi bin/ocamlbuild.cmx : \ plugin-lib/ocamlbuild_unix_plugin.cmx \ bin/ocamlbuild.cmi bin/ocamlbuild.cmi : bin/ocamlbuildlight.cmo : \ bin/ocamlbuildlight.cmi bin/ocamlbuildlight.cmx : \ bin/ocamlbuildlight.cmi bin/ocamlbuildlight.cmi : bin/ppcache.cmo : \ src/shell.cmi \ src/pathname.cmi \ src/my_std.cmi \ src/log.cmi \ src/command.cmi \ bin/ppcache.cmi bin/ppcache.cmx : \ src/shell.cmx \ src/pathname.cmx \ src/my_std.cmx \ src/log.cmx \ src/command.cmx \ bin/ppcache.cmi bin/ppcache.cmi : plugin-lib/ocamlbuild_executor.cmo : \ plugin-lib/ocamlbuild_executor.cmi plugin-lib/ocamlbuild_executor.cmx : \ plugin-lib/ocamlbuild_executor.cmi plugin-lib/ocamlbuild_executor.cmi : plugin-lib/ocamlbuild_plugin.cmo : \ plugin-lib/ocamlbuild_plugin.cmi plugin-lib/ocamlbuild_plugin.cmx : \ plugin-lib/ocamlbuild_plugin.cmi plugin-lib/ocamlbuild_plugin.cmi : plugin-lib/ocamlbuild_unix_plugin.cmo : \ plugin-lib/ocamlbuild_executor.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/exit_codes.cmi \ plugin-lib/ocamlbuild_unix_plugin.cmi plugin-lib/ocamlbuild_unix_plugin.cmx : \ plugin-lib/ocamlbuild_executor.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/exit_codes.cmx \ plugin-lib/ocamlbuild_unix_plugin.cmi plugin-lib/ocamlbuild_unix_plugin.cmi : src/bool.cmo : \ src/bool.cmi src/bool.cmx : \ src/bool.cmi src/bool.cmi : src/command.cmo : \ src/tags.cmi \ src/shell.cmi \ src/param_tags.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/log.cmi \ src/lexers.cmi \ src/const.cmo \ src/command.cmi src/command.cmx : \ src/tags.cmx \ src/shell.cmx \ src/param_tags.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/log.cmx \ src/lexers.cmx \ src/const.cmx \ src/command.cmi src/command.cmi : \ src/tags.cmi \ src/signatures.cmi src/configuration.cmo : \ src/tags.cmi \ src/param_tags.cmi \ src/my_std.cmi \ src/log.cmi \ src/loc.cmi \ src/lexers.cmi \ src/glob.cmi \ src/const.cmo \ src/configuration.cmi src/configuration.cmx : \ src/tags.cmx \ src/param_tags.cmx \ src/my_std.cmx \ src/log.cmx \ src/loc.cmx \ src/lexers.cmx \ src/glob.cmx \ src/const.cmx \ src/configuration.cmi src/configuration.cmi : \ src/tags.cmi \ src/pathname.cmi \ src/loc.cmi src/const.cmo : src/const.cmx : src/digest_cache.cmo : \ src/shell.cmi \ src/pathname.cmi \ src/options.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/digest_cache.cmi src/digest_cache.cmx : \ src/shell.cmx \ src/pathname.cmx \ src/options.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/digest_cache.cmi src/digest_cache.cmi : src/discard_printf.cmo : \ src/discard_printf.cmi src/discard_printf.cmx : \ src/discard_printf.cmi src/discard_printf.cmi : src/display.cmo : \ src/tags.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/discard_printf.cmi \ src/display.cmi src/display.cmx : \ src/tags.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/discard_printf.cmx \ src/display.cmi src/display.cmi : \ src/tags.cmi src/exit_codes.cmo : \ src/exit_codes.cmi src/exit_codes.cmx : \ src/exit_codes.cmi src/exit_codes.cmi : src/fda.cmo : \ src/pathname.cmi \ src/options.cmi \ src/log.cmi \ src/hygiene.cmi \ src/fda.cmi src/fda.cmx : \ src/pathname.cmx \ src/options.cmx \ src/log.cmx \ src/hygiene.cmx \ src/fda.cmi src/fda.cmi : \ src/slurp.cmi src/findlib.cmo : \ src/my_unix.cmi \ src/my_std.cmi \ src/lexers.cmi \ src/const.cmo \ src/command.cmi \ src/findlib.cmi src/findlib.cmx : \ src/my_unix.cmx \ src/my_std.cmx \ src/lexers.cmx \ src/const.cmx \ src/command.cmx \ src/findlib.cmi src/findlib.cmi : \ src/signatures.cmi \ src/command.cmi src/flags.cmo : \ src/tags.cmi \ src/param_tags.cmi \ src/log.cmi \ src/command.cmi \ src/bool.cmi \ src/flags.cmi src/flags.cmx : \ src/tags.cmx \ src/param_tags.cmx \ src/log.cmx \ src/command.cmx \ src/bool.cmx \ src/flags.cmi src/flags.cmi : \ src/tags.cmi \ src/command.cmi src/glob.cmo : \ src/my_std.cmi \ src/glob_lexer.cmi \ src/glob_ast.cmi \ src/bool.cmi \ src/glob.cmi src/glob.cmx : \ src/my_std.cmx \ src/glob_lexer.cmx \ src/glob_ast.cmx \ src/bool.cmx \ src/glob.cmi src/glob.cmi : \ src/signatures.cmi \ src/glob_ast.cmi \ src/bool.cmi src/glob_ast.cmo : \ src/bool.cmi \ src/glob_ast.cmi src/glob_ast.cmx : \ src/bool.cmx \ src/glob_ast.cmi src/glob_ast.cmi : \ src/bool.cmi src/glob_lexer.cmo : \ src/glob_ast.cmi \ src/bool.cmi \ src/glob_lexer.cmi src/glob_lexer.cmx : \ src/glob_ast.cmx \ src/bool.cmx \ src/glob_lexer.cmi src/glob_lexer.cmi : \ src/glob_ast.cmi src/hooks.cmo : \ src/hooks.cmi src/hooks.cmx : \ src/hooks.cmi src/hooks.cmi : src/hygiene.cmo : \ src/slurp.cmi \ src/shell.cmi \ src/pathname.cmi \ src/options.cmi \ src/my_std.cmi \ src/log.cmi \ src/hygiene.cmi src/hygiene.cmx : \ src/slurp.cmx \ src/shell.cmx \ src/pathname.cmx \ src/options.cmx \ src/my_std.cmx \ src/log.cmx \ src/hygiene.cmi src/hygiene.cmi : \ src/slurp.cmi src/lexers.cmo : \ src/my_std.cmi \ src/loc.cmi \ src/glob_ast.cmi \ src/glob.cmi \ src/bool.cmi \ src/lexers.cmi src/lexers.cmx : \ src/my_std.cmx \ src/loc.cmx \ src/glob_ast.cmx \ src/glob.cmx \ src/bool.cmx \ src/lexers.cmi src/lexers.cmi : \ src/loc.cmi \ src/glob.cmi src/loc.cmo : \ src/loc.cmi src/loc.cmx : \ src/loc.cmi src/loc.cmi : src/log.cmo : \ src/my_unix.cmi \ src/my_std.cmi \ src/display.cmi \ src/log.cmi src/log.cmx : \ src/my_unix.cmx \ src/my_std.cmx \ src/display.cmx \ src/log.cmi src/log.cmi : \ src/tags.cmi \ src/signatures.cmi src/main.cmo : \ src/tools.cmi \ src/tags.cmi \ src/solver.cmi \ src/slurp.cmi \ src/shell.cmi \ src/rule.cmi \ src/resource.cmi \ src/report.cmi \ src/plugin.cmi \ src/pathname.cmi \ src/param_tags.cmi \ src/options.cmi \ src/ocaml_utils.cmi \ src/ocaml_specific.cmi \ src/ocaml_dependencies.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/log.cmi \ src/loc.cmi \ src/lexers.cmi \ src/hooks.cmi \ src/flags.cmi \ src/fda.cmi \ src/exit_codes.cmi \ src/digest_cache.cmi \ src/const.cmo \ src/configuration.cmi \ src/command.cmi \ src/main.cmi src/main.cmx : \ src/tools.cmx \ src/tags.cmx \ src/solver.cmx \ src/slurp.cmx \ src/shell.cmx \ src/rule.cmx \ src/resource.cmx \ src/report.cmx \ src/plugin.cmx \ src/pathname.cmx \ src/param_tags.cmx \ src/options.cmx \ src/ocaml_utils.cmx \ src/ocaml_specific.cmx \ src/ocaml_dependencies.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/log.cmx \ src/loc.cmx \ src/lexers.cmx \ src/hooks.cmx \ src/flags.cmx \ src/fda.cmx \ src/exit_codes.cmx \ src/digest_cache.cmx \ src/const.cmx \ src/configuration.cmx \ src/command.cmx \ src/main.cmi src/main.cmi : src/my_std.cmo : \ src/my_std.cmi src/my_std.cmx : \ src/my_std.cmi src/my_std.cmi : \ src/signatures.cmi src/my_unix.cmo : \ src/my_std.cmi \ src/my_unix.cmi src/my_unix.cmx : \ src/my_std.cmx \ src/my_unix.cmi src/my_unix.cmi : src/ocaml_arch.cmo : \ src/pathname.cmi \ src/my_std.cmi \ src/command.cmi \ src/ocaml_arch.cmi src/ocaml_arch.cmx : \ src/pathname.cmx \ src/my_std.cmx \ src/command.cmx \ src/ocaml_arch.cmi src/ocaml_arch.cmi : \ src/signatures.cmi \ src/command.cmi src/ocaml_compiler.cmo : \ src/tools.cmi \ src/tags.cmi \ src/rule.cmi \ src/resource.cmi \ src/pathname.cmi \ src/options.cmi \ src/ocaml_utils.cmi \ src/ocaml_dependencies.cmi \ src/ocaml_arch.cmi \ src/my_std.cmi \ src/log.cmi \ src/command.cmi \ src/ocaml_compiler.cmi src/ocaml_compiler.cmx : \ src/tools.cmx \ src/tags.cmx \ src/rule.cmx \ src/resource.cmx \ src/pathname.cmx \ src/options.cmx \ src/ocaml_utils.cmx \ src/ocaml_dependencies.cmx \ src/ocaml_arch.cmx \ src/my_std.cmx \ src/log.cmx \ src/command.cmx \ src/ocaml_compiler.cmi src/ocaml_compiler.cmi : \ src/tags.cmi \ src/rule.cmi \ src/pathname.cmi \ src/command.cmi src/ocaml_dependencies.cmo : \ src/tools.cmi \ src/resource.cmi \ src/pathname.cmi \ src/ocaml_utils.cmi \ src/my_std.cmi \ src/log.cmi \ src/ocaml_dependencies.cmi src/ocaml_dependencies.cmx : \ src/tools.cmx \ src/resource.cmx \ src/pathname.cmx \ src/ocaml_utils.cmx \ src/my_std.cmx \ src/log.cmx \ src/ocaml_dependencies.cmi src/ocaml_dependencies.cmi : \ src/pathname.cmi src/ocaml_specific.cmo : \ src/tools.cmi \ src/tags.cmi \ src/rule.cmi \ src/pathname.cmi \ src/options.cmi \ src/ocamlbuild_config.cmo \ src/ocaml_utils.cmi \ src/ocaml_tools.cmi \ src/ocaml_compiler.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/log.cmi \ src/flags.cmi \ src/findlib.cmi \ src/configuration.cmi \ src/command.cmi \ src/ocaml_specific.cmi src/ocaml_specific.cmx : \ src/tools.cmx \ src/tags.cmx \ src/rule.cmx \ src/pathname.cmx \ src/options.cmx \ src/ocamlbuild_config.cmx \ src/ocaml_utils.cmx \ src/ocaml_tools.cmx \ src/ocaml_compiler.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/log.cmx \ src/flags.cmx \ src/findlib.cmx \ src/configuration.cmx \ src/command.cmx \ src/ocaml_specific.cmi src/ocaml_specific.cmi : src/ocaml_tools.cmo : \ src/tools.cmi \ src/tags.cmi \ src/rule.cmi \ src/pathname.cmi \ src/options.cmi \ src/ocaml_utils.cmi \ src/ocaml_compiler.cmi \ src/my_std.cmi \ src/flags.cmi \ src/command.cmi \ src/ocaml_tools.cmi src/ocaml_tools.cmx : \ src/tools.cmx \ src/tags.cmx \ src/rule.cmx \ src/pathname.cmx \ src/options.cmx \ src/ocaml_utils.cmx \ src/ocaml_compiler.cmx \ src/my_std.cmx \ src/flags.cmx \ src/command.cmx \ src/ocaml_tools.cmi src/ocaml_tools.cmi : \ src/tags.cmi \ src/rule.cmi \ src/pathname.cmi \ src/command.cmi src/ocaml_utils.cmo : \ src/tools.cmi \ src/tags.cmi \ src/pathname.cmi \ src/options.cmi \ src/my_std.cmi \ src/log.cmi \ src/lexers.cmi \ src/flags.cmi \ src/const.cmo \ src/command.cmi \ src/ocaml_utils.cmi src/ocaml_utils.cmx : \ src/tools.cmx \ src/tags.cmx \ src/pathname.cmx \ src/options.cmx \ src/my_std.cmx \ src/log.cmx \ src/lexers.cmx \ src/flags.cmx \ src/const.cmx \ src/command.cmx \ src/ocaml_utils.cmi src/ocaml_utils.cmi : \ src/tags.cmi \ src/pathname.cmi \ src/command.cmi src/ocamlbuild_config.cmo : src/ocamlbuild_config.cmx : src/ocamlbuild_where.cmo : \ src/ocamlbuild_config.cmo \ src/ocamlbuild_where.cmi src/ocamlbuild_where.cmx : \ src/ocamlbuild_config.cmx \ src/ocamlbuild_where.cmi src/ocamlbuild_where.cmi : src/options.cmo : \ src/shell.cmi \ src/ocamlbuild_where.cmi \ src/ocamlbuild_config.cmo \ src/my_std.cmi \ src/log.cmi \ src/lexers.cmi \ src/const.cmo \ src/command.cmi \ src/options.cmi src/options.cmx : \ src/shell.cmx \ src/ocamlbuild_where.cmx \ src/ocamlbuild_config.cmx \ src/my_std.cmx \ src/log.cmx \ src/lexers.cmx \ src/const.cmx \ src/command.cmx \ src/options.cmi src/options.cmi : \ src/slurp.cmi \ src/signatures.cmi \ src/command.cmi src/param_tags.cmo : \ src/tags.cmi \ src/my_std.cmi \ src/log.cmi \ src/loc.cmi \ src/lexers.cmi \ src/param_tags.cmi src/param_tags.cmx : \ src/tags.cmx \ src/my_std.cmx \ src/log.cmx \ src/loc.cmx \ src/lexers.cmx \ src/param_tags.cmi src/param_tags.cmi : \ src/tags.cmi \ src/loc.cmi src/pathname.cmo : \ src/shell.cmi \ src/options.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/log.cmi \ src/glob.cmi \ src/pathname.cmi src/pathname.cmx : \ src/shell.cmx \ src/options.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/log.cmx \ src/glob.cmx \ src/pathname.cmi src/pathname.cmi : \ src/signatures.cmi src/plugin.cmo : \ src/tools.cmi \ src/tags.cmi \ src/shell.cmi \ src/rule.cmi \ src/pathname.cmi \ src/param_tags.cmi \ src/options.cmi \ src/ocamlbuild_where.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/log.cmi \ src/exit_codes.cmi \ src/const.cmo \ src/command.cmi \ src/plugin.cmi src/plugin.cmx : \ src/tools.cmx \ src/tags.cmx \ src/shell.cmx \ src/rule.cmx \ src/pathname.cmx \ src/param_tags.cmx \ src/options.cmx \ src/ocamlbuild_where.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/log.cmx \ src/exit_codes.cmx \ src/const.cmx \ src/command.cmx \ src/plugin.cmi src/plugin.cmi : src/report.cmo : \ src/solver.cmi \ src/resource.cmi \ src/my_std.cmi \ src/log.cmi \ src/glob.cmi \ src/report.cmi src/report.cmx : \ src/solver.cmx \ src/resource.cmx \ src/my_std.cmx \ src/log.cmx \ src/glob.cmx \ src/report.cmi src/report.cmi : \ src/solver.cmi src/resource.cmo : \ src/slurp.cmi \ src/shell.cmi \ src/pathname.cmi \ src/options.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/log.cmi \ src/lexers.cmi \ src/glob_ast.cmi \ src/glob.cmi \ src/digest_cache.cmi \ src/const.cmo \ src/command.cmi \ src/resource.cmi src/resource.cmx : \ src/slurp.cmx \ src/shell.cmx \ src/pathname.cmx \ src/options.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/log.cmx \ src/lexers.cmx \ src/glob_ast.cmx \ src/glob.cmx \ src/digest_cache.cmx \ src/const.cmx \ src/command.cmx \ src/resource.cmi src/resource.cmi : \ src/slurp.cmi \ src/pathname.cmi \ src/my_std.cmi \ src/command.cmi src/rule.cmo : \ src/shell.cmi \ src/resource.cmi \ src/pathname.cmi \ src/options.cmi \ src/my_std.cmi \ src/log.cmi \ src/digest_cache.cmi \ src/command.cmi \ src/rule.cmi src/rule.cmx : \ src/shell.cmx \ src/resource.cmx \ src/pathname.cmx \ src/options.cmx \ src/my_std.cmx \ src/log.cmx \ src/digest_cache.cmx \ src/command.cmx \ src/rule.cmi src/rule.cmi : \ src/tags.cmi \ src/resource.cmi \ src/pathname.cmi \ src/my_std.cmi \ src/command.cmi src/shell.cmo : \ src/tags.cmi \ src/my_unix.cmi \ src/my_std.cmi \ src/log.cmi \ src/shell.cmi src/shell.cmx : \ src/tags.cmx \ src/my_unix.cmx \ src/my_std.cmx \ src/log.cmx \ src/shell.cmi src/shell.cmi : src/signatures.cmi : src/slurp.cmo : \ src/my_unix.cmi \ src/my_std.cmi \ src/slurp.cmi src/slurp.cmx : \ src/my_unix.cmx \ src/my_std.cmx \ src/slurp.cmi src/slurp.cmi : \ src/my_unix.cmi src/solver.cmo : \ src/rule.cmi \ src/resource.cmi \ src/pathname.cmi \ src/my_std.cmi \ src/log.cmi \ src/command.cmi \ src/solver.cmi src/solver.cmx : \ src/rule.cmx \ src/resource.cmx \ src/pathname.cmx \ src/my_std.cmx \ src/log.cmx \ src/command.cmx \ src/solver.cmi src/solver.cmi : \ src/pathname.cmi src/tags.cmo : \ src/tags.cmi src/tags.cmx : \ src/tags.cmi src/tags.cmi : \ src/signatures.cmi src/tools.cmo : \ src/tags.cmi \ src/rule.cmi \ src/pathname.cmi \ src/my_std.cmi \ src/log.cmi \ src/configuration.cmi \ src/tools.cmi src/tools.cmx : \ src/tags.cmx \ src/rule.cmx \ src/pathname.cmx \ src/my_std.cmx \ src/log.cmx \ src/configuration.cmx \ src/tools.cmi src/tools.cmi : \ src/tags.cmi \ src/pathname.cmi ocamlbuild-0.14.3/.gitignore000066400000000000000000000006141454061437200157110ustar00rootroot00000000000000# general patterns *.o *.a *.so *.obj *.lib *.dll *.cm[ioxat] *.cmx[as] *.cmti *.annot *.exe *.exe.manifest .depend .depend.nt .DS_Store *.out *.out.dSYM /tmp/ ocamlbuild.install Makefile.config /bootstrap/src /bootstrap/_build* /src/ocamlbuild_config.ml /src/lexers.ml /src/glob_lexer.ml /ocamlbuild.byte /ocamlbuild.native /man/ocamlbuild.1 /man/ocamlbuild.options.1 /man/options_man.byte ocamlbuild-0.14.3/.mailmap000066400000000000000000000002321454061437200153360ustar00rootroot00000000000000Armaël Guéneau Armael Jérémie Dimino Jeremie Dimino ocamlbuild-0.14.3/.merlin000066400000000000000000000000741454061437200152100ustar00rootroot00000000000000S src S bootstrap B . FLG -strict-sequence FLG -safe-string ocamlbuild-0.14.3/.travis.yml000066400000000000000000000023511454061437200160320ustar00rootroot00000000000000language: c os: linux env: - OCAML_VERSION=4.03.0 - OCAML_VERSION=4.04.2 - OCAML_VERSION=4.05.0 - OCAML_VERSION=4.06.1 - OCAML_VERSION=4.07.0 install: - echo "yes" | sudo add-apt-repository ppa:avsm/ppa - sudo apt-get update -qq - sudo apt-get install -qq opam - export OPAMYES=1 - opam init --compiler=${OCAML_VERSION} - opam install ocamlfind camlp4 menhir script: - eval `opam config env` # First, run our own testsuite. Do this *before* any ocamlbuild is installed globally, # to check that we don't have a spurious dependency on a global ocamlbuild. - VERBOSE=1 make test # Second, bootstrap ourselves using the freshly built binaries, as a more complex # exercise than the testsuite alone. - OCAMLBUILD=$(pwd)/ocamlbuild.native make -C bootstrap # Third, verify that installation works, and a variety of downstream opam packages # still install. - make distclean - opam pin add -n -k path ocamlbuild . - opam install -v ocamlbuild - opam install -v mtime.1.0.0 # this tests topkg, with stub libraries - opam install -v inotify.2.3 # this tests oasis, with stub libraries - opam install -v cpuid.0.1.1 # this tests the ocb-stubblr plugin - opam install -v shcaml.0.2.1 # this tests the cppo plugin ocamlbuild-0.14.3/CONTRIBUTING.adoc000066400000000000000000000043571454061437200164700ustar00rootroot00000000000000= Contributing to OCamlbuild Any contribution is warmly welcome! Bugs in OCamlbuild itself should be reported on https://github.com/ocaml/ocamlbuild/issues[the github bugtracker]. Any OCamlbuild-related question can also be asked on the mailto:caml-list@inria.fr[caml-list mailing-list]. Contributions in the form of patches are most welcome. We welcome pull requests on the https://github.com/ocaml/ocaml/pulls[GitHub repository], but you can also email a patch if that is your preference. OCamlbuild is free software, licensed under the GNU LGPL, and we do our best to review, give feedback, and integrate proposed patches. In particular, if you try to understand the implementation or documentation, and understanding some part of it requires excessive effort, a patch containing implementation or documentation comments to clarify it to future readers is an excellent idea. == The OCamlbuild manual This repository also hosts https://github.com/ocaml/ocamlbuild/tree/master/manual/manual.adoc[the OCamlbuild manual]. Feel free to ask questions about unclear part of the manual, or to contribute extra explanations. The documentation contains a set of https://github.com/ocaml/ocamlbuild/tree/master/examples[examples] that anyone can help grow. If there is a typical kind of setting that you've reused across several projects, is clear and informative, and is not represented in existing examples, feel free to submit it. You can also help complete the documentation by integrating http://ocaml.org/learn/tutorials/ocamlbuild/[ocaml.org Wiki] content in the OCamlbuild manual. This Wiki has a lot of valuable information, but for a mix of social and technical reasons it hasn't evolved into a good alternate documentation that we could point beginners to. We hope this manual can fill this gap. You can also use https://github.com/ocaml/ocamlbuild/issues[our issue tracker] to comment on precise or general shortcomings of the present documentation, such as: * Things that are missing and must be present; * Things that are here but should be shortened; or * Things of which you would like to change the presentation. A patch is even more useful than a bug report. For less precise comments (or to send patches), you can send an e-mail to (gabriel dot scherer at gmail). ocamlbuild-0.14.3/Changes000066400000000000000000003172061454061437200152240ustar00rootroot00000000000000We use "MPR#$N" to denote the ticket number $N on the Mantis bugtracker: http://caml.inria.fr/mantis/view.php?id=$N and OGPR#$N to denote the github pull issue against the OCaml repository https://github.com/ocaml/ocaml/pull/$N The form #$N indicates an issue on the github ocamlbuild repository, https://github.com/ocaml/ocamlbuild/issues/$N https://github.com/ocaml/ocamlbuild/pulls/$N We also use PR#$N for pull requests. Changes breaking compatibility are marked with a "* " bullet instead of the usual "- ". 0.14.3 (20 Dec 2023): --------------------- - Add OCaml 5.2 support (#325 by Hugo Heuzard) - Quote Makefile arguments to allow spaces in paths, especially on Windows. Documented in #321 (#324 by Jonah Beckford) 0.14.2 (28 Sep 2022): --------------------- - Add OCaml 5.1 support (#319 by Kate Deplaix, reviewed by Gabriel Scherer) 0.14.1 (09 Feb 2021): --------------------- - Add OCaml 5.00 support (#315 by Kate Deplaix, reviewed by Gabriel Scherer) - Fix race conditions when invoking ocamlbuild in parallel from a makefile (#302 by Gabriel Scherer) - Removes .so from products of all cmxs rules (#305 by Ivan Gotovchits, reviewed by Gabriel Scherer) 0.14.0 (23 Feb 2019): --------------------- Compared to the previous released version (0.12.0), OCamlbuild 0.14.0 contains new features (`ppopt(..)` and `ppxopt(...)` flags, ocamlbuild options) and support for OCaml 4.08+dev. * Revert the change to "pack" handling from the never-released 0.13 (#272), which turns out to break compatibility with too many projects. At this point in the lifetime of ocamlbuild usage, it's more important to keep building existing projects than to improve the build system for new projects -- of course the latter is also nice, but not when it endangers compatibility. (Gabriel Scherer) 0.13.1 (15 Sep 2018): --------------------- This bugfix release attempts to fix a regression due to the change in "pack" handling in 0.13.0. It is not clear whether the regression should be considered a bug in 0.13.0 or an incorrect _tags file in the broken package, but we prefer to fix it anyway. - #287: change "linkpkg" flag definition to not apply in the new "pack"++"link" mode introduced by #272. This avoids a build failure in webidl.1.4 and possibly other packages using "true: linkpkg". (Gabriel Scherer, report by Andreas Hauptmann) 0.13.0 (8 Sep 2018): -------------------- OCamlbuild 0.13.0 contains new features (`ppopt(..)` and `ppxopt(...)` flags, ocamlbuild options) and bugfixes (to pack production, for 4.08+dev support). - #45, #190: add ppopt(arg) and ppxopt(package,arg) when -use-ocamlfind (Gabriel Scherer, review by whitequark, request by Gabriel Scherer, Gabriel Radanne and Pavel Argentov) - #268, #269: add flag support for some ocamlmklib options: custom, debug, failsafe, linkall, ccopt(..), cclib(..), rpath(..), ldopt(..) (Gabriel Scherer, report by Hannes Mehnert, review by whitequark) * #272: add the "link" tag to "pack" actions Instead of a separate category, "pack" is now another form of linking like "program", "library", "toplevel" and "output_obj". This fixes the issue that package(...) tags where not passed at pack-production time, spotted by Jérémie Dimino. More generally, this extends the meaning of all "link" flags to "pack", which seems to be the correct behavior for all the rules we inspected. (Gabriel Scherer, original issue diagnosis by Jérémie Dimino) - #278: typo fixes in the manual (Xinzhe Yang) - #282: fix compilation with trunk OCaml (4.08+dev) (Xavier Clerc and Nandor Licker) 0.12.0 (11 Nov 2017): --------------------- OCamlbuild 0.12.0 is a maintenance release containing mostly bugfixes and a few user-contributed features. - #227: install signatures.{mli,cmi,cmti} to help documentation tools (Daniel Bünzli and Gabriel Scherer) - #232: fix Windows install rules (David Allsopp) - #234: add "afl_instrument" and "afl_inst_ratio" flags for corresponding ocamlopt options. (Jeremy Yallop) - #237: extend cc/ccopt/cclib flags to apply to "ocaml" compilation as well, as tweaking the C linker can be required for pure-OCaml projects -- see #236 (Gabriel Scherer, report by Nathan Rebours) - #253: only run native tests if ocamlopt is available. (Ximin Luo, review by whitequark and Gabriel Scherer) - #256, #258: pass -keep-docs and -keep-locs when using -pack (Gabriel Scherer, report by Vincent Jacques) - #257, #259: add `_opam` to the list of directories ignored by default; it is used for package-local opam switches (Gabriel Scherer, request by Edwin Török) 0.11.0 (5 Mar 2017): -------------------- OCamlbuild 0.11.0 introduces a change to the way `.cmxs` files are produced when no `.mldylib` file is absent: it will now use the exact same semantics as `.cmxa` and `.mllib` file -- in particular, it should not be necessary anymore to have identical `foo.{mllib,mldylib}` files, only `foo.mllib` should suffice. See the detailed changelog below for details. - #111: added "nostdlib" flag for corresponding ocaml{c,opt} options (Thomas Wood) - #115: add `node_modules` to the list of directories ignored by default (.svn/, CVS/, .bzr/, .hg/, .git/, _darcs/, node_modules/) (Yunxing Dai) - #125, #160: added "-toolchain" option for corresponding ocamlfind option. (whitequark) - #127, #137, #138: install ocamlbuild's man pages, missing since 4.02 (Adam Sampson and Gabriel Scherer) - #130: make sure that -just-plugin always stops after the plugin-build phase (Gabriel Scherer, report by whitequark) * #132, #159: remove the rule ".cmx -> .cmxs" Previously, there was a ".cmx -> .cmxa" rule that would pull a module and its dependencies in a .cmxa, and a separate ".cmx -> .cmxs" rule that would pull only a module as a .cmxs. The latter is a reasonable default choice, the idea being that a module's dependencies may often be statically linked with the program instead of being dynamically linked. But it conflicts with the presence of a rule ".cmxa -> .cmxs" as soon as the library has the same name as one of the modules it contains. The reason why the rule ".cmxa -> .cmxs" matter is that it can be composed with the rule ".mllib -> .cmxa" to build .cmxs files from .mllib files, without having to copy each .mllib file into a separate .mldylib file. In other terms, the previous behaviour would, by default (in absence of .mldylib file who always takes priority), only link the module in the .cmxs file, and people wishing otherwise would have to write a list of modules in a .mldylib file. The new behavior will, by default, take the .mllib file or the module dependencies (as for .cmxa) to build a .cmxs file, and people wishing otherwise will have to write just the module name in a .mldylib file. It is unclear whether this change will break some projects on which users relied on the previous semantics. It seems equally likely that the previous semantics, when it applied, was a source of bugs (the .cmxs files didn't have the expected modules) that would not be discovered by people not testing dynamic linking. Such bugs have been found and fixed in the following cases: - - - (Daniel Bünzli, Jérémie Dimino, Armaël Guéneau, Gabriel Scherer, whitequark) - #124, #136: do not explicitly pass -shared when building shared libraries; let the compiler decide what to build. (whitequark) - #143-171: migration of Mantis bugtracker issues to the github issue tracker (Damien Doligez) - #172-175, #177: setting up Continuous Infrastructure (CI) testsuite checks (whitequark) - #202: install license, changes and readme in opam's docdir for `odig` (Gabriel Scherer, request and review by Daniel Bünzli) * #240: new heuristic for handling the OCAMLLIB environment variable. `ocamlbuild -where` will ignore OCAMLLIB completely if OCAMLBUILD_LIBDIR is not a lexical subdirectory of OCAML_LIBDIR (i.e. an opam installation). Otherwise, it now returns $OCAMLLIB with the difference between OCAMLBUILD_LIBDIR and OCAML_LIBDIR appended (i.e. for a normal findlib installation, it now returns $OCAMLLIB/site-lib/ocamlbuild) (David Allsopp, review by Gabriel Schere) - "noautolink" tag for ocaml{c,opt} (Gabriel Scherer) 0.10.{0,1} (Dec 2016): ---------------------- These releases were never widely distributed, because of a quickly-caught regression due to the change of .cmxs compilation behavior (#132), fixed with the help Daniel Bünzli, Jérémie Dimino and, in particular, whitequark. 0.9.3 (6 Oct 2016): ------------------- OCamlbuild 0.9.3 introduces several features contributed or requested by our users. See the detailed changelog below. - #39: new ".o -> .clib" rule to build libraries out of single C stubs (Gabriel Scherer, request by whitequark) - #78: Integrate the in-progress OCamlbuild manual, previously located at https://github.com/gasche/manual-ocamlbuild into the ocamlbuild repository, in the manual/ subdirectory. The most current version of the manual can thus be accessed at https://github.com/ocaml/ocamlbuild/tree/master/manual/manual.adoc (Gabriel Scherer) - #93: added "noassert" and "unsafe" flag for corresponding ocaml{c,opt} options (François Pottier) - #94: added "cc", "cclib", and "ccopt" flags which correspond to the respective ocaml{c,opt} options (Rudi Grinberg) - PR#7295: add infer_interface support for various type-checking-time flags: color, keep_docs, no_alias_deps, nolabels, nopervasives, open, strict_formats, strict_sequence, warn, warn_error (Gabriel Scherer, report by Knuth Posern) 0.9.2 (1 May 2016): ------------------- OCamlbuild 0.9.2 is a release to support OCaml 4.03. Martin Neuhäußer contributed new flags for flambda-specific optimization options. We also extend the scope of the flags -opaque and -for-pack, to align with 4.03 best practices. Note that OCamlbuild should still work correctly under older OCaml releases. - #67: Add support for flambda's optimization parameters The flags are named according to the flambda options with two exceptions: optimization_rounds(int) for -rounds optimize({2,3,classic}) for -O{2,3,classic} (Martin Neuhäußer) - #70 (partial): fix hygiene complains about the build directory under Windows (Andreas Hauptmann, Gabriel Scherer) - #73: also pass predicates(foo) to ocamldep (Jérémie Dimino) - extend the scope of the -opaque flag under 4.03 (Gabriel Scherer) - extend the scope of the -for-pack flag to ocamlc, as recommend by OCaml compiler maintainers in [PR#5996](http://caml.inria.fr/mantis/view.php?id=5995#c13339) (Gabriel Scherer) 0.9.1 (29 Feb 2016): -------------------- OCamlbuild 0.9.1 synchronizes the behavior of ocamlbuild with changes in the OCaml compiler that are present in the 4.03 release branch; this version that should be usable for testing packages using 4.03 before its release. - Do not exclude files whose name starts with '_' from the source tree (Gabriel Scherer, report by Daniel Bünzli on the caml-list) - #44: When ocamlbuild discovers a cycle in the dependencies, the displayed problematic path is now refined to the actual cycle (François Bobot, review by Armaël Géneau) - #51: synchronize handling of -o flag for C files with upstream OCaml (whitequark) OCamlbuild 0.9.0 (19 Jan 2016): ------------------------------- OCamlbuild 0.9.0 is an experimental release designed to help testing OCaml software in preparation for the 4.03 release -- the first one to not include ocamlbuild. - MPR#6794, MPR#6809: pass package-specific include flags when building C files (Jérémie Dimino, request by whitequark) - OGPR#208: add "asm" tag to ocamlbuild to enable flag -S (ygrek) - Changed OCamlbuild's license to LGPLv2 with static linking exception. - OGPR#219: speedup target-already-built builds (ygrek) - MPR#6605, OGPR#117: un-hardcode camlp4 library path (Vincent Laporte and Gabriel Scherer) - #20: add -dot and -man-related ocamldoc options (Gabriel Scherer) - #10, PR#21: Fix manpages generation: properly pass the "manpage" tag. (Armaël Guéneau) - #20: add -documentation support for parametrized flag (Gabriel Scherer, review by Rudi Grinberg and François Bobot) - #10, #35: Use extension-independent tags for ocamldoc rules. (Armaël Guéneau) OCamlbuild was included in the OCaml compiler distribution between OCaml 3.10.0 (May 2007) and OCaml 4.02.3 (July 2015). The changes below correspond to the subset of ocamlbuild-related changes in those OCaml releases. ------------------------------------------------------------------------- OCaml 4.02.3 (27 Jul 2015): --------------------------- OCaml 4.02.2 (17 Jun 2015): --------------------------- OCamlbuild: - MPR#6237: explicit "infer" tag to control or disable menhir --infer (Hugo Heuzard) - MPR#6625: pass -linkpkg to files built with -output-obj. (whitequark) - MPR#6702: explicit "linkpkg" and "dontlink(foo)" flags (whitequark, Gabriel Scherer) - MPR#6712: Ignore common VCS directories (whitequark) - MPR#6720: pass -g to C compilers when tag 'debug' is set (whitequark, Gabriel Scherer) - MPR#6733: add .byte.so and .native.so targets to pass -output-obj -cclib -shared. (whitequark) - MPR#6733: "runtime_variant(X)" to pass -runtime-variant X option. (whitequark) - MPR#6774: new menhir-specific flags "only_tokens" and "external_tokens(Foo)" (François Pottier) Bug fixes: - MPR#6626: ocamlbuild on cygwin cannot find ocamlfind (Gergely Szilvasy) - MPR#6640: ocamlbuild: wrong "unused tag" warning on "precious" (report by user 'william') - MPR#6652: ocamlbuild -clean does not print a newline after output (Damien Doligez, report by Andi McClure) - MPR#6793: ocamlbuild passes nonsensical "-ocamlc ..." commands to menhir (Gabriel Scherer, report by Damien Doligez) - MPR#6893: ocamlbuild: "tag not used" warning when using (p)dep (Gabriel Scherer, report by Christiano Haesbaert) OCaml 4.02.1 (14 Oct 2014): --------------------------- Bug Fixes: - MPR#6599: ocamlbuild: add -bin-annot when using -pack (Christopher Zimmermann) - ocamlbuild: add an -ocamlmklib option to change the ocamlmklib command (Jérôme Vouillon) OCaml 4.02.0 (29 Aug 2014): --------------------------- Bug fixes: - MPR#5406 ocamlbuild: "tag 'package' does not expect a parameter" (Gabriel Scherer) - MPR#6184: ocamlbuild: `ocamlfind ocamldep` does not support -predicate (Jacques-Pascal Deplaix) - MPR#6300: ocamlbuild -use-ocamlfind conflicts with -ocamlc (Gabriel Scherer) - MPR#6482: ocamlbuild fails when _tags file in unhygienic directory (Gabriel Scherer) - MPR#6502: ocamlbuild spurious warning on "use_menhir" tag (Xavier Leroy) Features wishes: - MPR#5201: ocamlbuild: add --norc to the bash invocation to help performances (Daniel Weil) - MPR#6087: ocamlbuild, improve _tags parsing of escaped newlines (Gabriel Scherer, request by Daniel Bünzli) - MPR#6109: Typos in ocamlbuild error messages (Gabriel Kerneis) - MPR#6166: document -ocamldoc option of ocamlbuild (Xavier Clerc) - MPR#6187: ocamlbuild: warn when using -plugin-tag(s) without myocamlbuild.ml (Jacques-Pascal Deplaix) - MPR#6495: ocamlbuild tags 'safe_string', 'unsafe_string' (Anil Madhavapeddy) - make ocamldebug -I auto-detection work with ocamlbuild (Josh Watzman) OCaml 4.01.0 (12 Sep 2013): --------------------------- Bug fixes: - MPR#4469: emacs mode: caml-set-compile-command is annoying with ocamlbuild (Daniel Bünzli) - MPR#4502: ocamlbuild now reliably excludes the build-dir from hygiene check (Gabriel Scherer, report by Romain Bardou) - MPR#5102: ocamlbuild fails when using an unbound variable in rule dependency (Xavier Clerc, report by Daniel Bünzli) - MPR#5212: Improve ocamlbuild error messages of _tags parser (ygrek) - MPR#5300: ocamlbuild: verbose parameter should implicitly set classic display (Xavier Clerc, report by Robert Jakob) - MPR#5468: ocamlbuild should preserve order of parametric tags (Wojciech Meyer, report by Dario Texeira) - MPR#5763: ocamlbuild does not give correct flags when running menhir (Gabriel Scherer, reported by Philippe Veber) - MPR#5891: ocamlbuild: support rectypes tag for mlpack (Khoo Yit Phang) - MPR#6058: 'ocamlbuild -use-ocamlfind -tag thread -package threads t.cma' fails (Gabriel Scherer, report by Hezekiah M. Carty) - MPR#6109: Typos in ocamlbuild error messages (Gabriel Kerneis) Feature wishes: - MPR#5243: improve the ocamlbuild API documentation in signatures.mli (Christophe Troestler) - MPR#6059: add -output-obj rules for ocamlbuild (Anil Madhavapeddy) - MPR#6060: ocamlbuild tags 'principal', 'strict_sequence' and 'short_paths' (Anil Madhavapeddy) - ocamlbuild tag 'no_alias_deps' (Daniel Bünzli) Tools: - OCamlbuild now features a bin_annot tag to generate .cmt files. (Jonathan Protzenko) - OCamlbuild now features a strict_sequence tag to trigger the strict-sequence option. (Jonathan Protzenko) - OCamlbuild now picks the non-core tools like ocamlfind and menhir from PATH (Wojciech Meyer) OCaml 4.00.1 (5 Oct 2012): -------------------------- Bug fixes: - MPR#5468: ocamlbuild should preserve order of parametric tags OCaml 4.00.0 (26 Jul 2012): --------------------------- Bug Fixes: - MPR#5305: prevent ocamlbuild from complaining about links to _build/ - MPR#5356: ocamlbuild handling of 'predicates' for ocamlfind - MPR#5435: ocamlbuild does not find .opt executables on Windows - MPR#5503: error when ocamlbuild is passed an absolute path as build directory - MPR#5531: Allow ocamlbuild to add ocamldoc flags through -docflag - MPR#5604: fix permissions of files created by ocamlbuild itself - MPR#5616: move ocamlbuild documentation to the reference manual - MPR#5655: ocamlbuild doesn't pass cflags when building C stubs OCaml 3.12.1 (4 Jul 2011): -------------------------- Bug fixes: - MPR#4380: ocamlbuild should not use tput on windows - MPR#4552: ocamlbuild does not create symlinks when using '.itarget' file - MPR#4967: ocamlbuild passes wrong switches to ocamldep through menhir - MPR#5039: ocamlbuild should use '-linkpkg' only when linking programs - MPR#5095: ocamlbuild ignores some tags when building bytecode objects - MPR#5100: ocamlbuild always rebuilds a 'cmxs' file - MPR#5103: build and install objinfo when building with ocamlbuild - MPR#5165: ocamlbuild does not pass '-thread' option to ocamlfind - MPR#5213: ocamlbuild should pass '-rectypes' to ocamldoc when needed Feature wishes: - MPR#5065: added '-ocamldoc' option to ocamlbuild - MPR#5139: added possibility to add options to ocamlbuild - ocamlbuild: allow dependency on file "_oasis" Other changes: - Changed default minor heap size from 32k to 256k words. - Added new operation 'compare_ext' to custom blocks, called when comparing a custom block value with an unboxed integer. Objective Caml 3.12.0 (2 Aug 2010): ----------------------------------- Ocamlbuild: - Add support for native dynlink. All tools: - MPR#4857: add a -vnum option to display the version number and nothing else Objective Caml 3.11.2 (20 Jan 2010): ------------------------------------ Bug fixes: - MPR#4421: ocamlbuild uses wrong compiler for C files - MPR#4710, MPR#4720: ocamlbuild does not use properly configuration information - MPR#4856: ocamlbuild uses ocamlrun to execute a native plugin - MPR#4873: ocamlbuild ignores "thread" tag when building a custom toplevel - MPR#4890: ocamlbuild tries to use native plugin on bytecode-only arch - MPR#4896: ocamlbuild should always pass -I to tools for external libraries - MPR#4922: ocamlbuild recompiles too many files - Various build problems with ocamlbuild under Windows with msvc Feature wishes: - MPR#4723: "clear_rules" function to empty the set of ocamlbuild rules Objective Caml 3.11.1 (12 Jun 2009): ------------------------------------ - ocamlbuild: incorrectly using the compile-time value of $OCAMLLIB Objective Caml 3.11.0 (03 Dec 2008): ------------------------------------ Objective Caml 3.10.2 (29 Feb 2008): ------------------------------------ Objective Caml 3.10.1 (11 Jan 2008): ------------------------------------ - MPR#4286 ocamlbuild: cannot compile under AIX and SunOS - MPR#4304 ocamlbuild: handle -I correctly - MPR#4313 ocamlbuild: -log and missing directories - MPR#4327 ocamlbuild: make emacs look for .annot in _build directory - MPR#4378 ocamlbuild: typo in plugin.ml - MPR#4379 ocamlbuild: problem with plugins under Windows - MPR#4387 ocamlbuild: build directory not used properly - MPR#4410 ocamlbuild: problem with plugin and -build Objective Caml 3.10.0 (18 May 2007): ------------------------------------ New tools: - ocamlbuild: compilation manager for OCaml applications and libraries. See draft documentation at http://gallium.inria.fr/~pouillar/ The content below corresponds to the old Changelog, before ocamlbuild was included in the OCaml distribution. The version control history of those changes is unfortunately lost, but the log below is kept for historical purposes. (The use of a "* " bullet below does not indicate a compatibility-breaking change, it was just the standard format for this Changelog.) ------------------------------------------------------------------------- 2007-03-22 Nicolas Pouillard Allow to receive the build function in {custom,file}_rule. * rule.ml, * rule.mli, * signatures.mli: Ditto. * ocaml_specific.ml: Update. * command.ml, * command.mli: Add a function to get string and tags. * ocamldep.ml, * ocamldep.mli: Make tag based dependencies. * ocaml_compiler.ml: Do the pack as one command to be sure running the remove. * test/test8/myocamlbuild.ml, * test/good-output: Update. 2007-03-21 Nicolas Pouillard Fix the previous fix. * ocaml_compiler.ml: Remove the empty file. * test/good-output: Update. 2007-03-21 Nicolas Pouillard [native pack] use touch instead of mv and cmp. * ocaml_compiler.ml: This version is will force ocamlopt to do the right thing. * test/good-output: Update. 2007-03-20 Nicolas Pouillard Two bugs, two fixes. * ocaml_tools.ml: Add pp flags to interface inference. * ocaml_specific.ml: Add a rule for packing with a cmi that already exists. * test/good-output: Update. * Makefile: Change the default location. 2007-03-13 Nicolas Pouillard Fix a bug in expand_module. * ocaml_utils.ml: Handle correctly pathnames instead of just basenames. 2007-03-13 Nicolas Pouillard Use sys_file_exists instead of Sys.file_exists. * my_unix.ml: Since Sys.file_exists don't treat well captial letters. * my_std.ml: Fix a bug. * pathname.ml: Here is a an exception to the previous rule so, put a comment. 2007-03-11 Nicolas Pouillard Fix the List.union order. * my_std.ml: Fix and improve List.union. * pathname.ml: Use it and fix merge_include_dirs. * test/good-output: Update since the union order was wrong. 2007-03-11 Nicolas Pouillard Re fix menhir and include dirs. * ocaml_tools.ml: Specifiy ocamlc and -I with --ocamlc. 2007-03-11 Nicolas Pouillard Fix a bug: Add include directories to menhir. * ocaml_tools.ml: Ditto. * my_std.ml, * signatures.mli: Specification typo. 2007-03-07 Nicolas Pouillard Handle specially archives files during an import. * shell.ml: Ditto. 2007-03-07 Nicolas Pouillard Use cp -p in copy_rule, and fix some typos in the manual. * manual/manual.tex: Typos. * rule.ml, * rule.mli: Add cp_p and use it for copy_rule. 2007-03-05 Nicolas Pouillard Relaxe executor on exception condition. Patch from Berke. * executor.ml: Ignore Not_found and exceptional conditions. * TODO: Add an entry (needs to better understand POSIX). 2007-03-04 Nicolas Pouillard Split where in bindir and libdir. * ocamlbuild_where.mli: Ditto. * ocaml_specific.ml: Update. * options.ml: Use bindir. * plugin.ml: Update. * start.sh: Update. 2007-03-04 Nicolas Pouillard Virtual solvers for ocaml tools. * options.ml: Setup virtual command solver for commands like ocamlc, ocamlopt... This allow to have full pathname but let also failback to classic search path. * ocaml_compiler.ml: Add a tag to differentiate dependencies at link time. * ocamlbuild-presentation.rslide: Add an item as suggested by a friend. 2007-03-02 Nicolas Pouillard Same thing for the second link function. * ocaml_compiler.ml: Ignore stdlib. 2007-03-02 Nicolas Pouillard Move the stdlib hack. * ocaml_compiler.ml: Should works better. 2007-03-02 Nicolas Pouillard Little fix about library linking. * ocaml_utils.ml: Avoid linking twice in some cases. * ocaml_compiler.ml: Handle specially the OCaml stdlib. 2007-03-01 Nicolas Pouillard Remove a rec. * glob.ml: Parse is not rec. 2007-03-01 Nicolas Pouillard true: traverse and FAQ. * main.ml: Move the inital config upper to be loaded before the others and hygiene. * FAQ: New. 2007-02-28 Nicolas Pouillard Improve the glob dir handling. * glob.ml: Extend the ast instead of parsing an extended string. 2007-02-28 Nicolas Pouillard Ensure that the whole boolean expression is only valid in the directory. * glob.ml: Ditto. 2007-02-28 Nicolas Pouillard Put -g on link only for programs. * ocaml_specific.ml: Ditto. 2007-02-26 Berke Durak Added disclaimer to default rules table. * manual/manual.tex: . 2007-02-26 Nicolas Pouillard Add the -documentation option. * main.ml: Implement it. * flags.ml, * flags.mli: Add get_flags. * man/ocamlbuild.1: Update. * signatures.mli, * options.ml: Add show_documention. * rule.ml, * rule.mli: Add pretty_print. 2007-02-26 Nicolas Pouillard Add the -dont-catch-errors option. * main.ml: Implement it. * options.ml: Parse it. * signatures.mli: Declare it. * _tags: Use debug. 2007-02-26 Nicolas Pouillard Deal with the camlp4 library name. * ocaml_specific.ml: Introduce use_old_camlp4 for the old one. 2007-02-26 Nicolas Pouillard Minor `ocaml_lib' improvments. * signatures.mli: Declare and doc it. * ocamlbuild_plugin.ml: Export it. * ocaml_specific.ml, * ocaml_specific.mli: Add some dirs to std libs. Move the ocaml_lib implem to ... * ocaml_utils.mli, * ocaml_utils.ml: ... here. Improve it by adding the ~tag_name option. * ocaml_compiler.ml: The hash now contains the tag. * _tags: *.top use unix too. 2007-02-22 Berke Durak Should use Log.eprintf for show_tags. * main.ml: . 2007-02-22 Nicolas Pouillard ( & ), sanitize.sh, and the manual... * signatures.mli: Add ( & ). * hygiene.ml: Also clean the sanitize.sh script itself. * my_std.ml: Add ( & ). * manual/manual.tex: Some fixes and a section that I wrote but that's needs reflexion about what solution we want to support. 2007-02-22 Berke Durak Implemented fixes suggested by Commissar Leroy. * fda.ml: . * hygiene.ml: . * hygiene.mli: . * man/ocamlbuild.1: . * manual/manual.tex: . * ocaml_specific.ml: . * options.ml: . * signatures.mli: . 2007-02-20 Nicolas Pouillard Add -show-tags. * hygiene.ml: Rewrap the error message. * main.ml: Do the show_tags job. Move one hook. * ocaml_specific.ml: Add -g also in native code. * options.ml, * signatures.mli: Add the -show-tags option. * tags.ml: Fix print. * TODO: Add a done entry. 2007-02-16 Nicolas Pouillard Relaxing plural options to spaces. * lexers.mli, * lexers.mll: Add comma_or_blank_sep_strings. * options.ml: Use it. 2007-02-16 Nicolas Pouillard Add a plugin example. * manual/myocamlbuild.ml: New. 2007-02-16 Nicolas Pouillard Typos. * ocamlbuild-presentation.rslide: . * manual/trace.out: . 2007-02-16 Berke Durak Fixed a few typos and sentences. * ocamlbuild-presentation.rslide: . 2007-02-15 Nicolas Pouillard Little changes... * ocamlbuild-presentation.rslide: . 2007-02-15 Nicolas Pouillard Slides almost done... * manual/trace.out: New. Of course you needed it. * ocamlbuild-presentation.rslide: Ditto. 2007-02-15 Berke Durak Improving slides. * ocamlbuild-presentation.rslide: . 2007-02-15 Nicolas Pouillard Slides... * ocamlbuild-presentation.rslide: . 2007-02-15 Nicolas Pouillard Working on slides... * ocamlbuild-presentation.rslide: . 2007-02-15 Nicolas Pouillard More slides... * ocamlbuild-presentation.rslide: . 2007-02-12 Nicolas Pouillard Keep include dirs uniq. * ocaml_compiler.ml: Ditto. 2007-02-12 Nicolas Pouillard Keep include dirs uniq. * ocaml_compiler.ml: Ditto. 2007-02-12 Nicolas Pouillard Add ocamlmktop support. * ocamlbuild.mltop: New. * main.ml: Handle .top as binaries. * ocaml_compiler.ml, * ocaml_specific.ml, * ocaml_compiler.mli: Add mktop functions and rules. * options.ml, * signatures.mli: Add an ocamlmktop option. 2007-02-09 Berke Durak Was attempting to link with threads.cmxa in byte mode. * ocaml_specific.ml: . 2007-02-09 Berke Durak Talking of sterilize.sh. * manual/manual.tex: . 2007-02-09 Berke Durak Rewrote some parts, filled the abstract, moved rantings to the appendix. * manual/manual.tex: . * .vcs: . 2007-02-08 Nicolas Pouillard Add manual/manual.hva. * manual/manual.hva: New. 2007-02-08 Nicolas Pouillard Changes done with Luc. * manual/manual.tex: . * manual/Makefile: . 2007-02-08 Nicolas Pouillard Fix a bug found by Luc in hevea. * ocaml_utils.ml, * ocaml_utils.mli: Change keep_this_module into module_importance to have a finer grain. * ocaml_compiler.ml: Update to importance. * ocamldep.ml, * ocamldep.mli: We now try to also build stdlib modules but don't fail if they don't exists. * test/test5/stack.ml: New. * test/test5/a.ml: A test case (from hevea). * test/good-output: Update. 2007-02-08 Nicolas Pouillard Ocamldoc, extension:* tag ... * ocaml_tools.mli, * ocaml_tools.ml: The ocamldoc support now takes into account two modes *d and -o. * ocaml_specific.ml: Two more rules and many flags for some of the standard behaviors. * signatures.mli: Some comments. * tools.ml: Add the extension:* tag. * TODO: Update. 2007-02-08 Berke Durak Hygiene generates sterilize.sh. * fda.ml: . * fda.mli: . * hygiene.ml: . * hygiene.mli: . * main.ml: . * options.ml: . * signatures.mli: . 2007-02-07 Berke Durak Updated section on ocamldoc. * manual/manual.tex: . 2007-02-07 Nicolas Pouillard Some minor manual and slides changes. * ocamlbuild-presentation.rslide, * manual/manual.tex: Ditto. 2007-02-07 Nicolas Pouillard Make links for the documentation. * main.ml: Handle doc. * test/good-output: Update. 2007-02-07 Berke Durak Added manual section for ocamldoc. * manual/manual.tex: . * manual/Makefile: . 2007-02-07 Berke Durak Fixed truncated display problem. * executor.ml: . * .vcs: . 2007-02-07 Nicolas Pouillard Fix the bootstrap. * start.sh: Swap lines. * Makefile: -verbose. 2007-02-07 Berke Durak TODO + Executor. * manual/manual.tex: . * TODO: . 2007-02-06 Nicolas Pouillard Make -a more static, to avoid some complications. * ocaml_utils.ml, * ocaml_compiler.ml, * ocaml_compiler.ml, * ocaml_specific.ml: Ditto. 2007-02-06 Nicolas Pouillard A fix. * ocaml_compiler.ml: Don't use these refs too early. * ocamlbuild-presentation.rslide: . 2007-02-05 Nicolas Pouillard Plugin signature. Somewhat a big patch, but that's just moving things around. * signatures.mli: Add TAGS, OUTCOME, MISC, OPTIONS, ARCH and PLUGIN. * ocamlbuild_plugin.mli: New. * ocamlbuild_plugin.ml: Conform to the sig. * command.ml, * command.mli: Add a tags type. * main.ml: Quit early if no targets. * my_std.ml, * my_std.mli: More things are in signatures. * resource.ml, * resource.mli: Remove the type t that was an Pathname.t alias. * options.ml, * options.mli: Add ext_lib, ext_obj, ext_dll. * ocaml_compiler.ml: Update. * ocaml_tools.ml: Update to Outcome. * ocaml_specific.ml: Update. * ocaml_utils.mli: Remove *ext_*. * ocaml_arch.mli: Now in signatures. * pathname.ml: Add readdir. * slurp.ml: open Outcome. * rule.ml, * rule.mli, * solver.ml, * solver.mli: Update to Resource.t and Outcome.t. * tags.mli: Now in Signatures. * test/good-output: Update. * test/test8/test.sh, * test/test3/test.sh, * test/test4/test.sh, * test/test5/test.sh, * test/test6/test.sh, * test/test7/test.sh, * test/test2/test.sh: Update to -verbose 0. 2007-02-05 Berke Durak Continuing doc. * manual/manual.tex: . * .: . 2007-02-05 Berke Durak Described display line. * manual/manual.tex: . 2007-02-05 Berke Durak Renamed -debug as -verbose. Authorized spaces etc. in flags. Continuing documentation. * lexers.mll: . * manual/manual.tex: . * options.ml: . 2007-02-05 Berke Durak Added man page. * main.ml: . * man: New. * man/ocamlbuild.1: New. * manual/manual.tex: . * TODO: . 2007-02-05 Nicolas Pouillard Update start.sh. * start.sh: Update. 2007-02-05 Nicolas Pouillard Typo s/Orignal/Original/g. 2007-02-05 Nicolas Pouillard Make signatures and std_signatures mliS. * signatures.ml: Remove. * std_signatures.ml: Remove. * signatures.mli: New. * std_signatures.mli: New. * Makefile: Update. * lexers.mll: Allow any prefix: for tags. 2007-02-04 Nicolas Pouillard The beginning of a presentation. * ocamlbuild-presentation.rslide: New. 2007-02-04 Nicolas Pouillard Also add who is the original author of the file. * ocamlbuild.ml, * ocamlbuild_plugin.ml, * ocamlbuildlight.ml, * ocamlbuild_where.mli, * ocamlbuild.mli, * ocamlbuildlight.mli, * bool.ml, * bool.mli, * configuration.ml, * configuration.mli, * command.ml, * command.mli, * display.ml, * discard_printf.ml, * display.mli, * discard_printf.mli, * executor.ml, * executor.mli, * flags.ml, * fda.ml, * flags.mli, * fda.mli, * glob.ml, * glob_ast.ml, * glob_ast.mli, * glob.mli, * glob_lexer.mli, * glob_lexer.mll, * hygiene.ml, * hooks.ml, * hygiene.mli, * hooks.mli, * log.ml, * lexers.mli, * log.mli, * lexers.mll, * my_unix_with_unix.ml, * main.ml, * my_unix.ml, * my_std.ml, * my_unix_with_unix.mli, * my_std.mli, * my_unix.mli, * main.mli, * ocaml_utils.ml, * ocaml_tools.ml, * ocaml_arch.ml, * ocaml_specific.ml, * ocaml_compiler.ml, * ocaml_dependencies.ml, * ocaml_utils.mli, * ocaml_specific.mli, * ocaml_dependencies.mli, * ocaml_tools.mli, * ocaml_arch.mli, * ocaml_compiler.mli, * options.ml, * options.mli, * ocamldep.ml, * ocamldep.mli, * plugin.ml, * ppcache.ml, * pathname.ml, * ppcache.mli, * plugin.mli, * pathname.mli, * resource.ml, * resource.mli, * rule.ml, * rule.mli, * report.ml, * report.mli, * signatures.ml, * slurp.ml, * std_signatures.ml, * solver.ml, * shell.ml, * shell.mli, * slurp.mli, * solver.mli, * tags.ml, * tools.ml, * tags.mli, * tools.mli: Ditto. 2007-02-04 Nicolas Pouillard Add the header license. * ocamlbuildlight.ml, * ocamlbuild.ml, * ocamlbuild_plugin.ml, * ocamlbuild_where.mli, * ocamlbuild.mli, * ocamlbuildlight.mli, * bool.ml, * bool.mli, * configuration.ml, * configuration.mli, * command.ml, * command.mli, * discard_printf.ml, * display.ml, * display.mli, * discard_printf.mli, * executor.ml, * executor.mli, * fda.ml, * flags.ml, * flags.mli, * fda.mli, * glob.ml, * glob_ast.ml, * glob.mli, * glob_ast.mli, * glob_lexer.mli, * glob_lexer.mll, * hygiene.ml, * hooks.ml, * hygiene.mli, * hooks.mli, * log.ml, * lexers.mli, * log.mli, * lexers.mll, * my_unix.ml, * main.ml, * my_std.ml, * my_unix_with_unix.ml, * misc/opentracer.ml, * my_std.mli, * main.mli, * my_unix.mli, * my_unix_with_unix.mli, * ocaml_arch.ml, * ocaml_compiler.ml, * ocaml_specific.ml, * ocaml_tools.ml, * ocaml_utils.ml, * ocaml_dependencies.ml, * ocaml_utils.mli, * ocaml_tools.mli, * ocaml_dependencies.mli, * ocaml_compiler.mli, * ocaml_specific.mli, * ocaml_arch.mli, * options.ml, * options.mli, * ocamldep.ml, * ocamldep.mli, * plugin.ml, * pathname.ml, * ppcache.ml, * plugin.mli, * ppcache.mli, * pathname.mli, * resource.ml, * resource.mli, * rule.ml, * rule.mli, * report.ml, * report.mli, * slurp.ml, * std_signatures.ml, * signatures.ml, * solver.ml, * shell.ml, * shell.mli, * slurp.mli, * solver.mli, * tools.ml, * tags.ml, * tags.mli, * tools.mli: Ditto. 2007-02-03 Nicolas Pouillard Fix a bug in copy_file. * my_std.ml: Also use the binary mode for the output channel. 2007-02-03 Nicolas Pouillard Add nopervasives, and nolabels. * ocaml_specific.ml: Ditto. 2007-02-03 Nicolas Pouillard Windows cannot use executor. * shell.ml: As in command.ml use executor only in non-windows and non-degraded mode. * rule.ml: Update two error messages. 2007-02-02 Nicolas Pouillard Some minor things for the ocaml myocamlbuild for instance. * configuration.ml, * configuration.mli: Add has_tag. * my_std.ml, * my_std.mli: Add getenv and copy_chan. * ocaml_utils.ml, * ocaml_utils.mli: Move some commands to rule. * ocaml_specific.ml: Improve the menhir switching. * options.ml, * options.mli: Add -use-menhir and -menhir options. * rule.ml, * rule.mli: Add copy_rule and move some commands from ocaml_utils. * signatures.ml: . 2007-02-01 Nicolas Pouillard Move main sigs in signatures.ml and std_signatures.ml. * ocamlbuild_pack.mlpack: . * ocamlbuildlib.mllib: . * ocamlbuildlightlib.mllib: . * ocamlbuild.odocl: . * command.mli: . * glob.mli: . * log.mli: . * my_unix_with_unix.ml: . * my_std.ml: . * my_std.mli: . * ocaml_specific.ml: . * pathname.mli: . * std_signatures.ml: New. * signatures.ml: New. * start.sh: . * tags.ml: . * tags.mli: . * test/test5/_tags: . * Makefile: . * _tags: . 2007-02-01 Berke Durak Shell.run doesn't use execute_many in degraded mode. * shell.ml: . 2007-02-01 Berke Durak cp, rm -rf and mv-like commands use Executor to better play with display. * display.ml: . * my_unix.ml: . * main.ml: . * my_std.ml: . * my_unix.mli: . * shell.ml: . * shell.mli: . * start.sh: . * _tags: . 2007-02-01 Berke Durak Systematizing exit codes. * executor.ml: . * main.ml: . 2007-02-01 Berke Durak Added automatic file: tag, changed flag syntax. * lexers.mli: . * lexers.mll: . * main.ml: . * ocamldep.ml: . * ocamldep.mli: . * tools.ml: . 2007-01-31 Berke Durak Cleans up links to the _build directory. * main.ml: . * options.ml: . * options.mli: . * pathname.ml: . * pathname.mli: . 2007-01-31 Nicolas Pouillard Restore the link to binary targets functionality. * main.ml: Make it separate from target running. 2007-01-31 Nicolas Pouillard Add an hygiene hook pair. * ocamlbuild_plugin.ml, * hooks.ml, * hooks.mli, * main.ml: Ditto. 2007-01-31 Nicolas Pouillard The Killer feature about a fine grained dependency injection control. * rule.ml, * rule.mli: Add build_deps_of_tags and call it automatically before * ocaml_compiler.ml, * ocaml_compiler.mli: Rework tags, to have them when callinng build_deps_of_tags. executing a command. * ocaml_specific.ml, * ocaml_specific.mli: Move the exception Exit_build_error to main and remove the old dep function. * ocamlbuild_plugin.ml: Export some new functions. * test/test7/myocamlbuild.ml: Add a dep declaration. * test/test7/cool_plugin.ml: New. * test/test7/_tags: New. * test/good-output: Update. * flags.ml, * command.ml, * command.mli: Rename flags_of_tags as tag_handler. * main.ml: Update error handling. * TODO: Done. 2007-01-30 Nicolas Pouillard Fix and improve the new link/deps system. * ocaml_dependencies.ml, * ocaml_dependencies.mli: Some fixes and improvements. * pathname.ml, * pathname.mli: Add check_extension. * ocaml_compiler.ml, * ocaml_compiler.mli: Add support for hidden_packages and update. 2007-01-30 Nicolas Pouillard Reverse the last 2 patches, since there is fact no name clash. 2007-01-30 Nicolas Pouillard Shell -> Oshell second part. * ocamlbuild.odocl: Ditto. * test/good-output: Update. 2007-01-30 Nicolas Pouillard Rename the Shell module as Oshell to avoid a name clash with labltk. * shell.ml: Remove. * shell.mli: Remove. * oshell.ml: New. * oshell.mli: New. * ocamlbuild_pack.mlpack, * command.ml, * display.ml, * main.ml, * options.ml, * ppcache.ml, * pathname.ml, * plugin.ml, * resource.ml, * start.sh: Update. 2007-01-30 Nicolas Pouillard Fix 2 bugs. * test/test9/testglob.ml: More tests. * glob_lexer.mll: Fix "/**". * _tags: Restore my warnings. * executor.ml: Use the unused variable. 2007-01-30 Nicolas Pouillard Improve dprintf and update. * log.ml, log.mli: dprintf now wraps the message between "@[<2>" and "@]@.". * command.ml, * display.ml, * fda.ml, * main.ml, * ocaml_dependencies.ml, * ocaml_compiler.ml, * ocaml_utils.ml, * ocamldep.ml, * pathname.ml, * resource.ml, * rule.ml, * solver.ml: Update the dprintf usage. 2007-01-30 Nicolas Pouillard Add the new dependency linking system (plz test it !). * ocamlbuild_pack.mlpack: Add a brand new module. * ocaml_dependencies.ml: New. * ocaml_dependencies.mli: New. * ocaml_compiler.ml, * ocaml_compiler.mli: Use this new module. * resource.ml, * resource.mli: Export a folding function on dependencies. * TODO: Add something to do. * start.sh: . * main.ml: Update. 2007-01-29 Nicolas Pouillard Executor exit codes. * executor.ml: Use the standard exit. * main.ml: Some exit codes are reserved for Executor. 2007-01-29 Berke Durak Executor returns finer-grained results. * executor.ml: . * manual/manual.tex: . 2007-01-29 Nicolas Pouillard Toward a working command execute feature :). * executor.ml, * executor.mli: FIXME. * command.ml, * command.mli: Update to the new signature and merge the degraded mode to avoid duplication. * my_unix.ml, * my_unix.mli, * ocaml_utils.ml, * ocamldep.ml, * plugin.ml, * resource.ml, * rule.ml, * solver.ml, * test/good-output: Update. 2007-01-29 Nicolas Pouillard Revert almost all of the 2 last patches. * command.ml: . * command.mli: . * executor.ml: . * executor.mli: . * my_unix.ml: . * my_unix.mli: . * ocaml_utils.ml: . * ocaml_specific.ml: . * ocamldep.ml: . * plugin.ml: . * resource.ml: . * rule.ml: . * solver.ml: . 2007-01-29 Berke Durak Fixing before/after thunks. * command.ml: . * command.mli: . * ocaml_utils.ml: . * ocamldep.ml: . * plugin.ml: . * resource.ml: . * rule.ml: . * solver.ml: . * TODO: . 2007-01-29 Berke Durak Adding before and after handlers to Executor. * command.ml: . * executor.ml: . * executor.mli: . * my_unix.ml: . * my_unix.mli: . * manual/manual.tex: . 2007-01-29 Berke Durak Fixed multi-dir globbing. * glob_lexer.mll: . * manual/manual.tex: . 2007-01-29 Nicolas Pouillard Add Rule.custom_rule and cleanup the ocamldep meta rule. * ocamldep.ml, * ocamldep.mli: Make it a meta rule (or a rule generator). * rule.ml, * rule.mli: Add custom_rule. * ocaml_specific.ml: Update to Ocamldep. * test/good-output: Minor update. 2007-01-29 Nicolas Pouillard MakefileS... * manual/Makefile: More things to remove (sometimes). * Makefile: Use $(BUILDDIR) instead of _build. 2007-01-26 Berke Durak Documenting glob expressions. * glob_lexer.mll: Added negative character classes. * manual/manual.tex: . 2007-01-26 Berke Durak Started documenting glob syntax. * manual/manual.tex: . 2007-01-25 Nicolas Pouillard One other include dir fix. * main.ml: Ditto. * test/test9/testglob.ml: Add a failing test (request for feature). * test/good-output: Update. 2007-01-25 Nicolas Pouillard Include dirs and Backtrace. * main.ml: Fix -I, and restore the backtrace. * report.ml, * report.mli: Fix the backtrace and rename analyze to print_backtrace_analyze. 2007-01-25 Berke Durak Added cross-directory globbing. * glob_ast.ml: . * glob.ml: . * glob_ast.mli: . * glob_lexer.mll: . * test/test9/testglob.ml: . 2007-01-25 Nicolas Pouillard Inlcude dirs trought tags. * main.ml: Ditto. * my_unix_with_unix.ml: Imrpove stat errors. * my_std.ml, * my_std.mli: . * pathname.ml: bmla. * slurp.ml, * slurp.mli: Add force, fix bugs. 2007-01-25 Berke Durak Fixed double display of error status. * command.ml: . * display.ml: . * display.mli: . * log.ml: . * log.mli: . * main.ml: . * my_std.ml: . * my_std.mli: . * plugin.ml: . 2007-01-25 Berke Durak Stupid bug. * log.ml: . * main.ml: . * options.ml: . 2007-01-25 Berke Durak Fixed interface, handling of -- with no argument. * ocamlbuild_plugin.mli: Remove. * manual/manual.tex: . * options.ml: . 2007-01-25 Berke Durak Updated start.sh. * start.sh: . 2007-01-25 Berke Durak Added .mlis. * ocamlbuild_plugin.mli: New. * fda.mli: New. * main.ml: . * ocaml_specific.ml: . * plugin.ml: . * plugin.mli: New. 2007-01-25 Nicolas Pouillard Cut down ocaml_specific in pieces. * ocaml_specific.ml, * ocaml_specific.mli: Split. * ocamlbuild_plugin.ml: Update. * ocamlbuild_pack.mlpack: Add new modules. * my_std.ml, * my_std.mli: Add good_outcome. * ocaml_utils.ml: New. * ocaml_tools.ml: New. * ocaml_compiler.ml: New. * ocaml_utils.mli: New. * ocaml_compiler.mli: New. * ocaml_tools.mli: New. * ocamldep.ml: New. * ocamldep.mli: New. * start.sh: Update. * TODO: Move things done. 2007-01-25 Berke Durak Fixer return codes and error message flushing issues. * display.ml: . * log.ml: . * log.mli: . * main.ml: . * report.ml: . * report.mli: . 2007-01-25 Nicolas Pouillard Add a warning. * ocaml_specific.ml: In -debug 1 mode there is a now a warning when ocamlbuild skip a seliently a module, supposing that's an error of ocamldep. 2007-01-24 Nicolas Pouillard More hooks. * ocamlbuild_plugin.ml, * hooks.ml, * hooks.mli, * main.ml: Add {Before,After}_rules. 2007-01-24 Nicolas Pouillard Call these hooks. * main.ml: Call these hooks. 2007-01-24 Nicolas Pouillard Add a first version of dispatch. * ocamlbuild_plugin.ml: Export dispatch and the hooks type. * ocamlbuild_pack.mlpack: Add Hooks. * hooks.ml: New. * hooks.mli: New. * ocaml_specific.mli: New line. 2007-01-24 Berke Durak Mini slurp bug. * slurp.ml: . * TODO: . 2007-01-24 Nicolas Pouillard Fix few more things. * ocamlbuildlight.ml: . * ocamlbuild_version.ml: Remove. * ocamlbuild.ml: . * ocamlbuild_pack.mlpack: . * main.ml: . * ocaml_specific.ml: . * ocaml_specific.mli: . * start.sh: . * test/test2/toto.ml: . * test/good-output: . 2007-01-24 Berke Durak Read directories before files in Slurp. * slurp.ml: . * TODO: . 2007-01-24 Nicolas Pouillard Fix some bugs. * ocamlbuild_version.ml: Remove. * ocamlbuild.ml, * ocamlbuildlight.ml: Main is now in the pack. * ocamlbuild_pack.mlpack: more things. * ocaml_specific.ml: One fix and one comment. * start.sh: Update. 2007-01-24 Berke Durak Splitting ocaml_specific into multiple files. * ocamlbuildlight.ml: . * ocamlbuild.ml: . * ocamlbuild_version.ml: New. * ocamlbuild.mli: . * ocamlbuildlight.mli: . * ocamlbuild_pack.mlpack: . * command.ml: . * fda.ml: New. * hygiene.ml: . * main.ml: New. * my_std.ml: . * my_std.mli: . * main.mli: New. * manual/manual.tex: . * ocaml_specific.ml: . * ocaml_specific.mli: . * options.ml: . * options.mli: . * plugin.ml: New. * rule.ml: . * report.ml: . * tools.ml: New. * tools.mli: New. * TODO: . * _tags: . 2007-01-24 Nicolas Pouillard Minor changes. * manual/manual.tex: Typo s/the the/the/g. * ocaml_specific.ml, * ocaml_specific.mli: Add some function to deal with linking of a module list. Add a better lib declaration function. * TODO: Update. 2007-01-17 Nicolas Pouillard A new pathname operator and a bug fix. * pathname.ml, * pathname.mli: add the ( -.- ) operator to add an extension to a pathname. * ocaml_specific.ml: Use that new operator. * resource.ml: Fix a bug. 2007-01-17 Berke Durak More examples. * examples/example3/epoch.ml: . * examples/example3/make.sh: New. * manual/manual.tex: . * TODO: . 2007-01-17 Nicolas Pouillard Infered mli's, and bug fixes. * my_unix.ml: Fix a bug. * my_std.mli: Doc. * manual/manual.tex: Use \verb. * ocaml_arch.ml: Don't always overide the forpack_flags_of_pathname function reference. * ocaml_arch.mli: Remove the reference. * ocaml_specific.ml: Update for forpack and add infered mli's. * pathname.ml, * pathname.mli: Add is_directory. 2007-01-17 Berke Durak More examples. * examples/example3/epoch.ml: New. * examples/example2/hello.ml: . * examples/example2/greet.ml: New. * examples/example3: New. * examples/example2: New. * manual/manual.tex: . * TODO: . 2007-01-17 Berke Durak Started examples. * examples/example1/hello.ml: New. * examples/example1: New. * examples: New. * manual/manual.tex: . * .vcs: . * TODO: . 2007-01-17 Berke Durak Wrote limitations and features. * manual/manual.tex: . 2007-01-17 Berke Durak Wrote motivations. * manual/manual.tex: . * _tags: . 2007-01-17 Berke Durak Started manual. * manual/Makefile: New. * manual/manual.tex: New. * manual: New. 2007-01-17 Nicolas Pouillard Bugs, menhir, path variables. * display.ml: Fix a bug. * glob.mli: Fix a typo. * lexers.mli, * lexers.mll: Extend ocamldep_output lexer and meta_path lexer. * my_std.ml, * my_std.mli: Add memo and String.rev. * ocaml_specific.ml, * ocaml_specific.mli: Better rules for C lib linking and menhir rules. * resource.ml, * resource.mli: Handle naively some multiple variables. * rule.ml, * rule.mli: Update. * start.sh: Update. 2007-01-11 Nicolas Pouillard Integrate dprintf to the display. * display.ml, * display.mli: Add dprintf and log_level. * log.ml, * log.mli: Add dprintf and level. * debug.ml: Remove. * debug.mli: Remove. * options.ml: Update. * command.ml, ocaml_specific.ml, my_std.ml, * pathname.ml, ppcache.ml, resource.ml, * rule.ml, report.ml, slurp.ml, solver.ml, * configuration.ml, tags.ml: Update to Log. * ocamlbuild.odocl: Add Log, remove Debug. * ocamlbuild_pack.mlpack: Remove Debug. * bool.ml: Remove the debug dependency. 2007-01-10 Nicolas Pouillard Execute and windows... * command.ml: Test windows here. * my_unix_with_unix.ml: Revert a little. 2007-01-10 Nicolas Pouillard Don't use executor on windows. * my_unix_with_unix.ml: Since at least set_nonblock does not works on windows. 2007-01-10 Nicolas Pouillard Add the -no-log option and fix a log bug. * log.mli, * log.ml: Log is now a lazy to have the good setup order. * options.ml: Add the -no-log option. 2007-01-10 Nicolas Pouillard Fix a bug with quoting of the nil string. * shell.ml: Quote the nil string. 2007-01-09 Berke Durak Documented the interface of the glob module. * glob.mli: . 2007-01-09 Berke Durak Continuing to document interfaces. * bool.mli: . * debug.mli: . * discard_printf.mli: . * executor.mli: . * hygiene.mli: . * my_std.mli: . * slurp.mli: . * Makefile: . 2007-01-09 Nicolas Pouillard Fix a bug with directory links to build dir. * ocaml_specific.ml, * options.ml, * options.mli: Keep the Slurp.entry instead of a set. * pathname.ml: Clean the entry instead of the set, that more precise. * Makefile: Add doc phonny rules. 2007-01-09 Berke Durak Doc for Configuration. * ocamlbuild_plugin.ml: . * bool.mli: . * configuration.ml: . * configuration.mli: . * command.mli: . * doc: New. * glob.ml: . * ocaml_specific.ml: . * Makefile: . 2007-01-09 Berke Durak Started documentation. * bool.mli: . * command.ml: . * command.mli: . 2007-01-09 Nicolas Pouillard Export the doc. * Makefile: Use a link. * _tags: Don't spend times in that dir. 2007-01-09 Nicolas Pouillard Put the log file in the source dir and not when building plugin. * log.ml, * log.mli: Use an optional. * options.ml: Update. * pathname.mli: Export in_source_dir. * .vcs: Add _log. 2007-01-09 Berke Durak Added doc target. * report.ml: . * Makefile: . * TODO: . 2007-01-09 Berke Durak Writes tags to log file. * display.ml: . 2007-01-09 Nicolas Pouillard Add the Log module. * ocamlbuild_pack.mlpack: Add Log. * command.ml, * command.mli: Use Log. * log.ml: New. * log.mli: New. * options.ml: Use Log. * start.sh: Update. 2007-01-09 Berke Durak Added -log option. * command.ml: . * command.mli: . * display.ml: . * display.mli: . * executor.mli: . * options.ml: . * _tags: . 2007-01-09 Nicolas Pouillard Make usable the ocamldoc support. * ocaml_specific.ml: Add rules for ocamldoc. * ocamlbuild.odocl: New. * test/test3/proj.odocl: New. * test/good-output: Update. * test/test3/test.sh: Add a odoc test. 2007-01-09 Nicolas Pouillard Some cleanups. * ocamlbuild_plugin.ml: Add tag_file that simule one simple line in the _tags file. * ocaml_specific.ml, * ocaml_specific.mli: Add ln_s, touch, chmod. * pathname.ml, * pathname.mli: Remove map_extension*, split_extension* and compiled files hack skipping. * rule.ml: Improve logging. * solver.ml: Use another level. 2007-01-07 Nicolas Pouillard Fix a bug with debug rules. * ocaml_specific.ml: Move %.cmi from prods to deps. * test/good-output: Update. 2007-01-07 Nicolas Pouillard Add debugging rules. To get a ocamlbuild with debugging info you can call `make debug' that will produce ocamlbuild.d.byte and x.d.cmo files. * ocaml_specific.ml, * ocaml_specific.mli: Add debugging rules, reorder warnings flag to have 'A' and 'a' before others. * Makefile: Add the debug target. * _tags: Cleanup (remove the debug tag that was set by default). 2007-01-07 Nicolas Pouillard Add profiling support directly in rules. This means that you can now request for building a target such as my_main.p.native or my_lib.p.cmxa, that will create %.p.cmx intermediate files that do not interfer with non-profiling ones. * ocaml_specific.ml, * ocaml_specific.mli: Add rules and functions for native link and comilation in profiling mode. * Makefile: Add a profile target (require a fixed ocamlopt w.r.t pack). * _tags: Take care also of .p.cmx files. * glob.ml: IS.print is equivalent to print_is. * my_std.ml: Fix a bug. 2007-01-07 Nicolas Pouillard Add some functions... * glob.ml: Extract is_suffix and is_prefix. * my_std.ml, * my_std.mli: Add String.{is_suffix,is_prefix,first_chars,last_chars} and List.union. * pathname.ml, * pathname.mli: Add get_extensions, remove_extensions, update_extensions, map_extensions that treat all extensions instead of just the last. * tags.ml, * tags.mli: Add +++ and --- that treat optional tags. 2007-01-06 Nicolas Pouillard Change the default display in degraded mode. * command.ml: Ditto. 2007-01-06 Nicolas Pouillard Cleanup Makefile options. * Makefile: Ditto. 2007-01-06 Nicolas Pouillard Add a simple opened files tracer. * misc/opentracer.ml: New. Just support ktrace for now. A strace one will be appreciated the interface to follow is quite simple anyway. * misc: New. 2007-01-06 Nicolas Pouillard Handle better commands without Px atom. * command.ml: Display the whole command if no Px is found. * display.mli: No longer export these strings. 2007-01-06 Nicolas Pouillard Handle myocamlbuild_config.mli. * ocaml_specific.ml: Add support for an interface to the config. 2007-01-06 Berke Durak Improved language of explanations in Report. * report.ml: . 2007-01-06 Nicolas Pouillard Factor and fix the plugin building. * ocamlbuildlight.mli: New. * executor.ml: Call cleanup, add a fixme. * ocaml_specific.ml: Factor and fix plugin stuffs. * start.sh: Update. * Makefile: Update. * TODO: Update. * _tags: No longer do favors to some modules. 2007-01-05 Nicolas Pouillard Fix plugins. * ocamlbuildlib.mllib: Add missing modules. * ocamlbuildlightlib.mllib: New. * Makefile: Update. 2007-01-05 Nicolas Pouillard Change the my_unix system. * ocamlbuildlight.ml: Just call the main. * ocamlbuild.ml: Setup my_unix_with_unix. * ocamlbuildlib.mllib: Remove executor and exit_codes for the lib. * ocamlbuild_pack.mlpack: Remove my_std and my_unix. * exit_codes.ml: Remove. Put them directly in executor. * executor.ml: Add exitcodes. * my_unix.ml: New. Default implem. * my_unix_with_unix.ml: Extend the default implem. * my_unix_without_unix.ml: Remove. * my_unix.mli: Add the implem type and val. * my_unix_with_unix.mli: New. * ocaml_specific.ml, * pathname.ml, * slurp.ml, * Makefile, * command.ml, * _tags: Update. 2007-01-05 Nicolas Pouillard Don't use executor for the myocamlbuild call. * ocaml_specific.ml: Use sys_command directly. 2007-01-05 Nicolas Pouillard Fix a stupid bug. * command.ml: That cause to have reversed sequences. 2007-01-05 Nicolas Pouillard Some libs and ocamldoc changes. * ocaml_specific.ml, * ocaml_specific.mli: Improve ocaml_lib_flag, add fews libs. Fix ocamldoc support update tags, and use Px only once. 2007-01-05 Berke Durak Started ocamldoc support. * ocaml_specific.ml: . * options.ml: . * options.mli: . 2007-01-05 Berke Durak Pretend option didn't work. * command.ml: . 2007-01-05 Berke Durak TODO + typo. * options.ml: . * TODO: . 2007-01-05 Nicolas Pouillard Really call executor all time. * command.ml, * command.mli: Remove normalization. And execute_many, it's now execute that do all the job. In degraded mode it's execute_degraded. * my_unix_without_unix.ml: Update. * ocaml_specific.ml, * resource.ml, * rule.ml, * solver.ml: Update to Command.execute type. 2007-01-05 Berke Durak Isatty detection logic. * command.ml: . * executor.ml: . * my_unix_with_unix.ml: . * my_unix_without_unix.ml: . * my_unix.mli: . 2007-01-05 Nicolas Pouillard Always call executor. * command.ml: Unless in degraded mode. 2007-01-05 Berke Durak Removed debugging output, added period argument for ticker. * display.ml: . * executor.ml: . * executor.mli: . * my_unix.mli: . 2007-01-05 Berke Durak Somewhat slow but executor seems to work. * executor.ml: . 2007-01-05 Berke Durak Added an Exit_codes module. Fixing Executor... * ocamlbuild.ml: . * ocamlbuildlib.mllib: . * executor.ml: . * exit_codes.ml: New. * solver.ml: . 2007-01-05 Nicolas Pouillard Fix the max_jobs argument passing. * command.ml: Use an optional argument. 2007-01-05 Nicolas Pouillard Subway changes... * my_unix_without_unix.ml, * my_unix_with_unix.ml, * my_unix.mli, * command.ml: Call the new execute_many. * executor.ml, * executor.mli: Handle command sequences. 2007-01-04 Berke Durak Added Display.update. * display.ml: . * display.mli: . * executor.ml: . 2007-01-04 Berke Durak Added display function, indentation, language. * display.ml: . * display.mli: . * hygiene.ml: . 2007-01-04 Berke Durak Fixing interface of Executor. * executor.ml: . * executor.mli: . * my_unix_with_unix.ml: . 2007-01-04 Nicolas Pouillard Add attributes to entries. Add the -byte-plugin option. * slurp.ml, * slurp.mli: Add an attribute field, add map, rename fold_pathnames to fold and filter_on_names to filter. * hygiene.ml, * hygiene.mli: Perform hygiene only on entries with a true attribute. * options.ml, * options.mli: Add the native_plugin reference and the -byte-plugin option. * ocaml_specific.ml, * ocaml_specific.mli: Exclude files tagged not_hygienic or precious from hygiene. 2007-01-04 Berke Durak Fixed pack issues. * ocamlbuild.ml: . * executor.ml: . * executor.mli: New. * _tags: . 2007-01-04 Berke Durak Started executor module. * executor.ml: New. * hygiene.ml: . * my_unix_with_unix.ml: . 2007-01-04 Nicolas Pouillard Add virtual commands. * command.ml, * command.mli: Add the V constructor for virtual commands that will query a virtual command solver to use the best implementation of that virtual command. 2007-01-04 Nicolas Pouillard Mainly, prepare for parallel display. * ocamlbuild_plugin.ml: Export file_rule. * command.ml, * command.mli: Some cleanup and preparation. * lexers.mll: Remove the dirty hack. * my_std.ml, * my_std.mli: Move search_in_path to Command and add ( @:= ). * my_unix_with_unix.ml, * my_unix_without_unix.ml, * my_unix.mli: Change the execute_many_using_fork type. * ocaml_specific.ml: Use the nopervasives tag for pervasives dependencies. * start.sh: Update. * test/test8/myocamlbuild.ml: Update. * test/good-output: Update. * Makefile: Update. 2007-01-03 Nicolas Pouillard I don't like microbes. * hygiene.ml: Reverse the bool. 2007-01-03 Nicolas Pouillard Fix the stat problem. * ocaml_specific.ml: Use the filtered entry for source_dir_path_set. 2007-01-03 Berke Durak Hygiene filters cleaned out microbes. * hygiene.ml: . * hygiene.mli: . * ocaml_specific.ml: . * ocaml_specific.mli: . * slurp.ml: . * slurp.mli: . 2007-01-03 Nicolas Pouillard Filename concat cleanup. * my_std.ml, * my_std.mli: Add filename_concat. * glob.ml, * hygiene.ml, * lexers.mll, * pathname.ml, * resource.ml, * report.ml, * solver.ml, * slurp.ml, * solver.mli: Use filename_concat. * flags.ml: FIXME. 2007-01-03 Berke Durak Revert to old. * slurp.ml: . 2007-01-03 Berke Durak Debugging tags for myocamlbuild.ml. * ocaml_specific.ml: . * slurp.ml: . 2007-01-02 Nicolas Pouillard Another atempt to fix the slurp bug and lazy. * slurp.ml: Ditto. 2007-01-02 Nicolas Pouillard Fix slurp w.r.t lazyness: keep the cwd. * slurp.ml: Ditto. 2007-01-02 Nicolas Pouillard My_unix, slurp in degraded mode, _tags in subdirs, fix the bug with -j... * ocamlbuild_version.mli: Remove. * ocamlbuild_where.mli: New. * display.mli: New. * shell.ml: New. * shell.mli: New. * glob.ml, * glob.mli, * configuration.ml, * lexers.mli, * lexers.mll, * configuration.mli: Honor _tags files in subdirs. * my_unix_with_unix.ml, * command.ml, * command.mli, * resource.ml, * resource.mli, * solver.ml: Fix the bug with the -j option. * slurp.ml, * slurp.mli: New degraded mode using the find command. Use lazy values to avoid computing useless directories. * options.ml, * options.mli: Update -version and -where. * pathname.ml, * pathname.mli: Remove the init section. * rule.ml, * rule.mli: Add file_rule useful for rules that don't run a command but just write a file. * ocaml_specific.ml: Fix some plugin bugs. Remove -I to ocamldep. Handle msvc .obj,.lib instead of .o,.a. * my_unix_without_unix.ml: Make works link stuffs running the readlink command. * display.ml, * hygiene.ml, * my_std.ml, * my_unix.mli, * my_std.mli, * start.sh, * test/test5/test.sh, * test/good-output, * test/test6/test.sh, * test/test7/test.sh, * test/test4/test.sh, * test/test8/test.sh, * test/test3/test.sh, * test/test2/test.sh, * Makefile, * _tags, * ocamlbuild_pack.mlpack: Update. 2007-01-02 Berke Durak Fixed ticker. * display.ml: . 2006-12-21 Berke Durak Cosmetic. * command.ml: . * display.ml: . 2006-12-21 Berke Durak Computing display length. * display.ml: . 2006-12-21 Nicolas Pouillard Add -classic-display. * command.ml, * command.mli: Provide a way to use the classic display. * options.ml: Add the -classic-display option. * Makefile: Remove ppcache form the default. 2006-12-21 Berke Durak Finish display only once ; display number of jobs cached. * command.ml: . * display.ml: . 2006-12-21 Nicolas Pouillard Oops fix a bug. * command.ml: Add begin .. end. 2006-12-21 Nicolas Pouillard Some display fixes. * command.ml: Select the display mode and remove the assert false. * display.ml: Change the print function to have a more compact one. * start.sh: Update. 2006-12-21 Berke Durak Error support in Display.finish. * display.ml: . 2006-12-21 Berke Durak Support for cache. * display.ml: . 2006-12-21 Nicolas Pouillard Integrate display mode. * ocamlbuild_pack.mlpack: Add display. * command.mli: Add Px to indicate to highligth this pathname. * command.ml: Support Px and call Display. * display.ml: Fix minor bugs. * ocaml_specific.ml: Declare some Px, and quiet ocamlyacc, ocamllex. * options.ml: Add quiet to default tags. * ppcache.ml: Detect more accuratly ocamlrun. * pathname.ml: Improve concat. * _tags: No profile. 2006-12-21 Berke Durak Added pretend. * display.ml: . 2006-12-21 Berke Durak Added ticker. * display.ml: . 2006-12-21 Berke Durak Display module. * display.ml: . * my_unix_with_unix.ml: . * my_unix_without_unix.ml: . * my_unix.mli: . * test/test10/test.sh: New. * test/test10: New. * test/test10/dbdi: New. 2006-12-21 Nicolas Pouillard Use a better init order, and fix a Filename.concat usage. * ocaml_specific.ml: The plugin should act before any initialization. * ocaml_arch.ml: Use Pathname.(/). 2006-12-21 Berke Durak Started user-friendly display module. * display.ml: New. 2006-12-21 Nicolas Pouillard Fix init order. * ocaml_specific.ml: Config must be available for plugin building. 2006-12-21 Nicolas Pouillard Some fixes. * command.ml: Quote if needed. * my_std.mli: Comment String.contains_string. * resource.ml: Remove a useless separator. * test/good-output: Update. 2006-12-21 Nicolas Pouillard Plugin config file and profile mode. * ocaml_specific.ml: Fix a bug due to the lazyness of &&. * ocaml_specific.mli: Move some functions. 2006-12-21 Berke Durak Now compiles patterns for fast matching. Removed regexp support. * glob_ast.ml: . * glob.ml: . * glob_lexer.mli: . * glob_ast.mli: . * glob_lexer.mll: . * test/test9/testglob.ml: . * test/test9/dbgl: New. 2006-12-20 Berke Durak Pattern matching seems to start to work. * glob.ml: . 2006-12-20 Berke Durak Started faster pattern matching code. * ocaml_specific.ml: . * _tags: . 2006-12-20 Berke Durak myocamlbuild is rebuilt only as needed. * hygiene.ml: . * ocaml_specific.ml: . * pathname.ml: . * pathname.mli: . * resource.ml: . 2006-12-20 Nicolas Pouillard Some changes mainly for windows support. * command.ml, * command.mli: Add the Quote constructor to help quoting building in commands. * my_unix_with_unix.ml, * my_unix_without_unix.ml, * glob.ml: Commented reslash mode. * my_std.ml, * my_std.mli: Some new functions. * my_unix.mli: Export sys_command. * ocaml_specific.ml, * ocaml_specific.mli: Update and windows support. * options.ml, * options.mli: Remove the ocamlmklib option. * ppcache.ml: Fix a bug. * pathname.ml: Add more dirseps. Use a custom Filename.concat (for now). * resource.ml, * rule.ml, * Makefile, * _tags: Update. 2006-12-15 Nicolas Pouillard Update start order. * start.sh: Ditto. 2006-12-11 Berke Durak Added -custom, fixed paths for installation. * ocaml_specific.ml: . * Makefile: . 2006-12-11 Berke Durak Typo. * report.ml: . 2006-12-08 Nicolas Pouillard Add a basic ocamlmklib support. * ocaml_specific.ml, * ocaml_specific.mli: Use ocamlmklib to make libraries if enabled. * options.ml, * options.mli: Add -ocamlmklib and -use-ocamlmklib. 2006-12-08 Nicolas Pouillard Export more references of options. * command.ml, * command.mli: Add ?quiet to execute. * ocaml_specific.ml, * ocaml_specific.mli: Update to options. * options.ml, * options.mli: Move ocamlc, ocamlopt... to references on command specs. * solver.ml: Update. * Makefile: Use _ocamldistr to avoid hygiene. * .vcs: Use _ocamldistr. 2006-12-08 Nicolas Pouillard OCaml distrib stuffs. * command.ml, * command.mli: Add a normalization callback. * ocaml_specific.ml, * ocaml_specific.mli: Add a more complete interface. * options.ml, * options.mli: Add nostdlib. * pathname.ml: Add mkdir -p to import in build. * rule.ml, * rule.mli: Call normalization of commands for digest. * report.ml: Add ignore. * start.sh: Add report.ml*. * Makefile: Add distrib exportation (make a link). * .vcs: Unmask ocamldistrib link. 2006-12-07 Berke Durak Added TODO item. * .vcs: . * TODO: . 2006-12-07 Berke Durak Added TODO file. * TODO: New. 2006-12-07 Berke Durak Very rudimentary report analysis. * report.ml: . * _tags: . 2006-12-07 Nicolas Pouillard Update tests to run ocamlbuild correctly. * test/test2/test.sh, * test/test3/test.sh, * test/test4/test.sh, * test/test5/test.sh, * test/test6/test.sh, * test/test7/test.sh, * test/test8/test.sh, * test/test9/test.sh: Ditto. * test/good-output: Update. 2006-12-07 Nicolas Pouillard Make test9 independant. * test/test9/test.sh: Ditto. 2006-12-07 Berke Durak Rewrote globbing engine, adding {,} ; moved reporting functions to Report. * ocamlbuild_pack.mlpack: . * command.ml: . * glob_ast.ml: . * glob.ml: . * glob_ast.mli: . * glob_lexer.mll: . * ocaml_specific.ml: . * report.ml: New. * report.mli: New. * solver.ml: . * solver.mli: . * start.sh: . * test/test9/testglob.ml: . * test/test9/test.sh: . * test/test3/test.sh: . * _tags: . 2006-12-07 Nicolas Pouillard Degraded mode... * ocamlbuildlight.ml: New. * ocamlbuild_pack.mlpack: Include new modules. * bool.ml: Fake dependency. * configuration.ml: Adapt to the glob parser. * command.ml: Export the fork usage. * glob.ml: Use Str through My_unix. * glob_lexer.mli: New. * glob_lexer.mll: Add slashs to valid character patterns. * lexers.mli, * lexers.mll: Use the glob parser. * my_std.ml: Use My_unix. * my_unix_with_unix.ml: New. * my_unix_without_unix.ml: New. * my_unix.mli: New. * my_std.mli: Add search_in_path and change lazy force to ( !* ). * ocaml_specific.ml: Some updates. * options.ml, * options.mli: Add -ocamlrun. * pathname.ml: Adapt to an optional slurp. * ppcache.ml: Use search_in_path of my_std. * resource.ml: Update to ( !* ). * solver.ml: Export Unix errors reporting. * slurp.ml, * slurp.mli: Use My_unix. * start.sh: Update. * test/test9/testglob.ml: Test a constant. * test/test5/_tags, * test/test3/_tags, * test/test4/_tags: Don't use regexp. * test/good-output: Add test9. * test/test9/test.sh: Remove the parent usage. * Makefile: Add the light mode. * .vcs: Update. * _tags: Update. 2006-12-06 Berke Durak Extra tests for globbing. * test/test9/testglob.ml: . 2006-12-06 Berke Durak First draft of pattern matching. * glob_ast.ml: . * glob.ml: . * glob_ast.mli: . * glob_lexer.mll: . 2006-12-06 Berke Durak More hard-wired but common cases for globbing. * glob.ml: . * test/test9/testglob.ml: . 2006-12-06 Berke Durak Hidden interface in globber. * glob.mli: . * test/test9/testglob.ml: . 2006-12-06 Berke Durak Basic globbing works. * glob.ml: . * glob.mli: . * test/test9/testglob.ml: . 2006-12-06 Berke Durak Improved interface. * glob.ml: . * glob_ast.ml: New. * glob_ast.mli: New. * glob.mli: New. * glob_lexer.mll: . * test/test9/testglob.ml: . * _tags: . 2006-12-06 Berke Durak Added test9. * test/test9/testglob.ml: New. * test/test9/parent: New. * test/runtest.sh: . * test/test9: New. * test/test9/test.sh: New. 2006-12-06 Berke Durak Parser seems to work. * glob.ml: . * glob_lexer.mll: . 2006-12-06 Berke Durak Removed eof_char. * glob.ml: . * glob_lexer.mll: . 2006-12-06 Berke Durak Interface seems to be OK. * glob.ml: . * glob_lexer.mll: . 2006-12-06 Berke Durak Adding files for the globbing module. * bool.ml: New. * bool.mli: New. * glob.ml: New. * glob_lexer.mll: New. * _tags: . 2006-12-06 Berke Durak Replaced numeric escapes. * lexers.mll: . 2006-12-05 Nicolas Pouillard Remove most of the Str usage by using ocamllex. * ocamlbuild_pack.mlpack: Remove Re, add Lexers. * configuration.ml: Use Lexers. * command.ml: Don't use Re. * lexers.mli: New. * lexers.mll: New. * my_std.ml, * my_std.mli: Add String.before and String.after. * ocaml_specific.ml, * ocaml_specific.mli: Use Lexers but also provide tags for warnings. * resource.ml, * rule.ml, * options.ml, * ppcache.ml, * pathname.ml: Use Lexers. * re.ml: Remove. * re.mli: Remove. * start.sh: Update. * Makefile: Igonre _build... and gives -ml to ocamllex. * _tags: Warnings for lexers. 2006-12-05 Nicolas Pouillard Use Sys instead of Unix for readdir. * my_std.ml, * my_std.mli: Supress a Unix usage. 2006-12-05 Nicolas Pouillard Add an option to disable the link creation. * ocaml_specific.ml: Honor this option. * options.ml: Declare it. * options.mli: Define it. 2006-12-05 Nicolas Pouillard Don't import compiled files... * pathname.ml: For the OCaml compilation itself I need to exclude some dirs that contains compiled files but I want to use some of them with ocamlbuild. 2006-12-05 Nicolas Pouillard Support flags for ocamlyacc and ocamllex. * ocaml_specific.ml, * options.ml, * options.mli: Add these options. 2006-12-04 Nicolas Pouillard Two fixes (hygiene and libraries)... * hygiene.ml: Exit 0 if sterilize removes some files (since source files are cached in a rather persistent data structure I prefer let the user start on a fresh setup). * ocaml_specific.ml: Use the dirname if there is no directory named by removing the extension. 2006-12-04 Berke Durak Small bug in hygiene. * hygiene.ml: . 2006-12-04 Nicolas Pouillard Add postition specifications to rules. * rule.ml, * rule.mli: Add a way to specifie where to put a new rule (top,bottom,before another,after another). * flags.ml: Reorder. * my_std.ml, * my_std.mli: Add mv, fix an error handling. * ocaml_specific.ml: Better error message for circular dependencies. * ppcache.ml: Handle errors better. 2006-11-29 Nicolas Pouillard Add a working multiple job support. * command.ml, * command.mli: Add different versions of execute_many including a version that use forks. * options.ml, * options.mli: Restore the -j option. * solver.ml: Call Command.execute_many. * test/runtest.sh: Pass $@ to sub tests. * test/good-output: Update. 2006-11-28 Nicolas Pouillard Fix the link order. * start.sh: Fix the link order. 2006-11-28 Nicolas Pouillard One step toward multiple jobs: Add the support for suspended building. * resource.ml, * resource.mli: Add the notion of suspended building. This represent a resource that is fully ready for evaluation, it's just a command and a function to apply after. * rule.ml: Do not really execute rules that can be safely suspended. * solver.ml: Play with suspended rules to collect as many as possible to get closer to a pararllel execution. 2006-11-27 Nicolas Pouillard Fix the makefile. * Makefile: Fix deps. 2006-11-27 Nicolas Pouillard Activates more warnings, and prepare the -j feature. * hygiene.ml: Consolidates fragile patterns. * my_std.ml: Likewise. * ocaml_specific.ml: Mainly update to the new builder prototype. * pathname.ml, * pathname.mli: Kick a useless parameter. * resource.ml: Remove dead code and update. * rule.ml, * rule.mli: The bulider now takes a list of resource lists, it will try to make in parallel the first level of commands. * solver.ml: Update to builder without parallelism. * test/good-output: Update. * Makefile: Warnings are now set to -w A -warn-error A. 2006-11-26 Nicolas Pouillard Fix packages... again. * ocaml_specific.ml: Ditto. 2006-11-26 Nicolas Pouillard Fix packages. * ocaml_specific.ml: Try to handle better packages during link. * Makefile: Add the try_bootstrap rule. 2006-11-26 Nicolas Pouillard Add -tag, -tags to options. * ocaml_specific.ml: Append default tags from options. * options.ml, * options.mli: Add -tag and -tags. * tags.mli: Indent. 2006-11-26 Nicolas Pouillard Fix a bug and update tests. * resource.ml: Use Hashtbl.replace of course instead of Hashtbl.add to avoid a nasty bug. * test/test7/test.sh, * test/test8/test.sh, * test/test2/test.sh, * test/test6/test.sh, * test/test4/test.sh, * test/test5/test.sh, * test/test3/test.sh: Extract program options to be sure that the -nothing-should-be-rebuilt option is before the -- one. * test/good-output: Update. 2006-11-26 Nicolas Pouillard Use a hashtbl for digests. * resource.ml: Ditto. * ocaml_specific.ml: Remove dead code. 2006-11-26 Nicolas Pouillard Use lists instead of sets for rule deps & prods. * ocaml_specific.ml: Move the mli dep first. * resource.ml, * resource.mli: No more provide digest_resources but digest_resource. * rule.ml, * rule.mli: Use list instead of sets for deps and prods, since they are not heavily updated and the order matter. * solver.ml: Adapt. * test/good-output: Yeah! 2006-11-26 Nicolas Pouillard One more fix for libraries. * ocaml_specific.ml: Improve the link_exception handling. * test/good-output: Update. 2006-11-25 Nicolas Pouillard Fix the library linking. * ocaml_specific.ml: The test7 is specially made to check that feature. 2006-11-25 Nicolas Pouillard Remove list_set. * ocamlbuild_pack.mlpack: Remove list_set * list_set.ml: Remove. * list_set.mli: Remove. * start.sh: Remove list_set. * test/good-output: Regen. 2006-11-25 Nicolas Pouillard Fix the C rule when dirname = '.'. * ocaml_specific.ml: Don't move the output when it's useless. 2006-11-25 Nicolas Pouillard Ignore ocamlbuild_version.ml. 2006-11-25 Nicolas Pouillard New transitive closure. * ocamlbuild_version.ml: Remove. * my_std.ml, * my_std.mli: Add a debug mode for digests and run_and_read. * ocaml_specific.ml: New transitive closure. * pathname.ml, * pathname.mli: Export also parent_dir_name and fix same_contents. * resource.ml, * resource.mli: Add dependencies. * rule.ml: Adapt. * test/good-output: Regen. * Makefile: Improve install. * .vcs: Ignore other _build dirs. 2006-11-20 Nicolas Pouillard Rule definition shortcut and C files. * rule.ml, * rule.mli: Allow to pass ~prod and ~dep when there is just one file. * ocaml_specific.ml: Add a rule for C files and use the previous shortcut. 2006-11-18 Nicolas Pouillard No more extend Format. * command.ml, * my_std.ml, * my_std.mli: Put directly ksbprintf and sbprintf in My_std. 2006-11-18 Nicolas Pouillard Clean up and consistent use of Pathname instead of Filename. * command.ml, * my_std.ml, * my_std.mli, * ocaml_specific.ml, * pathname.ml, * ppcache.ml, * pathname.mli, * resource.ml: That's it. 2006-11-18 Nicolas Pouillard Restore List_set. * ocamlbuild_pack.mlpack, * list_set.ml, * list_set.mli, * resource.ml, * start.sh: Ditto. 2006-11-18 Nicolas Pouillard Remove List_set and List_map. * ocamlbuild_pack.mlpack: No more in the pack. * list_set.ml: Remove. * list_map.ml: Remove. * list_map.mli: Remove. * list_set.mli: Remove. * resource.ml: Use a Set. * start.sh: Adapt. 2006-11-18 Nicolas Pouillard Huge speed up, worth updating. * resource.ml, * resource.mli: Use a hash instead of map, remove the percent type. * rule.ml, * rule.mli: Remove the function for rule names. Use an exception to choose matching rules. 2006-11-18 Nicolas Pouillard Speedup rule calling. * rule.ml, * rule.mli: No more call the code rule twice to compute the digest. * ocaml_specific.ml, * ocaml_specific.mli: Adapt to Rule. * test/test8/myocamlbuild.ml: Use the exception. * test/good-output: Update. * boot: Update svn:ignore. 2006-11-16 Nicolas Pouillard Remove phony resources and include dependencies. * ocaml_specific.ml, * options.ml, * options.mli, * pathname.ml, * pathname.mli, * resource.ml, * resource.mli, * rule.ml, * rule.mli, * solver.ml, * test/test8/myocamlbuild.ml: Simplify a lot the code. 2006-11-16 Nicolas Pouillard Some improvements... * ocamlbuild.ml: . * ocamlbuild_version.ml: New. * ocamlbuild_plugin.ml: New. * ocamlbuild_version.mli: New. * ocamlbuildlib.mllib: . * ocamlbuild.sh: Remove. * ocamlbuild_pack.mlpack: New. * boot: . * ocaml_specific.ml: . * ocaml_specific.mli: . * options.ml: . * options.mli: . * rule.ml: . * rule.mli: . * start.sh: . * test/test8/a.ml: New. * test/test7/a2.ml: . * test/test7/a3.ml: New. * test/test8/myocamlbuild.ml: New. * test/test7/myocamlbuild.ml: New. * test/test8: New. * test/test8/test.sh: New. * test/runtest.sh: . * test/test7/test.sh: . * test/good-output: . * Makefile: . * _tags: . 2006-11-15 Nicolas Pouillard Add support for libraries. * ocamlbuildlib.ml: Remove. * ocamlbuildlib.mllib: New. * ocaml_specific.ml: Rules and actions for libraries. * rule.ml: Improve explanations. * start.sh: Don't make ocamlbuildlib. * test/test7/a.mli: New. * test/runtest.sh: Add test7. * test/test7/test.sh: Add reverts for a.ml. * test/good-output: Update. * Makefile: Remove junk lines. 2006-11-14 Nicolas Pouillard Add a tests for libraries. * test/test7/e.ml: New. * test/test7/d.ml: New. * test/test7/a.ml: New. * test/test7/b.ml: New. * test/test7/a2.ml: New. * test/test7/c.ml: New. * test/test7/test.sh: New. * test/test7/ablib.mllib: New. * test/test7: New. 2006-11-14 Nicolas Pouillard Simplify dependency rules. * ocaml_specific.ml: No more use bytelinkdeps... * rule.ml, * rule.mli: Add a dyndeps set. * ocamlbuild.sh, * pathname.ml, * Makefile: Update. 2006-11-14 Nicolas Pouillard Update tests... * test/test2/vivi3.ml: . * test/good-output: . 2006-11-10 Berke Durak Added -sterilize option. * hygiene.ml: ditto * hygiene.mli: ditto * ocaml_specific.ml: ditto * options.ml: ditto * options.mli: ditto 2006-11-10 Nicolas Pouillard View the context dir in first. * pathname.ml: Ditto. 2006-11-10 Berke Durak Added thread and profile tags. * ocaml_specific.ml: ditto. 2006-11-10 Berke Durak Added law for leftover dependency files. * ocaml_specific.ml: ditto. 2006-11-10 Nicolas Pouillard Reverse the ignore_auto default value. * options.ml: Add -no-skip, remove -ignore-auto, add -Is and -Xs. * test/test2/test.sh, * test/test5/test.sh, * test/test6/test.sh, * test/test4/test.sh, * test/test3/test.sh, * Makefile: Revert flags. 2006-11-10 Berke Durak Added install target to Makefile. * Makefile: . 2006-11-10 Nicolas Pouillard Deal with for-pack flags... * ocaml_arch.ml: Define a hook. * ocaml_arch.mli: Declare it. * ocaml_specific.ml: Use it. * test/test6: Ignore main.byte. 2006-11-09 Nicolas Pouillard Fix start.sh and remove dead code. * ocaml_specific.ml: Remove dead code about ignore_auto. * start.sh: Swap two modules. * test/test6/main.byte: Remove. 2006-11-09 Nicolas Pouillard Pack now works great... * ocamlbuild.sh: Use ocamlopt. * command.ml: Reset filesys cache. * my_std.ml, * my_std.mli: Add a filesys cache for case sensitive file_exists and digest over files. * ocaml_specific.ml: Work on link and packs. * ppcache.ml: Exit 2 is for unix. * pathname.ml, * resource.ml, * rule.ml, * rule.mli, * slurp.ml, * solver.ml, * solver.mli, * test/test5: Update. 2006-11-07 Nicolas Pouillard Too lazy to fill this up :). * ocamlbuild.sh, * configuration.ml, * command.ml, * debug.ml, * debug.mli, * my_std.ml, * my_std.mli, * ocaml_specific.ml, * ocaml_specific.mli, * options.ml, * options.mli, * pathname.ml, * ppcache.ml,ew. * ppcache.mli,ew. * pathname.mli, * resource.ml, * resource.mli, * rule.ml, * rule.mli, * slurp.ml, * solver.ml, * solver.mli, * slurp.mli, * start.sh, * tags.ml, * test/test5/test.sh, * test/test4/test.sh, * test/test3/test.sh, * test/good-output, * test/test2/test.sh, * test/test6/test.sh, * Makefile, * _tags: This too. 2006-11-04 Nicolas Pouillard Some pack,dirs stuffs. * ocamlbuild.ml, * ocamlbuildlib.ml,ew. * ocamlbuild.sh,ew. * configuration.ml, * my_std.ml, * my_std.mli, * ocaml_arch.ml,ew. * ocaml_specific.ml, * ocaml_specific.mli, * ocaml_arch.mli,ew. * options.ml, * options.mli, * pathname.ml, * pathname.mli, * resource.ml, * resource.mli, * rule.ml, * solver.ml, * test/good-output, * Makefile, * _tags: That's it. 2006-10-31 Nicolas Pouillard Remove the dirty thing about cmi's. * ocaml_specific.ml, * ocaml_specific.mli: Moves of files are no more needed. * test/good-output: Update. 2006-10-31 Nicolas Pouillard Some renaming and cleanup... * ocamlbuild.ml, * configuration.ml, * configuration.mli, * list_set.ml, * ocaml_specific.ml, * resource.ml, * test/good-output, * test/test6/test.sh: Do that. 2006-10-31 Nicolas Pouillard Use the nothing-should-be-rebuilt for tests and update the output. * test/test2, * test/test2/test.sh, * test/test3/test.sh, * test/test4/test.sh, * test/test5/test.sh, * test/test6/test.sh, * test/good-output: Do that. 2006-10-31 Nicolas Pouillard Add a mode usefull for tests. * options.ml, options.mli, rule.ml: This new mode fails when something needs to be rebuilt. 2006-10-31 Nicolas Pouillard Improve the ocaml rule set. * ocaml_specific.ml: Yipee! 2006-10-31 Nicolas Pouillard Add scripts to run tests. * test/test2/vivi1.ml: New. * test/test2/vivi2.ml: New. * test/test2/vivi3.ml: New. * test/test2/vivi.ml: . * test/test4/test.sh: New. * test/test5/test.sh: New. * test/test2/test.sh: New. * test/test6/test.sh: . * test/good-output: New. * test/test3/test.sh: New. * test/runtest.sh: New. 2006-10-31 Nicolas Pouillard Restore some recursivity for includes. * resource.ml, * resource.mli: Remove the digest field. * rule.ml: . * test/test6/test.sh: . 2006-10-30 Nicolas Pouillard Remove the arbitrary deep dependencies. * ocaml_specific.ml, * ocaml_specific.mli: No more implicit transitives deps. * resource.ml, * resource.mli: Remove as many things as possible. * rule.ml, * rule.mli, * solver.ml: Simplify. * command.ml: Fix newlines and flush. 2006-10-30 Nicolas Pouillard Separated preprocessing, total order over rules... * ocamlbuild.ml, * my_std.ml, * my_std.mli, * ocaml_specific.ml, * ocaml_specific.mli, * options.ml, * options.mli, * pathname.ml, * pathname.mli, * resource.ml, * resource.mli, * rule.ml, * rule.mli, * solver.ml, * test/test2/tutu.ml, * tags.ml, * test/test2/tyty.mli,ew. * test/test6/test.sh, * test/test6, * test/test5/_tags, * test/test5: Update. 2006-10-27 Nicolas Pouillard Add options: -ocamlc,-ocamlopt,-ocamldep,-ocamlyacc,-ocamllex. * options.ml, * options.mli: Declare them. * ocaml_specific.ml: Use them. 2006-10-27 Nicolas Pouillard Fix start.sh. * start.sh: Fix the output. 2006-10-27 Nicolas Pouillard Regen start.sh. * start.sh: Regen. 2006-10-27 Nicolas Pouillard Use the list based implems and fix many bugs. * ocamlbuild.ml: Rename some dependency files. * boot: Ignore boot/ocamlbuild.byte.save.* files. * command.ml: Fix command printing. * my_std.ml, * my_std.mli: Add List.equal, use the cp command in Shell.cp. * ocaml_specific.ml, * ocaml_specific.mli: Many things. * pathname.ml, pathname.mli: Make compare obselete prefer equal. * resource.ml, resource.mli: Add print_cache and use list based sets and maps. * Makefile: Add the bootstrap rule. 2006-10-27 Nicolas Pouillard Add a test for fine-grained dependencies. * test/test6/main.ml: New. * test/test6/d.ml: New. * test/test6/b.ml: New. * test/test6/a.ml: New. * test/test6/main.mli: New. * test/test6/a.mli: New. * test/test6/d.mli: New. * test/test6/b.mli: New. * test/test6/b.mli.v2: New. * test/test6/main.byte: New. * test/test6/d.mli.v1: New. * test/test6/test.sh: New. * test/test6/d.mli.v2: New. * test/test6/b.mli.v1: New. * test/test6: New. 2006-10-26 Nicolas Pouillard Dummy implementations for set and map using lists. The main advantage is to only rely on the equal function that is simpler to maintain correct in an imperative setting. * list_map.ml: New. * list_set.ml: New. * list_map.mli: New. * list_set.mli: New. 2006-10-24 Nicolas Pouillard Fixes and improvment. * ocamlbuild.ml, * my_std.ml, * my_std.mli, * ocaml_specific.ml, * ocaml_specific.mli, * pathname.ml, * resource.ml, * rule.ml, * rule.mli, * solver.ml, * solver.mli: The previous version was somwhat unstable. 2006-10-24 Nicolas Pouillard Many things... * ocamlbuild.ml, * command.ml, * command.mli, * ocaml_specific.ml, * ocaml_specific.mli, * options.ml, * options.mli, * resource.ml, * resource.mli, * rule.ml, * rule.mli, * solver.ml, * solver.mli: Simplify the whole solver by removing the value type. Rule code now returns a resource set, that is injected as dependencies. So rule code always returns unit. But can raise exceptions. Add -ignore, and -ignore-auto options to workaround ocamldep approximations without igonring errors. * Makefile: Add backup and restore targets. 2006-10-23 Nicolas Pouillard Compute digests of dependencies recursively. * ocamlbuild.ml, * ocaml_specific.ml, * options.ml, * options.mli, * resource.ml, * resource.mli, * rule.ml: Ditto. 2006-10-23 Nicolas Pouillard One step toward a parallelisable system. * boot, * command.ml, * ocaml_specific.ml, * ocaml_specific.mli, * options.ml, * options.mli, * rule.ml, * rule.mli, * solver.ml: Update. * value.ml: Remove. * value.mli: Remove. 2006-10-20 Nicolas Pouillard Add vcs config file to setup a good default setup. * .vcs: New. 2006-10-20 Nicolas Pouillard Simplify the bootstrap by introducing a shell script. * boot/ocamlbuild.byte: Remove. Useless in distribution mode but will be created, the first time. So the devel is not disturbed. * start.sh: New. * Makefile: Remove the old one to use start.sh. 2006-10-20 Nicolas Pouillard Take command line in account for the digest computation. * command.ml, * command.mli, * debug.ml, * ocaml_specific.ml, * ocaml_specific.mli, * resource.ml, * resource.mli, * rule.ml, * rule.mli, * solver.ml, * value.ml, * value.mli: Update. 2006-10-19 Nicolas Pouillard New pathname representation. * pathname.ml, pathname.mli: This new representation should avoids "fix" problems. 2006-10-17 Nicolas Pouillard Change the cache implem -> now really fast at link time. * ocamlbuild.ml, * boot/ocamlbuild.byte, * my_std.ml, * ocaml_specific.ml, * pathname.ml, * resource.ml, * resource.mli, * solver.ml: By replacing various sets by a map of records and remember that something has not changed, or cannot be built; there is a real speedup. In particular to detect that the link is not necessary to do. 2006-10-17 Nicolas Pouillard Add a basic support for a digest based cache verification. * resource.ml, resource.mli: Add have_digest and store_digest. * rule.ml: Use these digests but don't include the command for now. * test/test2/vivi.ml, test/test2/tata.mli: Dummy updates. 2006-10-16 Nicolas Pouillard Split in many files. * ocamlbuild.ml: Splitted. * boot/ocamlbuild.byte: Updated. * configuration.ml: New. * configuration.mli: New. * command.ml: New. * command.mli: New. * debug.ml: New. * debug.mli: New. * flags.ml: New. * flags.mli: New. * my_std.ml: New. * my_std.mli: New. * ocaml_specific.ml: New. * ocaml_specific.mli: New. * options.ml: New. * options.mli: New. * pathname.ml: New. * pathname.mli: New. * re.ml: New. * re.mli: New. * resource.ml: New. * resource.mli: New. * rule.ml: New. * rule.mli: New. * solver.ml: New. * solver.mli: New. * test/test5/d.ml: New. * tags.ml: New. * test/test5/b.ml: New. * test/test5/a.ml: New. * tags.mli: New. * test/test5/a.mli: New. * test/test5/c.mlpack: New. * test/test5/_tags: New. * test/test5: New. * value.ml: New. * value.mli: New. * Makefile: . 2006-10-16 Berke Durak Various useful changes. * ocamlbuild.ml: Hygiene to true. * slurp.ml: Remove debugging * Makefile: Clean annot and object files. 2006-10-15 Nicolas Pouillard Bootstrap it ;). * ocamlbuild.ml: Add support for -g, -dtypes, and -rectypes in four lines. * _tags: New. Specify how to build ocamlbuild itself. * boot: New. * boot/ocamlbuild.byte: New. A bytecode version needed to bootstrap * Makefile: By default make it a wrapper over ocamlbuild in boot. 2006-10-15 Nicolas Pouillard Little fix... * ocamlbuild.ml: Don't assoc over pathnames since the default compare is wrong and slow use the string repr. 2006-10-15 Nicolas Pouillard Allow to control flags, and libraries by tags. * ocamlbuild.ml: In the _tags file you can add or remove flags using a colon flag_name:flag_value. * test/test2/vivi.ml, * test/test3/f.ml, * test/test4/b/bb.ml: Dummy updates. * test/test3/_tags: New. * test/test4/_tags: New. 2006-10-15 Nicolas Pouillard Add a tag based flag system. * test/test2/vivi.ml: An example. * test/test2/_tags: New. * ocamlbuild.ml: Now a command can request for flags by giving a set of tags these tags include file specific tags this allow to tweak flags by just providing a _tags file. 2006-10-15 Nicolas Pouillard Add -lib,-libs options remove -P. * ocamlbuild.ml: -P Is useless due to the fact that we now have the same directory structure in the _build directory. Add -lib,-libs that allows one to specify -lib unix without its extension in order to request for native and byte compilations. 2006-10-15 Nicolas Pouillard Multi directories now works ;). * ocamlbuild.ml: Solve the whole problem by improving the Pathname module. Pathnames are now symbolic values that can include variable names. These variable names represent still ambiguous pathnames /a/b/(c|d as x1)/e.ml but variables can be shared, so discovering that /a/b/(c|d as x1)/e.ml is in fact /a/b/c/e.ml will make /a/b/(c|d as x1)/e.cmo automatically take this value /a/b/c/e.cmo cause it shares the x1 variable. 2006-10-13 Nicolas Pouillard I prefer capitalized names. * AUTHORS 2006-10-13 Berke Durak Added an AUTHORS file. * AUTHORS: New. 2006-10-13 Nicolas Pouillard Add the vcs dir. * vcs: New. * vcs/ocamlbuild.rb: New. 2006-10-13 Nicolas Pouillard * ocamlbuild.ml: Restore dependencies. 2006-10-13 Nicolas Pouillard Fix the makefile. * Makefile, discard_printf.ml: Ditto. 2006-10-13 Nicolas Pouillard Improve the directory handling. * ocamlbuild.ml: Ditto, but there is still a problem with native. * Makefile: Update. 2006-10-11 Nicolas Pouillard Fix native dependencies. * ocamlbuild.ml: By default due to inlining the cmx dependencies are needed to build a cmx. * Makefile: Add native support. 2006-10-11 Nicolas Pouillard Use phony for linkdeps. * ocamlbuild.ml: Ditto. 2006-10-11 Nicolas Pouillard Fix exit on multiple targets. * ocamlbuild.ml: Ditto. 2006-10-11 Nicolas Pouillard More flags -lflags,-lflag... * ocamlbuild.ml: Add plrual form options for those that use comma separated lists. 2006-10-11 Nicolas Pouillard Use phony resources for .cmo.linkdeps. * ocamlbuild.ml: Also restore the command running if "--" is specified 2006-10-11 Nicolas Pouillard Remove Include_string_list resources, add Phony resources. * ocamlbuild.ml: Also fix some rules. 2006-10-11 Nicolas Pouillard Shift debug levels. * ocamlbuild.ml: Add -quiet. 2006-10-11 Nicolas Pouillard Use str more intensively. * ocamlbuild.ml: Also clean up useless functions. 2006-10-11 Nicolas Pouillard Fix link dependencies. * ocamlbuild.ml: Force to consider recursivly Include_ tagged resources for their full contents. Alas it takes more time to know if we need to recompute the link. * test/test2/vivi.ml: Update. 2006-10-10 Nicolas Pouillard Support multiple directories, it can compile the OCaml compiler :). * ocamlbuild.ml: Add directory handling but also start the tags config files handling. * Makefile: Use str.cma. 2006-10-08 Nicolas Pouillard Add library support. * ocamlbuild.ml: Deduce basic set of tags form the target extension. 2006-10-08 Nicolas Pouillard More customisable flags, and cycle detection. * ocamlbuild.ml: Add some flags -lflag, -ppflag, -cflag, --. Also add a detection mechanism for dependencies. * discard_printf.ml, Makefile: Update. ocamlbuild-0.14.3/LICENSE000066400000000000000000000634121454061437200147330ustar00rootroot00000000000000OCamlbuild is distributed under the terms of the GNU Library General Public License version 2 (included below). As a special exception to the GNU Library General Public License, you may link, statically or dynamically, a "work that uses OCamlbuild" with a publicly distributed version of OCamlbuild to produce an executable file containing portions of OCamlbuild, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Library General Public License. By "a publicly distributed version of OCamlbuild", we mean either the unmodified Library as distributed by INRIA, or a modified version of OCamlbuild that is distributed under the conditions defined in clause 2 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Library General Public License. ---------------------------------------------------------------------- GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ocamlbuild-0.14.3/META000066400000000000000000000003101454061437200143630ustar00rootroot00000000000000# Specification for the "ocamlbuild" library requires = "unix" version = "0.14.3" description = "ocamlbuild support library" archive(byte) = "ocamlbuildlib.cma" archive(native) = "ocamlbuildlib.cmxa" ocamlbuild-0.14.3/Makefile000066400000000000000000000276261454061437200153750ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the GNU Library General Public License, with # # the special exception on linking described in file ../LICENSE. # # # ######################################################################### # see 'check-if-preinstalled' target CHECK_IF_PREINSTALLED ?= true # this configuration file is generated from configure.make include Makefile.config ifeq ($(OCAML_NATIVE_TOOLS), true) OCAMLC ?= ocamlc.opt OCAMLOPT ?= ocamlopt.opt OCAMLDEP ?= ocamldep.opt OCAMLLEX ?= ocamllex.opt else OCAMLC ?= ocamlc OCAMLOPT ?= ocamlopt OCAMLDEP ?= ocamldep OCAMLLEX ?= ocamllex endif CP ?= cp COMPFLAGS ?= -w +L -w +R -w +Z -I src -I plugin-lib -I bin -I +unix -safe-string -bin-annot -strict-sequence LINKFLAGS ?= -I +unix -I src PACK_CMO= $(addprefix src/,\ const.cmo \ loc.cmo \ discard_printf.cmo \ signatures.cmi \ my_std.cmo \ my_unix.cmo \ tags.cmo \ display.cmo \ log.cmo \ shell.cmo \ bool.cmo \ glob_ast.cmo \ glob_lexer.cmo \ glob.cmo \ lexers.cmo \ param_tags.cmo \ command.cmo \ ocamlbuild_config.cmo \ ocamlbuild_where.cmo \ slurp.cmo \ options.cmo \ pathname.cmo \ configuration.cmo \ flags.cmo \ hygiene.cmo \ digest_cache.cmo \ resource.cmo \ rule.cmo \ solver.cmo \ report.cmo \ tools.cmo \ fda.cmo \ findlib.cmo \ ocaml_arch.cmo \ ocaml_utils.cmo \ ocaml_dependencies.cmo \ ocaml_compiler.cmo \ ocaml_tools.cmo \ ocaml_specific.cmo \ exit_codes.cmo \ plugin.cmo \ hooks.cmo \ main.cmo \ ) EXTRA_CMO=$(addprefix plugin-lib/,\ ocamlbuild_plugin.cmo \ ocamlbuild_executor.cmo \ ocamlbuild_unix_plugin.cmo \ ) PACK_CMX=$(PACK_CMO:.cmo=.cmx) EXTRA_CMX=$(EXTRA_CMO:.cmo=.cmx) EXTRA_CMI=$(EXTRA_CMO:.cmo=.cmi) INSTALL_LIB=\ plugin-lib/ocamlbuildlib.cma \ bin/ocamlbuild.cmo \ src/ocamlbuild_pack.cmi \ $(EXTRA_CMO:.cmo=.cmi) INSTALL_LIB_OPT=\ plugin-lib/ocamlbuildlib.cmxa plugin-lib/ocamlbuildlib$(EXT_LIB) \ bin/ocamlbuild.cmx bin/ocamlbuild$(EXT_OBJ) \ src/ocamlbuild_pack.cmx \ $(EXTRA_CMO:.cmo=.cmx) $(EXTRA_CMO:.cmo=$(EXT_OBJ)) INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) INSTALL_BINDIR=$(DESTDIR)$(BINDIR) INSTALL_MANDIR=$(DESTDIR)$(MANDIR) INSTALL_SIGNATURES=\ src/signatures.mli \ src/signatures.cmi \ src/signatures.cmti ifeq ($(OCAML_NATIVE), true) all: byte native man else all: byte man endif byte: ocamlbuild.byte plugin-lib/ocamlbuildlib.cma # ocamlbuildlight.byte ocamlbuildlightlib.cma native: ocamlbuild.native plugin-lib/ocamlbuildlib.cmxa allopt: all # compatibility alias distclean:: clean # The executables ocamlbuild.byte: src/ocamlbuild_pack.cmo $(EXTRA_CMO) bin/ocamlbuild.cmo $(OCAMLC) $(LINKFLAGS) -o $@ unix.cma $^ ocamlbuildlight.byte: src/ocamlbuild_pack.cmo bin/ocamlbuildlight.cmo $(OCAMLC) $(LINKFLAGS) -o $@ $^ ocamlbuild.native: src/ocamlbuild_pack.cmx $(EXTRA_CMX) bin/ocamlbuild.cmx $(OCAMLOPT) $(LINKFLAGS) -o $@ unix.cmxa $^ # The libraries plugin-lib/ocamlbuildlib.cma: src/ocamlbuild_pack.cmo $(EXTRA_CMO) $(OCAMLC) -a -o $@ $^ bin/ocamlbuildlightlib.cma: src/ocamlbuild_pack.cmo bin/ocamlbuildlight.cmo $(OCAMLC) -a -o $@ $^ plugin-lib/ocamlbuildlib.cmxa: src/ocamlbuild_pack.cmx $(EXTRA_CMX) $(OCAMLOPT) -a -o $@ $^ # The packs # Build artifacts are first placed into tmp/ to avoid a race condition # described in https://caml.inria.fr/mantis/view.php?id=4991. src/ocamlbuild_pack.cmo: $(PACK_CMO) mkdir -p tmp $(OCAMLC) -pack $^ -o tmp/ocamlbuild_pack.cmo mv tmp/ocamlbuild_pack.cmi src/ocamlbuild_pack.cmi mv tmp/ocamlbuild_pack.cmo src/ocamlbuild_pack.cmo src/ocamlbuild_pack.cmi: src/ocamlbuild_pack.cmo src/ocamlbuild_pack.cmx: $(PACK_CMX) mkdir -p tmp $(OCAMLOPT) -pack $^ -o tmp/ocamlbuild_pack.cmx mv tmp/ocamlbuild_pack.cmx src/ocamlbuild_pack.cmx mv tmp/ocamlbuild_pack$(EXT_OBJ) src/ocamlbuild_pack$(EXT_OBJ) # The lexers src/lexers.ml: src/lexers.mll $(OCAMLLEX) src/lexers.mll clean:: rm -f src/lexers.ml beforedepend:: src/lexers.ml src/glob_lexer.ml: src/glob_lexer.mll $(OCAMLLEX) src/glob_lexer.mll clean:: rm -f src/glob_lexer.ml beforedepend:: src/glob_lexer.ml # The config file configure: $(MAKE) -f configure.make all # proxy rule for rebuilding configuration files directly from the main Makefile Makefile.config src/ocamlbuild_config.ml: $(MAKE) -f configure.make $@ clean:: $(MAKE) -f configure.make clean distclean:: $(MAKE) -f configure.make distclean beforedepend:: src/ocamlbuild_config.ml # man page man: man/ocamlbuild.1 man/ocamlbuild.1: man/ocamlbuild.header.1 man/ocamlbuild.options.1 man/ocamlbuild.footer.1 cat $^ > man/ocamlbuild.1 man/ocamlbuild.options.1: man/options_man.byte ./man/options_man.byte > man/ocamlbuild.options.1 clean:: rm -f man/ocamlbuild.options.1 distclean:: rm -f man/ocamlbuild.1 man/options_man.byte: src/ocamlbuild_pack.cmo $(OCAMLC) $^ -I src man/options_man.ml -o man/options_man.byte clean:: rm -f man/options_man.cm* rm -f man/options_man.byte ifdef EXT_OBJ rm -f man/options_man$(EXT_OBJ) endif # Testing test-%: testsuite/%.ml all cd testsuite && ocaml $(CURDIR)/$< test: test-internal test-findlibonly test-external clean:: rm -rf testsuite/_test_* # Installation # The binaries go in BINDIR. We copy ocamlbuild.byte and # ocamlbuild.native (if available), and also copy the best available # binary as BINDIR/ocamlbuild. # The library is put in LIBDIR/ocamlbuild. We copy # - the META file (for ocamlfind) # - src/signatures.{mli,cmi,cmti} (user documentation) # - the files in INSTALL_LIB and INSTALL_LIB_OPT (if available) # We support three installation methods: # - standard {install,uninstall} targets # - findlib-{install,uninstall} that uses findlib for the library install # - producing an OPAM .install file and not actually installing anything install-bin-byte: mkdir -p "$(INSTALL_BINDIR)" $(CP) ocamlbuild.byte "$(INSTALL_BINDIR)/ocamlbuild.byte$(EXE)" ifneq ($(OCAML_NATIVE), true) $(CP) ocamlbuild.byte "$(INSTALL_BINDIR)/ocamlbuild$(EXE)" endif install-bin-native: mkdir -p "$(INSTALL_BINDIR)" $(CP) ocamlbuild.native "$(INSTALL_BINDIR)/ocamlbuild$(EXE)" $(CP) ocamlbuild.native "$(INSTALL_BINDIR)/ocamlbuild.native$(EXE)" ifeq ($(OCAML_NATIVE), true) install-bin: install-bin-byte install-bin-native else install-bin: install-bin-byte endif install-bin-opam: echo 'bin: [' >> ocamlbuild.install echo ' "ocamlbuild.byte" {"ocamlbuild.byte"}' >> ocamlbuild.install ifeq ($(OCAML_NATIVE), true) echo ' "ocamlbuild.native" {"ocamlbuild.native"}' >> ocamlbuild.install echo ' "ocamlbuild.native" {"ocamlbuild"}' >> ocamlbuild.install else echo ' "ocamlbuild.byte" {"ocamlbuild"}' >> ocamlbuild.install endif echo ']' >> ocamlbuild.install echo >> ocamlbuild.install install-lib-basics: mkdir -p "$(INSTALL_LIBDIR)/ocamlbuild" $(CP) META $(INSTALL_SIGNATURES) "$(INSTALL_LIBDIR)/ocamlbuild" install-lib-basics-opam: echo ' "ocamlbuild.opam" {"opam"}' >> ocamlbuild.install echo ' "META"' >> ocamlbuild.install for lib in $(INSTALL_SIGNATURES); do \ echo " \"$$lib\" {\"$$(basename $$lib)\"}" >> ocamlbuild.install; \ done install-lib-byte: mkdir -p "$(INSTALL_LIBDIR)/ocamlbuild" $(CP) $(INSTALL_LIB) "$(INSTALL_LIBDIR)/ocamlbuild" install-lib-byte-opam: for lib in $(INSTALL_LIB); do \ echo " \"$$lib\" {\"$$(basename $$lib)\"}" >> ocamlbuild.install; \ done install-lib-native: mkdir -p "$(INSTALL_LIBDIR)/ocamlbuild" $(CP) $(INSTALL_LIB_OPT) "$(INSTALL_LIBDIR)/ocamlbuild" install-lib-native-opam: for lib in $(INSTALL_LIB_OPT); do \ echo " \"$$lib\" {\"$$(basename $$lib)\"}" >> ocamlbuild.install; \ done ifeq ($(OCAML_NATIVE), true) install-lib: install-lib-basics install-lib-byte install-lib-native else install-lib: install-lib-basics install-lib-byte endif install-lib-findlib: ifeq ($(OCAML_NATIVE), true) ocamlfind install ocamlbuild \ META $(INSTALL_SIGNATURES) $(INSTALL_LIB) $(INSTALL_LIB_OPT) else ocamlfind install ocamlbuild \ META $(INSTALL_SIGNATURES) $(INSTALL_LIB) endif install-lib-opam: echo 'lib: [' >> ocamlbuild.install $(MAKE) install-lib-basics-opam $(MAKE) install-lib-byte-opam ifeq ($(OCAML_NATIVE), true) $(MAKE) install-lib-native-opam endif echo ']' >> ocamlbuild.install echo >> ocamlbuild.install install-man: mkdir -p "$(INSTALL_MANDIR)/man1" cp man/ocamlbuild.1 "$(INSTALL_MANDIR)/man1/ocamlbuild.1" install-man-opam: echo 'man: [' >> ocamlbuild.install echo ' "man/ocamlbuild.1" {"man1/ocamlbuild.1"}' >> ocamlbuild.install echo ']' >> ocamlbuild.install echo >> ocamlbuild.install install-doc-opam: echo 'doc: [' >> ocamlbuild.install echo ' "LICENSE"' >> ocamlbuild.install echo ' "Changes"' >> ocamlbuild.install echo ' "Readme.md"' >> ocamlbuild.install echo ']' >> ocamlbuild.install uninstall-bin: rm $(BINDIR)/ocamlbuild rm $(BINDIR)/ocamlbuild.byte ifeq ($(OCAML_NATIVE), true) rm $(BINDIR)/ocamlbuild.native endif uninstall-lib-basics: rm $(LIBDIR)/ocamlbuild/META for lib in $(INSTALL_SIGNATURES); do \ rm $(LIBDIR)/ocamlbuild/`basename $$lib`;\ done uninstall-lib-byte: for lib in $(INSTALL_LIB); do\ rm $(LIBDIR)/ocamlbuild/`basename $$lib`;\ done uninstall-lib-native: for lib in $(INSTALL_LIB_OPT); do\ rm $(LIBDIR)/ocamlbuild/`basename $$lib`;\ done uninstall-lib: $(MAKE) uninstall-lib-basics uninstall-lib-byte ifeq ($(OCAML_NATIVE), true) $(MAKE) uninstall-lib-native endif ls "$(LIBDIR)/ocamlbuild" # for easier debugging if rmdir fails rmdir "$(LIBDIR)/ocamlbuild" uninstall-lib-findlib: ocamlfind remove ocamlbuild uninstall-man: rm "$(INSTALL_MANDIR)/man1/ocamlbuild.1" install: check-if-preinstalled $(MAKE) install-bin install-lib install-man uninstall: uninstall-bin uninstall-lib uninstall-man findlib-install: check-if-preinstalled $(MAKE) install-bin install-lib-findlib findlib-uninstall: uninstall-bin uninstall-lib-findlib opam-install: check-if-preinstalled $(MAKE) ocamlbuild.install ocamlbuild.install: rm -f ocamlbuild.install touch ocamlbuild.install $(MAKE) install-bin-opam $(MAKE) install-lib-opam $(MAKE) install-man-opam $(MAKE) install-doc-opam check-if-preinstalled: ifeq ($(CHECK_IF_PREINSTALLED), true) if test -d $(shell ocamlc -where)/ocamlbuild; then\ >&2 echo "ERROR: Preinstalled ocamlbuild detected at"\ "$(shell ocamlc -where)/ocamlbuild";\ >&2 echo "Installation aborted; if you want to bypass this"\ "safety check, pass CHECK_IF_PREINSTALLED=false to make";\ exit 2;\ fi endif # The generic rules %.cmo: %.ml $(OCAMLC) $(COMPFLAGS) -c $< %.cmi: %.mli $(OCAMLC) $(COMPFLAGS) -c $< src/%.cmx: src/%.ml $(OCAMLOPT) -for-pack Ocamlbuild_pack $(COMPFLAGS) -c $< bin/%.cmx: bin/%.ml $(OCAMLOPT) $(COMPFLAGS) -c $< plugin-lib/%.cmx: plugin-lib/%.ml $(OCAMLOPT) $(COMPFLAGS) -c $< clean:: rm -rf tmp/ rm -f src/*.cm* *.cm* ifdef EXT_OBJ rm -f src/*$(EXT_OBJ) *$(EXT_OBJ) endif ifdef EXT_LIB rm -f src/*$(EXT_LIB) *$(EXT_LIB) endif rm -f test/test2/vivi.ml distclean:: rm -f ocamlbuild.byte ocamlbuild.native rm -f ocamlbuild.install # The dependencies depend: beforedepend $(OCAMLDEP) -I src -I plugin-lib src/*.mli src/*.ml plugin-lib/*.mli plugin-lib/*.ml bin/*.mli bin/*.ml > .depend $(EXTRA_CMI): src/ocamlbuild_pack.cmi $(EXTRA_CMO): src/ocamlbuild_pack.cmo src/ocamlbuild_pack.cmi $(EXTRA_CMX): src/ocamlbuild_pack.cmx src/ocamlbuild_pack.cmi include .depend .PHONY: all allopt beforedepend clean configure .PHONY: install installopt installopt_really depend ocamlbuild-0.14.3/Readme.md000066400000000000000000000032601454061437200154400ustar00rootroot00000000000000# OCamlbuild # OCamlbuild is a generic build tool, that has built-in rules for building OCaml library and programs. In recent years, the OCaml community has converged towards a more recent and faster build tool: [Dune](https://github.com/ocaml/dune). If you are choosing a build system, you should probably use Dune instead. (Between January and June 2019, 77 new OCaml packages using ocamlbuild were publicly released, versus 544 packages using dune.) Your should refer to the [OCambuild manual](https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc) for more informations on how to use ocamlbuild. ## Automatic Installation ## With [opam](https://opam.ocaml.org/): ``` opam install ocamlbuild ``` If you are testing a not yet released version of OCaml, you may need to use the development version of OCamlbuild. With opam: ``` opam pin add ocamlbuild --kind=git "https://github.com/ocaml/ocamlbuild.git#master" ``` ## Compilation from source ## We assume GNU make, which may be named `gmake` on your system. 1. Configure. ``` make configure ``` The installation location is determined by the installation location of the ocaml compiler. You can set the following configuration variables (`make configure VAR=foo`): - `OCAMLBUILD_{PREFIX,BINDIR,LIBDIR}` will use opam or ocaml/ocamlfind's settings by default; see `configure.make` for the precise initialization logic. - `OCAML_NATIVE`: should be `true` if native compilation is available on your machine, `false` otherwise 2. Compile the sources. ``` make ``` 3. Install. ``` make install ``` You can also clean the compilation results with `make clean`, and uninstall a manually-installed OCamlbuild with `make uninstall`. ocamlbuild-0.14.3/VERSION000066400000000000000000000000061454061437200147640ustar00rootroot000000000000000.14.3ocamlbuild-0.14.3/bin/000077500000000000000000000000001454061437200144705ustar00rootroot00000000000000ocamlbuild-0.14.3/bin/ocamlbuild.ml000066400000000000000000000017411454061437200171400ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) Ocamlbuild_unix_plugin.setup (); Ocamlbuild_pack.Main.main () ocamlbuild-0.14.3/bin/ocamlbuild.mli000066400000000000000000000017041454061437200173100ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (** Nothing to export for now *) ocamlbuild-0.14.3/bin/ocamlbuildlight.ml000066400000000000000000000017021454061437200201650ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) Ocamlbuild_pack.Main.main ();; ocamlbuild-0.14.3/bin/ocamlbuildlight.mli000066400000000000000000000016611454061437200203420ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Nothing *) ocamlbuild-0.14.3/bin/ppcache.ml000066400000000000000000000053411454061437200164300ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Command open Pathname.Operators let () = Log.level := -1000 let usage () = Format.eprintf "Usage: %s @." Sys.argv.(0); exit 4 let () = if Array.length Sys.argv < 2 then usage () let args = List.tl (Array.to_list Sys.argv) let buf = Buffer.create 2048 let digest_file file = Buffer.add_string buf (Digest.file file) let digest_string string = Buffer.add_string buf (Digest.string string) let search_in_path x = if Sys.file_exists x then x else try search_in_path x with Not_found -> (Format.eprintf "Command not found %s@." x; exit 3) let cmd = match args with | ocamlrun :: x :: _ when String.contains_string ocamlrun 0 "ocamlrun" <> None -> digest_file (search_in_path ocamlrun); x | x :: _ -> x | _ -> usage () let output = ref "" let () = digest_file (search_in_path cmd) let rec loop = function | [] -> Digest.string (Buffer.contents buf) | ("-impl"|"-intf") :: x :: xs -> digest_string x; digest_file x; loop xs | "-o" :: x :: xs -> output := x; loop xs | x :: xs -> let ext = Pathname.get_extension x in digest_string x; (match ext with | "cmo" | "cma" | "ml" | "mli" -> digest_file x | _ -> ()); loop xs let digest = loop args;; let cache_dir = "/tmp/ppcache";; (* FIXME *) let () = Shell.mkdir_p cache_dir;; let path = cache_dir/(Digest.to_hex digest);; let cat path = with_input_file ~bin:true path (fun ic -> copy_chan ic stdout);; if sys_file_exists path then if !output = "" then cat path else Shell.cp path !output else let cmd = atomize args in if !output = "" then begin let tmp = path^".tmp" in Command.execute (Cmd(S[cmd; Sh ">"; A tmp])); Shell.mv tmp path; cat path end else begin Command.execute (Cmd cmd); Shell.cp !output path end ocamlbuild-0.14.3/bin/ppcache.mli000066400000000000000000000016731454061437200166050ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* nothing to export *) ocamlbuild-0.14.3/bootstrap/000077500000000000000000000000001454061437200157355ustar00rootroot00000000000000ocamlbuild-0.14.3/bootstrap/Makefile000066400000000000000000000012771454061437200174040ustar00rootroot00000000000000OCAMLBUILD ?= ocamlbuild all: stage2 setup: $(MAKE) -C .. clean $(MAKE) -C .. src/ocamlbuild_config.ml ln -sf ../src ln -sf ../bin ln -sf ../plugin-lib mkdir -p dest stage1: setup @echo "BOOTSTRAP (1): building local ocamlbuild from '$(OCAMLBUILD)'" @$(OCAMLBUILD) -build-dir _build_stage1 bootstrap.otarget stage2: stage1 @echo "BOOTSTRAP (2): building local ocamlbuild from local ocamlbuild" @_build_stage1/bin/ocamlbuild.native -build-dir _build_stage2 bootstrap.otarget clean: @$(OCAMLBUILD) -clean @$(OCAMLBUILD) -build-dir _build_stage1 -clean @$(OCAMLBUILD) -build-dir _build_stage2 -clean @rm -f src bin plugin-lib @rm -f dest/ocamlbuild_{stage1,stage2}.native @rmdir dest ocamlbuild-0.14.3/bootstrap/_tags000066400000000000000000000025721454061437200167630ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the GNU Library General Public License, with # # the special exception on linking described in file ../LICENSE. # # # ######################################################################### # OCamlbuild tags file true: debug "src": include "bin": include "plugin-lib": include <**/*.ml> or <**/*.mli>: warn_L, warn_R, warn_Z, annot "src/discard_printf.ml": rectypes "ocamlbuildlib.cma" or "ocamlbuildlightlib.cma": linkall <**/*.byte> or <**/*.native> or <**/*.top>: use_unix "ocamlbuildlight.byte": -use_unix, nopervasives : for-pack(Ocamlbuild_pack) # we have several build stages using different build directories, # so each build must ignore each other's build dir. <_build*>: -traverse ocamlbuild-0.14.3/bootstrap/bootstrap.itarget000066400000000000000000000003001454061437200213240ustar00rootroot00000000000000ocamlbuild_pack.cmo ocamlbuild_pack.cmx ocamlbuildlightlib.cma ocamlbuildlib.cma ocamlbuild.top ocamlbuild.docdir/index.html bin/ocamlbuildlight.byte bin/ocamlbuild.byte bin/ocamlbuild.native ocamlbuild-0.14.3/bootstrap/myocamlbuild.ml000066400000000000000000000005551454061437200207550ustar00rootroot00000000000000(* You cannot use a myocamlbuild.ml here: depending on OCamlbuild_plugin will link with both the local library and the installed version, and you will have weird build errors as soon as their signatures differ. This is an unfortunate side-effect of using ocamlbuild to build its own plugin: it is too clever to *not* link with the local library. *) ocamlbuild-0.14.3/bootstrap/ocamlbuild.mltop000066400000000000000000000001151454061437200211220ustar00rootroot00000000000000Ocamlbuild_pack Ocamlbuild_plugin Ocamlbuild_unix_plugin Ocamlbuild_executor ocamlbuild-0.14.3/bootstrap/ocamlbuild.odocl000066400000000000000000000006011454061437200210670ustar00rootroot00000000000000Log My_unix My_std Signatures Shell Display Command Configuration Discard_printf Flags Hygiene Options Pathname Report Resource Rule Slurp Solver Tags Tools Fda Ocaml_specific Ocaml_arch Ocamlbuild_where Ocamlbuild_config Lexers Glob Bool Glob_ast Glob_lexer Plugin Main Hooks Ocaml_utils Ocaml_tools Ocaml_compiler Ocaml_dependencies Exit_codes Digest_cache Ocamlbuild_plugin Findlib ocamlbuild-0.14.3/bootstrap/ocamlbuild_pack.mlpack000066400000000000000000000006041454061437200222370ustar00rootroot00000000000000Const Loc Log My_unix My_std Signatures Shell Display Command Configuration Discard_printf Flags Hygiene Options Pathname Report Resource Rule Slurp Solver Tags Tools Fda Ocaml_specific Ocaml_arch Ocamlbuild_where Ocamlbuild_config Lexers Glob Bool Glob_ast Glob_lexer Plugin Main Hooks Ocaml_utils Ocaml_tools Ocaml_compiler Ocaml_dependencies Exit_codes Digest_cache Findlib Param_tags ocamlbuild-0.14.3/bootstrap/ocamlbuildlib.mllib000066400000000000000000000001151454061437200215550ustar00rootroot00000000000000Ocamlbuild_pack Ocamlbuild_plugin Ocamlbuild_unix_plugin Ocamlbuild_executor ocamlbuild-0.14.3/bootstrap/ocamlbuildlightlib.mllib000066400000000000000000000000421454061437200226040ustar00rootroot00000000000000Ocamlbuild_pack Ocamlbuild_plugin ocamlbuild-0.14.3/configure.make000066400000000000000000000071711454061437200165460ustar00rootroot00000000000000# This file serve as a ./configure file, written as a GNU Makefile. # It generates a local Makefile.config file that will be included by # the main Makefile. # Note: we initially included `ocamlc -where`/Makefile.config directly # from the main Makefile, but this made it not robust to addition of # new variables to this ocaml/Makefile.config that we do not control. include $(shell ocamlc -where)/Makefile.config OCAML_PREFIX = $(PREFIX) OCAML_BINDIR = $(BINDIR) OCAML_LIBDIR = $(LIBDIR) OCAML_MANDIR = $(MANDIR) # If you want to affect ocamlbuild's configuration by passing variable # assignments to this Makefile, you probably want to define those # OCAMLBUILD_* variables. OCAMLBUILD_PREFIX ?= $(PREFIX) OCAMLBUILD_BINDIR ?= \ $(or $(shell opam config var bin 2>/dev/null),\ $(PREFIX)/bin) OCAMLBUILD_LIBDIR ?= \ $(or $(shell opam config var lib 2>/dev/null),\ $(shell ocamlfind printconf destdir 2>/dev/null),\ $(OCAML_LIBDIR)) OCAMLBUILD_MANDIR ?= \ $(or $(shell opam config var man 2>/dev/null),\ $(OCAML_MANDIR)) # It is important to distinguish OCAML_LIBDIR, which points to the # directory of the ocaml compiler distribution, and OCAMLBUILD_LIBDIR, # which should be the general library directory of OCaml projects on # the user machine. # # When ocamlbuild was distributed as part of the OCaml compiler # distribution, there was only one LIBDIR variable, which now # corresponds to OCAML_LIBDIR. # # In particular, plugin compilation would link # LIBDIR/ocamlbuild/ocamlbuild.cma. For an ocamlbuild distributed as # part of the compiler distribution, this LIBDIR occurence must be # interpreted as OCAML_LIBDIR; but with a separate ocamlbuild, it must # be interpreted as OCAMLBUILD_LIBDIR, as this is where ocamlbuild # libraries will be installed. # # In the generated configuration files, we export # OCAMLBUILD_{PREFIX,{BIN,LIB,MAN}DIR}, which are the ones that should # generally be used, as the shorter names PREFIX,{BIN,LIB,MAN}DIR. ifeq ($(ARCH), none) OCAML_NATIVE ?= false else OCAML_NATIVE ?= true endif OCAML_NATIVE_TOOLS ?= $(OCAML_NATIVE) all: Makefile.config src/ocamlbuild_config.ml clean: distclean: rm -f Makefile.config src/ocamlbuild_config.ml Makefile.config: (echo "# This file was generated from configure.make"; \ echo ;\ echo "OCAML_PREFIX=$(OCAML_PREFIX)"; \ echo "OCAML_BINDIR=$(OCAML_BINDIR)"; \ echo "OCAML_LIBDIR=$(OCAML_LIBDIR)"; \ echo "OCAML_MANDIR=$(OCAML_MANDIR)"; \ echo ;\ echo "EXT_OBJ=$(EXT_OBJ)"; \ echo "EXT_ASM=$(EXT_ASM)"; \ echo "EXT_LIB=$(EXT_LIB)"; \ echo "EXT_DLL=$(EXT_DLL)"; \ echo "EXE=$(EXE)"; \ echo ;\ echo "OCAML_NATIVE=$(OCAML_NATIVE)"; \ echo "OCAML_NATIVE_TOOLS=$(OCAML_NATIVE_TOOLS)"; \ echo "NATDYNLINK=$(NATDYNLINK)"; \ echo "SUPPORT_SHARED_LIBRARIES=$(SUPPORTS_SHARED_LIBRARIES)"; \ echo ;\ echo "PREFIX=$(OCAMLBUILD_PREFIX)"; \ echo "BINDIR=$(OCAMLBUILD_BINDIR)"; \ echo "LIBDIR=$(OCAMLBUILD_LIBDIR)"; \ echo "MANDIR=$(OCAMLBUILD_MANDIR)"; \ ) > $@ src/ocamlbuild_config.ml: (echo "(* This file was generated from ../configure.make *)"; \ echo ;\ echo 'let bindir = "$(OCAMLBUILD_BINDIR)"'; \ echo 'let libdir = "$(OCAMLBUILD_LIBDIR)"'; \ echo 'let ocaml_libdir = "$(abspath $(OCAML_LIBDIR))"'; \ echo 'let libdir_abs = "$(abspath $(OCAMLBUILD_LIBDIR))"'; \ echo 'let ocaml_native = $(OCAML_NATIVE)'; \ echo 'let ocaml_native_tools = $(OCAML_NATIVE_TOOLS)'; \ echo 'let supports_shared_libraries = $(SUPPORTS_SHARED_LIBRARIES)';\ echo 'let a = "$(A)"'; \ echo 'let o = "$(O)"'; \ echo 'let so = "$(SO)"'; \ echo 'let ext_dll = "$(EXT_DLL)"'; \ echo 'let exe = "$(EXE)"'; \ echo 'let version = "$(shell ocaml scripts/cat.ml VERSION)"'; \ ) > $@ ocamlbuild-0.14.3/examples/000077500000000000000000000000001454061437200155365ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/.gitignore000066400000000000000000000000301454061437200175170ustar00rootroot00000000000000*.byte _build/ *.native ocamlbuild-0.14.3/examples/01-simple/000077500000000000000000000000001454061437200172455ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/01-simple/Makefile000066400000000000000000000007151454061437200207100ustar00rootroot00000000000000# # Pure OCaml, no packages, no _tags # # bin-annot is required for Merlin and other IDE-like tools .PHONY: all clean byte native profile debug test OCB_FLAGS = -tag bin_annot OCB = ocamlbuild $(OCB_FLAGS) all: native byte # profile debug clean: $(OCB) -clean native: $(OCB) main.native byte: $(OCB) main.byte profile: $(OCB) -tag profile main.native debug: $(OCB) -tag debug main.byte test: native ./main.native "OCaml" "OCamlBuild" "users" ocamlbuild-0.14.3/examples/01-simple/main.ml000066400000000000000000000003511454061437200205220ustar00rootroot00000000000000 let main () = let argv = Array.to_list Sys.argv in let args = List.tl argv in match args with | [] -> Printf.printf "Hello, world!\n" | names -> Printf.printf "Hello, %s!\n" (Util.join names) let () = main () ocamlbuild-0.14.3/examples/01-simple/util.ml000066400000000000000000000002021454061437200205460ustar00rootroot00000000000000 let rec join = function | [] -> "" | [x] -> x | [x;y] -> x ^ " and " ^ y | x::xs -> x ^ ", " ^ join xs ocamlbuild-0.14.3/examples/01-simple/util.mli000066400000000000000000000001541454061437200207250ustar00rootroot00000000000000 (** join strings together using command and "and" for the last element *) val join: string list -> string ocamlbuild-0.14.3/examples/02-subdirs/000077500000000000000000000000001454061437200174305ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/02-subdirs/Makefile000066400000000000000000000010611454061437200210660ustar00rootroot00000000000000# # Pure OCaml, no packages, no _tags, code in several directories # # bin-annot is required for Merlin and other IDE-like tools # The -I flag introduces sub-directories to search for code .PHONY: all clean byte native profile debug test OCB_FLAGS = -tag bin_annot -I src -I lib OCB = ocamlbuild $(OCB_FLAGS) all: native byte # profile debug clean: $(OCB) -clean native: $(OCB) main.native byte: $(OCB) main.byte profile: $(OCB) -tag profile main.native debug: $(OCB) -tag debug main.byte test: native ./main.native "OCaml" "OCamlBuild" "users" ocamlbuild-0.14.3/examples/02-subdirs/lib/000077500000000000000000000000001454061437200201765ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/02-subdirs/lib/util.ml000066400000000000000000000002021454061437200214770ustar00rootroot00000000000000 let rec join = function | [] -> "" | [x] -> x | [x;y] -> x ^ " and " ^ y | x::xs -> x ^ ", " ^ join xs ocamlbuild-0.14.3/examples/02-subdirs/lib/util.mli000066400000000000000000000001541454061437200216560ustar00rootroot00000000000000 (** join strings together using command and "and" for the last element *) val join: string list -> string ocamlbuild-0.14.3/examples/02-subdirs/src/000077500000000000000000000000001454061437200202175ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/02-subdirs/src/main.ml000066400000000000000000000003511454061437200214740ustar00rootroot00000000000000 let main () = let argv = Array.to_list Sys.argv in let args = List.tl argv in match args with | [] -> Printf.printf "Hello, world!\n" | names -> Printf.printf "Hello, %s!\n" (Util.join names) let () = main () ocamlbuild-0.14.3/examples/03-packages/000077500000000000000000000000001454061437200175345ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/03-packages/Makefile000066400000000000000000000013021454061437200211700ustar00rootroot00000000000000# # Pure OCaml, package from Opam, two directories # # - The -I flag introduces sub-directories # - -use-ocamlfind is required to find packages (from Opam) # - _tags file introduces packages, bin_annot flag for tool chain .PHONY: all clean byte native profile debug sanity test OCB_FLAGS = -use-ocamlfind -I src -I lib OCB = ocamlbuild $(OCB_FLAGS) all: native byte # profile debug clean: $(OCB) -clean native: sanity $(OCB) main.native byte: sanity $(OCB) main.byte profile: sanity $(OCB) -tag profile main.native debug: sanity $(OCB) -tag debug main.byte # check that packages can be found sanity: ocamlfind query yojson test: native echo '[1, 2, "three", {"four": 4}]' | ./main.native ocamlbuild-0.14.3/examples/03-packages/_tags000066400000000000000000000000541454061437200205530ustar00rootroot00000000000000true: package(yojson) true: bin_annot ocamlbuild-0.14.3/examples/03-packages/lib/000077500000000000000000000000001454061437200203025ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/03-packages/lib/util.ml000066400000000000000000000002021454061437200216030ustar00rootroot00000000000000 let rec join = function | [] -> "" | [x] -> x | [x;y] -> x ^ " and " ^ y | x::xs -> x ^ ", " ^ join xs ocamlbuild-0.14.3/examples/03-packages/lib/util.mli000066400000000000000000000001541454061437200217620ustar00rootroot00000000000000 (** join strings together using command and "and" for the last element *) val join: string list -> string ocamlbuild-0.14.3/examples/03-packages/src/000077500000000000000000000000001454061437200203235ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/03-packages/src/main.ml000066400000000000000000000005231454061437200216010ustar00rootroot00000000000000 module J = Yojson.Basic let json io = J.from_channel io |> J.to_channel stdout let main () = let argv = Array.to_list Sys.argv in let args = List.tl argv in let this = List.hd argv in match args with | [] -> json stdin; print_newline () | _ -> Printf.eprintf "usage: %s" this; exit 1 let () = main () ocamlbuild-0.14.3/examples/04-library/000077500000000000000000000000001454061437200174235ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/04-library/Makefile000066400000000000000000000013231454061437200210620ustar00rootroot00000000000000# # Pure OCaml, package from Opam, two directories # # - The -I flag introduces sub-directories # - -use-ocamlfind is required to find packages (from Opam) # - _tags file introduces packages, bin_annot .PHONY: all clean byte native profile debug lib sanity test OCB_FLAGS = -use-ocamlfind -I src -I libdemo OCB = ocamlbuild $(OCB_FLAGS) all: native byte lib # profile debug clean: $(OCB) -clean lib: $(OCB) libdemo.cma $(OCB) libdemo.cmxa $(OCB) libdemo.cmxs native: sanity $(OCB) main.native byte: sanity $(OCB) main.byte profile: sanity $(OCB) -tag profile main.native debug: sanity $(OCB) -tag debug main.byte sanity: ocamlfind query yojson test: native echo '{"hello": "json"}' | ./main.native ocamlbuild-0.14.3/examples/04-library/_tags000066400000000000000000000000541454061437200204420ustar00rootroot00000000000000true: package(yojson) true: bin_annot ocamlbuild-0.14.3/examples/04-library/libdemo/000077500000000000000000000000001454061437200210365ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/04-library/libdemo/hello.ml000066400000000000000000000000271454061437200224720ustar00rootroot00000000000000 let hello = "hello" ocamlbuild-0.14.3/examples/04-library/libdemo/hello.mli000066400000000000000000000000231454061437200226370ustar00rootroot00000000000000 val hello: string ocamlbuild-0.14.3/examples/04-library/libdemo/libdemo.mllib000066400000000000000000000000161454061437200234670ustar00rootroot00000000000000 Hello Util ocamlbuild-0.14.3/examples/04-library/libdemo/util.ml000066400000000000000000000002121454061437200223400ustar00rootroot00000000000000 let rec join = function | [] -> "" | [x] -> x | [x;y] -> x ^ " and " ^ y | x::xs -> x ^ ", " ^ join xs ocamlbuild-0.14.3/examples/04-library/libdemo/util.mli000066400000000000000000000001541454061437200225160ustar00rootroot00000000000000 (** join strings together using command and "and" for the last element *) val join: string list -> string ocamlbuild-0.14.3/examples/04-library/src/000077500000000000000000000000001454061437200202125ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/04-library/src/main.ml000066400000000000000000000005231454061437200214700ustar00rootroot00000000000000 module J = Yojson.Basic let json io = J.from_channel io |> J.to_channel stdout let main () = let argv = Array.to_list Sys.argv in let args = List.tl argv in let this = List.hd argv in match args with | [] -> json stdin; print_newline () | _ -> Printf.eprintf "usage: %s" this; exit 1 let () = main () ocamlbuild-0.14.3/examples/05-lex-yacc/000077500000000000000000000000001454061437200174655ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/05-lex-yacc/Makefile000066400000000000000000000016161454061437200211310ustar00rootroot00000000000000# # Pure OCaml, package from Opam, two directories # # - The -I flag introduces sub-directories # - -use-ocamlfind is required to find packages (from Opam) # - _tags file introduces packages, bin_annot flag for tool chain # - using *.mll and *.mly are handled automatically # - we are using menhir, the modern replacement for OCamlYacc # OCB_FLAGS = -use-ocamlfind -I src -I lib # uses ocamlyacc .PHONY: all clean byte native profile debug sanity test OCB_FLAGS = -use-ocamlfind -use-menhir -I src -I lib # uses menhir OCB = ocamlbuild $(OCB_FLAGS) all: native byte # profile debug clean: $(OCB) -clean native: sanity $(OCB) main.native byte: sanity $(OCB) main.byte profile: sanity $(OCB) -tag profile main.native debug: sanity $(OCB) -tag debug main.byte # check that menhir is installed, use "opam install menhir" sanity: which menhir test: native ./main.native "2 + 3 * 3" ocamlbuild-0.14.3/examples/05-lex-yacc/_tags000066400000000000000000000000351454061437200205030ustar00rootroot00000000000000true: bin_annot, explain ocamlbuild-0.14.3/examples/05-lex-yacc/lib/000077500000000000000000000000001454061437200202335ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/05-lex-yacc/lib/hello.ml000066400000000000000000000000271454061437200216670ustar00rootroot00000000000000 let hello = "hello" ocamlbuild-0.14.3/examples/05-lex-yacc/lib/hello.mli000066400000000000000000000000231454061437200220340ustar00rootroot00000000000000 val hello: string ocamlbuild-0.14.3/examples/05-lex-yacc/lib/util.ml000066400000000000000000000002021454061437200215340ustar00rootroot00000000000000 let rec join = function | [] -> "" | [x] -> x | [x;y] -> x ^ " and " ^ y | x::xs -> x ^ ", " ^ join xs ocamlbuild-0.14.3/examples/05-lex-yacc/lib/util.mli000066400000000000000000000001541454061437200217130ustar00rootroot00000000000000 (** join strings together using command and "and" for the last element *) val join: string list -> string ocamlbuild-0.14.3/examples/05-lex-yacc/src/000077500000000000000000000000001454061437200202545ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/05-lex-yacc/src/lexer.mli000066400000000000000000000000531454061437200220740ustar00rootroot00000000000000 val token: Lexing.lexbuf -> Parser.token ocamlbuild-0.14.3/examples/05-lex-yacc/src/lexer.mll000066400000000000000000000012011454061437200220730ustar00rootroot00000000000000{ module P = Parser exception Error of string let error fmt = Printf.kprintf (fun msg -> raise (Error msg)) fmt let get = Lexing.lexeme } rule token = parse | [' ' '\t' '\n'] { token lexbuf } (* skip blanks *) | ['0'-'9']+ as lxm { P.INT(int_of_string lxm) } | '+' { P.PLUS } | '-' { P.MINUS } | '*' { P.TIMES } | '/' { P.DIV } | '(' { P.LPAREN } | ')' { P.RPAREN } | eof { P.EOF } | _ { error "don't know how to handle '%s'" (get lexbuf) } ocamlbuild-0.14.3/examples/05-lex-yacc/src/main.ml000066400000000000000000000004161454061437200215330ustar00rootroot00000000000000 let main () = let argv = Array.to_list Sys.argv in let args = List.tl argv in let expr = String.concat " " args in let lexbuf = Lexing.from_string expr in let result = Parser.main Lexer.token lexbuf in Printf.printf "%d\n" result let () = main () ocamlbuild-0.14.3/examples/05-lex-yacc/src/parser.mly000066400000000000000000000013201454061437200222670ustar00rootroot00000000000000 %token INT %token PLUS MINUS TIMES DIV %token LPAREN RPAREN %left PLUS MINUS /* lowest precedence */ %left TIMES DIV /* medium precedence */ %nonassoc UMINUS /* highest precedence */ %start main /* the entry point */ %token EOF %type main %% (* Menhir let us give names to symbol values, instead of having to use $1, $2, $3 as in ocamlyacc *) main : e = expr EOF { e } ; expr : n = INT { n } | LPAREN e = expr RPAREN { e } | e1=expr PLUS e2=expr { e1 + e2 } | e1=expr MINUS e2=expr { e1 - e2 } | e1=expr TIMES e2=expr { e1 * e2 } | e1=expr DIV e2=expr { e1 / e2 } | MINUS e = expr %prec UMINUS { - e } ; ocamlbuild-0.14.3/examples/06-ocamldoc/000077500000000000000000000000001454061437200175425ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/06-ocamldoc/Makefile000066400000000000000000000020161454061437200212010ustar00rootroot00000000000000# # Pure OCaml, no packages, no _tags, code in several directories # Targets starting with "doc_" generate documentation for the Util and Hello # modules # # bin-annot is required for Merlin and other IDE-like tools # The -I flag introduces sub-directories to search for code .PHONY: all clean byte native profile debug test OCB_FLAGS = -tag bin_annot -I src -I lib OCB = ocamlbuild $(OCB_FLAGS) all: native byte # profile debug clean: $(OCB) -clean native: $(OCB) main.native byte: $(OCB) main.byte profile: $(OCB) -tag profile main.native debug: $(OCB) -tag debug main.byte doc_html: $(OCB) doc/api.docdir/index.html doc_man: $(OCB) doc/api.docdir/man # the name of the .tex file can be anything doc_tex: $(OCB) doc/api.docdir/api.tex # the name of the .texi file can be anything doc_texinfo: $(OCB) doc/api.docdir/api.texi # the .dot graph represents inter-module dependencies # as before, the name doesn't matter doc_dot: $(OCB) doc/api.docdir/api.dot test: native ./main.native "OCaml" "OCamlBuild" "users" ocamlbuild-0.14.3/examples/06-ocamldoc/doc/000077500000000000000000000000001454061437200203075ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/06-ocamldoc/doc/api.odocl000066400000000000000000000000131454061437200220740ustar00rootroot00000000000000Hello Util ocamlbuild-0.14.3/examples/06-ocamldoc/lib/000077500000000000000000000000001454061437200203105ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/06-ocamldoc/lib/hello.ml000066400000000000000000000000241454061437200217410ustar00rootroot00000000000000let hello = "Hello" ocamlbuild-0.14.3/examples/06-ocamldoc/lib/hello.mli000066400000000000000000000001301454061437200221100ustar00rootroot00000000000000(** The hello module. *) (** A string mostly used as a greeting. *) val hello : string ocamlbuild-0.14.3/examples/06-ocamldoc/lib/util.ml000066400000000000000000000002021454061437200216110ustar00rootroot00000000000000 let rec join = function | [] -> "" | [x] -> x | [x;y] -> x ^ " and " ^ y | x::xs -> x ^ ", " ^ join xs ocamlbuild-0.14.3/examples/06-ocamldoc/lib/util.mli000066400000000000000000000002371454061437200217720ustar00rootroot00000000000000(** A module containing some utility functions. *) (** join strings together using command and "and" for the last element *) val join: string list -> string ocamlbuild-0.14.3/examples/06-ocamldoc/src/000077500000000000000000000000001454061437200203315ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/06-ocamldoc/src/main.ml000066400000000000000000000003731454061437200216120ustar00rootroot00000000000000 let main () = let argv = Array.to_list Sys.argv in let args = List.tl argv in match args with | [] -> Printf.printf "%s, world!\n" Hello.hello | names -> Printf.printf "%s, %s!\n" Hello.hello (Util.join names) let () = main () ocamlbuild-0.14.3/examples/07-dependent-projects/000077500000000000000000000000001454061437200215575ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/07-dependent-projects/Makefile000066400000000000000000000010771454061437200232240ustar00rootroot00000000000000# # Pure OCaml, project depends on library code from a local project # # For more details, see: # https://ocaml.org/learn/tutorials/ocamlbuild/Working_on_dependent_projects_with_ocamlbuild.html # # - The -I flag introduces sub-directories .PHONY: all clean byte native profile debug test OCB_FLAGS = -I src -I libdemo OCB = ocamlbuild $(OCB_FLAGS) all: native byte clean: $(OCB) -clean native: $(OCB) main.native byte: $(OCB) main.byte profile: $(OCB) -tag profile main.native debug: $(OCB) -tag debug main.byte test: native ./main.native groucho harpo chico ocamlbuild-0.14.3/examples/07-dependent-projects/libdemo000077700000000000000000000000001454061437200265462../04-library/libdemoustar00rootroot00000000000000ocamlbuild-0.14.3/examples/07-dependent-projects/src/000077500000000000000000000000001454061437200223465ustar00rootroot00000000000000ocamlbuild-0.14.3/examples/07-dependent-projects/src/main.ml000066400000000000000000000004001454061437200236160ustar00rootroot00000000000000let main () = let argv = Array.to_list Sys.argv in let args = List.tl argv in let this = List.hd argv in match args with | [] -> Printf.eprintf "usage: %s [WORD]..." this; exit 1 | _ -> Printf.eprintf "%s\n" (Util.join args) let () = main () ocamlbuild-0.14.3/examples/Makefile000066400000000000000000000003011454061437200171700ustar00rootroot00000000000000.PHONY: all test clean all: for d in [0-9]*-*; do $(MAKE) -C $$d all; done test: for d in [0-9]*-*; do $(MAKE) -C $$d test; done clean: for d in [0-9]*-*; do $(MAKE) -C $$d clean; done ocamlbuild-0.14.3/howto/000077500000000000000000000000001454061437200150605ustar00rootroot00000000000000ocamlbuild-0.14.3/howto/release.adoc000066400000000000000000000163771454061437200173460ustar00rootroot00000000000000= How to release a new OCamlbuild version = The steps below describe what needs to be done to release a new OCamlbuild version. The process should be simple and fast, so that we can release often. == Preparing the release == The steps can be done a few days in advance, and coordinated among several people. External contributors can do it, and you can use pull requests to get reviews and feedback. [[synch-opam-files]] === Synchronizing the local and remote opam files === One of the last release steps is to <>, and this will require an 'opam' file describing the installation-related metadata. There are two sources of inspiration for these opam files: - there is a local 'opam' file at the root of the ocamlbuild repository, that is used for pinning the development version. - there are the 'opam' files for previous OCamlbuild releases in the public opam repository: https://github.com/ocaml/opam-repository/tree/master/packages/ocamlbuild/ In theory the two should be in synch: the 'opam' file we send to the public opam repository is derived from the local 'opam' file. However, upstream opam repository curators may have made changes to the public opam files, to reflect new packaging best practices and policies. You should check for any change to the latest version's 'opam' file; if there is any, it should probably be reproduced into our local 'opam' file. Note that the local file may have changed during the release lifetime to reflect new dependencies or changes in packaging policies. These changes should be preserved. You can use +opam lint+ in the package repository to check that the current opam file satisfies best practices. === Changes and annoucement === The 'Changes' file at the root of our repository serves as a user- and contributors-facing memory of the project evolution. The section concerning the current development version is marked NEXT_RELEASE. ==== Changes entries ==== Check the detailed changelog to make sure that no important feature is missing, that compatibility-breaking changes are probably marked, and that existing change entries are descriptive enough. Changes entries should: - Describe the change in a way that end-users can understand - Explicitly say whether it breaks compatibility, and in particular use "* " as an entry bullet point in this case. - Link to the relevant online discussions of the change by giving PR or issue numbers when relevant. - Credit the contributors involved in this change. The name of the people that wrote the patch should be included, as well as other contributors having made significant non-coding contributions (code review, testing, etc.). [[change-summary]] ==== Release change summary ==== Write a full-text summary of the changes in the release, less detailed than the full change entries. This text should be a between one sentence and a couple paragraphs long, and will be included in the Github description of the release and email announcements. The release change summary should go in the section of the release, above the list of change entries. === Picking a version number === Choose the next version number. You should try to respect http://semver.org/[Semantic Versioning] whenever possible: point releases should have bugfixes and tweaks only, and minor releases should not break backward compatibility. === Update sources with new version number === During development we use +NEXT_RELEASE+ as a placeholder for the next release number, so any occurence of +NEXT_RELEASE+ in the development repository should be replaced by this version number. There is at least one such occurence in the 'Changes' file. Furthermore, the version coded is hardcoded in some parts of the codebase and needs to be updated: - the 'VERSION' file contains the current version number, with no ending newline - the 'META' file contains the current version number to inform ocamlfind You can use +git grep+ to look for all occurrences of +NEXT_RELEASE+ and a given version number, from the root of the repository: ---- git grep NEXT_RELEASE git grep -F "0.9" ---- == Doing the release == These steps should be performed by someone with push access to the central git repository. === Marking the release day in Changes === Mark the current release day in the Changes file. === Performing the release through github === Github's interface allows to create a release tag and publish a release. From the https://github.com/ocaml/ocamlbuild[github project page] you can go to the https://github.com/ocaml/ocamlbuild/releases[release tab] which lists the current tags and has a https://github.com/ocaml/ocamlbuild/releases/new[draft a new release] button. Clicking this button (or the latter link in the previous sentence) will let you pick a tag name, release title, and description. The tag name should be just the release version number. See +git tag --list+ to see existing tags from a command-line. The release name should be just +Release +. The description should be the Changes section corresponding to the release (release summary and detailed list of entries). ==== Releasing from the command-line instead ==== If you prefer, you can also perform the same steps using the command-line: ---- git tag -a ---- This command should start an editor to ask for a tag message. You can use the <> as the tag message. ==== Post-release changes ==== Create an empty Changes section for the next release, ``` NEXT_RELEASE: ------------- ``` Also put NEXT_RELEASE in your VERSION and META file. This will prevent you from forgetting to update them at the next release time. == Making the release visible to our users == === push it upstream === ---- git push git push --tags ---- [[opam-repo]] === opam-repository update === You should create a new opam package for the new version. For this, clone the opam-repository https://github.com/ocaml/opam-repository/[upstream repository], go to https://github.com/ocaml/opam-repository/tree/master/packages/ocamlbuild/['packages/ocamlbuild'] and create a new repository 'ocamlbuild.'; you need three files in this repository: - 'descr', a full-text description of the package: just copy the previous version's file. - 'url', which tells opam how to download an archive; you can copy the previous version's file, and you need to update the two fields. It looks like this: + ---- archive: "https://github.com/ocaml/ocamlbuild/archive/0.9.0.tar.gz" checksum: "71c813d51bed39e73937dd4751d593c6" ---- + The +archive+ is the file built by github at +https://github.com/ocaml/ocamlbuild/archive/.tar.gz+. To compute the checksum, fetch this file and compute its md5 sum; your system may have a +md5sum+ command to do this. - 'opam': this should be just a copy of the 'opam' file at the root of the ocamlbuild repository -- which should have been <> with upstream packaging changes -- with the +version+ field changed from +"dev"+ to the current version number. === announcing the release === You can send an email to the caml-list. The tradition is to use the subject [ANN] OCamlbuild The mail could be just the release change summary and the detailed list of change entries. Feel free to add other content according to your personal preference.ocamlbuild-0.14.3/man/000077500000000000000000000000001454061437200144735ustar00rootroot00000000000000ocamlbuild-0.14.3/man/ocamlbuild.footer.1000066400000000000000000000002021454061437200201570ustar00rootroot00000000000000.SH SEE ALSO The .BR ocamlbuild manual, .BR ocaml (1), .BR make (1). .br .I The OCaml user's manual, chapter "Batch compilation". ocamlbuild-0.14.3/man/ocamlbuild.header.1000066400000000000000000000050221454061437200201160ustar00rootroot00000000000000.\"***********************************************************************) .\"* *) .\"* ocamlbuild *) .\"* *) .\"* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) .\"* *) .\"* Copyright 2007 Institut National de Recherche en Informatique et *) .\"* en Automatique. All rights reserved. This file is distributed *) .\"* under the terms of the Q Public License version 1.0. *) .\"* *) .\"***********************************************************************) .\" .TH OCAMLBUILD 1 .SH NAME ocamlbuild \- The OCaml project compilation tool .SH SYNOPSIS .B ocamlbuild [ .B \-Is \ dir1,... ] [ .BI \-libs \ lib1,... ] [ .BI \-lflags \ flag1,... ] [ .BI \-pp \ flags ] [ .BI \-tags \ tag1,... ] [ .B \-j \ parallel-jobs ] .I target.native [ .B \-\- arg1 arg2 ... ] .I (same options) .SH DESCRIPTION .BR ocamlbuild (1) orchestrates the compilation process of your OCaml project. It is similar in function to .BR make (1) except that it is tailor-made to automatically compile most OCaml projects with very little user input. .BR ocamlbuild should be invoked in the root of a clean project tree (e.g., with no leftover compilation files). Given one or more targets to compile, it scans the required subdirectories to gather information about the various files present, running tools such as .BR ocamldep (1) to extract dependency information, and gathering optional files that fine-tune its behaviour. Target names are very significant. .SH TARGET NAMES .BR ocamlbuild uses a set of target naming conventions to select the kind of objects to produce. Target names are of the form .BR base.extension where .BR base is usually the name of the underlying OCaml module and .BR extension denotes the kind of object to produce from that file -- a byte code executable, a native executable, documentation... Of course extensions such as .BR .cmo, .BR .cma, .BR .cmi... map to their usual counterparts. Here is a list of the most important .BR ocamlbuild \&-specific extensions: .TP 2i .B .native Native code executable .TP 2i .B .byte Byte code executable .TP 2i .B .inferred.mli Interface inferred with .BR ocamlc -i .TP 2i .B .docdir/index.html HTML documentation generated with .BR ocamldoc .PP ocamlbuild-0.14.3/man/options_man.ml000066400000000000000000000024761454061437200173640ustar00rootroot00000000000000open Ocamlbuild_pack let options = Options.spec () let print (option, _, descr) = let escape str = My_std.String.subst "-" "\\-" str in let argument, descr = try (* take an aligned description, for example " foo bar", and splits it into an optional argument "" (ends on a space, empty if the first character is a space) and a description "foo bar" (skipping the spaces before it) *) let arg_index = String.index descr ' ' in let rec rest index = if index >= String.length descr then "" else if descr.[index] = ' ' then rest (index + 1) else My_std.String.after descr index in (Some (My_std.String.before descr arg_index), rest arg_index) with Not_found -> None, descr in print_endline ".TP"; print_string "\\fB"; print_string (escape option); print_string "\\fR"; begin match argument with | None | Some "" -> () | Some argument -> print_char ' '; print_string (escape argument) end; print_newline (); print_endline (escape descr); () let () = print_endline ".SH OPTIONS"; print_newline (); print_endline "The following command-line options are recognized by"; print_endline ".BR ocamlbuild (1)."; print_newline (); List.iter print options; print_newline (); print_endline ".PP"; () ocamlbuild-0.14.3/manual/000077500000000000000000000000001454061437200151755ustar00rootroot00000000000000ocamlbuild-0.14.3/manual/LICENSE000066400000000000000000000004441454061437200162040ustar00rootroot00000000000000The OCamlbuild manual is licensed under Creative Commons CC0 License, version 1.0, whose full text is available at the following address: https://creativecommons.org/publicdomain/zero/1.0/legalcode For a summary of the CC0 license, see https://creativecommons.org/publicdomain/zero/1.0/ ocamlbuild-0.14.3/manual/manual.adoc000066400000000000000000002002751454061437200173100ustar00rootroot00000000000000= The OCamlbuild manual :caution-caption: ☡ CAUTION :important-caption: ❗ IMPORTANT :note-caption: 🛈 NOTE :sectanchors: :sectlinks: :sectnums: :sectnumlevels: 6 :source-highlighter: pygments :tip-caption: 💡 TIP :toc-placement: preamble :toc: :toclevels: 3 :warning-caption: ⚠ WARNING OCamlbuild's job is to determine the sequence of calls to the compiler -- with the right set of command-line flags -- needed to build your OCaml-centric software project. // TODO: The current proportions between Overview and Reference documentation are unnatural. == Overview === Is OCamlbuild well-suited for your project? OCamlbuild is extremely convenient to use for simple projects. If you have a small OCaml project (program or library), you could likely directly invoke `ocamlbuild` to automatically discover various source files and dependencies, and build executables, library archives or documentation with one-line commands. In simple cases you don't need to write a configuration file at all. A few examples of quick `ocamlbuild` commands: [source,sh] ---- # builds a bytecode executable out of foo.ml and its local dependencies ocamlbuild 'foo.byte' # builds a native executable ocamlbuild 'foo.native' # builds a library archive from the modules listed (capitalized) in lib.mllib ocamlbuild 'lib.cma' # builds OCamldoc documentation from the modules listed in lib.odocl ocamlbuild 'lib.docdir/index.html' # enable a few ocamlfind packages and compile in debug mode ocamlbuild -use-ocamlfind -pkgs 'lwt,react,yojson,sedlex.ppx' -tag 'debug' 'foo.native' ---- If repeating `-pkgs 'lwt,react,yojson,sedlex.ppx' -tag 'debug'` becomes bothersome, you can create a `_tags` file in the project directory with the content: ---- true: package(lwt), package(react), package(sedlex), package(yojson), debug ---- , and then just use: [source,Sh] ---- ocamlbuild -use-ocamlfind 'foo.native' ---- OCamlbuild was designed as a generic build system (it is in fact not OCaml-specific), but also to be expressive enough to cover the specifics of the OCaml language that make writing good ``Makefile``s difficult, such as the dreaded `units Foo and Bar make inconsistent assumptions about Baz` error. === Examples We maintain a few self-contained examples of projects using various OCamlbuild features under link:../examples/[`examples/`]: .Examples [[Table_Examples]] [cols="1m,5", options="header"] |=== | Directory | Description | link:../examples/01-simple[01-simple] | A minimal example with self-contained OCaml code in the project directory. | link:../examples/02-subdirs[02-subdirs] | OCaml code in `lib/` and `src/` subdirectories. See <> for the details. | link:../examples/03-packages[03-packages] | A simple example of use of an Findlib package (http://mjambon.com/yojson.html[`yojson`]) in an OCamlbuild project. See <> introduction section for more details. | link:../examples/04-library[04-library] | A simple example of using a `.mllib` file to easily build library archives (`.cma` in bytecode, `.cmxa` with native compilation). See <> for more details. | link:../examples/05-lex-yacc[05-lex-yacc] | A simple program using `ocamllex` to generate a lexer, and http://gallium.inria.fr/~fpottier/menhir/[Menhir] to generate a parser (ocamlyacc would work as easily, but we recommend using Menhir instead which is just a better parser generator). See <> in <> for all parser-relevant options. | link:../examples/06-ocamldoc[06-ocamldoc] | A simple example illustrating the use of OCamldoc to generate documentation as html, TeX, man-pages and graphviz files. See <> for more details. | link:../examples/07-dependent-projects[07-dependent-projects] | A simple example demonstrating the use of symbolic links to include library code from another local project. See https://ocaml.org/learn/tutorials/ocamlbuild/Working_on_dependent_projects_with_ocamlbuild.html[here] for more details. |=== NOTE: There are many ways to integrate OCamlbuild in your project. The examples provided so far use a `Makefile` on top of OCamlbuild to provide the familiar `make; make install; make clean` interface to users, but you are free to do otherwise. === Pros, cons, and alternatives The main strengths of OCamlbuild are the following: * It ‘Just Works’ for most OCaml projects, with *minimal configuration* work on your part. * It is designed from the scratch with *dynamic dependencies* in mind. Dynamic dependencies are the dependencies that are only determined during the build of the target, e.g., the local modules on which a source file depends, and are not explicitly listed in a configuration file. This avoids, for example, the dance of pre-generating or post-generating `.depends` files that is occasionally bothersome with `Makefile` projects, without requiring you to describe all local dependency relations manually either. Two weaknesses are the following: * Instead of a homegrown soon-to-become-Turing-complete configuration language, OCamlbuild made the choice of using *OCaml as its configuration language*, and many users dislike this choice. Most features of OCamlbuild can be controlled through the purely declarative `_tags` file whose structure is explained in detail in this documentation, but for more complex projects you will eventually need to create a `myocamlbuild.ml` to configure the tool through its OCaml library interface. We strive for a simple API and we document it, so that should be more pleasant than you expect. * OCamlbuild is not the most efficient build system out there, and in particular its support for *build parallelization* is currently disappointing. + TIP: This could be solved with more engineering effort. OCamlbuild is maintained by volunteers, and your contributions are warmly welcome, see link:../CONTRIBUTING.adoc[`CONTRIBUTING.adoc`]. + For now, OCamlbuild's default build rules will not scale to millions-of-lines codebases. It is however used in countless useful libraries and projects where this has not been a limitation. Some alternatives for building OCaml projects are: * https://github.com/mmottl/ocaml-makefile[OCaml-Makefile], a generic set of Makefile rules for OCaml projects. Valuable if you want to build OCaml projects with `make`, without rewriting your own boilerplate from scratch. * http://omake.metaprl.org/index.html[OMake], a generic build system that has been succesfully used by several relatively large OCaml projects. * https://github.com/janestreet/jenga[jenga], a build tool developed internally at Jane Street. The design is interestingly close to OCamlbuild's, but with large engineering efforts oriented towards building their huge internal codebase. There is no easy-to-use frontend layer provided to build OCaml projects (and little documentation), it's more of a build-your-own-build-system toolkit for now. * https://github.com/ocaml-obuild/obuild[obuild] wants to be a really-simple build system with a declarative configuration language that has 80% the features, to cover most simple projects. NOTE: The https://realworldocaml.org/[_Real World OCaml_] textbook uses a tool named `corebuild`. This is in fact just a simple wrapper on top of `ocamlbuild` provided by the OCaml library named `core`, with some common options for `core` projects baked in. === Core concepts ==== Rules and targets OCamlbuild knows about a set of _rules_ to build programs. Rules are OCaml code that specifies on a high level how to build certain kinds of files, named __targets__, from some dependencies (statically known or dynamically discovered). For example, a built-in "%.ml -> %.cmo" rule describes how to build any `.cmo` compilation unit file from the `.ml` of the same name; if you call `ocamlbuild foo.cmo`, it will either use `foo.ml` in your source directory or, if it doesn't exist, try to build it, for example from `foo.mll` or `foo.mly`. OCamlbuild knows various targets to build all sorts of useful things: byte or native programs (`.byte`, `.native`), library archives (`.cma`, `.cmxa`, `.cmxs`), documentation (`.docdir/index.html`, `.docdir/man`), etc. We will detail these in the <> section. ==== Tags and the `_tags` file _Tags_ are an abstraction layer designed to specify command-line flags in a declarative style. If you're invoking the compiler directly and wish to build a program with debug information enabled, you need to pass the `-g` flag to the compilation and linking step of the build process, but not during an initial syntactic preprocessing step (if any), when building `.cma` library archives, or when calling `ocamldoc`. With OCamlbuild, you can simply add the `debug` tag to your program's targets, and it will sort out when to insert the `-g` flag or not. To attach tags to your OCamlbuild targets, you write them in a `_tags` file. Each line is of the form `foo: bar`, where `bar` is a list of tags, and `foo` is a filter that determines which targets `bar` applies to. For example, the `_tags` file: ---- true: package(toto), package(tata) or : debug "strange.ml": rectypes ---- will make your whole project (`true` matches anything) depend on the Findlib packages `toto` and `tata`, compile modules `foo` and `bar` with debug information, and pass `-rectypes` when compiling `strange.ml` -- but not `strange.mli`. For more detail, see the <>, and the set of <>. ==== `myocamlbuild.ml` The `_tags` file provides a convenient but limited interface to tune your project. For any more general purpose, we chose to use a configuration file directly written in OCaml, instead of reinventing a home-made configuration language -- or using your shell as Make does. Code put in the `myocamlbuild.ml` file at the root of your project will be compiled and executed by `ocamlbuild` upon invocation. For simple use cases, you should not have to write a `myocamlbuild.ml` file, except maybe to specify project-wide configuration options -- similar to command-line options you would pass to OCamlbuild. But it also allows to define new rules and targets (for example to support a shiny new preprocessing program), to define new tags or refine the meaning of existing tags. We will cover these use-cases in the more advanced section <>. === Working with a simple program Simple OCaml projects often have a set of `.ml` and `.mli` files that provide useful modules depending on each other, and possibly a main file `myprog.ml` that contains the main program code. ---- mod1.ml mod1.mli mod2.ml myprog.ml ---- You can build your program using either the bytecode compiler, with [source,sh] ---- ocamlbuild 'myprog.byte' ---- or the native compiler, with [source,sh] ---- ocamlbuild 'myprog.native' ---- Let's look at the organization of your source directory after this compilation command: ---- _build/ mod1.ml mod1.mli mod2.ml myprog.byte -> _build/myprog.byte* myprog.ml ---- OCamlbuild does all its work in a single `_build` directory, to help keep your source code directory tree clean. Targets are therefore built inside `_build`. It will generally add a symbolic link for the requested target in the user directory, but if a target does not appear after being built, chances are it is in `_build`. [[Sec_Hygiene]] === Hygiene OCamlbuild will proactively complain if some compiled files/build artifacts were left in the source directory: [source,sh] ---- # In the source directory of the previous example. ocamlc -c 'mod2.ml' ocamlbuild 'myprog.byte' ---- ---- SANITIZE: a total of 2 files that should probably not be in your source tree has been found. A script shell file "_build/sanitize.sh" is being created. Check this script and run it to remove unwanted files or use other options (such as defining hygiene exceptions or using the -no-hygiene option). IMPORTANT: I cannot work with leftover compiled files. ERROR: Leftover OCaml compilation files: File mod2.cmo in . has suffix .cmo File mod2.cmi in . has suffix .cmi Exiting due to hygiene violations. ---- [source,sh] ---- rm mod2.cm* ---- If this annoys you, it is possible to exclude some files from this hygiene checking by tagging them with the `precious` or `not_hygienic` tags, or to disable the check globally using the `-no-hygiene` command-line option. The reason for this check is that leftover intermediate files can disrupt the way your build system works. OCamlbuild knows which target you need (library archives or program executables), and tries to build their dependencies, which first builds the dependencies of those dependencies, etc., until it eventually reaches your source files (the _inputs_ of the build process). Everything present in the source directory is considered to be an input; if you keep old `.cmo` files in your source repository, OCamlbuild will not try to rebuild them from source files, but take them as references to produce the final targets, which is not what you want if they are stale. [[Sec_Findlib]] === Findlib-based packages Your project will probably depend on external libraries as well. Let's assume they are provided via the http://projects.camlcity.org/projects/findlib.html[Findlib] tool `ocamlfind`. Suppose we depend on packages `tata` and `toto`. To tell OCamlbuild about them, use the tags `package(tata)` and `package(toto)`. You also need to tell OCamlbuild to enable support for `ocamlfind` by passing the `-use-ocamlfind` command-line option. So you will have the following `_tags` file: ---- true: package(tata), package(toto) ---- and invoke compilation with [source,sh] ---- ocamlbuild -use-ocamlfind 'myprog.byte' ---- NOTE: Because of the popularity of Findlib you can expect to always invoke `ocamlbuild` with the `-use-ocamlfind` option. We will probably enable `-use-ocamlfind` by default in future versions of OCamlbuild, but in the meantime feel free to define a shell alias for convenience. If you have a `myocamlbuild.ml` file (see <>) at the root of your OCamlbuild project, you can use it to set this option, instead of using one command line parameter. Something like this: [source,ocaml] ---- open Ocamlbuild_plugin let () = dispatch (function | Before_options -> Options.use_ocamlfind := true | _ -> ()) ---- Since 0.9.4, `ocamlbuild` also accepts a `-toolchain foo` option that is passed to `ocamlfind`. === Syntax extensions If you use syntax extensions distributed through `ocamlfind`, you can use them as any Findlib package, but you must also use the `syntax(...)` tag to indicate which preprocessor you use: `camlp4o`, `camlp4r`, `camlp5o`, etc. ---- true: syntax(camlp4o) true: package(toto), package(blah.syntax) ---- In recent versions of OCamlbuild (since OCaml 4.01), you can also specify this using the `-syntax` command-line option: [source,sh] ---- ocamlbuild -use-ocamlfind -syntax 'camlp4o' 'myprog.byte' ---- NOTE: Passing the option `-tag "syntax(camlp4o)"` will also work in older versions. More generally, `-tag foo` will apply the tag `foo` to all targets, it is equivalent to adding `true: foo` in your tag line. Also note that the quoting, `-tag "syntax(camlp4o)"` instead of `-tag syntax(camlp4o)`, is necessary for your shell to understand tags that have parentheses. If you use `-ppx` preprocessors, you can use the parametrized tag `ppx(...)` (`-tag "ppx(...)"`) to specify the preprocessor to use. Since ocamlbuild NEXT_RELASE, the tags `ppopt(option)` and `ppxopt(package,option)` are also supported -- if you have set `-use-ocamlfind`. // TODO: Improve title. [[Sec_Archives_documentation]] === Archives, documentation Some OCamlbuild features require you to add new kind of files in your source directory. Suppose you would like to distribute an archive file `mylib.cma` that would contain the compilation unit for your modules `mod1.ml` and `mod2.ml`. For this, you should create a file `mylib.mllib` listing the name of desired modules -- capitalized, as in OCaml source code: ---- Mod1 Mod2 ---- OCamlbuild knows about a rule `"%.mllib -> %.cma"`, so you can then use: [source,sh] ---- ocamlbuild 'mylib.cma' ---- or, for a native archive [source,sh] ---- ocamlbuild 'mylib.cmxa' ---- Similarly, if you want to invoke `ocamldoc` to document your program, you should list the modules you want documented in a `.odocl` file. If you name it `mydoc.odocl` for example, you can then invoke: [source,sh] ---- ocamlbuild 'mydoc.docdir/index.html' ---- , which will produce the documentation in the subdirectory `mydoc.docdir`, thanks to a rule `"%.odocl -> %.docdir/index.html"`. [[Sec_Directories]] === Source and build directories, module paths, include paths The "source directories" that `ocamlbuild` will traverse to look for rule dependencies are a subset of the subdirectory tree rooted at the "root directory", the place where you invoke `ocamlbuild`. IMPORTANT: All filesystem paths discussed in this section are *relative to the root directory*. The build directory contains a copy of the source directories hierarchy, with the source file imported and additional targets produced during the previous builds. It is by convention the subdirectory `_build` of the root directory, although this can be set with the `-build-dir` command-line option. The build directory is not part of the source directories considered by OCamlbuild. A subdirectory of the subdirectory tree is included in the source directories if it has the "traverse" tag set. That means that if you want to add "foo/bar" (and its files) as part of the source directories and remove "foo/baz", you can use the following in your `_tags` file: ---- "foo/bar": traverse "foo/baz": -traverse ---- If the option `-r` (for _recursive_) is passed, then all subdirectories (recursively) are considered part of the source directories by default, except the build directory and directories that look like version-control information (`.svn`, `.bzr`, `.hg`, `.git`, `_darcs`) and `_opam`, used for project-local opam switches. This option is enabled by default _if_ the root directory looks like an OCamlbuild project: either a `myocamlbuild.ml` or a `_tags` file is present. NOTE: The reason for this heuristic is that calling `ocamlbuild` from your home directory could take a very long time if it recursively traverses your subdirectories, to check for hygiene for example. If the root directory does not look like an OCamlbuild project, but you still wish to use it as such, you can just add the `-r` option explicitly. In the other direction, you can explicitly disable recursive traverse with `true: -traverse` in your `_tags` file. ==== Module paths and include directories On many occasions OCamlbuild needs you to indicate _compilation units_ (set of source and object files for a given OCaml module) located somewhere in the source directories. The syntax to do this is to use an OCaml module name (in particular, capitalized), prefixed by the relative path from the root directory. For example, `bar/baz/Foo` will work with the files `bar/baz/[fF]oo.{ml[i],cm*}`, depending on the compilation phase. For convenience, it is possible to add a source directory to the set of _include paths_: paths that do not have to be explicitly prefixed to each module path. If `bar/` is in the include path, you can refer to `bar/baz/Foo` as just `baz/Foo`. To add `bar` to the include path, one can pass the `-I bar` option to ocamlbuild, or tag `"bar": include` in the `_tags` file. NOTE: Some have come to see the use of the same syntax `-I foo` in `ocamlbuild` and in OCaml compilers as a mistake, because the underlying concepts are rather different. In particular, it is _not_ the case that passing `-I foo` to `ocamlbuild` will transfer this command-line option to underlying compiler invocation. If `foo` is inside the source directories, this should not be needed, and if it is outside you are encouraged to rely on `ocamlfind` packages instead of absolute paths. [[Sec_Reference]] == Reference documentation In this chapter, we cover the built-in targets and tags provided by OCamlbuild. We will omit features that are deprecated, because we found they lead to bad practices or were superseded by better options. Of course, given that a `myocamlbuild.ml` can add new rules and tags, this documentation will always be incomplete. === File extensions of the OCaml compiler and common tools A large part of the file extensions in OCamlbuild rules have not been designed by OCamlbuild itself, but are standard extensions manipulated by the OCaml compiler. As you may not be familiar with them, we will recapitulate them now. For most use-cases OCamlbuild will hide most of those subtleties from you, but having this reference is still useful to understand advanced usage scenarios or read build logs. The OCaml compilers also accept native files (name extensions `{.o,.obj}`, `{.a,.lib}`) and even source files (`.c`) as input arguments, which get passed to the C toolchain (compiler or linker) when producing mixed C/OCaml programs or libraries. // TODO: Explain how they are passed to which C toolchain. Does it default to anything, does it use environment variables such as $CC? .File name extensions [[Table_File_name_extensions]] [cols="1,3", options="header"] |=== | File name, with extension | Description | `foo.mll` | Lexer description, to be processed by a lexer generator to produce a `foo.ml` file, and possibly `foo.mli`. | `foo.ml` | Grammar description, to be processed by a parser generator to produce a `foo.ml` file, and possibly `foo.mli`. | `foo.cmo` | OCaml bytecode-compiled object file, providing the implementation of the module `Foo`. | `foo.cmi` | OCaml bytecode-compiled object file, providing the interface of the module `Foo`. | `blah.cma` | OCaml bytecode-compiled archive file, containing a collection of `.cmo` or `.cma` files, to be used as a library (for either static or dynamic linking). | `foo.cmx` | OCaml native-compiled object file, providing the implementation of the module `Foo` | `foo.o` + _under Windows:_ `foo.obj` | Complementary native object file for the module `Foo`. | `foo.cmxa` | OCaml native-compiled archive file, containing a collection of `.cmx` files, for static linking only. | `foo.a` + `foo.lib` | Complementary native library files for a native-compiled archive file `foo.cmxa`, containing a collection of `.o` or `.obj` files. | `foo.cmxs` | OCaml native-compiled archive file (or "plugin") for dynamic linking, containing a collection of `.cmx`, `.cmxa`, `.o\|.obj`, `.a\|.lib` files. |=== In addition, the following extensions are not enforced by the compiler itself, but are commonly used by OCaml tools: .Additional, commonly found file name extensions [[Table_File_name_extensions_common]] [cols="1,3", options="header"] |=== | File name, with extension | Description | `foo.mll` | Lexer description, to be processed by a lexer generator to produce a `foo.ml` file, and possibly `foo.mli`. | `foo.mly` | Grammar description, to be processed by a parser generator to produce a `foo.ml` file, and possibly `foo.mli`. | `foo.mlp` + `foo.ml4` + `foo.mlip` + `foo.mli4` | Common extensions for files to be processed by an external preprocessor (`p` for "preprocessing" and `4` for Camlp4, an influential OCaml preprocessor). |=== === Targets and rules The built-in OCamlbuild targets for OCaml compilation all rely on file extensions to know which rule to use. Note that this is not imposed by OCamlbuild rule system, which would allow more flexible patterns. But it is always the filename of the target that determines which rules to apply to build it. In consequence, OCamlbuild adds specific file extensions to the one listed above (or variations of them), that are the user-interface to use its rules providing certain features. For example, `.inferred.mli` is not a standard extension in the OCaml compiler, but it is understood by a built-in rule of OCamlbuild to ask for the `.mli` that the compiler can auto-generate by typing a `.ml` file without an explicit interface: running `ocamlbuild foo.inferred.mli` will first build `foo.ml` (or find it in the source directory), then generate `foo.inferred.mli` from it. You are expected to then inspect `foo.inferred.mli`, ideally add documentation, and then move it to `foo.mli` by themselves. The target extensions understood by the built-in OCamlbuild rules are listed in the following subsections. Again, note that `myocamlbuild` plugins may add new targets and rules. To see them programmatically, see <>. ==== Basic targets .Basic targets [[Table_Basic_targets]] [cols="1,4", options="header"] |=== | File name extension | Description | `.cmi` + `.cmo` + `.cmx` | Builds those intermediate files from the corresponding source files (`.ml`, and the `.mli` if it exists). | `.byte` + `.native` | Executables generated from a module and its dependencies for bytecode and native compilation. | `.mllib` | Contains a list of module paths (`Bar`, `subdir/Baz`) that will be compiled and archived together to build a corresponding `.cma` or `.cmxa` target. | `.cma` + `.cmxa` | The preferred way to build a library archive is to use a `.mllib` file listing its content. If a `foo.mllib` is absent, building the target `foo.cm{,x}a` will create an archive with `foo.cm{o,x}` and all the local module it depends upon, transitively. | `.mldylib` | Contains a list of module paths (`Bar`, `subdir/Baz`) that will be compiled and archived together to build a corresponding `.cmxs` target (native plugin). There is no corresponding concept of bytecode plugin archive, as `.cma` files (built from `.mllib` files) support for static and dynamic linking. | `.cmxs` | The preferred way to build a plugin archive is to list its content in a `.mldylib` file. If a `foo.mldylib` is absent, the modules contained in `foo.cmxa` will be reused instead. In particular, one can transitively create a `foo.cmxs` from a `foo.mllib` file. WARNING: Before OCamlbuild 0.10.0, in absence of a `foo.mldylib` file, in the specific case where a module `Foo` existed, a `.cmxs` file would be built with only `foo.cmx` inside. If you ure users have older OCamlbuild versions, creating an explicit `foo.mldylib` file may be the safest choice. | `.itarget` + `.otarget` | Building `foo.otarget` (`o` for Output target) requests the build of the targets listed (one per line) in the corresponding `foo.itarget` file (`i` for Input list of targets). |=== ==== `ocamldoc` targets These targets will call the documentation generator `ocamldoc`. .`ocamldoc` targets [[Table_ocamldoc_targets]] [cols="1,3", options="header"] |=== | File name | Description | `.odocl` | Contains a list of module names for which to produce documentation, using one of the targets listed below. | `.docdir/index.html` | Building the target `foo.docdir/index.html` will create a subdirectory `foo.docdir` containing the HTML documentation of all modules listed in `foo.odocl`. | `.docdir/man` | As `.docdir/index.html` above, but builds the documentation in `man` format. | `.docdir/bar.tex` or `.docdir/bar.ltx` | Building the target `foo.docdir/bar.tex` will build the documentation for the modules listed in `foo.odocl`, as a LaTeX file named `foo.docdir/bar.tex`. The basename `bar` is not important, but it is the extension `.tex` or `.ltx` that indicates to OCamlbuild that ocamldoc should be asked for a LaTeX output. | `.docdir/bar.texi` | Same as above, but generates documentation in TeXinfo format. | `.docdir/bar.dot` | Same as above, but generates a `.dot` graph of inter-module dependencies. |=== [[Sec_ocamlyacc_and_Menhir_targets]] ==== `ocamlyacc` and Menhir targets OCamlbuild will by default use `ocamlyacc`, a legacy parser generator that is included in the OCaml distribution. The third-party parser generator http://gallium.inria.fr/~fpottier/menhir/[Menhir] is superior in all aspects, so you are encouraged to use it instead. To enable the use of Menhir instead of `ocamlyacc`, you should pass the `-use-menhir` option, or have `true: use_menhir` in your `_tags` file. OCamlbuild will then activate menhir-specific builtin rule listed below. .`ocamlyacc` and Menhir targets [[Table_ocamlyacc_and_Menhir_targets]] [cols="1,3", options="header"] |=== | File name extension | Description | `.mly` | Grammar description files. They will be passed on to `ocamlyacc` to produce the corresponding `.ml` file, or Menhir if it is enabled. | `.mlypack` | Menhir (not ocamlyacc) supports building a parser by composing several `.mly` files together, containing different parts of the grammar description. Listing module paths in `foo.mlypack` will produce `foo.ml` and `foo.mli` by combining the `.mly` files corresponding to the listed modules. | `.mly.depends` + `.mlypack.depends` | Menhir (but not `ocamlyacc`) supports calling `ocamldep` to approximate the dependencies of the OCaml module on which the generated parser will depend. |=== ==== Advanced targets // TODO: Which are file names, and which file name extensions? .Advanced targets [[Table_Advanced_targets]] [cols="1a,3a", options="header"] |=== | File name extension | Description | `.ml.depends` + `.mli.depends` | Call the `ocamldep` tool to compute a conservative over-approximation of the external dependencies of the corresponding source file. | `.inferred.mli` | Infer a `.mli` interface from the corresponding `.ml` file. | `.mlpack` | Contains a list of module paths (`Bar`, `subdir/Baz`) that can be packed as submodules of a `.cmo` or `.cmx` file: if `foo.mlpack` exist, asking for the target `foo.cmx` will build the modules listed in `foo.mlpack` and pack them together. + [NOTE] .Packed submodules ==== The native OCaml compiler requires the submodules that will be packed to be compiled with the `-for-pack Foo` option (where `Foo` is the name of the result of packing), and OCamlbuild does not hide this semantics from the user: you can use the built-in parametrized flag `for-pack(Foo)` for this purpose. For example, to build `foo.cmx` containing `Bar` and `subdir/Baz` as packed-submodules, you should have the following: ---- foo.mlpack: Bar subdir/Baz _tags: <{bar,subdir/baz}.cmx: for-pack(Foo) ---- ==== | `.byte.o` + `.byte.obj` _on Windows_ + + `.byte.so` + `.byte.dll` _on Windows_ + `.byte.dylib` _on OSX_ + + `.byte.c` | Produces object files for static or dynamic linking, or a C source file, by passing the `-output-obj` option to the OCaml bytecode compiler -- see `-output-obj` documentation. | `.native.{o,obj}` + `.native.{so,dll,dylib}` | Produces object files for static or dynamic linking by passing the `-output-obj` option to the OCaml native compiler -- see `-output-obj` documentation. | `.c` + `.{o,obj}` | OCamlbuild can build `.{o,obj}` files from `.c` files by passing them to the OCaml compiler (which in turns calls the C toolchain). The OCaml compiler called is `ocamlc` or `ocamlopt`, depending on whether or not the `native` flag is set on the `.c` source file. | `.clib` | Contains a list of file paths (e.g., `foo.o`, not module paths) to be linked together (by using the standard `ocamlmklib` tool) to produce a `.a` or `.lib` archive (for static linking) or a `.so` or `.dll` archive (for dynamic linking). The .clib name should be prefixed by `lib`, and the target name will then a `lib` or `dll` prefix, following standard conventions: to build a static library from `libfoo.clib`, you should require the target `libfoo.{a,lib}`, and to build a dynamic library you should require the target `dllfoo.{so,dll}`. If `foo.o` is listed and OCamlbuild is run from Windows, `foo.obj` will be used instead. | `.mltop` + `.top` | Requesting the build of `foo.top` will look for a list of module paths in `foo.mltop`, and build a custom toplevel with all these modules pre-linked using the standard `ocamlmktop` tool. |=== ==== Deprecated targets // TODO: I'm not certain which are file names, and which file name extensions. .Deprecated targets [[Table_Deprecated_targets]] [cols="1,3a", options="header"] |=== | File name extension | Description | ``.p.* `` + ``.d.* `` + | OCamlbuild supports requesting `foo.p.{cmx,native}` and `foo.d.{cmo,byte}` to build libraries or executables with profiling information (`.p`) or debug information (`.d`) incorporated. Unfortunately, this runs counter the simple scheme used by the OCaml compiler to find the object files of a compilation unit dependencies: if `Foo` depends on a module `Bar`, the compilation of `foo.p.cmx` will inspect `bar.cmx` (rather than `bar.p.cmx`) for cross-module information -- this is why `.d` is not supported for native code, as this defeats the purpose of debug builds. NOTE: `.p` is not supported for bytecode because bytecode profiling works very differently from native profiling. The more robust solution is to build `foo.{cmo,cmx,byte,native}` with the `profile` or `debug` flag set (e.g., `ocamlbuild -tag 'debug' 'foo.native'`, or using the `_tags` file). If the flag is set for certain files only, only those will have debugging or profiling information enabled. Note that (contrarily to the `.d.cmx` approach) this means you cannot keep a both a with-debug-info and a without-debug-info compiled object file for the same module at the same time: building `foo.byte` with `true: debug`, then without (or conversely) will rebuild all the `.cmo` files of all of `foo` dependencies each time. | `.pp.ml` | This target produces a pretty-printing (as OCaml source code) of the OCaml AST produced by preprocessing the corresponding `.ml` file. This does not work properly when using `ocamlfind` to activate Camlp4 preprocessors (the now-preferred way to enable syntax extensions), because `ocamlfind` does not provide a way to obtain the post-processing output, only to preprocess during compilation. Note that passing the `-dsource` compilation flag to the OCaml compiler will make it emit the result post-processing during compilation (as OCaml source code; use `-dparsetree` for a tree view of the AST). |=== [[Sec_Tags]] === Tags ==== Basic tags For convenience, we try to offer a tag for each setting exported as command-line parameters by the OCaml compilers and tools. A builtin tag `foo_bar` corresponding to the option `-foo-bar` is in general better than trying to pass `-cflags -foo-bar` to the ocamlbuild compilation command, as it can enable the `-foo-bar` flag only when it make sense, in a more fine-grained way that "during a compilation command". TIP: If you notice that a compiler-provided command-line option is missing its tag counterpart, this is a bug that you should report against OCamlbuild. Feel free to look at the implementation and link:../CONTRIBUTING.adoc[send a patch] adding this tag, it is really easy. ===== Compiler tags * `absname` * `annot` * `asm` (for `ocamlopt`'s `-S`) * `bin_annot` * `color(mode)` (for colors in compiler messages, mode can be `auto`, `always` or `never`) * `compat_32` * `custom` * `debug` (for `-g`) * `dtypes` * `for-pack(PackModule)` * `inline(5)` * `cc(ccomp)` * `cclib(-llibname)` * `ccopt(option)` * `keep_locs` * `linkall` * `no_alias_deps` * `no_float_const_prop` * `noassert` * `noautolink` (since 0.11.0) * `nolabels` * `nopervasives` * `nostdlib` (since 0.9.4) * `opaque` * `open(MyPervasives)` * `output_obj` * `output_shared` (for `-cclib -shared`, automatically set by `.{byte,native}.{so,dll,dylib}` targets) * `pp(my_pp_preprocessor)` * `ppx(my_ppx_preprocessor)` * `principal` * `profile` (for `-p`) * `rectypes` * `runtime_variant(_pic)` * `safe_string` * `short_paths` * `strict_formats` * `strict_sequence` * `thread` * `unsafe` * `unsafe_string` * `warn(A@10-28@40-42-45)` * `warn_error(+10+40)` ===== Compiler tags for native compilation using flambda (4.03 and newer) * `optimize(2)` (`2` gives the defaults of the tags below, `3` optimizes more, `classic` switches off flambda) * `optimization_rounds(2)` * `inline_toplevel(160)` * `inline_branch_factor(0.1)` * `inline_alloc_cost(7)` * `inline_branch_cost(5)` * `inline_call_cost(5)` * `inline_indirect_cost(4)` * `inline_prim_cost(3)` * `inline_lifting_benefit(1300)` * `inline_max_depth(1)` * `inline_max_unroll(0)` * `unbox_closures_factor(1)` * `inlining_report` * `remove_unused_arguments` * `unbox_closures` * `no_unbox_free_vars_of_closures` * `no_unbox_specialized_args` ===== Compiler tags for the AFL instrumentation mode (4.05 and newer) * `afl_instrument` (since 0.12.0) * `afl_inst_ratio` (since 0.12.0) ===== `ocamlfind` tags * `package(pkgname)` * `linkpkg` * `dontlink(pkgname)` * `predicate(foo)` * `syntax(bar)` * `ppopt(camlp4-option)` (since 0.13.0) * `ppxopt(package,option)` (since 0.13.0) ===== `ocamllex` tags * `quiet` (`-q`) * `generate_ml` (`-ml`) ===== Menhir tags * `only_tokens` * `infer` * `explain` * `external_tokens(TokenModule)` ===== `camlp4` tags * `use_caml4_{,bin}` * `camlp4{rrr,orrr,oof,orf,rf,of,r,o}{,.opt}` ==== Deprecated tags The tags `use_{ocamlbuild,ocamldoc,toplevel,graphics,dbm,nums,bigarray,str,unix,dynlink}` were designed to indicate that the tagged modules depend on the corresponding libraries from the OCaml distributions (`use_{ocamlbuild,ocamldoc,toplevel}` allows to compile against the tools' libraries to build plugins). We now recommend to enable those libraries through their corresponding `ocamlfind` package. ==== `ocamlbuild`-specific tags ** `not_hygienic` and `precious`: explicitly indicate that a file is part of the source directory and should not be warned about by the hygiene-checking tools. This is useful if for some reason you are given, for example, a `.cmi` file to use unchanged in your project. ** `traverse`: explicitly indicate that OCamlbuild should consider this subdirectory as part of the current project; this flag is set for all subdirectories by default (so OCamlbuild will look in subdirectories recursively to find module dependencies) as soon as the current directory "looks like an OCamlbuild project" (there is either a `myocamlbuild.ml` or `_tags` file present). This tag is usefully used negative, `"foo": -traverse`, to say that a part of the local directory hierarchy should _not_ be considered by OCamlbuild. ** `include`, `traverse`: see the section above on source directories and include paths. ** global tags: setting `true: use_menhir` in the root `_tags` file is equivalent to passing the `-use-menhir` command-line parameter. ==== Advanced (context) tags These tags are generally not meant to be used directly in `_tags` file, but rather to serve as the context part of tag declarations. For example, the `link` flag is automatically added thet set of tags of linking-related command, allowing tag declarations to add specific flags during linking phase only -- but it would make little sense to explicitly add the `link` tag to a target in your `_tags` file. * language context: `c` or `ocaml` indicate whether the compiler invocation are working with OCaml files, or C files (to be passed to the underlying C toolchain). If you wished to use OCamlbuild for a completely different purpose (not necessarily OCaml-related), for example building LaTeX documents, you could use a corresponding `latex` tag. * compilation stage context: `pp` (syntactic preprocessing), `compile` (compilation of source files), `link` (linking of object files), but also `pack` (when packing compiled object files), `library` (when creating library archives), `infer_interface` (producing a `.mli` from the corresponding `.ml`) and `toplevel` (when building custom toplevels). * byte or native compilation context: `byte` (`ocamlc`) or `native` (`ocamlopt`). * File tags: when building the target `foo.bar`, a tag `file:foo.bar` is added to the set of current tags. This can be used for one-off customizations. * extension tags: when building the target `foo.bar`, a tag `extension:bar` is added to the set of current tags. This is used by the builtin `ocamldoc` rules to enable either `-latex` or `-dot` depending on the requested target extension. * tool-specific tags: `menhir`, `ocamlyacc`, `ocamllex`, `doc` (for `ocamldoc`) [[Sec_dynamic_documentation]] === The `-documentation` option Invoking `ocamlbuild -documentation` will give a list of rules and tags known to OCamlbuild in the current project (including those defined in the `myocamlbuild` plugin). This is a good way to quickly look for the tag name corresponding to a particular option, and also more accurate than the above reference manual, which does cannot describe plugin-specific features. WARNING: This output is sensitive to the current configuration. For example, `ocamlbuild -use-ocamlfind -documentation` and `ocamlbuild -no-ocamlfind -documentation` produce different outputs, as the latter does not include ``ocamlfind``-specific tags. Here is an example of rule documentation included in the `ocamlbuild -documentation` output: [source,ocaml] ---- rule "ocaml: modular menhir (mlypack)" ~deps:[ %.mlypack ] ~prods:[ %.mli; %.ml ] ~doc:"Menhir supports building a parser by composing several .mly files together, containing different parts of the grammar description. To use that feature with ocamlbuild, you should create a .mlypack file with the same syntax as .mllib or .mlpack files: a whitespace-separated list of the capitalized module names of the .mly files you want to combine together." your_build_function ---- // TODO: In what sense is it not ‘valid’ OCaml code? WARNING: The previous sample resembles OCaml code (see <>), but is not valid OCaml code. Note that rule declaration only indicate the static dependencies of rules (those that determine whether or not the rule will be tried). This rule is explicit about the fact that invoking Menhir produces both a `.ml` and `.mli`. ==== Parameterized tags _Parameterized tags_ are documented since OCaml version 4.03. An example: ---- parametrized flag {. compile, ocaml, ppx(my_ppx) .} "-ppx my_ppx" [...] flag {. compile, no_alias_deps, ocaml .} "-no-alias-deps" ---- [[Sec_Syntax_of_tags_files]] === Syntax of `_tags` files A `_tags` file associates file name patterns with tags like this: ---- # This is a comment true: bin_annot, debug or : package(yojson) ---- The general syntax is: ---- {pattern}: {comma-separated tag list} ---- These items are ended by a newline. Comments (starting with `#`) and empty lines are ignored, and an escaped line break is considered as whitespace (so those items can span multiple lines). The `{pattern}` part is what we call a "glob expression", which is an expression built of basic logic connective on top of "glob patterns". .The syntax of glob expressions [[Table_The_syntax_of_glob_expressions]] [cols="1m,2m,4", options="header"] |=== | Syntax | Example | Meaning |

| | Paths matching the pattern `p`. | "s" | "foo/bar.ml" | The exact string `s`. | e1 or e2 | <*.ml> or | Paths matching at least one of the expression `e1` or `e2`. | e1 and e2 | <*.ml> and | Paths matching both expressions `e1` and `e2`. | not e | not <*.mli> | Paths not matching the expression `e`. | true | true | All pathnames. | false | false | Nothing. | ( e ) | ( <*> and not <*.*> ) | Same as `e` (useful for composing larger expressions). |=== .The syntax of glob patterns [[Table_The_syntax_of_glob_patterns]] [cols="4a,2m,2,2m,4", options="header"] |=== | Syntax | Example | Matches | Does not match | Meaning | `s` | foo.ml | `foo.ml` | `bar.ml` | The exact string `s`. | `*` + _(wildcard)_ | * | The empty path + `foo` + `bar` | `foo/bar` + `/baz` | Any string not containing a slash `/`. | `?` + _(joker)_ | ? | `a` + `b` + `z` | `/` + `/bar` | Any one-letter string, excluding the slash `/`. | `**/` + _(prefix inter-directory wildcard)_ | **/foo.ml | `foo.ml` + `bar/foo.ml` + `bar/baz/foo.ml` | `bar/foo` | The empty string, or any string ending with a slash `/`. | `/**` + _(suffix inter-directory wildcard)_ | foo/** | `foo` + `foo/bar` | `bar/foo` | The empty string, or any string starting with a slash `/`. | `/**/` + _(infix inter-directory wildcard)_ | bar/**/foo.ml | `bar/foo.ml` + `bar/baz/foo.ml` | `foo.ml` | Any string starting and ending with a slash `/`. | `[r1 r2 r3 ...]`, + where each `r` is either: + * A single character `c`; or * A range `c1-c2` + _(positive character class)_. | [a-fA-F0-9_.] | `3` + `F` + `.` | `z` + `bar` | Any one-letter string made up of characters from one of the given ranges. | `[^ r1 r2 r3 ...]`, + where each `r` is either: * A single character `c`; or * A range `c1-c2` + _(negative character class)_. | [a-fA-F0-9_.] | `z` + `bar` | `3` + `F` + `.` | Any one-letter string *not* made up of characters from one of the given ranges. | `p1 p2` + _(concatenation)_ | foo* | `foo` + `foob` + `foobar` | `fo` + `bar` | Any string with a (possibly empty) prefix matching the pattern `p1` and the (possibly empty) remainder matching the pattern `p2`. | `{ p1, p2, ... }` + _(union)_ | toto.{ml,mli} | `toto.ml` + `toto.mli` | `toto.` | Any string matching one of the given patterns. |=== In addition, rule patterns may include pattern variables. `%(foo: p)` will match for the pattern `p` and name the result `%(foo)`. For example, `%(path: <**/>)foo.ml` is useful. `%(foo)` will match the pattern `true` and name the result `%(foo)`, and finally `%` will match the pattern `true` and match the result `%`. Consider the following examples: ---- %.cmx %(dir).docdir/%(file) %(path:<**/>)lib%(libname:<*> and not <*.*>).so ---- [[Sec_Plugins]] == Enriching OCamlbuild through plugins === How `myocamlbuild.ml` is used If you have a `myocamlbuild.ml` file at the root of your OCamlbuild project, the building process will run in two steps. First, OCamlbuild will compile `myocamlbuild.ml`, linking it with all the modules that are part of the globally installed `ocamlbuild` executable. This will produce a program `_build/myocamlbuild` that behaves exactly like `ocamlbuild` itself, except that it also runs the code of your `myocamlbuild.ml` file. Immediately after, OCamlbuild will stop (before doing any work on the targets you gave it) and start the `_build/myocamlbuild` program instead, that will handle the rest of the job. This is quite close to how, for example, XMonad (a window manager whose configuration files are pure Haskell) works. This means that it is technically possible to do anything in `myocamlbuild.ml` that could be done by adding more code to the upstream OCamlbuild sources. But in practice, relying on the implementation internals would be fragile with respect to OCamlbuild version changes. We thus isolated a subset of the OCamlbuild API, exposed by the `Ocamlbuild_plugin` module, that defines a stable interface for plugin developers. It lets you manipulate command-line options, define new rules and targets, add new tags or refine the meaning of existing flags, etc. The signature of this module is the `PLUGIN` module type of the interface-only `signatures.mli` file of the OCamlbuild distribution. NOTE: You will find the module source code littered with comments explaining the purpose of the exposed values, but this documentation aspect can still be improved. We warmly welcome patches to improve this aspect of `ocamlbuild` -- link:../CONTRIBUTING.adoc[or any other aspect]. You can influence the `myocamlbuild.ml` compilation-and-launch process in several ways: * The `-no-plugin` option allows to ignore the `myocamlbuild.ml` file and just run the stock `ocamlbuild` executable on your project. This means that fancy new rules introduced by `myocamlbuild.ml` will not be available. * The `-just-plugin` option instructs OCamlbuild to stop compilation after having built the plugin. It also guarantees that OCamlbuild will try to compile the plugin, which it may not always do, for example when you only ask for cleaning or documentation. * The `-plugin-option FOO` option will pass the command-line option `FOO` to the `myocamlbuild` invocation -- and ignore it during plugin compilation. * The `-plugin-tag` and `-plugin-tags` options allow to pass tags that will be used to compile the plugin. For example, if someone develops a nice library to help writing OCamlbuild plugins and distribute as 'toto.ocamlbuild' in `ocamlfind` then `-plugin-tag "package(toto.ocamlbuild)"` will let you use it in your `myocamlbuild.ml`. NOTE: The rationale for `-plugin-option` and `-plugin-tag` to apply during different phases of the process is that an option is meaningful at runtime for the plugin, while a plugin tag is meaningful at compile-time. === Plugin dispatch Tag and rule declarations, or configuration option manipulation, are side-effects that modify a global OCamlbuild state. It would be fragile to write your `myocamlbuild.ml` with such side-effects performed at module initialization time, in the following style: [source,ocaml] ---- open Ocamlbuild_plugin (* bad style *) let () = Options.ocamlc := "/better/path/to/ocamlc" ;; ---- The problem is that you have little idea, and absolutely no flexibility, of the time at which those actions will be performed with respect to all the other actions of OCamlbuild. In this example, command-line argument parsing will happen after this plugin effect, so the changed option would be overridden by command-line options, which may or may not be what a plugin developer expects. To alleviate this side-effect order issue, OCamlbuild lets you register actions at hook points, to be called at a well-defined place during the OCamlbuild process. If you want your configuration change to happen after options have been processed, you should in fact write: [source,ocaml] ---- open Ocamlbuild_plugin let () = dispatch (function | After_options -> Options.ocamlc := "..." | _ -> ()) ---- The `dispatch` function register a hook-listening function provided by the user. Its type is `(hook -> unit) -> unit`. The hooks are currently defined as: [source,ocaml] ---- (** Here is the list of hooks that the dispatch function have to handle. Generally one responds to one or two hooks (like After_rules) and do nothing in the default case. *) type hook = | Before_hygiene | After_hygiene | Before_options | After_options | Before_rules | After_rules ---- WARNING: OCamlbuild does not guarantee any order in which it will call various hooks, except of course that `Before_foo` always happens before `After_foo`. In particular, the `hygiene` hooks may be called before or after other hooks, or not be called at all if OCamlbuild decides not to check <>. === Flag declarations A flag declaration maps a _set of tags_ to a list of command-line arguments/flags/options/parameters. These arguments will be added to a given compilation command if each of the tags are present on the given target. The following example can be found in `ocaml_specific.ml`, the file of the OCamlbuild sources that defines most OCaml-specific tags and rules of OCamlbuild: [source,ocaml] ---- flag ["ocaml"; "annot"; "compile"] (A "-annot"); ---- This means that the `-annot` command-line option is added to any compilation command for which those three tags are present. The tags `"ocaml"` and `"compile"` are activated by default by OCamlbuild, `"ocaml"` for any ocaml-related command, and `"compile"` specifically for compilation steps -- as opposed to linking, documentation generation, etc. The `"annot"` flag is not passed by default, so this tag declaration will only take effects on targets that are explicitly marked `annot` in the `_tags` file. This very simple declarative language, mapping sets of tags to command-line options, is the way to give meaning to OCamlbuild tags -- either add new ones or overload existing ones. It is very easy, for example, to pass a different command-line argument depending on whether byte or native-compilation is happening. [source,ocaml] ---- flag ["ocaml"; "use_camlp4_bin"; "link"; "byte"] (A"+camlp4/Camlp4Bin.cmo"); flag ["ocaml"; "use_camlp4_bin"; "link"; "native"] (A"+camlp4/Camlp4Bin.cmx"); ---- The `A` constructor stands for ‘atom(ic)’, and is part of a `spec` datatype, representing specifications of fragments of command. We will not describe its most advanced constructors -- it is again exposed and documented in `signatures.mli` -- but the most relevant here are: [source,ocaml] ---- (** The type for command specifications. That is pieces of command. *) and spec = | N (** No operation. *) | S of spec list (** A sequence. This gets flattened in the last stages *) | A of string (** An atom. *) | P of pathname (** A pathname. *) [...] ---- TIP: When introducing new flags, it is sometime difficult to guess which combination of tags to use. A hint to find the right combination is to have a look at OCamlbuild's log file that is saved in `_build/_log` each time `ocamlbuild` is run. It contains the targets OCamlbuild tried to produce, with the associated list of tags and the corresponding command lines. ==== Parametrized tags You can also define families of parametrized tags such as `package(foo)` or `inline(30)`. This is done through the `pflag` function, which takes a list of usual tags, the special parametrized tag, and a function from the tag parameter to the corresponding command specification. Again from the `PLUGIN` module type in `signatures.mli`: [source,ocaml] ---- (** Allows to use [flag] with a parametrized tag (as [pdep] for [dep]). Example: pflag ["ocaml"; "compile"] "inline" (fun count -> S [A "-inline"; A count]) says that command line option "-inline 42" should be added when compiling OCaml modules tagged with "inline(42)". *) val pflag : Tags.elt list -> Tags.elt -> (string -> Command.spec) -> unit ---- [[Sec_Rules]] === Rule declarations OCamlbuild let you build your own rules, to teach it how to build new kind of targets. This is done by calling the `rule` function from a plugin, which is declared and documented in the `PLUGIN` module in `signatures.mli`. We will not write an exhaustive documentation here (for this, have a look at `signatures.mli`), but rather expose the most common features through representative examples. [[Subsec_Rules__Rule_example]] === A simple rule Our first example is simple, as it is a rule without dynamic dependencies: [source,ocaml] ---- rule "ocaml dependencies ml" ~prod:"%.ml.depends" ~dep:"%.ml" ~doc:"call ocamldep to compute a syntactic over-approximation \\ of the dependencies of the corresponding implementation file" ocamldep_ml_command ---- The first string parameter is the name of the rule. This rule tells OCamlbuild how to build `foo.ml.depends` from its `foo.ml`. The `%` character here is a pattern variable: if the target name (e.g., `foo.ml.depends`) matches the pattern of the rule production `%.ml.depends` then OCamlbuild will try to build the static dependency of the rule. The static dependency is the evaluation of `%.ml` in the pattern-matching environment `% -> "foo"` (that is, `foo.ml`). If this static dependency can be built, then the "action" `ocamldep_ml_command` will be invoked to produce the expected result. The action, of type `PLUGIN.action`, is a function that takes the current pattern-matching environment (in our example, mapping the pattern variable `%` to `foo`), a builder function, and returns a command, the command to execute to produce the final target of this rule. A plugin developer defining this rule should define the `ocamldep_ml_command` as follows: [source,ocaml] ---- let ocamldep_ml_command env _build = let arg = env "%.ml" and out = env "%.ml.depends" in let tags = tags_of_pathname arg ++ "ocaml" ++ "ocamldep" in Cmd(S[A "ocamldep"; T tags; A "-modules"; P arg; Sh ">"; Px out]) ---- The first line in this definition uses the pattern environment to compute the actual name of the input and output files. These are then passed in as arguments to the `ocamldep` command and shell redirect, respectively, on the third line. The environment type `PLUGIN.env` is just `string -> string`, it takes a pattern and substitutes its pattern variables to return a closed result. The second line in this definition computes the tags to include in the command invocation. When OCamlbuild is passed back the command, it uses the tag declarations to determine which, if any, additional flags to insert into the command invocation. The call `tags_of_pathname arg` looks up in the `_tags` file any tags associated with file `foo.ml`. To these tags the rule code also adds the two contextual tags `ocaml` and `ocamldep` (on which flag declarations may depend). Finally, the command is built: [source,ocaml] ---- Cmd(S[A "ocamldep"; T tags; A "-modules"; P arg; Sh ">"; Px out]) ---- We already mentioned above the constructors `S`, `A` and `P` of the `command.spec` type: * `S` just builds a sequence by concatenating sequent fragments; * `A` is used for ‘atoms’ (fragments of text to be included as-is, but may be escaped to make them syntactic shell code); and * `P` denotes a filesystem path that should be quoted. The constructor `T` is used to embed tags within a command. Mind that passing `T` twice, one with the tag set `ocaml, ocamldep` and the other with the tag `foo`, is not equivalent to passing `ocaml, ocamldep, foo` together, as the transformation of tags into flags proceeds on each `T` fragment separately. `Sh` is used for bits of raw shell code that should not be quoted at all, here the output redirection `>`. Finally, `Px` indicates a filesystem path just as `P`, but it adds the information that this filesystem path is the path of the target produced by this rule. This information is used by OCamlbuild for logging purposes. [NOTE] .Tags handling in rules ==== It is entirely the rule author's responsibility to include tags in the action's command. In particular, it is the code of the rule's action that decides which, if any, tags are taken into account and if they come from the rule dependencies, products or both. (Unfortunately, the built-in rules themselves are sometimes inconsistent on this.) // TODO: Where are they inconsistent? ==== [[Subsec_Rules__Dynamic_dependencies]] ==== Dynamic dependencies In the action `ocamldep_ml_command` of the previous example, the `~build` parameter (of type `PLUGIN.builder`) was ignored, because the rule had no dynamic dependencies. Therefore there was no need to build extra targets determined during the execution of the rule itself. The static dependency is built by ``ocamlbuild``'s resolution engine before the action executed. On the contrary, dynamic dependencies are targets that are not indicated as dependencies in the rule declaration, but who are dynamically requested to build during the execution of the rule action. For example, the `target_list` action below reads a targets of paths in a `%.itarget` file, and builds all those targets. The targets cannot be known at the time the rule is declared, they are dynamic dependencies. [source,ocaml] ---- let target_list env build = let itarget = env "%.itarget" in let targets = let dir = Pathname.dirname itarget in let files = string_list_of_file itarget in List.map (fun file -> [Pathname.concat dir file]) files in let results = List.map Outcome.good (build targets) in let link_command result = Cmd (S [A "ln"; A "-sf"; P (Pathname.concat !Options.build_dir result); A Pathname.pwd]) in Seq (List.map link_command results) rule "target files" ~dep:"%.itarget" ~stamp:"%.otarget" ~doc:"If foo.itarget contains a list of ocamlbuild targets, \ asking ocamlbuild to produce foo.otarget will \ build each of those targets in turn." target_list ---- The `string_list_of_file` function reads a file and returns the list of its lines. It is used in the various built-in rules for files containing other file or module paths (e.g., `.mllib`, `.odocl` or here `.itarget`). The function `build` takes as argument a list of lists, to be understood as a conjunction of disjunctions. For example, if passed the input `[["a/foo.byte"; "b/foo.byte"]; ["a/foo.native"; "b/foo.native"]]`, it tries to build ( (`a/foo.byte` OR `b/foo.byte`) AND (`a/foo.native` OR `b/foo.native`) ). The disjunctive structure (this OR that) is useful because we are often not quite sure where a particular target may be (for example the module `Foo` may be in any of the subdirectories in the include path). The conjunctive structure (this AND that) is essential to parallelizing the build, since `ocamlbuild` tries to build all these targets in parallel, whereas sequential invocation of the build function on each of the disjunctions would give sequential builds. // TODO: Rephrase. ‘Disjoint-sum type’ is terminology far above the level just explained in the previous paragraph. Better define target audience? The function `build` returns a list of outcomes (`(string, exn) Outcome.t` -- `Outcome.t` is just a disjoint-sum type), that is either a `string` (the possible target that could be built) or an exception. `Outcome.good` returns the good result if it exists, or raises the exception. [[Subsec_Rules__Stamps]] ==== Stamps In the rule above, the production `"%.otarget"` is not passed as `~prod` parameter, but as a `~stamp`. Stamps are special files that record the list of digests of the dynamic dependencies of the rule that produced them. This is useful to know whether a target should be re-compiled, or whether it is already up-to-date from a previous build and can be just kept as-is. Imagine that a rule to produce a file `foo.weird` depends on the rules listed in the corresponding `foo.itarget` (and then performs some build action). When should `foo.weird` be rebuilt, and when is it up-to-date? More precisely, after we have built the targets of `foo.itarget`, how do we know whether we should re-run the build action of `foo.weird`? Obviously, just checking if the `foo.itarget` file changed is not enough (the list of targets could be identical and yet, if one of the target changed, `foo.weird` must be rebuilt). This is where `foo.otarget` comes in: because it contains a list of digests of the dependencies of `foo.itarget`, `foo.weird` can statically depend on `foo.otarget`. `foo.weird` does not need to depend on `foo.itarget` directly, and it will transitively depend on it through `foo.otarget`. This stamp file will change each time one of the `foo.itarget` elements changes, and thus `foo.weird` will be rebuilt exactly as necessary. Such stamps should be used each time a rule has no natural file output to use as output (the case of `.itarget`), or when this file output does not contain enough information for its digest to correctly require rebuilding. The latter case occurs in the rule to build `ocamldoc` documentation `%.docdir/index.html`: the `index.html` only lists the documented modules. It does not contain their documentation -- that is in other files generated. The rule thus produces a stamp `%.docdir/html.stamp`. You should only depend on that stamp if you want your rule to be executed _each time_ the documentation changes. [[Subsec_Rules__Pattern_variables]] ==== Pattern variables Most rules need exactly one pattern variable and use `%` for this purpose. You may use any string of the form `%(identifier)` as pattern variable, or even `%(identifier:pattern)`, in which case the pattern will be only be matched by a string matching the corresponding `pattern`. For example, the rule to produce the dynamic library archive `dllfoo.so` from the file list `libfoo.clib` starts as follows: [source,ocaml] ---- rule "ocaml C stubs: clib & (o|obj)* -> (a|lib) & (so|dll)" ~prods:(["%(path:<**/>)lib%(libname:<*> and not <*.*>)"-.-ext_lib] @ if Ocamlbuild_config.supports_shared_libraries then ["%(path:<**/>)dll%(libname:<*> and not <*.*>)"-.-ext_dll] else []) ~dep:"%(path)lib%(libname).clib" ---- [[Subsec_Rules__Rule_ordering]] ==== Rule ordering and `~insert` One cannot define a rule if there already exists a built-in rule of the same name. Directly including the rule `"ocaml dependencies ml"` used above in your plugin would result in a failure when loading the plugin: [source,ocaml] ---- Rule.Exit_rule_error("Rule.add_rule: already exists: (ocaml dependencies ml)"). ---- Even if you pick another name for the rule, you may find out that the rule you are defining is not used. OCamlbuild orders rule definitions, and the new rule needs to come _before_ the rule that it is replacing. Use the `~insert` argument to `rule` to either (suggested) place it before the built in rule (`~insert:(`before "ocaml dependencies ml)`) or at the top (`~insert:(`top)`). The default behavior, in absence of `~insert` argument, is to place custom rules at the bottom; this is fine when defining rules for new targets, but not when overriding built-in rules. === Complete example: Menhir support in OCamlbuild [source,ocaml] .Menhir support in OCamlbuild ---- include::../samples/complete-example-menhir-support-in-ocamlbuild/myocamlbuild.ml[] ---- , where the Menhir-specific actions in `Ocaml_tools` are defined as follows: [source,ocaml] ---- include::../samples/complete-example-menhir-support-in-ocamlbuild/Ocaml_tools.ml[] ---- ocamlbuild-0.14.3/misc/000077500000000000000000000000001454061437200146535ustar00rootroot00000000000000ocamlbuild-0.14.3/misc/opentracer.ml000066400000000000000000000074671454061437200173650ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) open My_std module type TRACER = sig (** Call the given command using the tracer, it returns the exit status. *) val call : string -> string list -> StringSet.t * Unix.process_status end module Ktrace = struct let process_line line (wait_a_string, set) = let strings = Lexers.space_sep_strings (Lexing.from_string line) in if wait_a_string then match strings with | [_; _; "NAMI"; file] -> false, StringSet.add file set | _ -> failwith (Printf.sprintf "unexpected ktrace output line (%S)" line) else match strings with | [_; _; "CALL"; fct] -> (String.length fct > 5 && String.sub fct 0 5 = "open("), set | _ -> false, set let call cmd args = let tmp = Filename.temp_file "ktrace" "out" in match Unix.fork () with | 0 -> Unix.execvp "ktrace" (Array.of_list("-d"::"-i"::"-t"::"nc"::"-f"::tmp::cmd::args)) | pid -> let _, st = Unix.waitpid [] pid in let ic = Unix.open_process_in (Printf.sprintf "kdump -f %s" (Filename.quote tmp)) in let close () = ignore (Unix.close_process_in ic); Sys.remove tmp in let set = try let rec loop acc = match try Some (input_line ic) with End_of_file -> None with | Some line -> loop (process_line line acc) | None -> acc in let _, set = loop (false, StringSet.empty) in close (); set with e -> (close (); raise e) in set, st end module Driver (T : TRACER) = struct let usage () = Printf.eprintf "Usage: %s [-a ]* *\n%!" Sys.argv.(0); exit 2 let main () = let log = "opentracer.log" in let oc = if sys_file_exists log then open_out_gen [Open_wronly;Open_append;Open_text] 0 log else let oc = open_out log in let () = output_string oc "---\n" in oc in let rec loop acc = function | "-a" :: file :: rest -> loop (StringSet.add file acc) rest | "-a" :: _ -> usage () | "--" :: cmd :: args -> acc, cmd, args | cmd :: args -> acc, cmd, args | [] -> usage () in let authorized_files, cmd, args = loop StringSet.empty (List.tl (Array.to_list Sys.argv)) in let opened_files, st = T.call cmd args in let forbidden_files = StringSet.diff opened_files authorized_files in if not (StringSet.is_empty forbidden_files) then begin Printf.fprintf oc "- cmd: %s\n args:\n%!" cmd; let pp = Printf.fprintf oc " - %s\n%!" in List.iter pp args; Printf.fprintf oc " forbidden_files:\n%!"; StringSet.iter pp forbidden_files; end; close_out oc; match st with | Unix.WEXITED st -> exit st | Unix.WSIGNALED s | Unix.WSTOPPED s -> Unix.kill (Unix.getpid ()) s end let main = (* match os with *) (* | "macos" -> *) let module M = Driver(Ktrace) in M.main (* | "linux" -> *) (* let module M = Driver(Strace) in M.main *) let () = main () ocamlbuild-0.14.3/ocamlbuild.opam000066400000000000000000000016671454061437200167230ustar00rootroot00000000000000opam-version: "2.0" maintainer: "Gabriel Scherer " authors: ["Nicolas Pouillard" "Berke Durak"] homepage: "https://github.com/ocaml/ocamlbuild/" bug-reports: "https://github.com/ocaml/ocamlbuild/issues" license: "LGPL-2.0-or-later WITH OCaml-LGPL-linking-exception" doc: "https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc" dev-repo: "git+https://github.com/ocaml/ocamlbuild.git" synopsis: "OCamlbuild is a build system with builtin rules to easily build most OCaml projects" build: [ [ make "-f" "configure.make" "all" "OCAMLBUILD_PREFIX=%{prefix}%" "OCAMLBUILD_BINDIR=%{bin}%" "OCAMLBUILD_LIBDIR=%{lib}%" "OCAMLBUILD_MANDIR=%{man}%" "OCAML_NATIVE=%{ocaml:native}%" "OCAML_NATIVE_TOOLS=%{ocaml:native}%" ] [make "check-if-preinstalled" "all" "opam-install"] ] conflicts: [ "base-ocamlbuild" "ocamlfind" {< "1.6.2"} ] depends: [ "ocaml" {>= "4.03"} ] ocamlbuild-0.14.3/plugin-lib/000077500000000000000000000000001454061437200157625ustar00rootroot00000000000000ocamlbuild-0.14.3/plugin-lib/ocamlbuild_executor.ml000066400000000000000000000242051454061437200223500ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Compatibility with both OCaml < 4.08 and >= 5.00 *) module Pervasives = struct let stdout = stdout end (* Original author: Berke Durak *) (* Ocamlbuild_executor *) open Unix;; type error = | Subcommand_failed | Subcommand_got_signal | Io_error | Exceptionl_condition type task = unit -> string;; type job = { job_id : int * int; job_command : string; job_next : task list; job_result : bool ref; (* Result of this sequence group *) job_stdout : in_channel; job_stdin : out_channel; job_stderr : in_channel; job_buffer : Buffer.t; mutable job_dying : bool; };; module JS = Set.Make(struct type t = job let compare = compare end);; module FDM = Map.Make(struct type t = file_descr let compare = compare end);; let sf = Printf.sprintf;; let fp = Printf.fprintf;; (*** print_unix_status *) (* FIXME never called *) let print_unix_status oc = function | WEXITED x -> fp oc "exit %d" x | WSIGNALED i -> fp oc "signal %d" i | WSTOPPED i -> fp oc "stop %d" i ;; (* ***) (*** print_job_id *) let print_job_id oc (x,y) = fp oc "%d.%d" x y;; (* ***) (*** output_lines *) let output_lines prefix oc buffer = let u = Buffer.contents buffer in let m = String.length u in let output_line i j = output_string oc prefix; output_substring oc u i (j - i); output_char oc '\n' in let rec loop i = if i < m then let j = try String.index_from u i '\n' with Not_found -> m in output_line i j; loop (j + 1) else () in loop 0 ;; (* ***) (*** execute *) (* XXX: Add test for non reentrancy *) let execute ?(max_jobs=max_int) ?(ticker=ignore) ?(period=0.1) ?(display=(fun f -> f Pervasives.stdout)) ~exit (commands : task list list) = let batch_id = ref 0 in let env = environment () in let jobs = ref JS.empty in let jobs_active = ref 0 in let jobs_to_terminate = Queue.create () in let commands_to_execute = Queue.create () in let all_ok = ref true in let results = List.map (fun tasks -> let result = ref false in Queue.add (tasks, result) commands_to_execute; result) commands in let outputs = ref FDM.empty in let doi = descr_of_in_channel in let doo = descr_of_out_channel in (*** compute_fds *) let compute_fds = let fds = ref ([], [], []) in let prev_jobs = ref JS.empty in fun () -> if not (!prev_jobs == !jobs) then begin prev_jobs := !jobs; fds := JS.fold begin fun job (rfds, wfds, xfds) -> let ofd = doi job.job_stdout and ifd = doo job.job_stdin and efd = doi job.job_stderr in (ofd :: efd :: rfds, wfds, ofd :: ifd :: efd :: xfds) end !jobs ([], [], []) end; !fds in (* ***) (*** add_job *) let add_job cmd rest result id = (*display begin fun oc -> fp oc "Job %a is %s\n%!" print_job_id id cmd; end;*) let (stdout', stdin', stderr') = open_process_full cmd env in incr jobs_active; set_nonblock (doi stdout'); set_nonblock (doi stderr'); let job = { job_id = id; job_command = cmd; job_next = rest; job_result = result; job_stdout = stdout'; job_stdin = stdin'; job_stderr = stderr'; job_buffer = Buffer.create 1024; job_dying = false } in outputs := FDM.add (doi stdout') job (FDM.add (doi stderr') job !outputs); jobs := JS.add job !jobs; in (* ***) (*** skip_empty_tasks *) let rec skip_empty_tasks = function | [] -> None | task :: tasks -> let cmd = task () in if cmd = "" then skip_empty_tasks tasks else Some(cmd, tasks) in (* ***) (*** add_some_jobs *) let add_some_jobs () = let (tasks, result) = Queue.take commands_to_execute in match skip_empty_tasks tasks with | None -> result := false | Some(cmd, rest) -> let b_id = !batch_id in incr batch_id; add_job cmd rest result (b_id, 0) in (* ***) (*** terminate *) let terminate ?(continue=true) job = if not job.job_dying then begin job.job_dying <- true; Queue.add (job, continue) jobs_to_terminate end else () in (* ***) (*** add_more_jobs_if_possible *) let add_more_jobs_if_possible () = while !jobs_active < max_jobs && not (Queue.is_empty commands_to_execute) do add_some_jobs () done in (* ***) (*** do_read *) let do_read = let u = Bytes.create 4096 in fun ?(loop=false) fd job -> (*if job.job_dying then () else*) try let rec iteration () = let m = try read fd u 0 (Bytes.length u) with | Unix.Unix_error(e,_,_) -> let msg = error_message e in display (fun oc -> fp oc "Error while reading stdout/stderr: %s\n" msg); 0 in if m = 0 then if job.job_dying then () else terminate job else begin Buffer.add_subbytes job.job_buffer u 0 m; if loop then iteration () else () end in iteration () with | x -> display begin fun oc -> fp oc "Exception %s while reading output of command %S\n%!" job.job_command (Printexc.to_string x); end; exit Io_error in (* ***) (*** process_jobs_to_terminate *) let process_jobs_to_terminate () = while not (Queue.is_empty jobs_to_terminate) do ticker (); let (job, continue) = Queue.take jobs_to_terminate in (*display begin fun oc -> fp oc "Terminating job %a\n%!" print_job_id job.job_id; end;*) decr jobs_active; (* PR#5371: we would get EAGAIN below otherwise *) clear_nonblock (doi job.job_stdout); clear_nonblock (doi job.job_stderr); do_read ~loop:true (doi job.job_stdout) job; do_read ~loop:true (doi job.job_stderr) job; outputs := FDM.remove (doi job.job_stdout) (FDM.remove (doi job.job_stderr) !outputs); jobs := JS.remove job !jobs; let status = close_process_full (job.job_stdout, job.job_stdin, job.job_stderr) in let shown = ref false in let show_command () = if !shown then () else display begin fun oc -> shown := true; fp oc "+ %s\n" job.job_command; output_lines "" oc job.job_buffer end in if Buffer.length job.job_buffer > 0 then show_command (); begin match status with | Unix.WEXITED 0 -> begin if continue then begin match skip_empty_tasks job.job_next with | None -> job.job_result := true | Some(cmd, rest) -> let (b_id, s_id) = job.job_id in add_job cmd rest job.job_result (b_id, s_id + 1) end else all_ok := false; end | Unix.WEXITED rc -> show_command (); display (fun oc -> fp oc "Command exited with code %d.\n" rc); all_ok := false; exit Subcommand_failed | Unix.WSTOPPED s | Unix.WSIGNALED s -> show_command (); all_ok := false; display (fun oc -> fp oc "Command got signal %d.\n" s); exit Subcommand_got_signal end done in (* ***) (*** terminate_all_jobs *) let terminate_all_jobs () = JS.iter (terminate ~continue:false) !jobs in (* ***) (*** loop *) let rec loop () = (*display (fun oc -> fp oc "Total %d jobs\n" !jobs_active);*) process_jobs_to_terminate (); add_more_jobs_if_possible (); if JS.is_empty !jobs then () else begin let (rfds, wfds, xfds) = compute_fds () in ticker (); let rec select_non_intr r w x p = try select r w x p with Unix_error (EINTR, _, _) -> select_non_intr r w x p in let (chrfds, chwfds, chxfds) = select_non_intr rfds wfds xfds period in List.iter begin fun (fdlist, hook) -> List.iter begin fun fd -> try let job = FDM.find fd !outputs in ticker (); hook fd job with | Not_found -> () (* XXX *) end fdlist end [chrfds, do_read ~loop:false; chwfds, (fun _ _ -> ()); chxfds, begin fun _ _job -> (*display (fun oc -> fp oc "Exceptional condition on command %S\n%!" job.job_command); exit Exceptional_condition*) () (* FIXME *) end]; loop () end in try loop (); None with | x -> begin try terminate_all_jobs () with | x' -> display (fun oc -> fp oc "Extra exception %s\n%!" (Printexc.to_string x')) end; Some(List.map (!) results, x) ;; (* ***) ocamlbuild-0.14.3/plugin-lib/ocamlbuild_executor.mli000066400000000000000000000046571454061437200225320ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Ocamlbuild_executor *) (** UNIX-specific module for running tasks in parallel and properly multiplexing their outputs. *) type error = | Subcommand_failed | Subcommand_got_signal | Io_error | Exceptionl_condition (** [execute ~ticker ~period ~display ~exit commands] will execute the commands in [commands] in parallel, correctly multiplexing their outputs. A command is a function that given a unit [()] returns the shell command string to execute, commands are functions in order to do some job just before executing the command. These functions will be called once. If specified, it will call [ticker] at least every [period] seconds. If specified, it will call [display f] when it wishes to print something; [display] should then call [f] with then channel on which [f] should print. Note that if the shell command to execute is the empty string [""], it's considered as a no-op. Note that [f] must be idempotent as it may well be called twice, once for the log file, once for the actual output. If one of the commands fails, it will exit with an appropriate error code, calling [cleanup] before. All exits are done trough the call to the given [exit] function, if not supplied Pervasives.exit is used. *) val execute : ?max_jobs:int -> ?ticker:(unit -> unit) -> ?period:float -> ?display:((out_channel -> unit) -> unit) -> exit:(error -> unit) -> ((unit -> string) list list) -> (bool list * exn) option ocamlbuild-0.14.3/plugin-lib/ocamlbuild_plugin.ml000066400000000000000000000060111454061437200220030ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open Ocamlbuild_pack include Ocamlbuild_pack.My_std module Arch = Ocamlbuild_pack.Ocaml_arch module Command = Ocamlbuild_pack.Command module Pathname = Ocamlbuild_pack.Pathname module Tags = Ocamlbuild_pack.Tags include Pathname.Operators include Tags.Operators module Rule = Ocamlbuild_pack.Rule module Options = Ocamlbuild_pack.Options module Findlib = Ocamlbuild_pack.Findlib type command = Command.t = Seq of command list | Cmd of spec | Echo of string list * string | Nop and spec = Command.spec = | N | S of spec list | A of string | P of string | Px of string | Sh of string | T of Tags.t | V of string | Quote of spec include Rule.Common_commands type env = Pathname.t -> Pathname.t type builder = Pathname.t list list -> (Pathname.t, exn) Ocamlbuild_pack.My_std.Outcome.t list type action = env -> builder -> Command.t let rule = Rule.rule let clear_rules = Rule.clear_rules let dep = Command.dep let pdep = Command.pdep let copy_rule = Rule.copy_rule let ocaml_lib = Ocamlbuild_pack.Ocaml_utils.ocaml_lib let flag = Ocamlbuild_pack.Flags.flag ?deprecated:None let pflag = Ocamlbuild_pack.Flags.pflag ?doc_param:None let mark_tag_used = Ocamlbuild_pack.Flags.mark_tag_used let flag_and_dep = Ocamlbuild_pack.Flags.flag_and_dep let pflag_and_dep = Ocamlbuild_pack.Flags.pflag_and_dep ?doc_param:None let non_dependency = Ocamlbuild_pack.Ocaml_utils.non_dependency let use_lib = Ocamlbuild_pack.Ocaml_utils.use_lib let module_name_of_pathname = Ocamlbuild_pack.Ocaml_utils.module_name_of_pathname let string_list_of_file = Ocamlbuild_pack.Ocaml_utils.string_list_of_file let expand_module = Ocamlbuild_pack.Ocaml_utils.expand_module let tags_of_pathname = Ocamlbuild_pack.Tools.tags_of_pathname let hide_package_contents = Ocamlbuild_pack.Ocaml_compiler.hide_package_contents let tag_file = Ocamlbuild_pack.Configuration.tag_file let tag_any = Ocamlbuild_pack.Configuration.tag_any let run_and_read = Ocamlbuild_pack.My_unix.run_and_read type hook = Ocamlbuild_pack.Hooks.message = | Before_hygiene | After_hygiene | Before_options | After_options | Before_rules | After_rules let dispatch = Ocamlbuild_pack.Hooks.setup_hooks ocamlbuild-0.14.3/plugin-lib/ocamlbuild_plugin.mli000066400000000000000000000021541454061437200221600ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) include Ocamlbuild_pack.Signatures.PLUGIN with module Pathname = Ocamlbuild_pack.Pathname and module Outcome = Ocamlbuild_pack.My_std.Outcome and module Tags = Ocamlbuild_pack.Tags and module Command = Ocamlbuild_pack.Command ocamlbuild-0.14.3/plugin-lib/ocamlbuild_unix_plugin.ml000066400000000000000000000067401454061437200230570ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open Format open Ocamlbuild_pack open My_unix let report_error f = function | Unix.Unix_error(err, fun_name, arg) -> fprintf f "%s: %S failed" Sys.argv.(0) fun_name; if String.length arg > 0 then fprintf f " on %S" arg; fprintf f ": %s" (Unix.error_message err) | exn -> raise exn let mkstat unix_stat x = let st = try unix_stat x with Unix.Unix_error _ as e -> raise (Sys_error (My_std.sbprintf "%a" report_error e)) in { stat_key = sprintf "(%d,%d)" st.Unix.st_dev st.Unix.st_ino; stat_file_kind = match st.Unix.st_kind with | Unix.S_LNK -> FK_link | Unix.S_DIR -> FK_dir | Unix.S_CHR | Unix.S_BLK | Unix.S_FIFO | Unix.S_SOCK -> FK_other | Unix.S_REG -> FK_file } let is_link s = (Unix.lstat s).Unix.st_kind = Unix.S_LNK let at_exit_once callback = let pid = Unix.getpid () in at_exit begin fun () -> if pid = Unix.getpid () then callback () end let run_and_open s kont = let ic = Unix.open_process_in s in let close () = match Unix.close_process_in ic with | Unix.WEXITED 0 -> () | Unix.WEXITED _ | Unix.WSIGNALED _ | Unix.WSTOPPED _ -> failwith (Printf.sprintf "Error while running: %s" s) in let res = try kont ic with e -> (close (); raise e) in close (); res let stdout_isatty () = Unix.isatty Unix.stdout && try Unix.getenv "TERM" <> "dumb" with Not_found -> true let execute_many = let exit i = raise (My_std.Exit_with_code i) in let exit = function | Ocamlbuild_executor.Subcommand_failed -> exit Exit_codes.rc_executor_subcommand_failed | Ocamlbuild_executor.Subcommand_got_signal -> exit Exit_codes.rc_executor_subcommand_got_signal | Ocamlbuild_executor.Io_error -> exit Exit_codes.rc_executor_io_error | Ocamlbuild_executor.Exceptionl_condition -> exit Exit_codes.rc_executor_excetptional_condition in Ocamlbuild_executor.execute ~exit (* Ocamlbuild code assumes throughout that [readlink] will return a file name relative to the current directory. Let's make it so. *) let myunixreadlink x = let y = Unix.readlink x in if Filename.is_relative y then Filename.concat (Filename.dirname x) y else y let setup () = implem.is_degraded <- false; implem.stdout_isatty <- stdout_isatty; implem.gettimeofday <- Unix.gettimeofday; implem.report_error <- report_error; implem.execute_many <- execute_many; implem.readlink <- myunixreadlink; implem.run_and_open <- run_and_open; implem.at_exit_once <- at_exit_once; implem.is_link <- is_link; implem.stat <- mkstat Unix.stat; implem.lstat <- mkstat Unix.lstat;; ocamlbuild-0.14.3/plugin-lib/ocamlbuild_unix_plugin.mli000066400000000000000000000016741454061437200232310ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val setup : unit -> unit ocamlbuild-0.14.3/samples/000077500000000000000000000000001454061437200153645ustar00rootroot00000000000000ocamlbuild-0.14.3/samples/complete-example-menhir-support-in-ocamlbuild/000077500000000000000000000000001454061437200263345ustar00rootroot00000000000000ocamlbuild-0.14.3/samples/complete-example-menhir-support-in-ocamlbuild/Ocaml_tools.ml000066400000000000000000000041331454061437200311420ustar00rootroot00000000000000let menhir_ocamldep_command' tags ~menhir_spec out = let menhir = if !Options.ocamlyacc = N then V"MENHIR" else !Options.ocamlyacc in Cmd(S[menhir; T tags; A"--raw-depend"; A"--ocamldep"; Quote (ocamldep_command' Tags.empty); menhir_spec ; Sh ">"; Px out]) let menhir_ocamldep_command arg out env _build = let arg = env arg and out = env out in let tags = tags_of_pathname arg++"ocaml"++"menhir_ocamldep" in menhir_ocamldep_command' tags ~menhir_spec:(P arg) out let import_mlypack build mlypack = let tags1 = tags_of_pathname mlypack in let files = string_list_of_file mlypack in let include_dirs = Pathname.include_dirs_of (Pathname.dirname mlypack) in let files_alternatives = List.map begin fun module_name -> expand_module include_dirs module_name ["mly"] end files in let files = List.map Outcome.good (build files_alternatives) in let tags2 = List.fold_right (fun file -> Tags.union (tags_of_pathname file)) files tags1 in (tags2, files) let menhir_modular_ocamldep_command mlypack out env build = let mlypack = env mlypack and out = env out in let (tags,files) = import_mlypack build mlypack in let tags = tags++"ocaml"++"menhir_ocamldep" in let menhir_base = Pathname.remove_extensions mlypack in let menhir_spec = S[A "--base" ; P menhir_base ; atomize_paths files] in menhir_ocamldep_command' tags ~menhir_spec out let menhir_modular menhir_base mlypack mlypack_depends env build = let menhir = if !Options.ocamlyacc = N then "menhir" else !Options.ocamlyacc in let menhir_base = env menhir_base in let mlypack = env mlypack in let mlypack_depends = env mlypack_depends in let (tags,files) = import_mlypack build mlypack in let () = List.iter Outcome.ignore_good (build [[mlypack_depends]]) in Ocaml_compiler.prepare_compile build mlypack; let ocamlc_tags = tags++"ocaml"++"byte"++"compile" in let tags = tags++"ocaml"++"parser"++"menhir" in Cmd(S[menhir ; A "--ocamlc"; Quote(S[!Options.ocamlc; T ocamlc_tags; ocaml_include_flags mlypack]); T tags ; A "--base" ; Px menhir_base ; atomize_paths files])ocamlbuild-0.14.3/samples/complete-example-menhir-support-in-ocamlbuild/myocamlbuild.ml000066400000000000000000000031131454061437200313450ustar00rootroot00000000000000rule "ocaml: modular menhir (mlypack)" ~prods:["%.mli" ; "%.ml"] ~deps:["%.mlypack"] ~doc:"Menhir supports building a parser by composing several .mly files \ together, containing different parts of the grammar description. \ To use that feature with ocamlbuild, you should create a .mlypack \ file with the same syntax as .mllib or .mlpack files: \ a whitespace-separated list of the capitalized module names \ of the .mly files you want to combine together." (Ocaml_tools.menhir_modular "%" "%.mlypack" "%.mlypack.depends"); rule "ocaml: menhir modular dependencies" ~prod:"%.mlypack.depends" ~dep:"%.mlypack" (Ocaml_tools.menhir_modular_ocamldep_command "%.mlypack" "%.mlypack.depends"); rule "ocaml: menhir" ~prods:["%.ml"; "%.mli"] ~deps:["%.mly"; "%.mly.depends"] ~doc:"Invokes menhir to build the .ml and .mli files derived from a .mly \ grammar. If you want to use ocamlyacc instead, you must disable the \ -use-menhir option that was passed to ocamlbuild." (Ocaml_tools.menhir "%.mly"); rule "ocaml: menhir dependencies" ~prod:"%.mly.depends" ~dep:"%.mly" (Ocaml_tools.menhir_ocamldep_command "%.mly" "%.mly.depends"); flag ["ocaml"; "menhir"] (atomize !Options.ocaml_yaccflags); flag [ "ocaml" ; "menhir" ; "explain" ] (S[A "--explain"]); flag [ "ocaml" ; "menhir" ; "infer" ] (S[A "--infer"]); List.iter begin fun mode -> flag [ mode; "only_tokens" ] (S[A "--only-tokens"]); pflag [ mode ] "external_tokens" (fun name -> S[A "--external-tokens"; A name]); end [ "menhir"; "menhir_ocamldep" ];ocamlbuild-0.14.3/scripts/000077500000000000000000000000001454061437200154075ustar00rootroot00000000000000ocamlbuild-0.14.3/scripts/cat.ml000066400000000000000000000003071454061437200165100ustar00rootroot00000000000000 let () = let cin = open_in Sys.argv.(1) in begin try while true do print_endline (input_line cin) done; with | End_of_file -> () | _ -> () end; close_in cin ocamlbuild-0.14.3/src/000077500000000000000000000000001454061437200145075ustar00rootroot00000000000000ocamlbuild-0.14.3/src/bool.ml000066400000000000000000000030101454061437200157660ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Bool *) type 'a boolean = And of 'a boolean list | Or of 'a boolean list | Not of 'a boolean | Atom of 'a | True | False;; let rec eval f = function | And l -> List.for_all (eval f) l | Or l -> List.exists (eval f) l | Not x -> not (eval f x) | Atom a -> f a | True -> true | False -> false ;; let rec iter f = function | (And l|Or l) -> List.iter (iter f) l | Not x -> iter f x | Atom a -> f a | True|False -> () ;; let rec map f = function | And l -> And(List.map (map f) l) | Or l -> Or(List.map (map f) l) | Not x -> Not(map f x) | Atom a -> Atom(f a) | (True|False) as b -> b ;; ocamlbuild-0.14.3/src/bool.mli000066400000000000000000000032031454061437200161430ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Bool *) (** Provides a datatype for representing boolean formulas and evaluation, iteration and map functions. *) (** Public type for generic boolean formulas. An empty conjunction [And[]] is true and an empty disjunction [Or[]] is false. *) type 'a boolean = And of 'a boolean list | Or of 'a boolean list | Not of 'a boolean | Atom of 'a | True | False val eval : ('a -> bool) -> 'a boolean -> bool (** [eval g f] evaluates the boolean formula [f] using the values returned by [g] for the atoms. *) val iter : ('a -> unit) -> 'a boolean -> unit (** [iter g f] calls [g] over every atom of [f]. *) val map : ('a -> 'b) -> 'a boolean -> 'b boolean (** [map g f] replaces every atom of [f] by its image by [g]. *) ocamlbuild-0.14.3/src/command.ml000066400000000000000000000311071454061437200164610ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Command *) open My_std open Log type tags = Tags.t type pathname = string let jobs = ref 1 type t = | Seq of t list | Cmd of spec | Echo of string list * pathname | Nop and spec = | N (* nop or nil *) | S of spec list | A of string | P of pathname | Px of pathname | Sh of string | T of Tags.t | V of string | Quote of spec (*type v = [ `Seq of v list | `Cmd of vspec | `Nop ] and vspec = [ `N | `S of vspec list | `A of string | `P of pathname | `Px of pathname | `Sh of string | `Quote of vspec ] let rec spec_of_vspec = function | `N -> N | `S vspecs -> S (List.map spec_of_vspec vspecs) | `A s -> A s | `P s -> P s | `Px s -> Px s | `Sh s -> Sh s | `Quote vspec -> Quote (spec_of_vspec vspec) let rec vspec_of_spec = function | N -> `N | S specs -> `S (List.map vspec_of_spec specs) | A s -> `A s | P s -> `P s | Px s -> `Px s | Sh s -> `Sh s | T _ -> invalid_arg "vspec_of_spec: T not supported" | Quote spec -> `Quote (vspec_of_spec spec) let rec t_of_v = function | `Nop -> Nop | `Cmd vspec -> Cmd (spec_of_vspec vspec) | `Seq cmds -> Seq (List.map t_of_v cmds) let rec v_of_t = function | Nop -> `Nop | Cmd spec -> `Cmd (vspec_of_spec spec) | Seq cmds -> `Seq (List.map v_of_t cmds)*) let no_tag_handler _ = failwith "no_tag_handler" let tag_handler = ref no_tag_handler (*** atomize *) let atomize l = S(List.map (fun x -> A x) l) let atomize_paths l = S(List.map (fun x -> P x) l) (* ***) let env_path = lazy begin let path_var = Sys.getenv "PATH" in let parse_path = if Sys.os_type = "Win32" then Lexers.parse_environment_path_w else Lexers.parse_environment_path in let paths = parse_path Const.Source.path (Lexing.from_string path_var) in let norm_current_dir_name path = if path = "" then Filename.current_dir_name else path in List.map norm_current_dir_name paths end let virtual_solvers = Hashtbl.create 32 let setup_virtual_command_solver virtual_command solver = Hashtbl.replace virtual_solvers virtual_command solver let virtual_solver virtual_command = let solver = try Hashtbl.find virtual_solvers virtual_command with Not_found -> failwith (sbprintf "no solver for the virtual command %S \ (setup one with Command.setup_virtual_command_solver)" virtual_command) in try solver () with Not_found -> failwith (Printf.sprintf "the solver for the virtual command %S \ has failed finding a valid command" virtual_command) (* On Windows, we need to also check for the ".exe" version of the file. *) let file_or_exe_exists file = sys_file_exists file || ((Sys.win32 || Sys.cygwin) && sys_file_exists (file ^ ".exe")) let search_in_path cmd = (* Try to find [cmd] in path [path]. *) let try_path path = (* Don't know why we're trying to be subtle here... *) if path = Filename.current_dir_name then file_or_exe_exists cmd else file_or_exe_exists (filename_concat path cmd) in if Filename.is_implicit cmd then let path = List.find try_path !*env_path in (* We're not trying to append ".exe" here because all windows shells are * capable of understanding the command without the ".exe" suffix. *) filename_concat path cmd else cmd (*** string_of_command_spec{,_with_calls *) let rec string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals spec = let self = string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals in let b = Buffer.create 256 in (* The best way to prevent bash from switching to its windows-style * quote-handling is to prepend an empty string before the command name. *) if Sys.os_type = "Win32" then Buffer.add_string b "''"; let first = ref true in let put_space () = if !first then first := false else Buffer.add_char b ' ' in let put_filename p = Buffer.add_string b (Shell.quote_filename_if_needed p) in let rec do_spec = function | N -> () | A u -> put_space (); put_filename u | Sh u -> put_space (); Buffer.add_string b u | P p -> put_space (); put_filename p | Px u -> put_space (); put_filename u; call_with_target u | V v -> if resolve_virtuals then do_spec (virtual_solver v) else (put_space (); Printf.bprintf b "" (Shell.quote_filename_if_needed v)) | S l -> List.iter do_spec l | T tags -> call_with_tags tags; do_spec (!tag_handler tags) | Quote s -> put_space (); put_filename (self s) in do_spec spec; Buffer.contents b let string_of_command_spec x = string_of_command_spec_with_calls ignore ignore false x let string_target_and_tags_of_command_spec spec = let rtags = ref Tags.empty in let rtarget = ref "" in let union_rtags tags = rtags := Tags.union !rtags tags in let s = string_of_command_spec_with_calls union_rtags ((:=) rtarget) true spec in let target = if !rtarget = "" then s else !rtarget in s, target, !rtags let string_print_of_command_spec spec quiet pretend = let s, target, tags = string_target_and_tags_of_command_spec spec in fun () -> if not quiet then Log.event ~pretend s target tags; s (* ***) let print_escaped_string f = Format.fprintf f "%S" let rec print f = function | Cmd spec -> Format.pp_print_string f (string_of_command_spec spec) | Seq seq -> List.print print f seq | Nop -> Format.pp_print_string f "nop" | Echo(texts, dest_path) -> Format.fprintf f "@[<2>Echo(%a,@ %a)@]" (List.print print_escaped_string) texts print_escaped_string dest_path let to_string x = sbprintf "%a" print x let add_parallel_stat, dump_parallel_stats = let xmin = ref max_int in let xmax = ref 0 in let xsum = ref 0 in let xsumall = ref 0 in let xcount = ref 0 in let xcountall = ref 0 in let add_parallel_stat x = if x > 0 then begin incr xcountall; xsumall := x + !xsumall; end; if x > 1 then begin incr xcount; xsum := x + !xsum; xmax := max !xmax x; xmin := min !xmin x; end in let dump_parallel_stats () = if !jobs <> 1 then if !xcount = 0 then dprintf 1 "# No parallelism done" else let xaverage = float_of_int !xsumall /. float_of_int !xcountall in let xaveragepara = float_of_int !xsum /. float_of_int !xcount in dprintf 1 "# Parallel statistics: { count(total): %d(%d), max: %d, min: %d, average(total): %.3f(%.3f) }" !xcount !xcountall !xmax !xmin xaveragepara xaverage in add_parallel_stat, dump_parallel_stats module Primitives = struct let do_echo texts dest_path = with_output_file dest_path begin fun oc -> List.iter (output_string oc) texts end let echo x y () = (* no print here yet *) do_echo x y; "" end let rec list_rev_iter f = function | [] -> () | x :: xs -> list_rev_iter f xs; f x let flatten_commands quiet pretend cmd = let rec loop acc = function | [] -> acc | Nop :: xs -> loop acc xs | Cmd spec :: xs -> loop (string_print_of_command_spec spec quiet pretend :: acc) xs | Echo(texts, dest_path) :: xs -> loop (Primitives.echo texts dest_path :: acc) xs | Seq l :: xs -> loop (loop acc l) xs in List.rev (loop [] [cmd]) let execute_many ?(quiet=false) ?(pretend=false) cmds = add_parallel_stat (List.length cmds); let degraded = !*My_unix.is_degraded || Sys.os_type = "Win32" in let jobs = !jobs in if jobs < 0 then invalid_arg "jobs < 0"; let max_jobs = if jobs = 0 then None else Some jobs in let ticker = Log.update in let display = Log.display in if cmds = [] then None else begin let konts = List.map (flatten_commands quiet pretend) cmds in if pretend then begin List.iter (List.iter (fun f -> ignore (f ()))) konts; None end else begin reset_filesys_cache (); if degraded then let res, opt_exn = List.fold_left begin fun (acc_res, acc_exn) cmds -> match acc_exn with | None -> begin try List.iter begin fun action -> let cmd = action () in let rc = sys_command cmd in if rc <> 0 then begin if not quiet then eprintf "Exit code %d while executing this \ command:@\n%s" rc cmd; raise (Exit_with_code rc) end end cmds; true :: acc_res, None with e -> false :: acc_res, Some e end | Some _ -> false :: acc_res, acc_exn end ([], None) konts in match opt_exn with | Some(exn) -> Some(List.rev res, exn) | None -> None else My_unix.execute_many ~ticker ?max_jobs ~display konts end end ;; let execute ?quiet ?pretend cmd = match execute_many ?quiet ?pretend [cmd] with | Some(_, exn) -> raise exn | _ -> () let iter_tags f x = let rec spec x = match x with | N | A _ | Sh _ | P _ | Px _ | V _ | Quote _ -> () | S l -> List.iter spec l | T tags -> f tags in let rec cmd x = match x with | Nop | Echo _ -> () | Cmd(s) -> spec s | Seq(s) -> List.iter cmd s in cmd x let fold_pathnames f x = let rec spec = function | N | A _ | Sh _ | V _ | Quote _ | T _ -> fun acc -> acc | P p | Px p -> f p | S l -> List.fold_right spec l in let rec cmd = function | Nop -> fun acc -> acc | Echo(_, p) -> f p | Cmd(s) -> spec s | Seq(s) -> List.fold_right cmd s in cmd x let rec reduce x = let rec self x acc = match x with | N -> acc | A _ | Sh _ | P _ | Px _ | V _ -> x :: acc | S l -> List.fold_right self l acc | T tags -> self (!tag_handler tags) acc | Quote s -> Quote (reduce s) :: acc in match self x [] with | [] -> N | [x] -> x | xs -> S xs let digest = let list = List.fold_right in let text x acc = Digest.string x :: acc in let rec cmd = function | Cmd spec -> fun acc -> string_of_command_spec spec :: acc | Seq seq -> list cmd seq | Nop -> fun acc -> acc | Echo(texts, dest_path) -> list text (dest_path :: texts) in fun x -> match cmd x [] with | [x] -> x | xs -> Digest.string ("[" ^ String.concat ";" xs ^ "]") let all_deps_of_tags = ref [] let cons deps acc = List.rev& List.fold_left begin fun acc dep -> if List.mem dep acc then acc else dep :: acc end acc deps let deps_of_tags tags = List.fold_left begin fun acc (xtags, xdeps) -> if Tags.does_match tags xtags then cons xdeps acc else acc end [] !all_deps_of_tags let set_deps_of_tags tags deps = all_deps_of_tags := (tags, deps) :: !all_deps_of_tags let dep tags deps = set_deps_of_tags (Tags.of_list tags) deps let pdep tags ptag deps = Param_tags.declare ptag (fun param -> dep (Param_tags.make ptag param :: tags) (deps param)) let list_all_deps () = !all_deps_of_tags (* let to_string_for_digest x = let rec cmd_of_spec = function | [] -> None | N :: xs -> cmd_of_spec xs | (A x | P x | P x) :: _ -> Some x | Sh x :: _ -> if Shell.is_simple_filename x then Some x else None (* Sh"ocamlfind ocamlc" for example will not be digested. *) | S specs1 :: specs2 -> cmd_of_spec (specs1 @ specs2) | (T _ | Quote _) :: _ -> assert false in let rec cmd_of_cmds = function | Nop | Seq [] -> None | Cmd spec -> cmd_of_spec [spec] | Seq (cmd :: _) -> cmd_of_cmds cmd in let s = to_string x in match cmd_of_cmds x with | Some x -> if sys_file_exists x then sprintf "(%S,%S)" s (Digest.file x) else s | None -> s *) ocamlbuild-0.14.3/src/command.mli000066400000000000000000000040611454061437200166310ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Command *) (** Provides an abstract type for easily building complex shell commands without making quotation mistakes. *) include Signatures.COMMAND with type tags = Tags.t and type pathname = string (** {6 For system use only, not for the casual user} *) val string_target_and_tags_of_command_spec : spec -> string * string * Tags.t val iter_tags : (Tags.t -> unit) -> t -> unit val fold_pathnames : (pathname -> 'a -> 'a) -> t -> 'a -> 'a (** Digest the given command. *) val digest : t -> Digest.t (** Maximum number of parallel jobs. *) val jobs : int ref (** Hook here the function that maps a set of tags to appropriate command options. It also build the dependencies that matches the tags. *) val tag_handler : (Tags.t -> spec) ref (** For system use only *) val dump_parallel_stats : unit -> unit val deps_of_tags : Tags.t -> pathname list (** [dep tags deps] Will build [deps] when [tags] will be activated. *) val dep : Tags.elt list -> pathname list -> unit val pdep : Tags.elt list -> Tags.elt -> (string -> pathname list) -> unit val list_all_deps : unit -> (Tags.t * pathname list) list val file_or_exe_exists: string -> bool ocamlbuild-0.14.3/src/configuration.ml000066400000000000000000000065001454061437200177110ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Log open Lexers type t = Lexers.conf let acknowledge_config source config = let ack (tag, loc) = Param_tags.acknowledge source (Some loc) tag in List.iter (fun (_, config) -> List.iter ack config.plus_tags) config let cache = Hashtbl.create 107 let (configs, add_config) = let configs = ref [] in (fun () -> !configs), (fun source config -> acknowledge_config source config; configs := config :: !configs; Hashtbl.clear cache) let parse_lexbuf ?dir source lexbuf = let conf = Lexers.conf_lines dir source lexbuf in add_config source conf let parse_string ?source s = let source = match source with | Some source -> source | None -> Const.Source.configuration in parse_lexbuf source (lexbuf_of_string s) let parse_file ?dir file = with_input_file file begin fun ic -> let lexbuf = Lexing.from_channel ic in set_lexbuf_fname file lexbuf; parse_lexbuf ?dir Const.Source.file lexbuf end let key_match = Glob.eval let apply_config s (config : t) init = let add (tag, _loc) = Tags.add tag in let remove (tag, _loc) = Tags.remove tag in List.fold_left begin fun tags (key, v) -> if key_match key s then List.fold_right add v.plus_tags (List.fold_right remove v.minus_tags tags) else tags end init config let apply_configs s = List.fold_right (apply_config s) (configs ()) Tags.empty let tags_of_filename s = try Hashtbl.find cache s with Not_found -> let res = apply_configs s in let () = Hashtbl.replace cache s res in res let global_tags () = tags_of_filename "" let has_tag tag = Tags.mem tag (global_tags ()) let tag_file file tags = if tags <> [] then parse_string (Printf.sprintf "%S: %s" file (String.concat ", " tags));; let tag_any tags = if tags <> [] then parse_string (Printf.sprintf "true: %s" (String.concat ", " tags));; let check_tags_usage useful_tags = let check_tag (tag, loc) = if not (Tags.mem tag useful_tags) then Log.eprintf "%aWarning: the tag %S is not used in any flag or dependency \ declaration, so it will have no effect; it may be a typo. \ Otherwise you can use `mark_tag_used` in your myocamlbuild.ml \ to disable this warning." Loc.print_loc loc tag in let check_conf (_, values) = List.iter check_tag values.plus_tags; List.iter check_tag values.minus_tags; in List.iter (List.iter check_conf) (configs ()) ocamlbuild-0.14.3/src/configuration.mli000066400000000000000000000040571454061437200200670ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Configuration *) (** Handles the "_tags" file mechanism. *) (** Incorporate a newline-separated configuration string into the current configuration. Will usually raising an [Invalid_arg] with an appropriately explicit message in case of error. *) val parse_string : ?source:Loc.source -> string -> unit (** [parse_file ?dir fn] incorporates the configuration file named [fn], prefixing its glob patterns with [dir] if given. *) val parse_file : ?dir:string -> string -> unit (** Return the set of tags that apply to a given filename under the current configuration. *) val tags_of_filename : string -> Tags.t val has_tag : string -> bool (** [tag_file filename tag_list] Tag the given filename with all given tags. *) val tag_file : Pathname.t -> Tags.elt list -> unit (** [tag_any tag_list] Tag anything with all given tags. *) val tag_any : Tags.elt list -> unit (** the tags that apply to any file *) val global_tags : unit -> Tags.t (** Given the list of all tags that are really used by an existing flagset, traverse existing configuration files and warns on tags that will never get used. *) val check_tags_usage : Tags.t -> unit ocamlbuild-0.14.3/src/const.ml000066400000000000000000000005031454061437200161650ustar00rootroot00000000000000module Source = struct let file = "file" let command_line = "command-line" let path = "path" let ocamlfind_query = "ocamlfind query" let ocamldep = "ocamldep" let target_pattern = "target pattern" let builtin = "builtin configuration" let configuration = "configuration" let plugin_tag = "plugin tag" end ocamlbuild-0.14.3/src/digest_cache.ml000066400000000000000000000031161454061437200174440ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Pathname.Operators let digests = Hashtbl.create 103 let get = Hashtbl.find digests let put = Hashtbl.replace digests let _digests = lazy (!Options.build_dir / (Pathname.mk "_digests")) let finalize () = with_output_file !*_digests begin fun oc -> Hashtbl.iter begin fun name digest -> Printf.fprintf oc "%S: %S\n" name digest end digests end let init () = Shell.chdir !Options.build_dir; if Pathname.exists !*_digests then with_input_file !*_digests begin fun ic -> try while true do let l = input_line ic in Scanf.sscanf l "%S: %S" put done with End_of_file -> () end; My_unix.at_exit_once finalize ocamlbuild-0.14.3/src/digest_cache.mli000066400000000000000000000017721454061437200176230ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val init : unit -> unit val get : string -> string val put : string -> string -> unit ocamlbuild-0.14.3/src/discard_printf.ml000066400000000000000000000017501454061437200200370ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) let discard_printf fmt = Format.ifprintf Format.std_formatter fmt;; ocamlbuild-0.14.3/src/discard_printf.mli000066400000000000000000000021531454061437200202060ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Discard_printf *) (** This module compiled with [-rectypes] allows one to write functions taking formatters as arguments. *) open Format val discard_printf: ('a, formatter, unit) format -> 'a ocamlbuild-0.14.3/src/display.ml000066400000000000000000000302551454061437200165130ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Display *) open My_std;; open My_unix;; let fp = Printf.fprintf;; (*** ANSI *) module ANSI = struct let up oc n = fp oc "\027[%dA" n;; let clear_to_eol oc () = fp oc "\027[K";; let bol oc () = fp oc "\r";; let get_columns () = if Sys.os_type = "Unix" then try int_of_string (String.chomp (My_unix.run_and_read "tput cols")) with | Failure _ -> 80 else 80 end ;; (* ***) (*** tagline_description *) type tagline_description = (string * char) list;; (* ***) (*** sophisticated_display *) type sophisticated_display = { ds_channel : out_channel; (** Channel for writing *) ds_start_time : float; (** When was compilation started *) mutable ds_last_update : float; (** When was the display last updated *) mutable ds_last_target : string; (** Last target built *) mutable ds_last_cached : bool; (** Was the last target cached or really built ? *) mutable ds_last_tags : Tags.t; (** Tags of the last command *) mutable ds_changed : bool; (** Does the tag line need recomputing ? *) ds_update_interval : float; (** Minimum interval between updates *) ds_columns : int; (** Number of columns in dssplay *) mutable ds_jobs : int; (** Number of jobs launched or cached *) mutable ds_jobs_cached : int; (** Number of jobs cached *) ds_tagline : bytes; (** Current tagline *) mutable ds_seen_tags : Tags.t; (** Tags that we have encountered *) ds_pathname_length : int; (** How much space for displaying pathnames ? *) ds_tld : tagline_description; (** Description for the tagline *) };; (* ***) (*** display_line, display *) type display_line = | Classic | Sophisticated of sophisticated_display type display = { di_log_level : int; mutable di_log_channel : (Format.formatter * out_channel) option; di_channel : out_channel; di_formatter : Format.formatter; di_display_line : display_line; mutable di_finished : bool; } ;; (* ***) (*** various defaults *) let default_update_interval = 0.05;; let default_tagline_description = [ "ocaml", 'O'; "native", 'N'; "byte", 'B'; "program", 'P'; "pp", 'R'; "debug", 'D'; "interf", 'I'; "link", 'L'; ];; (* NOT including spaces *) let countdown_chars = 8;; let jobs_chars = 3;; let jobs_cached_chars = 5;; let dots = "...";; let start_target = "STARTING";; let finish_target = "FINISHED";; let ticker_chars = 3;; let ticker_period = 0.25;; let ticker_animation = [| "\\"; "|"; "/"; "-"; |];; let cached = "*";; let uncached = " ";; let cache_chars = 1;; (* ***) (*** create_tagline *) let create_tagline description = Bytes.make (List.length description) '-';; (* ***) (*** create *) let create ?(channel=stdout) ?(mode:[`Classic|`Sophisticated] = `Sophisticated) ?columns:(_columns=75) ?(description = default_tagline_description) ?log_file ?(log_level=1) () = let log_channel = match log_file with | None -> None | Some fn -> let oc = open_out_gen [Open_text; Open_wronly; Open_creat; Open_trunc] 0o666 fn in let f = Format.formatter_of_out_channel oc in Format.fprintf f "### Starting build.\n"; Some (f, oc) in let display_line = match mode with | `Classic -> Classic | `Sophisticated -> (* We assume Unix is not degraded. *) let n = ANSI.get_columns () in let tag_chars = List.length description in Sophisticated { ds_channel = stdout; ds_start_time = gettimeofday (); ds_last_update = 0.0; ds_last_target = start_target; ds_last_tags = Tags.empty; ds_last_cached = false; ds_changed = false; ds_update_interval = default_update_interval; ds_columns = n; ds_jobs = 0; ds_jobs_cached = 0; ds_tagline = create_tagline description; ds_seen_tags = Tags.empty; ds_pathname_length = n - (countdown_chars + 1 + jobs_chars + 1 + jobs_cached_chars + 1 + cache_chars + 1 + tag_chars + 1 + ticker_chars + 2); ds_tld = description } in { di_log_level = log_level; di_log_channel = log_channel; di_channel = channel; di_formatter = Format.formatter_of_out_channel channel; di_display_line = display_line; di_finished = false } ;; (* ***) (*** print_time *) let print_time oc t = let t = int_of_float t in let s = t mod 60 in let m = (t / 60) mod 60 in let h = t / 3600 in fp oc "%02d:%02d:%02d" h m s ;; (* ***) (*** print_shortened_pathname *) let print_shortened_pathname length oc u = assert(length >= 3); let m = String.length u in if m <= length then begin output_string oc u; fp oc "%*s" (length - m) "" end else begin let n = String.length dots in let k = length - n in output_string oc dots; output_substring oc u (m - k) k; end (* ***) (*** Layout 00000000001111111111222222222233333333334444444444555555555566666666667777777777 01234567890123456789012345678901234567890123456789012345678901234567890123456789 HH MM SS XXXX PATHNAME 00:12:31 32 ( 26) ...lp4Filters/Camlp4LocationStripper.cmo * OBn------------- | | | | | \ tags | | | \ last target built \ cached ? | | | | | \ number of jobs cached | \ number of jobs \ elapsed time cmo mllib ***) (*** redraw_sophisticated *) let redraw_sophisticated ds = let t = gettimeofday () in let oc = ds.ds_channel in let dt = t -. ds.ds_start_time in ds.ds_last_update <- t; fp oc "%a" ANSI.bol (); let ticker_phase = (abs (int_of_float (ceil (dt /. ticker_period)))) mod (Array.length ticker_animation) in let ticker = ticker_animation.(ticker_phase) in fp oc "%a %-4d (%-4d) %a %s %s %s" print_time dt ds.ds_jobs ds.ds_jobs_cached (print_shortened_pathname ds.ds_pathname_length) ds.ds_last_target (if ds.ds_last_cached then cached else uncached) (Bytes.to_string ds.ds_tagline) ticker; fp oc "%a%!" ANSI.clear_to_eol () ;; (* ***) (*** redraw *) let redraw = function | Classic -> () | Sophisticated ds -> redraw_sophisticated ds ;; (* ***) (*** finish_sophisticated *) let finish_sophisticated ?(how=`Success) ds = let t = gettimeofday () in let oc = ds.ds_channel in let dt = t -. ds.ds_start_time in match how with | `Success|`Error -> fp oc "%a" ANSI.bol (); fp oc "%s %d target%s (%d cached) in %a." (if how = `Error then "Compilation unsuccessful after building" else "Finished,") ds.ds_jobs (if ds.ds_jobs = 1 then "" else "s") ds.ds_jobs_cached print_time dt; fp oc "%a\n%!" ANSI.clear_to_eol () | `Quiet -> fp oc "%a%a%!" ANSI.bol () ANSI.clear_to_eol (); ;; (* ***) (*** sophisticated_display *) let sophisticated_display ds f = fp ds.ds_channel "%a%a%!" ANSI.bol () ANSI.clear_to_eol (); f ds.ds_channel ;; (* ***) (*** call_if *) let call_if log_channel f = match log_channel with | None -> () | Some x -> f x ;; (* ***) (*** display *) let display di f = call_if di.di_log_channel (fun (_, oc) -> f oc); match di.di_display_line with | Classic -> f di.di_channel | Sophisticated ds -> sophisticated_display ds f ;; (* ***) (*** finish *) let finish ?(how=`Success) di = if not di.di_finished then begin di.di_finished <- true; call_if di.di_log_channel begin fun (fmt, oc) -> Format.fprintf fmt "# Compilation %ssuccessful.@." (if how = `Error then "un" else ""); close_out oc; di.di_log_channel <- None end; match di.di_display_line with | Classic -> () | Sophisticated ds -> finish_sophisticated ~how ds end ;; (* ***) (*** update_tagline_from_tags *) let update_tagline_from_tags ds = let tagline = ds.ds_tagline in let tags = ds.ds_last_tags in let rec loop i = function | [] -> for j = i to Bytes.length tagline - 1 do Bytes.set tagline j '-' done | (tag, c) :: rest -> if Tags.mem tag tags then Bytes.set tagline i (Char.uppercase_ascii c) else if Tags.mem tag ds.ds_seen_tags then Bytes.set tagline i (Char.lowercase_ascii c) else Bytes.set tagline i '-'; loop (i + 1) rest in loop 0 ds.ds_tld; ;; (* ***) (*** update_sophisticated *) let update_sophisticated ds = let t = gettimeofday () in let dt = t -. ds.ds_last_update in if dt > ds.ds_update_interval then begin if ds.ds_changed then begin update_tagline_from_tags ds; ds.ds_changed <- false end; redraw_sophisticated ds end else () ;; (* ***) (*** set_target_sophisticated *) let set_target_sophisticated ds target tags cached = ds.ds_changed <- true; ds.ds_last_target <- target; ds.ds_last_tags <- tags; ds.ds_jobs <- 1 + ds.ds_jobs; if cached then ds.ds_jobs_cached <- 1 + ds.ds_jobs_cached; ds.ds_last_cached <- cached; ds.ds_seen_tags <- Tags.union ds.ds_seen_tags ds.ds_last_tags; update_sophisticated ds ;; let print_tags f tags = let first = ref true in Tags.iter begin fun tag -> if !first then begin first := false; Format.fprintf f "%s" tag end else Format.fprintf f ", %s" tag end tags ;; (* ***) (*** update *) let update di = match di.di_display_line with | Classic -> () | Sophisticated ds -> update_sophisticated ds ;; (* ***) (*** event *) let event di ?(pretend=false) command target tags = call_if di.di_log_channel (fun (fmt, _) -> Format.fprintf fmt "# Target: %s, tags: { %a }\n" target print_tags tags; Format.fprintf fmt "%s%s@." command (if pretend then " # cached" else "")); match di.di_display_line with | Classic -> if pretend then begin (* This should work, even on Windows *) let command = Filename.basename command in if di.di_log_level >= 2 then Format.fprintf di.di_formatter "[cache hit] %s\n%!" command end else (if di.di_log_level >= 1 then Format.fprintf di.di_formatter "%s\n%!" command) | Sophisticated ds -> set_target_sophisticated ds target tags pretend; update_sophisticated ds ;; (* ***) (*** dprintf *) let is_logging di log_level = log_level <= di.di_log_level let dprintf ?(raw=false) ?(log_level=1) di fmt = if log_level > di.di_log_level then Discard_printf.discard_printf fmt else let fmt = if raw then fmt else "@[<2>"^^fmt^^"@]@." in match di.di_display_line with | Classic -> Format.fprintf di.di_formatter fmt | Sophisticated _ -> if log_level < 0 then begin display di ignore; Format.fprintf di.di_formatter fmt end else match di.di_log_channel with | Some (f, _) -> Format.fprintf f fmt | None -> Discard_printf.discard_printf fmt (* ***) ocamlbuild-0.14.3/src/display.mli000066400000000000000000000030301454061437200166530ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Display *) type display type tagline_description = (string * char) list val create : ?channel:out_channel -> ?mode:[ `Classic | `Sophisticated ] -> ?columns:int -> ?description:tagline_description -> ?log_file:string -> ?log_level:int -> unit -> display val finish : ?how:[`Success|`Error|`Quiet] -> display -> unit val event : display -> ?pretend:bool -> string -> string -> Tags.t -> unit val display : display -> (out_channel -> unit) -> unit val update : display -> unit val is_logging : display -> int -> bool val dprintf : ?raw:bool -> ?log_level:int -> display -> ('a, Format.formatter, unit) format -> 'a ocamlbuild-0.14.3/src/exit_codes.ml000066400000000000000000000030021454061437200171620ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let rc_ok = 0 let rc_usage = 1 let rc_failure = 2 let rc_invalid_argument = 3 let rc_system_error = 4 let rc_hygiene = 1 let rc_circularity = 5 let rc_solver_failed = 6 let rc_ocamldep_error = 7 let rc_lexing_error = 8 let rc_build_error = 9 let rc_executor_subcommand_failed = 10 let rc_executor_subcommand_got_signal = 11 let rc_executor_io_error = 12 let rc_executor_excetptional_condition = 13 ocamlbuild-0.14.3/src/exit_codes.mli000066400000000000000000000030341454061437200173400ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val rc_ok : int val rc_usage : int val rc_failure : int val rc_invalid_argument : int val rc_system_error : int val rc_hygiene : int val rc_circularity : int val rc_solver_failed : int val rc_ocamldep_error : int val rc_lexing_error : int val rc_build_error : int val rc_executor_subcommand_failed : int val rc_executor_subcommand_got_signal : int val rc_executor_io_error : int val rc_executor_excetptional_condition : int ocamlbuild-0.14.3/src/fda.ml000066400000000000000000000053721454061437200156020ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* FDA *) open Log open Hygiene ;; exception Exit_hygiene_failed ;; let laws = [ { law_name = "Leftover OCaml compilation files"; law_rules = [Not ".cmo"; Not ".cmi"; Not ".cmx"; Not ".cma"; Not ".cmxa"]; law_penalty = Fail }; { law_name = "Leftover OCaml type annotation files"; law_rules = [Not ".annot"]; law_penalty = Warn }; { law_name = "Leftover object files"; law_rules = [Not ".o"; Not ".a"; Not ".so"; Not ".obj"; Not ".lib"; Not ".dll"]; law_penalty = Fail }; { law_name = "Leftover ocamlyacc-generated files"; law_rules = [Implies_not(".mly",".ml"); Implies_not(".mly",".mli")]; law_penalty = Fail }; { law_name = "Leftover ocamllex-generated files"; law_rules = [Implies_not(".mll",".ml")]; law_penalty = Fail }; { law_name = "Leftover dependency files"; law_rules = [Not ".ml.depends"; Not ".mli.depends"]; law_penalty = Fail } ] let inspect entry = dprintf 5 "Doing sanity checks"; let evil = ref false in match Hygiene.check ?sanitize: begin if !Options.sanitize then Some(Pathname.concat !Options.build_dir !Options.sanitization_script) else None end laws entry with | [] -> () | stuff -> List.iter begin fun (law, msgs) -> Printf.printf "%s: %s:\n" (match law.law_penalty with | Warn -> "Warning" | Fail -> if not !evil then begin Printf.printf "IMPORTANT: I cannot work with leftover compiled files.\n%!"; evil := true end; "ERROR") law.law_name; List.iter begin fun msg -> Printf.printf " %s\n" msg end msgs end stuff; if !evil then raise Exit_hygiene_failed; ;; ocamlbuild-0.14.3/src/fda.mli000066400000000000000000000017561454061437200157550ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Fda *) exception Exit_hygiene_failed val inspect : bool Slurp.entry -> unit ocamlbuild-0.14.3/src/findlib.ml000066400000000000000000000134531454061437200164560ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Romain Bardou *) open My_std open My_unix open Command type command_spec = Command.spec type error = | Cannot_run_ocamlfind | Dependency_not_found of string * string (* package, dependency *) | Package_not_found of string | Cannot_parse_query of string * string (* package, explaination *) exception Findlib_error of error let error x = raise (Findlib_error x) let string_of_error = function | Cannot_run_ocamlfind -> "Cannot run Ocamlfind." | Dependency_not_found(p, d) -> Printf.sprintf "Ocamlfind returned \"%s\" as a dependency for package \"%s\" but does \ not know this dependency." d p | Package_not_found p -> Printf.sprintf "Findlib package not found: \"%s\"." p | Cannot_parse_query(p, e) -> Printf.sprintf "Cannot parse Ocamlfind query for package \"%s\": %s" p e let report_error e = prerr_endline (string_of_error e); exit 2 let ocamlfind = "ocamlfind" type package = { name: string; description: string; version: string; archives_byte: string; archives_native: string; link_options: string; location: string; dependencies: package list; } let packages = Hashtbl.create 42 let run_and_parse lexer command = Printf.ksprintf (fun command -> lexer & Lexing.from_string & run_and_read command) command let run_and_read command = Printf.ksprintf run_and_read command let rec query name = try Hashtbl.find packages name with Not_found -> try let n, d, v, a_byte, lo, l = run_and_parse (Lexers.ocamlfind_query Const.Source.ocamlfind_query) "%s query -l -predicates byte %s" ocamlfind name in let a_native = run_and_parse (Lexers.trim_blanks Const.Source.ocamlfind_query) "%s query -a-format -predicates native %s" ocamlfind name in let deps = run_and_parse (Lexers.blank_sep_strings Const.Source.ocamlfind_query) "%s query -r -p-format %s" ocamlfind name in let deps = List.filter ((<>) n) deps in let deps = try List.map query deps with Findlib_error (Package_not_found dep_name) -> (* Ocamlfind cannot find a package which it returned as a dependency. This should not happen. *) error (Dependency_not_found (name, dep_name)) in let package = { name = n; description = d; version = v; archives_byte = a_byte; archives_native = a_native; link_options = lo; location = l; dependencies = deps; } in Hashtbl.add packages n package; package with | Failure _ -> (* TODO: Improve to differenciate whether ocamlfind cannot be run or is not installed *) error Cannot_run_ocamlfind | Lexers.Error (s,_) -> error (Cannot_parse_query (name, s)) let split_nl s = let x = ref [] in let rec go s = let pos = String.index s '\n' in x := (String.before s pos)::!x; go (String.after s (pos + 1)) in try go s with Not_found -> !x let before_space s = try String.before s (String.index s ' ') with Not_found -> s let list () = List.map before_space (split_nl & run_and_read "%s list" ocamlfind) (* The closure algorithm is easy because the dependencies are already closed and sorted for each package. We only have to make the union. We could also make another ocamlfind query such as: ocamlfind query -p-format -r package1 package2 ... *) let topological_closure l = let add l x = if List.mem x l then l else x :: l in let l = List.fold_left begin fun acc p -> add (List.fold_left add acc p.dependencies) p end [] l in List.rev l module SSet = Set.Make(String) let add_atom a l = match a, l with | A "", _ -> l | _ -> a :: l let include_flags l = let pkgs = topological_closure l in let locations = List.fold_left begin fun acc p -> SSet.add p.location acc end SSet.empty pkgs in let flags = [] in (* includes *) let flags = List.fold_left begin fun acc l -> add_atom (P l) (add_atom (A "-I") acc) end flags (SSet.elements locations) in S (List.rev flags) let compile_flags_byte = include_flags let compile_flags_native = include_flags let link_flags f l = let pkgs = topological_closure l in let locations = List.fold_left begin fun acc p -> SSet.add p.location acc end SSet.empty pkgs in let flags = [] in (* includes *) let flags = List.fold_left begin fun acc l -> add_atom (P l) (add_atom (A "-I") acc) end flags (SSet.elements locations) in (* special link options *) let flags = List.fold_left begin fun acc x -> add_atom (A x.link_options) acc end flags pkgs in (* archives *) let flags = List.fold_left begin fun acc x -> add_atom (A (f x)) acc end flags pkgs in S (List.rev flags) let link_flags_byte = link_flags (fun x -> x.archives_byte) let link_flags_native = link_flags (fun x -> x.archives_native) ocamlbuild-0.14.3/src/findlib.mli000066400000000000000000000017411454061437200166240ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Romain Bardou *) include Signatures.FINDLIB with type command_spec = Command.spec ocamlbuild-0.14.3/src/flags.ml000066400000000000000000000072121454061437200161370ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open Command open Bool (* FIXME remove me *) open Tags.Operators type decl = { tags: Tags.t; flags: Command.spec; deprecated: bool; } let flags_of_decl { flags; _ } = flags let tags_of_decl { tags; _ } = tags let all_decls = ref [] let of_tags matched_tags = S begin List.fold_left begin fun acc { tags; flags; _ } -> if Tags.does_match matched_tags tags then flags :: acc else acc end [] !all_decls end let () = Command.tag_handler := of_tags let of_tag_list x = of_tags (Tags.of_list x) let add_decl decl = all_decls := decl :: !all_decls let flag ?(deprecated=false) tags flags = let tags = Tags.of_list tags in add_decl { tags; flags; deprecated } type pflag_doc = Tags.elt list * Tags.elt * string option * (string -> Command.spec) let pflags_doc = ref ([] : pflag_doc list) let pflag tags ptag ?doc_param flags = pflags_doc := (tags, ptag, doc_param, flags) :: !pflags_doc; Param_tags.declare ptag (fun param -> flag (Param_tags.make ptag param :: tags) (flags param)) let flag_and_dep tags cmd_spec = flag tags cmd_spec; let ps = Command.fold_pathnames (fun p ps -> p :: ps) (Cmd cmd_spec) [] in Command.dep tags ps let pflag_and_dep tags ptag ?doc_param cmd_spec = pflags_doc := (tags, ptag, doc_param, cmd_spec) :: !pflags_doc; Param_tags.declare ptag (fun param -> flag_and_dep (Param_tags.make ptag param :: tags) (cmd_spec param)) let add x xs = x :: xs let remove me = List.filter (fun x -> me <> x) let pretty_print header tags sflag = let pp fmt = Log.raw_dprintf (-1) fmt in pp "@[<2>%s@ {. %a .}@ %S@]@\n@\n" header Tags.print tags sflag let pretty_print_flag { tags; flags; deprecated } = let sflag = Command.string_of_command_spec flags in let header = if deprecated then "deprecated flag" else "flag" in pretty_print header tags sflag let pretty_print_pflag (tags, ptag, doc_param, flags) = let header = "parametrized flag" in let doc_param = match doc_param with | None -> "X" | Some param -> param in let tags = Tags.of_list (Param_tags.make ptag doc_param :: tags) in let sflag = try Command.string_of_command_spec (flags doc_param) with exn -> Printf.sprintf "" (Printexc.to_string exn) in pretty_print header tags sflag let show_documentation () = List.iter pretty_print_pflag !pflags_doc; let not_deprecated, deprecated = List.partition (fun d -> d.deprecated) !all_decls in List.iter pretty_print_flag not_deprecated; List.iter pretty_print_flag deprecated; Log.raw_dprintf (-1) "@." let used_tags = ref Tags.empty let mark_tag_used tag = used_tags := Tags.add tag !used_tags let get_used_tags () = List.fold_left (fun acc decl -> Tags.union acc decl.tags) !used_tags !all_decls ocamlbuild-0.14.3/src/flags.mli000066400000000000000000000054741454061437200163200ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val of_tags : Tags.t -> Command.spec val of_tag_list : Tags.elt list -> Command.spec (* The ?deprecated parameter marks the flag declaration as deprecated, because it is superseded by a different, better way to express the same thing (eg. a parametrized tag). So far, it is only used when showing documentation. This flag is not exported in OCamlbuild_plugin interface for now. It would make sense to let plugin authors deprecate their own flags, but it has to be balanced again the simplicity of the plugin interface exposed. If you're reading this as a plugin author that has a real need for deprecation, drop us a note on the bugtracker. *) val flag : ?deprecated:bool -> Tags.elt list -> Command.spec -> unit (* The ?doc_param parameter provides an example parameter that will be used to generate documentation for this parametrized flag: we invoke the parametrized rule with this parameter, and give the documentation for the resulting spec. If no parameter is provided, we will not invoke the parametrized commands (which may in general perform arbitrary side-effects, or at least fail to parse a dummy parameter), but just list its activation tags in the documentation -- so users will still be aware of its existence. As for the ?deprecated flag above, this is not exported to the plugin interface for now. *) val pflag : Tags.elt list -> string -> ?doc_param:string -> (string -> Command.spec) -> unit val flag_and_dep : Tags.elt list -> Command.spec -> unit val pflag_and_dep : Tags.elt list -> Tags.elt -> ?doc_param:string -> (string -> Command.spec) -> unit val add : 'a -> 'a list -> 'a list val remove : 'a -> 'a list -> 'a list val show_documentation : unit -> unit (** "useful" tags: they are used by a tag declaration, or have been explicitly added with [mark_as_used] *) val get_used_tags : unit -> Tags.t val mark_tag_used : Tags.elt -> unit ocamlbuild-0.14.3/src/glob.ml000066400000000000000000000267461454061437200160030ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Glob *) open My_std;; open Bool;; include Glob_ast;; open Glob_lexer;; let sf = Printf.sprintf;; let brute_limit = 10;; (*** string_of_token *) let string_of_token = function | ATOM _ -> "ATOM" | AND -> "AND" | OR -> "OR" | NOT -> "NOT" | LPAR -> "LPAR" | RPAR -> "RPAR" | TRUE -> "TRUE" | FALSE -> "FALSE" | EOF -> "EOF" ;; (* ***) (*** match_character_class *) let match_character_class cl c = Bool.eval begin function (c1,c2) -> c1 <= c && c <= c2 end cl ;; (* ***) (*** NFA *) module NFA = struct type transition = | QCLASS of character_class | QEPSILON ;; module IS = Set.Make(struct type t = int let compare (x:t) y = compare x y let print = Format.pp_print_int end);; module ISM = Map.Make(struct type t = IS.t let compare = IS.compare let print = IS.print end);; type machine = { mc_qi : IS.t; mc_table : (character_class * IS.t) list array; mc_qf : int; mc_power_table : (char, IS.t ISM.t) Hashtbl.t } (*** build' *) let build' p = let count = ref 0 in let transitions = ref [] in let epsilons : (int * int) list ref = ref [] in let state () = let id = !count in incr count; id in let ( --> ) q1 t q2 = match t with | QEPSILON -> epsilons := (q1,q2) :: !epsilons; q1 | QCLASS cl -> transitions := (q1,cl,q2) :: !transitions; q1 in (* Build the transitions corresponding to the given pattern and arriving * on state qf. Return the original state. *) let rec loop qf = function | Epsilon -> qf | Word u -> let m = String.length u in let q0 = state () in let rec loop q i = if i = m then q0 else begin let q' = if i = m - 1 then qf else state () in let _ = (q --> QCLASS(Atom(u.[i], u.[i]))) q' in loop q' (i + 1) end in loop q0 0 | Class cl -> let q1 = state () in (q1 --> QCLASS cl) qf | Star p -> (* The fucking Kleene star *) let q2 = state () in let q1 = loop q2 p in (* q1 -{p}-> q2 *) let _ = (q1 --> QEPSILON) qf in let _ = (q2 --> QEPSILON) q1 in let _ = (q2 --> QEPSILON) q1 in q1 | Concat(p1,p2) -> let q12 = state () in let q1 = loop q12 p1 in (* q1 -{p1}-> q12 *) let q2 = loop qf p2 in (* q2 -{p2}-> qf *) let _ = (q12 --> QEPSILON) q2 in q1 | Union pl -> let qi = state () in List.iter begin fun p -> let q = loop qf p in (* q -{p2}-> qf *) let _ = (qi --> QEPSILON) q in (* qi -{}---> q *) () end pl; qi in let qf = state () in let qi = loop qf p in let m = !count in (* Compute epsilon closure *) let graph = Array.make m IS.empty in List.iter begin fun (q,q') -> graph.(q) <- IS.add q' graph.(q) end !epsilons; let closure = Array.make m IS.empty in let rec transitive past = function | [] -> past | q :: future -> let past' = IS.add q past in let future' = IS.fold begin fun q' future' -> (* q -{}--> q' *) if IS.mem q' past' then future' else q' :: future' end graph.(q) future in transitive past' future' in for i = 0 to m - 1 do closure.(i) <- transitive IS.empty [i] (* O(n^2), I know *) done; (* Finally, build the table *) let table = Array.make m [] in List.iter begin fun (q,t,q') -> table.(q) <- (t, closure.(q')) :: table.(q) end !transitions; (graph, closure, { mc_qi = closure.(qi); mc_table = table; mc_qf = qf; mc_power_table = Hashtbl.create 37 }) ;; let build x = let (_,_, machine) = build' x in machine;; (* ***) (*** run *) let run ?(trace=false) machine u = let m = String.length u in let apply qs c = try let t = Hashtbl.find machine.mc_power_table c in ISM.find qs t with | Not_found -> let qs' = IS.fold begin fun q qs' -> List.fold_left begin fun qs' (cl,qs'') -> if match_character_class cl c then IS.union qs' qs'' else qs' end qs' machine.mc_table.(q) end qs IS.empty in let t = try Hashtbl.find machine.mc_power_table c with | Not_found -> ISM.empty in Hashtbl.replace machine.mc_power_table c (ISM.add qs qs' t); qs' in let rec loop qs i = if IS.is_empty qs then false else begin if i = m then IS.mem machine.mc_qf qs else begin let c = u.[i] in if trace then begin Printf.printf "%d %C {" i c; IS.iter (fun q -> Printf.printf " %d" q) qs; Printf.printf " }\n%!" end; let qs' = apply qs c in loop qs' (i + 1) end end in loop machine.mc_qi 0 ;; (* ***) end ;; (* ***) (*** Brute *) module Brute = struct exception Succeed;; exception Fail;; exception Too_hard;; (*** match_pattern *) let match_pattern counter p u = let m = String.length u in (** [loop i n p] returns [true] iff the word [u.(i .. i + n - 1)] is in the ** language generated by the pattern [p]. ** We must have 0 <= i and i + n <= m *) let rec loop (i,n,p) = assert (0 <= i && 0 <= n && i + n <= m); incr counter; if !counter >= brute_limit then raise Too_hard; match p with | Word v -> String.length v = n && begin let rec check j = j = n || (v.[j] = u.[i + j] && check (j + 1)) in check 0 end | Epsilon -> n = 0 | Star(Class True) -> true | Star(Class cl) -> let rec check k = if k = n then true else (match_character_class cl u.[i + k]) && check (k + 1) in check 0 | Star _ -> raise Too_hard | Class cl -> n = 1 && match_character_class cl u.[i] | Concat(p1,p2) -> let rec scan j = j <= n && ((loop (i,j,p1) && loop (i+j, n - j,p2)) || scan (j + 1)) in scan 0 | Union pl -> List.exists (fun p' -> loop (i,n,p')) pl in loop (0,m,p) ;; (* ***) end ;; (* ***) (*** fast_pattern_contents, fast_pattern, globber *) type fast_pattern_contents = | Brute of int ref * pattern | Machine of NFA.machine ;; type fast_pattern = fast_pattern_contents ref;; type globber = fast_pattern atom Bool.boolean;; (* ***) (*** fast_pattern_of_pattern *) let fast_pattern_of_pattern p = ref (Brute(ref 0, p));; (* ***) (*** add_dir *) let add_dir dir x = match dir with | None -> x | Some(dir) -> match x with | Constant(s) -> Constant(My_std.filename_concat dir s) | Pattern(p) -> Pattern(Concat(Word(My_std.filename_concat dir ""), p)) ;; (* ***) (*** add_ast_dir *) let add_ast_dir dir x = match dir with | None -> x | Some dir -> let slash = Class(Atom('/','/')) in let any = Class True in let q = Union[Epsilon; Concat(slash, Star any)] in (* ( /** )? *) And[Atom(Pattern(ref (Brute(ref 0, Concat(Word dir, q))))); x] ;; (* ***) (*** parse *) let parse ?dir u = let l = Lexing.from_string u in let tok = ref None in let f = fun () -> match !tok with | None -> token l | Some x -> tok := None; x in let g t = match !tok with | None -> tok := Some t | Some t' -> raise (Parse_error(sf "Trying to unput token %s while %s is active" (string_of_token t) (string_of_token t'))) in let read x = let y = f () in if x = y then () else raise (Parse_error(sf "Unexpected token, expecting %s, got %s" (string_of_token x) (string_of_token y))) in let rec atomizer continuation = match f () with | NOT -> atomizer (fun x -> continuation (Not x)) | ATOM x -> begin let a = match add_dir dir x with | Constant u -> Constant u | Pattern p -> Pattern(fast_pattern_of_pattern p) in continuation (Atom a) end | TRUE -> continuation True | FALSE -> continuation False | LPAR -> let y = parse_s () in read RPAR; continuation y | t -> raise (Parse_error(sf "Unexpected token %s in atomizer" (string_of_token t))) and parse_s1 x = match f () with | OR -> let y = parse_s () in Or[x; y] | AND -> parse_t x | t -> g t; x and parse_t1 x y = match f () with | OR -> let z = parse_s () in Or[And[x;y]; z] | AND -> parse_t (And[x;y]) | t -> g t; And[x;y] and parse_s () = atomizer parse_s1 and parse_t x = atomizer (parse_t1 x) in let x = parse_s () in read EOF; add_ast_dir dir x ;; (* ***) (*** eval *) let eval g u = Bool.eval begin function | Constant v -> u = v | Pattern kind -> match !kind with | Brute(count, p) -> begin let do_nfa () = let m = NFA.build p in kind := Machine m; NFA.run m u in if !count >= brute_limit then do_nfa () else try Brute.match_pattern count p u with | Brute.Too_hard -> do_nfa () end | Machine m -> NFA.run m u end g (* ***) (*** Debug *) (*let (Atom(Pattern x)) = parse "<{a,b}>";; #install_printer IS.print;; #install_printer ISM.print;; let (graph, closure, machine) = build' x;;*) (* ***) ocamlbuild-0.14.3/src/glob.mli000066400000000000000000000025441454061437200161420ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Glob *) (** The type representing fast patterns. Do not attempt to compare them, as they get on-the-fly optimizations. *) type fast_pattern (** A self-contained module implementing extended shell glob patterns who have an expressive power equal to boolean combinations of regular expressions. *) include Signatures.GLOB with type globber = fast_pattern Glob_ast.atom Bool.boolean val fast_pattern_of_pattern : Glob_ast.pattern -> fast_pattern ocamlbuild-0.14.3/src/glob_ast.ml000066400000000000000000000023631454061437200166370ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Glob_ast *) exception Parse_error of string;; type pattern = | Epsilon | Star of pattern (* The fucking Kleene star *) | Class of character_class | Concat of pattern * pattern | Union of pattern list | Word of string and character_class = (char * char) Bool.boolean ;; type 'pattern atom = | Constant of string | Pattern of 'pattern ;; ocamlbuild-0.14.3/src/glob_ast.mli000066400000000000000000000023111454061437200170010ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Glob_ast *) exception Parse_error of string type pattern = | Epsilon | Star of pattern | Class of character_class | Concat of pattern * pattern | Union of pattern list | Word of string and character_class = (char * char) Bool.boolean type 'pattern atom = Constant of string | Pattern of 'pattern ocamlbuild-0.14.3/src/glob_lexer.mli000066400000000000000000000020501454061437200173310ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) open Glob_ast type token = | ATOM of pattern atom | AND | OR | NOT | LPAR | RPAR | TRUE | FALSE | EOF val token : Lexing.lexbuf -> token ocamlbuild-0.14.3/src/glob_lexer.mll000066400000000000000000000077121454061437200173460ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Glob *) { open Bool;; open Glob_ast;; type token = | ATOM of pattern atom | AND | OR | NOT | LPAR | RPAR | TRUE | FALSE | EOF ;; let sf = Printf.sprintf;; let concat_patterns p1 p2 = match (p1,p2) with | (Epsilon,_) -> p2 | (_,Epsilon) -> p1 | (_,_) -> Concat(p1,p2) ;; let slash = Class(Atom('/','/'));; let not_slash = Class(Not(Atom('/','/')));; let any = Class True;; } let pattern_chars = ['a'-'z']|['A'-'Z']|'_'|'-'|['0'-'9']|'.' let space_chars = [' ' '\t' '\n' '\r' '\012'] rule token = parse | '<' { ATOM(Pattern(let (p,_) = parse_pattern ['>'] Epsilon lexbuf in p)) } | '"' { ATOM(Constant(parse_string (Buffer.create 32) lexbuf)) } | "and"|"AND"|"&" { AND } | "or"|"OR"|"|" { OR } | "not"|"NOT"|"~" { NOT } | "true"|"1" { TRUE } | "false"|"0" { FALSE } | "(" { LPAR } | ")" { RPAR } | space_chars+ { token lexbuf } | eof { EOF } and parse_pattern eof_chars p = parse | (pattern_chars+ as u) { parse_pattern eof_chars (concat_patterns p (Word u)) lexbuf } | '{' { let rec loop pl = let (p',c) = parse_pattern ['}';','] Epsilon lexbuf in let pl = p' :: pl in if c = ',' then loop pl else parse_pattern eof_chars (concat_patterns p (Union pl)) lexbuf in loop [] } | "[^" { let cl = Not(Or(parse_class [] lexbuf)) in parse_pattern eof_chars (concat_patterns p (Class cl)) lexbuf } | '[' { let cl = Or(parse_class [] lexbuf) in parse_pattern eof_chars (concat_patterns p (Class cl)) lexbuf } (* Random thought... **/* seems to be equal to True *) | "/**/" (* / | /\Sigma^*/ *) { let q = Union[slash; Concat(slash, Concat(Star any, slash)) ] in parse_pattern eof_chars (concat_patterns p q) lexbuf } | "/**" (* \varepsilon | /\Sigma^* *) { let q = Union[Epsilon; Concat(slash, Star any)] in parse_pattern eof_chars (concat_patterns p q) lexbuf } | "**/" (* \varepsilon | \Sigma^*/ *) { let q = Union[Epsilon; Concat(Star any, slash)] in parse_pattern eof_chars (concat_patterns p q) lexbuf } | "**" { raise (Parse_error("Ambiguous ** pattern not allowed unless surrounded by one or more slashes")) } | '*' { parse_pattern eof_chars (concat_patterns p (Star not_slash)) lexbuf } | '/' { parse_pattern eof_chars (concat_patterns p slash) lexbuf } | '?' { parse_pattern eof_chars (concat_patterns p not_slash) lexbuf } | _ as c { if List.mem c eof_chars then (p,c) else raise (Parse_error(sf "Unexpected character %C in glob pattern" c)) } and parse_string b = parse | "\"" { Buffer.contents b } | "\\\"" { Buffer.add_char b '"'; parse_string b lexbuf } | [^'"' '\\']+ as u { Buffer.add_string b u; parse_string b lexbuf } | _ as c { raise (Parse_error(sf "Unexpected character %C in string" c)) } and parse_class cl = parse | ']' { cl } | "-]" { ((Atom('-','-'))::cl) } | (_ as c1) '-' (_ as c2) { parse_class ((Atom(c1,c2))::cl) lexbuf } | _ as c { parse_class ((Atom(c,c))::cl) lexbuf } ocamlbuild-0.14.3/src/hooks.ml000066400000000000000000000021611454061437200161640ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) type message = | Before_hygiene | After_hygiene | Before_options | After_options | Before_rules | After_rules let hooks = ref ignore let setup_hooks f = hooks := f let call_hook m = !hooks m ocamlbuild-0.14.3/src/hooks.mli000066400000000000000000000021521454061437200163350ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) type message = | Before_hygiene | After_hygiene | Before_options | After_options | Before_rules | After_rules val setup_hooks : (message -> unit) -> unit val call_hook : message -> unit ocamlbuild-0.14.3/src/hygiene.ml000066400000000000000000000140431454061437200164730ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Hygiene *) open My_std open Slurp exception Exit_hygiene_violations type rule = | Implies_not of pattern * pattern | Not of pattern and pattern = suffix and suffix = string type penalty = Warn | Fail type law = { law_name : string; law_rules : rule list; law_penalty : penalty } let list_collect f l = let rec loop result = function | [] -> List.rev result | x :: rest -> match f x with | None -> loop result rest | Some y -> loop (y :: result) rest in loop [] l let list_none_for_all f l = let rec loop = function | [] -> None | x :: rest -> match f x with | None -> loop rest | y -> y in loop l let sf = Printf.sprintf module SS = Set.Make(String);; let check ?sanitize laws entry = let penalties = ref [] in let microbes = ref SS.empty in let () = match sanitize with | Some fn -> if sys_file_exists fn then sys_remove fn | None -> () in let remove path name = if sanitize <> None then microbes := SS.add (filename_concat path name) !microbes in let check_rule = fun entries -> function | Not suffix -> list_collect begin function | File(path, name, _, true) -> if Filename.check_suffix name suffix && not ( Pathname.link_to_dir (filename_concat path name) !Options.build_dir ) then begin remove path name; Some(sf "File %s in %s has suffix %s" name path suffix) end else None | File _ | Dir _| Error _ | Nothing -> None end entries | Implies_not(suffix1, suffix2) -> list_collect begin function | File(path, name, _, true) -> if Filename.check_suffix name suffix1 then begin let base = Filename.chop_suffix name suffix1 in let name' = base ^ suffix2 in if List.exists begin function | File(_, name'', _, true) -> name' = name'' | File _ | Dir _ | Error _ | Nothing -> false end entries then begin remove path name'; Some(sf "Files %s and %s should not be together in %s" name name' path) end else None end else None | File _ | Dir _ | Error _ | Nothing -> None end entries in let rec check_entry = function | Dir(_,_,_,true,entries) -> List.iter begin fun law -> match List.concat (List.map (check_rule !*entries) law.law_rules) with | [] -> () | explanations -> penalties := (law, explanations) :: !penalties end laws; List.iter check_entry !*entries | Dir _ | File _ | Error _ | Nothing -> () in check_entry entry; begin let microbes = !microbes in if not (SS.is_empty microbes) then begin match sanitize with | None -> Log.eprintf "sanitize: the following are files that should probably not be in your\n\ source tree:\n"; SS.iter begin fun fn -> Log.eprintf " %s" fn end microbes; Log.eprintf "Remove them manually, don't use the -no-sanitize option, use -no-hygiene, or\n\ define hygiene exceptions using the tags or plugin mechanism.\n"; raise Exit_hygiene_violations | Some fn -> let m = SS.cardinal microbes in Log.eprintf "@[SANITIZE:@ a@ total@ of@ %d@ file%s@ that@ should@ probably\ @ not@ be@ in@ your@ source@ tree@ has@ been@ found.\ @ A@ script@ shell@ file@ %S@ is@ being@ created.\ @ Check@ this@ script@ and@ run@ it@ to@ remove@ unwanted@ files\ @ or@ use@ other@ options@ (such@ as@ defining@ hygiene@ exceptions\ @ or@ using@ the@ -no-hygiene@ option).@]" m (if m = 1 then "" else "s") fn; let oc = open_out_gen [Open_wronly; Open_creat; Open_trunc; Open_binary] 0o777 fn in (* See PR #5338: under mingw, one produces a shell script, which must follow Unix eol convention; hence Open_binary. *) let fp = Printf.fprintf in fp oc "#!/bin/sh\n\ # File generated by ocamlbuild\n\ \n\ cd %s\n\ \n" (Shell.quote_filename_if_needed Pathname.pwd); SS.iter begin fun fn -> fp oc "rm -f %s\n" (Shell.quote_filename_if_needed fn) end microbes; (* Also clean itself *) fp oc "# Also clean the script itself\n"; fp oc "rm -f %s\n" (Shell.quote_filename_if_needed fn); close_out oc end; !penalties end ;; ocamlbuild-0.14.3/src/hygiene.mli000066400000000000000000000051431454061437200166450ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Hygiene *) (** Module for checking that the source tree is not polluted by object files. *) (** Sanity rules to abide. Not to be confused with compilation rules. *) type rule = Implies_not of pattern * pattern (** The rule [Implies_not(".mll",".ml")] is broken if there is a file [foo.mll] together with a file [foo.ml] int the same directory. The second file can get sanitized. *) | Not of pattern (* No files with suffix [pattern] will be tolerated. *) (** Suffix matching is enough for the purpose of this module. *) and pattern = suffix (** And a suffix is a string. *) and suffix = string (** A warning is simply displayed. A failures stops the compilation. *) type penalty = Warn | Fail (** This type is used to encode laws that will be checked by this module. *) type law = { law_name : string; (** The name of the law that will be printed when it is violated. *) law_rules : rule list; (** Breaking any of these rules is breaking this law. *) law_penalty : penalty; (** Breaking the law gives you either a warning or a failure. *) } (** [check ~sanitize laws entry] will scan the directory tree [entry] for violation to the given [laws]. Any warnings or errors will be printed on the [stdout]. If [sanitize] is [Some fn], a shell script will be written into the file [fn] with commands to delete the offending files. The command will return a pair [(fatal, penalties)] where [fatal] is [true] when serious hygiene violations have been spotted, and [penalties] is a list of laws and messages describing the offenses. *) val check : ?sanitize:string -> law list -> bool Slurp.entry -> (law * string list) list ocamlbuild-0.14.3/src/lexers.mli000066400000000000000000000044331454061437200165200ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) exception Error of (string * Loc.location) type conf_values = { plus_tags : (string * Loc.location) list; minus_tags : (string * Loc.location) list } type conf = (Glob.globber * conf_values) list val ocamldep_output : Loc.source -> Lexing.lexbuf -> (string * string list) list val space_sep_strings : Loc.source -> Lexing.lexbuf -> string list val blank_sep_strings : Loc.source -> Lexing.lexbuf -> string list val comma_sep_strings : Loc.source -> Lexing.lexbuf -> string list val comma_or_blank_sep_strings : Loc.source -> Lexing.lexbuf -> string list val trim_blanks : Loc.source -> Lexing.lexbuf -> string (* Parse an environment path (i.e. $PATH). This is a colon separated string. Note: successive colons means an empty string. Example: ":aaa:bbb:::ccc:" -> [""; "aaa"; "bbb"; ""; ""; "ccc"; ""] *) val parse_environment_path : Loc.source -> Lexing.lexbuf -> string list (* Same one, for Windows (PATH is ;-separated) *) val parse_environment_path_w : Loc.source -> Lexing.lexbuf -> string list val conf_lines : string option -> Loc.source -> Lexing.lexbuf -> conf val path_scheme : bool -> Loc.source -> Lexing.lexbuf -> [ `Word of string | `Var of (string * Glob.globber) ] list val ocamlfind_query : Loc.source -> Lexing.lexbuf -> string * string * string * string * string * string val tag_gen : Loc.source -> Lexing.lexbuf -> string * string option ocamlbuild-0.14.3/src/lexers.mll000066400000000000000000000204251454061437200165220ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) { exception Error of (string * Loc.location) let error source lexbuf fmt = Printf.ksprintf (fun s -> raise (Error (s, Loc.of_lexbuf source lexbuf)) ) fmt open Glob_ast type conf_values = { plus_tags : (string * Loc.location) list; minus_tags : (string * Loc.location) list } type conf = (Glob.globber * conf_values) list let empty = { plus_tags = []; minus_tags = [] } let locate source lexbuf txt = (txt, Loc.of_lexbuf source lexbuf) let sublex lexer s = lexer (Lexing.from_string s) } let newline = ('\n' | '\r' | "\r\n") let space = [' ' '\t' '\012'] let space_or_esc_nl = (space | '\\' newline) let sp = space_or_esc_nl let blank = newline | space let not_blank = [^' ' '\t' '\012' '\n' '\r'] let not_space_nor_comma = [^' ' '\t' '\012' ','] let not_newline = [^ '\n' '\r' ] let not_newline_nor_colon = [^ '\n' '\r' ':' ] let normal_flag_value = [^ '(' ')' '\n' '\r'] let normal = [^ ':' ',' '(' ')' ''' ' ' '\n' '\r'] let tag = normal+ | ( normal+ ':' normal+ ) | normal+ '(' [^ ')' ]* ')' let variable = [ 'a'-'z' 'A'-'Z' '_' '-' '0'-'9' ]* let pattern = ([^ '(' ')' '\\' ] | '\\' [ '(' ')' ])* rule ocamldep_output source = parse | ([^ ':' '\n' '\r' ]+ as k) ':' { let x = (k, space_sep_strings_nl source lexbuf) in x :: ocamldep_output source lexbuf } | eof { [] } | _ { error source lexbuf "Expecting colon followed by space-separated module name list" } and space_sep_strings_nl source = parse | space* (not_blank+ as word) { word :: space_sep_strings_nl source lexbuf } | space* newline { Lexing.new_line lexbuf; [] } | _ { error source lexbuf "Expecting space-separated strings terminated with newline" } and space_sep_strings source = parse | space* (not_blank+ as word) { word :: space_sep_strings source lexbuf } | space* newline? eof { [] } | _ { error source lexbuf "Expecting space-separated strings" } and blank_sep_strings source = parse | blank* '#' not_newline* newline { blank_sep_strings source lexbuf } | blank* '#' not_newline* eof { [] } | blank* (not_blank+ as word) { word :: blank_sep_strings source lexbuf } | blank* eof { [] } | _ { error source lexbuf "Expecting blank-separated strings" } and comma_sep_strings source = parse | space* (not_space_nor_comma+ as word) space* eof { [word] } | space* (not_space_nor_comma+ as word) { word :: comma_sep_strings_aux source lexbuf } | space* eof { [] } | _ { error source lexbuf "Expecting comma-separated strings (1)" } and comma_sep_strings_aux source = parse | space* ',' space* (not_space_nor_comma+ as word) { word :: comma_sep_strings_aux source lexbuf } | space* eof { [] } | _ { error source lexbuf "Expecting comma-separated strings (2)" } and comma_or_blank_sep_strings source = parse | space* (not_space_nor_comma+ as word) space* eof { [word] } | space* (not_space_nor_comma+ as word) { word :: comma_or_blank_sep_strings_aux source lexbuf } | space* eof { [] } | _ { error source lexbuf "Expecting (comma|blank)-separated strings (1)" } and comma_or_blank_sep_strings_aux source = parse | space* ',' space* (not_space_nor_comma+ as word) { word :: comma_or_blank_sep_strings_aux source lexbuf } | space* (not_space_nor_comma+ as word) { word :: comma_or_blank_sep_strings_aux source lexbuf } | space* eof { [] } | _ { error source lexbuf "Expecting (comma|blank)-separated strings (2)" } and parse_environment_path_w source = parse | ([^ ';']* as word) { word :: parse_environment_path_aux_w source lexbuf } | ';' ([^ ';']* as word) { "" :: word :: parse_environment_path_aux_w source lexbuf } | eof { [] } and parse_environment_path_aux_w source = parse | ';' ([^ ';']* as word) { word :: parse_environment_path_aux_w source lexbuf } | eof { [] } | _ { error source lexbuf "Impossible: expecting colon-separated strings" } and parse_environment_path source = parse | ([^ ':']* as word) { word :: parse_environment_path_aux source lexbuf } | ':' ([^ ':']* as word) { "" :: word :: parse_environment_path_aux source lexbuf } | eof { [] } and parse_environment_path_aux source = parse | ':' ([^ ':']* as word) { word :: parse_environment_path_aux source lexbuf } | eof { [] } | _ { error source lexbuf "Impossible: expecting colon-separated strings" } and conf_lines dir source = parse | space* '#' not_newline* newline { Lexing.new_line lexbuf; conf_lines dir source lexbuf } | space* '#' not_newline* eof { [] } | space* newline { Lexing.new_line lexbuf; conf_lines dir source lexbuf } | space* eof { [] } | space* (not_newline_nor_colon+ as k) (sp* as s1) ':' (sp* as s2) { let bexpr = try Glob.parse ?dir k with exn -> error source lexbuf "Invalid globbing pattern %S" k (Printexc.to_string exn) in sublex (count_lines lexbuf) s1; sublex (count_lines lexbuf) s2; let v1 = conf_value empty source lexbuf in let v2 = conf_values v1 source lexbuf in let rest = conf_lines dir source lexbuf in (bexpr,v2) :: rest } | _ { error source lexbuf "Invalid line syntax" } and conf_value x source = parse | '-' (tag as tag) { { (x) with minus_tags = locate source lexbuf tag :: x.minus_tags } } | '+'? (tag as tag) { { (x) with plus_tags = locate source lexbuf tag :: x.plus_tags } } | (_ | eof) { error source lexbuf "Invalid tag modifier only '+ or '-' are allowed as prefix for tag" } and conf_values x source = parse | (sp* as s1) ',' (sp* as s2) { sublex (count_lines lexbuf) s1; sublex (count_lines lexbuf) s2; conf_values (conf_value x source lexbuf) source lexbuf } | newline { Lexing.new_line lexbuf; x } | eof { x } | _ { error source lexbuf "Only ',' separated tags are allowed" } and path_scheme patt_allowed source = parse | ([^ '%' ]+ as prefix) { `Word prefix :: path_scheme patt_allowed source lexbuf } | "%(" (variable as var) ')' { `Var (var, Bool.True) :: path_scheme patt_allowed source lexbuf } | "%(" (variable as var) ':' (pattern as patt) ')' { if patt_allowed then let patt = My_std.String.implode (unescape (Lexing.from_string patt)) in `Var (var, Glob.parse patt) :: path_scheme patt_allowed source lexbuf else error source lexbuf "Patterns are not allowed in this pathname (%%(%s:%s) only in ~prod)" var patt } | '%' { `Var ("", Bool.True) :: path_scheme patt_allowed source lexbuf } | eof { [] } | _ { error source lexbuf "Bad pathanme scheme" } and unescape = parse | '\\' (['(' ')'] as c) { c :: unescape lexbuf } | _ as c { c :: unescape lexbuf } | eof { [] } and ocamlfind_query source = parse | newline* "package:" space* (not_newline* as n) newline+ "description:" space* (not_newline* as d) newline+ "version:" space* (not_newline* as v) newline+ "archive(s):" space* (not_newline* as a) newline+ "linkopts:" space* (not_newline* as lo) newline+ "location:" space* (not_newline* as l) newline+ { n, d, v, a, lo, l } | _ { error source lexbuf "Bad ocamlfind query" } and trim_blanks source = parse | blank* (not_blank* as word) blank* { word } | _ { error source lexbuf "Bad input for trim_blanks" } and tag_gen source = parse | (normal+ as name) ('(' ([^')']* as param) ')')? { name, param } | _ { error source lexbuf "Not a valid parametrized tag" } and count_lines lb = parse | space* { count_lines lb lexbuf } | '\\' newline { Lexing.new_line lb; count_lines lb lexbuf } | eof { () } ocamlbuild-0.14.3/src/loc.ml000066400000000000000000000022761454061437200156250ustar00rootroot00000000000000(* it's not worth adding a dependency on parsing/location.ml(i) or compilerlibs just to support location printing, so we re-implement that here *) open Lexing (* We use a loosely structural type so that this bit of code can be easily reused by project that would wish it, without introducing any type-compatibility burden. *) type source = string (* "file", "environment variable", "command-line option" ... *) type location = source * position * position let file loc = loc.pos_fname let line loc = loc.pos_lnum let char loc = loc.pos_cnum - loc.pos_bol let print_loc ppf (source, start, end_) = let open Format in let print one_or_two ppf (start_num, end_num) = if one_or_two then fprintf ppf " %d" start_num else fprintf ppf "s %d-%d" start_num end_num in fprintf ppf "%s %S, line%a, character%a:@." (String.capitalize_ascii source) (file start) (print (line start = line end_)) (line start, line end_) (print (line start = line end_ && char start = char end_)) (char start, char end_) let of_lexbuf source lexbuf = (source, lexbuf.lex_start_p, lexbuf.lex_curr_p) let print_loc_option ppf = function | None -> () | Some loc -> print_loc ppf loc ocamlbuild-0.14.3/src/loc.mli000066400000000000000000000003761454061437200157750ustar00rootroot00000000000000type source = string type location = source * Lexing.position * Lexing.position val print_loc : Format.formatter -> location -> unit val print_loc_option : Format.formatter -> location option -> unit val of_lexbuf : source -> Lexing.lexbuf -> location ocamlbuild-0.14.3/src/log.ml000066400000000000000000000054511454061437200156270ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std module Debug = struct let mode _ = true end include Debug let level = ref 1 let classic_display = ref false let internal_display = ref None let failsafe_display = lazy (Display.create ~mode:`Classic ~log_level:!level ()) let ( !- ) r = match !r with | None -> !*failsafe_display | Some x -> x let init log_file = let mode = if !classic_display || !*My_unix.is_degraded || !level <= 0 || not (My_unix.stdout_isatty ()) then `Classic else `Sophisticated in internal_display := Some (Display.create ~mode ?log_file ~log_level:!level ()) let raw_dprintf log_level = Display.dprintf ~raw:true ~log_level !-internal_display let dprintf log_level fmt = Display.dprintf ~log_level !-internal_display fmt let is_logging log_level = Display.is_logging !-internal_display log_level let eprintf fmt = dprintf (-1) fmt let update () = Display.update !-internal_display let event ?pretend x = Display.event !-internal_display ?pretend x let display x = Display.display !-internal_display x let do_at_end = Queue.create () let already_asked = Hashtbl.create 10 let at_end_always ~name thunk = if not (Hashtbl.mem already_asked name) then begin Hashtbl.add already_asked name (); Queue.add thunk do_at_end; end let at_end ~name thunk = at_end_always ~name (function | `Quiet -> () | `Success | `Error -> thunk `Error) let at_failure ~name thunk = at_end_always ~name (function | `Success | `Quiet -> () | `Error -> thunk `Error) let finish ?how () = while not (Queue.is_empty do_at_end) do let actions = Queue.copy do_at_end in Queue.clear do_at_end; (* calling a thunk may add new actions again, hence the loop *) Queue.iter (fun thunk -> thunk (match how with None -> `Quiet | Some how -> how) ) actions; done; match !internal_display with | None -> () | Some d -> Display.finish ?how d (*let () = My_unix.at_exit_once finish*) ocamlbuild-0.14.3/src/log.mli000066400000000000000000000035561454061437200160040ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Log *) (** Module for modulating the logging output with the logging level. *) include Signatures.LOG (** Turn it to true to have a classic display of commands. *) val classic_display : bool ref (** See {Display.event}. *) val event : ?pretend:bool -> string -> string -> Tags.t -> unit (**/**) (** Initialize the Log module given a log file name. *) val init : string option -> unit val finish : ?how:[`Success|`Error|`Quiet] -> unit -> unit val display : (out_channel -> unit) -> unit val update : unit -> unit val mode : string -> bool (** Wrap logging event so that only fire at the end of the compilation process, possibly depending on the termination status. The name is used to avoid printing the same hint/warning twice, even if [at_end] is called several times. Use different names for distinct events. *) val at_end : name:string -> ([> `Error | `Quiet ] -> unit) -> unit val at_failure : name:string -> ([> `Error ] -> unit) -> unit ocamlbuild-0.14.3/src/main.ml000066400000000000000000000303031454061437200157640ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Compatibility with both OCaml < 4.08 and >= 5.00 *) module Pervasives = struct let exit = exit end (* Original author: Berke Durak *) open My_std open Log open Pathname.Operators open Command open Tools open Ocaml_specific ;; exception Exit_build_error of string exception Exit_silently let clean () = Log.finish (); Shell.rm_rf !Options.build_dir; if !Options.make_links then begin let entry = Slurp.map (fun _ _ _ -> true) (Slurp.slurp Filename.current_dir_name) in Slurp.force (Resource.clean_up_links entry) end; raise Exit_silently ;; let show_tags () = if List.length !Options.show_tags > 0 then Log.eprintf "Warning: the following tags do not include \ dynamically-generated tags, such as link, compile, pack, byte, native, c, \ pdf... (this list is by no means exhaustive).\n"; List.iter begin fun path -> Log.eprintf "@[<2>Tags for %S:@ {. %a .}@]" path Tags.print (tags_of_pathname path) end !Options.show_tags ;; let show_documentation () = Rule.show_documentation (); Flags.show_documentation (); ;; (* these tags are used in an ad-hoc way by the ocamlbuild implementation; this means that even if they were not part of any flag declaration, they should be marked as useful, to avoid the "unused tag" warning. *) let builtin_useful_tags = Tags.of_list [ "include"; "traverse"; "not_hygienic"; "precious"; "pack"; "ocamlmklib"; "native"; "thread"; "nopervasives"; "use_menhir"; "ocamldep"; "thread"; ] ;; let proceed () = Hooks.call_hook Hooks.Before_options; Options.init (); Options.include_dirs := List.map Pathname.normalize !Options.include_dirs; Options.exclude_dirs := List.map Pathname.normalize !Options.exclude_dirs; if !Options.must_clean then clean (); Hooks.call_hook Hooks.After_options; let options_wd = Sys.getcwd () in let first_run_for_plugin = (* If we are in the first run before launching the plugin, we should skip the user-visible operations (hygiene) that may need information from the plugin to run as the user expects it. Note that we don't need to disable the [Hooks] call as they are no-ops anyway, before any plugin has registered hooks. *) Plugin.we_need_a_plugin () && not !Options.just_plugin in let target_dirs = List.union [] (List.map Pathname.dirname !Options.targets) in Configuration.parse_string ~source:Const.Source.builtin {| <**/*.ml> or <**/*.mli> or <**/*.mlpack> or <**/*.ml.depends>: ocaml <**/*.byte>: ocaml, byte, program <**/*.odoc>: ocaml, doc <**/*.native>: ocaml, native, program <**/*.cma>: ocaml, byte, library <**/*.cmxa>: ocaml, native, library <**/*.cmo>: ocaml, byte <**/*.cmi>: ocaml, byte, native <**/*.cmx>: ocaml, native <**/*.mly>: infer <**/.svn>|"CVS"|".bzr"|".hg"|".git"|"_darcs"|"_opam"|"node_modules": -traverse |}; List.iter (Configuration.parse_string ~source:Const.Source.command_line) !Options.tag_lines; Configuration.tag_any !Options.tags; if !Options.recursive || Options.ocamlbuild_project_heuristic () then Configuration.tag_any ["traverse"]; (* options related to findlib *) if !Options.use_ocamlfind then List.iter (fun pkg -> let tag = Param_tags.make "package" pkg in Configuration.tag_any [tag]) !Options.ocaml_pkgs; begin match !Options.ocaml_syntax with | Some syntax -> Configuration.tag_any [Param_tags.make "syntax" syntax] | None -> () end; let newpwd = Sys.getcwd () in Sys.chdir Pathname.pwd; let entry_include_dirs = ref [] in let entry = Slurp.filter begin fun path name () -> let dir = if path = Filename.current_dir_name then None else Some path in let path_name = path/name in if name = "_tags" then begin let tags_path = (* PR#6482: remember that this code is run lazily by the Slurp command, and may run only after the working directory has been changed. On the other hand, always using the absolute path makes error messages longer and more frigthening in case of syntax error in the _tags file. So we use the absolute path only when necessary -- the working directory has changed. *) if Sys.getcwd () = Pathname.pwd then path_name else Pathname.pwd / path_name in ignore (Configuration.parse_file ?dir tags_path); end; ((* beware: !Options.build_dir is an absolute directory *) Pathname.pwd/name <> !Options.build_dir && not (List.mem name !Options.exclude_dirs)) && begin not (path_name <> Filename.current_dir_name && Pathname.is_directory path_name) || begin let tags = tags_of_pathname path_name in (if Tags.mem "include" tags || List.mem path_name !Options.include_dirs then (entry_include_dirs := path_name :: !entry_include_dirs; true) else Tags.mem "traverse" tags || List.exists (Pathname.is_prefix path_name) !Options.include_dirs || List.exists (Pathname.is_prefix path_name) target_dirs) end end end (Slurp.slurp Filename.current_dir_name) in Hooks.call_hook Hooks.Before_hygiene; let hygiene_entry = Slurp.map begin fun path name () -> let tags = tags_of_pathname (path/name) in not (Tags.mem "not_hygienic" tags) && not (Tags.mem "precious" tags) end entry in Slurp.force hygiene_entry; if !Options.hygiene && not first_run_for_plugin then Fda.inspect hygiene_entry; let entry = hygiene_entry in Hooks.call_hook Hooks.After_hygiene; Options.include_dirs := Pathname.current_dir_name :: List.rev !entry_include_dirs; dprintf 3 "include directories are:@ %a" print_string_list !Options.include_dirs; Options.entry := Some entry; Hooks.call_hook Hooks.Before_rules; Ocaml_specific.init (); Hooks.call_hook Hooks.After_rules; Sys.chdir options_wd; Plugin.execute_plugin_if_needed (); (* [Param_tags.init ()] is called *after* the plugin is executed, as some of the parametrized tags present in the _tags files parsed will be declared by the plugin, and would therefore result in "tag X does not expect a parameter" warnings if initialized before. Note that [Plugin.rebuild_plugin_if_needed] is careful to partially initialize the tags that it uses for plugin compilation. *) Param_tags.init (); Sys.chdir newpwd; (*let () = dprintf 0 "source_dir_path_set:@ %a" StringSet.print source_dir_path_set*) if !Options.show_documentation then begin show_documentation (); raise Exit_silently end; let all_tags = let builtin = builtin_useful_tags in let used_in_flags = Flags.get_used_tags () in let used_in_deps = List.fold_left (fun acc (tags, _deps) -> Tags.union acc tags) Tags.empty (Command.list_all_deps ()) in Tags.union builtin (Tags.union used_in_flags used_in_deps) in Configuration.check_tags_usage all_tags; Digest_cache.init (); Sys.catch_break true; show_tags (); let targets = List.map begin fun starget -> let starget = Resource.import starget in let target = path_and_context_of_string starget in let ext = Pathname.get_extension starget in (target, starget, ext) end !Options.targets in try let targets = List.map begin fun (target, starget, ext) -> Shell.mkdir_p (Pathname.dirname starget); let target = Solver.solve_target starget target in (target, ext) end targets in Command.dump_parallel_stats (); Log.finish (); Shell.chdir Pathname.pwd; let call spec = sys_command (Command.string_of_command_spec spec) in let cmds = List.fold_right begin fun (target, ext) acc -> let cmd = !Options.build_dir/target in let link x = if !Options.make_links then ignore (call (S [A"ln"; A"-sf"; P x; A Pathname.pwd])) in match ext with | "byte" | "native" | "top" -> link cmd; cmd :: acc | "html" -> link (Pathname.dirname cmd); acc | _ -> if !Options.program_to_execute then eprintf "Warning: Won't execute %s whose extension is neither .byte nor .native" cmd; acc end targets [] in if !Options.program_to_execute then begin match List.rev cmds with | [] -> raise (Exit_usage "Using -- requires one target"); | cmd :: rest -> if rest <> [] then dprintf 0 "Warning: Using -- only run the last target"; let cmd_spec = S [P cmd; atomize !Options.program_args] in dprintf 3 "Running the user command:@ %a" Pathname.print cmd; raise (Exit_with_code (call cmd_spec)) (* Exit with the exit code of the called command *) end else () with | Ocaml_dependencies.Circular_dependencies(cycle, p) -> raise (Exit_build_error (sbprintf "@[<2>Circular dependencies: %S already seen in@ %a@]@." p pp_l cycle)) ;; open Exit_codes;; let main () = let exit rc = Log.finish ~how:(if rc <> 0 then `Error else `Success) (); Pervasives.exit rc in try proceed () with e -> if !Options.catch_errors then try raise e with | Exit_OK -> exit rc_ok | Fda.Exit_hygiene_failed -> Log.eprintf "Exiting due to hygiene violations."; exit rc_hygiene | Exit_usage u -> Log.eprintf "Usage:@ %s." u; exit rc_usage | Exit_system_error msg -> Log.eprintf "System error:@ %s." msg; exit rc_system_error | Exit_with_code rc -> exit rc | Exit_silently -> Log.finish ~how:`Quiet (); Pervasives.exit rc_ok | Exit_silently_with_code rc -> Log.finish ~how:`Quiet (); Pervasives.exit rc | Solver.Failed backtrace -> Log.raw_dprintf (-1) "@[@[<2>Solver failed:@ %a@]@." Report.print_backtrace_analyze backtrace; Log.raw_dprintf 1 "@[Backtrace:%a@]@]@." Report.print_backtrace backtrace; exit rc_solver_failed | Failure s -> Log.eprintf "Failure:@ %s." s; exit rc_failure | Solver.Circular(r, rs) -> Log.eprintf "Circular build detected@ (%a already seen in %a)" Resource.print r (List.print Resource.print) rs; exit rc_circularity | Invalid_argument s -> Log.eprintf "INTERNAL ERROR: Invalid argument %s\n\ This is likely to be a bug, please report this to the ocamlbuild\n\ developers." s; exit rc_invalid_argument | Ocaml_utils.Ocamldep_error msg -> Log.eprintf "Ocamldep error: %s" msg; exit rc_ocamldep_error | Lexers.Error (msg,loc) -> Log.eprintf "%aLexing error: %s." Loc.print_loc loc msg; exit rc_lexing_error | Arg.Bad msg -> Log.eprintf "%s" msg; exit rc_usage | Exit_build_error msg -> Log.eprintf "%s" msg; exit rc_build_error | Arg.Help msg -> Log.eprintf "%s" msg; exit rc_ok | e -> try Log.eprintf "%a" My_unix.report_error e; exit 100 with | e -> Log.eprintf "Exception@ %s." (Printexc.to_string e); exit 100 else raise e ;; ocamlbuild-0.14.3/src/main.mli000066400000000000000000000016731454061437200161450ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val main : unit -> unit ocamlbuild-0.14.3/src/my_std.ml000066400000000000000000000310121454061437200163350ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Compatibility with both OCaml < 4.08 and >= 5.00 *) module Pervasives = struct let compare = compare end (* Original author: Nicolas Pouillard *) open Format exception Exit_OK exception Exit_usage of string exception Exit_system_error of string exception Exit_with_code of int exception Exit_silently_with_code of int module Outcome = struct type ('a,'b) t = | Good of 'a | Bad of 'b let ignore_good = function | Good _ -> () | Bad e -> raise e let good = function | Good x -> x | Bad exn -> raise exn let wrap f x = try Good (f x) with e -> Bad e end let opt_print elt ppf = function | Some x -> fprintf ppf "@[<2>Some@ %a@]" elt x | None -> pp_print_string ppf "None" open Format let ksbprintf g fmt = let buff = Buffer.create 42 in let f = formatter_of_buffer buff in kfprintf (fun f -> (pp_print_flush f (); g (Buffer.contents buff))) f fmt let sbprintf fmt = ksbprintf (fun x -> x) fmt (** Some extensions of the standard library *) module Set = struct module type OrderedTypePrintable = sig include Set.OrderedType val print : formatter -> t -> unit end module type S = sig include Set.S val find_elt : (elt -> bool) -> t -> elt val map : (elt -> elt) -> t -> t val of_list : elt list -> t val print : formatter -> t -> unit end module Make (M : OrderedTypePrintable) : S with type elt = M.t = struct include Set.Make(M) exception Found of elt let find_elt p set = try iter begin fun elt -> if p elt then raise (Found elt) end set; raise Not_found with Found elt -> elt let map f set = fold (fun x -> add (f x)) set empty let of_list l = List.fold_right add l empty let print f s = let () = fprintf f "@[@[{.@ " in let _ = fold begin fun elt first -> if not first then fprintf f ",@ "; M.print f elt; false end s true in fprintf f "@]@ .}@]" end end module List = struct include List let print pp_elt f ls = fprintf f "@[<2>[@ "; let _ = fold_left begin fun first elt -> if not first then fprintf f ";@ "; pp_elt f elt; false end true ls in fprintf f "@ ]@]" let filter_opt f xs = List.fold_right begin fun x acc -> match f x with | Some x -> x :: acc | None -> acc end xs [] let rec rev_append_uniq acc = function | [] -> acc | x :: xs -> if mem x acc then rev_append_uniq acc xs else rev_append_uniq (x :: acc) xs let union a b = rev (rev_append_uniq (rev_append_uniq [] a) b) let ordered_unique (type el) (lst : el list) = let module Set = Set.Make(struct type t = el let compare = Pervasives.compare let print _ _ = () end) in let _, lst = List.fold_left (fun (set,acc) el -> if Set.mem el set then set, acc else Set.add el set, el :: acc) (Set.empty,[]) lst in List.rev lst let index_of x l = let rec aux x n = function | [] -> None | a::_ when a = x -> Some n | _::l -> aux x (n+1) l in aux x 0 l let rec split_at n l = let rec aux n acc = function | l when n <= 0 -> List.rev acc, l | [] -> List.rev acc, [] | a::l -> aux (n-1) (a::acc) l in aux n [] l end module String = struct include String let print f s = fprintf f "%S" s let chomp s = let is_nl_char = function '\n' | '\r' -> true | _ -> false in let rec cut n = if n = 0 then 0 else if is_nl_char s.[n-1] then cut (n-1) else n in let ls = length s in let n = cut ls in if n = ls then s else sub s 0 n let before s pos = sub s 0 pos let after s pos = sub s pos (length s - pos) let first_chars s n = sub s 0 n let last_chars s n = sub s (length s - n) n let rec eq_sub_strings s1 p1 s2 p2 len = if len > 0 then s1.[p1] = s2.[p2] && eq_sub_strings s1 (p1+1) s2 (p2+1) (len-1) else true let rec contains_string s1 p1 s2 = let ls1 = length s1 in let ls2 = length s2 in try let pos = index_from s1 p1 s2.[0] in if ls1 - pos < ls2 then None else if eq_sub_strings s1 pos s2 0 ls2 then Some pos else contains_string s1 (pos + 1) s2 with Not_found -> None let subst patt repl s = let lpatt = length patt in let lrepl = length repl in let rec loop s from = match contains_string s from patt with | Some pos -> loop (before s pos ^ repl ^ after s (pos + lpatt)) (pos + lrepl) | None -> s in loop s 0 let tr patt subst text = String.map (fun c -> if c = patt then subst else c) text (*** is_prefix : is u a prefix of v ? *) let is_prefix u v = let m = String.length u and n = String.length v in m <= n && let rec loop i = i = m || u.[i] = v.[i] && loop (i + 1) in loop 0 (* ***) (*** is_suffix : is v a suffix of u ? *) let is_suffix u v = let m = String.length u and n = String.length v in n <= m && let rec loop i = i = n || u.[m - 1 - i] = v.[n - 1 - i] && loop (i + 1) in loop 0 (* ***) let rev s = let sl = String.length s in let s' = Bytes.create sl in for i = 0 to sl - 1 do Bytes.set s' i s.[sl - i - 1] done; Bytes.to_string s';; let implode l = match l with | [] -> "" | cs -> let r = Bytes.create (List.length cs) in let pos = ref 0 in List.iter begin fun c -> Bytes.unsafe_set r !pos c; incr pos end cs; Bytes.to_string r let explode s = let sl = String.length s in let rec go pos = if pos >= sl then [] else unsafe_get s pos :: go (pos + 1) in go 0 end module StringSet = Set.Make(String) let sys_readdir, reset_readdir_cache, reset_readdir_cache_for = let cache = Hashtbl.create 103 in let sys_readdir dir = try Hashtbl.find cache dir with Not_found -> let res = Outcome.wrap Sys.readdir dir in (Hashtbl.add cache dir res; res) and reset_readdir_cache () = Hashtbl.clear cache and reset_readdir_cache_for dir = Hashtbl.remove cache dir in (sys_readdir, reset_readdir_cache, reset_readdir_cache_for) let sys_file_exists x = let dirname = Filename.dirname x in let basename = Filename.basename x in match sys_readdir dirname with | Outcome.Bad _ -> false | Outcome.Good a -> if basename = Filename.current_dir_name then true else if dirname = x (* issue #86: (dirname "/" = "/") *) then true else try Array.iter (fun x -> if x = basename then raise Exit) a; false with Exit -> true let sys_command = match Sys.os_type with | "Win32" -> fun cmd -> if cmd = "" then 0 else let cmd = "bash --norc -c " ^ Filename.quote cmd in Sys.command cmd | _ -> fun cmd -> if cmd = "" then 0 else Sys.command cmd (* FIXME warning fix and use Filename.concat *) let filename_concat x y = if x = Filename.current_dir_name || x = "" then y else if Sys.os_type = "Win32" && (x.[String.length x - 1] = '\\') || x.[String.length x - 1] = '/' then if y = "" then x else x ^ y else x ^ "/" ^ y (* let reslash = match Sys.os_type with | "Win32" -> tr '\\' '/' | _ -> (fun x -> x) *) open Format let invalid_arg' fmt = ksbprintf invalid_arg fmt let the = function Some x -> x | None -> invalid_arg "the: expect Some not None" let getenv ?default var = try Sys.getenv var with Not_found -> match default with | Some x -> x | None -> failwith (sprintf "This command must have %S in his environment" var);; let with_input_file ?(bin=false) x f = let ic = (if bin then open_in_bin else open_in) x in try let res = f ic in close_in ic; res with e -> (close_in ic; raise e) let with_output_file ?(bin=false) x f = reset_readdir_cache_for (Filename.dirname x); let oc = (if bin then open_out_bin else open_out) x in try let res = f oc in close_out oc; res with e -> (close_out oc; raise e) let read_file x = with_input_file ~bin:true x begin fun ic -> let len = in_channel_length ic in really_input_string ic len end let copy_chan ic oc = let m = in_channel_length ic in let m = (m lsr 12) lsl 12 in let m = max 16384 (min Sys.max_string_length m) in let buf = Bytes.create m in let rec loop () = let len = input ic buf 0 m in if len > 0 then begin output oc buf 0 len; loop () end in loop () let copy_file src dest = reset_readdir_cache_for (Filename.dirname dest); with_input_file ~bin:true src begin fun ic -> with_output_file ~bin:true dest begin fun oc -> copy_chan ic oc end end let ( !* ) = Lazy.force let ( @:= ) ref list = ref := !ref @ list let ( & ) f x = f x let ( |> ) x f = f x let print_string_list = List.print String.print module Digest = struct include Digest (* USEFUL FOR DIGEST DEBUGING let digest_log_hash = Hashtbl.create 103;; let digest_log = "digest.log";; let digest_log_oc = open_out_gen [Open_append;Open_wronly;Open_text;Open_creat] 0o666 digest_log;; let my_to_hex x = to_hex x ^ ";";; if sys_file_exists digest_log then with_input_file digest_log begin fun ic -> try while true do let l = input_line ic in Scanf.sscanf l "%S: %S" (Hashtbl.replace digest_log_hash) done with End_of_file -> () end;; let string s = let res = my_to_hex (string s) in if try let x = Hashtbl.find digest_log_hash res in s <> x with Not_found -> true then begin Hashtbl.replace digest_log_hash res s; Printf.fprintf digest_log_oc "%S: %S\n%!" res s end; res let file f = my_to_hex (file f) let to_hex x = x *) let digest_cache = Hashtbl.create 103 let reset_digest_cache () = Hashtbl.clear digest_cache let reset_digest_cache_for file = Hashtbl.remove digest_cache file let file f = try Hashtbl.find digest_cache f with Not_found -> let res = file f in (Hashtbl.add digest_cache f res; res) end let reset_filesys_cache () = Digest.reset_digest_cache (); reset_readdir_cache () let reset_filesys_cache_for_file file = Digest.reset_digest_cache_for file; reset_readdir_cache_for (Filename.dirname file) let sys_remove x = reset_filesys_cache_for_file x; Sys.remove x let with_temp_file pre suf fct = let tmp = Filename.temp_file pre suf in (* Sys.remove is used instead of sys_remove since we know that the tempfile is not that important *) try let res = fct tmp in Sys.remove tmp; res with e -> (Sys.remove tmp; raise e) let memo f = let cache = Hashtbl.create 103 in fun x -> try Hashtbl.find cache x with Not_found -> let res = f x in (Hashtbl.add cache x res; res) let memo2 f = let cache = Hashtbl.create 103 in fun x y -> try Hashtbl.find cache (x,y) with Not_found -> let res = f x y in (Hashtbl.add cache (x,y) res; res) let memo3 f = let cache = Hashtbl.create 103 in fun x y z -> try Hashtbl.find cache (x,y,z) with Not_found -> let res = f x y z in (Hashtbl.add cache (x,y,z) res; res) let set_lexbuf_fname fname lexbuf = let open Lexing in lexbuf.lex_start_p <- { lexbuf.lex_start_p with pos_fname = fname }; lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = fname }; () let lexbuf_of_string ?name content = let lexbuf = Lexing.from_string content in let fname = match name with | Some name -> name | None -> (* 40: hope the location will fit one line of 80 chars *) if String.length content < 40 && not (String.contains content '\n') then String.escaped content else "" in set_lexbuf_fname fname lexbuf; lexbuf let split_ocaml_version = let version major minor patch rest = (major, minor, patch, rest) in try Some (Scanf.sscanf Sys.ocaml_version "%d.%d.%d%s@\n" version) with _ -> None ocamlbuild-0.14.3/src/my_std.mli000066400000000000000000000050301454061437200165070ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* My_std *) (** Generic utility functions, and system-independent glue. *) exception Exit_OK exception Exit_usage of string exception Exit_system_error of string exception Exit_with_code of int exception Exit_silently_with_code of int module Outcome : Signatures.OUTCOME val ksbprintf : (string -> 'a) -> ('b, Format.formatter, unit, 'a) format4 -> 'b val sbprintf : ('a, Format.formatter, unit, string) format4 -> 'a module Set : sig module type OrderedTypePrintable = Signatures.OrderedTypePrintable module type S = Signatures.SET module Make (M : OrderedTypePrintable) : S with type elt = M.t end module List : Signatures.LIST module String : Signatures.STRING module Digest : sig type t = string val string : string -> t val substring : string -> int -> int -> t val channel : in_channel -> int -> t val file : string -> t val output : out_channel -> t -> unit val input : in_channel -> t val to_hex : t -> string end module StringSet : Set.S with type elt = String.t val sys_readdir : string -> (string array, exn) Outcome.t val sys_remove : string -> unit val reset_readdir_cache : unit -> unit val reset_filesys_cache : unit -> unit val reset_filesys_cache_for_file : string -> unit val sys_file_exists : string -> bool val sys_command : string -> int val filename_concat : string -> string -> string val invalid_arg' : ('a, Format.formatter, unit, 'b) format4 -> 'a include Signatures.MISC val set_lexbuf_fname : string -> Lexing.lexbuf -> unit val lexbuf_of_string : ?name:string -> string -> Lexing.lexbuf val split_ocaml_version : (int * int * int * string) option (** (major, minor, patchlevel, rest) *) ocamlbuild-0.14.3/src/my_unix.ml000066400000000000000000000111701454061437200165310ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std type file_kind = | FK_dir | FK_file | FK_link | FK_other type stats = { stat_file_kind : file_kind; stat_key : string } type implem = { mutable is_degraded : bool; mutable is_link : string -> bool; mutable run_and_open : 'a . string -> (in_channel -> 'a) -> 'a; mutable readlink : string -> string; mutable execute_many : ?max_jobs:int -> ?ticker:(unit -> unit) -> ?period:float -> ?display:((out_channel -> unit) -> unit) -> ((unit -> string) list list) -> (bool list * exn) option; mutable report_error : Format.formatter -> exn -> unit; mutable at_exit_once : (unit -> unit) -> unit; mutable gettimeofday : unit -> float; mutable stdout_isatty : unit -> bool; mutable stat : string -> stats; mutable lstat : string -> stats; } let is_degraded = true let stat f = { stat_key = f; stat_file_kind = if sys_file_exists f then if Sys.is_directory f then FK_dir else FK_file else let _ = with_input_file f input_char in assert false } let run_and_open s kont = with_temp_file "ocamlbuild" "out" begin fun tmp -> let s = Printf.sprintf "%s > '%s'" s tmp in let st = sys_command s in if st <> 0 then failwith (Printf.sprintf "Error while running: %s" s); with_input_file tmp kont end exception Not_a_link exception No_such_file exception Link_to_directories_not_supported let readlinkcmd = let cache = Hashtbl.create 32 in fun x -> try Hashtbl.find cache x with Not_found -> run_and_open (Printf.sprintf "readlink %s" (Filename.quote x)) begin fun ic -> let y = String.chomp (input_line ic) in Hashtbl.replace cache x y; y end let rec readlink x = if sys_file_exists x then try let y = readlinkcmd x in let y = if Filename.is_relative y then Filename.concat (Filename.dirname x) y else y in if (lstat y).stat_file_kind = FK_dir then raise Link_to_directories_not_supported else y with Failure(_) -> raise Not_a_link else raise No_such_file and is_link x = try ignore(readlink x); true with | No_such_file | Not_a_link -> false and lstat x = if is_link x then { stat_key = x; stat_file_kind = FK_link } else stat x let implem = { is_degraded = true; stat = stat; lstat = lstat; readlink = readlink; is_link = is_link; run_and_open = run_and_open; (* at_exit_once is at_exit in the degraded mode since fork is not accessible in this mode *) at_exit_once = at_exit; report_error = (fun _ -> raise); gettimeofday = (fun () -> assert false); stdout_isatty = (fun () -> false); execute_many = (fun ?max_jobs:(_) ?ticker:(_) ?period:(_) ?display:(_) _ -> assert false) } let is_degraded = lazy implem.is_degraded let stat x = implem.stat x let lstat x = implem.lstat x let readlink x = implem.readlink x let is_link x = implem.is_link x let run_and_open x = implem.run_and_open x let at_exit_once x = implem.at_exit_once x let report_error x = implem.report_error x let gettimeofday x = implem.gettimeofday x let stdout_isatty x = implem.stdout_isatty x let execute_many ?max_jobs = implem.execute_many ?max_jobs let run_and_read cmd = let bufsiz = 2048 in let buf = Bytes.create bufsiz in let totalbuf = Buffer.create 4096 in implem.run_and_open cmd begin fun ic -> let rec loop pos = let len = input ic buf 0 bufsiz in if len > 0 then begin Buffer.add_subbytes totalbuf buf 0 len; loop (pos + len) end in loop 0; Buffer.contents totalbuf end ocamlbuild-0.14.3/src/my_unix.mli000066400000000000000000000050371454061437200167070ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) type file_kind = | FK_dir | FK_file | FK_link | FK_other type stats = { stat_file_kind : file_kind; stat_key : string } val is_degraded : bool Lazy.t val is_link : string -> bool val run_and_open : string -> (in_channel -> 'a) -> 'a val readlink : string -> string val run_and_read : string -> string (** See [Ocamlbuild_executor.execute] *) val execute_many : ?max_jobs:int -> ?ticker:(unit -> unit) -> ?period:float -> ?display:((out_channel -> unit) -> unit) -> ((unit -> string) list list) -> (bool list * exn) option val report_error : Format.formatter -> exn -> unit val at_exit_once : (unit -> unit) -> unit val gettimeofday : unit -> float val stdout_isatty : unit -> bool val stat : string -> stats val lstat : string -> stats (** internal usage only *) type implem = { mutable is_degraded : bool; mutable is_link : string -> bool; mutable run_and_open : 'a . string -> (in_channel -> 'a) -> 'a; mutable readlink : string -> string; mutable execute_many : ?max_jobs:int -> ?ticker:(unit -> unit) -> ?period:float -> ?display:((out_channel -> unit) -> unit) -> ((unit -> string) list list) -> (bool list * exn) option; mutable report_error : Format.formatter -> exn -> unit; mutable at_exit_once : (unit -> unit) -> unit; mutable gettimeofday : unit -> float; mutable stdout_isatty : unit -> bool; mutable stat : string -> stats; mutable lstat : string -> stats; } val implem : implem ocamlbuild-0.14.3/src/ocaml_arch.ml000066400000000000000000000126141454061437200171350ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Command open Pathname.Operators type 'a arch = | Arch_dir of string * 'a * 'a arch list | Arch_dir_pack of string * 'a * 'a arch list | Arch_file of string * 'a let dir name contents = Arch_dir(name, (), contents) let dir_pack name contents = Arch_dir_pack(name, (), contents) let file name = Arch_file(name, ()) type info = { current_path : string; include_dirs : string list; for_pack : string; } let join_pack parent base = if parent = "" then base else parent ^ "." ^ base let annotate arch = let rec self arch acc = match arch with | Arch_dir_pack(name, _, contents) -> let acc = { (acc) with for_pack = join_pack acc.for_pack name } in let (_, _, i, new_contents) = self_contents name contents acc in ([], Arch_dir_pack(name, i, List.rev new_contents)) | Arch_dir(name, _, contents) -> let (current_path, include_dirs, i, new_contents) = self_contents name contents acc in (current_path :: include_dirs, Arch_dir(name, i, List.rev new_contents)) | Arch_file(name, _) -> ([], Arch_file(name, acc)) and self_contents name contents acc = let current_path = acc.current_path/name in let include_dirs = if current_path = "" then acc.include_dirs else current_path :: acc.include_dirs in let i = { (acc) with current_path = current_path; include_dirs = include_dirs } in let (include_dirs, new_contents) = List.fold_left begin fun (include_dirs, new_contents) x -> let j = { (i) with include_dirs = include_dirs @ i.include_dirs } in let (include_dirs', x') = self x j in (include_dirs @ include_dirs', x' :: new_contents) end ([], []) contents in (current_path, include_dirs, i, new_contents) in let init = { current_path = ""; include_dirs = []; for_pack = "" } in snd (self arch init) let rec print print_info f = let rec print_contents f = function | [] -> () | x :: xs -> Format.fprintf f "@ %a%a" (print print_info) x print_contents xs in function | Arch_dir(name, info, contents) -> Format.fprintf f "@[dir %S%a%a@]" name print_info info print_contents contents | Arch_dir_pack(name, info, contents) -> Format.fprintf f "@[dir_pack %S%a%a@]" name print_info info print_contents contents | Arch_file(name, info) -> Format.fprintf f "@[<2>file %S%a@]" name print_info info let print_include_dirs = List.print String.print let print_info f i = Format.fprintf f "@ @[{ @[<2>current_path =@ %S@];@\ \ @[<2>include_dirs =@ %a@];@\ \ @[<2>for_pack =@ %S@] }@]" i.current_path print_include_dirs i.include_dirs i.for_pack let rec iter_info f = function | Arch_dir_pack(_, i, xs) | Arch_dir(_, i, xs) -> f i; List.iter (iter_info f) xs | Arch_file(_, i) -> f i let rec fold_info f arch acc = match arch with | Arch_dir_pack(_, i, xs) | Arch_dir(_, i, xs) -> List.fold_right (fold_info f) xs (f i acc) | Arch_file(_, i) -> f i acc module SS = Set.Make(String) let iter_include_dirs arch = let set = fold_info (fun i -> List.fold_right SS.add i.include_dirs) arch SS.empty in fun f -> SS.iter f set let forpack_flags_of_pathname = ref (fun _ -> N) let print_table print_value f table = Format.fprintf f "@[{:@["; Hashtbl.iter begin fun k v -> if k <> "" then Format.fprintf f "@ @[<2>%S =>@ %a@];" k print_value v; end table; Format.fprintf f "@]@ :}@]" let print_tables f (include_dirs_table, for_pack_table) = Format.fprintf f "@[<2>@[<2>include_dirs_table:@ %a@];@ @[<2>for_pack_table: %a@]@]" (print_table (List.print String.print)) include_dirs_table (print_table String.print) for_pack_table let mk_tables arch = let include_dirs_table = Hashtbl.create 17 and for_pack_table = Hashtbl.create 17 in iter_info begin fun i -> Hashtbl.replace include_dirs_table i.current_path i.include_dirs; Hashtbl.replace for_pack_table i.current_path i.for_pack end arch; let previous_forpack_flags_of_pathname = !forpack_flags_of_pathname in forpack_flags_of_pathname := begin fun m -> let m' = Pathname.dirname m in try let for_pack = Hashtbl.find for_pack_table m' in if for_pack = "" then N else S[A"-for-pack"; A for_pack] with Not_found -> previous_forpack_flags_of_pathname m end; (* Format.eprintf "@[<2>%a@]@." print_tables (include_dirs_table, for_pack_table); *) (include_dirs_table, for_pack_table) let forpack_flags_of_pathname m = !forpack_flags_of_pathname m ocamlbuild-0.14.3/src/ocaml_arch.mli000066400000000000000000000017631454061437200173110ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) include Signatures.ARCH val forpack_flags_of_pathname : string -> Command.spec ocamlbuild-0.14.3/src/ocaml_compiler.ml000066400000000000000000000420341454061437200200310ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Format open Log open Pathname.Operators open Tools open Command open Rule open Tags.Operators open Ocaml_utils open Rule.Common_commands open Outcome let forpack_flags arg tags = if Tags.mem "pack" tags then Ocaml_arch.forpack_flags_of_pathname arg else N let include_flags_for_deps deps = let dirnames = List.union [] (List.map Pathname.dirname deps) in let include_flags = List.fold_right ocaml_add_include_flag dirnames [] in S include_flags let ocamlc_c tags arg out = let tags = tags++"ocaml"++"byte" in Cmd (S [!Options.ocamlc; A"-c"; T(tags++"compile"); ocaml_ppflags tags; ocaml_include_flags arg; A"-o"; Px out; P arg]) let ocamlc_link flag tags deps out = Cmd (S [!Options.ocamlc; flag; T tags; include_flags_for_deps deps; atomize_paths deps; A"-o"; Px out]) let ocamlc_link_lib = ocamlc_link (A"-a") let ocamlc_link_prog = ocamlc_link N let ocamlmklib tags deps out = Cmd (S [!Options.ocamlmklib; T tags; atomize_paths deps; A"-o"; Px (Pathname.remove_extensions out)]) let ocamlmktop tags deps out = Cmd( S [!Options.ocamlmktop; T (tags++"mktop"); atomize_paths deps; A"-o"; Px out]) let byte_lib_linker tags = if Tags.mem "ocamlmklib" tags then ocamlmklib tags else ocamlc_link_lib tags let byte_lib_linker_tags tags = tags++"ocaml"++"link"++"byte"++"library" let ocamlc_p tags deps out = Cmd (S [!Options.ocamlc; A"-pack"; T tags; atomize_paths deps; A"-o"; Px out]) let ocamlopt_c tags arg out = let tags = tags++"ocaml"++"native" in Cmd (S [!Options.ocamlopt; A"-c"; Ocaml_arch.forpack_flags_of_pathname arg; T(tags++"compile"); ocaml_ppflags tags; ocaml_include_flags arg; A"-o"; Px out (* FIXME ocamlopt bug -o cannot be after the input file *); P arg]) let ocamlopt_link flag tags deps out = Cmd (S [!Options.ocamlopt; flag; forpack_flags out tags; T tags; include_flags_for_deps deps; atomize_paths deps; A"-o"; Px out]) let ocamlopt_link_lib = ocamlopt_link (A"-a") let ocamlopt_link_shared_lib = ocamlopt_link (A"-shared") let ocamlopt_link_prog = ocamlopt_link N let ocamlopt_p tags deps out = let mli = Pathname.update_extensions "mli" out in let cmd = S [!Options.ocamlopt; A"-pack"; forpack_flags out tags; T tags; include_flags_for_deps deps; atomize_paths deps; A"-o"; Px out] in if (*FIXME true ||*) Pathname.exists mli then Cmd cmd else let rm = S[A"rm"; A"-f"; P mli] in Cmd(S[A"touch"; P mli; Sh" ; if "; cmd; Sh" ; then "; rm; Sh" ; else "; rm; Sh" ; exit 1; fi"]) let native_lib_linker tags = if Tags.mem "ocamlmklib" tags then ocamlmklib tags else ocamlopt_link_lib tags let native_shared_lib_linker tags = (* ocamlmklib seems to not support -shared, is this OK? if Tags.mem "ocamlmklib" tags then ocamlmklib tags else *) ocamlopt_link_shared_lib tags let native_lib_linker_tags tags = tags++"ocaml"++"link"++"native"++"library" let prepare_compile build ml = let dir = Pathname.dirname ml in let include_dirs = Pathname.include_dirs_of dir in let modules = path_dependencies_of ml in let results = build (List.map (fun (_, x) -> expand_module include_dirs x ["cmi"]) modules) in List.iter2 begin fun (mandatory, name) res -> match mandatory, res with | _, Good _ -> () | `mandatory, Bad exn -> if not !Options.ignore_auto then raise exn; dprintf 3 "Warning: Failed to build the module %s requested by ocamldep." name; if not (!Options.recursive || Options.ocamlbuild_project_heuristic ()) then Log.at_failure ~name:"a module failed to build, while recursive traversal was disabled by fragile heuristic; hint that having a _tags or myocamlbuild.ml would maybe solve the build error" (fun `Error -> eprintf "Hint:@ Recursive@ traversal@ of@ subdirectories@ \ was@ not@ enabled@ for@ this@ build,@ as@ the@ working@ \ directory does@ not@ look@ like@ an@ ocamlbuild@ project@ \ (no@ '_tags'@ or@ 'myocamlbuild.ml'@ file).@ \ If@ you@ have@ modules@ in@ subdirectories,@ you@ should@ add@ \ the@ option@ \"-r\"@ or@ create@ an@ empty@ '_tags'@ file.@\n\ @\n\ To@ enable@ recursive@ traversal@ for@ some@ subdirectories@ \ only,@ you@ can@ use@ the@ following@ '_tags'@ file:@\n\ @[@,\ true: -traverse@,\ or : traverse@,\ @]" ); | `just_try, Bad _ -> () end modules results let byte_compile_ocaml_interf mli cmi env build = let mli = env mli and cmi = env cmi in prepare_compile build mli; ocamlc_c (tags_of_pathname mli++"interf") mli cmi (* given that .cmi can be built from either ocamlc and ocamlopt, this "agnostic" rule chooses either compilers depending on whether the "native" tag is present. This was requested during PR#4613 as way to enable using ocamlbuild in environments where only ocamlopt is available, not ocamlc. *) let compile_ocaml_interf mli cmi env build = let mli = env mli and cmi = env cmi in prepare_compile build mli; let tags = tags_of_pathname mli++"interf" in let comp_c = if Tags.mem "native" tags then ocamlopt_c else ocamlc_c in comp_c tags mli cmi let byte_compile_ocaml_implem ?tag ml cmo env build = let ml = env ml and cmo = env cmo in prepare_compile build ml; ocamlc_c (Tags.union (tags_of_pathname ml) (tags_of_pathname cmo)++"implem"+++tag) ml cmo let cache_prepare_link = Hashtbl.create 107 let rec prepare_link tag cmx extensions build = let key = (tag, cmx, extensions) in let dir = Pathname.dirname cmx in let include_dirs = Pathname.include_dirs_of dir in let ml = Pathname.update_extensions "ml" cmx in let mli = Pathname.update_extensions "mli" cmx in let modules = List.union (if Pathname.exists (ml-.-"depends") then path_dependencies_of ml else []) (if Pathname.exists (mli-.-"depends") then path_dependencies_of mli else []) in let modules = if (modules = []) && (Pathname.exists (ml^"pack")) then List.map (fun s -> (`mandatory, s)) (string_list_of_file (ml^"pack")) else modules in if modules <> [] && not (Hashtbl.mem cache_prepare_link key) then let () = Hashtbl.add cache_prepare_link key true in let modules' = List.map (fun (_, x) -> expand_module include_dirs x extensions) modules in List.iter2 begin fun (mandatory, _) result -> match mandatory, result with | _, Good p -> prepare_link tag p extensions build | `mandatory, Bad exn -> if not !Options.ignore_auto then raise exn | `just_try, Bad _ -> () end modules (build modules') let native_compile_ocaml_implem ?tag ?(cmx_ext="cmx") ml env build = let ml = env ml in let cmi = Pathname.update_extensions "cmi" ml in let cmx = Pathname.update_extensions cmx_ext ml in prepare_link cmx cmi [cmx_ext; "cmi"] build; ocamlopt_c (Tags.union (tags_of_pathname ml) (tags_of_pathname cmx)++"implem"+++tag) ml cmx let libs_of_use_lib tags = Tags.fold begin fun tag acc -> try let libpath, extern = Hashtbl.find info_libraries tag in if extern then acc else libpath :: acc with Not_found -> acc end tags [] let prepare_libs cma_ext a_ext out build = let out_no_ext = Pathname.remove_extension out in let libs1 = List.union (libraries_of out_no_ext) (libs_of_use_lib (tags_of_pathname out)) in let () = dprintf 10 "prepare_libs: %S -> %a" out pp_l libs1 in let libs = List.map (fun x -> x-.-cma_ext) libs1 in let libs2 = List.map (fun lib -> [lib-.-a_ext]) libs1 in List.iter ignore_good (build libs2); libs let library_index = Hashtbl.create 32 let package_index = Hashtbl.create 32 let hidden_packages = ref [] let hide_package_contents package = hidden_packages := package :: !hidden_packages module Ocaml_dependencies_input = struct let fold_dependencies = Resource.Cache.fold_dependencies let fold_libraries f = Hashtbl.fold f library_index let fold_packages f = Hashtbl.fold f package_index end module Ocaml_dependencies = Ocaml_dependencies.Make(Ocaml_dependencies_input) let caml_transitive_closure = Ocaml_dependencies.caml_transitive_closure let link_one_gen linker tagger cmX out env _build = let cmX = env cmX and out = env out in let tags = tagger (tags_of_pathname out) in linker tags [cmX] out let link_gen cmX_ext cma_ext a_ext extensions linker tagger cmX out env build = let cmX = env cmX and out = env out in let tags = tagger (tags_of_pathname out) in let dyndeps = Rule.build_deps_of_tags build (tags++"link_with") in let cmi = Pathname.update_extensions "cmi" cmX in prepare_link cmX cmi extensions build; let libs = prepare_libs cma_ext a_ext out build in let hidden_packages = List.map (fun x -> x-.-cmX_ext) !hidden_packages in let deps = caml_transitive_closure ~caml_obj_ext:cmX_ext ~caml_lib_ext:cma_ext ~used_libraries:libs ~hidden_packages (cmX :: dyndeps) in let deps = (List.filter (fun l -> not (List.mem l deps)) libs) @ deps in (* Hack to avoid linking twice with the standard library. *) let stdlib = "stdlib/stdlib"-.-cma_ext in let is_not_stdlib x = x <> stdlib in let deps = List.filter is_not_stdlib deps in if deps = [] then failwith "Link list cannot be empty"; let () = dprintf 6 "link: %a -o %a" print_string_list deps Pathname.print out in linker (tags++"dont_link_with") deps out let byte_link_gen = link_gen "cmo" "cma" "cma" ["cmo"; "cmi"] let byte_link = byte_link_gen ocamlc_link_prog (fun tags -> tags++"ocaml"++"link"++"byte"++"program") let byte_output_obj = byte_link_gen ocamlc_link_prog (fun tags -> tags++"ocaml"++"link"++"byte"++"output_obj") let byte_output_shared = byte_link_gen ocamlc_link_prog (fun tags -> tags++"ocaml"++"link"++"byte"++"output_obj"++"output_shared") let byte_library_link = byte_link_gen byte_lib_linker byte_lib_linker_tags let byte_debug_link_gen = link_gen "d.cmo" "d.cma" "d.cma" ["d.cmo"; "cmi"] let byte_debug_link = byte_debug_link_gen ocamlc_link_prog (fun tags -> tags++"ocaml"++"link"++"byte"++"debug"++"program") let byte_debug_library_link = byte_debug_link_gen byte_lib_linker (fun tags -> byte_lib_linker_tags tags++"debug") let native_link_gen linker = link_gen "cmx" "cmxa" !Options.ext_lib [!Options.ext_obj; "cmi"] linker let native_link x = native_link_gen ocamlopt_link_prog (fun tags -> tags++"ocaml"++"link"++"native"++"program") x let native_output_obj x = native_link_gen ocamlopt_link_prog (fun tags -> tags++"ocaml"++"link"++"native"++"output_obj") x let native_output_shared x = native_link_gen ocamlopt_link_prog (fun tags -> tags++"ocaml"++"link"++"native"++"output_obj"++"output_shared") x let native_library_link x = native_link_gen native_lib_linker native_lib_linker_tags x let native_profile_link_gen linker = link_gen "p.cmx" "p.cmxa" ("p" -.- !Options.ext_lib) ["p" -.- !Options.ext_obj; "cmi"] linker let native_profile_link x = native_profile_link_gen ocamlopt_link_prog (fun tags -> tags++"ocaml"++"link"++"native"++"profile"++"program") x let native_profile_library_link x = native_profile_link_gen native_lib_linker (fun tags -> native_lib_linker_tags tags++"profile") x let link_units table extensions cmX_ext cma_ext a_ext linker tagger contents_list cmX env build = let cmX = env cmX in let tags = tagger (tags_of_pathname cmX) in let _ = Rule.build_deps_of_tags build tags in let dir = let dir1 = Pathname.remove_extensions cmX in if Resource.exists_in_source_dir dir1 then dir1 else Pathname.dirname cmX in let include_dirs = Pathname.include_dirs_of dir in let extension_keys = List.map fst extensions in let libs = prepare_libs cma_ext a_ext cmX build in let results = build begin List.map begin fun module_name -> expand_module include_dirs module_name extension_keys end contents_list end in let module_paths = List.map begin function | Good p -> let extension_values = List.assoc (Pathname.get_extensions p) extensions in List.iter begin fun ext -> List.iter ignore_good (build [[Pathname.update_extensions ext p]]) end extension_values; p | Bad exn -> raise exn end results in Hashtbl.replace table cmX module_paths; let hidden_packages = List.map (fun x -> x-.-cmX_ext) !hidden_packages in let deps = caml_transitive_closure ~caml_obj_ext:cmX_ext ~caml_lib_ext:cma_ext ~hidden_packages ~pack_mode:true module_paths in let full_contents = libs @ module_paths in let deps = List.filter (fun x -> List.mem x full_contents) deps in let deps = (List.filter (fun l -> not (List.mem l deps)) libs) @ deps in (* Hack to avoid linking twice with the standard library. *) let stdlib = "stdlib/stdlib"-.-cma_ext in let is_not_stdlib x = x <> stdlib in let deps = List.filter is_not_stdlib deps in linker tags deps cmX let link_modules = link_units library_index let pack_modules = link_units package_index let link_from_file link modules_file cmX env build = let modules_file = env modules_file in let contents_list = string_list_of_file modules_file in link contents_list cmX env build let byte_library_link_modules = link_modules [("cmo",[])] "cmo" "cma" "cma" byte_lib_linker byte_lib_linker_tags let byte_library_link_mllib = link_from_file byte_library_link_modules let byte_toplevel_link_modules = link_modules [("cmo",[])] "cmo" "cma" "cma" ocamlmktop (fun tags -> tags++"ocaml"++"link"++"byte"++"toplevel") let byte_toplevel_link_mltop = link_from_file byte_toplevel_link_modules let byte_debug_library_link_modules = link_modules [("d.cmo",[])] "d.cmo" "d.cma" "d.cma" byte_lib_linker (fun tags -> byte_lib_linker_tags tags++"debug") let byte_debug_library_link_mllib = link_from_file byte_debug_library_link_modules let byte_pack_modules = pack_modules [("cmo",["cmi"]); ("cmi",[])] "cmo" "cma" "cma" ocamlc_p (fun tags -> tags++"ocaml"++"pack"++"byte") let byte_pack_mlpack = link_from_file byte_pack_modules let byte_debug_pack_modules = pack_modules [("d.cmo",["cmi"]); ("cmi",[])] "d.cmo" "d.cma" "d.cma" ocamlc_p (fun tags -> tags++"ocaml"++"pack"++"byte"++"debug") let byte_debug_pack_mlpack = link_from_file byte_debug_pack_modules let native_pack_modules x = pack_modules [("cmx",["cmi"; !Options.ext_obj]); ("cmi",[])] "cmx" "cmxa" !Options.ext_lib ocamlopt_p (fun tags -> tags++"ocaml"++"pack"++"native") x let native_pack_mlpack = link_from_file native_pack_modules let native_profile_pack_modules x = pack_modules [("p.cmx",["cmi"; "p" -.- !Options.ext_obj]); ("cmi",[])] "p.cmx" "p.cmxa" ("p" -.- !Options.ext_lib) ocamlopt_p (fun tags -> tags++"ocaml"++"pack"++"native"++"profile") x let native_profile_pack_mlpack = link_from_file native_profile_pack_modules let native_library_link_modules x = link_modules [("cmx",[!Options.ext_obj])] "cmx" "cmxa" !Options.ext_lib native_lib_linker native_lib_linker_tags x let native_shared_library_link_modules x = link_modules [("cmx",[!Options.ext_obj])] "cmx" "cmxa" !Options.ext_lib native_shared_lib_linker (fun tags -> native_lib_linker_tags tags++"shared") x let native_library_link_mllib = link_from_file native_library_link_modules let native_shared_library_link_mldylib = link_from_file native_shared_library_link_modules let native_shared_library_tags tags basetags = List.fold_left (++) (basetags++"ocaml"++"link"++"native"++"shared"++"library") tags let native_shared_library_link ?(tags = []) x = link_one_gen native_shared_lib_linker (native_shared_library_tags tags) x let native_profile_library_link_modules x = link_modules [("p.cmx",["p" -.- !Options.ext_obj])] "p.cmx" "p.cmxa" ("p" -.- !Options.ext_lib) native_lib_linker (fun tags -> native_lib_linker_tags tags++"profile") x let native_profile_shared_library_link_modules x = link_modules [("p.cmx",["p" -.- !Options.ext_obj])] "p.cmx" "p.cmxa" ("p" -.- !Options.ext_lib) native_shared_lib_linker (fun tags -> native_lib_linker_tags tags++"shared"++"profile") x let native_profile_library_link_mllib = link_from_file native_profile_library_link_modules let native_profile_shared_library_link_mldylib = link_from_file native_profile_shared_library_link_modules ocamlbuild-0.14.3/src/ocaml_compiler.mli000066400000000000000000000124661454061437200202100ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val forpack_flags : string -> Tags.t -> Command.spec val ocamlc_c : Tags.t -> Pathname.t -> Pathname.t -> Command.t val ocamlc_link_lib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlc_link_prog : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlc_p : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlopt_c : Tags.t -> Pathname.t -> Pathname.t -> Command.t val ocamlopt_link_lib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlopt_link_shared_lib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlopt_link_prog : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlopt_p : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlmklib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val ocamlmktop : Tags.t -> Pathname.t list -> Pathname.t -> Command.t val prepare_compile : Rule.builder -> Pathname.t -> unit val compile_ocaml_interf : string -> string -> Rule.action val byte_compile_ocaml_interf : string -> string -> Rule.action val byte_compile_ocaml_implem : ?tag:string -> string -> string -> Rule.action val prepare_link : Pathname.t -> Pathname.t -> string list -> Rule.builder -> unit val native_compile_ocaml_implem : ?tag:string -> ?cmx_ext:string -> string -> Rule.action val prepare_libs : string -> string -> Pathname.t -> Rule.builder -> Pathname.t list val link_gen : string -> string -> string -> string list -> (Tags.t -> Pathname.t list -> Pathname.t -> Command.t) -> (Tags.t -> Tags.t) -> string -> string -> Rule.action val byte_link : string -> string -> Rule.action val byte_output_obj : string -> string -> Rule.action val byte_output_shared : string -> string -> Rule.action val byte_library_link : string -> string -> Rule.action val byte_debug_link : string -> string -> Rule.action val byte_debug_library_link : string -> string -> Rule.action val native_link : string -> string -> Rule.action val native_output_obj : string -> string -> Rule.action val native_output_shared : string -> string -> Rule.action val native_library_link : string -> string -> Rule.action val native_shared_library_link : ?tags:(string list) -> string -> string -> Rule.action val native_profile_link : string -> string -> Rule.action val native_profile_library_link : string -> string -> Rule.action val link_modules : (Pathname.t * string list) list -> string -> string -> string -> (Tags.t -> Pathname.t list -> Pathname.t -> Command.t) -> (Tags.t -> Tags.t) -> string list -> string -> Rule.action val pack_modules : (Pathname.t * string list) list -> string -> string -> string -> (Tags.t -> Pathname.t list -> Pathname.t -> Command.t) -> (Tags.t -> Tags.t) -> string list -> string -> Rule.action val byte_library_link_modules : string list -> string -> Rule.action val byte_library_link_mllib : string -> string -> Rule.action val byte_debug_library_link_modules : string list -> string -> Rule.action val byte_debug_library_link_mllib : string -> string -> Rule.action val byte_pack_modules : string list -> string -> Rule.action val byte_pack_mlpack : string -> string -> Rule.action val byte_debug_pack_modules : string list -> string -> Rule.action val byte_debug_pack_mlpack : string -> string -> Rule.action val byte_toplevel_link_modules : string list -> string -> Rule.action val byte_toplevel_link_mltop : string -> string -> Rule.action val native_pack_modules : string list -> string -> Rule.action val native_pack_mlpack : string -> string -> Rule.action val native_library_link_modules : string list -> string -> Rule.action val native_library_link_mllib : string -> string -> Rule.action val native_shared_library_link_modules : string list -> string -> Rule.action val native_shared_library_link_mldylib : string -> string -> Rule.action val native_profile_pack_modules : string list -> string -> Rule.action val native_profile_pack_mlpack : string -> string -> Rule.action val native_profile_library_link_modules : string list -> string -> Rule.action val native_profile_library_link_mllib : string -> string -> Rule.action val native_profile_shared_library_link_modules : string list -> string -> Rule.action val native_profile_shared_library_link_mldylib : string -> string -> Rule.action (** [hide_package_contents pack_name] Don't treat the given package as an open package. So a module will not be replaced during linking by this package even if it contains that module. *) val hide_package_contents : string -> unit ocamlbuild-0.14.3/src/ocaml_dependencies.ml000066400000000000000000000170351454061437200206500ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Log open Tools open Ocaml_utils let mydprintf fmt = dprintf 10 fmt exception Circular_dependencies of string list * string module type INPUT = sig val fold_dependencies : (string -> string -> 'a -> 'a) -> 'a -> 'a val fold_libraries : (string -> string list -> 'a -> 'a) -> 'a -> 'a val fold_packages : (string -> string list -> 'a -> 'a) -> 'a -> 'a end module Make (I : INPUT) = struct open I module SMap = Map.Make(String) module Resources = Resource.Resources module Utils = struct let add = SMap.add let empty = SMap.empty let find_all_set x acc = try SMap.find x acc with Not_found -> Resources.empty let smap_add_set src dst acc = SMap.add src (Resources.add dst (find_all_set src acc)) acc let print_smap pp f smap = Format.fprintf f "@[{:@["; SMap.iter begin fun k v -> Format.fprintf f "@ @[<2>%S =>@ %a@];" k pp v end smap; Format.fprintf f "@]@,:}@]" let print_smap_list = print_smap pp_l let print_smap_set = print_smap Resources.print let print_lazy pp f l = pp f !*l let find_all_list x acc = try SMap.find x acc with Not_found -> [] let find_all_rec xs map = let visited = Hashtbl.create 32 in let rec self x acc = try Hashtbl.find visited x; acc with Not_found -> Hashtbl.replace visited x (); let acc = Resources.add x acc in try Resources.fold self (SMap.find x map) acc with Not_found -> acc in List.fold_right self xs Resources.empty let mkindex fold filter = fold begin fun name contents acc -> if filter name then List.fold_right begin fun elt acc -> add elt (name :: (find_all_list elt acc)) acc end contents acc else acc end empty end open Utils let caml_transitive_closure ?(caml_obj_ext="cmo") ?(caml_lib_ext="cma") ?(pack_mode=false) ?(used_libraries=[]) ?(hidden_packages=[]) fns = let valid_link_exts = if pack_mode then [caml_obj_ext; "cmi"] else [caml_obj_ext; caml_lib_ext] in mydprintf "caml_transitive_closure@ ~caml_obj_ext:%S@ ~pack_mode:%b@ ~used_libraries:%a@ %a" caml_obj_ext pack_mode pp_l used_libraries pp_l fns; let packages = fold_packages (fun name _ -> Resources.add name) Resources.empty in mydprintf "packages:@ %a" Resources.print packages; let caml_obj_ext_of_cmi x = if Filename.check_suffix x ".cmi" then Pathname.update_extensions caml_obj_ext x else x in let maybe_caml_obj_ext_of_cmi x = if pack_mode then if Filename.check_suffix x ".cmi" then let caml_obj = Pathname.update_extensions caml_obj_ext x in if Resource.exists_in_build_dir caml_obj then caml_obj else x else x else if Filename.check_suffix x ".cmi" then Pathname.update_extensions caml_obj_ext x else x in let not_linkable x = not (List.exists (Pathname.check_extension x) valid_link_exts) in let dependency_map = fold_dependencies begin fun x y acc -> let x = maybe_caml_obj_ext_of_cmi x and y = maybe_caml_obj_ext_of_cmi y in if x = y || not_linkable x || not_linkable y then acc else smap_add_set x y acc end SMap.empty in mydprintf "dependency_map:@ %a" print_smap_set dependency_map; let used_files = find_all_rec fns dependency_map in mydprintf "used_files:@ %a" Resources.print used_files; let open_packages = Resources.fold begin fun file acc -> if Resources.mem file packages && not (List.mem file hidden_packages) then file :: acc else acc end used_files [] in mydprintf "open_packages:@ %a" pp_l open_packages; let index_filter ext list x = Pathname.check_extension x ext && List.mem x list in let lib_index = lazy (mkindex fold_libraries (index_filter caml_lib_ext used_libraries)) in mydprintf "lib_index:@ %a" (print_lazy print_smap_list) lib_index; let package_index = lazy (mkindex fold_packages (index_filter caml_obj_ext open_packages)) in let rec resolve_packages x = match find_all_list x !*package_index with | [] -> x | [x] -> resolve_packages x | pkgs -> failwith (sbprintf "the file %S is included in more than one active open package (%a)" x pp_l pkgs) in let libs_of x = find_all_list x !*lib_index in let lib_of x = match libs_of x with | [] -> None | [lib] -> Some(lib) | libs -> failwith (sbprintf "the file %S is included in more than one active library (%a)" x pp_l libs) in let convert_dependency src dst acc = let src = resolve_packages src in let dst = resolve_packages dst in let add_if_diff x y = if x = y then acc else smap_add_set x y acc in match (lib_of src, lib_of dst) with | None, None -> add_if_diff src dst | Some(liba), Some(libb) -> add_if_diff liba libb | Some(lib), None -> add_if_diff lib dst | None, Some(lib) -> add_if_diff src lib in let dependencies = lazy begin SMap.fold begin fun k -> Resources.fold (convert_dependency k) end dependency_map empty end in mydprintf "dependencies:@ %a" (print_lazy print_smap_set) dependencies; let dependencies_of x = try SMap.find x !*dependencies with Not_found -> Resources.empty in let needed_in_order = ref [] in let needed = ref Resources.empty in let rec aux on_the_go fn = if sys_file_exists fn && not (Resources.mem fn !needed) then begin begin match List.index_of fn on_the_go with | None -> () (* good no cycle *) | Some n -> raise (Circular_dependencies(fst (List.split_at (n+1) on_the_go), fn)) end; let on_the_go = fn::on_the_go in Resources.iter begin fun f -> if sys_file_exists f then if Filename.check_suffix f ".cmi" then let f' = caml_obj_ext_of_cmi f in if f' <> fn then if sys_file_exists f' then aux on_the_go f' else if pack_mode then aux on_the_go f else () else () else aux on_the_go f end (dependencies_of fn); needed := Resources.add fn !needed; needed_in_order := fn :: !needed_in_order end in List.iter (aux []) fns; mydprintf "caml_transitive_closure:@ %a ->@ %a" pp_l fns pp_l !needed_in_order; List.rev !needed_in_order end ocamlbuild-0.14.3/src/ocaml_dependencies.mli000066400000000000000000000041471454061437200210210ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (** OCaml dependencies *) exception Circular_dependencies of string list * string (** Give to this module a way to access libraries, packages, and dependencies between files. *) module type INPUT = sig val fold_dependencies : (string -> string -> 'a -> 'a) -> 'a -> 'a val fold_libraries : (string -> string list -> 'a -> 'a) -> 'a -> 'a val fold_packages : (string -> string list -> 'a -> 'a) -> 'a -> 'a end (** Wait an [INPUT] module and gives a function to compute the transitive closure of caml file takeing in account libraries and packages. *) module Make (I : INPUT) : sig (** [caml_transitive_closure] takes a list of root ocaml compiled files and returns the list of files that must be given to a linker. Optionally you can change the extension of caml object/library files (cmo/cma by default); use the pack mode (false by default) to include only root files (just sort them); and gives the list of used libraries (empty by default). *) val caml_transitive_closure : ?caml_obj_ext:string -> ?caml_lib_ext:string -> ?pack_mode:bool -> ?used_libraries:string list -> ?hidden_packages:string list -> Pathname.t list -> Pathname.t list end ocamlbuild-0.14.3/src/ocaml_specific.ml000066400000000000000000001225271454061437200200120ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Format open Log open Pathname.Operators open Tags.Operators open Rule open Tools open Rule.Common_commands open Outcome open Command;; open Ocaml_utils module C_tools = struct let link_C_library clib a libname env build = let clib = env clib and a = env a and libname = env libname in let objs = string_list_of_file clib in let include_dirs = Pathname.include_dirs_of (Pathname.dirname a) in let obj_of_o x = if Filename.check_suffix x ".o" && !Options.ext_obj <> "o" then Pathname.update_extension !Options.ext_obj x else x in let results = build (List.map (fun o -> List.map (fun dir -> dir / obj_of_o o) include_dirs) objs) in let objs = List.map begin function | Good o -> o | Bad exn -> raise exn end results in Cmd(S[!Options.ocamlmklib; A"-o"; Px libname; T(tags_of_pathname a++"c"++"ocamlmklib"); atomize objs]);; let make_single_library cobj_base clib env _build = Echo ([env cobj_base; ".o"; "\n"], env clib) end open Flags open Command open Rule let init () = let module M = struct let ext_lib = !Options.ext_lib;; let ext_obj = !Options.ext_obj;; let ext_dll = !Options.ext_dll;; let x_o = "%"-.-ext_obj;; let x_a = "%"-.-ext_lib;; let x_dll = "%"-.-ext_dll;; let x_p_o = "%.p"-.-ext_obj;; let x_p_a = "%.p"-.-ext_lib;; let x_p_dll = "%.p"-.-ext_dll;; (* -output-obj targets *) let x_byte_c = "%.byte.c";; let x_byte_o = "%.byte"-.-ext_obj;; let x_byte_so = "%.byte"-.-ext_dll;; let x_native_o = "%.native"-.-ext_obj;; let x_native_so = "%.native"-.-ext_dll;; rule "target files" ~dep:"%.itarget" ~stamp:"%.otarget" ~doc:"If foo.itarget contains a list of ocamlbuild targets, \ asking ocamlbuild to produce foo.otarget will \ build each of those targets in turn." begin fun env build -> let itarget = env "%.itarget" in let targets = let dir = Pathname.dirname itarget in let files = string_list_of_file itarget in List.map (fun file -> [Pathname.concat dir file]) files in let results = List.map Outcome.good (build targets) in let link_command result = Cmd (S [A "ln"; A "-sf"; P (Pathname.concat !Options.build_dir result); A Pathname.pwd]) in if not !Options.make_links then Nop else Seq (List.map link_command results) end;; rule "ocaml: mli -> cmi" ~prod:"%.cmi" ~deps:["%.mli"; "%.mli.depends"] (Ocaml_compiler.compile_ocaml_interf "%.mli" "%.cmi");; rule "ocaml: mlpack & d.cmo* -> d.cmo & cmi" ~prods:["%.d.cmo"] ~deps:["%.mlpack"; "%.cmi"] (Ocaml_compiler.byte_debug_pack_mlpack "%.mlpack" "%.d.cmo");; rule "ocaml: mlpack & cmo* & cmi -> cmo" ~prod:"%.cmo" ~deps:["%.mli"; "%.cmi"; "%.mlpack"] ~doc:"If foo.mlpack contains a list of capitalized module names, \ the target foo.cmo will produce a packed module containing \ those modules as submodules. You can also have a foo.mli file \ to restrict the interface of the resulting module. \ Warning: to produce a native foo.cmx out of a foo.mlpack, you must \ manually tag the included compilation units with for-pack(foo). \ See the documentation of the corresponding rules for more details. \ The modules named in the .mlpack \ will be dynamic dependencies of the compilation action. \ You cannot give the .mlpack the same name as one of the module \ it contains, as this would create a circular dependency." (Ocaml_compiler.byte_pack_mlpack "%.mlpack" "%.cmo");; rule "ocaml: mlpack & cmo* -> cmo & cmi" ~prods:["%.cmo"; "%.cmi"] ~dep:"%.mlpack" (Ocaml_compiler.byte_pack_mlpack "%.mlpack" "%.cmo");; rule "ocaml: ml & cmi -> d.cmo" ~prod:"%.d.cmo" ~deps:["%.mli"(* This one is inserted to force this rule to be skiped when a .ml is provided without a .mli *); "%.ml"; "%.ml.depends"; "%.cmi"] ~doc:"The foo.d.cmo target compiles foo.ml with the 'debug' tag enabled (-g).\ See also foo.d.byte. \ For technical reason, .d.cmx and .d.native are not yet supported, \ so you should explicitly add the 'debug' tag \ to native targets (both compilation and linking)." (Ocaml_compiler.byte_compile_ocaml_implem ~tag:"debug" "%.ml" "%.d.cmo");; rule "ocaml: ml & cmi -> cmo" ~prod:"%.cmo" ~deps:["%.mli"(* This one is inserted to force this rule to be skiped when a .ml is provided without a .mli *); "%.ml"; "%.ml.depends"; "%.cmi"] (Ocaml_compiler.byte_compile_ocaml_implem "%.ml" "%.cmo");; rule "ocaml: mlpack & cmi & p.cmx* & p.o* -> p.cmx & p.o" ~prods:["%.p.cmx"; x_p_o (* no cmi here you must make the byte version to have it *)] ~deps:["%.mlpack"; "%.cmi"] (Ocaml_compiler.native_profile_pack_mlpack "%.mlpack" "%.p.cmx");; rule "ocaml: mlpack & cmi & cmx* & o* -> cmx & o" ~prods:["%.cmx"; x_o (* no cmi here you must make the byte version to have it *)] ~deps:["%.mlpack"; "%.cmi"] ~doc:"If foo.mlpack contains a list of capitalized module names, \ the target foo.cmx will produce a packed module containing \ those modules as submodules. \ Warning: The .cmx files that will be included must be manually tagged \ with the tag \"for-pack(foo)\". This means that you cannot include \ the same bar.cmx in several .mlpack files, and that you should not \ use an included .cmx as a separate module on its own. \ This requirement comes from a technical limitation of \ native module packing: ocamlopt needs the -for-pack argument to be passed \ ahead of time, when compiling each included submodule, \ because there is no reliable, portable way to rewrite \ native object files afterwards." (Ocaml_compiler.native_pack_mlpack "%.mlpack" "%.cmx");; rule "ocaml: ml & cmi -> p.cmx & p.o" ~prods:["%.p.cmx"; x_p_o] ~deps:["%.ml"; "%.ml.depends"; "%.cmi"] ~doc:"The foo.p.cmx target compiles foo.ml with the 'profile' \ tag enabled (-p). Note that ocamlbuild provides no support \ for the bytecode profiler, which works completely differently." (Ocaml_compiler.native_compile_ocaml_implem ~tag:"profile" ~cmx_ext:"p.cmx" "%.ml");; rule "ocaml: ml & cmi -> cmx & o" ~prods:["%.cmx"; x_o] ~deps:["%.ml"; "%.ml.depends"; "%.cmi"] (Ocaml_compiler.native_compile_ocaml_implem "%.ml");; rule "ocaml: ml -> d.cmo & cmi" ~prods:["%.d.cmo"] ~deps:["%.ml"; "%.ml.depends"; "%.cmi"] (Ocaml_compiler.byte_compile_ocaml_implem ~tag:"debug" "%.ml" "%.d.cmo");; rule "ocaml: ml -> cmo & cmi" ~prods:["%.cmo"; "%.cmi"] ~deps:["%.ml"; "%.ml.depends"] ~doc:"This rule allows to produce a .cmi from a .ml file \ when the corresponding .mli is missing. \ Note: you are strongly encourage to have a .mli file \ for each of your .ml module, as it is a good development \ practice which also simplifies the way build systems work, \ as it avoids producing .cmi files as a silent side-effect of \ another compilation action." (Ocaml_compiler.byte_compile_ocaml_implem "%.ml" "%.cmo");; rule "ocaml: d.cmo* -> d.byte" ~prod:"%.d.byte" ~dep:"%.d.cmo" ~doc:"The target foo.d.byte will build a bytecode executable \ with debug information enabled." (Ocaml_compiler.byte_debug_link "%.d.cmo" "%.d.byte");; rule "ocaml: cmo* -> byte" ~prod:"%.byte" ~dep:"%.cmo" (Ocaml_compiler.byte_link "%.cmo" "%.byte");; rule "ocaml: cmo* -> byte.(o|obj)" ~prod:x_byte_o ~dep:"%.cmo" ~doc:"The foo.byte.o target, or foo.byte.obj under Windows, \ will produce an object file by passing the -output-obj option \ to the OCaml compiler. See also foo.byte.c, and foo.native.{o,obj}." (Ocaml_compiler.byte_output_obj "%.cmo" x_byte_o);; rule "ocaml: cmo* -> byte.c" ~prod:x_byte_c ~dep:"%.cmo" (Ocaml_compiler.byte_output_obj "%.cmo" x_byte_c);; rule "ocaml: cmo* -> byte.(so|dll)" ~prod:x_byte_so ~dep:"%.cmo" ~doc:"The foo.byte.so target, or foo.byte.dll under Windows \ and macOS will produce a shared library file by passing \ the -output-obj option to the OCaml compiler. \ See also foo.native.{so,dll}." (Ocaml_compiler.byte_output_shared "%.cmo" x_byte_so);; rule "ocaml: p.cmx* & p.o* -> p.native" ~prod:"%.p.native" ~deps:["%.p.cmx"; x_p_o] ~doc:"The foo.p.native target builds the native executable \ with the 'profile' tag (-p) enabled throughout compilation and linking." (Ocaml_compiler.native_profile_link "%.p.cmx" "%.p.native");; rule "ocaml: cmx* & o* -> native" ~prod:"%.native" ~deps:["%.cmx"; x_o] ~doc:"Builds a native executable" (Ocaml_compiler.native_link "%.cmx" "%.native");; rule "ocaml: cmx* & o* -> native.(o|obj)" ~prod:x_native_o ~deps:["%.cmx"; x_o] (Ocaml_compiler.native_output_obj "%.cmx" x_native_o);; rule "ocaml: cmx* & o* -> native.(so|dll)" ~prod:x_native_so ~deps:["%.cmx"; x_o] (Ocaml_compiler.native_output_shared "%.cmx" x_native_so);; rule "ocaml: mllib & d.cmo* -> d.cma" ~prod:"%.d.cma" ~dep:"%.mllib" (Ocaml_compiler.byte_debug_library_link_mllib "%.mllib" "%.d.cma");; rule "ocaml: mllib & cmo* -> cma" ~prod:"%.cma" ~dep:"%.mllib" ~doc:"Build a .cma archive file (bytecode library) containing \ the list of modules (`Foo`, `subdir/Bar`) given in the .mllib file \ of the same name, one per line. \ Note that the .cma archive will contain exactly the modules listed, \ so it may not be self-contained if some dependencies are missing." (Ocaml_compiler.byte_library_link_mllib "%.mllib" "%.cma");; rule "ocaml: d.cmo* -> d.cma" ~prod:"%.d.cma" ~dep:"%.d.cmo" (Ocaml_compiler.byte_debug_library_link "%.d.cmo" "%.d.cma");; rule "ocaml: cmo* -> cma" ~prod:"%.cma" ~dep:"%.cmo" ~doc:"The preferred way to build a .cma archive is to create a .mllib file \ with a list of modules to include. It is however possible to build one \ from a .cmo of the same name; the archive will include this module and \ the local modules it depends upon, transitively." (Ocaml_compiler.byte_library_link "%.cmo" "%.cma");; rule "ocaml C stubs: clib & (o|obj)* -> (a|lib) & (so|dll)" ~prods:(["%(path:<**/>)lib%(libname:<*> and not <*.*>)"-.-ext_lib] @ if Ocamlbuild_config.supports_shared_libraries then ["%(path:<**/>)dll%(libname:<*> and not <*.*>)"-.-ext_dll] else []) ~dep:"%(path)lib%(libname).clib" ~doc:"OCamlbuild can create a C library by calling ocamlmklib \ with the file paths listed (one per line) in libfoo.clib. \ To build a static library from libfoo.clib, you should \ request libfoo.a (or libfoo.lib on Windows), and to build \ a dynamic library you should request libfoo.so (or libfoo.dll \ on Windows). Finally, any file listed in the .clib \ with name 'bar/baz.o' will link 'bar/baz.obj' instead on Windows. \ This means that using the .o extension will give portable clib files, \ even if it is not the object file extension on your system." (C_tools.link_C_library "%(path)lib%(libname).clib" ("%(path)lib%(libname)"-.-ext_lib) "%(path)%(libname)");; rule "ocaml C stubs: (o|obj) -> clib" ~prod:"%(path:<**/>)lib%(libname:<*> and not <*.*>).clib" ~dep:("%(path)%(libname)"-.-ext_obj) ~doc:"The preferred way to build a C library libfoo.a is to create \ a libfoo.clib file with a list of C object files to include. \ It is however possible to build one from a .(o|obj) file of \ corresponding name, foo.(o|obj); the library will include this \ object file only." (C_tools.make_single_library "%(path)%(libname)" "%(path)lib%(libname).clib");; (** Static libraries (.cmxa) and (.cmxs): Historically ocamlbuild had a bit too many .cmxs-related rules for its own good. There were rules to build a .cmxs from a .mldylib, but also from a .cmxa, and from a .cmx. In particular, the latter two options conflicted with the rule to build a .cmxa from a .cmx, giving two distinct ways to build a .cmxs from a .cmx, giving two different results. The new design is as follows: - First we declare, with the highest priority, the *explicit* rules, the one where the users expresses its intent. + .mllib -> .cmxa + .mldylib -> .cmxs - Then we declare, with lower priority, the *implicit* rules that are given for the user convenience. We ask that these rules do not conflict with each other by creating distinct paths to build the same target. + .cmx -> .cmxa (to mirror the bytecode rule .cmo -> .cma) + .cmxa -> .cmxs In particular, we had to remove the (.cmx -> .cmxs) rules, which conflicts with the two other low-priority rules. The user willing to recover this semantics should write a .mldylib rule with a single module name in it. *) rule "ocaml: mllib & p.cmx* & p.o* -> p.cmxa & p.a" ~prods:["%.p.cmxa"; x_p_a] ~dep:"%.mllib" (Ocaml_compiler.native_profile_library_link_mllib "%.mllib" "%.p.cmxa");; rule "ocaml: mllib & cmx* & o* -> cmxa & a" ~prods:["%.cmxa"; x_a] ~dep:"%.mllib" ~doc:"Creates a native archive file .cmxa, using the .mllib file \ as the .cma rule above. Note that whereas bytecode .cma can \ be used both for static and dynamic linking, .cmxa only support \ static linking. For an archive usable with Dynlink, \ see the rules producing a .cmxs from a .mllib or a .mldylib." (Ocaml_compiler.native_library_link_mllib "%.mllib" "%.cmxa");; rule "ocaml: mldylib & p.cmx* & p.o* -> p.cmxs" ~prods:["%.p.cmxs"] ~dep:"%.mldylib" (Ocaml_compiler.native_profile_shared_library_link_mldylib "%.mldylib" "%.p.cmxs");; rule "ocaml: mldylib & cmx* & o* -> cmxs" ~prods:["%.cmxs"] ~dep:"%.mldylib" ~doc:"Builds a .cmxs (native archive for dynamic linking) containing exactly \ the modules listed in the corresponding .mldylib file." (Ocaml_compiler.native_shared_library_link_mldylib "%.mldylib" "%.cmxs");; rule "ocaml: p.cmx & p.o -> p.cmxa & p.a" ~prods:["%.p.cmxa"; x_p_a] ~deps:["%.p.cmx"; x_p_o] (Ocaml_compiler.native_profile_library_link "%.p.cmx" "%.p.cmxa");; rule "ocaml: cmx & o -> cmxa & a" ~prods:["%.cmxa"; x_a] ~deps:["%.cmx"; x_o] ~doc:"Just as you can build a .cma from a .cmo in absence of .mllib file, \ you can build a .cmxa (native archive file for static linking only) \ from a .cmx, which will include the local modules it depends upon, \ transitivitely." (Ocaml_compiler.native_library_link "%.cmx" "%.cmxa");; rule "ocaml: p.cmxa & p.a -> p.cmxs" ~prods:["%.p.cmxs"] ~deps:["%.p.cmxa"] (Ocaml_compiler.native_shared_library_link ~tags:["profile";"linkall"] "%.p.cmxa" "%.p.cmxs");; rule "ocaml: cmxa -> cmxs" ~prods:["%.cmxs"] ~deps:["%.cmxa"] ~doc:"This rule allows to build a .cmxs from a .cmxa, to avoid having \ to duplicate a .mllib file into a .mldylib." (Ocaml_compiler.native_shared_library_link ~tags:["linkall"] "%.cmxa" "%.cmxs");; rule "ocaml dependencies ml" ~prod:"%.ml.depends" ~dep:"%.ml" ~doc:"OCamlbuild will use ocamldep to approximate dependencies \ of a source file. The ocamldep tool being purely syntactic, \ it only computes an over-approximation of the dependencies. \ If you manipulate a module Foo that is in fact a submodule Bar.Foo \ (after 'open Bar'), ocamldep may believe that your module depends \ on foo.ml -- when such a file also exists in your project. This can \ lead to spurious circular dependencies. In that case, you can use \ OCamlbuild_plugin.non_dependency in your myocamlbuild.ml \ to manually remove the spurious dependency. See the plugins API." (Ocaml_tools.ocamldep_command "%.ml" "%.ml.depends");; rule "ocaml dependencies mli" ~prod:"%.mli.depends" ~dep:"%.mli" (Ocaml_tools.ocamldep_command "%.mli" "%.mli.depends");; rule "ocamllex" ~prod:"%.ml" ~dep:"%.mll" (Ocaml_tools.ocamllex "%.mll");; rule "ocaml: mli -> odoc" ~prod:"%.odoc" ~deps:["%.mli"; "%.mli.depends"] ~doc:".odoc are intermediate files storing the result of ocamldoc processing \ on a source file. See the various .docdir/... targets for ocamldoc." (Ocaml_tools.document_ocaml_interf "%.mli" "%.odoc");; rule "ocaml: ml -> odoc" ~prod:"%.odoc" ~deps:["%.ml"; "%.ml.depends"] (Ocaml_tools.document_ocaml_implem "%.ml" "%.odoc");; rule "ocamldoc: document ocaml project odocl & *odoc -> docdir (html)" ~prod:"%.docdir/index.html" ~stamp:"%.docdir/html.stamp" ~dep:"%.odocl" ~doc:"the target foo.docdir/index.html will call ocamldoc to produce \ the html documentation for the module paths listed \ in foo.odocl, one per line. \ See also the man|latex|texinfo|dot target below." (Ocaml_tools.document_ocaml_project ~tags:["html"] ~ocamldoc:Ocaml_tools.ocamldoc_l_dir "%.odocl" "%.docdir/index.html" "%.docdir");; rule "ocamldoc: document ocaml project odocl & *odoc -> docdir (man)" ~prod:"%.docdir/man" ~stamp:"%.docdir/man.stamp" ~dep:"%.odocl" ~doc:"The target foo.docdir/man will call ocamldoc to produce \ documentation, in man format, for the module paths \ listed in foo.odocl, one per line." (Ocaml_tools.document_ocaml_project ~tags:["man"] ~ocamldoc:Ocaml_tools.ocamldoc_l_dir "%.odocl" "%.docdir/man" "%.docdir");; rule "ocamldoc: document ocaml project odocl & *odoc -> latex" ~prod:"%(dir).docdir/%(file).%(ext:\"tex\" or \"ltx\")" ~dep:"%(dir).odocl" ~doc:"The target foo.docdir/bar.tex (or bar.ltx) will call ocamldoc \ to produce documentation, in LaTeX format, for the module paths \ listed in foo.odocl, one per line." (Ocaml_tools.document_ocaml_project ~tags:["tex"] ~ocamldoc:Ocaml_tools.ocamldoc_l_file "%(dir).odocl" "%(dir).docdir/%(file).%(ext)" "%(dir).docdir");; rule "ocamldoc: document ocaml project odocl & *odoc -> texinfo" ~prod:"%(dir).docdir/%(file).texi" ~dep:"%(dir).odocl" ~doc:"The target foo.docdir/bar.texi will call ocamldoc to produce \ documentation, in TeXinfo format, for the module paths \ listed in foo.odocl, one per line." (Ocaml_tools.document_ocaml_project ~tags:["texi"] ~ocamldoc:Ocaml_tools.ocamldoc_l_file "%(dir).odocl" "%(dir).docdir/%(file).texi" "%(dir).docdir");; rule "ocamldoc: document ocaml project odocl & *odoc -> dot" ~prod:"%(dir).docdir/%(file).dot" ~dep:"%(dir).odocl" ~doc:"The target foo.docdir/bar.dot will generate a dot graph of module \ dependencies." (Ocaml_tools.document_ocaml_project ~tags:["dot"] ~ocamldoc:Ocaml_tools.ocamldoc_l_file "%(dir).odocl" "%(dir).docdir/%(file).dot" "%(dir).docdir");; (* To use menhir give the -use-menhir option at command line, Or put true: use_menhir in your tag file. *) if !Options.use_menhir || Configuration.has_tag "use_menhir" then begin (* Automatic handling of menhir modules, given a description file %.mlypack *) rule "ocaml: modular menhir (mlypack)" ~prods:["%.mli" ; "%.ml"] ~deps:["%.mlypack"] ~doc:"Menhir supports building a parser by composing several .mly files \ together, containing different parts of the grammar description. \ To use that feature with ocamlbuild, you should create a .mlypack \ file with the same syntax as .mllib or .mlpack files: \ a whitespace-separated list of the capitalized module names \ of the .mly files you want to combine together." (Ocaml_tools.menhir_modular "%" "%.mlypack" "%.mlypack.depends"); rule "ocaml: menhir modular dependencies" ~prod:"%.mlypack.depends" ~dep:"%.mlypack" (Ocaml_tools.menhir_modular_ocamldep_command "%.mlypack" "%.mlypack.depends"); rule "ocaml: menhir" ~prods:["%.ml"; "%.mli"] ~deps:["%.mly"; "%.mly.depends"] ~doc:"Invokes menhir to build the .ml and .mli files derived from a .mly \ grammar. If you want to use ocamlyacc instead, you must disable the \ -use-menhir option that was passed to ocamlbuild." (Ocaml_tools.menhir "%.mly"); rule "ocaml: menhir dependencies" ~prod:"%.mly.depends" ~dep:"%.mly" (Ocaml_tools.menhir_ocamldep_command "%.mly" "%.mly.depends"); end else rule "ocamlyacc" ~prods:["%.ml"; "%.mli"] ~dep:"%.mly" ~doc:"By default, ocamlbuild will use ocamlyacc to produce a .ml and .mly \ from a .mly file of the same name. You can also enable the \ -use-menhir option to use menhir instead. Menhir is a recommended \ replacement for ocamlyacc, that supports more feature, lets you \ write more readable grammars, and helps you understand conflicts." (Ocaml_tools.ocamlyacc "%.mly");; rule "ocaml C stubs: c -> o" ~prod:x_o ~dep:"%.c" ~doc:"The OCaml compiler can be passed .c files and will call \ the underlying C toolchain to produce corresponding .o files. \ ocamlc or ocamlopt will be used depending on whether \ the 'native' flag is set on the .c file." begin fun env _build -> let c = env "%.c" in let o = env x_o in let comp = if Tags.mem "native" (tags_of_pathname c) then !Options.ocamlopt else !Options.ocamlc in (* The workaround below is necessary on 4.03 and older OCaml version because ocamlc -c -o dir/foo.o dir/foo.c does not work as expected. See the original discussion: http://caml.inria.fr/mantis/view.php?id=6475 the partial revert: https://github.com/ocaml/ocamlbuild/pull/51 the 4.04 improvement: https://github.com/ocaml/ocaml/pull/464 Whenever we support to drop support for OCaml 4.03 we can replace the lines below with just Cmd(S[comp; T(tags_of_pathname c++"c"++"compile"); A"-c"; A"-o"; P o; Px c]) *) let cc = Cmd(S[comp; T(tags_of_pathname c++"c"++"compile"); A"-c"; Px c]) in if Pathname.dirname o = Pathname.current_dir_name then cc else Seq[cc; mv (Pathname.basename o) o] end;; rule "ocaml: ml & ml.depends & *cmi -> .inferred.mli" ~prod:"%.inferred.mli" ~deps:["%.ml"; "%.ml.depends"] ~doc:"The target foo.inferred.mli will produce a .mli that exposes all the \ declarations in foo.ml, as obtained by direct invocation of `ocamlc -i`." (Ocaml_tools.infer_interface "%.ml" "%.inferred.mli");; rule "ocaml: mltop -> top" ~prod:"%.top" ~dep:"%.mltop" ~doc:"If foo.mltop contains a list of module paths, then building foo.top \ will call the ocamlmktop tool to build a custom toplevel with those \ modules pre-linked." (Ocaml_compiler.byte_toplevel_link_mltop "%.mltop" "%.top");; rule "preprocess: ml -> pp.ml" ~dep:"%.ml" ~prod:"%.pp.ml" ~doc:"The target foo.pp.ml should generate a source file equivalent \ to foo.ml after syntactic preprocessors (camlp4, etc.) have been \ applied. \ Warning: This option is currently known to malfunction \ when used together with -use-ocamlfind (for syntax extensions \ coming from ocamlfind packages). Direct compilation of the \ corresponding file to produce a .cmx or .cmo will still work well." (Ocaml_tools.camlp4 "pp.ml" "%.ml" "%.pp.ml");; flag ["ocaml"; "pp"] begin S (List.fold_right (fun x acc -> Sh x :: acc) !Options.ocaml_ppflags []) end;; flag ["ocaml"; "compile"] begin atomize !Options.ocaml_cflags end;; flag ["c"; "compile"] begin atomize !Options.ocaml_cflags end;; flag ["ocaml"; "link"] begin atomize !Options.ocaml_lflags end;; flag ["c"; "link"] begin atomize !Options.ocaml_lflags end;; flag ["ocaml"; "ocamlyacc"] (atomize !Options.ocaml_yaccflags);; flag ["ocaml"; "menhir"] (atomize !Options.ocaml_yaccflags);; flag ["ocaml"; "doc"] (atomize !Options.ocaml_docflags);; flag ["ocaml"; "ocamllex"] (atomize !Options.ocaml_lexflags);; (* menhir options *) flag [ "ocaml" ; "menhir" ; "explain" ] (S[A "--explain"]);; flag [ "ocaml" ; "menhir" ; "infer" ] (S[A "--infer"]);; flag [ "ocaml" ; "menhir" ; "table" ] (S[A "--table"]);; flag [ "ocaml" ; "menhir" ; "trace" ] (S[A "--trace"]);; flag [ "ocaml" ; "menhir" ; "trace" ] (S[A "--canonical"]);; (* Define two ocamlbuild flags [only_tokens] and [external_tokens(Foo)] which correspond to menhir's [--only-tokens] and [--external-tokens Foo]. When they are used, these flags should be passed both to [menhir] and to [menhir --raw-depend]. *) let () = List.iter begin fun mode -> flag [ mode; "only_tokens" ] (S[A "--only-tokens"]); pflag [ mode ] "external_tokens" ~doc_param:"TokenModule" (fun name -> S[A "--external-tokens"; A name]); end [ "menhir"; "menhir_ocamldep" ];; (* Tell ocamllex to generate ml code *) flag [ "ocaml" ; "ocamllex" ; "generate_ml" ] (S[A "-ml"]);; flag ["ocaml"; "byte"; "link"] begin S (List.map (fun x -> A (x^".cma")) !Options.ocaml_libs) end;; flag ["ocaml"; "native"; "link"] begin S (List.map (fun x -> A (x^".cmxa")) !Options.ocaml_libs) end;; flag ["ocaml"; "byte"; "link"] begin S (List.map (fun x -> A (x^".cmo")) !Options.ocaml_mods) end;; flag ["ocaml"; "native"; "link"] begin S (List.map (fun x -> A (x^".cmx")) !Options.ocaml_mods) end;; (* findlib *) let () = if !Options.use_ocamlfind then begin let doc_param = "my_package" in (* Ocamlfind will link the archives for us. *) flag ["ocaml"; "link"; "program"] & A"-linkpkg"; flag ["ocaml"; "link"; "toplevel"] & A"-linkpkg"; flag ["ocaml"; "link"; "output_obj"] & A"-linkpkg"; (* "program" will make sure that -linkpkg is passed when compiling whole-programs (.byte and .native); but it is occasionally useful to pass -linkpkg when building archives for example (.cma and .cmxa); the "linkpkg" flag allows user to request it explicitly. *) flag ["ocaml"; "link"; "library"; "linkpkg"] & A"-linkpkg"; pflag ["ocaml"; "link"] "dontlink" ~doc_param (fun pkg -> S[A"-dontlink"; A pkg]); let all_tags = [ ["ocaml"; "byte"; "compile"]; ["ocaml"; "native"; "compile"]; ["ocaml"; "byte"; "link"]; ["ocaml"; "native"; "link"]; ["ocaml"; "ocamldep"]; ["ocaml"; "doc"]; ["ocaml"; "mktop"]; ["ocaml"; "infer_interface"]; (* PR#6794: ocamlbuild should pass -package flags when building C files *) ["c"; "compile"]; ] in (* tags package(X), predicate(X) and syntax(X), ppopt(X), ppxopt(X) *) List.iter begin fun tags -> pflag tags "package" ~doc_param (fun pkg -> S [A "-package"; A pkg]); pflag tags "predicate" ~doc_param:"archive" (fun pkg -> S [A "-predicates"; A pkg]); if List.mem "ocaml" tags then begin pflag tags "syntax" ~doc_param:"camlp4o" (fun pkg -> S [A "-syntax"; A pkg]); pflag tags "ppopt" ~doc_param:"pparg" (fun arg -> S [A "-ppopt"; A arg]); pflag tags "ppxopt" ~doc_param:"package,arg" (fun arg -> S [A "-ppxopt"; A arg]); end; end all_tags end else begin try (* Note: if there is no -pkg option, ocamlfind won't be called *) let pkgs = List.map Findlib.query !Options.ocaml_pkgs in flag ["ocaml"; "byte"; "compile"] (Findlib.compile_flags_byte pkgs); flag ["ocaml"; "native"; "compile"] (Findlib.compile_flags_native pkgs); flag ["ocaml"; "byte"; "link"] (Findlib.link_flags_byte pkgs); flag ["ocaml"; "native"; "link"] (Findlib.link_flags_native pkgs); (* PR#6794: ocamlbuild should pass -package flags when building C files *) flag ["c"; "compile"] (Findlib.include_flags pkgs) with Findlib.Findlib_error e -> Findlib.report_error e end (* parameterized tags *) let () = pflag ["ocaml"; "compile"] "for-pack" ~doc_param:"PackModule" (fun param -> S [A "-for-pack"; A param]); pflag ["ocaml"; "pack"] "for-pack" ~doc_param:"PackModule" (fun param -> S [A "-for-pack"; A param]); pflag ["ocaml"; "native"; "compile"] "inline" ~doc_param:"5" (fun param -> S [A "-inline"; A param]); pflag ["ocaml"; "compile"] "color" (fun setting -> S[A "-color"; A setting]); pflag ["ocaml"; "infer_interface"] "color" (fun setting -> S[A "-color"; A setting]); List.iter (fun pp -> let doc_param = "my_" ^ pp in pflag ["ocaml"; "compile"] pp ~doc_param (fun param -> S [A ("-" ^ pp); A param]); pflag ["ocaml"; "ocamldep"] pp ~doc_param (fun param -> S [A ("-" ^ pp); A param]); pflag ["ocaml"; "doc"] pp ~doc_param (fun param -> S [A ("-" ^ pp); A param]); pflag ["ocaml"; "infer_interface"] pp ~doc_param (fun param -> S [A ("-" ^ pp); A param]) ) ["pp"; "ppx"]; pflag ["ocaml";"compile";] "warn" ~doc_param:"A@10-28@40-42-45" (fun param -> S [A "-w"; A param]); pflag ["ocaml";"infer_interface";] "warn" ~doc_param:"A@10-28@40-42-45" (fun param -> S [A "-w"; A param]); pflag ["ocaml";"compile";] "warn_error" ~doc_param:"+10+40" (fun param -> S [A "-warn-error"; A param]); pflag ["ocaml";"infer_interface";] "warn_error" ~doc_param:"+10+40" (fun param -> S [A "-warn-error"; A param]); pflag ["ocaml"; "ocamldep"] "open" ~doc_param:"MyPervasives" (fun param -> S [A "-open"; A param]); pflag ["ocaml"; "compile"] "open" ~doc_param:"MyPervasives" (fun param -> S [A "-open"; A param]); pflag ["ocaml"; "infer_interface"] "open" ~doc_param:"MyPervasives" (fun param -> S [A "-open"; A param]); pflag ["ocaml"; "link"] "runtime_variant" ~doc_param:"_pic" (fun param -> S [A "-runtime-variant"; A param]); pflag ["ocaml"; "native"; "compile"] "optimize" ~doc_param:"2" (fun param -> match param with | "classic" | "2" | "3" -> S [A ("-O" ^ param)] | _ -> let e = Printf.sprintf "Invalid parameter for \"optimize\" tag: %s (can be classic, 2, or 3)." param in raise (Invalid_argument e)); pflag ["ocaml"; "native"; "compile"] "optimization_rounds" ~doc_param:"2" (fun param -> S [A "-rounds"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_toplevel" ~doc_param:"160" (fun param -> S [A "-inline-toplevel"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_branch_factor" ~doc_param:"0.1" (fun param -> S [A "-inline-branch-factor"; A param];); pflag ["ocaml"; "native"; "compile"] "inline_alloc_cost" ~doc_param:"7" (fun param -> S [A "-inline-alloc-cost"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_branch_cost" ~doc_param:"5" (fun param -> S [A "-inline-branch-cost"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_call_cost" ~doc_param:"5" (fun param -> S [A "-inline-call-cost"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_indirect_cost" ~doc_param:"4" (fun param -> S [A "-inline-indirect-cost"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_prim_cost" ~doc_param:"3" (fun param -> S [A "-inline-prim-cost"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_lifting_benefit" ~doc_param:"1300" (fun param -> S [A "-inline-lifting-benefit"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_max_depth" ~doc_param:"1" (fun param -> S [A "-inline-max-depth"; A param]); pflag ["ocaml"; "native"; "compile"] "inline_max_unroll" ~doc_param:"0" (fun param -> S [A "-inline-max-unroll"; A param]); pflag ["ocaml"; "native"; "compile"] "unbox_closures_factor" ~doc_param:"10" (fun param -> S [A "-unbox-closures-factor"; A param]); pflag ["ocaml"; "native"; "compile"] "afl_inst_ratio" ~doc_param:"50" (fun param -> S [A "-afl-inst-ratio"; A param]); () let camlp4_flags camlp4s = List.iter begin fun camlp4 -> flag ["ocaml"; "pp"; camlp4] (A camlp4) end camlp4s;; let p4_series = ["camlp4o"; "camlp4r"; "camlp4of"; "camlp4rf"; "camlp4orf"; "camlp4oof"];; let p4_opt_series = List.map (fun f -> f ^ ".opt") p4_series;; camlp4_flags p4_series;; camlp4_flags p4_opt_series;; let camlp4_flags' camlp4s = List.iter begin fun (camlp4, flags) -> flag ["ocaml"; "pp"; camlp4] flags end camlp4s;; camlp4_flags' ["camlp4orr", S[A"camlp4of"; A"-parser"; A"reloaded"]; "camlp4rrr", S[A"camlp4rf"; A"-parser"; A"reloaded"]];; flag ["ocaml"; "pp"; "camlp4:no_quot"] (A"-no_quot");; ocaml_lib ~extern:true "dynlink";; ocaml_lib ~extern:true "unix";; ocaml_lib ~extern:true "str";; ocaml_lib ~extern:true "bigarray";; ocaml_lib ~extern:true "nums";; ocaml_lib ~extern:true "dbm";; ocaml_lib ~extern:true "graphics";; ocaml_lib ~extern:true ~tag_name:"use_toplevel" "toplevellib";; ocaml_lib ~extern:true ~dir:"+ocamldoc" "ocamldoc";; ocaml_lib ~extern:true ~dir:"+ocamlbuild" ~tag_name:"use_ocamlbuild" "ocamlbuildlib";; let camlp4dir = let where cmd = (* may raise a Failure exception *) String.chomp (My_unix.run_and_read (cmd ^ " -where 2>/dev/null")) in try where "camlp4" with _ -> "+camlp4" ;; ocaml_lib ~extern:true ~dir:camlp4dir ~tag_name:"use_camlp4" "camlp4lib";; ocaml_lib ~extern:true ~dir:camlp4dir ~tag_name:"use_old_camlp4" "camlp4";; ocaml_lib ~extern:true ~dir:camlp4dir ~tag_name:"use_camlp4_full" "camlp4fulllib";; flag ["ocaml"; "compile"; "use_camlp4_full"] (S[A"-I"; A(camlp4dir^"/Camlp4Parsers"); A"-I"; A(camlp4dir^"/Camlp4Printers"); A"-I"; A(camlp4dir^"/Camlp4Filters")]);; flag ["ocaml"; "use_camlp4_bin"; "link"; "byte"] (A(camlp4dir^"/Camlp4Bin.cmo"));; flag ["ocaml"; "use_camlp4_bin"; "link"; "native"] (A(camlp4dir^"/Camlp4Bin.cmx"));; flag ["ocaml"; "debug"; "compile"; "byte"] (A "-g");; flag ["ocaml"; "debug"; "link"; "byte"; "program"] (A "-g");; flag ["ocaml"; "debug"; "pack"; "byte"] (A "-g");; flag ["ocaml"; "debug"; "compile"; "native"] (A "-g");; flag ["ocaml"; "debug"; "link"; "native"; "program"] (A "-g");; flag ["ocaml"; "debug"; "pack"; "native"] (A "-g");; flag ["c"; "debug"; "compile"] (A "-g"); flag ["c"; "debug"; "link"] (A "-g"); flag ["ocaml"; "link"; "native"; "output_obj"] (A"-output-obj");; flag ["ocaml"; "link"; "byte"; "output_obj"] (A"-output-obj");; flag ["ocaml"; "dtypes"; "compile"] (A "-dtypes");; flag ["ocaml"; "annot"; "compile"] (A "-annot");; flag ["ocaml"; "annot"; "pack"] (A "-annot");; flag ["ocaml"; "bin_annot"; "compile"] (A "-bin-annot");; flag ["ocaml"; "bin_annot"; "pack"] (A "-bin-annot");; flag ["ocaml"; "safe_string"; "compile"] (A "-safe-string");; flag ["ocaml"; "safe_string"; "infer_interface"] (A "-safe-string");; flag ["ocaml"; "unsafe_string"; "compile"] (A "-unsafe-string");; flag ["ocaml"; "unsafe_string"; "infer_interface"] (A "-unsafe-string");; flag ["ocaml"; "short_paths"; "compile"] (A "-short-paths");; flag ["ocaml"; "short_paths"; "infer_interface"] (A "-short-paths");; flag ["ocaml"; "rectypes"; "compile"] (A "-rectypes");; flag ["ocaml"; "rectypes"; "infer_interface"] (A "-rectypes");; flag ["ocaml"; "rectypes"; "doc"] (A "-rectypes");; flag ["ocaml"; "rectypes"; "pack"] (A "-rectypes");; flag ["ocaml"; "principal"; "compile"] (A "-principal");; flag ["ocaml"; "principal"; "infer_interface"] (A "-principal");; flag ["ocaml"; "linkall"; "link"] (A "-linkall");; flag ["ocaml"; "noautolink"; "link"] (A "-noautolink");; flag ["ocaml"; "link"; "profile"; "native"] (A "-p");; flag ["ocaml"; "link"; "program"; "custom"; "byte"] (A "-custom");; flag ["ocaml"; "link"; "library"; "custom"; "byte"] (A "-custom");; flag ["ocaml"; "link"; "toplevel"; "custom"; "byte"] (A "-custom");; flag ["ocaml"; "compile"; "profile"; "native"] (A "-p");; flag ["ocamlmklib"; "linkall"] (A "-linkall");; flag ["ocamlmklib"; "custom"] (A "-custom");; flag ["ocamlmklib"; "failsafe"] (A "-failsafe");; flag ["ocamlmklib"; "debug"] (A "-g");; flag ["ocaml"; "compile"; "no_alias_deps";] (A "-no-alias-deps");; flag ["ocaml"; "infer_interface"; "no_alias_deps";] (A "-no-alias-deps");; flag ["ocaml"; "compile"; "strict_formats";] (A "-strict-formats");; flag ["ocaml"; "infer_interface"; "strict_formats";] (A "-strict-formats");; flag ["ocaml"; "compile"; "noassert"] (A "-noassert");; flag ["ocaml"; "compile"; "unsafe"] (A "-unsafe");; begin let above_403 = match split_ocaml_version with | Some (major, minor, _patch, _rest) -> major > 4 || minor >= 3 | None -> false in (* starting from 4.03, ocamlc also supports -opaque *) if above_403 then flag ["ocaml"; "compile"; "opaque";] (A "-opaque") else flag ["ocaml"; "native"; "compile"; "opaque";] (A "-opaque") end;; flag ["ocaml"; "native"; "compile"; "no_float_const_prop";] (A "-no-float-const-prop"); ["compile"; "link"; "pack"] |> List.iter begin fun phase -> flag ["ocaml"; phase; "keep_docs";] (A "-keep-docs"); flag ["ocaml"; phase; "keep_locs";] (A "-keep-locs"); end;; ["compile"; "infer_interface"] |> List.iter begin fun phase -> flag ["ocaml"; phase; "absname"] (A "-absname"); end;; flag ["ocaml"; "byte"; "compile"; "compat_32";] (A "-compat-32");; flag ["ocaml";"compile";"native";"asm"] & S [A "-S"];; (* AFL instrumentation *) flag ["ocaml"; "compile"; "native"; "afl_instrument"] (A "-afl-instrument");; (* threads, with or without findlib *) flag ["ocaml"; "compile"; "thread"] (A "-thread");; flag ["ocaml"; "link"; "thread"] (A "-thread");; if !Options.use_ocamlfind then (* PR#6794: Needed as we pass -package when compiling C files *) flag ["c"; "compile"; "thread"] (A "-thread") else begin flag ["ocaml"; "doc"; "thread"] (S[A"-I"; A"+threads"]); flag ["ocaml"; "link"; "thread"; "native"; "program"] (A "threads.cmxa"); flag ["ocaml"; "link"; "thread"; "byte"; "program"] (A "threads.cma"); flag ["ocaml"; "link"; "thread"; "native"; "toplevel"] (A "threads.cmxa"); flag ["ocaml"; "link"; "thread"; "byte"; "toplevel"] (A "threads.cma"); end;; flag ["ocaml"; "compile"; "nostdlib"] (A"-nostdlib");; flag ["ocaml"; "infer_interface"; "nostdlib"] (A"-nostdlib");; flag ["ocaml"; "link"; "nostdlib"] (A"-nostdlib");; flag ["ocaml"; "compile"; "nopervasives"] (A"-nopervasives");; flag ["ocaml"; "infer_interface"; "nopervasives"] (A"-nopervasives");; flag ["ocaml"; "compile"; "nolabels"] (A"-nolabels");; flag ["ocaml"; "infer_interface"; "nolabels"] (A"-nolabels");; (*flag ["ocaml"; "ocamlyacc"; "quiet"] (A"-q");;*) flag ["ocaml"; "ocamllex"; "quiet"] (A"-q");; let ocaml_warn_flag c = flag ~deprecated:true ["ocaml"; "compile"; sprintf "warn_%c" (Char.uppercase_ascii c)] (S[A"-w"; A (sprintf "%c" (Char.uppercase_ascii c))]); flag ~deprecated:true ["ocaml"; "compile"; sprintf "warn_error_%c" (Char.uppercase_ascii c)] (S[A"-warn-error"; A (sprintf "%c" (Char.uppercase_ascii c))]); flag ~deprecated:true ["ocaml"; "compile"; sprintf "warn_%c" (Char.lowercase_ascii c)] (S[A"-w"; A (sprintf "%c" (Char.lowercase_ascii c))]); flag ~deprecated:true ["ocaml"; "compile"; sprintf "warn_error_%c" (Char.lowercase_ascii c)] (S[A"-warn-error"; A (sprintf "%c" (Char.lowercase_ascii c))]);; List.iter ocaml_warn_flag ['A'; 'C'; 'D'; 'E'; 'F'; 'K'; 'L'; 'M'; 'P'; 'R'; 'S'; 'U'; 'V'; 'X'; 'Y'; 'Z'];; flag ~deprecated:true ["ocaml"; "compile"; "strict-sequence"] (A "-strict-sequence");; flag ["ocaml"; "compile"; "strict_sequence"] (A "-strict-sequence");; flag ["ocaml"; "infer_interface"; "strict_sequence"] (A "-strict-sequence");; flag ["ocaml"; "doc"; "docdir"; "html"] (A"-html");; flag ["ocaml"; "doc"; "docdir"; "man"] (A"-man");; flag ["ocaml"; "doc"; "docfile"; "dot"] (A"-dot");; flag ["ocaml"; "doc"; "docfile"; "tex"] (A"-latex");; flag ["ocaml"; "doc"; "docfile"; "texi"] (A"-texi");; (* Inlining and flambda optimization options *) flag ["ocaml"; "native"; "compile"; "inlining_report"] (A"-inlining-report");; flag ["ocaml"; "native"; "compile"; "remove_unused_arguments"] (A"-remove-unused-arguments");; flag ["ocaml"; "native"; "compile"; "unbox_closures"] (A"-unbox-closures");; flag ["ocaml"; "native"; "compile"; "no_unbox_free_vars_of_closures"] (A"-no-unbox-free-vars-of-closures");; flag ["ocaml"; "native"; "compile"; "no_unbox_specialized_args"] (A"-no-unbox-specialized-args");; (* Kept for backward compatibility. *) flag ["ocaml"; "doc"; "docdir"; "manpage"] (A"-man");; pflag ["ocaml"; "doc"; "dot"] "dot_colors" (fun param -> S [A "-dot-colors"; A param]);; flag ["ocaml"; "doc"; "dot"; "dot_include_all"] (A"-dot-include-all");; flag ["ocaml"; "doc"; "dot"; "dot_reduce"] (A"-dot-reduce");; flag ["ocaml"; "doc"; "dot"; "dot_types"] (A"-dot-types");; flag ["ocaml"; "doc"; "man"; "man_mini"] (A"-man-mini");; pflag ["ocaml"; "doc"; "man"] "man_suffix" (fun param -> S [A "-man-suffix"; A param]);; pflag ["ocaml"; "doc"; "man"] "man_section" (fun param -> S [A "-man-section"; A param]);; ocaml_lib "ocamlbuildlib";; ocaml_lib "ocamlbuildlightlib";; begin let ccflag ~lang ~phase ~flag = pflag [lang; phase] flag (fun param -> S [A ("-"^flag); A param]) in ["c"; "ocaml"] |> List.iter (fun lang -> ["compile"; "link"] |> List.iter (fun phase -> ["cc"; "ccopt"; "cclib"] |> List.iter (fun flag -> ccflag ~lang ~phase ~flag))) end;; begin let ocamlmklib_pflag ?doc_param flag = pflag ["ocamlmklib"] flag ?doc_param (fun param -> S [A ("-"^flag); A param]) in ocamlmklib_pflag "cclib"; ocamlmklib_pflag "ccopt"; ocamlmklib_pflag "rpath"; ocamlmklib_pflag "ldopt"; end;; end in () ocamlbuild-0.14.3/src/ocaml_specific.mli000066400000000000000000000016751454061437200201630ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val init : unit -> unit ocamlbuild-0.14.3/src/ocaml_tools.ml000066400000000000000000000155461454061437200173670ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Pathname.Operators open Tags.Operators open Tools open Command open Ocaml_utils let add_suffix s = List.map (fun x -> x -.- s) ;; let ocamldep_command' tags = let tags' = tags++"ocaml"++"ocamldep" in S [!Options.ocamldep; T tags'; ocaml_ppflags (tags++"pp:dep"); A "-modules"] let menhir_ocamldep_command' tags ~menhir_spec out = let menhir = if !Options.ocamlyacc = N then V"MENHIR" else !Options.ocamlyacc in Cmd(S[menhir; T tags; A"--raw-depend"; A"--ocamldep"; Quote (ocamldep_command' Tags.empty); menhir_spec ; Sh ">"; Px out]) let menhir_ocamldep_command arg out env _build = let arg = env arg and out = env out in let tags = tags_of_pathname arg++"ocaml"++"menhir_ocamldep" in menhir_ocamldep_command' tags ~menhir_spec:(P arg) out let import_mlypack build mlypack = let tags1 = tags_of_pathname mlypack in let files = string_list_of_file mlypack in let include_dirs = Pathname.include_dirs_of (Pathname.dirname mlypack) in let files_alternatives = List.map begin fun module_name -> expand_module include_dirs module_name ["mly"] end files in let files = List.map Outcome.good (build files_alternatives) in let tags2 = List.fold_right (fun file -> Tags.union (tags_of_pathname file)) files tags1 in (tags2, files) let menhir_modular_ocamldep_command mlypack out env build = let mlypack = env mlypack and out = env out in let (tags,files) = import_mlypack build mlypack in let tags = tags++"ocaml"++"menhir_ocamldep" in let menhir_base = Pathname.remove_extensions mlypack in let menhir_spec = S[A "--base" ; P menhir_base ; atomize_paths files] in menhir_ocamldep_command' tags ~menhir_spec out let menhir_modular menhir_base mlypack mlypack_depends env build = let menhir = if !Options.ocamlyacc = N then V"MENHIR" else !Options.ocamlyacc in let menhir_base = env menhir_base in let mlypack = env mlypack in let mlypack_depends = env mlypack_depends in let (tags,files) = import_mlypack build mlypack in let () = List.iter Outcome.ignore_good (build [[mlypack_depends]]) in Ocaml_compiler.prepare_compile build mlypack; let ocamlc_tags = tags++"ocaml"++"byte"++"compile" in let tags = tags++"ocaml"++"parser"++"menhir" in Cmd(S[menhir ; A "--ocamlc"; Quote(S[!Options.ocamlc; T ocamlc_tags; ocaml_include_flags mlypack]); T tags ; A "--base" ; Px menhir_base ; atomize_paths files]) let ocamldep_command arg out env _build = let arg = env arg and out = env out in let tags = tags_of_pathname arg in Cmd(S[ocamldep_command' tags; P arg; Sh ">"; Px out]) let ocamlyacc mly env _build = let mly = env mly in let ocamlyacc = if !Options.ocamlyacc = N then V"OCAMLYACC" else !Options.ocamlyacc in Cmd(S[ocamlyacc; T(tags_of_pathname mly++"ocaml"++"parser"++"ocamlyacc"); Px mly]) let ocamllex mll env _build = let mll = env mll in Cmd(S[!Options.ocamllex; T(tags_of_pathname mll++"ocaml"++"lexer"++"ocamllex"); Px mll]) let infer_interface ml mli env build = let ml = env ml and mli = env mli in let tags = tags_of_pathname ml++"ocaml" in Ocaml_compiler.prepare_compile build ml; Cmd(S[!Options.ocamlc; ocaml_ppflags tags; ocaml_include_flags ml; A"-i"; (if Tags.mem "thread" tags then A"-thread" else N); T(tags++"infer_interface"); P ml; Sh">"; Px mli]) let menhir mly env build = let mly = env mly in let ml = Pathname.update_extension "ml" mly in let menhir = if !Options.ocamlyacc = N then V"MENHIR" else !Options.ocamlyacc in let ocamlc_tags = tags_of_pathname ml ++"ocaml"++"byte"++"compile" in let menhir_tags = tags_of_pathname mly ++"ocaml"++"parser"++"menhir" in Ocaml_compiler.prepare_compile build mly; Cmd(S[menhir; A"--ocamlc"; Quote(S[!Options.ocamlc; T ocamlc_tags; ocaml_include_flags mly]); T menhir_tags; Px mly]) let ocamldoc_c tags arg odoc = let tags = tags++"ocaml" in Cmd (S [!Options.ocamldoc; A"-dump"; Px odoc; T(tags++"doc"); ocaml_ppflags (tags++"pp:doc"); ocaml_include_flags arg; P arg]) let ocamldoc_l_dir tags deps _docout docdir = Seq[Cmd (S[A"rm"; A"-rf"; Px docdir]); Cmd (S[A"mkdir"; A"-p"; Px docdir]); Cmd (S [!Options.ocamldoc; S(List.map (fun a -> S[A"-load"; P a]) deps); T(tags++"doc"++"docdir"); A"-d"; Px docdir])] let ocamldoc_l_file tags deps docout _docdir = Seq[Cmd (S[A"rm"; A"-rf"; Px docout]); Cmd (S[A"mkdir"; A"-p"; Px (Pathname.dirname docout)]); Cmd (S [!Options.ocamldoc; S(List.map (fun a -> S[A"-load"; P a]) deps); T(tags++"doc"++"docfile"); A"-o"; Px docout])] let document_ocaml_interf mli odoc env build = let mli = env mli and odoc = env odoc in Ocaml_compiler.prepare_compile build mli; ocamldoc_c (tags_of_pathname mli++"interf") mli odoc let document_ocaml_implem ml odoc env build = let ml = env ml and odoc = env odoc in Ocaml_compiler.prepare_compile build ml; ocamldoc_c (tags_of_pathname ml++"implem") ml odoc let document_ocaml_project ?(ocamldoc=ocamldoc_l_file) ?(tags = []) odocl docout docdir env build = let odocl = env odocl and docout = env docout and docdir = env docdir in let contents = string_list_of_file odocl in let include_dirs = Pathname.include_dirs_of (Pathname.dirname odocl) in let to_build = List.map begin fun module_name -> expand_module include_dirs module_name ["odoc"] end contents in let module_paths = List.map Outcome.good (build to_build) in let tags = Tags.union ((Tags.of_list tags) ++ "ocaml") (Tags.union (tags_of_pathname docout) (tags_of_pathname docdir)) in ocamldoc tags module_paths docout docdir let camlp4 ?(default=A"camlp4o") tag i o env build = let ml = env i and pp_ml = env o in let tags = tags_of_pathname ml++"ocaml"++"pp"++tag in let _ = Rule.build_deps_of_tags build tags in let pp = Command.reduce (Flags.of_tags tags) in let pp = match pp with | N -> default | _ -> pp in Cmd(S[pp; P ml; A"-printer"; A"o"; A"-o"; Px pp_ml]) ocamlbuild-0.14.3/src/ocaml_tools.mli000066400000000000000000000036221454061437200175300ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val ocamldoc_c : Tags.t -> string -> string -> Command.t val ocamldoc_l_dir : Tags.t -> string list -> string -> string -> Command.t val ocamldoc_l_file : Tags.t -> string list -> string -> string -> Command.t val ocamldep_command : string -> string -> Rule.action val menhir_ocamldep_command : string -> string -> Rule.action val menhir_modular_ocamldep_command : string -> string -> Rule.action val menhir_modular : string -> string -> string -> Rule.action val ocamlyacc : string -> Rule.action val ocamllex : string -> Rule.action val menhir : string -> Rule.action val infer_interface : string -> string -> Rule.action val document_ocaml_interf : string -> string -> Rule.action val document_ocaml_implem : string -> string -> Rule.action val document_ocaml_project : ?ocamldoc:(Tags.t -> string list -> string -> string -> Command.t) -> ?tags:(string list) -> string -> string -> string -> Rule.action val camlp4 : ?default:Command.spec -> Tags.elt -> Pathname.t -> Pathname.t -> Rule.action ocamlbuild-0.14.3/src/ocaml_utils.ml000066400000000000000000000144611454061437200173620ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Format open Log open Pathname.Operators open Tags.Operators open Tools open Flags open Command;; module S = Set.Make(String) let stdlib_dir = lazy begin let ocamlc_where = !Options.build_dir / (Pathname.mk "ocamlc.where") in let () = Command.execute ~quiet:true (Cmd(S[!Options.ocamlc; A"-where"; Sh">"; P ocamlc_where])) in String.chomp (read_file ocamlc_where) end let flag_and_dep = Flags.flag_and_dep let pflag_and_dep = Flags.pflag_and_dep ?doc_param:None let module_name_of_filename f = String.capitalize_ascii (Pathname.remove_extensions f) let module_name_of_pathname x = module_name_of_filename (Pathname.to_string (Pathname.basename x)) let ignore_stdlib x = if !Options.nostdlib then false else let x' = !*stdlib_dir/((String.uncapitalize_ascii x)-.-"cmi") in Pathname.exists x' let non_dependencies = ref [] let non_dependency m1 m2 = (* non_dependency was not supposed to accept pathnames without extension. *) if String.length (Pathname.get_extensions m1) = 0 then invalid_arg "non_dependency: no extension"; non_dependencies := (m1, m2) :: !non_dependencies let path_importance path x = if List.mem (path, x) !non_dependencies || (List.mem x !Options.ignore_list) then begin let () = dprintf 3 "This module (%s) is ignored by %s" x path in `ignored end else if ignore_stdlib x then `just_try else `mandatory let expand_module = memo3 (fun include_dirs module_name exts -> let dirname = Pathname.dirname module_name in let basename = Pathname.basename module_name in let module_name_cap = dirname/(String.capitalize_ascii basename) in let module_name_uncap = dirname/(String.uncapitalize_ascii basename) in List.fold_right begin fun include_dir -> List.fold_right begin fun ext acc -> include_dir/(module_name_uncap-.-ext) :: include_dir/(module_name_cap-.-ext) :: acc end exts end include_dirs []) let string_list_of_file file = with_input_file file begin fun ic -> Lexers.blank_sep_strings Const.Source.file (Lexing.from_channel ic) end let print_path_list = Pathname.print_path_list let ocaml_ppflags tags = let flags = Flags.of_tags (tags++"ocaml"++"pp") in let reduced = Command.reduce flags in if reduced = N then N else S[A"-pp"; Quote reduced] let ocaml_add_include_flag x acc = if x = Pathname.current_dir_name then acc else A"-I" :: A x :: acc let ocaml_include_flags path = S (List.fold_right ocaml_add_include_flag (Pathname.include_dirs_of (Pathname.dirname path)) []) let info_libraries = Hashtbl.create 103 let libraries = Hashtbl.create 103 let libraries_of m = try Hashtbl.find libraries m with Not_found -> [] let use_lib m lib = Hashtbl.replace libraries m (lib :: libraries_of m) let ocaml_lib ?(extern=false) ?(byte=true) ?(native=true) ?dir ?tag_name libpath = let add_dir x = match dir with | Some dir -> S[A"-I"; P dir; x] | None -> x in let tag_name = match tag_name with | Some x -> x | None -> "use_" ^ Pathname.basename libpath in let flag_and_dep tags lib = flag tags (add_dir (A lib)); if not extern then dep tags [lib] (* cannot happen? *) in Hashtbl.replace info_libraries tag_name (libpath, extern); (* adding [tag_name] to [info_libraries] will make this tag affect include-dir lookups, so it is used even if not mentioned explicitly in any rule. *) Flags.mark_tag_used tag_name; if extern then begin if byte then flag_and_dep ["ocaml"; tag_name; "link"; "byte"] (libpath^".cma"); if native then flag_and_dep ["ocaml"; tag_name; "link"; "native"] (libpath^".cmxa"); end else begin if not byte && not native then invalid_arg "ocaml_lib: ~byte:false or ~native:false only works with ~extern:true"; end; match dir with | None -> () | Some dir -> List.iter (fun x -> flag ["ocaml"; tag_name; x] (S[A"-I"; P dir])) ["compile"; "doc"; "infer_interface"] let cmi_of = Pathname.update_extensions "cmi" exception Ocamldep_error of string let read_path_dependencies = let path_dependencies = Hashtbl.create 103 in let read path = let module_name = module_name_of_pathname path in let depends = path-.-"depends" in with_input_file depends begin fun ic -> let ocamldep_output = try Lexers.ocamldep_output Const.Source.ocamldep (Lexing.from_channel ic) with Lexers.Error (msg,_) -> raise (Ocamldep_error(Printf.sprintf "Ocamldep.ocamldep: bad output (%s)" msg)) in let deps = List.fold_right begin fun (path, deps) acc -> let module_name' = module_name_of_pathname path in if module_name' = module_name then List.union deps acc else raise (Ocamldep_error(Printf.sprintf "Ocamldep.ocamldep: multiple files in ocamldep output (%s not expected)" path)) end ocamldep_output [] in let deps = if !Options.nostdlib && not (Tags.mem "nopervasives" (tags_of_pathname path)) then "Pervasives" :: deps else deps in let deps' = List.fold_right begin fun dep acc -> match path_importance path dep with | `ignored -> acc | (`just_try | `mandatory) as importance -> (importance, dep) :: acc end deps [] in Hashtbl.replace path_dependencies path (List.union (try Hashtbl.find path_dependencies path with Not_found -> []) deps'); deps' end in read let path_dependencies_of = memo read_path_dependencies ocamlbuild-0.14.3/src/ocaml_utils.mli000066400000000000000000000040531454061437200175270ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val stdlib_dir : Pathname.t Lazy.t val module_name_of_filename : Pathname.t -> string val module_name_of_pathname : Pathname.t -> string val ignore_stdlib : string -> bool val non_dependency : string -> string -> unit val expand_module : Pathname.t list -> Pathname.t -> string list -> Pathname.t list val string_list_of_file : string -> string list val ocaml_ppflags : Tags.t -> Command.spec val ocaml_include_flags : Pathname.t -> Command.spec val libraries_of : Pathname.t -> Pathname.t list val use_lib : Pathname.t -> Pathname.t -> unit val cmi_of : Pathname.t -> Pathname.t val ocaml_add_include_flag : string -> Command.spec list -> Command.spec list val flag_and_dep : Tags.elt list -> Command.spec -> unit val pflag_and_dep : Tags.elt list -> Tags.elt -> (string -> Command.spec) -> unit exception Ocamldep_error of string (* Takes a path and returns a list of modules *) val path_dependencies_of : Pathname.t -> ([ `mandatory | `just_try ] * string) list val info_libraries : (string, string * bool) Hashtbl.t val ocaml_lib : ?extern:bool -> ?byte:bool -> ?native:bool -> ?dir:Pathname.t -> ?tag_name:string -> Pathname.t -> unit ocamlbuild-0.14.3/src/ocamlbuild_where.ml000066400000000000000000000046461454061437200203600ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) module O = Ocamlbuild_config;; let bindir = ref O.bindir;; let libdir = ref begin let root, suffix = let ocaml_lib_len = String.length O.ocaml_libdir + 1 in let lib_len = String.length O.libdir_abs in (* Windows note: O.ocaml_libdir and O.libdir_abs have both been passed through GNU make's abspath function and will be forward-slash normalised. Filename.dir_sep is therefore not appropriate here. *) if lib_len < ocaml_lib_len || String.sub O.libdir_abs 0 ocaml_lib_len <> O.ocaml_libdir ^ "/" then O.libdir, "ocamlbuild" else (* https://github.com/ocaml/ocamlbuild/issues/69. Only use OCAMLLIB if the configured LIBDIR is a subdirectory (lexically) of OCAML_LIBDIR. If it is, append the difference between LIBDIR and OCAML_LIBDIR to OCAMLLIB. This allows `OCAMLLIB=/foo ocamlbuild -where` to return /foo/site-lib/ocamlbuild for a findlib-based installation and also to ignore OCAMLLIB in an opam-based installation (where setting OCAMLLIB is already a strange thing to have done). *) try let normalise_slashes = if Sys.os_type = "Win32" then String.map (function '/' -> '\\' | c -> c) else function s -> s in let subroot = String.sub O.libdir_abs ocaml_lib_len (lib_len - ocaml_lib_len) |> normalise_slashes in Sys.getenv "OCAMLLIB", Filename.concat subroot "ocamlbuild" with Not_found -> O.libdir, "ocamlbuild" in Filename.concat root suffix end;; ocamlbuild-0.14.3/src/ocamlbuild_where.mli000066400000000000000000000017251454061437200205240ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val bindir : string ref val libdir : string ref ocamlbuild-0.14.3/src/options.ml000066400000000000000000000432251454061437200165420ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) type command_spec = Command.spec open My_std open Arg open Format open Command let entry = ref None let project_root_dir = ref None let build_dir = ref (filename_concat (Sys.getcwd ()) "_build") let include_dirs = ref [] let exclude_dirs = ref [] let nothing_should_be_rebuilt = ref false let sanitize = ref true let sanitization_script = ref "sanitize.sh" let hygiene = ref true let ignore_auto = ref true let plugin = ref true let just_plugin = ref false let native_plugin = ref true let make_links = ref true let nostdlib = ref false let use_menhir = ref false let catch_errors = ref true let use_ocamlfind = ref false let plugin_use_ocamlfind = ref false let toolchain = ref "" (* Currently only ocamlfind and menhir is defined as no-core tool, perhaps later we need something better *) let is_core_tool = function "ocamlfind" | "menhir" -> false | _ -> true let find_tool cmd = let dir = Ocamlbuild_where.bindir in let core_tool = is_core_tool cmd in let opt = cmd ^ ".opt" in let search_in_path = memo Command.search_in_path in if sys_file_exists !dir then let long = filename_concat !dir cmd in let long_opt = long ^ ".opt" in (* This defines how the command will be found *) let choices = [(fun () -> if file_or_exe_exists long_opt then Some long_opt else None); (fun () -> if file_or_exe_exists long then Some long else None)] in (* For non core tool the preference is too look at PATH first *) let choices' = [fun () -> try let _ = search_in_path opt in Some opt with Not_found -> Some cmd] in let choices = if core_tool then choices @ choices' else choices' @ choices in try match (List.find (fun choice -> not (choice () = None)) choices) () with Some cmd -> cmd | None -> raise Not_found with Not_found -> failwith (Printf.sprintf "Can't find tool: %s" cmd) else try let _ = search_in_path opt in opt with Not_found -> cmd let mk_virtual_solvers = List.iter begin fun cmd -> let solver () = A (find_tool cmd) in Command.setup_virtual_command_solver (String.uppercase_ascii cmd) solver end let () = mk_virtual_solvers ["ocamlc"; "ocamlopt"; "ocamldep"; "ocamldoc"; "ocamlyacc"; "menhir"; "ocamllex"; "ocamlmklib"; "ocamlmktop"; "ocamlfind"] let ocamlc = ref (V"OCAMLC") let plugin_ocamlc = ref (V"OCAMLC") let ocamlopt = ref (V"OCAMLOPT") let plugin_ocamlopt = ref (V"OCAMLOPT") let ocamldep = ref (V"OCAMLDEP") let ocamldoc = ref (V"OCAMLDOC") let ocamlyacc = ref N let ocamllex = ref (V"OCAMLLEX") let ocamlmklib = ref (V"OCAMLMKLIB") let ocamlmktop = ref (V"OCAMLMKTOP") let ocamlrun = ref N let ocamlfind_cmd = ref (V"OCAMLFIND") let ocamlfind arg = if !toolchain = "" then S[!ocamlfind_cmd; arg] else S[!ocamlfind_cmd; A"-toolchain"; A!toolchain; arg] let plugin_ocamlfind arg = S[!ocamlfind_cmd; arg] let program_to_execute = ref false let must_clean = ref false let show_documentation = ref false let recursive = ref false let ext_lib = ref Ocamlbuild_config.a let ext_obj = ref Ocamlbuild_config.o let ext_dll = let s = Ocamlbuild_config.ext_dll in ref (String.sub s 1 (String.length s - 1)) let exe = ref Ocamlbuild_config.exe let targets_internal = ref [] let ocaml_libs_internal = ref [] let ocaml_mods_internal = ref [] let ocaml_pkgs_internal = ref [] let ocaml_syntax = ref None let ocaml_lflags_internal = ref [] let ocaml_cflags_internal = ref [] let ocaml_docflags_internal = ref [] let ocaml_ppflags_internal = ref [] let ocaml_yaccflags_internal = ref [] let ocaml_lexflags_internal = ref [] let program_args_internal = ref [] let ignore_list_internal = ref [] let tags_internal = ref [["quiet"]] let tag_lines_internal = ref [] let show_tags_internal = ref [] let plugin_tags_internal = ref [] let log_file_internal = ref "_log" let my_include_dirs = ref [[Filename.current_dir_name]] let my_exclude_dirs = ref [ [".svn"; "CVS"; ".bzr"; ".hg"; ".git"; "_darcs"; "_opam"; "node_modules"] ] let dummy = "*invalid-dummy-string*";; (* Dummy string for delimiting the latest argument *) (* The JoCaml support will be in a plugin when the plugin system will support * multiple/installed plugins *) let use_jocaml () = ocamlc := A "jocamlc"; plugin_ocamlc := A "jocamlc"; ocamlopt := A "jocamlopt"; plugin_ocamlopt := A "jocamlopt"; ocamldep := A "jocamldep"; ocamlyacc := A "jocamlyacc"; ocamllex := A "jocamllex"; ocamlmklib := A "jocamlmklib"; ocamlmktop := A "jocamlmktop"; ocamlrun := A "jocamlrun"; ;; let add_to rxs x = let xs = Lexers.comma_or_blank_sep_strings Const.Source.command_line (Lexing.from_string x) in rxs := xs :: !rxs let add_to' rxs x = if x <> dummy then rxs := [x] :: !rxs else () let set_cmd rcmd = String (fun s -> rcmd := Sh s) let set_build_dir s = make_links := false; if Filename.is_relative s then build_dir := Filename.concat (Sys.getcwd ()) s else build_dir := s let spec = ref ( let print_version () = Printf.printf "ocamlbuild %s\n%!" Ocamlbuild_config.version; raise Exit_OK in let print_vnum () = print_endline Ocamlbuild_config.version; raise Exit_OK in Arg.align [ "-version", Unit print_version , " Display the version"; "--version", Unit print_version, " same as -version"; "-vnum", Unit print_vnum, " Display the version number"; "--vnum", Unit print_vnum, " same as -vnum"; "-quiet", Unit (fun () -> Log.level := 0), " Make as quiet as possible"; "-verbose", Int (fun i -> Log.classic_display := true; Log.level := i + 2), " Set the verbosity level on a scale from 0 to 8 (included)"; "-documentation", Set show_documentation, " Show rules and flags"; "-log", Set_string log_file_internal, " Set log file"; "-no-log", Unit (fun () -> log_file_internal := ""), " No log file"; "-clean", Set must_clean, " Remove build directory and other files, then exit"; "-r", Set recursive, " Traverse directories by default (true: traverse)"; "-I", String (add_to' my_include_dirs), " Add to include directories"; "-Is", String (add_to my_include_dirs), " (same as above, but accepts a (comma or blank)-separated list)"; "-X", String (add_to' my_exclude_dirs), " Directory to ignore"; "-Xs", String (add_to my_exclude_dirs), " (idem)"; "-lib", String (add_to' ocaml_libs_internal), " Link to this ocaml library"; "-libs", String (add_to ocaml_libs_internal), " (idem)"; "-mod", String (add_to' ocaml_mods_internal), " Link to this ocaml module"; "-mods", String (add_to ocaml_mods_internal), " (idem)"; "-pkg", String (add_to' ocaml_pkgs_internal), " Link to this ocaml findlib package"; "-pkgs", String (add_to ocaml_pkgs_internal), " (idem)"; "-package", String (add_to' ocaml_pkgs_internal), " (idem)"; "-syntax", String (fun syntax -> ocaml_syntax := Some syntax), " Specify syntax using ocamlfind"; "-lflag", String (add_to' ocaml_lflags_internal), " Add to ocamlc link flags"; "-lflags", String (add_to ocaml_lflags_internal), " (idem)"; "-cflag", String (add_to' ocaml_cflags_internal), " Add to ocamlc compile flags"; "-cflags", String (add_to ocaml_cflags_internal), " (idem)"; "-docflag", String (add_to' ocaml_docflags_internal), " Add to ocamldoc flags"; "-docflags", String (add_to ocaml_docflags_internal), " (idem)"; "-yaccflag", String (add_to' ocaml_yaccflags_internal), " Add to ocamlyacc flags"; "-yaccflags", String (add_to ocaml_yaccflags_internal), " (idem)"; "-lexflag", String (add_to' ocaml_lexflags_internal), " Add to ocamllex flags"; "-lexflags", String (add_to ocaml_lexflags_internal), " (idem)"; "-ppflag", String (add_to' ocaml_ppflags_internal), " Add to ocaml preprocessing flags"; "-pp", String (add_to ocaml_ppflags_internal), " (idem)"; "-tag", String (add_to' tags_internal), " Add to default tags"; "-tags", String (add_to tags_internal), " (idem)"; "-plugin-tag", String (add_to' plugin_tags_internal), " Use this tag when compiling the myocamlbuild.ml plugin"; "-plugin-tags", String (add_to plugin_tags_internal), " (idem)"; "-tag-line", String (add_to' tag_lines_internal), " Use this line of tags (as in _tags)"; "-show-tags", String (add_to' show_tags_internal), " Show tags that applies on that pathname"; "-ignore", String (add_to ignore_list_internal), " Don't try to build these modules"; "-no-links", Clear make_links, " Don't make links of produced final targets"; "-no-skip", Clear ignore_auto, " Don't skip modules that are requested by ocamldep but cannot be built"; "-no-hygiene", Clear hygiene, " Don't apply sanity-check rules"; "-no-plugin", Clear plugin, " Don't build myocamlbuild.ml"; "-no-stdlib", Set nostdlib, " Don't ignore stdlib modules"; "-dont-catch-errors", Clear catch_errors, " Don't catch and display exceptions (useful to display the call stack)"; "-just-plugin", Set just_plugin, " Just build myocamlbuild.ml"; "-byte-plugin", Clear native_plugin, " Don't use a native plugin but bytecode"; "-plugin-option", String ignore, " Use the option only when plugin is run"; "-sanitization-script", Set_string sanitization_script, " Change the file name for the generated sanitization script"; "-no-sanitize", Clear sanitize, " Do not generate sanitization script"; "-nothing-should-be-rebuilt", Set nothing_should_be_rebuilt, " Fail if something needs to be rebuilt"; "-classic-display", Set Log.classic_display, " Display executed commands the old-fashioned way"; "-use-menhir", Set use_menhir, " Use menhir instead of ocamlyacc"; "-use-jocaml", Unit use_jocaml, " Use jocaml compilers instead of ocaml ones"; "-use-ocamlfind", Unit (fun () -> use_ocamlfind := true; plugin_use_ocamlfind := true), " Use the 'ocamlfind' wrapper instead of \ using Findlib directly to determine command-line arguments. \ Use -no-ocamlfind to disable. Implies -plugin-use-ocamlfind."; "-no-ocamlfind", Unit (fun () -> use_ocamlfind := false; plugin_use_ocamlfind := false), " Don't use ocamlfind. Implies -plugin-no-ocamlfind."; "-plugin-use-ocamlfind", Set plugin_use_ocamlfind, " Use the 'ocamlfind' wrapper \ for building myocamlbuild.ml"; "-plugin-no-ocamlfind", Clear plugin_use_ocamlfind, " Don't use ocamlfind \ for building myocamlbuild.ml"; "-toolchain", Set_string toolchain, " Set the Findlib toolchain to use. \ The default toolchain is always used for building myocamlbuild.ml."; "-j", Set_int Command.jobs, " Allow N jobs at once (0 for unlimited)"; "-build-dir", String set_build_dir, " Set build directory (implies no-links)"; "-install-lib-dir", Set_string Ocamlbuild_where.libdir, " Set the install library directory"; "-install-bin-dir", Set_string Ocamlbuild_where.bindir, " Set the install binary directory"; "-where", Unit (fun () -> print_endline !Ocamlbuild_where.libdir; raise Exit_OK), " Display the install library directory"; "-which", String (fun cmd -> print_endline (find_tool cmd); raise Exit_OK), " Display path to the tool command"; "-ocamlc", set_cmd ocamlc, " Set the OCaml bytecode compiler"; "-plugin-ocamlc", set_cmd plugin_ocamlc, " Set the OCaml bytecode compiler \ used when building myocamlbuild.ml (only)"; "-ocamlopt", set_cmd ocamlopt, " Set the OCaml native compiler"; "-plugin-ocamlopt", set_cmd plugin_ocamlopt, " Set the OCaml native compiler \ used when building myocamlbuild.ml (only)"; "-ocamldep", set_cmd ocamldep, " Set the OCaml dependency tool"; "-ocamldoc", set_cmd ocamldoc, " Set the OCaml documentation generator"; "-ocamlyacc", set_cmd ocamlyacc, " Set the ocamlyacc tool"; "-menhir", set_cmd ocamlyacc, " Set the menhir tool (use it after -use-menhir)"; "-ocamllex", set_cmd ocamllex, " Set the ocamllex tool"; "-ocamlmklib", set_cmd ocamlmklib, " Set the ocamlmklib tool"; "-ocamlmktop", set_cmd ocamlmktop, " Set the ocamlmktop tool"; "-ocamlrun", set_cmd ocamlrun, " Set the ocamlrun tool"; "--", Rest (fun x -> program_to_execute := true; add_to' program_args_internal x), " Stop argument processing, remaining arguments are given to the user program"; ]) let add x = spec := !spec @ [x] let targets = ref [] let ocaml_libs = ref [] let ocaml_mods = ref [] let ocaml_pkgs = ref [] let ocaml_lflags = ref [] let ocaml_cflags = ref [] let ocaml_ppflags = ref [] let ocaml_docflags = ref [] let ocaml_yaccflags = ref [] let ocaml_lexflags = ref [] let program_args = ref [] let ignore_list = ref [] let tags = ref [] let tag_lines = ref [] let show_tags = ref [] let plugin_tags = ref [] let init () = let anon_fun = add_to' targets_internal in let usage_msg = sprintf "Usage %s [options] " Sys.argv.(0) in let argv' = Array.concat [Sys.argv; [|dummy|]] in parse_argv argv' !spec anon_fun usage_msg; Shell.mkdir_p !build_dir; project_root_dir := Some (Sys.getcwd ()); let () = let log = !log_file_internal in if log = "" then Log.init None else if not (Filename.is_implicit log) then failwith (sprintf "Bad log file name: the file name must be implicit (not %S)" log) else let log = filename_concat !build_dir log in Shell.mkdir_p (Filename.dirname log); Shell.rm_f log; let log = if !Log.level > 0 then Some log else None in Log.init log in let with_ocamlfind (ocamlfind, command_name, command_ref) = command_ref := match !command_ref with | Sh user_command -> (* this command has been set by the user using an -ocamlc, -ocamlopt, etc. flag; not all such combinations make sense (eg. "ocamlfind /my/special/path/to/ocamlc" will make ocamlfind choke), but the user will see the error and hopefully fix the flags. *) ocamlfind & (Sh user_command); | _ -> ocamlfind & A command_name in if !use_ocamlfind then begin begin try ignore(Command.search_in_path "ocamlfind") with Not_found -> failwith "ocamlfind not found on path, but -no-ocamlfind not used" end; (* Note that plugins can still modify these variables After_options. This design decision can easily be changed. *) List.iter with_ocamlfind [ ocamlfind, "ocamlc", ocamlc; ocamlfind, "ocamlopt", ocamlopt; ocamlfind, "ocamldep", ocamldep; ocamlfind, "ocamldoc", ocamldoc; ocamlfind, "ocamlmklib", ocamlmklib; ocamlfind, "ocamlmktop", ocamlmktop; ] end; if !plugin_use_ocamlfind then begin begin try ignore(Command.search_in_path "ocamlfind") with Not_found -> failwith "ocamlfind not found on path, but -no-plugin-ocamlfind not used" end; List.iter with_ocamlfind [ plugin_ocamlfind, "ocamlc", plugin_ocamlc; plugin_ocamlfind, "ocamlopt", plugin_ocamlopt; ] end; let reorder x y = x := !x @ (List.concat (List.rev !y)) in reorder targets targets_internal; reorder ocaml_libs ocaml_libs_internal; reorder ocaml_mods ocaml_mods_internal; reorder ocaml_pkgs ocaml_pkgs_internal; reorder ocaml_cflags ocaml_cflags_internal; reorder ocaml_lflags ocaml_lflags_internal; reorder ocaml_ppflags ocaml_ppflags_internal; reorder ocaml_docflags ocaml_docflags_internal; reorder ocaml_yaccflags ocaml_yaccflags_internal; reorder ocaml_lexflags ocaml_lexflags_internal; reorder program_args program_args_internal; reorder tags tags_internal; reorder tag_lines tag_lines_internal; reorder ignore_list ignore_list_internal; reorder show_tags show_tags_internal; reorder plugin_tags plugin_tags_internal; let check_dir dir = if Filename.is_implicit dir then sys_file_exists dir else failwith (sprintf "Included or excluded directories must be implicit (not %S)" dir) in let dir_reorder my dir = let d = !dir in reorder dir my; dir := List.filter check_dir (!dir @ d) in dir_reorder my_include_dirs include_dirs; dir_reorder my_exclude_dirs exclude_dirs; ignore_list := List.map String.capitalize_ascii !ignore_list ;; (* The current heuristic: we know we are in an ocamlbuild project if either _tags or myocamlbuild.ml are present at the root. This heuristic has been documented and explained to users, so it should not be changed. *) let ocamlbuild_project_heuristic () = let root_dir = match !project_root_dir with | None -> Sys.getcwd () | Some dir -> dir in let at_root file = Filename.concat root_dir file in Sys.file_exists (* authorized since we're not in build *) (at_root "_tags") || Sys.file_exists (* authorized since we're not in build *) (at_root "myocamlbuild.ml") let spec () = !spec ocamlbuild-0.14.3/src/options.mli000066400000000000000000000033421454061437200167070ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) include Signatures.OPTIONS with type command_spec = Command.spec (* This option is not in Signatures.OPTIONS yet because adding tags to the compilation of the plugin is a recent feature that may still be subject to change, so the interface may not be stable; besides, there is obviously little to gain from tweaking that option from inside the plugin itself... *) val plugin_tags : string list ref (* Returns 'true' if we heuristically infer that we are run from an ocamlbuild projet (either _tags or myocamlbuild.ml are present). This information is used to decide whether to enable recursive traversal of subdirectories by default. *) val ocamlbuild_project_heuristic : unit -> bool val spec : unit -> (Arg.key * Arg.spec * Arg.doc) list val entry : bool Slurp.entry option ref val init : unit -> unit ocamlbuild-0.14.3/src/param_tags.ml000066400000000000000000000050231454061437200171570ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) open My_std (* Original author: Romain Bardou *) module StringSet = Set.Make(String) (* tag name -> tag action (string -> unit) *) let declared_tags = Hashtbl.create 17 let acknowledged_tags = ref [] let only_once f = let instances = ref StringSet.empty in fun param -> if StringSet.mem param !instances then () else begin instances := StringSet.add param !instances; f param end let declare name action = Hashtbl.add declared_tags name (only_once action) let parse source tag = Lexers.tag_gen source (lexbuf_of_string tag) let acknowledge source maybe_loc tag = acknowledged_tags := (parse source tag, maybe_loc) :: !acknowledged_tags let really_acknowledge ?(quiet=false) ((name, param), maybe_loc) = match param with | None -> if Hashtbl.mem declared_tags name && not quiet then Log.eprintf "%aWarning: tag %S expects a parameter" Loc.print_loc_option maybe_loc name | Some param -> let actions = List.rev (Hashtbl.find_all declared_tags name) in if actions = [] && not quiet then Log.eprintf "%aWarning: tag %S does not expect a parameter, \ but is used with parameter %S" Loc.print_loc_option maybe_loc name param; List.iter (fun f -> f param) actions let partial_init ?quiet source tags = let parse_noloc tag = (parse source tag, None) in Tags.iter (fun tag -> really_acknowledge ?quiet (parse_noloc tag)) tags let init () = List.iter really_acknowledge (My_std.List.ordered_unique !acknowledged_tags) let make = Printf.sprintf "%s(%s)" let is_applied tag = let len = String.length tag in len > 0 && tag.[len - 1] = ')' ocamlbuild-0.14.3/src/param_tags.mli000066400000000000000000000045661454061437200173430ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Romain Bardou *) val declare: string -> (string -> unit) -> unit (** Declare a parameterized tag. [declare "name" action]: [action "param"] will be executed (once) by [init] if a tag of the form [name(param)] is [acknowledge]d. A given tag may be declared several times with different actions. All actions will be executed, in the order they were declared. *) val acknowledge: Loc.source -> Loc.location option -> string -> unit (** Acknowledge a tag. If the tag is of the form [X(Y)], and have been declared using [declare], then the actions given using [declare] will be executed with [Y] as parameter when [init] is executed. The action will only be called once per acknowledged parameter. *) val init: unit -> unit (** Initialize parameterized tags. This will make effective all instantiations [foo(bar)] such that the parametrized tag [foo] has been [declare]d and [foo(bar)] has been [acknowledge]d after the last [init] call. *) val partial_init: ?quiet:bool -> Loc.source -> Tags.t -> unit (** Initialize a list of tags This will make effective the instances [foo(bar)] appearing in the given tag list, instead of those that have been [acknowledged] previously. This is for system use only. *) val make: Tags.elt -> string -> Tags.elt (** Make a parameterized tag instance. Example: [make "package" "unix"]: return the tag ["package(unix)"] *) val is_applied: Tags.elt -> bool (** [is_applied tag] is [true] when the tag is the result of the application of a parametrized tag. *) ocamlbuild-0.14.3/src/pathname.ml000066400000000000000000000107641454061437200166460ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Format open Log type t = string include Filename let print_strings = List.print String.print let concat = filename_concat let compare (x:t) y = compare x y let print = pp_print_string let mk s = s let pwd = Sys.getcwd () let add_extension ext x = x ^ "." ^ ext let check_extension x ext = let lx = String.length x and lext = String.length ext in lx > lext + 1 && x.[lx - lext - 1] = '.' && String.is_suffix x ext module Operators = struct let ( / ) = concat let ( -.- ) file ext = add_extension ext file end open Operators let equal x y = x = y let to_string x = x let is_link = Shell.is_link let readlink = Shell.readlink let is_directory x = try (My_unix.stat x).My_unix.stat_file_kind = My_unix.FK_dir with Sys_error _ -> false let readdir x = Outcome.good (sys_readdir x) let dir_seps = ['/';'\\'] (* FIXME add more *) let not_normal_form_re = Glob.parse "<**/{,.,..}/**>" let parent x = concat parent_dir_name x let split p = let rec go p acc = let dir = dirname p in if dir = p then dir, acc else go dir (basename p :: acc) in go p [] let join root paths = let root = if root = current_dir_name then "" else root in List.fold_left (/) root paths let _H1 = assert (current_dir_name = ".") let _H2 = assert (parent_dir_name = "..") (* Use H1, H2 *) let rec normalize_list = function | [] -> [] | "." :: xs -> normalize_list xs | ".." :: _ -> failwith "Pathname.normalize_list: .. is forbidden here" | _ :: ".." :: xs -> normalize_list xs | x :: xs -> x :: normalize_list xs let normalize x = if Glob.eval not_normal_form_re x then let root, paths = split x in join root (normalize_list paths) else x (* [is_prefix x y] is [x] a pathname prefix of [y] *) let is_prefix x y = let lx = String.length x and ly = String.length y in if lx = ly then x = (String.before y lx) else if lx < ly then x = (String.before y lx) && List.mem y.[lx] dir_seps else false let link_to_dir p dir = is_link p && is_prefix dir (readlink p) let remove_extension x = try chop_extension x with Invalid_argument _ -> x let get_extension x = try let pos = String.rindex x '.' in String.after x (pos + 1) with Not_found -> "" let update_extension ext x = add_extension ext (chop_extension x) let chop_extensions x = let dirname = dirname x and basename = basename x in try let pos = String.index basename '.' in dirname / (String.before basename pos) with Not_found -> invalid_arg "chop_extensions: no extensions" let remove_extensions x = try chop_extensions x with Invalid_argument _ -> x let get_extensions x = let basename = basename x in try let pos = String.index basename '.' in String.after basename (pos + 1) with Not_found -> "" let update_extensions ext x = add_extension ext (chop_extensions x) let exists = sys_file_exists let copy = Shell.cp let remove = Shell.rm let try_remove x = if exists x then Shell.rm x let read = read_file let with_input_file = with_input_file let with_output_file = with_output_file let print_path_list = List.print print let context_table = Hashtbl.create 107 let rec include_dirs_of dir = try Hashtbl.find context_table dir with Not_found -> dir :: List.filter (fun dir' -> dir <> dir') !Options.include_dirs (* let include_dirs_of s = let res = include_dirs_of s in let () = dprintf 0 "include_dirs_of %S ->@ %a" s (List.print print) res in res *) let define_context dir context = let dir = if dir = "" then current_dir_name else dir in Hashtbl.replace context_table dir& List.union context& include_dirs_of dir let same_contents x y = Digest.file x = Digest.file y ocamlbuild-0.14.3/src/pathname.mli000066400000000000000000000017671454061437200170220ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) include Signatures.PATHNAME val link_to_dir : t -> t -> bool val normalize : t -> t ocamlbuild-0.14.3/src/plugin.ml000066400000000000000000000306711454061437200163460ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Format open Log open Pathname.Operators open Tags.Operators open Rule open Tools open Command ;; let plugin = "myocamlbuild" let plugin_file = plugin^".ml" let plugin_config_file = plugin^"_config.ml" let plugin_config_file_interface = plugin^"_config.mli" let we_have_a_plugin_source () = sys_file_exists plugin_file let we_need_a_plugin_binary () = !Options.plugin && we_have_a_plugin_source () let we_have_a_plugin_binary () = sys_file_exists ((!Options.build_dir/plugin)^(!Options.exe)) let we_have_a_config_file () = sys_file_exists plugin_config_file let we_have_a_config_file_interface () = sys_file_exists plugin_config_file_interface (* exported through plugin.mli *) let we_need_a_plugin () = we_need_a_plugin_binary () module Make(U:sig end) = struct let we_need_a_plugin_binary = we_need_a_plugin_binary () let we_have_a_plugin_source = we_have_a_plugin_source () let we_have_a_config_file = we_have_a_config_file () let we_have_a_config_file_interface = we_have_a_config_file_interface () let we_have_a_plugin_binary () = (* this remains a function as it will change during the build *) we_have_a_plugin_binary () let up_to_date_or_copy fn = let fn' = !Options.build_dir/fn in Pathname.exists fn && begin Pathname.exists fn' && Pathname.same_contents fn fn' || begin Shell.cp fn fn'; false end end let rebuild_plugin () = let a = up_to_date_or_copy plugin_file in let b = (not we_have_a_config_file) || up_to_date_or_copy plugin_config_file in let c = (not we_have_a_config_file_interface) || up_to_date_or_copy plugin_config_file_interface in if a && b && c && we_have_a_plugin_binary () then () (* Up to date *) (* FIXME: remove ocamlbuild_config.ml in _build/ if removed in parent *) else begin if !Options.native_plugin && not (sys_file_exists ((!Ocamlbuild_where.libdir)/"ocamlbuildlib.cmxa")) then begin Options.native_plugin := false; eprintf "Warning: Won't be able to compile a native plugin" end; let plugin_config = if we_have_a_config_file then if we_have_a_config_file_interface then S[P plugin_config_file_interface; P plugin_config_file] else P plugin_config_file else N in let cma, cmo, compiler, byte_or_native = if !Options.native_plugin then "cmxa", "cmx", !Options.plugin_ocamlopt, "native" else "cma", "cmo", !Options.plugin_ocamlc, "byte" in let (unix_spec, ocamlbuild_lib_spec, ocamlbuild_module_spec) = let use_light_mode = not !Options.native_plugin && !*My_unix.is_degraded in let use_ocamlfind_pkgs = !Options.plugin_use_ocamlfind && !Options.plugin_tags <> [] in (* The plugin has the following dependencies that must be included during compilation: - unix.cmxa, if it is available - ocamlbuildlib.cm{a,xa}, the library part of ocamlbuild - ocamlbuild.cm{o,x}, the module that performs the initialization work of the ocamlbuild executable, using modules of ocamlbuildlib.cmxa We pass all this stuff to the compilation command for the plugin, with two independent important details to handle: (1) ocamlbuild is designed to still work in environments where Unix is not available for some reason; in this case, we should not link unix, and use the "ocamlbuildlight.cmo" initialization module, which runs a "light" version of ocamlbuild without unix. There is also an ocamlbuildlightlib.cma archive to be used in that case. The boolean variable [use_light_mode] tells us whether we are in this unix-deprived scenario. (2) there are risks of compilation error due to double-linking of native modules when the user passes its own tags to the plugin compilation process (as was added to support modular construction of ocamlbuild plugins). Indeed, if we hard-code linking to unix.cmxa in all cases, and the user enables -plugin-use-ocamlfind and passes -plugin-tag "package(unix)" (or package(foo) for any foo which depends on unix), the command-line finally executed will be ocamlfind ocamlopt unix.cmxa -package unix myocamlbuild.ml which fails with a compilation error due to doubly-passed native modules. To sanest way to solve this problem at the ocamlbuild level is to pass "-package unix" instead of unix.cmxa when we detect that such a situation may happen. OCamlfind will see that the same package is demanded twice, and only request it once to the compiler. Similarly, we use "-package ocamlbuild" instead of linking ocamlbuildlib.cmxa[1]. We switch to this behavior when two conditions, embodied in the boolean variable [use_ocamlfind_pkgs], are met: (a) plugin-use-ocamlfind is enabled (b) the user is passing some plugin tags Condition (a) is overly conservative as the double-linking issue may also happen in non-ocamlfind situations, such as "-plugin-tags use_unix" -- but it's unclear how one would avoid the issue in that case, except by documenting that people should not do that, or getting rid of the hard-linking logic entirely, with the corresponding risks of regression. Condition (b) should not be necessary (we expect using ocamlfind packages to work whenever ocamlfind is available), but allows the behavior in absence of -plugin-tags to be completely unchanged, to reassure us about potential regressions introduced by this option. [1]: we may wonder whether to use "-package ocamlbuildlight" in unix-deprived situations, but currently ocamlfind doesn't know about the ocamlbuildlight library. As a compromise we always use "-package ocamlbuild" when use_ocamlfind_pkgs is set. An ocamlfind and -plugin-tags user in unix-deprived environment may want to mutate the META of ocamlbuild to point to ocamlbuildlightlib instead of ocamlbuildlib. *) let unix_lib = if use_ocamlfind_pkgs then `Package "unix" else if use_light_mode then `Nothing else `Lib "unix" in let ocamlbuild_lib = if use_ocamlfind_pkgs then `Package "ocamlbuild" else if use_light_mode then `Local_lib "ocamlbuildlightlib" else `Local_lib "ocamlbuildlib" in let ocamlbuild_module = if use_light_mode then `Local_mod "ocamlbuildlight" else `Local_mod "ocamlbuild" in let dir = !Ocamlbuild_where.libdir in let dir = if Pathname.is_implicit dir then Pathname.pwd/dir else dir in let in_dir file = let path = dir/file in if not (sys_file_exists path) then failwith (sprintf "Cannot find %S in ocamlbuild -where directory" file); path in let spec = function | `Nothing -> N | `Package pkg -> S[A "-package"; A pkg] | `Lib lib -> P (lib -.- cma) | `Local_lib llib -> S [A "-I"; A dir; P (in_dir (llib -.- cma))] | `Local_mod lmod -> P (in_dir (lmod -.- cmo)) in (spec unix_lib, spec ocamlbuild_lib, spec ocamlbuild_module) in let plugin_tags = Tags.of_list !Options.plugin_tags ++ "ocaml" ++ "program" ++ "link" ++ byte_or_native in (* The plugin is compiled before [Param_tags.init()] is called globally, which means that parametrized tags have not been made effective yet. The [partial_init] calls below initializes precisely those that will be used during the compilation of the plugin, and no more. *) Param_tags.partial_init Const.Source.plugin_tag plugin_tags; let cmd = (* The argument order is important: we carefully put the plugin source files before the ocamlbuild.cm{o,x} module doing the main initialization, so that user global side-effects (setting options, installing flags..) are performed brefore ocamlbuild's main routine. This is a fragile thing to rely upon and we insist that our users use the more robust [dispatch] registration instead, but we still aren't going to break that now. For the same reason we place the user plugin-tags after the plugin libraries (in case a tag would, say, inject a .cmo that also relies on them), but before the main plugin source file and ocamlbuild's initialization. *) Cmd(S[compiler; unix_spec; ocamlbuild_lib_spec; T plugin_tags; plugin_config; P plugin_file; ocamlbuild_module_spec; A"-o"; Px (plugin^(!Options.exe))]) in Shell.chdir !Options.build_dir; Shell.rm_f (plugin^(!Options.exe)); Command.execute cmd; end let execute_plugin () = Shell.chdir Pathname.pwd; let runner = if !Options.native_plugin then N else !Options.ocamlrun in let argv = List.tl (Array.to_list Sys.argv) in let passed_argv = List.filter (fun s -> s <> "-plugin-option") argv in let spec = S[runner; P(!Options.build_dir/plugin^(!Options.exe)); A"-no-plugin"; atomize passed_argv] in Log.finish (); let rc = sys_command (Command.string_of_command_spec spec) in raise (Exit_silently_with_code rc) let main () = if we_need_a_plugin_binary then begin rebuild_plugin (); if not (we_have_a_plugin_binary ()) then begin Log.eprintf "Error: we failed to build the plugin"; raise (Exit_with_code Exit_codes.rc_build_error); end end; (* if -just-plugin is passed by there is no plugin, nothing happens, and we decided not to emit a warning: this lets people that write ocamlbuild-driver scripts always run a first phase (ocamlbuild -just-plugin ...) if they want to, without having to test for the existence of a plugin first. *) if !Options.just_plugin then begin Log.finish (); raise Exit_OK; end; (* On the contrary, not having a plugin yet passing -plugin-tags is probably caused by a user error that we should warn about; for example people may incorrectly think that -plugin-tag foo.ocamlbuild will enable foo's rules: they have to explicitly use Foo in their plugin and it's best to warn if they don't. *) if not we_have_a_plugin_source && !Options.plugin_tags <> [] then eprintf "Warning: option -plugin-tag(s) has no effect \ in absence of plugin file %S" plugin_file; if we_need_a_plugin_binary && we_have_a_plugin_binary () then execute_plugin () end ;; let execute_plugin_if_needed () = let module P = Make(struct end) in P.main () ;; ocamlbuild-0.14.3/src/plugin.mli000066400000000000000000000020011454061437200165010ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Plugin *) val execute_plugin_if_needed : unit -> unit val we_need_a_plugin : unit -> bool ocamlbuild-0.14.3/src/report.ml000066400000000000000000000050601454061437200163550ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Report *) open My_std open Log open Format open Solver let sources_glob = Glob.parse "<*.ml> or <*.mli> or <*.c> or <*.h>";; let rec analyze f bt = match bt with | Leaf r -> fprintf f "Ocamlbuild knows of no rules that apply to a target named %a. \ This can happen if you ask Ocamlbuild to build a target with the \ wrong extension (e.g. .opt instead of .native) or if the source \ files live in directories that have not been specified as \ include directories." Resource.print r; false | Depth(r, bt) -> if Glob.eval sources_glob r then begin fprintf f "Ocamlbuild cannot find or build %a. A file with such a name would \ usually be a source file. I suspect you have given a wrong target \ name to Ocamlbuild." Resource.print r; false end else analyze f bt | Choice bl -> List.for_all (analyze f) bl | Target(_, bt) -> analyze f bt let rec print_backtrace f = function | Target (name, backtrace) -> fprintf f "@\n- @[<2>Failed to build the target %s%a@]" name print_backtrace backtrace | Leaf r -> fprintf f "@\n- @[<2>Building %a@]" Resource.print r | Depth (r, backtrace) -> fprintf f "@\n- @[Building %a:%a@]" Resource.print r print_backtrace backtrace | Choice [backtrace] -> print_backtrace f backtrace | Choice backtraces -> fprintf f "@\n- @[Failed to build all of these:"; List.iter (print_backtrace f) backtraces; fprintf f "@]" let print_backtrace_analyze f bt = ignore (analyze f bt) ocamlbuild-0.14.3/src/report.mli000066400000000000000000000020721454061437200165260ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Report *) val print_backtrace_analyze : Format.formatter -> Solver.backtrace -> unit val print_backtrace : Format.formatter -> Solver.backtrace -> unit ocamlbuild-0.14.3/src/resource.ml000066400000000000000000000311051454061437200166700ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Format open Log open Pathname.Operators type t = Pathname.t module Resources = Set.Make(Pathname) let print = Pathname.print let equal = (=) let compare = compare let in_source_dir p = if Pathname.is_implicit p then Pathname.pwd/p else invalid_arg (Printf.sprintf "in_source_dir: %S" p) let in_build_dir p = if Pathname.is_relative p then p else invalid_arg (Printf.sprintf "in_build_dir: %S" p) let clean_up_links entry = if not !Options.make_links then entry else Slurp.filter begin fun path name _ -> let pathname = in_source_dir (path/name) in if Pathname.link_to_dir pathname !Options.build_dir then let z = Pathname.readlink pathname in (* Here is one exception where one can use Sys.file_exists directly *) (if not (Sys.file_exists z) then Shell.rm pathname; false) else true end entry let clean_up_link_to_build () = Options.entry := Some(clean_up_links (the !Options.entry)) let source_dir_path_set_without_links_to_build = lazy begin clean_up_link_to_build (); Slurp.fold (fun path name _ -> StringSet.add (path/name)) (the !Options.entry) StringSet.empty end let clean_links () = if !*My_unix.is_degraded then () else ignore (clean_up_link_to_build ()) let exists_in_source_dir p = if !*My_unix.is_degraded then sys_file_exists (in_source_dir p) else StringSet.mem p !*source_dir_path_set_without_links_to_build let clean p = Shell.rm_f p module Cache = struct let clean () = Shell.chdir Pathname.pwd; Shell.rm_rf !Options.build_dir type knowledge = | Yes | No | Unknown type suspension = (Command.t * (unit -> unit)) type build_status = | Bbuilt | Bcannot_be_built | Bnot_built_yet | Bsuspension of suspension type cache_entry = { mutable built : build_status; mutable changed : knowledge; mutable dependencies : Resources.t } let empty () = { built = Bnot_built_yet; changed = Unknown; dependencies = Resources.empty } let print_knowledge f = function | Yes -> pp_print_string f "Yes" | No -> pp_print_string f "No" | Unknown -> pp_print_string f "Unknown" let print_build_status f = function | Bbuilt -> pp_print_string f "Bbuilt" | Bnot_built_yet -> pp_print_string f "Bnot_built_yet" | Bcannot_be_built -> pp_print_string f "Bcannot_be_built" | Bsuspension(cmd, _) -> fprintf f "@[<2>Bsuspension(%a,@ ( : unit -> unit))@]" Command.print cmd let print_cache_entry f e = fprintf f "@[<2>{ @[<2>built =@ %a@];@ @[<2>changed =@ %a@];@ @[<2>dependencies =@ %a@]@ }@]" print_build_status e.built print_knowledge e.changed Resources.print e.dependencies module Hashtbl = Hashtbl.Make(struct type t = Pathname.t let hash = Hashtbl.hash let equal (x:string) y = x = y end) let cache = Hashtbl.create 103 let get r = try Hashtbl.find cache r with Not_found -> let cache_entry = empty () in Hashtbl.add cache r cache_entry; cache_entry let fold_cache f x = Hashtbl.fold f cache x let print_cache f () = fprintf f "@[@[{:"; fold_cache begin fun k v () -> fprintf f "@ @[<2>%a =>@ %a@];" print k print_cache_entry v end (); fprintf f "@]:}@]" let print_graph f () = fprintf f "@[@[{:"; fold_cache begin fun k v () -> if not (Resources.is_empty v.dependencies) then fprintf f "@ @[<2>%a =>@ %a@];" print k Resources.print v.dependencies end (); fprintf f "@]@ :}@]" let resource_changed r = dprintf 10 "resource_changed:@ %a" print r; (get r).changed <- Yes let external_is_up_to_date absolute_path = let key = "Resource: " ^ absolute_path in let digest = Digest.file absolute_path in let is_up_to_date = try let digest' = Digest_cache.get key in digest = digest' with Not_found -> false in is_up_to_date || (Digest_cache.put key digest; false) let source_is_up_to_date r_in_source_dir r_in_build_dir = let key = "Resource: " ^ r_in_source_dir in let digest = Digest.file r_in_source_dir in let r_is_up_to_date = Pathname.exists r_in_build_dir && try let digest' = Digest_cache.get key in digest = digest' with Not_found -> false in r_is_up_to_date || (Digest_cache.put key digest; false) let prod_is_up_to_date p = let x = in_build_dir p in not (exists_in_source_dir p) || Pathname.exists x && Pathname.same_contents x (in_source_dir p) let rec resource_has_changed r = let cache_entry = get r in match cache_entry.changed with | Yes -> true | No -> false | Unknown -> let res = match cache_entry.built with | Bbuilt -> false | Bsuspension _ -> assert false | Bcannot_be_built -> false | Bnot_built_yet -> not (prod_is_up_to_date r) in let () = cache_entry.changed <- if res then Yes else No in res let resource_state r = (get r).built let resource_built r = (get r).built <- Bbuilt let resource_failed r = (get r).built <- Bcannot_be_built let import_in_build_dir r = let cache_entry = get r in let r_in_build_dir = in_build_dir r in let r_in_source_dir = in_source_dir r in if source_is_up_to_date r_in_source_dir r_in_build_dir then begin dprintf 5 "%a exists and up to date" print r; end else begin dprintf 5 "%a exists in source dir -> import it" print r; Shell.mkdir_p (Pathname.dirname r); Pathname.copy r_in_source_dir r_in_build_dir; cache_entry.changed <- Yes; end; cache_entry.built <- Bbuilt let suspend_resource r cmd kont prods = let cache_entry = get r in match cache_entry.built with | Bsuspension _ -> () | Bbuilt -> () | Bcannot_be_built -> assert false | Bnot_built_yet -> let kont = begin fun () -> kont (); List.iter begin fun prod -> (get prod).built <- Bbuilt end prods end in cache_entry.built <- Bsuspension(cmd, kont) let resume_suspension (cmd, kont) = Command.execute cmd; kont () let resume_resource r = let cache_entry = get r in match cache_entry.built with | Bsuspension(s) -> resume_suspension s | Bbuilt -> () | Bcannot_be_built -> () | Bnot_built_yet -> () let get_optional_resource_suspension r = match (get r).built with | Bsuspension cmd_kont -> Some cmd_kont | Bbuilt | Bcannot_be_built | Bnot_built_yet -> None let clear_resource_failed r = (get r).built <- Bnot_built_yet let dependencies r = (get r).dependencies let fold_dependencies f = fold_cache (fun k v -> Resources.fold (f k) v.dependencies) let add_dependency r s = let cache_entry = get r in cache_entry.dependencies <- Resources.add s cache_entry.dependencies let print_dependencies = print_graph end let digest p = let f = Pathname.to_string (in_build_dir p) in let buf = Buffer.create 1024 in Buffer.add_string buf f; (if sys_file_exists f then Buffer.add_string buf (Digest.file f)); Digest.string (Buffer.contents buf) let exists_in_build_dir p = Pathname.exists (in_build_dir p) (* type env = string let split_percent s = try let pos = String.index s '%' in Some (String.before s pos, String.after s (pos + 1)) with Not_found -> None let extract prefix suffix s = let lprefix = String.length prefix in let lsuffix = String.length suffix in let ls = String.length s in if lprefix + lsuffix > ls then None else let s' = String.sub s lprefix (ls - lsuffix - lprefix) in if equal (prefix ^ s' ^ suffix) s then Some s' else None let matchit r1 r2 = match split_percent r1 with | Some (x, y) -> extract x y r2 | _ -> if equal r1 r2 then Some "" else None let rec subst percent r = match split_percent r with | Some (x, y) -> x ^ percent ^ y | _ -> r let print_env = pp_print_string *) (* Should normalize *) let import x = Pathname.normalize x module MetaPath : sig type t type env val mk : (bool * string) -> t val matchit : t -> string -> env option val subst : env -> t -> string val print_env : Format.formatter -> env -> unit end = struct open Glob_ast type atoms = A of string | V of string * Glob.globber type t = atoms list type env = (string * string) list exception No_solution let mk (pattern_allowed, s) = List.map begin function | `Var(var_name, globber) -> V(var_name, globber) | `Word s -> A s end (Lexers.path_scheme pattern_allowed Const.Source.target_pattern (lexbuf_of_string s)) let mk = memo mk let match_prefix s pos prefix = match String.contains_string s pos prefix with | Some(pos') -> if pos = pos' then pos' + String.length prefix else raise No_solution | None -> raise No_solution let matchit p s = let sl = String.length s in let rec loop xs pos acc delta = match xs with | [] -> if pos = sl then acc else raise No_solution | A prefix :: xs -> loop xs (match_prefix s pos prefix) acc 0 | V(var, patt) :: A s2 :: xs' -> begin match String.contains_string s (pos + delta) s2 with | Some(pos') -> let matched = String.sub s pos (pos' - pos) in if Glob.eval patt matched then try loop xs' (pos' + String.length s2) ((var, matched) :: acc) 0 with No_solution -> loop xs pos acc (pos' - pos + 1) else loop xs pos acc (pos' - pos + 1) | None -> raise No_solution end | [V(var, patt)] -> let matched = String.sub s pos (sl - pos) in if Glob.eval patt matched then (var, matched) :: acc else raise No_solution | V _ :: _ -> assert false in try Some (loop p 0 [] 0) with No_solution -> None let pp_opt pp_elt f = function | None -> pp_print_string f "None" | Some x -> Format.fprintf f "Some(%a)" pp_elt x let print_env f env = List.iter begin fun (k, v) -> if k = "" then Format.fprintf f "%%=%s " v else Format.fprintf f "%%(%s)=%s " k v end env (* let matchit p s = let res = matchit p s in Format.eprintf "matchit %S %S = %a@." p s (pp_opt print_env) res; res let _ = begin assert (matchit "%(path)lib%(libname).a" "libfoo.a" <> None); assert (matchit "%(path)lib%(libname).a" "path/libfoo.a" <> None); assert (matchit "libfoo.a" "libfoo.a" <> None); assert (matchit "lib%(libname).a" "libfoo.a" <> None); assert (matchit "%(path)libfoo.a" "path/libfoo.a" <> None); assert (matchit "foo%" "foobar" <> None); exit 42 end;; *) let subst env s = String.concat "" begin List.map begin fun x -> match x with | A atom -> atom | V(var, _) -> try List.assoc var env with Not_found -> (* unbound variable *) "" end s end end type env = MetaPath.env type resource_pattern = (Pathname.t * MetaPath.t) let print_pattern f (x, _) = Pathname.print f x let import_pattern x = x, MetaPath.mk (true, x) let matchit (_, p) x = MetaPath.matchit p x let subst env s = MetaPath.subst env (MetaPath.mk (false, s)) let subst_any env s = MetaPath.subst env (MetaPath.mk (true, s)) let subst_pattern env (_, p) = MetaPath.subst env p let print_env = MetaPath.print_env ocamlbuild-0.14.3/src/resource.mli000066400000000000000000000054351454061437200170500ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Pathname type resource_pattern type env type t = Pathname.t module Resources : Set.S with type elt = t module Cache : sig type cache_entry type suspension type build_status = | Bbuilt | Bcannot_be_built | Bnot_built_yet | Bsuspension of suspension val clean : unit -> unit val resource_state : t -> build_status val resource_changed : t -> unit val resource_has_changed : t -> bool val resource_built : t -> unit val resource_failed : t -> unit val import_in_build_dir : t -> unit val suspend_resource : t -> Command.t -> (unit -> unit) -> t list -> unit val resume_resource : t -> unit val resume_suspension : suspension -> unit val get_optional_resource_suspension : t -> (Command.t * (unit -> unit)) option val clear_resource_failed : t -> unit val add_dependency : t -> t -> unit val fold_dependencies : (string -> string -> 'a -> 'a) -> 'a -> 'a val external_is_up_to_date : t -> bool (* These are not currently used by others modules. *) val dependencies : t -> Resources.t val print_cache : Format.formatter -> unit -> unit val print_dependencies : Format.formatter -> unit -> unit end val digest : t -> string val exists_in_source_dir : t -> bool val exists_in_build_dir : t -> bool val in_build_dir : t -> t val in_source_dir : t -> t val clean_up_links : bool Slurp.entry -> bool Slurp.entry val compare : t -> t -> int val print : Format.formatter -> t -> unit val print_pattern : Format.formatter -> resource_pattern -> unit val clean : t -> unit val import : string -> t val import_pattern : string -> resource_pattern val matchit : resource_pattern -> t -> env option val subst : env -> t -> t val subst_any : env -> t -> t val subst_pattern : env -> resource_pattern -> t (* val is_up_to_date : t -> bool *) val print_env : Format.formatter -> env -> unit ocamlbuild-0.14.3/src/rule.ml000066400000000000000000000300041454061437200160050ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Format open Log open Outcome module Resources = Resource.Resources exception Exit_rule_error of string exception Failed type env = Pathname.t -> Pathname.t type builder = Pathname.t list list -> (Pathname.t, exn) Outcome.t list type action = env -> builder -> Command.t type digest_command = { digest : string; command : Command.t } type 'a gen_rule = { name : string; deps : Pathname.t list; (* These pathnames must be normalized *) prods : 'a list; (* Note that prods also contains stamp *) stamp : 'a option; doc : string option; code : env -> builder -> digest_command } type rule = Pathname.t gen_rule type rule_scheme = Resource.resource_pattern gen_rule let name_of_rule r = r.name let deps_of_rule r = r.deps let prods_of_rule r = r.prods let stamp_of_rule r = r.stamp let doc_of_rule r = r.doc type 'a rule_printer = (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a gen_rule -> unit let compare _ _ = assert false let print_rule_name f r = pp_print_string f r.name let print_resource_list = List.print Resource.print let print_rule_contents ppelt f r = fprintf f "@[{@ @[<2>name =@ %S@];@ @[<2>deps =@ %a@];@ @[<2>prods = %a@];@ @[<2>code = @];@ @[ doc = %s@]@]@ }" r.name print_resource_list r.deps (List.print ppelt) r.prods (match r.doc with | None -> "None" | Some doc -> sprintf "Some %S" doc) let pretty_print ppelt f r = fprintf f "@[rule %S@ ~deps:%a@ ~prods:%a@ " r.name print_resource_list r.deps (List.print ppelt) r.prods; begin match r.doc with | None -> () | Some doc -> fprintf f "~doc:\"@[%a@]\"@ " pp_print_text doc end; fprintf f "@]" let print = print_rule_name let subst env rule = let subst_resources = List.map (Resource.subst env) in let subst_resource_patterns = List.map (Resource.subst_pattern env) in let finder next_finder p = next_finder (Resource.subst_any env p) in let stamp = match rule.stamp with None -> None | Some x -> Some (Resource.subst_pattern env x) in let prods = subst_resource_patterns rule.prods in { name = sbprintf "%s (%a)" rule.name Resource.print_env env; prods = prods; deps = (* The substition should preserve normalization of pathnames *) subst_resources rule.deps; stamp = stamp; doc = rule.doc; code = (fun env -> rule.code (finder env)) } exception Can_produce of rule let can_produce target rule = try List.iter begin fun resource -> match Resource.matchit resource target with | Some env -> raise (Can_produce (subst env rule)) | None -> () end rule.prods; None with Can_produce r -> Some r let digest_prods r = List.fold_right begin fun p acc -> let f = Pathname.to_string (Resource.in_build_dir p) in if sys_file_exists f then (f, Digest.file f) :: acc else acc end r.prods [] let digest_deps r dyndeps = let buf = Buffer.create 1024 in let add_resource r = Buffer.add_string buf (Digest.to_hex (Resource.digest r)) in Buffer.add_string buf "deps:"; List.iter add_resource r.deps; Buffer.add_string buf "dyndeps:"; Resources.iter add_resource dyndeps; Digest.to_hex (Digest.string (Buffer.contents buf)) let digest_rule r dyndeps action = let buf = Buffer.create 1024 in Buffer.add_string buf action.digest; let add_resource r = Buffer.add_string buf (Resource.digest r) in Buffer.add_string buf "prods:"; List.iter add_resource r.prods; Buffer.add_string buf "deps:"; List.iter add_resource r.deps; Buffer.add_string buf "dyndeps:"; Resources.iter add_resource dyndeps; Digest.string (Buffer.contents buf) let cached_digest r = try Some (Digest_cache.get ("Rule: " ^ r.name)) with Not_found -> None let store_digest r digest = Digest_cache.put ("Rule: " ^ r.name) digest let print_digest f x = pp_print_string f (Digest.to_hex x) let exists2 find p rs = try Some (find p rs) with Not_found -> None let build_deps_of_tags builder tags = match Command.deps_of_tags tags with | [] -> [] | deps -> List.map Outcome.good (builder (List.map (fun x -> [x]) deps)) let build_deps_of_tags_on_cmd builder = Command.iter_tags begin fun tags -> match Command.deps_of_tags tags with | [] -> () | deps -> List.iter ignore_good (builder (List.map (fun x -> [x]) deps)) end let call builder r = let dyndeps = ref Resources.empty in let builder rs = let results = builder rs in List.map begin fun res -> match res with | Good res' -> let () = dprintf 10 "new dyndep for %S(%a): %S" r.name print_resource_list r.prods res' in dyndeps := Resources.add res' !dyndeps; List.iter (fun x -> Resource.Cache.add_dependency x res') r.prods; res | Bad _ -> res end results in let () = dprintf 5 "start rule %a" print r in let action = r.code (fun x -> x) builder in build_deps_of_tags_on_cmd builder action.command; let dyndeps = !dyndeps in let () = dprintf 10 "dyndeps: %a" Resources.print dyndeps in let (reason, cached) = match exists2 List.find (fun r -> not (Resource.exists_in_build_dir r)) r.prods with | Some r -> (`cache_miss_missing_prod r, false) | _ -> begin match exists2 List.find Resource.Cache.resource_has_changed r.deps with | Some r -> (`cache_miss_changed_dep r, false) | _ -> begin match exists2 Resources.find_elt Resource.Cache.resource_has_changed dyndeps with | Some r -> (`cache_miss_changed_dyn_dep r, false) | _ -> begin match cached_digest r with | None -> (`cache_miss_no_digest, false) | Some d -> let rule_digest = digest_rule r dyndeps action in if d = rule_digest then (`cache_hit, true) else (`cache_miss_digest_changed(d, rule_digest), false) end end end in let explain_reason l = raw_dprintf (l+1) "mid rule %a: " print r; match reason with | `cache_miss_missing_prod r -> dprintf l "cache miss: a product is not in build dir (%a)" Resource.print r | `cache_miss_changed_dep r -> dprintf l "cache miss: a dependency has changed (%a)" Resource.print r | `cache_miss_changed_dyn_dep r -> dprintf l "cache miss: a dynamic dependency has changed (%a)" Resource.print r | `cache_miss_no_digest -> dprintf l "cache miss: no digest found for %S (the command, a dependency, or a product)" r.name | `cache_hit -> dprintf (l+1) "cache hit" | `cache_miss_digest_changed(old_d, new_d) -> dprintf l "cache miss: the digest has changed for %S (the command, a dependency, or a product: %a <> %a)" r.name print_digest old_d print_digest new_d in let prod_digests = digest_prods r in (if not cached then List.iter Resource.clean r.prods); (if !Options.nothing_should_be_rebuilt && not cached then (explain_reason (-1); let msg = sbprintf "Need to rebuild %a through the rule `%a'" print_resource_list r.prods print r in raise (Exit_rule_error msg))); explain_reason 3; let thunk () = try if cached then Command.execute ~pretend:true action.command else begin match r.stamp with | Some stamp -> reset_filesys_cache (); let digest_deps = digest_deps r dyndeps in with_output_file stamp (fun oc -> output_string oc digest_deps) | None -> () end; List.iter (fun r -> Resource.Cache.resource_built r) r.prods; (if not cached then let new_rule_digest = digest_rule r dyndeps action in let new_prod_digests = digest_prods r in let () = store_digest r new_rule_digest in List.iter begin fun p -> let f = Pathname.to_string (Resource.in_build_dir p) in (try let digest = List.assoc f prod_digests in let new_digest = List.assoc f new_prod_digests in if digest <> new_digest then raise Not_found with Not_found -> Resource.Cache.resource_changed p) end r.prods); dprintf 5 "end rule %a" print r with exn -> (List.iter Resource.clean r.prods; raise exn) in if cached then thunk () else List.iter (fun x -> Resource.Cache.suspend_resource x action.command thunk r.prods) r.prods let (get_rules, add_rule, clear_rules) = let rules = ref [] in (fun () -> !rules), begin fun pos r -> try let _ = List.find (fun x -> x.name = r.name) !rules in raise (Exit_rule_error (sbprintf "Rule.add_rule: already exists: (%a)" print r)) with Not_found -> match pos with | `bottom -> rules := !rules @ [r] | `top -> rules := r :: !rules | `after s -> rules := List.fold_right begin fun x acc -> if x.name = s then x :: r :: acc else x :: acc end !rules [] | `before s -> rules := List.fold_right begin fun x acc -> if x.name = s then r :: x :: acc else x :: acc end !rules [] end, (fun () -> rules := []) let rule name ?tags ?(prods=[]) ?(deps=[]) ?prod ?dep ?stamp ?(insert = `bottom) ?doc code = let () = match tags with | None -> () | Some _ -> Log.eprintf "Warning: your ocamlbuild rule %S uses the ~tags parameter, which is deprecated and ignored." name in let res_add import xs xopt = let init = match xopt with | None -> [] | Some r -> [import r] in List.fold_right begin fun x acc -> let r = import x in if List.mem r acc then failwith (sprintf "in rule %s, multiple occurrences of the resource %s" name x) else r :: acc end xs init in if prods = [] && prod = None && stamp = None then raise (Exit_rule_error "Can't make a rule that produces nothing"); let stamp, prods = match stamp with | None -> None, prods | Some stamp -> Some (Resource.import_pattern stamp), stamp :: prods in let prods = res_add Resource.import_pattern prods prod in let code env build = let cmd = code env build in { digest = Command.digest cmd ; command = cmd } in add_rule insert { name = name; deps = res_add Resource.import (* should normalize *) deps dep; stamp = stamp; doc = doc; prods = prods; code = code } module Common_commands = struct open Command let mv src dest = Cmd (S [A"mv"; P src; Px dest]) let cp src dest = Cmd (S [A"cp"; P src; Px dest]) let cp_p src dest = Cmd (S [A"cp"; A"-p"; P src; Px dest]) let ln_f pointed pointer = Cmd (S [A"ln"; A"-f"; P pointed; Px pointer]) let ln_s pointed pointer = Cmd (S[A"ln"; A"-s"; P pointed; Px pointer]) let rm_f x = Cmd (S [A"rm"; A"-f"; Px x]) let chmod opts file = Cmd (S[A"chmod"; opts; Px file]) let cmp a b = Cmd (S[A"cmp"; P a; Px b]) end open Common_commands let copy_rule name ?insert src dest = rule name ?insert ~prod:dest ~dep:src begin fun env _ -> let src = env src and dest = env dest in Shell.mkdir_p (Pathname.dirname dest); cp_p src dest end let show_documentation () = let pp fmt = Log.raw_dprintf (-1) fmt in let rules = get_rules () in List.iter (fun rule -> pp "%a@\n@\n" (pretty_print Resource.print_pattern) rule) rules; pp "@." ocamlbuild-0.14.3/src/rule.mli000066400000000000000000000060211454061437200161600ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Resource type env = Pathname.t -> Pathname.t type builder = Pathname.t list list -> (Pathname.t, exn) Outcome.t list type action = env -> builder -> Command.t type 'a gen_rule type rule = Pathname.t gen_rule type rule_scheme = resource_pattern gen_rule type 'a rule_printer = (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a gen_rule -> unit (** This exception can be raised inside the action of a rule to make the algorithm skip this rule. *) exception Failed val name_of_rule : 'a gen_rule -> string val deps_of_rule : 'a gen_rule -> Pathname.t list val prods_of_rule : 'a gen_rule -> 'a list val doc_of_rule : 'a gen_rule -> string option val rule : string -> ?tags:string list -> ?prods:string list -> ?deps:string list -> ?prod:string -> ?dep:string -> ?stamp:string -> ?insert:[`top | `before of string | `after of string | `bottom] -> ?doc:string -> action -> unit (** [copy_rule name ?insert source destination] *) val copy_rule : string -> ?insert:[`top | `before of string | `after of string | `bottom] -> string -> string -> unit module Common_commands : sig val mv : Pathname.t -> Pathname.t -> Command.t val cp : Pathname.t -> Pathname.t -> Command.t val cp_p : Pathname.t -> Pathname.t -> Command.t val ln_f : Pathname.t -> Pathname.t -> Command.t val ln_s : Pathname.t -> Pathname.t -> Command.t val rm_f : Pathname.t -> Command.t val chmod : Command.spec -> Pathname.t -> Command.t val cmp : Pathname.t -> Pathname.t -> Command.t end val print : Format.formatter -> rule -> unit val pretty_print : 'a rule_printer (** For system use only *) val subst : Resource.env -> rule_scheme -> rule val can_produce : Pathname.t -> rule_scheme -> rule option (* val tags_matches : Tags.t -> t -> t option *) val compare : 'a gen_rule -> 'a gen_rule -> int val print_rule_name : Format.formatter -> 'a gen_rule -> unit val print_rule_contents : 'a rule_printer val get_rules : unit -> rule_scheme list val clear_rules : unit -> unit val call : builder -> rule -> unit val build_deps_of_tags : builder -> Tags.t -> Pathname.t list val show_documentation : unit -> unit ocamlbuild-0.14.3/src/shell.ml000066400000000000000000000103251454061437200161510ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std let is_simple_filename s = let ls = String.length s in ls <> 0 && let rec loop pos = if pos >= ls then true else match s.[pos] with | 'a'..'z' | 'A'..'Z' | '0'..'9' | '.' | '-' | '/' | '_' | ':' | '@' | '+' | ',' -> loop (pos + 1) | _ -> false in loop 0 let quote_filename_if_needed s = if is_simple_filename s then s (* We should probably be using [Filename.unix_quote] except that function * isn't exported. Users on Windows will have to live with not being able to * install OCaml into c:\o'caml. Too bad. *) else if Sys.os_type = "Win32" then Printf.sprintf "'%s'" s else Filename.quote s let chdir dir = reset_filesys_cache (); Sys.chdir dir let run args target = reset_readdir_cache (); let cmd = String.concat " " (List.map quote_filename_if_needed args) in if !*My_unix.is_degraded || Sys.os_type = "Win32" then begin Log.event cmd target Tags.empty; let st = sys_command cmd in if st <> 0 then failwith (Printf.sprintf "Error during command `%s'.\nExit code %d.\n" cmd st) else () end else match My_unix.execute_many ~ticker:Log.update ~display:Log.display [[(fun () -> cmd)]] with | None -> () | Some(_, x) -> failwith (Printf.sprintf "Error during command %S: %s" cmd (Printexc.to_string x)) let rm = sys_remove let rm_f x = if sys_file_exists x then () else (* We checked that the file does not exist, but we still ignore failures due to the possibility of race conditions -- another thread having removed the file at the same time. See issue #300 and PR #302 for a race-condition in the wild, and a reproduction script. We could reproduce such races due to the Shell.rm_f call on the log file at the start of ocamlbuild's invocation. *) try sys_remove x with _ -> () let mkdir dir = reset_filesys_cache_for_file dir; (*Sys.mkdir dir (* MISSING in ocaml *) *) run ["mkdir"; dir] dir let try_mkdir dir = if not (sys_file_exists dir) then (* We checked that the file does not exist, but we still ignore failures due to the possibility of race conditions -- same as rm_f above. Note: contrarily to the rm_f implementation which uses sys_remove directly, the 'mkdir' implementation uses 'run', which will create noise in the log and on display, especially in case of (ignored) failure: an error message will be shown, but the call will still be considered a success. Error messages only occur in racy scenarios that we don't support, so this is probably okay. *) try mkdir dir with _ -> () let rec mkdir_p dir = if sys_file_exists dir then () else begin mkdir_p (Filename.dirname dir); try_mkdir dir end let cp_pf src dest = reset_filesys_cache_for_file dest; run["cp";"-pf";src;dest] dest (* Archive files are handled specially during copy *) let cp src dst = if Filename.check_suffix src ".a" && Filename.check_suffix dst ".a" then cp_pf src dst (* try to make a hard link *) else copy_file src dst let readlink = My_unix.readlink let is_link = My_unix.is_link let rm_rf x = reset_filesys_cache (); run["rm";"-Rf";x] x let mv src dest = reset_filesys_cache_for_file src; reset_filesys_cache_for_file dest; run["mv"; src; dest] dest (*Sys.rename src dest*) ocamlbuild-0.14.3/src/shell.mli000066400000000000000000000026741454061437200163320ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) val is_simple_filename : string -> bool val quote_filename_if_needed : string -> string (** This will quote using Unix conventions, even on Windows, because commands are * always run through bash -c on Windows. *) val chdir : string -> unit val rm : string -> unit val rm_f : string -> unit val rm_rf : string -> unit val mkdir : string -> unit val try_mkdir : string -> unit val mkdir_p : string -> unit val cp : string -> string -> unit val mv : string -> string -> unit val readlink : string -> string val is_link : string -> bool ocamlbuild-0.14.3/src/signatures.mli000066400000000000000000001046561454061437200174120ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (** This module contains all module signatures that the user could use to build an ocamlbuild plugin. *) module type OrderedTypePrintable = sig type t val compare : t -> t -> int val print : Format.formatter -> t -> unit end module type SET = sig include Set.S val find_elt : (elt -> bool) -> t -> elt val map : (elt -> elt) -> t -> t val of_list : elt list -> t val print : Format.formatter -> t -> unit end module type LIST = sig (* Added functions *) val print : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a list -> unit val filter_opt : ('a -> 'b option) -> 'a list -> 'b list val union : 'a list -> 'a list -> 'a list val ordered_unique : 'a list -> 'a list val index_of: 'a -> 'a list -> int option (** give the offset of an element (0 for the first element) *) val split_at: int -> 'a list -> 'a list * 'a list (** split the list before the element at the given offset *) (* Original functions *) include module type of List end module type STRING = sig val print : Format.formatter -> string -> unit val chomp : string -> string (** [before s n] returns the substring of all characters of [s] that precede position [n] (excluding the character at position [n]). This is the same function as {!Str.string_before}. *) val before : string -> int -> string (** [after s n] returns the substring of all characters of [s] that follow position [n] (including the character at position [n]). This is the same function as {!Str.string_after}. *) val after : string -> int -> string val first_chars : string -> int -> string (** [first_chars s n] returns the first [n] characters of [s]. This is the same function as {!before} ant {!Str.first_chars}. *) val last_chars : string -> int -> string (** [last_chars s n] returns the last [n] characters of [s]. This is the same function as {!Str.last_chars}. *) val eq_sub_strings : string -> int -> string -> int -> int -> bool (** [is_prefix u v] is u a prefix of v ? *) val is_prefix : string -> string -> bool (** [is_suffix u v] : is v a suffix of u ? *) val is_suffix : string -> string -> bool (** [contains_string s1 p2 s2] Search in [s1] starting from [p1] if it contains the [s2] string. Returns [Some position] where [position] is the beginning of the string [s2] in [s1], [None] otherwise. *) val contains_string : string -> int -> string -> int option (** [subst patt repl text] *) val subst : string -> string -> string -> string (** [tr patt repl text] *) val tr : char -> char -> string -> string val rev : string -> string (* Convert a character list into a character string *) val implode : char list -> string (* Convert a character string into a character list *) val explode : string -> char list (** The following are original functions from the [String] module. *) include module type of String end module type TAGS = sig include Set.S with type elt = string (** [Tags.elt] represents a tag, which is simply a string, usually lowercase, for example "ocaml" or "native". The set of tags attached to a file is computed by applying the tagging rules to the filename. Tagging rules are defined in _tags files in any parent directory of a file, up to the main project directory. *) val of_list : string list -> t val print : Format.formatter -> t -> unit val does_match : t -> t -> bool module Operators : sig val ( ++ ) : t -> elt -> t val ( -- ) : t -> elt -> t val ( +++ ) : t -> elt option -> t val ( --- ) : t -> elt option -> t end end module type PATHNAME = sig type t = string val concat : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool val exists : t -> bool val mk : string -> t val define_context : string -> string list -> unit val include_dirs_of : string -> string list val copy : t -> t -> unit val to_string : t -> string val print : Format.formatter -> t -> unit val current_dir_name : t val parent_dir_name : t val read : t -> string val same_contents : t -> t -> bool val basename : t -> t val dirname : t -> t val is_relative : t -> bool val readlink : t -> t val readdir : t -> t array val is_link : t -> bool val is_directory : t -> bool val add_extension : string -> t -> t val check_extension : t -> string -> bool val get_extension : t -> string val remove_extension : t -> t val update_extension : string -> t -> t val get_extensions : t -> string val remove_extensions : t -> t val update_extensions : string -> t -> t val print_path_list : Format.formatter -> t list -> unit val pwd : t val parent : t -> t (** [is_prefix x y] is [x] a pathname prefix of [y] *) val is_prefix : t -> t -> bool val is_implicit : t -> bool module Operators : sig val ( / ) : t -> t -> t val ( -.- ) : t -> string -> t end end (** Provides an abstract type for easily building complex shell commands without making quotation mistakes. *) module type COMMAND = sig type tags type pathname (** The type [t] provides some basic combinators and command primitives. Other commands can be made of command specifications ([spec]). *) type t = | Seq of t list (** A sequence of commands (like the `;' in shell) *) | Cmd of spec (** A command is made of command specifications ([spec]) *) | Echo of string list * pathname (** Write the given strings as is (newlines are not added) to the given file *) | Nop (** The command that does nothing *) (** The type for command specifications. That is pieces of command. *) and spec = | N (** No operation. *) | S of spec list (** A sequence. This gets flattened in the last stages *) | A of string (** An atom. *) | P of pathname (** A pathname. *) | Px of pathname (** A pathname, that will also be given to the call_with_target hook. *) | Sh of string (** A bit of raw shell code, that will not be escaped. *) | T of tags (** A set of tags, that describe properties and some semantics information about the command, afterward these tags will be replaced by command [spec]s (flags for instance). *) | V of string (** A virtual command, that will be resolved at execution using [resolve_virtuals] *) | Quote of spec (** A string that should be quoted like a filename but isn't really one. *) (*type v = [ `Seq of v list | `Cmd of vspec | `Nop ] and vspec = [ `N | `S of vspec list | `A of string | `P of pathname | `Px of pathname | `Sh of string | `Quote of vspec ] val spec_of_vspec : vspec -> spec val vspec_of_spec : spec -> vspec val t_of_v : v -> t val v_of_t : t -> v*) (** Will convert a string list to a list of atoms by adding [A] constructors. *) val atomize : string list -> spec (** Will convert a string list to a list of paths by adding [P] constructors. *) val atomize_paths : string list -> spec (** Run the command. *) val execute : ?quiet:bool -> ?pretend:bool -> t -> unit (** Run the commands in the given list, if possible in parallel. See the module [Ocamlbuild_executor]. *) val execute_many : ?quiet:bool -> ?pretend:bool -> t list -> (bool list * exn) option (** [setup_virtual_command_solver virtual_command solver] the given solver can raise Not_found if it fails to find a valid command for this virtual command. *) val setup_virtual_command_solver : string -> (unit -> spec) -> unit (** Search the given command in the command path and return its absolute pathname. *) val search_in_path : string -> string (** Simplify a command by flattening the sequences and resolving the tags into command-line options. *) val reduce : spec -> spec (** Print a command (the format is not suitable to running the command). *) val print : Format.formatter -> t -> unit (** Convert a command to a string (same format as print). *) val to_string : t -> string (** Build a string representation of a command that can be passed to the system calls. *) val string_of_command_spec : spec -> string end (** A self-contained module implementing extended shell glob patterns who have an expressive power equal to boolean combinations of regular expressions. *) module type GLOB = sig (** A globber is a boolean combination of basic expressions indented to work on pathnames. Known operators are [or], [and] and [not], which may also be written [|], [&] and [~]. There are also constants [true] and [false] (or [1] and [0]). Expression can be grouped using parentheses. - [true] matches anything, - [false] matches nothing, - {i basic} [or] {i basic} matches strings matching either one of the basic expressions, - {i basic} [and] {i basic} matches strings matching both basic expressions, - not {i basic} matches string that don't match the basic expression, - {i basic} matches strings that match the basic expression. A basic expression can be a constant string enclosed in double quotes, in which double quotes must be preceded by backslashes, or a glob pattern enclosed between a [<] and a [>], - ["]{i string}["] matches the literal string {i string}, - [<]{i glob}[>] matches the glob pattern {i glob}. A glob pattern is an anchored regular expression in a shell-like syntax. Most characters stand for themselves. Character ranges are given in usual shell syntax between brackets. The star [*] stands for any sequence of characters. The joker '?' stands for exactly one, unspecified character. Alternation is achieved using braces [{]. - {i glob1}{i glob2} matches strings who have a prefix matching {i glob1} and the corresponding suffix matching {i glob2}. - [a] matches the string consisting of the single letter [a]. - [{]{i glob1},{i glob2}[}] matches strings matching {i glob1} or {i glob2}. - [?] any one-letter string, excluding the slash. - [*] matches all strings not containing a slash, including the empty one. - [**/] the empty string, or any string ending with a slash. - [/**] any string starting with a slash, or the empty string. - [/**/] any string starting and ending with a slash. - [\[]{i c1}-{i c2}{i c3}-{i c4}...[\]] matches characters in the range {i c1} to {i c2} inclusive, or in the range {i c3} to {i c4} inclusive. For instance [\[a-fA-F0-9\]] matches hexadecimal digits. To match the dash, put it at the end. *) (** The type representing globbers. Do not attempt to compare them, as they get on-the-fly optimizations. *) type globber (** [parse ~dir pattern] will parse the globber pattern [pattern], optionally prefixing its patterns with [dir]. *) val parse : ?dir:string -> string -> globber (** A descriptive exception raised when an invalid glob pattern description is given. *) exception Parse_error of string (** [eval g u] returns [true] if and only if the string [u] matches the given glob expression. Avoid re-parsing the same pattern, since the automaton implementing the pattern is optimized on the fly. The first few evaluations are done using a time-inefficient but memory-efficient algorithm. It then compiles the pattern into an efficient but more memory-hungry data structure. *) val eval : globber -> string -> bool end (** Module for modulating the logging output with the logging level. *) module type LOG = sig (** Current logging (debugging) level. *) val level : int ref (** [dprintf level fmt args...] formats the logging information [fmt] with the arguments [args...] on the logging output if the logging level is greater than or equal to [level]. The default level is 1. More obscure debugging information should have a higher logging level. Your formats are wrapped inside these two formats ["@\[<2>"] and ["@\]@."]. *) val dprintf : int -> ('a, Format.formatter, unit) format -> 'a (** @return whether logging at this level will print anything *) val is_logging : int -> bool (** Equivalent to calling [dprintf] with a level [< 0]. *) val eprintf : ('a, Format.formatter, unit) format -> 'a (** Same as dprintf but without the format wrapping. *) val raw_dprintf : int -> ('a, Format.formatter, unit) format -> 'a end module type OUTCOME = sig type ('a,'b) t = | Good of 'a | Bad of 'b val wrap : ('a -> 'b) -> 'a -> ('b, exn) t val ignore_good : ('a, exn) t -> unit val good : ('a, exn) t -> 'a end module type MISC = sig val opt_print : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a option -> unit val the : 'a option -> 'a val getenv : ?default:string -> string -> string val with_input_file : ?bin:bool -> string -> (in_channel -> 'a) -> 'a val with_output_file : ?bin:bool -> string -> (out_channel -> 'a) -> 'a val with_temp_file : string -> string -> (string -> 'a) -> 'a val read_file : string -> string val copy_chan : in_channel -> out_channel -> unit val copy_file : string -> string -> unit val print_string_list : Format.formatter -> string list -> unit (** A shortcut to force lazy value (See {Lazy.force}). *) val ( !* ) : 'a Lazy.t -> 'a (** The right associative application. Useful when writing to much parentheses: << f (g x ... t) >> becomes << f& g x ... t >> << f (g (h x)) >> becomes << f& g& h x >> *) val ( & ) : ('a -> 'b) -> 'a -> 'b (** The reversed application combinator. Useful to describe some operations chaining. << f x (g y (h z)) >> becomes << z |> h |> g y |> f x >> *) val ( |> ) : 'a -> ('a -> 'b) -> 'b (** [r @:= l] is equivalent to [r := !r @ l] *) val ( @:= ) : 'a list ref -> 'a list -> unit val memo : ('a -> 'b) -> ('a -> 'b) val memo2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'c) val memo3 : ('a -> 'b -> 'c -> 'd) -> ('a -> 'b -> 'c -> 'd) end module type OPTIONS = sig type command_spec val build_dir : string ref val include_dirs : string list ref val exclude_dirs : string list ref val nothing_should_be_rebuilt : bool ref val ocamlc : command_spec ref val plugin_ocamlc : command_spec ref val ocamlopt : command_spec ref val plugin_ocamlopt : command_spec ref val ocamldep : command_spec ref val ocamldoc : command_spec ref val ocamlyacc : command_spec ref val ocamllex : command_spec ref val ocamlrun : command_spec ref val ocamlmklib : command_spec ref val ocamlmktop : command_spec ref val hygiene : bool ref val sanitize : bool ref val sanitization_script : string ref val ignore_auto : bool ref val plugin : bool ref val just_plugin : bool ref val native_plugin : bool ref val make_links : bool ref val nostdlib : bool ref val program_to_execute : bool ref val must_clean : bool ref val catch_errors : bool ref val use_menhir : bool ref val show_documentation : bool ref val recursive : bool ref val use_ocamlfind : bool ref val plugin_use_ocamlfind : bool ref val targets : string list ref val ocaml_libs : string list ref val ocaml_mods : string list ref val ocaml_pkgs : string list ref val ocaml_syntax : string option ref val ocaml_cflags : string list ref val ocaml_lflags : string list ref val ocaml_ppflags : string list ref val ocaml_docflags : string list ref val ocaml_yaccflags : string list ref val ocaml_lexflags : string list ref val program_args : string list ref val ignore_list : string list ref val tags : string list ref val tag_lines : string list ref val show_tags : string list ref val ext_obj : string ref val ext_lib : string ref val ext_dll : string ref val exe : string ref val add : Arg.key * Arg.spec * Arg.doc -> unit end module type ARCH = sig type 'a arch = private | Arch_dir of string * 'a * 'a arch list | Arch_dir_pack of string * 'a * 'a arch list | Arch_file of string * 'a val dir : string -> unit arch list -> unit arch val dir_pack : string -> unit arch list -> unit arch val file : string -> unit arch type info = private { current_path : string; include_dirs : string list; for_pack : string; } val annotate : 'a arch -> info arch val print : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a arch -> unit val print_include_dirs : Format.formatter -> string list -> unit val print_info : Format.formatter -> info -> unit val iter_info : ('a -> unit) -> 'a arch -> unit val fold_info : ('a -> 'b -> 'b) -> 'a arch -> 'b -> 'b val iter_include_dirs : info arch -> (string -> unit) -> unit val mk_tables : info arch -> (string, string list) Hashtbl.t * (string, string) Hashtbl.t val print_table : (Format.formatter -> 'a -> unit) -> Format.formatter -> (string, 'a) Hashtbl.t -> unit end module type FINDLIB = sig (** Findlib / Ocamlfind tools. *) type command_spec type error = | Cannot_run_ocamlfind | Dependency_not_found of string * string (* package, dependency *) | Package_not_found of string | Cannot_parse_query of string * string (* package, explanation *) exception Findlib_error of error val string_of_error: error -> string (** Return a string message describing an error. *) val report_error: error -> 'a (** Report an error on the standard error and exit with code 2. *) type package = { name: string; description: string; version: string; archives_byte: string; (** Archive names, with the .cma extension, but without the directory. *) archives_native: string; (** Archive names, with the .cmxa extension, but without the directory. *) link_options: string; location: string; dependencies: package list; (** Transitive closure, as returned by [ocamlfind query -r]. *) } (** Package information. *) val query: string -> package (** Query information about a package, given its name. May raise [Not_found]. *) val list: unit -> string list (** Return the names of all known packages. *) val topological_closure: package list -> package list (** Computes the transitive closure of a list of packages and sort them in topological order. Given any list of package [l], [topological_closure l] returns a list of packages including [l] and their dependencies, in an order where any element may only depend on the previous ones. *) val include_flags: package list -> command_spec (** Return the list of include directories. *) val compile_flags_byte: package list -> command_spec (** Return the flags to add when compiling in byte mode (include directories). *) val compile_flags_native: package list -> command_spec (** Same as [compile_flags_byte] but for native mode. *) val link_flags_byte: package list -> command_spec (** Return the flags to add when linking in byte mode. It includes: include directories, libraries and special link options. *) val link_flags_native: package list -> command_spec (** Same as [link_flags_byte] but for native mode. *) end (** This module contains the functions and values that can be used by plugins. *) module type PLUGIN = sig module Pathname : PATHNAME module Tags : TAGS module Command : COMMAND with type tags = Tags.t and type pathname = Pathname.t module Outcome : OUTCOME module String : STRING module List : LIST module StringSet : Set.S with type elt = String.t module Options : OPTIONS with type command_spec = Command.spec module Arch : ARCH module Findlib : FINDLIB with type command_spec = Command.spec include MISC (** See {!COMMAND.t} for the description of this type. *) type command = Command.t = | Seq of command list | Cmd of spec | Echo of string list * Pathname.t | Nop (** See {!COMMAND.spec} for the description of this type. *) and spec = Command.spec = | N | S of spec list | A of string | P of string | Px of string | Sh of string | T of Tags.t | V of string | Quote of spec (** [path1/path2] Join the given path names. *) val ( / ) : Pathname.t -> Pathname.t -> Pathname.t (** [path-.-extension] Add the given extension to the given pathname. *) val ( -.- ) : Pathname.t -> string -> Pathname.t (** [tags++tag] Add the given tag to the given set of tags. *) val ( ++ ) : Tags.t -> Tags.elt -> Tags.t (** [tags--tag] Remove the given tag to the given set of tags. *) val ( -- ) : Tags.t -> Tags.elt -> Tags.t (** [tags+++optional_tag] Add the given optional tag to the given set of tags if the given option is Some. *) val ( +++ ) : Tags.t -> Tags.elt option -> Tags.t (** [tags---optional_tag] Remove the given optional tag to the given set of tags if the given option is Some. *) val ( --- ) : Tags.t -> Tags.elt option -> Tags.t (** Targets and dependencies in rules are patterns, which are matched by the actual targets requested by the user. For example, if a rule explains how to build "%.cmo" from "%.ml", it will be fired if the user tries to build "foo.cmo". The environment records the value of the pattern variables (here "%") in this matching. In the context of our example, the environment will be a function substituting "%" by "foo"; calling it on "%.cmo" will return "foo.cmo", and calling it on "%.ml" will return "foo.ml". For a typical example of use of the environment, see the [ocamldep_ml_command] example in the documentation of {!action} below. *) type env = Pathname.t -> Pathname.t (** A builder is a function that waits for a conjunction of alternative targets. The alternatives are here to support some choices, for instance for an OCaml module an alternatives can be foo.cmo or Foo.cmo. Conjunctions are here to enable parallelism: commands that are independent will be run concurrently. For example, passing [["foo.cmi"; "Foo.cmi"]; ["bar.cmi"; "Bar.cmi"]] will build the interfaces of the modules Foo and Bar, trying both possible capitalization of the source file names. For an example of use of a builder function, see the [targets] function given as an example in the documentation of the {!action} type below. *) type builder = Pathname.t list list -> (Pathname.t, exn) Outcome.t list (** This is the type for rule actions. An action receive as argument, the environment lookup function (see {!env}), and a function to dynamically build more targets (see {!builder}). An action should return the command to run in order to build the rule productions using the rule dependencies. For example, here is an action to build an [ocamldep] command, for use in the example of rule given in the documentation of {!rule} below: {[ let ocamldep_ml_command env _build = let arg = env "%.ml" and out = env "%.ml.depends" in let tags = tags_of_pathname arg ++ "ocaml" ++ "ocamldep" in Cmd(S[A "ocamldep"; T tags; A "-modules"; P arg; Sh ">"; Px out]) ]} In the example above, the build function is not used, as there are no dynamic dependencies. There are in the example below: we build a list of targets dynamically read from a "foo.itarget" file. The final command returned by the action links each of them in the current directory. {[ let target_list env build = let itarget = env "%.itarget" in let targets = let dir = Pathname.dirname itarget in let files = string_list_of_file itarget in List.map (fun file -> [Pathname.concat dir file]) files in let results = List.map Outcome.good (build targets) in let link_command result = Cmd (S [A "ln"; A "-sf"; P (Pathname.concat !Options.build_dir result); A Pathname.pwd]) in Seq (List.map link_command results) ]} *) type action = env -> builder -> Command.t (** This is the main function for adding a rule to the ocamlbuild engine. - The first argument is the name of the rule (should be unique). - It takes files that the rule produces. Use [~prod] for one file, [~prods] for list of files. - It also takes files that the rule uses. Use [~dep] for one file, [~deps] for list of files. - It finally takes the action to perform in order to produce the productions files using the dependencies (see [action]). There are some more optional parameters: - The [~insert] argument allows to insert the rules precisely between other rules. - The [~stamp] argument specifies the name of a file that will be automatically produced by ocamlbuild. This file can serve as a virtual target (or phony target), since it will be filled up by a digest of it dependencies. - The [~tags] argument in deprecated, don't use it. Finally, the optional [~doc] argument allows to give an informal explanation of the rule purpose and behavior, that will be displayed by [ocamlbuild -documentation]. For example, it is a good place to specify the commands that will be called, any new tags introduced by the rule, and dynamic dependencies. For example, here is how a rule producing [foo.ml.depends] from [foo.ml] (calling [ocamldep]) is defined, slightly simplified from the built-in definition. {[ rule "ocaml dependencies ml" ~prod:"%.ml.depends" ~dep:"%.ml" ~doc:"call ocamldep to compute a syntactic over-approximation \\ of the dependencies of the corresponding implementation file" ocamldep_ml_command ]} The rule that builds a list of targets from a [%.itarget] file is an example of use of the [?stamp] argument. It uses the [target_list] action provided in the documentation of {!action} above. Besides the targets listed in the [%.itarget] file, this command will also produce a [%.otarget] file (the "stamp") that contains the digest of all the [%.itarget] dependencies. This stamp file is the name to use when you want to ask OCamlbuild to build the targets listed: invoking [ocamlbuild foo.otarget] will build the the targets listed in [foo.itarget]. Similarly, new rules that would depend on that list of targets should depend on [%.otarget] (output), not [%.itarget] (input). {[ rule "target files" ~dep:"%.itarget" ~stamp:"%.otarget" ~doc:"If foo.itarget contains a list of ocamlbuild targets, \ asking ocamlbuild to produce foo.otarget will \ build each of those targets in turn." target_list ]} *) val rule : string -> ?tags:string list -> ?prods:string list -> ?deps:string list -> ?prod:string -> ?dep:string -> ?stamp:string -> ?insert:[`top | `before of string | `after of string | `bottom] -> ?doc:string -> action -> unit (** [copy_rule name ?insert source destination] *) val copy_rule : string -> ?insert:[`top | `before of string | `after of string | `bottom] -> string -> string -> unit (** Empties the list of rules of the ocamlbuild engine. *) val clear_rules : unit -> unit (** [dep tags deps] Will build [deps] when all [tags] will be activated. If you do not know which tags to use, have a look to the file _build/_log after trying to compile your code. *) val dep : Tags.elt list -> Pathname.t list -> unit (** [pdep tags ptag deps] is equivalent to [dep tags deps], with an additional parametrized tag [ptag]. [deps] is now a function which takes the parameter of the tag [ptag] as an argument. Example: [pdep ["ocaml"; "compile"] "autodep" (fun param -> param)] says that the tag [autodep(file)] can now be used to automatically add [file] as a dependency when compiling an OCaml program. *) val pdep : Tags.elt list -> Tags.elt -> (string -> Pathname.t list) -> unit (** [flag tags command_spec] Will inject the given piece of command ([command_spec]) when all [tags] will be activated. If you do not know which tags to use, have a look to the file _build/_log after trying to compile your code. *) val flag : Tags.elt list -> Command.spec -> unit (** Allows to use [flag] with a parametrized tag (as [pdep] for [dep]). Example: [pflag ["ocaml"; "compile"] "inline" (fun count -> S [A "-inline"; A count])] says that command line option ["-inline 42"] should be added when compiling OCaml modules tagged with ["inline(42)"]. *) val pflag : Tags.elt list -> Tags.elt -> (string -> Command.spec) -> unit (** [flag_and_dep tags command_spec] Combines [flag] and [dep] function. Basically it calls [flag tags command_spec], and calls [dep tags files] where [files] is the list of all pathnames in [command_spec]. Pathnames selected are those in the constructor [P] or [Px], or the pathname argument of builtins like [Echo]. *) val flag_and_dep : Tags.elt list -> Command.spec -> unit (** Allows to use [flag_and_dep] with a parametrized tag (as [pdep] for [dep]). *) val pflag_and_dep : Tags.elt list -> Tags.elt -> (string -> Command.spec) -> unit (** manually mark the tag as "useful" to silence the warning about tags that are not part of any flag declaration. This is useful, for example, if the tag is used in a flag declaration that is only performed in a conditional branch: [if we_are_on_Windows then flag ["libfoo"] (A "bar");] When [we_are_on_Windows] is not true, you could get a warning about "libfoo" not used in any flag declaration. *) val mark_tag_used : Tags.elt -> unit (** [non_dependency module_path module_name] Example: [non_dependency "foo/bar/baz" "Goo"] Says that the module [Baz] in the file [foo/bar/baz.*] does not depend on [Goo]. *) val non_dependency : Pathname.t -> string -> unit (** [use_lib module_path lib_path]*) val use_lib : Pathname.t -> Pathname.t -> unit (** [ocaml_lib library_pathname] Declare an ocaml library. This informs ocamlbuild and produce tags to use the library; they are named by default use_#{library_name}. Example: [ocaml_lib "foo/bar"] will setup the tag use_bar. At link time it will include: foo/bar.cma or foo/bar.cmxa @param dir supply the [~dir:"boo"] option to add '-I boo' at link and compile time. @param extern use ~extern:true for non-ocamlbuild handled libraries. Set this to add libraries whose sources are not in your project. @param byte use ~byte:false to disable byte mode. @param native use ~native:false to disable native mode. @param tag_name Use ~tag_name:"usebar" to override the default tag name. *) val ocaml_lib : ?extern:bool -> ?byte:bool -> ?native:bool -> ?dir:Pathname.t -> ?tag_name:string -> Pathname.t -> unit (** [expand_module include_dirs module_name extensions] Example: [expand_module ["a";"b";"c"] "Foo" ["cmo";"cmi"] = ["a/foo.cmo"; "a/Foo.cmo"; "a/foo.cmi"; "a/Foo.cmi"; "b/foo.cmo"; "b/Foo.cmo"; "b/foo.cmi"; "b/Foo.cmi"; "c/foo.cmo"; "c/Foo.cmo"; "c/foo.cmi"; "c/Foo.cmi"]] *) val expand_module : Pathname.t list -> Pathname.t -> string list -> Pathname.t list (** Reads the given file, parse it has list of words separated by blanks. It ignore lines that begins with a '#' character. *) val string_list_of_file : Pathname.t -> string list (** Takes a pathname and returns an OCaml module name. Basically it will remove directories and extensions, and then capitalize the string. *) val module_name_of_pathname : Pathname.t -> string (** The Unix mv command. *) val mv : Pathname.t -> Pathname.t -> Command.t (** The Unix cp command. *) val cp : Pathname.t -> Pathname.t -> Command.t (** The Unix ln -f command. *) val ln_f : Pathname.t -> Pathname.t -> Command.t (** The Unix ln -s command. *) val ln_s : Pathname.t -> Pathname.t -> Command.t (** The Unix rm -f command. *) val rm_f : Pathname.t -> Command.t (** The Unix chmod command (almost deprecated). *) val chmod : Command.spec -> Pathname.t -> Command.t (** The Unix cmp command (almost deprecated). *) val cmp : Pathname.t -> Pathname.t -> Command.t (** [hide_package_contents pack_name] Don't treat the given package as an open package. So a module will not be replaced during linking by this package even if it contains that module. *) val hide_package_contents : string -> unit (** [tag_file filename tag_list] Tag the given filename with all given tags. Prefix a tag with the minus sign to remove it. This is usually used as an [After_rules] hook. For example [tag_file "bla.ml" ["use_unix"]] tags the file "bla.ml" with "use_unix" and [tag_file "bla.ml" ["-use_unix"]] removes the tag "use_unix" from the file "bla.ml". *) val tag_file : Pathname.t -> Tags.elt list -> unit (** [tag_any tag_list] Tag anything with all given tags. *) val tag_any : Tags.elt list -> unit (** Returns the set of tags that applies to the given pathname. *) val tags_of_pathname : Pathname.t -> Tags.t (** Run the given command and returns it's output as a string. *) val run_and_read : string -> string (** Here is the list of hooks that the dispatch function have to handle. Generally one responds to one or two hooks (like After_rules) and do nothing in the default case. *) type hook = | Before_hygiene | After_hygiene | Before_options | After_options | Before_rules | After_rules (** [dispatch hook_handler] Is the entry point for ocamlbuild plugins. Every plugin must call it with a [hook_handler] where all calls to plugin functions lives. *) val dispatch : (hook -> unit) -> unit end ocamlbuild-0.14.3/src/slurp.ml000066400000000000000000000146661454061437200162230ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Slurp *) open My_std open Outcome type 'a entry = | Dir of string * string * My_unix.stats Lazy.t * 'a * 'a entry list Lazy.t | File of string * string * My_unix.stats Lazy.t * 'a | Error of exn | Nothing let (/) = filename_concat let rec filter predicate = function | Dir(path, name, st, attr, entries) -> if predicate path name attr then Dir(path, name, st, attr, lazy (List.map (filter predicate) !*entries)) else Nothing | File(path, name, _, attr) as f -> if predicate path name attr then f else Nothing | Nothing -> Nothing | Error _ as e -> e let real_slurp path = let cwd = Sys.getcwd () in let abs x = if Filename.is_implicit x || Filename.is_relative x then cwd/x else x in let visited = Hashtbl.create 1024 in let rec scandir path names = let (file_acc, dir_acc) = Array.fold_left begin fun ((file_acc, dir_acc) as acc) name -> match do_entry true path name with | None -> acc | Some((Dir _|Error _) as entry) -> (file_acc, entry :: dir_acc) | Some((File _) as entry) -> (entry :: file_acc, dir_acc) | Some Nothing -> acc end ([], []) names in file_acc @ dir_acc and do_entry link_mode path name = let fn = path/name in let absfn = abs fn in match try Good(if link_mode then My_unix.lstat absfn else My_unix.stat absfn) with | x -> Bad x with | Bad x -> Some(Error x) | Good st -> let key = st.My_unix.stat_key in if try Hashtbl.find visited key with Not_found -> false then None else begin Hashtbl.add visited key true; let res = match st.My_unix.stat_file_kind with | My_unix.FK_link -> let fn' = My_unix.readlink absfn in if sys_file_exists (abs fn') then do_entry false path name else Some(File(path, name, lazy st, ())) | My_unix.FK_dir -> (match sys_readdir absfn with | Good names -> Some(Dir(path, name, lazy st, (), lazy (scandir fn names))) | Bad exn -> Some(Error exn)) | My_unix.FK_other -> None | My_unix.FK_file -> Some(File(path, name, lazy st, ())) in Hashtbl.replace visited key false; res end in match do_entry true "" path with | None -> raise Not_found | Some entry -> entry let split path = let rec aux path = if path = Filename.current_dir_name then [] else (Filename.basename path) :: aux (Filename.dirname path) in List.rev (aux path) let rec join = function | [] -> assert false | [x] -> x | x :: xs -> x/(join xs) let rec add root path entries = match path, entries with | [], _ -> entries | xpath :: xspath, (Dir(dpath, dname, dst, dattr, dentries) as d) :: entries -> if xpath = dname then Dir(dpath, dname, dst, dattr, lazy (add (root/xpath) xspath !*dentries)) :: entries else d :: add root path entries | [xpath], [] -> [File(root, xpath, lazy (My_unix.stat (root/xpath)), ())] | xpath :: xspath, [] -> [Dir(root/(join xspath), xpath, lazy (My_unix.stat (root/(join path))), (), lazy (add (root/xpath) xspath []))] | _, Nothing :: entries -> add root path entries | _, Error _ :: _ -> entries | [xpath], (File(_, fname, _, _) as f) :: entries' -> if xpath = fname then entries else f :: add root path entries' | xpath :: xspath, (File(fpath, fname, fst, fattr) as f) :: entries' -> if xpath = fname then Dir(fpath, fname, fst, fattr, lazy (add (root/xpath) xspath [])) :: entries' else f :: add root path entries' let slurp_with_find path = let find_cmd = try Sys.getenv "OCAMLBUILD_FIND" with _ -> "find" in let lines = My_unix.run_and_open (Printf.sprintf "%s %s" find_cmd (Filename.quote path)) begin fun ic -> let acc = ref [] in try while true do acc := input_line ic :: !acc done; [] with End_of_file -> !acc end in let res = List.fold_right begin fun line acc -> add path (split line) acc end lines [] in match res with | [] -> Nothing | [entry] -> entry | entries -> Dir(path, Filename.basename path, lazy (My_unix.stat path), (), lazy entries) let slurp x = if !*My_unix.is_degraded then slurp_with_find x else real_slurp x let rec print print_attr f entry = match entry with | Dir(path, name, _, attr, entries) -> Format.fprintf f "@[<2>Dir(%S,@ %S,@ _,@ %a,@ %a)@]" path name print_attr attr (List.print (print print_attr)) !*entries | File(path, name, _, attr) -> Format.fprintf f "@[<2>File(%S,@ %S,@ _,@ %a)@]" path name print_attr attr | Nothing -> Format.fprintf f "Nothing" | Error(_) -> Format.fprintf f "Error(_)" let rec fold f entry acc = match entry with | Dir(path, name, _, attr, contents) -> f path name attr (List.fold_right (fold f) !*contents acc) | File(path, name, _, attr) -> f path name attr acc | Nothing | Error _ -> acc let map f entry = let rec self entry = match entry with | Dir(path, name, st, attr, contents) -> Dir(path, name, st, f path name attr, lazy (List.map self !*contents)) | File(path, name, st, attr) -> File(path, name, st, f path name attr) | Nothing -> Nothing | Error e -> Error e in self entry let rec force = function | Dir(_, _, st, _, contents) -> let _ = !*st in List.iter force !*contents | File(_, _, st, _) -> ignore !*st | Nothing | Error _ -> () ocamlbuild-0.14.3/src/slurp.mli000066400000000000000000000050101454061437200163530ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Berke Durak *) (* Slurp *) (** Scans a directory lazily to build a tree that can be user-decorated. *) type 'a entry = Dir of string * string * My_unix.stats Lazy.t * 'a * 'a entry list Lazy.t (** [Dir(path, name, lst, decoration, lentries)] is a directory named [name] whose path is [path]. Its stat is lazily stored in [lst] and its entries are lazily scanned in [lentries]. [decoration] is of type 'a. *) | File of string * string * My_unix.stats Lazy.t * 'a (** [File(path, name, lst, decoration)] is a file named [name] whose path is [path]. Its stat is lazily stored in [lst]. [decoration] is of type 'a. *) | Error of exn (** [Error x] means that the exception [x] was raised while scanning or statting an entry. *) | Nothing (** Convenient when filtering out entries. *) (** Recursively scan the filesystem starting at the given directory. *) val slurp : string -> unit entry (** [filter f entry] only retains from [entry] the nodes for which [f path name] returns [true]. *) val filter : (string -> string -> 'a -> bool) -> 'a entry -> 'a entry (** [map f entries] changes the decoration in [entries] by applying [f] to them. [f] is called as [f path name decoration]. *) val map : (string -> string -> 'a -> 'b) -> 'a entry -> 'b entry (** [fold f entry x] iterates [f] over the entries and an accumulator initially containing [x]; at each iteration, [f] gets the current value of the accumulator and returns its new value. *) val fold : (string -> string -> 'b -> 'a -> 'a) -> 'b entry -> 'a -> 'a (** Force the evaluation of the whole entry. *) val force : 'a entry -> unit ocamlbuild-0.14.3/src/solver.ml000066400000000000000000000133071454061437200163570ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) open My_std open Log open Outcome type backtrace = | Leaf of Pathname.t | Choice of backtrace list | Depth of Pathname.t * backtrace | Target of string * backtrace exception Failed of backtrace exception Circular of Pathname.t * Pathname.t list let failed target backtrace = Resource.Cache.resource_failed target; raise (Failed backtrace) let rec pp_repeat f (n, s) = let open Format in if n > 0 then (pp_print_string f s; pp_repeat f (n - 1, s)) (* Targets must be normalized pathnames. * Recursive calls are either on input targets * or dependencies of these targets (returned by Rule.deps_of_rule). *) let rec self depth on_the_go target = let rules = Rule.get_rules () in (* skip allocating fmt on a hot path *) if is_logging 4 then dprintf 4 "==%a> %a" pp_repeat (depth, "==") Resource.print target; begin match List.index_of target on_the_go with | None -> () (* good no cycle *) | Some n -> raise (Circular(target, fst (List.split_at (n+1) on_the_go))) end; let on_the_go = target :: on_the_go in match Resource.Cache.resource_state target with | Resource.Cache.Bbuilt -> (if is_logging 5 then dprintf 5 "%a already built" Resource.print target) | Resource.Cache.Bcannot_be_built -> (if is_logging 5 then dprintf 5 "%a already failed" Resource.print target; failed target (Leaf target)) | Resource.Cache.Bsuspension(s) -> (if is_logging 5 then dprintf 5 "%a was suspended -> resuming" Resource.print target; Resource.Cache.resume_suspension s) | Resource.Cache.Bnot_built_yet -> if not (Pathname.is_relative target) && Pathname.exists target then if Resource.Cache.external_is_up_to_date target then () else (* perhaps the error can be refined *) failed target (Leaf target) else if Resource.exists_in_source_dir target then Resource.Cache.import_in_build_dir target else match List.filter_opt (Rule.can_produce target) rules with | [] -> failed target (Leaf target) | matching_rules -> let rec until_works rs backtraces = match rs with | [] -> assert false | r :: rs -> try List.iter (force_self (depth + 1) on_the_go) (Rule.deps_of_rule r); try Rule.call (self_firsts (depth + 1) on_the_go) r with Rule.Failed -> raise (Failed (Leaf target)) with Failed backtrace -> if rs = [] then failed target (Depth (target, Choice (backtrace :: backtraces))) else let () = match backtrace with | Depth (top_prod, _) -> Resource.Cache.clear_resource_failed top_prod | Target _ | Choice _ | Leaf _ -> () in until_works rs (backtrace :: backtraces) in until_works matching_rules [] (* Build the first target that is buildable *) and self_first depth on_the_go already_failed rs = match rs with | [] -> Bad (Failed (Choice already_failed)) | r :: rs -> try self depth on_the_go r; Good r with Failed backtrace -> self_first depth on_the_go (backtrace :: already_failed) rs (* This variant is the one (once partially applied) called the 'build' * function in the rule actions. * * This one takes a list of list of pathnames to build. * This is a parallel conjonction of sequential alternatives. * This means that in each sublist of pathnames, the first * target that is buildable will be picked. The outer list * denotes that one can build each target in parallel. *) and self_firsts depth on_the_go rss = let results = List.map (self_first depth on_the_go []) rss in let cmds, thunks = List.fold_right begin fun res ((acc1, acc2) as acc) -> match res with | Bad _ -> acc | Good res -> match Resource.Cache.get_optional_resource_suspension res with | None -> acc | Some (cmd, thunk) -> (cmd :: acc1, thunk :: acc2) end results ([], []) in let count = List.length cmds in let job_debug = if !Command.jobs = 1 then 10 else 5 in (* skip allocating fmt on a hot path *) if is_logging job_debug && count > 1 then dprintf job_debug ">>> PARALLEL: %d" count; let opt_exn = Command.execute_many cmds in if is_logging job_debug && count > 1 then dprintf job_debug "<<< PARALLEL"; begin match opt_exn with | Some(res, exn) -> List.iter2 (fun res thunk -> if res then thunk ()) res thunks; Log.finish ~how:`Error (); raise exn | None -> List.iter (fun thunk -> thunk ()) thunks end; results and force_self depth on_the_go x = self depth on_the_go x; Resource.Cache.resume_resource x let solve = force_self 0 [] let solve_target name rs = match self_first 0 [] [] rs with | Good res -> Resource.Cache.resume_resource res; res | Bad (Failed backtrace) -> raise (Failed (Target (name, backtrace))) | Bad exn -> raise exn ocamlbuild-0.14.3/src/solver.mli000066400000000000000000000023411454061437200165240ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) type backtrace = private | Leaf of Pathname.t | Choice of backtrace list | Depth of Pathname.t * backtrace | Target of string * backtrace exception Failed of backtrace exception Circular of Pathname.t * Pathname.t list val solve : Pathname.t -> unit val solve_target : string -> Pathname.t list -> Pathname.t ocamlbuild-0.14.3/src/tags.ml000066400000000000000000000041571454061437200160060ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) let compare_tags str1 str2 = let len1, len2 = String.length str1, String.length str2 in if len1 = 0 || len2 = 0 then String.compare str1 str2 else (* if the last character is ')', the tag is an applied parametrized tag; place it first for visibility *) begin match str1.[len1 - 1] = ')', str2.[len2 - 1] = ')' with | true, false -> -1 | false, true -> 1 | true, true | false, false -> String.compare str1 str2 end include Set.Make(struct type t = string let compare = compare_tags end) (** does_match {foo, bar, baz} {foo} => ok does_match {foo, bar, baz} {foo, boo} => ko does_match {foo, bar, baz} {} => ok does_match {foo, bar, baz} {foo, bar, baz} => ok *) let does_match x y = subset y x let of_list l = List.fold_right add l empty open Format let print f s = let () = fprintf f "@[<0>" in let _ = fold begin fun elt first -> if not first then fprintf f ",@ "; pp_print_string f elt; false end s true in fprintf f "@]" module Operators = struct let ( ++ ) x y = add y x let ( -- ) x y = remove y x let ( +++ ) x = function Some y -> add y x | None -> x let ( --- ) x = function Some y -> remove y x | None -> x end ocamlbuild-0.14.3/src/tags.mli000066400000000000000000000016741454061437200161600ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) include Signatures.TAGS ocamlbuild-0.14.3/src/tools.ml000066400000000000000000000032611454061437200162030ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Tools *) open My_std open Format open Log open Pathname.Operators open Tags.Operators open Rule let pp_l = List.print String.print let tags_of_pathname p = Configuration.tags_of_filename (Pathname.to_string p) ++("file:"^p) ++("extension:" ^ Pathname.get_extension p) let opt_print elt ppf = function | Some x -> fprintf ppf "@[<2>Some@ %a@]" elt x | None -> pp_print_string ppf "None" let path_and_context_of_string s = if Pathname.is_implicit s then let b = Pathname.basename s in let d = Pathname.dirname s in if d <> Pathname.current_dir_name then let () = Pathname.define_context d [d] in [s] else let include_dirs = Pathname.include_dirs_of d in List.map (fun include_dir -> include_dir/b) include_dirs else [s] ocamlbuild-0.14.3/src/tools.mli000066400000000000000000000021161454061437200163520ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Original author: Nicolas Pouillard *) (* Tools *) val tags_of_pathname : Pathname.t -> Tags.t val path_and_context_of_string : Pathname.t -> Pathname.t list val pp_l : Format.formatter -> string list -> unit ocamlbuild-0.14.3/test/000077500000000000000000000000001454061437200146775ustar00rootroot00000000000000ocamlbuild-0.14.3/test/good-output000066400000000000000000002143751454061437200171240ustar00rootroot00000000000000 _____ _ ____ |_ _|__ ___| |_|___ \ | |/ _ \/ __| __| __) | | | __/\__ \ |_ / __/ |_|\___||___/\__|_____| ocamldep.opt -modules toto.ml > toto.ml.depends ocamldep.opt -modules tata.mli > tata.mli.depends ocamldep.opt -modules titi.ml > titi.ml.depends ocamldep.opt -modules tutu.mli > tutu.mli.depends ocamlc.opt -c -o tata.cmi tata.mli ocamlc.opt -c -o titi.cmo titi.ml ocamlc.opt -c -o tutu.cmi tutu.mli ocamlc.opt -c -o toto.cmo toto.ml ocamldep.opt -modules tata.ml > tata.ml.depends ocamldep.opt -modules tutu.ml > tutu.ml.depends ocamldep.opt -modules tyty.mli > tyty.mli.depends ocamldep.opt -pp camlp4o.opt -modules vivi.ml > vivi.ml.depends ocamlc.opt -c -o tyty.cmi tyty.mli ocamlc.opt -c -pp camlp4o.opt -o vivi.cmo vivi.ml ocamlc.opt -c -o tata.cmo tata.ml ocamlc.opt -c -o tutu.cmo tutu.ml ocamlc.opt tata.cmo titi.cmo vivi.cmo tutu.cmo toto.cmo -o toto.byte ocamlopt.opt -c -pp camlp4o.opt -o vivi.cmx vivi.ml ocamlopt.opt -c -o tata.cmx tata.ml ocamlopt.opt -c -o titi.cmx titi.ml ocamlopt.opt -c -o tutu.cmx tutu.ml ocamlopt.opt -c -o toto.cmx toto.ml ocamlopt.opt tata.cmx titi.cmx vivi.cmx tutu.cmx toto.cmx -o toto.native Warning: Using -- only run the last target toto.native: /home/danmey/src/ocaml-trunk/ocamlbuild/test/test2/_build/toto.native: Hello world!!! Tutu.tutu => 1 Tata.tata => "TATA2" [cache hit] ocamldep.opt -modules toto.ml > toto.ml.depends [cache hit] ocamldep.opt -modules tata.mli > tata.mli.depends [cache hit] ocamlc.opt -c -o tata.cmi tata.mli [cache hit] ocamldep.opt -modules titi.ml > titi.ml.depends [cache hit] ocamlc.opt -c -o titi.cmo titi.ml [cache hit] ocamldep.opt -modules tutu.mli > tutu.mli.depends [cache hit] ocamlc.opt -c -o tutu.cmi tutu.mli [cache hit] ocamlc.opt -c -o toto.cmo toto.ml [cache hit] ocamldep.opt -modules tata.ml > tata.ml.depends [cache hit] ocamlc.opt -c -o tata.cmo tata.ml [cache hit] ocamldep.opt -modules tutu.ml > tutu.ml.depends [cache hit] ocamldep.opt -modules tyty.mli > tyty.mli.depends [cache hit] ocamlc.opt -c -o tyty.cmi tyty.mli [cache hit] ocamldep.opt -pp camlp4o.opt -modules vivi.ml > vivi.ml.depends [cache hit] ocamlc.opt -c -pp camlp4o.opt -o vivi.cmo vivi.ml [cache hit] ocamlc.opt -c -o tutu.cmo tutu.ml [cache hit] ocamlc.opt tata.cmo titi.cmo vivi.cmo tutu.cmo toto.cmo -o toto.byte [cache hit] ocamlopt.opt -c -o tata.cmx tata.ml [cache hit] ocamlopt.opt -c -o titi.cmx titi.ml [cache hit] ocamlopt.opt -c -pp camlp4o.opt -o vivi.cmx vivi.ml [cache hit] ocamlopt.opt -c -o tutu.cmx tutu.ml [cache hit] ocamlopt.opt -c -o toto.cmx toto.ml [cache hit] ocamlopt.opt tata.cmx titi.cmx vivi.cmx tutu.cmx toto.cmx -o toto.native Warning: Using -- only run the last target toto.native: /home/danmey/src/ocaml-trunk/ocamlbuild/test/test2/_build/toto.native: Hello world!!! Tutu.tutu => 1 Tata.tata => "TATA2" ocamldep.opt -pp camlp4o.opt -modules vivi.ml > vivi.ml.depends ocamlc.opt -c -pp camlp4o.opt -o vivi.cmo vivi.ml ocamlc.opt tata.cmo titi.cmo vivi.cmo tutu.cmo toto.cmo -o toto.byte ocamlopt.opt -c -pp camlp4o.opt -o vivi.cmx vivi.ml ocamlopt.opt tata.cmx titi.cmx vivi.cmx tutu.cmx toto.cmx -o toto.native Warning: Using -- only run the last target toto.native: /home/danmey/src/ocaml-trunk/ocamlbuild/test/test2/_build/toto.native: Hello world!!! Tutu.tutu => 1 Tata.tata => "TATA2" [cache hit] ocamldep.opt -modules toto.ml > toto.ml.depends [cache hit] ocamldep.opt -modules tata.mli > tata.mli.depends [cache hit] ocamlc.opt -c -o tata.cmi tata.mli [cache hit] ocamldep.opt -modules titi.ml > titi.ml.depends [cache hit] ocamlc.opt -c -o titi.cmo titi.ml [cache hit] ocamldep.opt -modules tutu.mli > tutu.mli.depends [cache hit] ocamlc.opt -c -o tutu.cmi tutu.mli [cache hit] ocamlc.opt -c -o toto.cmo toto.ml [cache hit] ocamldep.opt -modules tata.ml > tata.ml.depends [cache hit] ocamlc.opt -c -o tata.cmo tata.ml [cache hit] ocamldep.opt -modules tutu.ml > tutu.ml.depends [cache hit] ocamldep.opt -modules tyty.mli > tyty.mli.depends [cache hit] ocamlc.opt -c -o tyty.cmi tyty.mli [cache hit] ocamldep.opt -pp camlp4o.opt -modules vivi.ml > vivi.ml.depends [cache hit] ocamlc.opt -c -pp camlp4o.opt -o vivi.cmo vivi.ml [cache hit] ocamlc.opt -c -o tutu.cmo tutu.ml [cache hit] ocamlc.opt tata.cmo titi.cmo vivi.cmo tutu.cmo toto.cmo -o toto.byte [cache hit] ocamlopt.opt -c -o tata.cmx tata.ml [cache hit] ocamlopt.opt -c -o titi.cmx titi.ml [cache hit] ocamlopt.opt -c -pp camlp4o.opt -o vivi.cmx vivi.ml [cache hit] ocamlopt.opt -c -o tutu.cmx tutu.ml [cache hit] ocamlopt.opt -c -o toto.cmx toto.ml [cache hit] ocamlopt.opt tata.cmx titi.cmx vivi.cmx tutu.cmx toto.cmx -o toto.native Warning: Using -- only run the last target toto.native: /home/danmey/src/ocaml-trunk/ocamlbuild/test/test2/_build/toto.native: Hello world!!! Tutu.tutu => 1 Tata.tata => "TATA2" ocamldep.opt -pp camlp4o.opt -modules vivi.ml > vivi.ml.depends ocamlc.opt -c -pp camlp4o.opt -o vivi.cmo vivi.ml ocamlc.opt -c -o tutu.cmo tutu.ml ocamlc.opt tata.cmo titi.cmo vivi.cmo tutu.cmo toto.cmo -o toto.byte ocamlopt.opt -c -pp camlp4o.opt -o vivi.cmx vivi.ml ocamlopt.opt -c -o tutu.cmx tutu.ml ocamlopt.opt -c -o toto.cmx toto.ml ocamlopt.opt tata.cmx titi.cmx vivi.cmx tutu.cmx toto.cmx -o toto.native Warning: Using -- only run the last target toto.native: /home/danmey/src/ocaml-trunk/ocamlbuild/test/test2/_build/toto.native: Hello world!!! Tutu.tutu => 2 Tata.tata => "TATA2" [cache hit] ocamldep.opt -modules toto.ml > toto.ml.depends [cache hit] ocamldep.opt -modules tata.mli > tata.mli.depends [cache hit] ocamlc.opt -c -o tata.cmi tata.mli [cache hit] ocamldep.opt -modules titi.ml > titi.ml.depends [cache hit] ocamlc.opt -c -o titi.cmo titi.ml [cache hit] ocamldep.opt -modules tutu.mli > tutu.mli.depends [cache hit] ocamlc.opt -c -o tutu.cmi tutu.mli [cache hit] ocamlc.opt -c -o toto.cmo toto.ml [cache hit] ocamldep.opt -modules tata.ml > tata.ml.depends [cache hit] ocamlc.opt -c -o tata.cmo tata.ml [cache hit] ocamldep.opt -modules tutu.ml > tutu.ml.depends [cache hit] ocamldep.opt -modules tyty.mli > tyty.mli.depends [cache hit] ocamlc.opt -c -o tyty.cmi tyty.mli [cache hit] ocamldep.opt -pp camlp4o.opt -modules vivi.ml > vivi.ml.depends [cache hit] ocamlc.opt -c -pp camlp4o.opt -o vivi.cmo vivi.ml [cache hit] ocamlc.opt -c -o tutu.cmo tutu.ml [cache hit] ocamlc.opt tata.cmo titi.cmo vivi.cmo tutu.cmo toto.cmo -o toto.byte [cache hit] ocamlopt.opt -c -o tata.cmx tata.ml [cache hit] ocamlopt.opt -c -o titi.cmx titi.ml [cache hit] ocamlopt.opt -c -pp camlp4o.opt -o vivi.cmx vivi.ml [cache hit] ocamlopt.opt -c -o tutu.cmx tutu.ml [cache hit] ocamlopt.opt -c -o toto.cmx toto.ml [cache hit] ocamlopt.opt tata.cmx titi.cmx vivi.cmx tutu.cmx toto.cmx -o toto.native Warning: Using -- only run the last target toto.native: /home/danmey/src/ocaml-trunk/ocamlbuild/test/test2/_build/toto.native: Hello world!!! Tutu.tutu => 2 Tata.tata => "TATA2" _____ _ _____ |_ _|__ ___| |_|___ / | |/ _ \/ __| __| |_ \ | | __/\__ \ |_ ___) | |_|\___||___/\__|____/ ocamldep.opt -modules a.mli > a.mli.depends ocamlc.opt -c -o a.cmi a.mli ocamldep.opt -modules a.ml > a.ml.depends ocamldep.opt -modules b.mli > b.mli.depends ocamlc.opt -c -o b.cmi b.mli ocamlc.opt -c -o a.cmo a.ml ocamldep.opt -modules b.ml > b.ml.depends ocamldep.opt -modules c.mli > c.mli.depends ocamlc.opt -c -o c.cmi c.mli ocamlc.opt -c -o b.cmo b.ml ocamldep.opt -modules c.ml > c.ml.depends ocamldep.opt -modules d.mli > d.mli.depends ocamlc.opt -c -o d.cmi d.mli ocamlc.opt -c -o c.cmo c.ml ocamldep.opt -modules d.ml > d.ml.depends ocamldep.opt -modules e.mli > e.mli.depends ocamlc.opt -c -o e.cmi e.mli ocamlc.opt -c -o d.cmo d.ml ocamldep.opt -modules e.ml > e.ml.depends ocamldep.opt -modules f.mli > f.mli.depends ocamlc.opt -c -o f.cmi f.mli ocamlc.opt -c -o e.cmo e.ml ocamldep.opt -modules f.ml > f.ml.depends ocamlc.opt -c -o f.cmo f.ml ocamlc.opt unix.cma f.cmo e.cmo d.cmo c.cmo b.cmo a.cmo -o a.byte ocamlopt.opt -c -o f.cmx f.ml ocamlopt.opt -c -o e.cmx e.ml ocamlopt.opt -c -o d.cmx d.ml ocamlopt.opt -c -o c.cmx c.ml ocamlopt.opt -c -o b.cmx b.ml ocamlopt.opt -c -o a.cmx a.ml ocamlopt.opt unix.cmxa f.cmx e.cmx d.cmx c.cmx b.cmx a.cmx -o a.native ocamldoc.opt -dump a.odoc a.mli ocamldoc.opt -dump b.odoc b.mli ocamldoc.opt -dump c.odoc c.mli ocamldoc.opt -dump d.odoc d.mli ocamldoc.opt -dump e.odoc e.mli ocamldoc.opt -dump f.odoc f.mli rm -rf proj.docdir mkdir -p proj.docdir ocamldoc.opt -load a.odoc -load b.odoc -load c.odoc -load d.odoc -load e.odoc -load f.odoc -html -d proj.docdir [cache hit] ocamldep.opt -modules a.mli > a.mli.depends [cache hit] ocamlc.opt -c -o a.cmi a.mli [cache hit] ocamldep.opt -modules a.ml > a.ml.depends [cache hit] ocamldep.opt -modules b.mli > b.mli.depends [cache hit] ocamlc.opt -c -o b.cmi b.mli [cache hit] ocamlc.opt -c -o a.cmo a.ml [cache hit] ocamldep.opt -modules b.ml > b.ml.depends [cache hit] ocamldep.opt -modules c.mli > c.mli.depends [cache hit] ocamlc.opt -c -o c.cmi c.mli [cache hit] ocamlc.opt -c -o b.cmo b.ml [cache hit] ocamldep.opt -modules c.ml > c.ml.depends [cache hit] ocamldep.opt -modules d.mli > d.mli.depends [cache hit] ocamlc.opt -c -o d.cmi d.mli [cache hit] ocamlc.opt -c -o c.cmo c.ml [cache hit] ocamldep.opt -modules d.ml > d.ml.depends [cache hit] ocamldep.opt -modules e.mli > e.mli.depends [cache hit] ocamlc.opt -c -o e.cmi e.mli [cache hit] ocamlc.opt -c -o d.cmo d.ml [cache hit] ocamldep.opt -modules e.ml > e.ml.depends [cache hit] ocamldep.opt -modules f.mli > f.mli.depends [cache hit] ocamlc.opt -c -o f.cmi f.mli [cache hit] ocamlc.opt -c -o e.cmo e.ml [cache hit] ocamldep.opt -modules f.ml > f.ml.depends [cache hit] ocamlc.opt -c -o f.cmo f.ml [cache hit] ocamlc.opt unix.cma f.cmo e.cmo d.cmo c.cmo b.cmo a.cmo -o a.byte [cache hit] ocamlopt.opt -c -o f.cmx f.ml [cache hit] ocamlopt.opt -c -o e.cmx e.ml [cache hit] ocamlopt.opt -c -o d.cmx d.ml [cache hit] ocamlopt.opt -c -o c.cmx c.ml [cache hit] ocamlopt.opt -c -o b.cmx b.ml [cache hit] ocamlopt.opt -c -o a.cmx a.ml [cache hit] ocamlopt.opt unix.cmxa f.cmx e.cmx d.cmx c.cmx b.cmx a.cmx -o a.native [cache hit] ocamldoc.opt -dump a.odoc a.mli [cache hit] ocamldoc.opt -dump b.odoc b.mli [cache hit] ocamldoc.opt -dump c.odoc c.mli [cache hit] ocamldoc.opt -dump d.odoc d.mli [cache hit] ocamldoc.opt -dump e.odoc e.mli [cache hit] ocamldoc.opt -dump f.odoc f.mli [cache hit] rm -rf proj.docdir [cache hit] mkdir -p proj.docdir [cache hit] ocamldoc.opt -load a.odoc -load b.odoc -load c.odoc -load d.odoc -load e.odoc -load f.odoc -html -d proj.docdir _____ _ _ _ |_ _|__ ___| |_| || | | |/ _ \/ __| __| || |_ | | __/\__ \ |_|__ _| |_|\___||___/\__| |_| aa.mli.depends aa.mli aa.ml.depends bb.ml.depends bb.ml aa.ml aa.byte bb.ml aa.ml aa.native [cache hit] aa.mli.depends [cache hit] aa.mli [cache hit] aa.ml.depends [cache hit] bb.ml.depends [cache hit] bb.ml [cache hit] aa.ml [cache hit] aa.byte [cache hit] bb.ml [cache hit] aa.ml [cache hit] aa.native _____ _ ____ |_ _|__ ___| |_| ___| | |/ _ \/ __| __|___ \ | | __/\__ \ |_ ___) | |_|\___||___/\__|____/ ocamldep.opt -modules d.ml > d.ml.depends ocamldep.opt -modules a.mli > a.mli.depends ocamlc.opt -c -o a.cmi a.mli ocamldep.opt -modules a.ml > a.ml.depends ocamldep.opt -modules stack.ml > stack.ml.depends ocamlc.opt -c -o stack.cmo stack.ml ocamldep.opt -modules b.ml > b.ml.depends ocamlc.opt -c -o a.cmo a.ml ocamlc.opt -c -o b.cmo b.ml ocamlc.opt -pack a.cmo b.cmo -o c.cmo ocamlc.opt -c -o d.cmo d.ml ocamlc.opt stack.cmo c.cmo d.cmo -o d.byte + /home/danmey/src/ocaml-trunk/bin/ocamlc.opt stack.cmo c.cmo d.cmo -o d.byte File "stack.cmo", line 1: Warning 31: files stack.cmo and /home/danmey/src/ocaml-trunk/lib/ocaml/stdlib.cma(Stack) both define a module named Stack ocamlopt.opt -c -o stack.cmx stack.ml ocamlopt.opt -c -for-pack C -o a.cmx a.ml ocamlopt.opt -c -for-pack C -o b.cmx b.ml ocamlopt.opt -pack a.cmx b.cmx -o c.cmx ; then rm -f c.mli ; else rm -f c.mli ; exit 1; fi ocamlopt.opt -c -o d.cmx d.ml ocamlopt.opt stack.cmx c.cmx d.cmx -o d.native [cache hit] ocamldep.opt -modules d.ml > d.ml.depends [cache hit] ocamldep.opt -modules a.mli > a.mli.depends [cache hit] ocamlc.opt -c -o a.cmi a.mli [cache hit] ocamldep.opt -modules a.ml > a.ml.depends [cache hit] ocamldep.opt -modules stack.ml > stack.ml.depends [cache hit] ocamlc.opt -c -o stack.cmo stack.ml [cache hit] ocamlc.opt -c -o a.cmo a.ml [cache hit] ocamldep.opt -modules b.ml > b.ml.depends [cache hit] ocamlc.opt -c -o b.cmo b.ml [cache hit] ocamlc.opt -pack a.cmo b.cmo -o c.cmo [cache hit] ocamlc.opt -c -o d.cmo d.ml [cache hit] ocamlc.opt stack.cmo c.cmo d.cmo -o d.byte [cache hit] ocamlopt.opt -c -o stack.cmx stack.ml [cache hit] ocamlopt.opt -c -for-pack C -o a.cmx a.ml [cache hit] ocamlopt.opt -c -for-pack C -o b.cmx b.ml [cache hit] ocamlopt.opt -pack a.cmx b.cmx -o c.cmx ; then rm -f c.mli ; else rm -f c.mli ; exit 1; fi [cache hit] ocamlopt.opt -c -o d.cmx d.ml [cache hit] ocamlopt.opt stack.cmx c.cmx d.cmx -o d.native _____ _ __ |_ _|__ ___| |_ / /_ | |/ _ \/ __| __| '_ \ | | __/\__ \ |_| (_) | |_|\___||___/\__|\___/ ocamldep.opt -modules main.mli > main.mli.depends ocamlc.opt -c -o main.cmi main.mli ocamldep.opt -modules main.ml > main.ml.depends ocamldep.opt -modules a.mli > a.mli.depends ocamldep.opt -modules d.mli > d.mli.depends ocamlc.opt -c -o a.cmi a.mli ocamlc.opt -c -o d.cmi d.mli ocamlc.opt -c -o main.cmo main.ml ocamldep.opt -modules a.ml > a.ml.depends ocamldep.opt -modules b.mli > b.mli.depends ocamlc.opt -c -o b.cmi b.mli ocamldep.opt -modules d.ml > d.ml.depends ocamlc.opt -c -o a.cmo a.ml ocamlc.opt -c -o d.cmo d.ml ocamldep.opt -modules b.ml > b.ml.depends ocamlc.opt -c -o b.cmo b.ml ocamlc.opt d.cmo b.cmo a.cmo main.cmo -o main.byte [cache hit] ocamldep.opt -modules main.mli > main.mli.depends [cache hit] ocamlc.opt -c -o main.cmi main.mli [cache hit] ocamldep.opt -modules main.ml > main.ml.depends [cache hit] ocamldep.opt -modules a.mli > a.mli.depends [cache hit] ocamlc.opt -c -o a.cmi a.mli [cache hit] ocamldep.opt -modules d.mli > d.mli.depends [cache hit] ocamlc.opt -c -o d.cmi d.mli [cache hit] ocamlc.opt -c -o main.cmo main.ml [cache hit] ocamldep.opt -modules a.ml > a.ml.depends [cache hit] ocamldep.opt -modules b.mli > b.mli.depends [cache hit] ocamlc.opt -c -o b.cmi b.mli [cache hit] ocamlc.opt -c -o a.cmo a.ml [cache hit] ocamldep.opt -modules d.ml > d.ml.depends [cache hit] ocamlc.opt -c -o d.cmo d.ml [cache hit] ocamldep.opt -modules b.ml > b.ml.depends [cache hit] ocamlc.opt -c -o b.cmo b.ml [cache hit] ocamlc.opt d.cmo b.cmo a.cmo main.cmo -o main.byte ocamldep.opt -modules d.mli > d.mli.depends ocamlc.opt -c -o d.cmi d.mli ocamlc.opt -c -o main.cmo main.ml ocamldep.opt -modules b.mli > b.mli.depends + /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules b.mli > b.mli.depends File "b.mli", line 13, characters 0-2: Error: Syntax error Command exited with code 2. ocamldep.opt -modules b.mli > b.mli.depends ocamlc.opt -c -o b.cmi b.mli ocamlc.opt -c -o d.cmo d.ml ocamlc.opt -c -o b.cmo b.ml ocamlc.opt d.cmo b.cmo a.cmo main.cmo -o main.byte [cache hit] ocamldep.opt -modules main.mli > main.mli.depends [cache hit] ocamlc.opt -c -o main.cmi main.mli [cache hit] ocamldep.opt -modules main.ml > main.ml.depends [cache hit] ocamldep.opt -modules a.mli > a.mli.depends [cache hit] ocamlc.opt -c -o a.cmi a.mli [cache hit] ocamldep.opt -modules d.mli > d.mli.depends [cache hit] ocamlc.opt -c -o d.cmi d.mli [cache hit] ocamlc.opt -c -o main.cmo main.ml [cache hit] ocamldep.opt -modules a.ml > a.ml.depends [cache hit] ocamldep.opt -modules b.mli > b.mli.depends [cache hit] ocamlc.opt -c -o b.cmi b.mli [cache hit] ocamlc.opt -c -o a.cmo a.ml [cache hit] ocamldep.opt -modules d.ml > d.ml.depends [cache hit] ocamlc.opt -c -o d.cmo d.ml [cache hit] ocamldep.opt -modules b.ml > b.ml.depends [cache hit] ocamlc.opt -c -o b.cmo b.ml [cache hit] ocamlc.opt d.cmo b.cmo a.cmo main.cmo -o main.byte PASS _____ _ _____ |_ _|__ ___| ||___ | | |/ _ \/ __| __| / / | | __/\__ \ |_ / / |_|\___||___/\__/_/ ocamlbuild.cmx -o myocamlbuild /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.mli > bb.mli.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmi bb.mli /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.ml > bb.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cc.ml > cc.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules aa.ml > aa.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.mli > c2.mli.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o aa.cmo aa.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmi c2.mli /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmo bb.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cc.cmo cc.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a bb.cmo cc.cmo -o bbcc.cma /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules main.ml > main.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c3.ml > c3.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c3.cmo c3.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o main.cmo main.ml /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cool_plugin.ml > cool_plugin.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cool_plugin.cmo cool_plugin.ml /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.ml > c2.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmo c2.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt aa.cmo c2.cmo bbcc.cma c3.cmo main.cmo cool_plugin.cmo -o main.byte /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o bb.cmx bb.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o aa.cmx aa.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c2.cmx c2.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o cc.cmx cc.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a bb.cmx cc.cmx -o bbcc.cmxa /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c3.cmx c3.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o main.cmx main.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt aa.cmx c2.cmx bbcc.cmxa c3.cmx main.cmx -o main.native [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.mli > bb.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmi bb.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.ml > bb.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmo bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cc.ml > cc.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules aa.ml > aa.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o aa.cmo aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.mli > c2.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmi c2.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cc.cmo cc.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a bb.cmo cc.cmo -o bbcc.cma [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules main.ml > main.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c3.ml > c3.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c3.cmo c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o main.cmo main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cool_plugin.ml > cool_plugin.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cool_plugin.cmo cool_plugin.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.ml > c2.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmo c2.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt aa.cmo c2.cmo bbcc.cma c3.cmo main.cmo cool_plugin.cmo -o main.byte [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o bb.cmx bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o aa.cmx aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c2.cmx c2.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o cc.cmx cc.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a bb.cmx cc.cmx -o bbcc.cmxa [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c3.cmx c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o main.cmx main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt aa.cmx c2.cmx bbcc.cmxa c3.cmx main.cmx -o main.native [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.mli > bb.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmi bb.mli /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.ml > bb.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cc.ml > cc.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules aa.ml > aa.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o aa.cmo aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.mli > c2.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmi c2.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cc.cmo cc.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmo bb.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a bb.cmo cc.cmo -o bbcc.cma [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules main.ml > main.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c3.ml > c3.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c3.cmo c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o main.cmo main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cool_plugin.ml > cool_plugin.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cool_plugin.cmo cool_plugin.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.ml > c2.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmo c2.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt aa.cmo c2.cmo bbcc.cma c3.cmo main.cmo cool_plugin.cmo -o main.byte [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o aa.cmx aa.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o bb.cmx bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c2.cmx c2.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o cc.cmx cc.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a bb.cmx cc.cmx -o bbcc.cmxa /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c3.cmx c3.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o main.cmx main.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt aa.cmx c2.cmx bbcc.cmxa c3.cmx main.cmx -o main.native [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.mli > bb.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmi bb.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.ml > bb.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmo bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cc.ml > cc.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules aa.ml > aa.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o aa.cmo aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.mli > c2.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmi c2.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cc.cmo cc.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a bb.cmo cc.cmo -o bbcc.cma [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules main.ml > main.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c3.ml > c3.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c3.cmo c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o main.cmo main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cool_plugin.ml > cool_plugin.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cool_plugin.cmo cool_plugin.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.ml > c2.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmo c2.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt aa.cmo c2.cmo bbcc.cma c3.cmo main.cmo cool_plugin.cmo -o main.byte [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o bb.cmx bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o aa.cmx aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c2.cmx c2.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o cc.cmx cc.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a bb.cmx cc.cmx -o bbcc.cmxa [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c3.cmx c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o main.cmx main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt aa.cmx c2.cmx bbcc.cmxa c3.cmx main.cmx -o main.native [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.mli > bb.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmi bb.mli /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.ml > bb.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cc.ml > cc.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules aa.ml > aa.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o aa.cmo aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.mli > c2.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmi c2.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cc.cmo cc.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmo bb.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a bb.cmo cc.cmo -o bbcc.cma [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules main.ml > main.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c3.ml > c3.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c3.cmo c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o main.cmo main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cool_plugin.ml > cool_plugin.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cool_plugin.cmo cool_plugin.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.ml > c2.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmo c2.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt aa.cmo c2.cmo bbcc.cma c3.cmo main.cmo cool_plugin.cmo -o main.byte [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o aa.cmx aa.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o bb.cmx bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c2.cmx c2.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o cc.cmx cc.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a bb.cmx cc.cmx -o bbcc.cmxa [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c3.cmx c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o main.cmx main.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt aa.cmx c2.cmx bbcc.cmxa c3.cmx main.cmx -o main.native [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.mli > bb.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmi bb.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules bb.ml > bb.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o bb.cmo bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cc.ml > cc.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules aa.ml > aa.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o aa.cmo aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.mli > c2.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmi c2.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cc.cmo cc.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a bb.cmo cc.cmo -o bbcc.cma [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules main.ml > main.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c3.ml > c3.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c3.cmo c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o main.cmo main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules cool_plugin.ml > cool_plugin.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o cool_plugin.cmo cool_plugin.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules c2.ml > c2.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o c2.cmo c2.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt aa.cmo c2.cmo bbcc.cma c3.cmo main.cmo cool_plugin.cmo -o main.byte [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o bb.cmx bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o aa.cmx aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c2.cmx c2.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o cc.cmx cc.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a bb.cmx cc.cmx -o bbcc.cmxa [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o c3.cmx c3.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o main.cmx main.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt aa.cmx c2.cmx bbcc.cmxa c3.cmx main.cmx -o main.native _____ _ ___ |_ _|__ ___| |_( _ ) | |/ _ \/ __| __/ _ \ | | __/\__ \ || (_) | |_|\___||___/\__\___/ ocamlbuild.cmx -o myocamlbuild /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules a.ml > a.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules myconfig.ml > myconfig.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o myconfig.cmo myconfig.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o a.cmo a.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt myconfig.cmo a.cmo -o a.byte /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o myconfig.cmx myconfig.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o a.cmx a.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt myconfig.cmx a.cmx -o a.native cp -p a.byte a cp -p a.native a.opt cp -p a.byte bin/a.byte cp -p bin/a.byte bin/a cp -p a.native bin/a.native cp -p bin/a.native bin/a.opt [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules a.ml > a.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules myconfig.ml > myconfig.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o myconfig.cmo myconfig.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -o a.cmo a.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt myconfig.cmo a.cmo -o a.byte [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o myconfig.cmx myconfig.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -o a.cmx a.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt myconfig.cmx a.cmx -o a.native [cache hit] cp -p a.byte a [cache hit] cp -p a.native a.opt [cache hit] cp -p a.byte bin/a.byte [cache hit] cp -p bin/a.byte bin/a [cache hit] cp -p a.native bin/a.native [cache hit] cp -p bin/a.native bin/a.opt _____ _ ___ |_ _|__ ___| |_ / _ \ | |/ _ \/ __| __| (_) | | | __/\__ \ |_ \__, | |_|\___||___/\__| /_/ Globexp for "\"hello\"" OK Globexp for "" OK Globexp for "" OK Globexp for " and or " OK Globexp for " titi" OK Glob.eval "<[a]>" "a" = true OK Glob.eval "<[a]>" "b" = false OK Glob.eval "<[a]>" "a" = true OK Glob.eval "<[a]>" "b" = false OK Glob.eval "<[a]>" "a" = true OK Glob.eval "<[a]>" "b" = false OK Glob.eval "<[a-z]>" "a" = true OK Glob.eval "<[a-z]>" "e" = true OK Glob.eval "<[a-z]>" "k" = true OK Glob.eval "<[a-z]>" "z" = true OK Glob.eval "<[a-z]>" "0" = false OK Glob.eval "<[a-z]>" "A" = false OK Glob.eval "<[a-z]>" "~" = false OK Glob.eval "<[a-z]>" "a" = true OK Glob.eval "<[a-z]>" "e" = true OK Glob.eval "<[a-z]>" "k" = true OK Glob.eval "<[a-z]>" "z" = true OK Glob.eval "<[a-z]>" "0" = false OK Glob.eval "<[a-z]>" "A" = false OK Glob.eval "<[a-z]>" "~" = false OK Glob.eval "<[a-z]>" "a" = true OK Glob.eval "<[a-z]>" "e" = true OK Glob.eval "<[a-z]>" "k" = true OK Glob.eval "<[a-z]>" "z" = true OK Glob.eval "<[a-z]>" "0" = false OK Glob.eval "<[a-z]>" "A" = false OK Glob.eval "<[a-z]>" "~" = false OK Glob.eval "<[a-z][0-9]>" "a0" = true OK Glob.eval "<[a-z][0-9]>" "b9" = true OK Glob.eval "<[a-z][0-9]>" "a00" = false OK Glob.eval "<[a-z][0-9]>" "a0a" = false OK Glob.eval "<[a-z][0-9]>" "b0a" = false OK Glob.eval "<[a-z][0-9]>" "isduis" = false OK Glob.eval "<[a-z][0-9]>" "" = false OK Glob.eval "<[a-z][0-9]>" "a0" = true OK Glob.eval "<[a-z][0-9]>" "b9" = true OK Glob.eval "<[a-z][0-9]>" "a00" = false OK Glob.eval "<[a-z][0-9]>" "a0a" = false OK Glob.eval "<[a-z][0-9]>" "b0a" = false OK Glob.eval "<[a-z][0-9]>" "isduis" = false OK Glob.eval "<[a-z][0-9]>" "" = false OK Glob.eval "<[a-z][0-9]>" "a0" = true OK Glob.eval "<[a-z][0-9]>" "b9" = true OK Glob.eval "<[a-z][0-9]>" "a00" = false OK Glob.eval "<[a-z][0-9]>" "a0a" = false OK Glob.eval "<[a-z][0-9]>" "b0a" = false OK Glob.eval "<[a-z][0-9]>" "isduis" = false OK Glob.eval "<[a-z][0-9]>" "" = false OK Glob.eval "" "hello" = true OK Glob.eval "" "helli" = false OK Glob.eval "" "hello" = true OK Glob.eval "" "helli" = false OK Glob.eval "" "hello" = true OK Glob.eval "" "helli" = false OK Glob.eval "\"hello\"" "hello" = true OK Glob.eval "\"hello\"" "heidi" = false OK Glob.eval "\"hello\"" "hello" = true OK Glob.eval "\"hello\"" "heidi" = false OK Glob.eval "\"hello\"" "hello" = true OK Glob.eval "\"hello\"" "heidi" = false OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "ax" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "ax" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "ax" = true OK Glob.eval "" "ab" = true OK Glob.eval "" "acb" = true OK Glob.eval "" "axxxxxb" = true OK Glob.eval "" "ababbababb" = true OK Glob.eval "" "abx" = false OK Glob.eval "" "xxxxxab" = false OK Glob.eval "" "xab" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "acb" = true OK Glob.eval "" "axxxxxb" = true OK Glob.eval "" "ababbababb" = true OK Glob.eval "" "abx" = false OK Glob.eval "" "xxxxxab" = false OK Glob.eval "" "xab" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "acb" = true OK Glob.eval "" "axxxxxb" = true OK Glob.eval "" "ababbababb" = true OK Glob.eval "" "abx" = false OK Glob.eval "" "xxxxxab" = false OK Glob.eval "" "xab" = false OK Glob.eval "<*.ml>" "hello.ml" = true OK Glob.eval "<*.ml>" ".ml" = true OK Glob.eval "<*.ml>" "ml" = false OK Glob.eval "<*.ml>" "" = false OK Glob.eval "<*.ml>" "toto.mli" = false OK Glob.eval "<*.ml>" "hello.ml" = true OK Glob.eval "<*.ml>" ".ml" = true OK Glob.eval "<*.ml>" "ml" = false OK Glob.eval "<*.ml>" "" = false OK Glob.eval "<*.ml>" "toto.mli" = false OK Glob.eval "<*.ml>" "hello.ml" = true OK Glob.eval "<*.ml>" ".ml" = true OK Glob.eval "<*.ml>" "ml" = false OK Glob.eval "<*.ml>" "" = false OK Glob.eval "<*.ml>" "toto.mli" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aa" = false OK Glob.eval "" "ba" = false OK Glob.eval "" "ab" = false OK Glob.eval "" "abaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aa" = false OK Glob.eval "" "ba" = false OK Glob.eval "" "ab" = false OK Glob.eval "" "abaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aa" = false OK Glob.eval "" "ba" = false OK Glob.eval "" "ab" = false OK Glob.eval "" "abaa" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "" = false OK Glob.eval "" "abab" = false OK Glob.eval "" "aba" = false OK Glob.eval "" "abx" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "" = false OK Glob.eval "" "abab" = false OK Glob.eval "" "aba" = false OK Glob.eval "" "abx" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "" = false OK Glob.eval "" "abab" = false OK Glob.eval "" "aba" = false OK Glob.eval "" "abx" = false OK Glob.eval "" "abac" = true OK Glob.eval "" "abxc" = true OK Glob.eval "" "abab" = false OK Glob.eval "" "ababab" = false OK Glob.eval "" "ababa" = false OK Glob.eval "" "abac" = true OK Glob.eval "" "abxc" = true OK Glob.eval "" "abab" = false OK Glob.eval "" "ababab" = false OK Glob.eval "" "ababa" = false OK Glob.eval "" "abac" = true OK Glob.eval "" "abxc" = true OK Glob.eval "" "abab" = false OK Glob.eval "" "ababab" = false OK Glob.eval "" "ababa" = false OK Glob.eval "<*ab?cd*>" "123abecd345" = true OK Glob.eval "<*ab?cd*>" "abccd" = true OK Glob.eval "<*ab?cd*>" "abccd345" = true OK Glob.eval "<*ab?cd*>" "ababcababccdab" = true OK Glob.eval "<*ab?cd*>" "abcd" = false OK Glob.eval "<*ab?cd*>" "aaaaabcdababcd" = false OK Glob.eval "<*ab?cd*>" "123abecd345" = true OK Glob.eval "<*ab?cd*>" "abccd" = true OK Glob.eval "<*ab?cd*>" "abccd345" = true OK Glob.eval "<*ab?cd*>" "ababcababccdab" = true OK Glob.eval "<*ab?cd*>" "abcd" = false OK Glob.eval "<*ab?cd*>" "aaaaabcdababcd" = false OK Glob.eval "<*ab?cd*>" "123abecd345" = true OK Glob.eval "<*ab?cd*>" "abccd" = true OK Glob.eval "<*ab?cd*>" "abccd345" = true OK Glob.eval "<*ab?cd*>" "ababcababccdab" = true OK Glob.eval "<*ab?cd*>" "abcd" = false OK Glob.eval "<*ab?cd*>" "aaaaabcdababcd" = false OK Glob.eval "<*this*is*a*test*>" "this is a test" = true OK Glob.eval "<*this*is*a*test*>" "You know this is a test really" = true OK Glob.eval "<*this*is*a*test*>" "thisisatest" = true OK Glob.eval "<*this*is*a*test*>" "thisatest" = false OK Glob.eval "<*this*is*a*test*>" "this is a test" = true OK Glob.eval "<*this*is*a*test*>" "You know this is a test really" = true OK Glob.eval "<*this*is*a*test*>" "thisisatest" = true OK Glob.eval "<*this*is*a*test*>" "thisatest" = false OK Glob.eval "<*this*is*a*test*>" "this is a test" = true OK Glob.eval "<*this*is*a*test*>" "You know this is a test really" = true OK Glob.eval "<*this*is*a*test*>" "thisisatest" = true OK Glob.eval "<*this*is*a*test*>" "thisatest" = false OK Glob.eval "" "bxx" = true OK Glob.eval "" "bx" = true OK Glob.eval "" "aaab" = false OK Glob.eval "" "" = false OK Glob.eval "" "bxx" = true OK Glob.eval "" "bx" = true OK Glob.eval "" "aaab" = false OK Glob.eval "" "" = false OK Glob.eval "" "bxx" = true OK Glob.eval "" "bx" = true OK Glob.eval "" "aaab" = false OK Glob.eval "" "" = false OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "aaa" = true OK Glob.eval "<*>" "aaaaa" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "aaa" = true OK Glob.eval "<*>" "aaaaa" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "aaa" = true OK Glob.eval "<*>" "aaaaa" = true OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aaa" = false OK Glob.eval "" "aaaaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aaa" = false OK Glob.eval "" "aaaaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aaa" = false OK Glob.eval "" "aaaaa" = false OK Glob.eval "<{a,b}>" "a" = true OK Glob.eval "<{a,b}>" "b" = true OK Glob.eval "<{a,b}>" "" = false OK Glob.eval "<{a,b}>" "aa" = false OK Glob.eval "<{a,b}>" "ab" = false OK Glob.eval "<{a,b}>" "ba" = false OK Glob.eval "<{a,b}>" "bb" = false OK Glob.eval "<{a,b}>" "c" = false OK Glob.eval "<{a,b}>" "a" = true OK Glob.eval "<{a,b}>" "b" = true OK Glob.eval "<{a,b}>" "" = false OK Glob.eval "<{a,b}>" "aa" = false OK Glob.eval "<{a,b}>" "ab" = false OK Glob.eval "<{a,b}>" "ba" = false OK Glob.eval "<{a,b}>" "bb" = false OK Glob.eval "<{a,b}>" "c" = false OK Glob.eval "<{a,b}>" "a" = true OK Glob.eval "<{a,b}>" "b" = true OK Glob.eval "<{a,b}>" "" = false OK Glob.eval "<{a,b}>" "aa" = false OK Glob.eval "<{a,b}>" "ab" = false OK Glob.eval "<{a,b}>" "ba" = false OK Glob.eval "<{a,b}>" "bb" = false OK Glob.eval "<{a,b}>" "c" = false OK Glob.eval "" "toto.ml" = true OK Glob.eval "" "toto.mli" = true OK Glob.eval "" "toto." = false OK Glob.eval "" "toto.mll" = false OK Glob.eval "" "toto.ml" = true OK Glob.eval "" "toto.mli" = true OK Glob.eval "" "toto." = false OK Glob.eval "" "toto.mll" = false OK Glob.eval "" "toto.ml" = true OK Glob.eval "" "toto.mli" = true OK Glob.eval "" "toto." = false OK Glob.eval "" "toto.mll" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aeg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "beg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "afg" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "af" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aee" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aeg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "beg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "afg" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "af" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aee" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aeg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "beg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "afg" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "af" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aee" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "b.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "hello.ml" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli.x" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "b.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "hello.ml" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli.x" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "b.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "hello.ml" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli.x" = false OK Glob.eval "<*>" "alpha" = true OK Glob.eval "<*>" "beta" = true OK Glob.eval "<*>" "alpha/beta" = false OK Glob.eval "<*>" "gamma/delta" = false OK Glob.eval "<*>" "alpha" = true OK Glob.eval "<*>" "beta" = true OK Glob.eval "<*>" "alpha/beta" = false OK Glob.eval "<*>" "gamma/delta" = false OK Glob.eval "<*>" "alpha" = true OK Glob.eval "<*>" "beta" = true OK Glob.eval "<*>" "alpha/beta" = false OK Glob.eval "<*>" "gamma/delta" = false OK Glob.eval "" "alpha/beta" = true OK Glob.eval "" "alpha/gamma/beta" = true OK Glob.eval "" "alpha/gamma/delta/beta" = true OK Glob.eval "" "alpha" = false OK Glob.eval "" "beta" = false OK Glob.eval "" "gamma/delta" = false OK Glob.eval "" "alpha/beta" = true OK Glob.eval "" "alpha/gamma/beta" = true OK Glob.eval "" "alpha/gamma/delta/beta" = true OK Glob.eval "" "alpha" = false OK Glob.eval "" "beta" = false OK Glob.eval "" "gamma/delta" = false OK Glob.eval "" "alpha/beta" = true OK Glob.eval "" "alpha/gamma/beta" = true OK Glob.eval "" "alpha/gamma/delta/beta" = true OK Glob.eval "" "alpha" = false OK Glob.eval "" "beta" = false OK Glob.eval "" "gamma/delta" = false OK Glob.eval "<**/*.ml>" "toto.ml" = true OK Glob.eval "<**/*.ml>" "toto/tata.ml" = true OK Glob.eval "<**/*.ml>" "alpha/gamma/delta/beta.ml" = true OK Glob.eval "<**/*.ml>" "toto.mli" = false OK Glob.eval "<**/*.ml>" "toto.ml" = true OK Glob.eval "<**/*.ml>" "toto/tata.ml" = true OK Glob.eval "<**/*.ml>" "alpha/gamma/delta/beta.ml" = true OK Glob.eval "<**/*.ml>" "toto.mli" = false OK Glob.eval "<**/*.ml>" "toto.ml" = true OK Glob.eval "<**/*.ml>" "toto/tata.ml" = true OK Glob.eval "<**/*.ml>" "alpha/gamma/delta/beta.ml" = true OK Glob.eval "<**/*.ml>" "toto.mli" = false OK Glob.eval "" "toto/" = true OK Glob.eval "" "toto/tata" = true OK Glob.eval "" "toto/alpha/gamma/delta/beta.ml" = true OK Glob.eval "" "toto" = true OK Glob.eval "" "toto2/tata" = false OK Glob.eval "" "tata/titi" = false OK Glob.eval "" "toto/" = true OK Glob.eval "" "toto/tata" = true OK Glob.eval "" "toto/alpha/gamma/delta/beta.ml" = true OK Glob.eval "" "toto" = true OK Glob.eval "" "toto2/tata" = false OK Glob.eval "" "tata/titi" = false OK Glob.eval "" "toto/" = true OK Glob.eval "" "toto/tata" = true OK Glob.eval "" "toto/alpha/gamma/delta/beta.ml" = true OK Glob.eval "" "toto" = true OK Glob.eval "" "toto2/tata" = false OK Glob.eval "" "tata/titi" = false OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/bar/libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibs/unix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibsliblib/unlibix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/libfoo/boo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "bar" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libbar/foo.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.b.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/bar/libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibs/unix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibsliblib/unlibix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/libfoo/boo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "bar" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libbar/foo.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.b.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/bar/libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibs/unix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibsliblib/unlibix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/libfoo/boo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "bar" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libbar/foo.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.b.a" = None OK _____ _ _ ___ |_ _|__ ___| |_/ |/ _ \ | |/ _ \/ __| __| | | | | | | __/\__ \ |_| | |_| | |_|\___||___/\__|_|\___/ Globexp for "\"hello\"" OK Globexp for "" OK Globexp for "" OK Globexp for " and or " OK Globexp for " titi" OK Glob.eval "<[a]>" "a" = true OK Glob.eval "<[a]>" "b" = false OK Glob.eval "<[a]>" "a" = true OK Glob.eval "<[a]>" "b" = false OK Glob.eval "<[a]>" "a" = true OK Glob.eval "<[a]>" "b" = false OK Glob.eval "<[a-z]>" "a" = true OK Glob.eval "<[a-z]>" "e" = true OK Glob.eval "<[a-z]>" "k" = true OK Glob.eval "<[a-z]>" "z" = true OK Glob.eval "<[a-z]>" "0" = false OK Glob.eval "<[a-z]>" "A" = false OK Glob.eval "<[a-z]>" "~" = false OK Glob.eval "<[a-z]>" "a" = true OK Glob.eval "<[a-z]>" "e" = true OK Glob.eval "<[a-z]>" "k" = true OK Glob.eval "<[a-z]>" "z" = true OK Glob.eval "<[a-z]>" "0" = false OK Glob.eval "<[a-z]>" "A" = false OK Glob.eval "<[a-z]>" "~" = false OK Glob.eval "<[a-z]>" "a" = true OK Glob.eval "<[a-z]>" "e" = true OK Glob.eval "<[a-z]>" "k" = true OK Glob.eval "<[a-z]>" "z" = true OK Glob.eval "<[a-z]>" "0" = false OK Glob.eval "<[a-z]>" "A" = false OK Glob.eval "<[a-z]>" "~" = false OK Glob.eval "<[a-z][0-9]>" "a0" = true OK Glob.eval "<[a-z][0-9]>" "b9" = true OK Glob.eval "<[a-z][0-9]>" "a00" = false OK Glob.eval "<[a-z][0-9]>" "a0a" = false OK Glob.eval "<[a-z][0-9]>" "b0a" = false OK Glob.eval "<[a-z][0-9]>" "isduis" = false OK Glob.eval "<[a-z][0-9]>" "" = false OK Glob.eval "<[a-z][0-9]>" "a0" = true OK Glob.eval "<[a-z][0-9]>" "b9" = true OK Glob.eval "<[a-z][0-9]>" "a00" = false OK Glob.eval "<[a-z][0-9]>" "a0a" = false OK Glob.eval "<[a-z][0-9]>" "b0a" = false OK Glob.eval "<[a-z][0-9]>" "isduis" = false OK Glob.eval "<[a-z][0-9]>" "" = false OK Glob.eval "<[a-z][0-9]>" "a0" = true OK Glob.eval "<[a-z][0-9]>" "b9" = true OK Glob.eval "<[a-z][0-9]>" "a00" = false OK Glob.eval "<[a-z][0-9]>" "a0a" = false OK Glob.eval "<[a-z][0-9]>" "b0a" = false OK Glob.eval "<[a-z][0-9]>" "isduis" = false OK Glob.eval "<[a-z][0-9]>" "" = false OK Glob.eval "" "hello" = true OK Glob.eval "" "helli" = false OK Glob.eval "" "hello" = true OK Glob.eval "" "helli" = false OK Glob.eval "" "hello" = true OK Glob.eval "" "helli" = false OK Glob.eval "\"hello\"" "hello" = true OK Glob.eval "\"hello\"" "heidi" = false OK Glob.eval "\"hello\"" "hello" = true OK Glob.eval "\"hello\"" "heidi" = false OK Glob.eval "\"hello\"" "hello" = true OK Glob.eval "\"hello\"" "heidi" = false OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "ax" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "ax" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "ax" = true OK Glob.eval "" "ab" = true OK Glob.eval "" "acb" = true OK Glob.eval "" "axxxxxb" = true OK Glob.eval "" "ababbababb" = true OK Glob.eval "" "abx" = false OK Glob.eval "" "xxxxxab" = false OK Glob.eval "" "xab" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "acb" = true OK Glob.eval "" "axxxxxb" = true OK Glob.eval "" "ababbababb" = true OK Glob.eval "" "abx" = false OK Glob.eval "" "xxxxxab" = false OK Glob.eval "" "xab" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "acb" = true OK Glob.eval "" "axxxxxb" = true OK Glob.eval "" "ababbababb" = true OK Glob.eval "" "abx" = false OK Glob.eval "" "xxxxxab" = false OK Glob.eval "" "xab" = false OK Glob.eval "<*.ml>" "hello.ml" = true OK Glob.eval "<*.ml>" ".ml" = true OK Glob.eval "<*.ml>" "ml" = false OK Glob.eval "<*.ml>" "" = false OK Glob.eval "<*.ml>" "toto.mli" = false OK Glob.eval "<*.ml>" "hello.ml" = true OK Glob.eval "<*.ml>" ".ml" = true OK Glob.eval "<*.ml>" "ml" = false OK Glob.eval "<*.ml>" "" = false OK Glob.eval "<*.ml>" "toto.mli" = false OK Glob.eval "<*.ml>" "hello.ml" = true OK Glob.eval "<*.ml>" ".ml" = true OK Glob.eval "<*.ml>" "ml" = false OK Glob.eval "<*.ml>" "" = false OK Glob.eval "<*.ml>" "toto.mli" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aa" = false OK Glob.eval "" "ba" = false OK Glob.eval "" "ab" = false OK Glob.eval "" "abaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aa" = false OK Glob.eval "" "ba" = false OK Glob.eval "" "ab" = false OK Glob.eval "" "abaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aa" = false OK Glob.eval "" "ba" = false OK Glob.eval "" "ab" = false OK Glob.eval "" "abaa" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "" = false OK Glob.eval "" "abab" = false OK Glob.eval "" "aba" = false OK Glob.eval "" "abx" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "" = false OK Glob.eval "" "abab" = false OK Glob.eval "" "aba" = false OK Glob.eval "" "abx" = false OK Glob.eval "" "ab" = true OK Glob.eval "" "" = false OK Glob.eval "" "abab" = false OK Glob.eval "" "aba" = false OK Glob.eval "" "abx" = false OK Glob.eval "" "abac" = true OK Glob.eval "" "abxc" = true OK Glob.eval "" "abab" = false OK Glob.eval "" "ababab" = false OK Glob.eval "" "ababa" = false OK Glob.eval "" "abac" = true OK Glob.eval "" "abxc" = true OK Glob.eval "" "abab" = false OK Glob.eval "" "ababab" = false OK Glob.eval "" "ababa" = false OK Glob.eval "" "abac" = true OK Glob.eval "" "abxc" = true OK Glob.eval "" "abab" = false OK Glob.eval "" "ababab" = false OK Glob.eval "" "ababa" = false OK Glob.eval "<*ab?cd*>" "123abecd345" = true OK Glob.eval "<*ab?cd*>" "abccd" = true OK Glob.eval "<*ab?cd*>" "abccd345" = true OK Glob.eval "<*ab?cd*>" "ababcababccdab" = true OK Glob.eval "<*ab?cd*>" "abcd" = false OK Glob.eval "<*ab?cd*>" "aaaaabcdababcd" = false OK Glob.eval "<*ab?cd*>" "123abecd345" = true OK Glob.eval "<*ab?cd*>" "abccd" = true OK Glob.eval "<*ab?cd*>" "abccd345" = true OK Glob.eval "<*ab?cd*>" "ababcababccdab" = true OK Glob.eval "<*ab?cd*>" "abcd" = false OK Glob.eval "<*ab?cd*>" "aaaaabcdababcd" = false OK Glob.eval "<*ab?cd*>" "123abecd345" = true OK Glob.eval "<*ab?cd*>" "abccd" = true OK Glob.eval "<*ab?cd*>" "abccd345" = true OK Glob.eval "<*ab?cd*>" "ababcababccdab" = true OK Glob.eval "<*ab?cd*>" "abcd" = false OK Glob.eval "<*ab?cd*>" "aaaaabcdababcd" = false OK Glob.eval "<*this*is*a*test*>" "this is a test" = true OK Glob.eval "<*this*is*a*test*>" "You know this is a test really" = true OK Glob.eval "<*this*is*a*test*>" "thisisatest" = true OK Glob.eval "<*this*is*a*test*>" "thisatest" = false OK Glob.eval "<*this*is*a*test*>" "this is a test" = true OK Glob.eval "<*this*is*a*test*>" "You know this is a test really" = true OK Glob.eval "<*this*is*a*test*>" "thisisatest" = true OK Glob.eval "<*this*is*a*test*>" "thisatest" = false OK Glob.eval "<*this*is*a*test*>" "this is a test" = true OK Glob.eval "<*this*is*a*test*>" "You know this is a test really" = true OK Glob.eval "<*this*is*a*test*>" "thisisatest" = true OK Glob.eval "<*this*is*a*test*>" "thisatest" = false OK Glob.eval "" "bxx" = true OK Glob.eval "" "bx" = true OK Glob.eval "" "aaab" = false OK Glob.eval "" "" = false OK Glob.eval "" "bxx" = true OK Glob.eval "" "bx" = true OK Glob.eval "" "aaab" = false OK Glob.eval "" "" = false OK Glob.eval "" "bxx" = true OK Glob.eval "" "bx" = true OK Glob.eval "" "aaab" = false OK Glob.eval "" "" = false OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "aaa" = true OK Glob.eval "<*>" "aaaaa" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "aaa" = true OK Glob.eval "<*>" "aaaaa" = true OK Glob.eval "<*>" "" = true OK Glob.eval "<*>" "a" = true OK Glob.eval "<*>" "aaa" = true OK Glob.eval "<*>" "aaaaa" = true OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aaa" = false OK Glob.eval "" "aaaaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aaa" = false OK Glob.eval "" "aaaaa" = false OK Glob.eval "" "a" = true OK Glob.eval "" "" = false OK Glob.eval "" "aaa" = false OK Glob.eval "" "aaaaa" = false OK Glob.eval "<{a,b}>" "a" = true OK Glob.eval "<{a,b}>" "b" = true OK Glob.eval "<{a,b}>" "" = false OK Glob.eval "<{a,b}>" "aa" = false OK Glob.eval "<{a,b}>" "ab" = false OK Glob.eval "<{a,b}>" "ba" = false OK Glob.eval "<{a,b}>" "bb" = false OK Glob.eval "<{a,b}>" "c" = false OK Glob.eval "<{a,b}>" "a" = true OK Glob.eval "<{a,b}>" "b" = true OK Glob.eval "<{a,b}>" "" = false OK Glob.eval "<{a,b}>" "aa" = false OK Glob.eval "<{a,b}>" "ab" = false OK Glob.eval "<{a,b}>" "ba" = false OK Glob.eval "<{a,b}>" "bb" = false OK Glob.eval "<{a,b}>" "c" = false OK Glob.eval "<{a,b}>" "a" = true OK Glob.eval "<{a,b}>" "b" = true OK Glob.eval "<{a,b}>" "" = false OK Glob.eval "<{a,b}>" "aa" = false OK Glob.eval "<{a,b}>" "ab" = false OK Glob.eval "<{a,b}>" "ba" = false OK Glob.eval "<{a,b}>" "bb" = false OK Glob.eval "<{a,b}>" "c" = false OK Glob.eval "" "toto.ml" = true OK Glob.eval "" "toto.mli" = true OK Glob.eval "" "toto." = false OK Glob.eval "" "toto.mll" = false OK Glob.eval "" "toto.ml" = true OK Glob.eval "" "toto.mli" = true OK Glob.eval "" "toto." = false OK Glob.eval "" "toto.mll" = false OK Glob.eval "" "toto.ml" = true OK Glob.eval "" "toto.mli" = true OK Glob.eval "" "toto." = false OK Glob.eval "" "toto.mll" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aeg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "beg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "afg" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "af" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aee" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aeg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "beg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "afg" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "af" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aee" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "acg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "adg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aeg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bcg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdf" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bdg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "bef" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "beg" = true OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "afg" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "af" = false OK Glob.eval "<{a,b}{c,[de]}{f,g}>" "aee" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "b.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "hello.ml" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli.x" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "b.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "hello.ml" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli.x" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "b.ml" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli" = true OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "hello.ml" = false OK Glob.eval "(<*.ml> or <*.mli>) and not \"hello.ml\"" "a.mli.x" = false OK Glob.eval "<*>" "alpha" = true OK Glob.eval "<*>" "beta" = true OK Glob.eval "<*>" "alpha/beta" = false OK Glob.eval "<*>" "gamma/delta" = false OK Glob.eval "<*>" "alpha" = true OK Glob.eval "<*>" "beta" = true OK Glob.eval "<*>" "alpha/beta" = false OK Glob.eval "<*>" "gamma/delta" = false OK Glob.eval "<*>" "alpha" = true OK Glob.eval "<*>" "beta" = true OK Glob.eval "<*>" "alpha/beta" = false OK Glob.eval "<*>" "gamma/delta" = false OK Glob.eval "" "alpha/beta" = true OK Glob.eval "" "alpha/gamma/beta" = true OK Glob.eval "" "alpha/gamma/delta/beta" = true OK Glob.eval "" "alpha" = false OK Glob.eval "" "beta" = false OK Glob.eval "" "gamma/delta" = false OK Glob.eval "" "alpha/beta" = true OK Glob.eval "" "alpha/gamma/beta" = true OK Glob.eval "" "alpha/gamma/delta/beta" = true OK Glob.eval "" "alpha" = false OK Glob.eval "" "beta" = false OK Glob.eval "" "gamma/delta" = false OK Glob.eval "" "alpha/beta" = true OK Glob.eval "" "alpha/gamma/beta" = true OK Glob.eval "" "alpha/gamma/delta/beta" = true OK Glob.eval "" "alpha" = false OK Glob.eval "" "beta" = false OK Glob.eval "" "gamma/delta" = false OK Glob.eval "<**/*.ml>" "toto.ml" = true OK Glob.eval "<**/*.ml>" "toto/tata.ml" = true OK Glob.eval "<**/*.ml>" "alpha/gamma/delta/beta.ml" = true OK Glob.eval "<**/*.ml>" "toto.mli" = false OK Glob.eval "<**/*.ml>" "toto.ml" = true OK Glob.eval "<**/*.ml>" "toto/tata.ml" = true OK Glob.eval "<**/*.ml>" "alpha/gamma/delta/beta.ml" = true OK Glob.eval "<**/*.ml>" "toto.mli" = false OK Glob.eval "<**/*.ml>" "toto.ml" = true OK Glob.eval "<**/*.ml>" "toto/tata.ml" = true OK Glob.eval "<**/*.ml>" "alpha/gamma/delta/beta.ml" = true OK Glob.eval "<**/*.ml>" "toto.mli" = false OK Glob.eval "" "toto/" = true OK Glob.eval "" "toto/tata" = true OK Glob.eval "" "toto/alpha/gamma/delta/beta.ml" = true OK Glob.eval "" "toto" = true OK Glob.eval "" "toto2/tata" = false OK Glob.eval "" "tata/titi" = false OK Glob.eval "" "toto/" = true OK Glob.eval "" "toto/tata" = true OK Glob.eval "" "toto/alpha/gamma/delta/beta.ml" = true OK Glob.eval "" "toto" = true OK Glob.eval "" "toto2/tata" = false OK Glob.eval "" "tata/titi" = false OK Glob.eval "" "toto/" = true OK Glob.eval "" "toto/tata" = true OK Glob.eval "" "toto/alpha/gamma/delta/beta.ml" = true OK Glob.eval "" "toto" = true OK Glob.eval "" "toto2/tata" = false OK Glob.eval "" "tata/titi" = false OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/bar/libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibs/unix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibsliblib/unlibix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/libfoo/boo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "bar" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libbar/foo.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.b.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/bar/libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibs/unix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibsliblib/unlibix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/libfoo/boo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "bar" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libbar/foo.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.b.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/bar/libfoo.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibs/unix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "otherlibsliblib/unlibix/libunix.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "src/libfoo/boo/libbar.a" OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "bar" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libbar/foo.a" = None OK Resource.matchit "%(path:<**/>)lib%(libname:<*> and not <*.*>).a" "libfoo.b.a" = None OK _____ _ _ _ |_ _|__ ___| |_/ / | | |/ _ \/ __| __| | | | | __/\__ \ |_| | | |_|\___||___/\__|_|_| ocamlbuild.cmx -o myocamlbuild /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules a/aa.mli > a/aa.mli.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -I a -I b -o a/aa.cmi a/aa.mli /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules a/aa.ml > a/aa.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules b/bb.ml > b/bb.ml.depends /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -I b -I a -o b/bb.cmo b/bb.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -I a -I b -o a/aa.cmo a/aa.ml /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a b/bb.cmo -o b/libb.cma /home/danmey/src/ocaml-trunk/bin/ocamlc.opt b/libb.cma a/aa.cmo -o a/aa.byte /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -I b -I a -o b/bb.cmx b/bb.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -I a -I b -o a/aa.cmx a/aa.ml /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a b/bb.cmx -o b/libb.cmxa /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt b/libb.cmxa a/aa.cmx -o a/aa.native looks if libs are there _build/b/libb.a _build/b/libb.cma _build/b/libb.cmxa [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules a/aa.mli > a/aa.mli.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -I a -I b -o a/aa.cmi a/aa.mli [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules a/aa.ml > a/aa.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamldep.opt -modules b/bb.ml > b/bb.ml.depends [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -I b -I a -o b/bb.cmo b/bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -c -I a -I b -o a/aa.cmo a/aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt -a b/bb.cmo -o b/libb.cma [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlc.opt b/libb.cma a/aa.cmo -o a/aa.byte [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -I b -I a -o b/bb.cmx b/bb.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -c -I a -I b -o a/aa.cmx a/aa.ml [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt -a b/bb.cmx -o b/libb.cmxa [cache hit] /home/danmey/src/ocaml-trunk/bin/ocamlopt.opt b/libb.cmxa a/aa.cmx -o a/aa.native _____ _ _ ____ |_ _|__ ___| |_/ |___ \ | |/ _ \/ __| __| | __) | | | __/\__ \ |_| |/ __/ |_|\___||___/\__|_|_____| ocamldep.opt -modules Main.ml > Main.ml.depends Packed.ml.depends Lib.mli.depends Lib.mli Packed.ml Packed.cmo -o Pack.cmo ocamlc.opt -c -I lib -o Main.cmo Main.ml Lib.ml.depends Lib.ml Packed.ml Packed.cmx -o Pack.cmx ; then rm -f Pack.mli ; else rm -f Pack.mli ; exit 1; fi ocamlopt.opt -c -I lib -o Main.cmx Main.ml Lib.cmx Pack.cmx Main.cmx -o Main.native Lib.ml Lib.cmo Pack.cmo Main.cmo -o Main.byte looks if executable are there _build/Main.byte _build/Main.byte _build/Main.native _____ _ __ ___ _ _ |_ _|__ ___| |_ \ \ / (_)_ __| |_ _ _ __ _| | | |/ _ \/ __| __| \ \ / /| | '__| __| | | |/ _` | | | | __/\__ \ |_ \ V / | | | | |_| |_| | (_| | | |_|\___||___/\__| \_/ |_|_| \__|\__,_|\__,_|_| _____ _ |_ _|_ _ _ __ __ _ ___| |_ ___ | |/ _` | '__/ _` |/ _ \ __/ __| | | (_| | | | (_| | __/ |_\__ \ |_|\__,_|_| \__, |\___|\__|___/ |___/ ocamlbuild-0.14.3/test/runtest.sh000077500000000000000000000026501454061437200167450ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh set -e cd `dirname $0` export OCB=$PWD/../ocamlbuild.native myfiglet() { figlet $@ | sed 's/ *$//' } if figlet ""; then BANNER=myfiglet else echo "Install figlet to have a better output, press enter to continue with echo" read BANNER=echo fi HERE=`pwd` $BANNER Test2 ./test2/test.sh $@ $BANNER Test3 ./test3/test.sh $@ $BANNER Test4 ./test4/test.sh $@ $BANNER Test5 ./test5/test.sh $@ $BANNER Test6 ./test6/test.sh $@ $BANNER Test7 ./test7/test.sh $@ $BANNER Test8 ./test8/test.sh $@ $BANNER Test9 ./test9/test.sh $@ $BANNER Test11 ./test11/test.sh $@ $BANNER Test Virtual Targets ./test_virtual/test.sh $@ ocamlbuild-0.14.3/test/test1/000077500000000000000000000000001454061437200157375ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test1/foo.ml000066400000000000000000000016111454061437200170530ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) module MA1 = A1 ocamlbuild-0.14.3/test/test11/000077500000000000000000000000001454061437200160205ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test11/_tags000066400000000000000000000015421454061437200170420ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### # a comment "a/aa.byte" or "a/aa.native": use_libb ocamlbuild-0.14.3/test/test11/a/000077500000000000000000000000001454061437200162405ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test11/a/aa.ml000066400000000000000000000016321454061437200171550ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let bar = 3 + List.length Bb.foo ocamlbuild-0.14.3/test/test11/a/aa.mli000066400000000000000000000016071454061437200173300ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val bar : int ocamlbuild-0.14.3/test/test11/b/000077500000000000000000000000001454061437200162415ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test11/b/bb.ml000066400000000000000000000016111454061437200171550ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let foo = [2.2] ocamlbuild-0.14.3/test/test11/b/libb.mllib000066400000000000000000000000031454061437200201630ustar00rootroot00000000000000Bb ocamlbuild-0.14.3/test/test11/myocamlbuild.ml000066400000000000000000000017341454061437200210400ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) open Ocamlbuild_plugin;; dispatch begin function | After_rules -> ocaml_lib "b/libb" | _ -> () end ocamlbuild-0.14.3/test/test11/test.sh000077500000000000000000000022211454061437200173330ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOTPS="" # -- command args BUILD="$OCB -I a -I b aa.byte aa.native -no-skip -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" rm -rf _build $BUILD1 echo looks if libs are there ls _build/b/libb.cma _build/b/libb.cmxa _build/b/libb.a $BUILD2 $OCB -clean ocamlbuild-0.14.3/test/test2/000077500000000000000000000000001454061437200157405ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test2/_tags000066400000000000000000000015551454061437200167660ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### "vivi.ml": camlp4o # , some_useless_tag, \ more_useless_tags ocamlbuild-0.14.3/test/test2/tata.ml000066400000000000000000000016141454061437200172250ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let tata = "TATA2" ocamlbuild-0.14.3/test/test2/tata.mli000066400000000000000000000016331454061437200173770ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* a comment *) val tata : string ocamlbuild-0.14.3/test/test2/test.sh000077500000000000000000000022231454061437200172550ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOPTS="-- -help" BUILD="$OCB toto.byte toto.native -no-skip -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" rm -rf _build cp vivi1.ml vivi.ml $BUILD1 $BUILD2 cp vivi2.ml vivi.ml $BUILD1 $BUILD2 cp vivi3.ml vivi.ml $BUILD1 $BUILD2 $OCB -clean rm vivi.ml ocamlbuild-0.14.3/test/test2/titi.ml000066400000000000000000000016071454061437200172470ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let titi = [] ocamlbuild-0.14.3/test/test2/toto.ml000066400000000000000000000021311454061437200172540ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let i = Tutu.tutu + 10 let s = Tata.tata ^ ".ml" let l = 3 :: Titi.titi let () = Format.printf "toto.native: %s: Hello world!!!@." Sys.argv.(0) let () = Format.printf "Tutu.tutu => %d@.Tata.tata => %S@." Tutu.tutu Tata.tata ocamlbuild-0.14.3/test/test2/tutu.ml000066400000000000000000000017131454061437200172750ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let tutu = (Array.length Vivi.vivi : Tyty.t) let tutu' = 2.0 +. float_of_int tutu ocamlbuild-0.14.3/test/test2/tutu.mli000066400000000000000000000016521454061437200174500ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* a comment *) val tutu : int val tutu' : float ocamlbuild-0.14.3/test/test2/tyty.mli000066400000000000000000000016061454061437200174570ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) type t = int ocamlbuild-0.14.3/test/test2/vivi1.ml000066400000000000000000000016601454061437200173330ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let rec p i = [< '1; '2; p (i + 1) >] let vivi = [|2|] ocamlbuild-0.14.3/test/test2/vivi2.ml000066400000000000000000000016601454061437200173340ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let rec p i = [< '1; '2; p (i + 1) >] let vivi = [|3|] ocamlbuild-0.14.3/test/test2/vivi3.ml000066400000000000000000000016671454061437200173440ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let rec p i = [< '1; '2; p (i + 1) >] let vivi = [|2.1; 1.1|] ocamlbuild-0.14.3/test/test3/000077500000000000000000000000001454061437200157415ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test3/_tags000066400000000000000000000015201454061437200167570ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### "a.byte" or "a.native": use_unix ocamlbuild-0.14.3/test/test3/a.ml000066400000000000000000000016061454061437200165160ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) module X = B ocamlbuild-0.14.3/test/test3/a.mli000066400000000000000000000016071454061437200166700ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Nothing *) ocamlbuild-0.14.3/test/test3/b.ml000066400000000000000000000016061454061437200165170ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) module X = C ocamlbuild-0.14.3/test/test3/b.mli000066400000000000000000000016071454061437200166710ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* nothing *) ocamlbuild-0.14.3/test/test3/c.ml000066400000000000000000000016061454061437200165200ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) module X = D ocamlbuild-0.14.3/test/test3/c.mli000066400000000000000000000016071454061437200166720ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* nothing *) ocamlbuild-0.14.3/test/test3/d.ml000066400000000000000000000016061454061437200165210ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) module X = E ocamlbuild-0.14.3/test/test3/d.mli000066400000000000000000000016071454061437200166730ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* nothing *) ocamlbuild-0.14.3/test/test3/e.ml000066400000000000000000000016061454061437200165220ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) module X = F ocamlbuild-0.14.3/test/test3/e.mli000066400000000000000000000016071454061437200166740ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* nothing *) ocamlbuild-0.14.3/test/test3/f.ml000066400000000000000000000016311454061437200165210ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* nothing *) let _ = Unix.stat ocamlbuild-0.14.3/test/test3/f.mli000066400000000000000000000016071454061437200166750ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* nothing *) ocamlbuild-0.14.3/test/test3/proj.odocl000066400000000000000000000000141454061437200177300ustar00rootroot00000000000000A B C D E F ocamlbuild-0.14.3/test/test3/test.sh000077500000000000000000000021071454061437200172570ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOTPS="" # -- command args BUILD="$OCB a.byte a.native proj.docdir/index.html -no-skip -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" rm -rf _build $BUILD1 $BUILD2 $OCB -clean ocamlbuild-0.14.3/test/test4/000077500000000000000000000000001454061437200157425ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test4/_tags000066400000000000000000000015411454061437200167630ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### # a comment "a/aa.byte" or "a/aa.native": use_str ocamlbuild-0.14.3/test/test4/a/000077500000000000000000000000001454061437200161625ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test4/a/aa.ml000066400000000000000000000016321454061437200170770ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let bar = 3 + List.length Bb.foo ocamlbuild-0.14.3/test/test4/a/aa.mli000066400000000000000000000016071454061437200172520ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val bar : int ocamlbuild-0.14.3/test/test4/b/000077500000000000000000000000001454061437200161635ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test4/b/bb.ml000066400000000000000000000016401454061437200171010ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let r = Str.regexp "r" let foo = [2.2] ocamlbuild-0.14.3/test/test4/test.sh000077500000000000000000000020741454061437200172630ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOTPS="" # -- command args BUILD="$OCB -I a -I b aa.byte aa.native -no-skip -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" rm -rf _build $BUILD1 $BUILD2 $OCB -clean ocamlbuild-0.14.3/test/test5/000077500000000000000000000000001454061437200157435ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test5/_tags000066400000000000000000000015171454061437200167670ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### "a.cmx" or "b.cmx": for-pack(C) ocamlbuild-0.14.3/test/test5/a.ml000066400000000000000000000016221454061437200165160ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let a = 42 + Stack.stack ocamlbuild-0.14.3/test/test5/a.mli000066400000000000000000000016051454061437200166700ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val a : int ocamlbuild-0.14.3/test/test5/b.ml000066400000000000000000000016111454061437200165150ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let b = A.a + 1 ocamlbuild-0.14.3/test/test5/c.mlpack000066400000000000000000000000041454061437200173500ustar00rootroot00000000000000A B ocamlbuild-0.14.3/test/test5/d.ml000066400000000000000000000016341454061437200165240ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) Format.printf "C.B.b = %d@." C.B.b ocamlbuild-0.14.3/test/test5/stack.ml000066400000000000000000000016101454061437200174000ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let stack = 42 ocamlbuild-0.14.3/test/test5/test.sh000077500000000000000000000020601454061437200172570ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOPTS="" # -- command args BUILD="$OCB d.byte d.native -no-skip -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" rm -rf _build $BUILD1 $BUILD2 $OCB -clean ocamlbuild-0.14.3/test/test6/000077500000000000000000000000001454061437200157445ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test6/a.ml000066400000000000000000000016051454061437200165200ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let a = B.b ocamlbuild-0.14.3/test/test6/a.mli000066400000000000000000000016121454061437200166670ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val a : 'a -> 'a ocamlbuild-0.14.3/test/test6/b.ml000066400000000000000000000016051454061437200165210ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let b = D.d ocamlbuild-0.14.3/test/test6/b.mli.v1000066400000000000000000000016121454061437200172150ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val b : 'a -> 'a ocamlbuild-0.14.3/test/test6/b.mli.v2000066400000000000000000000016171454061437200172230ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) .... val b : 'a -> 'a ocamlbuild-0.14.3/test/test6/d.ml000066400000000000000000000016141454061437200165230ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) type t let d x = x ocamlbuild-0.14.3/test/test6/d.mli.v1000066400000000000000000000016211454061437200172170ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) type t val d : 'a -> 'a ocamlbuild-0.14.3/test/test6/d.mli.v2000066400000000000000000000016121454061437200172200ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val d : 'a -> 'a ocamlbuild-0.14.3/test/test6/main.ml000066400000000000000000000016121454061437200172220ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) A.a 2. +. D.d 1. ocamlbuild-0.14.3/test/test6/main.mli000066400000000000000000000016071454061437200173770ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* nothing *) ocamlbuild-0.14.3/test/test6/test.sh000077500000000000000000000024211454061437200172610ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -x rm -rf _build CMDOPTS="" # -- command args BUILD="$OCB -no-skip main.byte -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" cp b.mli.v1 b.mli cp d.mli.v1 d.mli $BUILD1 $BUILD2 cp b.mli.v2 b.mli cp d.mli.v2 d.mli $BUILD1 cp b.mli.v1 b.mli if $BUILD1; then if $BUILD2; then echo PASS else echo "FAIL (-nothing-should-be-rebuilt)" fi else echo FAIL fi $OCB -clean rm {b,d}.mli ocamlbuild-0.14.3/test/test7/000077500000000000000000000000001454061437200157455ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test7/_tags000066400000000000000000000015131454061437200167650ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### "main.byte": my_cool_plugin ocamlbuild-0.14.3/test/test7/aa.ml000066400000000000000000000016071454061437200166640ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let aa = "aa" ocamlbuild-0.14.3/test/test7/bb.mli000066400000000000000000000016061454061437200170360ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val bb : int ocamlbuild-0.14.3/test/test7/bb1.ml000066400000000000000000000016051454061437200167450ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let bb = 43 ocamlbuild-0.14.3/test/test7/bb2.ml000066400000000000000000000016531454061437200167510ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let bb = 43 let f x = x + 1 let () = incr (ref 0) ocamlbuild-0.14.3/test/test7/bb3.ml000066400000000000000000000016531454061437200167520ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let bb = 43 let f x = x + 1 let () = incr (ref 1) ocamlbuild-0.14.3/test/test7/bbcc.mllib000066400000000000000000000000061454061437200176530ustar00rootroot00000000000000Bb Cc ocamlbuild-0.14.3/test/test7/c2.ml000066400000000000000000000016051454061437200166050ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let c2 = 12 ocamlbuild-0.14.3/test/test7/c2.mli000066400000000000000000000016061454061437200167570ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) val c2 : int ocamlbuild-0.14.3/test/test7/c3.ml000066400000000000000000000016151454061437200166070ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let c3 = Bb.bb + 13 ocamlbuild-0.14.3/test/test7/cc.ml000066400000000000000000000016501454061437200166660ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let cc = (String.length Aa.aa) + Bb.bb + C2.c2 ocamlbuild-0.14.3/test/test7/cool_plugin.ml000066400000000000000000000016341454061437200206150ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) print_endline "I am a cool plugin" ocamlbuild-0.14.3/test/test7/main.ml000066400000000000000000000016641454061437200172320ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) let main = String.length Aa.aa - Bb.bb - C3.c3 - Cc.cc - 1 ocamlbuild-0.14.3/test/test7/myocamlbuild.ml000066400000000000000000000020551454061437200207620ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) open Ocamlbuild_plugin;; dispatch begin function | After_rules -> use_lib "main" "bbcc"; dep ["ocaml"; "link"; "byte"; "my_cool_plugin"] ["cool_plugin.cmo"]; | _ -> () end ocamlbuild-0.14.3/test/test7/test.sh000077500000000000000000000022701454061437200172640ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOPTS="" # -- command args BUILD="$OCB bbcc.cma main.byte bbcc.cmxa main.native -no-skip -classic-display $@" BUILD1="$BUILD $CMDARGS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDARGS" rm -rf _build cp bb1.ml bb.ml $BUILD1 $BUILD2 cp bb2.ml bb.ml $BUILD1 -verbose 0 $BUILD2 cp bb3.ml bb.ml $BUILD1 -verbose 0 $BUILD2 $OCB -clean rm bb.ml ocamlbuild-0.14.3/test/test8/000077500000000000000000000000001454061437200157465ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test8/a.ml000066400000000000000000000016321454061437200165220ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) print_endline Myconfig.version;; ocamlbuild-0.14.3/test/test8/myocamlbuild.ml000066400000000000000000000027121454061437200207630ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) open Ocamlbuild_plugin;; let version = "0.1";; dispatch begin function | After_rules -> rule "myconfig.ml" ~prod:"myconfig.ml" begin fun _ _ -> Echo(["let version = \""; version; "\";;\n"], "myconfig.ml") end; copy_rule "copy byte-code executables" "%(path).byte" "%(path:not <**/*.*>)"; copy_rule "copy native executables" "%(path).native" "%(path:not <**/*.*>).opt"; copy_rule "copy binaries to bin" "%(basename).%(extension)" "bin/%(basename).%(extension:<{byte,native}>)"; | _ -> () end ocamlbuild-0.14.3/test/test8/test.sh000077500000000000000000000021101454061437200172560ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOPTS="" # -- command args BUILD="$OCB a.byte a.native a a.opt bin/a bin/a.opt -no-skip -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" rm -rf _build $BUILD1 $BUILD2 $OCB -clean ocamlbuild-0.14.3/test/test9/000077500000000000000000000000001454061437200157475ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test9/dbgl000066400000000000000000000020131454061437200165760ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the Q Public License version 1.0. *) (* *) (***********************************************************************) #load "unix.cma";; #load "str.cma";; #load "discard_printf.cmo";; #load "debug.cmo";; #load "bool.cmo";; #load "glob_ast.cmo";; #load "glob_lexer.cmo";; #load "my_unix.cmo";; #use "glob.ml";; #install_printer print_is;; ocamlbuild-0.14.3/test/test9/test.sh000077500000000000000000000017201454061437200172650ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh set -e set -x cd `dirname $0`/../.. ocamlc -I src ocamlbuild_pack.cmo test/test9/testglob.ml -o ./testglob.native ./testglob.native rm testglob.native ocamlbuild-0.14.3/test/test9/testglob.ml000066400000000000000000000126101454061437200201240ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) (* Testglob *) open Ocamlbuild_pack;; open Bool;; open Glob;; let yep f x = try ignore (f x); true with | _ -> false ;; let tests1 = [ "\"hello\"", true; "", true; "", true; " and or ", true; " titi", false ];; let tests2 = [ "<[a]>", ["a"], ["b"]; "<[a-z]>", ["a";"e";"k";"z"], ["0";"A";"~"]; "<[a-z][0-9]>", ["a0";"b9"], ["a00";"a0a";"b0a";"isduis";""]; "", ["hello"], ["helli"]; "\"hello\"", ["hello"], ["heidi"]; "<*>", ["";"a";"ax"], []; "", ["ab";"acb";"axxxxxb";"ababbababb"], ["abx";"xxxxxab";"xab"]; "<*.ml>", ["hello.ml";".ml"], ["ml"; ""; "toto.mli"]; "", ["a"], ["";"aa";"ba";"ab";"abaa"]; "", ["ab"], ["";"abab";"aba";"abx"]; "", ["abac";"abxc"], ["abab";"ababab";"ababa"]; "<*ab?cd*>", ["123abecd345";"abccd";"abccd345";"ababcababccdab"], ["abcd";"aaaaabcdababcd"]; "<*this*is*a*test*>", ["this is a test";"You know this is a test really";"thisisatest"], ["thisatest"]; "", ["bxx";"bx"], ["aaab";""]; "<*>", ["";"a";"aaa";"aaaaa"], []; "", ["a"],["";"aaa";"aaaaa"]; "<{a,b}>", ["a";"b"],["";"aa";"ab";"ba";"bb";"c"]; "", ["toto.ml";"toto.mli"],["toto.";"toto.mll"]; "<{a,b}{c,[de]}{f,g}>", ["acf";"acg";"adf";"adg";"aef";"aeg";"bcf";"bcg";"bdf";"bdg";"bef";"beg"], ["afg";"af";"aee"]; "(<*.ml> or <*.mli>) and not \"hello.ml\"", ["a.ml"; "b.ml"; "a.mli"], ["hello.ml"; "a.mli.x"]; "<*>", ["alpha";"beta"], ["alpha/beta";"gamma/delta"]; "", ["alpha/beta";"alpha/gamma/beta";"alpha/gamma/delta/beta"], ["alpha";"beta";"gamma/delta"]; "<**/*.ml>", ["toto.ml";"toto/tata.ml";"alpha/gamma/delta/beta.ml"], ["toto.mli"]; "", ["toto/";"toto/tata";"toto/alpha/gamma/delta/beta.ml";"toto"], ["toto2/tata"; "tata/titi"] ];; let tests3 = [ "%(path:<**/>)lib%(libname:<*> and not <*.*>).a", ["libfoo.a","","foo"; "src/bar/libfoo.a","src/bar/","foo"; "otherlibs/unix/libunix.a","otherlibs/unix/","unix"; "otherlibsliblib/unlibix/libunix.a","otherlibsliblib/unlibix/","unix"; "libfoo/libbar.a","libfoo/","bar"; "src/libfoo/boo/libbar.a","src/libfoo/boo/","bar"; ], ["bar"; "libbar/foo.a"; "libfoo.b.a"] ];; let _ = let times = 3 in List.iter begin fun (str, ast) -> let ast' = yep Glob.parse str in if ast <> ast' then begin Printf.printf "Globexp parsing failed for %S.\n%!" str; exit 1 end else Printf.printf "Globexp for %S OK\n%!" str end tests1; List.iter begin fun (gstr, yes, no) -> let globber = Glob.parse gstr in let check polarity = List.iter begin fun y -> if Glob.eval globber y = polarity then Printf.printf "Glob.eval %S %S = %b OK\n%!" gstr y polarity else begin Printf.printf "Glob.eval %S %S = %b FAIL\n%!" gstr y (not polarity); exit 1 end end in for k = 1 to times do check true yes; check false no done end tests2; List.iter begin fun (str, yes, no) -> let resource = Resource.import_pattern str in for k = 1 to times do List.iter begin fun (y, path, libname) -> let resource' = Resource.import y in match Resource.matchit resource resource' with | Some env -> let path' = Resource.subst env "%(path)" in let libname' = Resource.subst env "%(libname)" in if path' = path && libname = libname' then Printf.printf "Resource.matchit %S %S OK\n%!" str y else begin Printf.printf "Resource.matchit %S %S FAIL\n%!" str y; exit 1 end | None -> begin Printf.printf "Resource.matchit %S %S = None FAIL\n%!" str y; exit 1 end end yes; List.iter begin fun y -> let resource' = Resource.import y in if Resource.matchit resource resource' = None then Printf.printf "Resource.matchit %S %S = None OK\n%!" str y else begin Printf.printf "Resource.matchit %S %S <> None FAIL\n%!" str y; exit 1 end end no done end tests3 ;; ocamlbuild-0.14.3/test/test_virtual/000077500000000000000000000000001454061437200174245ustar00rootroot00000000000000ocamlbuild-0.14.3/test/test_virtual/foo.itarget000066400000000000000000000000041454061437200215620ustar00rootroot00000000000000foo ocamlbuild-0.14.3/test/test_virtual/foo1000066400000000000000000000000051454061437200202060ustar00rootroot00000000000000foo1 ocamlbuild-0.14.3/test/test_virtual/foo2000066400000000000000000000000051454061437200202070ustar00rootroot00000000000000foo2 ocamlbuild-0.14.3/test/test_virtual/myocamlbuild.ml000066400000000000000000000021301454061437200224330ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) open Ocamlbuild_plugin;; dispatch begin function | After_rules -> rule "copy foo" ~prod:"bar" ~dep:"foo.otarget" begin fun _env _build -> cp "foo" "bar" end | _ -> () end ocamlbuild-0.14.3/test/test_virtual/test.sh000077500000000000000000000021501454061437200207400ustar00rootroot00000000000000######################################################################### # # # OCaml # # # # Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # # # # Copyright 2007 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### #!/bin/sh cd `dirname $0` set -e set -x CMDOPTS="" # -- command args BUILD="$OCB bar -no-skip -no-links -classic-display $@" BUILD1="$BUILD $CMDOPTS" BUILD2="$BUILD -verbose 0 -nothing-should-be-rebuilt $CMDOPTS" rm -rf _build cp foo1 foo $BUILD1 $BUILD2 cp foo2 foo $BUILD1 -verbose 0 $BUILD2 $OCB -clean rm foo ocamlbuild-0.14.3/testsuite/000077500000000000000000000000001454061437200157515ustar00rootroot00000000000000ocamlbuild-0.14.3/testsuite/.gitignore000066400000000000000000000000601454061437200177350ustar00rootroot00000000000000_test_internal _test_findlibonly _test_external ocamlbuild-0.14.3/testsuite/README000066400000000000000000000012241454061437200166300ustar00rootroot00000000000000The organization of tests is the following: - internal.ml contains the tests that should be runnable from a bare OCaml installation -- always passing the -no-ocamlfind option. - findlibonly.ml contains the tests that should be runnable from a bare OCaml installation, with only ocamlfind/findlib on top. The only ocamlfind packages it relies over are those of the OCaml distribution. - external.ml contains the tests that rely on other findlib packages or external tools to run. Each test will only run if the findlib package it depends on is present. To execute a test file (e.g. internal.ml), run from this directory: ocaml internal.ml ocamlbuild-0.14.3/testsuite/external.ml000066400000000000000000000044011454061437200201240ustar00rootroot00000000000000#use "internal_test_header.ml";; #use "findlibonly_test_header.ml";; #use "external_test_header.ml";; let () = test "SyntaxFlag" ~options:[`use_ocamlfind; `package "camlp4.macro"; `syntax "camlp4o"] ~requirements:(package_exists "camlp4.macro") ~description:"-syntax for ocamlbuild" ~tree:[T.f "dummy.ml" ~content:"IFDEF TEST THEN\nprint_endline \"Hello\";;\nENDIF;;"] ~matching:[M.f "dummy.native"] ~targets:("dummy.native",[]) ();; (* This test fails with the recent versions of camlp4, see https://caml.inria.fr/mantis/view.php?id=5652#c8776. let () = test "Camlp4NativePlugin" ~description:"Fixes PR#5652" ~requirements:(package_exists "camlp4.macro") ~options:[`use_ocamlfind; `package "camlp4.macro"; `tags ["camlp4o.opt"; "syntax(camp4o)"]; `ppflag "camlp4o.opt"; `ppflag "-parser"; `ppflag "macro"; `ppflag "-DTEST"] ~tree:[T.f "dummy.ml" ~content:"IFDEF TEST THEN\nprint_endline \"Hello\";;\nENDIF;;"] ~matching:[M.x "dummy.native" ~output:"Hello"] ~targets:("dummy.native",[]) ();; *) let () = test "SubtoolOptions" ~description:"Options that come from tags that needs to be spliced \ to the subtool invocation (PR#5763)" (* testing for the 'menhir' executable directly is too hard to do in a portable way; test the ocamlfind package instead *) ~requirements:(package_exists "menhirLib") ~options:[`use_ocamlfind; `use_menhir; `tags ["package(camlp4.fulllib)"]] ~tree:[T.f "parser.mly" ~content:"%{ %} %token DUMMY %start test %% test: DUMMY {None}"] ~matching:[M.f "parser.native"; M.f "parser.byte"] ~targets:("parser.native",["parser.byte"]) ();; let () = test "ppopt" ~description:"Test the -ppopt option" ~requirements:(package_exists "camlp4") ~options:[`use_ocamlfind; `package "camlp4"; `syntax "camlp4o"; `tags ["ppopt(-no_quot)"]; ] ~tree:[T.f "test.ml" (* <> looks like a camlp4 quotation and will fail to compile unless '-no_quot' is passed *) ~content:"let test (<<) (>>) x y z = x <> z"] ~targets:("test.cmo",[]) ();; run ~root:"_test_external";; ocamlbuild-0.14.3/testsuite/external_test_header.ml000066400000000000000000000004671454061437200225030ustar00rootroot00000000000000(* Fullfilled and Missing are defined in ocamlbuild_test.ml Findlib was loaded in findlibonly_test_header.ml *) let package_exists package = let open Findlib in try ignore (package_directory package); Fullfilled with No_such_package _ -> Missing (Printf.sprintf "the ocamlfind package %s" package) ocamlbuild-0.14.3/testsuite/findlibonly.ml000066400000000000000000000016401454061437200206150ustar00rootroot00000000000000#use "internal_test_header.ml";; #use "findlibonly_test_header.ml";; let () = test "ThreadAndArchive" ~description:"Fixes PR#6058" ~options:[`use_ocamlfind; `package "threads"; `tag "thread"] ~tree:[T.f "t.ml" ~content:""] ~matching:[M.f "_build/t.cma"] ~targets:("t.cma",[]) ();; let () = test "PredicateFlag" ~description:"ocamlfind ocamldep does not support the -predicate option" ~options:[`use_ocamlfind; `tag "predicate(byte)"] ~tree:[T.f "test.ml" ~content:"let x = List.map"] ~matching:[_build [M.f "test.ml.depends"]] ~targets:("test.ml.depends", []) ();; let () = test "ToolsFlagsConflict" ~description:"PR#6300: conflicts between -ocamlc and -use-ocamlfind options" ~options:[`use_ocamlfind; `ocamlc "\"ocamlc -annot\""] ~tree:[T.f "test.ml" ~content:"let x = 1"] ~matching:[_build [M.f "test.annot"; M.f "test.byte"]] ~targets:("test.byte", []) ();; run ~root:"_test_findlibonly";; ocamlbuild-0.14.3/testsuite/findlibonly_test_header.ml000066400000000000000000000003441454061437200231640ustar00rootroot00000000000000match Sys.command "ocamlfind ocamlc" with | 0 -> () | _ -> prerr_endline "Having ocamlfind installed is a prerequisite \ for running these tests. Aborting."; exit 1; ;; #use "topfind";; ocamlbuild-0.14.3/testsuite/internal.ml000066400000000000000000000470131454061437200201240ustar00rootroot00000000000000#use "internal_test_header.ml";; let () = test "BasicNativeTree" ~options:[`no_ocamlfind] ~description:"Output tree for native compilation" ~requirements:ocamlopt_available ~tree:[T.f "dummy.ml"] ~matching:[M.Exact (_build (M.lf ["_digests"; "dummy.cmi"; "dummy.cmo"; "dummy.cmx"; "dummy.ml"; "dummy.ml.depends"; "dummy.native"; "dummy.o"; "_log"]))] ~targets:("dummy.native",[]) ();; let () = test "BasicByteTree" ~options:[`no_ocamlfind] ~description:"Output tree for byte compilation" ~tree:[T.f "dummy.ml"] ~matching:[M.Exact (_build (M.lf ["_digests"; "dummy.cmi"; "dummy.cmo"; "dummy.ml"; "dummy.ml.depends"; "dummy.byte"; "_log"]))] ~targets:("dummy.byte",[]) ();; let () = test "SeveralTargets" ~options:[`no_ocamlfind] ~description:"Several targets" ~requirements:ocamlopt_available ~tree:[T.f "dummy.ml"] ~matching:[_build (M.lf ["dummy.byte"; "dummy.native"])] ~targets:("dummy.byte",["dummy.native"]) ();; let alt_build_dir = "BuIlD2";; let () = test "BuildDir" ~options:[`no_ocamlfind; `build_dir alt_build_dir] ~description:"Different build directory" ~tree:[T.f "dummy.ml"] ~matching:[M.d alt_build_dir (M.lf ["dummy.byte"])] ~targets:("dummy.byte",[]) ();; let tag_pat_msgs = ["*:a", "File \"_tags\", line 1, characters 0-2:\n\ Lexing error: Invalid globbing pattern \"*\"."; "\n<*{>:a", "File \"_tags\", line 2, characters 0-5:\n\ Lexing error: Invalid globbing pattern \"<*{>\"."; "<*>: ~@a,# ~a", "File \"_tags\", line 1, characters 10-11:\n\ Lexing error: Only ',' separated tags are allowed."];; List.iteri (fun i (content,failing_msg) -> let () = test (Printf.sprintf "TagsErrorMessage_%d" (i+1)) ~options:[`no_ocamlfind] ~description:"Confirm relevance of an error message due to erronous _tags" ~failing_msg ~tree:[T.f "_tags" ~content; T.f "dummy.ml"] ~targets:("dummy.native",[]) () in ()) tag_pat_msgs;; let () = test "Itarget" ~options:[`no_ocamlfind] ~description:".itarget building with dependencies between the modules (PR#5686)" ~tree:[T.f "foo.itarget" ~content:"a.cma\nb.byte\n"; T.f "a.ml"; T.f "b.ml" ~content:"open A\n"] ~matching:[M.f "a.cma"; M.f "b.byte"] ~targets:("foo.otarget",[]) ();; let () = test "PackAcross" ~options:[`no_ocamlfind] ~description:"Pack using a module from the other tree (PR#4592)" ~requirements:ocamlopt_available ~tree:[T.f "main.ml" ~content:"let _ = Pack.Packed.g ()\n"; T.f "Pack.mlpack" ~content:"pack/Packed"; T.f "_tags" ~content:": include\n: for-pack(Pack)\n"; T.d "lib" [T.f "Lib.ml" ~content:"let f()=()"; T.f "Lib.mli" ~content:"val f : unit -> unit"]; T.d "pack" [T.f "Packed.ml" ~content:"let g() = Lib.f ()"]] ~matching:[M.f "main.byte"; M.f "main.native"] ~targets:("main.byte", ["main.native"]) ();; let () = test "PackAcross2" ~options:[`no_ocamlfind] ~description:"Pack using a module from the other tree (PR#4592)" ~tree:[T.f "a2.mli" ~content:"val f : unit -> unit"; T.f "a2.ml" ~content:"let f _ = ()"; T.f "lib.ml" ~content:"module A = A2"; T.f "b.ml" ~content:"let g = Lib.A.f"; T.f "sup.mlpack" ~content:"B"; T.f "prog.ml" ~content:"Sup.B.g"] ~matching:[M.f "prog.byte"] ~targets:("prog.byte",[]) ();; let () = test "PackAcross3" ~options:[`no_ocamlfind] ~description:"Pack using a module from the other tree (PR#4592)" ~tree:[T.d "foo" [ T.f "bar.ml" ~content:"let baz = Quux.xyzzy"]; T.f "foo.mlpack" ~content:"foo/Bar"; T.f "main.ml" ~content:"prerr_endline Foo.Bar.baz"; T.f "myocamlbuild.ml"; T.f "quux.ml" ~content:"let xyzzy = \"xyzzy\""; T.f "quux.mli" ~content:"val xyzzy : string"] ~matching:[M.f "main.byte"] ~targets:("main.byte",[]) ();; let () = test "NativeMliCmi" ~options:[`no_ocamlfind; `ocamlc "toto" (*using ocamlc would fail*); `tags["native"]] ~description:"check that ocamlopt is used for .mli->.cmi \ when tag 'native' is set (part of PR#4613)" ~requirements:ocamlopt_available ~tree:[T.f "foo.mli" ~content:"val bar : int"] ~matching:[_build [M.f "foo.cmi"]] ~targets:("foo.cmi",[]) ();; let () = test "NoIncludeNoHygiene1" ~options:[`no_ocamlfind] ~description:"check that hygiene checks are only done in traversed directories\ (PR#4502)" ~tree:[T.d "must_ignore" [ T.f "dirty.mli" ~content:"val bug : int"]; T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; T.f "_tags" ~content:": -traverse"] ~pre_cmd:"ocamlc -c must_ignore/dirty.mli" (* will make hygiene fail if must_ignore/ is checked *) ~targets:("hello.byte",[]) ();; let () = test "NoIncludeNoHygiene2" ~options:[`no_ocamlfind; `build_dir "must_ignore"] ~description:"check that hygiene checks are not done on the -build-dir \ (PR#4502)" ~tree:[T.d "must_ignore" [ T.f "dirty.mli" ~content:"val bug : int"]; T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; T.f "_tags" ~content:""] ~pre_cmd:"ocamlc -c must_ignore/dirty.mli" (* will make hygiene fail if must_ignore/ is checked *) ~targets:("hello.byte",[]) ();; let () = test "NoIncludeNoHygiene3" ~options:[`no_ocamlfind; `X "must_ignore"] ~description:"check that hygiene checks are not done on excluded dirs (PR#4502)" ~tree:[T.d "must_ignore" [ T.f "dirty.mli" ~content:"val bug : int"]; T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; T.f "_tags" ~content:""] ~pre_cmd:"ocamlc -c must_ignore/dirty.mli" (* will make hygiene fail if must_ignore/ is checked *) ~targets:("hello.byte",[]) ();; let () = test "OutputObj" ~options:[`no_ocamlfind] ~description:"output_obj targets for native and bytecode (PR #6049)" ~requirements:ocamlopt_available ~tree:[T.f "hello.ml" ~content:"print_endline \"Hello, World!\""] ~targets:("hello.byte.o",["hello.byte.c";"hello.native.o"]) ();; let () = test "OutputShared" ~options:[`no_ocamlfind] ~description:"output_shared targets for native and bytecode (PR #6733)" ~requirements:ocamlopt_available ~tree:[T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; T.f "_tags" ~content:"<*.so>: runtime_variant(_pic)"] ~targets:("hello.byte.so",["hello.native.so"]) ();; let () = test "CmxsStubLink" ~options:[`no_ocamlfind] ~description:".cmxs link rules pass correct -I flags" ~requirements:ocamlopt_available ~tree:[T.d "src" [ T.f "foo_stubs.c" ~content:""; T.f "libfoo_stubs.clib" ~content:"foo_stubs.o"; T.f "foo.ml" ~content:""; ]; T.f "_tags" ~content:" : record_foo_stubs : link_foo_stubs"; T.f "myocamlbuild.ml" ~content:" open Ocamlbuild_plugin let () = dispatch begin function | After_rules -> dep [\"record_foo_stubs\"] [\"src/libfoo_stubs.a\"]; flag_and_dep [\"link\"; \"ocaml\"; \"link_foo_stubs\"] (P \"src/libfoo_stubs.a\"); flag [\"library\"; \"ocaml\"; \"record_foo_stubs\"] (S ([A \"-cclib\"; A \"-lfoo_stubs\"])); | _ -> () end "] ~targets:("src/foo.cmxs",[]) ();; let () = test "StrictSequenceFlag" ~options:[`no_ocamlfind; `quiet] ~description:"strict_sequence tag" ~tree:[T.f "hello.ml" ~content:"let () = 1; ()"; T.f "_tags" ~content:"true: strict_sequence\n"] ~failing_msg:(if Sys.ocaml_version < "4.07.0" then "File \"hello.ml\", line 1, characters 9-10: Error: This expression has type int but an expression was expected of type unit Command exited with code 2." else if Sys.ocaml_version < "4.08.0" then "File \"hello.ml\", line 1, characters 9-10: Error: This expression has type int but an expression was expected of type unit because it is in the left-hand side of a sequence Command exited with code 2." else "File \"hello.ml\", line 1, characters 9-10: 1 | let () = 1; () ^ Error: This expression has type int but an expression was expected of type unit because it is in the left-hand side of a sequence Command exited with code 2." ) ~targets:("hello.byte",[]) ();; let () = test "StrictFormatsFlag" ~options:[`no_ocamlfind; `quiet] ~description:"strict_format tag" ~tree:[T.f "hello.ml" ~content:"let _ = Printf.printf \"%.10s\""; T.f "_tags" ~content:"true: strict_formats\n"] ~failing_msg:(if Sys.ocaml_version < "4.08.0" then "File \"hello.ml\", line 1, characters 22-29: Error: invalid format \"%.10s\": at character number 0, \ `precision' is incompatible with 's' in sub-format \"%.10s\" Command exited with code 2." else "File \"hello.ml\", line 1, characters 22-29: 1 | let _ = Printf.printf \"%.10s\" ^^^^^^^ Error: invalid format \"%.10s\": at character number 0, \ `precision' is incompatible with 's' in sub-format \"%.10s\" Command exited with code 2." ) ~targets:("hello.byte",[]) ();; let () = test "PrincipalFlag" ~options:[`no_ocamlfind; `quiet] ~description:"-principal tag" ~tree:[T.f "hello.ml" ~content:"type s={foo:int;bar:unit} type t={foo:int} let f x = (x.bar; x.foo)"; T.f "_tags" ~content:"true: principal\n"] ~failing_msg:(if Sys.ocaml_version < "4.08.0" then "File \"hello.ml\", line 2, characters 42-45: Warning 18: this type-based field disambiguation is not principal." else if Sys.ocaml_version < "4.12.0" then "File \"hello.ml\", line 2, characters 42-45: 2 | let f x = (x.bar; x.foo) ^^^ Warning 18: this type-based field disambiguation is not principal." else "File \"hello.ml\", line 2, characters 42-45: 2 | let f x = (x.bar; x.foo) ^^^ Warning 18 [not-principal]: this type-based field disambiguation is not principal." ) ~targets:("hello.byte",[]) ();; let () = test "ModularPlugin1" ~description:"test a plugin with dependency on external libraries" ~options:[`no_ocamlfind; `quiet; `plugin_tag "use_str"] ~tree:[T.f "main.ml" ~content:"let x = 1"; T.f "myocamlbuild.ml" ~content:"ignore (Str.quote \"\");;"] ~matching:[M.f "main.byte"] ~targets:("main.byte",[]) ();; let () = test "ModularPlugin2" ~description:"check that parametrized tags defined by the plugin \ do not warn at plugin-compilation time" ~requirements:ocamlopt_available ~options:[`no_ocamlfind; `quiet] ~tree:[T.f "main.ml" ~content:"let x = 1"; T.f "_tags" ~content:": toto(-g)"; T.f "myocamlbuild.ml" ~content:"open Ocamlbuild_plugin;; pflag [\"link\"] \"toto\" (fun arg -> A arg);;"] ~failing_msg:"" ~matching:[M.f "main.byte"] ~targets:("main.byte",[]) ();; let () = test "ModularPlugin3" ~description:"check that unknown parametrized tags encountered \ during plugin compilation still warn" ~requirements:ocamlopt_available ~options:[`no_ocamlfind; `quiet; `plugin_tag "toto(-g)"] ~tree:[T.f "main.ml" ~content:"let x = 1"; T.f "myocamlbuild.ml" ~content:"open Ocamlbuild_plugin;; pflag [\"link\"] \"toto\" (fun arg -> A arg);;"] ~failing_msg:"Warning: tag \"toto\" does not expect a parameter, \ but is used with parameter \"-g\"" ~matching:[M.f "main.byte"] ~targets:("main.byte",[]) ();; let () = test "PluginCompilation1" ~description:"check that the plugin is not compiled when -no-plugin is passed" ~options:[`no_ocamlfind; `no_plugin] ~tree:[T.f "main.ml" ~content:"let x = 1"; T.f "myocamlbuild.ml" ~content:"prerr_endline \"foo\";;"] ~matching:[_build [M.Not (M.f "myocamlbuild")]] ~targets:("main.byte",[]) ();; let () = test "PluginCompilation2" ~description:"check that the plugin is compiled when -just-plugin is passed" ~options:[`no_ocamlfind; `just_plugin] ~tree:[T.f "main.ml" ~content:"let x = 1"; T.f "myocamlbuild.ml" ~content:"print_endline \"foo\";;"] ~matching:[_build [M.f "myocamlbuild"]] ~targets:("", []) ();; let () = test "PluginCompilation3" ~description:"check that the plugin is not executed \ when -just-plugin is passed" ~requirements:ocamlopt_available ~options:[`no_ocamlfind; `quiet; `just_plugin] ~tree:[T.f "main.ml" ~content:"let x = 1"; T.f "myocamlbuild.ml" ~content:"print_endline \"foo\";;"] (* if the plugin were executed we'd get "foo" in failing_msg *) ~failing_msg:"" ~targets:("main.byte", []) ();; let () = test "PluginTagsWarning" ~description:"check that a warning is raised if -plugin-tags \ is used without a plugin file" ~options:[`no_ocamlfind; `plugin_tag "use_str"] ~tree:[T.f "main.ml" ~content:""] ~matching:[_build [M.f "main.cmo"]] ~failing_msg:"Warning: option -plugin-tag(s) has no effect \ in absence of plugin file \"myocamlbuild.ml\"" ~targets:("main.ml", []) ();; let () = test "TagsInNonHygienic" ~description:"Regression test for PR#6482, where a _tags \ in a non-traversed directory would cause \ ocamlbuild to abort" ~options:[`no_ocamlfind] ~tree:[ T.f "main.ml" ~content:""; T.d "deps" [T.f "_tags" ~content:""]; T.f "_tags" ~content:": not_hygienic\n"; ] ~matching:[M.f "main.byte"] ~targets:("main.byte",[]) ();; let () = test "TagsNewlines" ~description:"Regression test for PR#6087 about placement \ of newline-escaping backslashes" ~options:[`no_ocamlfind] ~tree:[ T.f "main.ml" ~content:""; T.f "_tags" ~content: ": debug,\\ rectypes : \\ debug, rectypes \\ : debug, rectypes "; ] ~matching:[M.f "main.byte"] ~targets:("main.byte",[]) ();; let () = test "OpenTag" ~description:"Test the parametrized tag for the new -open feature" ~options:[`no_ocamlfind] ~tree:[ T.f "test.ml" ~content:"let _ = map rev [ []; [3;2] ]"; T.f "_tags" ~content: ": open(List)"; ] ~matching:[M.f "test.byte"] ~targets:("test.byte",[]) ();; let () = test "OpenDependencies" ~description:"Test dependency computation for the new -open feature (PR#6584)" ~options:[`no_ocamlfind] ~tree:[ T.f "a.ml" ~content:"let x = 1"; T.f "b.ml" ~content:"print_int x; print_newline ()"; T.f "_tags" ~content: ": open(A)"; ] ~matching:[M.f "b.byte"] ~targets:("b.byte",[]) ();; let () = test "TargetsStartingWithUnderscore" ~description:"Build targets whose name starts with '_'" (* requested by Daniel Bünzli on the caml-list: Subject: [Caml-list] ocamlbuild, build a source that starts with _ Date: Tue, 9 Feb 2016 14:35:06 +0100 https://sympa.inria.fr/sympa/arc/caml-list/2016-02/msg00033.html *) ~options:[`no_ocamlfind] ~tree:[ T.f "_a.c" ~content:"" ] ~targets:("_a.o", []) ();; let () = test "OpaqueEverything" ~description:"Check that tagging everything opaque does not break build" (* Since 4.03, ocamlc also handles the -opaque flag and it has an interesting semantics when compiling .cmi flags. This means that under 4.03 we must add the -opaque flags on .cmi targets, while this would break compilation under older version. Check that code previously written with "-tag opaque" does not break on older OCaml versions. *) ~options:[`no_ocamlfind; `tag "opaque"] ~tree:[ T.f "test.mli" ~content:"val x : int"; T.f "test.ml" ~content:"let x = 123"; ] ~targets:("test.byte", []) ();; let () = test "ForPackEverything" ~description:"Check that tagging everything with -for-pack does not break build" (* OCaml's PR#5995 highlighted that also using -for-pack for bytecode compilation was benefitial in some situations (when using OCaml 4.03 or higher), so we changed ocamlbuild to pass the -for-pack flag under both native and bytecode compilation, instead of just native. Check that this does not break bytecode compilation. *) ~options:[`no_ocamlfind; `tag "for_pack(Foo)"] ~tree:[ T.f "test.mli" ~content:"val x : int"; T.f "test.ml" ~content:"let x = 123"; ] ~targets:("test.cmo", []) ();; let () = test "CLibFromCObj" ~description:"Build a C library from a C object file" ~options:[`no_ocamlfind; `no_plugin] ~tree:[ T.f "test.c" ~content:{| #include #include #include CAMLprim value hello_world(value unit) { CAMLparam1 (unit); printf("Hello World!\n"); CAMLreturn (Val_unit); } |}; ] ~targets:("libtest.a", []) ();; let () = test "JustNoPlugin" ~description:"(ocamlbuild -just-plugin) should do nothing when no plugin is there" ~options:[`no_ocamlfind; `just_plugin] ~tree:[T.f "test.ml" ~content:{|print_endline "Hellow World"|};] (* we check that the target is *not* built *) ~matching:[_build [M.Not (M.f "test.cmo")]] ~targets:("test.cmo", []) ();; let () = test "CmxsFromMllib1" ~description:"Check that a .cmxs file can be built from a .mllib file" ~requirements:ocamlopt_available ~options:[`no_ocamlfind; `no_plugin] ~tree:[ T.f "a.ml" ~content:"let a = 1\n"; T.f "b.ml" ~content:"let b = true\n"; T.f "foo.mllib" ~content:"A\nB\n"; ] ~targets:("foo.cmxs", []) ();; let () = test "CmxsFromMllib2" ~description:"Check that a .cmxs file can be built from a .mllib file, even when one of the module has the same name as the library" ~requirements:ocamlopt_available ~options:[`no_ocamlfind; `no_plugin] ~tree:[ T.f "a.ml" ~content:"let a = 1\n"; T.f "b.ml" ~content:"let b = true\n"; T.f "foo.ml" ~content:"let foo = (A.a, B.b)\n"; T.f "foo.mllib" ~content:"A\nB\nFoo\n"; ] ~targets:("foo.cmxs", []) ();; let () = test "MldylibOverridesMllib" ~description:"Check that the rule producing a cmxs from a .mllib only \ triggers if there is no .mldylib" ~requirements:ocamlopt_available (* GPR #132 (requested by issue #131) adds a new rule which allows producing a .cmxs from a .mllib, where previously this was only possible by providing a separate .mldylib file. This test ensures that the added rule behaves conservatively, i.e. only triggers when no .mldylib file can be found. *) ~options:[`no_ocamlfind; `no_plugin] ~matching:[_build [M.Not (M.f "bar.cmi")]] ~tree:[ T.f "foo.ml"; T.f "bar.ml"; T.f "mylib.mllib" ~content:"Foo\nBar"; T.f "mylib.mldylib" ~content:"Foo"; ] ~targets:("mylib.cmxs", []) ();; let () = test "MldylibOverridesCmx" ~description:"Check that the rule producing foo.cmxs from foo.mldylib \ takes precedence over the one that uses foo.cmx" ~requirements:ocamlopt_available ~options:[`no_ocamlfind; `no_plugin] ~matching:[_build [M.f "bar.cmi"]] ~tree:[ T.f "foo.ml"; T.f "bar.ml"; T.f "foo.mldylib" ~content:"Foo\nBar"; ] ~targets:("foo.cmx", ["foo.cmxs"]) ();; let () = test "MllibOverridesCmx" ~description:"Check that the rule producing foo.cmxs from foo.mllib \ takes precedence over the one that uses foo.cmx" ~requirements:ocamlopt_available ~options:[`no_ocamlfind; `no_plugin] ~matching:[_build [M.f "bar.cmi"]] ~tree:[ T.f "foo.ml"; T.f "bar.ml"; T.f "foo.mllib" ~content:"Foo\nBar"; ] ~targets:("foo.cmx", ["foo.cmxs"]) ();; run ~root:"_test_internal";; ocamlbuild-0.14.3/testsuite/internal_test_header.ml000066400000000000000000000004171454061437200224700ustar00rootroot00000000000000#load "unix.cma";; #mod_use "../src/ocamlbuild_config.ml";; #use "ocamlbuild_test.ml";; module M = Match;; module T = Tree;; let _build = M.d "_build";; let ocamlopt_available = if Ocamlbuild_config.ocaml_native then Fullfilled else Missing ("ocamlopt") ocamlbuild-0.14.3/testsuite/ocamlbuild_test.ml000066400000000000000000000473611454061437200214700ustar00rootroot00000000000000(***********************************************************************) (* *) (* ocamlbuild *) (* *) (* Wojciech Meyer *) (* *) (* Copyright 2012 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file ../LICENSE. *) (* *) (***********************************************************************) open Format external (|>) : 'a -> ('a -> 'b) -> 'b = "%revapply" let print_list ~sep f ppf = function | [] -> () | x :: [] -> f ppf x | x :: xs -> f ppf x; List.iter (fun x -> sep ppf (); f ppf x) xs let print_list_com f = print_list ~sep:(fun ppf () -> pp_print_string ppf ",") f let print_list_blank f = print_list ~sep:(fun ppf () -> pp_print_string ppf " ") f let pp_print_escaped ppf s = Format.fprintf ppf "%S" s let print_string_list = print_list_com pp_print_string let print_string_list_com = print_list_com pp_print_string let print_string_list_blank = print_list_blank pp_print_string let exists filename = try ignore(Unix.stat filename); true with Unix.Unix_error ((Unix.ENOENT),_,_) -> false let execute cmd = let ic = Unix.open_process_in cmd and lst = ref [] in try while true do lst := input_line ic :: !lst done; assert false with End_of_file -> let ret_code = Unix.close_process_in ic in ret_code, List.rev !lst let rm f = if exists f then ignore(Sys.command (Printf.sprintf "rm -r %s" f)) module Match = struct type atts = unit (* File consists of file attribute and name *) type file = atts * string (* Result is an outcome of execution, if consists of returned exit code, and stream from stdout *) type result = int * string type t = (* Represents file in the tree *) | F of file (* Directory, consists of name and sub entries *) | D of file * t list (* Like file, but will be executed, and the result will compared *) | X of file * result (* Symlink; currently not supported *) (* | L of file * file *) (* We request that everything below should match exactly *) | Exact of t (* Here we want just the tree contained entities but we allow some other stuff to be there too *) | Contains of t (* matching on Empty always fail *) | Empty (* matches the negation of its argument: fails when it succeeds and vice versa; Any can be expressed as (Not Empty) *) | Not of t (* Type of error, we either expect something or something is un-expected *) type error = Expected of string | Unexpected of string | Structure of string * string list | Output of string * string * string (* This will print the tree *) let print ppf tree = let rec lines ppf lst = List.iter (fun line -> pp_print_space ppf (); item ppf line) lst and item ppf = function | F (_, name) -> fprintf ppf "@[%s@]" name | D ((_, name), children) -> fprintf ppf "@[@[%s/@]%a@]" name lines children | X ((_,name), _) -> fprintf ppf "@[%s@]" name (* | L ((_,src), (_,dst)) -> fprintf ppf "@[%s->%s@]@" src dst *) | Exact content -> fprintf ppf "{%a}" item content | Contains content -> fprintf ppf "<%a>" item content | Empty -> pp_print_char ppf '#' | Not t -> fprintf ppf "not(@[%a@])" item t in pp_open_vbox ppf 0; item ppf tree; pp_close_box ppf () let f ?(atts=()) name = F (atts, name) let d ?(atts=()) name children = D ((atts, name), children) let lf ?(atts=()) lst = List.map (fun nm -> F (atts,nm)) lst let x ?(atts=()) name ~output = X ((atts,name), (0,output)) let match_with_fs ~root m = let rec visit ~exact ~successes ~errors path m = let string_of_path path = "./" ^ String.concat "/" (List.rev path) in let file name = string_of_path (name :: path) in let push li x = li := x :: !li in let exists_assert filename = push (if exists filename then successes else errors) (Expected filename) in let rec take_name = function | F (_, name) | D ((_, name), _) | X ((_, name), _) -> [name] | Exact sub | Contains sub | Not sub -> take_name sub | Empty -> [] in match m with | F ((),name) -> exists_assert (file name) | D (((),name), sub) -> exists_assert (file name); let lst = List.flatten (List.map take_name sub) in let lst' = Sys.readdir name |> Array.to_list in let lst' = List.filter (fun x -> not (List.mem x lst)) lst' in (if exact && lst' <> [] then errors := Structure ((file name), lst') :: !errors); List.iter (visit ~exact ~successes ~errors (name :: path)) sub | X (((), name), (retcode, output)) -> let _,output' = execute (file name) in let output' = String.concat "\n" output' in push (if output <> output' then errors else successes) (Output (file name, output, output')); | Exact sub -> visit ~exact:true ~successes ~errors path sub | Contains sub -> visit ~exact:false ~successes ~errors path sub | Empty -> push errors (Unexpected (string_of_path path)) | Not sub -> visit ~exact ~errors:successes ~successes:errors path sub in let dir = Sys.getcwd () in Unix.chdir root; let successes = ref [] in let errors = ref [] in visit ~exact:false ~successes ~errors [] m; Unix.chdir dir; List.rev !errors let string_of_error = function | Expected s -> Printf.sprintf "expected '%s' on a file system" s | Unexpected s -> Printf.sprintf "un-expected '%s' on a file system" s | Structure (s,l) -> Printf.sprintf "directory structure '%s' has un-expected files %s" s (String.concat ", " l) | Output (s, e, p) -> Printf.sprintf "executable %s expected output %S but got %S" s e p end module Option = struct type flag = string type path = string type level = int type package = string type file = string type command = string type _module = string type tag = string type t = [ `version | `vnum | `quiet | `verbose of level | `documentation | `log of file | `no_log | `clean | `r | `I of path | `Is of path list | `X of path | `Xs of path list | `lib of flag | `libs of flag list | `_mod of _module | `mods of _module list | `pkg of package | `pkgs of package list | `package of package | `syntax of string | `lflag of flag | `lflags of flag list | `cflag of flag | `cflags of flag list | `docflag of flag | `docflags of flag list | `yaccflag of flag | `yaccflags of flag list | `lexflag of flag | `lexflags of flag list | `ppflag of flag | `pp of flag list | `tag of tag | `tags of tag list | `plugin_tag of tag | `plugin_tags of tag list | `tag_line of tag | `show_tags of path | `ignore of _module list | `no_links | `no_skip | `no_hygiene | `no_ocamlfind | `no_plugin | `no_stdlib | `dont_catch_errors | `just_plugin | `byte_plugin | `plugin_option | `sanitization_script | `no_sanitize | `nothing_should_be_rebuilt | `classic_display | `use_menhir | `use_jocaml | `use_ocamlfind | `j of level | `build_dir of path | `install_lib_dir of path | `install_bin_dir of path | `where | `ocamlc of command | `ocamlopt of command | `ocamldep of command | `ocamldoc of command | `ocamlyacc of command | `menhir of command | `ocamllex of command | `ocamlmktop of command | `ocamlrun of command | `help ] type arg = string * string list let print_level = pp_print_int let print_flag = pp_print_string let print_package = pp_print_string let print_tag = pp_print_escaped let print_tags = print_list_com pp_print_escaped let print_path = pp_print_string let print_paths = print_string_list_com let print_flags = print_string_list_com let print_module = pp_print_string let print_modules = print_string_list_com let print_packages = print_string_list_com let print_command = pp_print_string let print_opt ppf o = fprintf ppf "-"; match o with | `version -> fprintf ppf "version" | `vnum -> fprintf ppf "vnum" | `quiet -> fprintf ppf "quiet" | `verbose level -> fprintf ppf "verbose %a" print_level level | `documentation -> fprintf ppf "documentation" | `log file -> fprintf ppf "log" | `no_log -> fprintf ppf "no-log" | `clean -> fprintf ppf "clean" | `r -> fprintf ppf "r" | `I path -> fprintf ppf "I %a" print_path path | `Is paths -> fprintf ppf "Is %a" print_paths paths | `X path -> fprintf ppf "X %a" print_path path | `Xs paths -> fprintf ppf "Xs %a" print_paths paths | `lib flag -> fprintf ppf "lib %a" print_flag flag | `libs flags -> fprintf ppf "libs %a" print_flags flags | `_mod _module -> fprintf ppf "mod %a" print_module _module | `mods _modules -> fprintf ppf "mods %a" print_modules _modules | `pkg package -> fprintf ppf "pkg %a" print_package package | `pkgs packages -> fprintf ppf "pkgs %a" print_packages packages | `package package -> fprintf ppf "package %a" print_package package | `syntax syntax -> fprintf ppf "syntax %a" pp_print_string syntax | `lflag flag -> fprintf ppf "lflag %a" print_flag flag | `lflags flags -> fprintf ppf "lflags %a" print_flags flags | `cflag flag -> fprintf ppf "cflag %a" print_flag flag | `cflags flags -> fprintf ppf "cflags %a" print_flags flags | `docflag flag -> fprintf ppf "docflag %a" print_flag flag | `docflags flags -> fprintf ppf "docflags %a" print_flags flags | `yaccflag flag -> fprintf ppf "yaccflag %a" print_flag flag | `yaccflags flags -> fprintf ppf "yaccflags %a" print_flags flags | `lexflag flag -> fprintf ppf "lexflag %a" print_flag flag | `lexflags flags -> fprintf ppf "lexflags %a" print_flags flags | `ppflag flag -> fprintf ppf "ppflag %a" print_flag flag | `pp flags -> fprintf ppf "pp %a" print_flags flags | `tag tag -> fprintf ppf "tag %a" print_tag tag | `tags tags -> fprintf ppf "tags %a" print_tags tags | `plugin_tag tag -> fprintf ppf "plugin-tag %a" print_tag tag | `plugin_tags tags -> fprintf ppf "plugin-tags %a" print_tags tags | `tag_line tag -> fprintf ppf "tag-line %a" print_tag tag | `show_tags path -> fprintf ppf "show-tags %a" print_path path | `ignore _modules -> fprintf ppf "ignore %a" print_modules _modules | `no_links -> fprintf ppf "no-links" | `no_skip -> fprintf ppf "no-skip" | `no_hygiene -> fprintf ppf "no-hygiene" | `no_ocamlfind -> fprintf ppf "no-ocamlfind" | `no_plugin -> fprintf ppf "no-plugin" | `no_stdlib -> fprintf ppf "no-stdlib" | `dont_catch_errors -> fprintf ppf "dont" | `just_plugin -> fprintf ppf "just-plugin" | `byte_plugin -> fprintf ppf "byte-plugin" | `plugin_option -> fprintf ppf "plugin-option" | `sanitization_script -> fprintf ppf "sanitization-script" | `no_sanitize -> fprintf ppf "no-sanitze" | `nothing_should_be_rebuilt -> fprintf ppf "nothing_should_be_rebuilt" | `classic_display -> fprintf ppf "classic-display" | `use_menhir -> fprintf ppf "use-menhir" | `use_jocaml -> fprintf ppf "use-jocaml" | `use_ocamlfind -> fprintf ppf "use-ocamlfind" | `j level -> fprintf ppf "j %a" print_level level | `build_dir path -> fprintf ppf "build-dir %a" print_path path | `install_lib_dir path -> fprintf ppf "install-lib-dir %a" print_path path | `install_bin_dir path -> fprintf ppf "install-bin-dir %a" print_path path | `where -> fprintf ppf "where" | `ocamlc command -> fprintf ppf "ocamlc %a" print_command command | `ocamlopt command -> fprintf ppf "ocamlopt %a" print_command command | `ocamldep command -> fprintf ppf "ocamldep %a" print_command command | `ocamldoc command -> fprintf ppf "ocamldoc %a" print_command command | `ocamlyacc command -> fprintf ppf "ocamlyacc %a" print_command command | `menhir command -> fprintf ppf "menhir %a" print_command command | `ocamllex command -> fprintf ppf "ocamllex %a" print_command command | `ocamlmktop command -> fprintf ppf "ocamlmktop %a" print_command command | `ocamlrun command -> fprintf ppf "ocamlrun %a" print_command command | `help -> fprintf ppf "help" end module Tree = struct type name = string type content = string type t = F of name * content | D of name * t list | E let f ?(content="") name = F (name, content) let d name children = D (name, children) let create_on_fs ~root f = let rec visit path f = let file name = List.rev (name :: path) |> String.concat "/" in match f with | F (name, content) -> let ch = file name |> open_out in output_string ch content; close_out ch | D (name, sub) -> (* print_endline ("mking " ^ (file name)); *) Unix.mkdir (file name) 0o750; List.iter (visit (name :: path)) sub | E -> () in let dir = Sys.getcwd () in Unix.chdir root; visit [] f; Unix.chdir dir end type content = string type filename = string type run = filename * content type requirements = Fullfilled | Missing of string type test = { name : string ; description : string ; requirements : requirements option ; tree : Tree.t list ; matching : Match.t list ; options : Option.t list ; targets : string * string list ; pre_cmd : string option ; failing_msg : string option ; run : run list } let tests = ref [] let test name ~description ?requirements ?(options=[]) ?(run=[]) ?pre_cmd ?failing_msg ?(tree=[]) ?(matching=[]) ~targets () = tests := !tests @ [{ name; description; requirements; tree; matching; options; targets; pre_cmd; failing_msg; run; }] let print_colored header_color header name body_color body = let color_code = function | `Red -> "31" | `Green -> "32" | `Yellow -> "33" | `Blue -> "34" | `Magenta -> "35" | `Cyan -> "36" in Printf.printf "\x1b[0;%sm\x1b[1m[%s]\x1b[0m \ \x1b[1m%-20s\x1b[0;%sm%s.\n\x1b[m%!" (color_code header_color) header name (color_code body_color) body let run ~root = let dir = Sys.getcwd () in let root = dir ^ "/" ^ root in rm root; Unix.mkdir root 0o750; let test_tree = Filename.dirname (Sys.argv.(0)) in let test_tree = if test_tree = "." then Sys.getcwd () else test_tree in let build_tree = Filename.dirname test_tree in let ocamlbuild = Filename.concat build_tree "ocamlbuild.byte" in let testsuite_opts = [ (`install_bin_dir build_tree); (`install_lib_dir (Filename.concat build_tree "src")); ] in let verbose = try ignore (Sys.getenv "VERBOSE"); true with Not_found -> false in let command opts args = let b = Buffer.create 127 in let f = Format.formatter_of_buffer b in fprintf f "%s %a %a" ocamlbuild (print_list_blank Option.print_opt) (testsuite_opts @ opts) (print_list_blank pp_print_string) args; Format.pp_print_flush f (); Buffer.contents b in let failed = ref false in let one_test { name ; description ; requirements ; tree ; matching ; options ; targets ; failing_msg ; pre_cmd ; run } = let full_name = root ^ "/" ^ name in rm full_name; Unix.mkdir full_name 0o750; List.iter (Tree.create_on_fs ~root:full_name) tree; Unix.chdir full_name; match requirements with | Some (Missing req) -> print_colored `Yellow "SKIPPED" name `Yellow (Printf.sprintf "%s is required and missing" req) | Some Fullfilled | None -> begin (match pre_cmd with | None -> () | Some str -> ignore(Sys.command str)); let log_name = full_name ^ ".log" in let cmd = command options (fst targets :: snd targets) in let allow_failure = failing_msg <> None in let open Unix in match execute cmd with | WEXITED n,lines | WSIGNALED n,lines | WSTOPPED n,lines when allow_failure || n <> 0 -> begin match failing_msg with | None -> if verbose then begin print_colored `Red "FAILED" name `Yellow (Printf.sprintf "Command '%s' with error code %n, \ output below" cmd n); List.iter print_endline lines; end else begin let ch = open_out log_name in List.iter (fun l -> output_string ch l; output_string ch "\n") lines; close_out ch; print_colored `Red "FAILED" name `Yellow (Printf.sprintf "Command '%s' with error code %n, \ output written to %s" cmd n log_name); end; failed := true; | Some failing_msg -> let starts_with_plus s = String.length s > 0 && s.[0] = '+' in let lines = (* filter out -classic-display output *) List.filter (fun s -> not (starts_with_plus s)) lines in let msg = String.concat "\n" lines in if failing_msg = msg then print_colored `Green "PASSED" name `Cyan description else begin print_colored `Red "FAILED" name `Yellow ((Printf.sprintf "Failure with not matching message:\n\ %s\n!=\n%s\n") msg failing_msg); failed := true end end; | _ -> let errors = List.concat (List.map (Match.match_with_fs ~root:full_name) matching) in begin if errors == [] then print_colored `Green "PASSED" name `Cyan description else begin if verbose then begin print_colored `Red "FAILED" name `Yellow "Some system checks failed, output below"; List.iter (fun e -> Printf.printf "%s.\n%!" (Match.string_of_error e)) errors; end else begin let ch = open_out log_name in output_string ch ("Run '" ^ cmd ^ "'\n"); List.iter (fun e -> output_string ch (Match.string_of_error e); output_string ch ".\n") errors; close_out ch; print_colored `Red "FAILED" name `Yellow (Printf.sprintf "Some system checks failed, \ output written to %s" log_name); end; failed := true end end end in let tests_to_run = List.tl (Array.to_list Sys.argv) in begin match tests_to_run with | [] -> List.iter one_test !tests | _ -> !tests |> List.iter (fun test -> if List.mem test.name tests_to_run then one_test test) end; if !failed then exit 1