From 4f09104d882102dd45e3462e937dd32b4f3fdd26 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Sun, 29 Sep 2019 12:14:49 +0100 Subject: [PATCH] Allow by-host worktree-sharable configure caches The Git configuration value ocaml.configure-cache can be used to specify a directory to keep autoconf cache files in, relative to the worktree root (so `git config ocaml.configure-cache .` enables the feature, and `git config --global ocaml.configure-cache ..` enables it for all worktrees, assuming they're at the same level). autoconf's --cache-file option speeds up future runs of configure by caching the results of previous tests. The cache is invalidated if any environment variables differ (e.g. LDFLAGS) or if the build-host-target triplet differs. This is a nuisance on Windows, where configure is both very slow and it's also common to build with multiple different --host values. This PR allows a tree to be quickly reconfigured from one Windows port to another. --- .gitignore | 1 + Changes | 4 +++- HACKING.adoc | 17 ++++++++++++++ configure | 51 ++++++++++++++++++++++++++++++++++++---- tools/git-dev-options.sh | 51 ++++++++++++++++++++++++++++++++++++---- 5 files changed, 113 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index ff1bf2805..5da73a826 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ _build /autom4te.cache /ocamlc /config.cache +/ocaml-*.cache /config.log /config.status /libtool diff --git a/Changes b/Changes index 06a6fe28b..1371ce168 100644 --- a/Changes +++ b/Changes @@ -266,7 +266,9 @@ Working version (David Allsopp, review by Nicolás Ojeda Bär, report by Sebastian Rasmussen) - #8995: allow developers to specify frequently-used configure options in - Git (ocaml.configure option) See HACKING.adoc for further details. + Git (ocaml.configure option) and a directory for host-specific, shareable + config.cache files (ocaml.configure-cache option). See HACKING.adoc for + further details. (David Allsopp, review by Gabriel Scherer) ### Compiler user-interface and warnings: diff --git a/HACKING.adoc b/HACKING.adoc index 48cb2b2e7..ea25c9889 100644 --- a/HACKING.adoc +++ b/HACKING.adoc @@ -249,6 +249,23 @@ debug runtime, since the enable flag appears after the disable flag. You can also use the full power of Git's `config` command and have options specific to particular clone or worktree. +=== Speeding up configure + +`configure` includes the standard `-C` option which caches various test results +in the file `config.cache` and can use those results to avoid running tests in +subsequent invocations. This mechanism works fine, except that it is easy to +clean the cache by mistake (e.g. with `git clean -dfX`). The cache is also +host-specific which means the file has to be deleted if you run `configure` with +a new `--host` value (this is quite common on Windows, where `configure` is +also quite slow to run). + +You can elect to have host-specific cache files by issuing +`git config --global ocaml.configure-cache .`. The `configure` script will now +automatically create `ocaml-host.cache` (e.g. `ocaml-x86_64-pc-windows.cache`, +or `ocaml-default.cache`). If you work with multiple worktrees, you can share +these cache files by issuing `git config --global ocaml.configure-cache ..`. The +directory is interpreted _relative_ to the `configure` script. + === Bootstrapping The OCaml compiler is bootstrapped. This means that diff --git a/configure b/configure index f30b41d17..34a7f7c28 100755 --- a/configure +++ b/configure @@ -1,16 +1,57 @@ #! /bin/sh if test -e '.git' ; then : - extra_args=$(git config ocaml.configure 2>/dev/null) - if test -n "$extra_args" ; then : - if test -z "$ac_read_git_config" ; then : + if test -z "$ac_read_git_config" ; then : + extra_args=$(git config ocaml.configure 2>/dev/null) + extended_cache=$(git config ocaml.configure-cache 2>/dev/null) + cache_file= + + # If ocaml.configure-cache is set, parse the command-line for the --host + # option, in order to determine the name of the cache file. + if test -n "$extended_cache" ; then : + echo "Detected Git configuration option ocaml.configure-cache set to \ +\"$extended_cache\"" + dashdash= + prev= + host=default + # The logic here is pretty borrowed from autoconf's + for option in $extra_args "$@" + do + if test -n "$prev" ; then : + host=$option + continue + fi + + case $dashdash$option in + --) + dashdash=yes ;; + -host | --host | --hos | --ho) + prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + case $option in + *=?*) host=$(expr "X$option" : '[^=]*=\(.*\)') ;; + *=) host= ;; + esac ;; + esac + done + cache_file="`dirname "$0"`/$extended_cache/ocaml-$host.cache" + fi + + # If either option has a value, re-invoke configure + if test -n "$extra_args$cache_file" ; then : echo "Detected Git configuration option ocaml.configure set to \ \"$extra_args\"" # Too much effort to get the echo to show appropriate quoting - the # invocation itself intentionally quotes $0 and passes $@ exactly as given # but allows a single expansion of ocaml.configure - echo "Re-running $0 $extra_args $@" - ac_read_git_config=true exec "$0" $extra_args "$@" + if test -n "$cache_file" ; then : + echo "Re-running $0 $extra_args --cache-file \"$cache_file\" $@" + ac_read_git_config=true exec "$0" $extra_args \ + --cache-file "$cache_file" "$@" + else + echo "Re-running $0 $extra_args $@" + ac_read_git_config=true exec "$0" $extra_args "$@" + fi fi fi fi diff --git a/tools/git-dev-options.sh b/tools/git-dev-options.sh index 21e60f50f..41925f432 100755 --- a/tools/git-dev-options.sh +++ b/tools/git-dev-options.sh @@ -15,16 +15,57 @@ # This script should have the same shebang as configure if test -e '.git' ; then : - extra_args=$(git config ocaml.configure 2>/dev/null) - if test -n "$extra_args" ; then : - if test -z "$ac_read_git_config" ; then : + if test -z "$ac_read_git_config" ; then : + extra_args=$(git config ocaml.configure 2>/dev/null) + extended_cache=$(git config ocaml.configure-cache 2>/dev/null) + cache_file= + + # If ocaml.configure-cache is set, parse the command-line for the --host + # option, in order to determine the name of the cache file. + if test -n "$extended_cache" ; then : + echo "Detected Git configuration option ocaml.configure-cache set to \ +\"$extended_cache\"" + dashdash= + prev= + host=default + # The logic here is pretty borrowed from autoconf's + for option in $extra_args "$@" + do + if test -n "$prev" ; then : + host=$option + continue + fi + + case $dashdash$option in + --) + dashdash=yes ;; + -host | --host | --hos | --ho) + prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + case $option in + *=?*) host=$(expr "X$option" : '[^=]*=\(.*\)') ;; + *=) host= ;; + esac ;; + esac + done + cache_file="`dirname "$0"`/$extended_cache/ocaml-$host.cache" + fi + + # If either option has a value, re-invoke configure + if test -n "$extra_args$cache_file" ; then : echo "Detected Git configuration option ocaml.configure set to \ \"$extra_args\"" # Too much effort to get the echo to show appropriate quoting - the # invocation itself intentionally quotes $0 and passes $@ exactly as given # but allows a single expansion of ocaml.configure - echo "Re-running $0 $extra_args $@" - ac_read_git_config=true exec "$0" $extra_args "$@" + if test -n "$cache_file" ; then : + echo "Re-running $0 $extra_args --cache-file \"$cache_file\" $@" + ac_read_git_config=true exec "$0" $extra_args \ + --cache-file "$cache_file" "$@" + else + echo "Re-running $0 $extra_args $@" + ac_read_git_config=true exec "$0" $extra_args "$@" + fi fi fi fi