User:Sam/Autoconf cache
Background
configure
tests can be rather time-intensive, especially on lower-end hardware. It's especially frustrating to see this:
root #
./configure
... checking for size_t... yes checking for working alloca.h... yes checking for alloca... yes checking for dirent.h that defines DIR... yes checking for library containing opendir... none required checking for egrep... (cached) /bin/grep -E checking for sys/wait.h that is POSIX.1 compatible... (cached) yes checking for an ANSI C-conforming const... yes checking how to run the C preprocessor... x86_64-pc-linux-gnu-gcc -m32 -E checking for uid_t in sys/types.h... yes ...
It's possible for configure (autoconf-generated configure, at least) to cache the results of some tests so it doesn't have to re-run them. Note that it's most valuable to cache tests where a small e.g. C program is being compiled and executed as these are often the most expensive.
Implementation within Portage
This was actually implemented within Portage for a period between 2006 and 2008 when it was removed.
It was removed because of various bugs (TODO: links), but the main context is in bug #156308.
There was also a package dev-util/confcache
which seems to be on GitHub, but not verified it. I'm curious as to what it did. It ended up being dropped as:
root #
git log 62796a056f4480fdbe90ca0d6b0b093a33d1c3a0
commit 62796a056f4480fdbe90ca0d6b0b093a33d1c3a0 Author: Alec Warner <antarus@gentoo.org> Date: Mon Oct 30 18:19:35 2006 +0000 <+ferringb> antarus: just punt the fucking thing, frankly. [...]
It was hosted at http://gentooexperimental.org/~ferringb/confcache/.
See also bug #433563.
Thoughts
- Obviously, you can't easily use this across systems and platforms
- You can kind of do this if you restrict to a subset of tests, but you really want to generate it at least once on each platform, not guess.
- Need to invalidate cache on major observable changes (which is easy enough to do, just hash a combination of the below, use a symlink and update it when it changes):
- CHOST
- Architecture
- Profile?
- Toolchain versions changing
- Exclude more too-specific variables (stuff from libraries which are way too likely to change) (also, it's good enough even with just the basic autoconf ones, and then less likely to fail)
- Implement it per-package instead to speed up rebuilds and upgrades at least, rather than system-wide
- ccache analogue here
- Would benefit from a shared workaround list like app-portage/no-distcc-env or gentooLTO
Setup
Please don't file bugs when using this configuration for now. Various tests will fail unexpectedly on some packages.
Create a directory for the cache files to reside in:
root #
mkdir /etc/portage/confcache
Initialise the cache:
root #
touch /etc/portage/confcache/config.cache /etc/portage/confcache/config.cache.x86
Then configure /etc/portage as follows:
# See wiki.gentoo.org/User:Sam/Autoconf_cache
pre_src_configure() {
if has multilib-minimal ${INHERITED} ; then
# This is a beauti^W horrible bash intercept for multilib_src_configure
# We need to define CONFIG_SITE based on the specific (multilib) ABI in use
# 1. Check if multilib_src_configure is defined before trying to intercept it
# 2. Make sure we haven't already intercepted it (check for presence of the backup/original: orig_multilib_src_configure)
if [[ $(type -t multilib_src_configure) == function && $(type -t orig_multilib_src_configure) != function ]] ; then
# Backup the original function
eval orig_"$(declare -f multilib_src_configure)"
# Intercept the multilib-minimal.eclass call to multilib_src_configure
multilib_src_configure() {
# Needed because e.g. x86 multilib won't match CC
if [[ -n ${ABI} && ${ABI} != *amd64* ]] ; then
export CONFIG_SITE="${PORTAGE_CONFIGROOT}/etc/portage/confcache/config.site.${ABI}"
else
export CONFIG_SITE="${PORTAGE_CONFIGROOT}/etc/portage/confcache/config.site"
fi
# Call the original version of the function that we saved
orig_multilib_src_configure
}
fi
else
export CONFIG_SITE="${PORTAGE_CONFIGROOT}/etc/portage/confcache/config.site"
fi
}
post_src_configure() {
unset CONFIG_SITE
}
# (From smaeul's repo)
# Load the cache, but don't tell configure where it is, to keep configure
# from overwriting it.
. "${PORTAGE_CONFIGROOT}/etc/portage/confcache/config.cache"
# (From smaeul's repo)
# Load the cache, but don't tell configure where it is, to keep configure
# from overwriting it.
. "${PORTAGE_CONFIGROOT}/etc/portage/confcache/config.cache.x86"
# Allow writing to /etc/portage/confcache, not /etc/portage
# out of caution.
# TODO: I doubt PORTAGE_CONFIGROOT works literally here.
SANDBOX_WRITE="${PORTAGE_CONFIGROOT}/etc/portage/confcache"
Populating the cache
- Build a few packages which use autoconf using FEATURES="keepwork"
- find /var/tmp/portage/ -iname config.log -exec grep -hrsi "ac_cv" {} \+ | egrep -v "(ac_cv_lib|ac_cv_env|ac_cv_path_install)" | sort -u >> /etc/portage/confcache/config.cache
- mv /etc/portage/confcache/config.cache /etc/portage/confcache/config.cache.tmp
- sort -u -t= -k1,1 /etc/portage/confcache/config.cache.tmp >> /etc/portage/confcache/config.cache
- Manually filter out anything else which looks suspicious from /etc/portage/confcache/config.cache/
- Go wild!
Whole system
It may be desirable to run src_configure for everything on the system:
- echo "pre_src_compile() { die }" >> /etc/portage/bashrc
- FEATURES="keepwork" emerge --jobs=200 -evO @world
- sed -i -e '/pre_src_compile/d' /etc/portage/bashrc
- find /var/tmp/portage/ -path "*abi_x86_32.x86*" -iname config.log -exec egrep -hrsi "^ac_cv" {} \+ | egrep -v "(ac_cv_lib|ac_cv_env|ac_cv_path_install)" | sort -u >> /etc/portage/confcache/config.cache.x86 ; mv /etc/portage/confcache/config.cache.x86 /etc/portage/confcache/config.cache.x86.tmp ; sort -u -t= -k1,1 /etc/portage/confcache/config.cache.x86.tmp >> /etc/portage/confcache/config.cache.x86
- find /var/tmp/portage/ -iname config.log -a -not -path "*abi_x86_32.x86*" -exec egrep -hrsi "^ac_cv" {} \+ | egrep -v "(ac_cv_lib|ac_cv_env|ac_cv_path_install)" | sort -u >> /etc/portage/confcache/config.cache ; mv /etc/portage/confcache/config.cache /etc/portage/confcache/config.cache.tmp ; sort -u -t= -k1,1 /etc/portage/confcache/config.cache.tmp >> /etc/portage/confcache/config.cache
Verification
TODO: explain how to check if it's working
Common issues
- autoconf macros contained within AC_CACHE_CHECK incorrectly (issue is with custom checks written that try to respect AC_CACHE_CHECK but get something wrong):
Links
- GNU autoconf documentation
- smaeul's Portage configuration
- chimera's setup
- NetBSD's autoswc