1# SPDX-License-Identifier: BSD-2-Clause 2# 3# $Id: dirdeps-cache-update.mk,v 1.23 2024/02/17 17:26:57 sjg Exp $ 4# 5# @(#) Copyright (c) 2020, Simon J. Gerraty 6# 7# This file is provided in the hope that it will 8# be of use. There is absolutely NO WARRANTY. 9# Permission to copy, redistribute or otherwise 10# use this file is hereby granted provided that 11# the above copyright notice and this notice are 12# left intact. 13# 14# Please send copies of changes and bug-fixes to: 15# sjg@crufty.net 16# 17 18## 19# 20# This makefile deals with the updating of STATIC_DIRDEPS_CACHE. 21# Some targets are so huge that computing dirdeps takes a significant 22# amount of time. For such targets a STATIC_DIRDEPS_CACHE can make 23# sense. 24# 25# If the target is represented by targets/pseudo/production 26# it's normal DIRDEPS would be in 27# targets/pseudo/production/Makefile.depend 28# and STATIC_DIRDEPS_CACHE would be 29# targets/pseudo/production/Makefile.dirdeps.cache 30# which is simply initialized by copying dirdeps.cache.production 31# from $OBJTOP 32# 33# When dirdeps-targets.mk is initializing DIRDEPS it will look for 34# Makefile.dirdeps.cache and unless told not to 35# (MK_STATIC_DIRDEPS_CACHE=no) will use it as DIRDEPS_CACHE. 36# 37# If MK_STATIC_DIRDEPS_CACHE_UPDATE is "yes", then this makefile 38# comes into play. 39# 40# We usually get included from local.dirdeps.mk 41# as well as Makefile.depend of RELDIR with a static Makefile.dirdeps.cache 42# 43# If we see that STATIC_DIRDEPS_CACHE is in use, we need to hook a 44# cache-update target into the build to regenerate dirdeps.cache 45# in parallel with the rest of the build. 46# If MK_STATIC_DIRDEPS_CACHE_UPDATE_IMMEDIATE is "yes" we update 47# STATIC_DIRDEPS_CACHE as soon as the update is ready, 48# otherwise it will be done at the end of the build. 49# 50# If STATIC_DIRDEPS_CACHE is not in use, but a DIRDEPS_CACHE is, 51# then we need do nothing except export STATIC_DIRDEPS_CACHE and 52# DYNAMIC_DIRDEPS_CACHE for use when we are include during the visit 53# to the ultimate target (targets/pseudo/production). 54# 55# Regardless of which happens, when included at .MAKE.LEVEL > 0 56# for a target other than cache-update we simply copy 57# DYNAMIC_DIRDEPS_CACHE to STATIC_DIRDEPS_CACHE with some optional 58# filtering. 59# 60# If we are included for the target cache-update we take care of 61# running dirdeps.mk again to generate the DYNAMIC_DIRDEPS_CACHE. 62# 63 64.if !target(_${.PARSEFILE}_) 65_${.PARSEFILE}_: .NOTMAIN 66 67STATIC_CACHE_SED += \ 68 -e '/Autogenerated/s,-.*,- edit with care!,' \ 69 -e '/cache-update/d' 70 71STATIC_DIRDEPS_CACHE_UPDATE_SCRIPT ?= \ 72 { echo Saving ${DYNAMIC_DIRDEPS_CACHE} as ${STATIC_DIRDEPS_CACHE}; \ 73 sed ${STATIC_CACHE_SED} ${DYNAMIC_DIRDEPS_CACHE} > ${STATIC_DIRDEPS_CACHE}; } 74.endif 75 76.if ${MK_DIRDEPS_CACHE:Uno} == "yes" 77.if ${MK_STATIC_DIRDEPS_CACHE_UPDATE:Uno} == "yes" 78.if ${_debug_reldir:U0} || ${DEBUG_DIRDEPS:U:Mcache*} != "" 79_debug_cache = 1 80.else 81_debug_cache = 0 82.endif 83 84.if ${.MAKE.LEVEL} == 0 && !make(cache-update) 85 86.if ${_debug_cache} 87.info ${MK_STATIC_DIRDEPS_CACHE_UPDATE MK_STATIC_DIRDEPS_CACHE MK_DIRDEPS_CACHE DIRDEPS_CACHE STATIC_DIRDEPS_CACHE:L:@v@$v=${$v}@} 88.endif 89 90.if ${MK_STATIC_DIRDEPS_CACHE} == "yes" && defined(STATIC_DIRDEPS_CACHE) && exists(${STATIC_DIRDEPS_CACHE}) 91.if !make(dirdeps) && !target(cache_update_dirdep) 92# We are using static cache and this is the only look we will get. 93# We want to generate an updated cache while we build 94# so need to hook cache-update to dirdeps now. 95# Note: we are running as a sibling to dirdeps-cached, 96# attempting to do this in that context is problematic. 97 98# One of these should exist - to actually kick off the cache generation 99.for d in ${STATIC_DIRDEPS_CACHE:H}/cache-update ${STATIC_DIRDEPS_CACHE:H:H}/cache-update ${STATIC_DIRDEPS_CACHE:H:H:H}/cache-update 100.if exists($d) 101cache_update_dirdep ?= $d.${TARGET_SPEC} 102.endif 103.endfor 104dirdeps cache_update_dirdep: ${cache_update_dirdep} 105${cache_update_dirdep}: _DIRDEP_USE 106DYNAMIC_DIRDEPS_CACHE := ${OBJTOP}/dirdeps.cache.${STATIC_DIRDEPS_CACHE:H:T}-update 107.export DYNAMIC_DIRDEPS_CACHE STATIC_DIRDEPS_CACHE 108.endif # make(dirdeps) 109.endif # MK_* 110 111.endif # .MAKE.LEVEL 0 112 113.if ${.MAKE.LEVEL} > 0 && ${.CURDIR:T} == "cache-update" 114# we are the background update shim 115 116.if ${_debug_cache} 117.info level ${.MAKE.LEVEL}: ${MK_DIRDEPS_CACHE DYNAMIC_DIRDEPS_CACHE STATIC_DIRDEPS_CACHE:L:@v@$v=${$v}@} 118.endif 119 120all: cache-build 121cache-build: .META 122 @set -x; MAKELEVEL=0 \ 123 ${.MAKE} -C ${SRCTOP} -f ${RELDIR}/Makefile cache-update \ 124 -DWITHOUT_STATIC_DIRDEPS_CACHE_UPDATE 125 126.endif # cache-update 127 128.elif ${.MAKE.LEVEL} == 0 && make(cache-update) && !target(cache-update) 129# we were invoked above 130# we just leverage dirdeps.mk 131BUILD_DIRDEPS_TARGETS := ${STATIC_DIRDEPS_CACHE:H:T} 132DIRDEPS := ${STATIC_DIRDEPS_CACHE:H:S,^${SRCTOP}/,,}.${TARGET_SPEC} 133DIRDEPS_CACHE := ${DYNAMIC_DIRDEPS_CACHE} 134 135.if ${DEBUG_DIRDEPS:U:Mcache*} != "" 136.info level 0: ${MK_DIRDEPS_CACHE DIRDEPS_CACHE DIRDEPS:L:@v@$v=${$v}@} 137.endif 138 139# so cache-built below can check on us 140x!= echo; echo ${.MAKE.PID} > ${DIRDEPS_CACHE}.new.pid 141 142cache-update: ${DIRDEPS_CACHE} 143 @rm -f ${DIRDEPS_CACHE}.new.pid 144.if ${MK_STATIC_DIRDEPS_CACHE_UPDATE_IMMEDIATE:Uno} == "yes" 145 ${STATIC_DIRDEPS_CACHE_UPDATE_SCRIPT} 146.endif 147 148all: 149 150.include <dirdeps.mk> 151 152.endif # MK_STATIC_DIRDEPS_CACHE_UPDATE 153.endif # MK_DIRDEPS_CACHE 154 155.if ${.MAKE.LEVEL} > 0 && ${MK_STATIC_DIRDEPS_CACHE_UPDATE:Uno} == "yes" && \ 156 ${STATIC_DIRDEPS_CACHE:Uno:H} == "${SRCTOP}/${RELDIR}" 157.if !defined(DYNAMIC_DIRDEPS_CACHE) 158all: 159.else 160# This is the easy bit, time to save the cache 161 162all: cache-update 163 164# ensure the cache update is completed 165cache-built: 166 @test -s ${DYNAMIC_DIRDEPS_CACHE}.new || exit 0; \ 167 pid=`cat ${DYNAMIC_DIRDEPS_CACHE}.new.pid 2> /dev/null`; \ 168 test $${pid:-0} -gt 1 || exit 0; \ 169 echo "Waiting for $$pid to finish ${DYNAMIC_DIRDEPS_CACHE} ..."; \ 170 while 'kill' -0 $$pid; do sleep 30; done > /dev/null 2>&1 171 172cache-update: cache-built 173.if ${MK_STATIC_DIRDEPS_CACHE_UPDATE_IMMEDIATE:Uno} == "no" 174 @test ! -s ${DYNAMIC_DIRDEPS_CACHE} || \ 175 ${STATIC_DIRDEPS_CACHE_UPDATE_SCRIPT} 176.endif 177 178.endif 179.endif 180