mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-12 06:57:57 +04:00
build: cache the autoconf results of a package that opts in
A configure run spends its time on the compiler invocations behind its checks, not on the shell. tools/m4 runs the compiler 633 times and takes 24 seconds. ccache does not help, because it refuses to cache an autoconf conftest compile at all; it counts these separately as "Autoconf compile/link" under its uncacheable calls. A package that sets PKG_CONFIGURE_CACHE or HOST_CONFIGURE_CACHE keeps a config.cache under tmp/, so a package that is cleaned and built again reads the answers instead of running the checks. The configure stage of tools/m4 drops from 24.5 s to 1.5 s. dirclean removes tmp/, so a full reset of the tree starts from cold answers. A package has to opt in, because a cache is only correct for a configure script that keeps its side effects outside the AC_CACHE_VAL body. ncurses appends -D_XOPEN_SOURCE and -D_DEFAULT_SOURCE to CPPFLAGS inside that body, so a cached run restores the value, skips the append, and then fails to compile wcwidth. ncurses_cfg.h is identical in both cases; the difference is in the generated Makefile. The path covers everything else that changes an answer. A target package is keyed on the toolchain directory, which carries the gcc version. A host package is keyed on the version string of the host compiler, because autoconf cannot detect a new compiler behind an unchanged name; gcc 14 turned an implicit function declaration into an error and changed many answers that way. Both are keyed on a hash of the configure arguments and the build flags, and autoconf refuses a cache written with different flags on top of that. A cached program path outlives a wipe of staging_dir, so ac_cv_path_ and ac_cv_prog_ answers are dropped when the cache loads and configure searches PATH again. Without that, a cache written before staging_dir held sed pins /usr/bin/sed for good. A search runs no compiler, so this costs nothing that matters. The cache arrives through a site script rather than --cache-file, so a hand written configure script never sees a new argument. The site script removes the file of the previous arguments, so a different configuration gets a cold cache instead of an autoconf error. It also unsets the variable, and make exports it for the configure stage alone, so a nested configure run keeps its own cache. Set CONFIGURE_CACHE_DIR to keep the cache elsewhere, or to the empty string to run every check again. Host builds now read a site script on Linux as well. Before this change only Darwin had one. CONFIG_SITE holds one path name: autoconf before 2.70 reads the whole value as that one name, so a second path would silence both scripts. It names the cache script alone, and the cache script loads the site script of the architecture from CONFIG_SITE_BASE. Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
1 parent
48c1e36bf2
commit
a0b036985a
4 files changed
+99
-5
No files matched your search
@@ -109,9 +109,12 @@ HOST_MAKE_FLAGS =
|
||||
|
||||
HOST_CONFIGURE_CMD = $(BASH) ./configure
|
||||
|
||||
ifeq ($(HOST_OS),Darwin)
|
||||
HOST_CONFIG_SITE:=$(INCLUDE_DIR)/site/darwin
|
||||
endif
|
||||
HOST_CONFIG_SITE_BASE:=$(if $(filter Darwin,$(HOST_OS)),$(INCLUDE_DIR)/site/darwin)
|
||||
HOST_CONFIG_SITE:=$(INCLUDE_DIR)/site/cache
|
||||
# Set HOST_CONFIGURE_CACHE:=1 to keep the autoconf result cache of this host
|
||||
# build between builds. Read the note above PKG_CONFIGURE_CACHE in package.mk
|
||||
# before you opt a package in.
|
||||
HOST_CONFIGURE_CACHE_FILE = $(CONFIGURE_CACHE_BASE)/$(notdir $(BUILD_DIR_HOST))-$(host_cc_id)/$(notdir $(HOST_BUILD_DIR))/$(call strhash,$(HOST_CONFIGURE_ARGS) $(HOST_CONFIGURE_VARS)).cache
|
||||
|
||||
define Host/Configure/Default
|
||||
$(if $(HOST_CONFIGURE_PARALLEL),+)(cd $(HOST_BUILD_DIR)/$(3); \
|
||||
@@ -170,6 +173,7 @@ define Host/Exports/Default
|
||||
$(1) : export PKG_CONFIG_LIBDIR=$$(HOST_BUILD_PREFIX)/lib/pkgconfig
|
||||
$(1) : export GIT_CEILING_DIRECTORIES=$$(BUILD_DIR_HOST)
|
||||
$(if $(HOST_CONFIG_SITE),$(1) : export CONFIG_SITE:=$(HOST_CONFIG_SITE))
|
||||
$(if $(HOST_CONFIG_SITE_BASE),$(1) : export CONFIG_SITE_BASE:=$(HOST_CONFIG_SITE_BASE))
|
||||
$(if $(IS_PACKAGE_BUILD),$(1) : export PATH=$$(TARGET_PATH_PKG))
|
||||
endef
|
||||
Host/Exports=$(Host/Exports/Default)
|
||||
@@ -192,6 +196,7 @@ ifndef DUMP
|
||||
$(call BuildTimeLog,end,prepare)
|
||||
|
||||
$(call Host/Exports,$(HOST_STAMP_CONFIGURED))
|
||||
$(if $(and $(CONFIGURE_CACHE_BASE),$(HOST_CONFIGURE_CACHE)),$(HOST_STAMP_CONFIGURED) : export CONFIGURE_CACHE_FILE:=$(HOST_CONFIGURE_CACHE_FILE))
|
||||
$(HOST_STAMP_CONFIGURED): $(HOST_STAMP_PREPARED)
|
||||
$(call BuildTimeLog,begin,configure)
|
||||
$(foreach hook,$(Hooks/HostConfigure/Pre),$(call $(hook))$(sep))
|
||||
|
||||
+12
-2
@@ -188,11 +188,19 @@ include $(INCLUDE_DIR)/autotools.mk
|
||||
_pkg_target:=$(if $(QUILT),,.)
|
||||
|
||||
override MAKEFLAGS=
|
||||
CONFIG_SITE:=$(INCLUDE_DIR)/site/$(ARCH)
|
||||
CONFIG_SITE_BASE:=$(INCLUDE_DIR)/site/$(ARCH)
|
||||
CONFIG_SITE:=$(INCLUDE_DIR)/site/cache
|
||||
# Set PKG_CONFIGURE_CACHE:=1 to keep the autoconf result cache of this package
|
||||
# between builds. Opt in only after you check that the package configures the
|
||||
# same way with a warm cache as it does without one. A configure script that
|
||||
# changes CPPFLAGS or CFLAGS inside an AC_CACHE_VAL body is not safe: a warm
|
||||
# cache restores the value and skips the change. Compare the generated
|
||||
# Makefile, not only config.h, because that is where the difference shows.
|
||||
PKG_CONFIGURE_CACHE_FILE = $(CONFIGURE_CACHE_BASE)/$(TOOLCHAIN_DIR_NAME)/$(notdir $(PKG_BUILD_DIR))/$(call strhash,$(CONFIGURE_ARGS) $(CONFIGURE_VARS)).cache
|
||||
CUR_MAKEFILE:=$(filter-out Makefile,$(firstword $(MAKEFILE_LIST)))
|
||||
SUBMAKE:=$(NO_TRACE_MAKE) $(if $(CUR_MAKEFILE),-f $(CUR_MAKEFILE))
|
||||
PKG_CONFIG_PATH=$(STAGING_DIR)/usr/lib/pkgconfig:$(STAGING_DIR)/usr/share/pkgconfig
|
||||
unexport QUIET CONFIG_SITE
|
||||
unexport QUIET CONFIG_SITE CONFIG_SITE_BASE
|
||||
|
||||
ifeq ($(DUMP)$(filter prereq clean refresh update,$(MAKECMDGOALS)),)
|
||||
ifneq ($(if $(QUILT),,$(CONFIG_AUTOREBUILD)),)
|
||||
@@ -224,6 +232,7 @@ define Build/Exports/Default
|
||||
$(1) : export STAGING_PREFIX=$$(STAGING_DIR)/usr
|
||||
$(1) : export PATH=$$(TARGET_PATH_PKG)
|
||||
$(1) : export CONFIG_SITE:=$$(CONFIG_SITE)
|
||||
$(1) : export CONFIG_SITE_BASE:=$$(CONFIG_SITE_BASE)
|
||||
$(1) : export PKG_CONFIG_PATH:=$$(PKG_CONFIG_PATH)
|
||||
$(1) : export PKG_CONFIG_LIBDIR:=$$(PKG_CONFIG_PATH)
|
||||
$(1) : export GIT_CEILING_DIRECTORIES:=$$(BUILD_DIR)
|
||||
@@ -258,6 +267,7 @@ define Build/CoreTargets
|
||||
$(call BuildTimeLog,end,prepare)
|
||||
|
||||
$(call Build/Exports,$(STAMP_CONFIGURED))
|
||||
$(if $(and $(CONFIGURE_CACHE_BASE),$(PKG_CONFIGURE_CACHE)),$(STAMP_CONFIGURED) : export CONFIGURE_CACHE_FILE:=$(PKG_CONFIGURE_CACHE_FILE))
|
||||
$(STAMP_CONFIGURED): $(STAMP_PREPARED) $(STAMP_CONFIGURED_DEPENDS)
|
||||
$(call BuildTimeLog,begin,configure)
|
||||
rm -f $(STAMP_CONFIGURED_WILDCARD)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Points the autoconf result cache at the file that the build system keeps for
|
||||
# this package. Set CONFIGURE_CACHE_DIR to switch this on; see rules.mk.
|
||||
#
|
||||
# configure sources the site scripts before it loads the cache, so setting
|
||||
# cache_file here has the same effect as --cache-file, without a configure
|
||||
# argument that a hand written configure script would choke on.
|
||||
|
||||
# Autoconf before 2.70 reads CONFIG_SITE as a single path name, so the site
|
||||
# script of the architecture cannot be a second word in it. Load it from here.
|
||||
if [ -n "$CONFIG_SITE_BASE" ] && [ -r "$CONFIG_SITE_BASE" ]; then
|
||||
. "$CONFIG_SITE_BASE"
|
||||
fi
|
||||
|
||||
if [ -n "$CONFIGURE_CACHE_FILE" ]; then
|
||||
configure_cache_dir=${CONFIGURE_CACHE_FILE%/*}
|
||||
|
||||
mkdir -p "$configure_cache_dir" 2>/dev/null
|
||||
|
||||
# A change of the configure arguments gives a new file name. Drop the
|
||||
# file of the previous arguments so that the directory holds one cache
|
||||
# per package.
|
||||
for configure_cache_stale in "$configure_cache_dir"/*.cache; do
|
||||
[ -f "$configure_cache_stale" ] || continue
|
||||
[ "$configure_cache_stale" = "$CONFIGURE_CACHE_FILE" ] || rm -f "$configure_cache_stale"
|
||||
done
|
||||
|
||||
# A cached program path outlives a wipe of staging_dir, so it can name a
|
||||
# tool that is gone, or miss one that the build installed since. Drop
|
||||
# those answers and let configure search PATH again. A search runs no
|
||||
# compiler, and the compiler is where the time goes.
|
||||
if [ -f "$CONFIGURE_CACHE_FILE" ]; then
|
||||
grep -v -e '^ac_cv_path_' -e '^ac_cv_prog_' \
|
||||
"$CONFIGURE_CACHE_FILE" > "$CONFIGURE_CACHE_FILE.tmp"
|
||||
mv -f "$CONFIGURE_CACHE_FILE.tmp" "$CONFIGURE_CACHE_FILE"
|
||||
fi
|
||||
|
||||
cache_file=$CONFIGURE_CACHE_FILE
|
||||
|
||||
# A configure script that runs further configure scripts must not hand
|
||||
# this cache to them. Their checks run with different flags.
|
||||
unset CONFIGURE_CACHE_FILE configure_cache_dir configure_cache_stale
|
||||
fi
|
||||
Reference in new issue
Block a user