diff --git a/contrib/bootstrap b/contrib/bootstrap
index c51a5fd45fa5b835562b1695d0ef41c5bdee4d03..eb7eaac6a4faf0745ac729bb6259a4bc7dc599d4 100755
--- a/contrib/bootstrap
+++ b/contrib/bootstrap
@@ -37,6 +37,7 @@ HOST=
 PREFIX=
 PKGS_ENABLE=
 PKGS_DISABLE=
+CACHE_BUILD=
 CONF_TARBALLS=
 
 if test ! -f "../src/main.mak"
@@ -61,8 +62,12 @@ do
 		--disable-downloads)
 			DISABLE_CONTRIB_DOWNLOADS="TRUE"
 			;;
-                --cache-dir=*)
-			CONF_TARBALLS="${1#--cache-dir=}"
+		--cache-dir=*)
+			CACHE_DIR="${1#--cache-dir=}"
+			CONF_TARBALLS="${CACHE}"
+			;;
+		--cache-builds)
+			CACHE_BUILD=1
 			;;
 		--enable-debug)
 			ENABLE_DEBUG=1
@@ -128,6 +133,8 @@ PKGS_ENABLE := $PKGS_ENABLE
 DISABLE_CONTRIB_DOWNLOADS := $DISABLE_CONTRIB_DOWNLOADS
 DISABLE_CONTRIB_CHECKSUMS := $DISABLE_CONTRIB_CHECKSUMS
 CONF_TARBALLS := $CONF_TARBALLS
+CACHE_DIR := $CACHE_DIR
+CACHE_BUILD := $CACHE_BUILD
 ENABLE_DEBUG := $ENABLE_DEBUG
 EOF
 
diff --git a/contrib/src/main.mak b/contrib/src/main.mak
index fa1557f84719940aee965ea3a2611819b8a8fc57..972852ffb3660be0470020795fd462614d75b761 100644
--- a/contrib/src/main.mak
+++ b/contrib/src/main.mak
@@ -435,7 +435,37 @@ convert-static:
 	for p in $(PREFIX)/lib/pkgconfig/*.pc; do $(SRC)/pkg-static.sh $$p; done
 fetch: $(PKGS:%=.sum-%)
 fetch-all: $(PKGS_ALL:%=.sum-%)
+
+ifdef CACHE_BUILD
+
+ENTRY=$(CACHE_DIR)/contrib/$(shell cat $(MAKEFILE_LIST) | sha256sum | cut -d ' ' -f 1)
+CACHE_PREFIX=$(ENTRY)/$(shell basename $(PREFIX))
+
+install: $(PREFIX)
+
+ifneq ($(PREFIX),$(CACHE_PREFIX))
+$(PREFIX): $(CACHE_PREFIX)
+	ln --symbolic $^ $@
+endif
+
+$(CACHE_PREFIX): $(ENTRY)/.build
+
+ifeq ($(MAKELEVEL), 0)
+$(ENTRY)/.build:
+	unlink $(PREFIX) || true
+	mkdir --parents $(CACHE_PREFIX)
+	$(FLOCK) $(ENTRY) $(MAKE) PREFIX=$(CACHE_PREFIX)
+	touch $@
+else
+$(ENTRY)/.build: $(PKGS:%=.%) convert-static
+$(PKGS:%=.%): FORCE
+FORCE:
+endif
+
+else
 install: $(PKGS:%=.%) convert-static
+endif
+
 
 mostlyclean:
 	-$(RM) $(foreach p,$(PKGS_ALL),.$(p) .sum-$(p) .dep-$(p))