meta.stage.mk revision 288964
146283Sdfr# $FreeBSD: head/share/mk/meta.stage.mk 288964 2015-10-07 00:24:27Z sjg $ 298944Sobrien# $Id: meta.stage.mk,v 1.35 2015/05/20 06:40:33 sjg Exp $ 346283Sdfr# 498944Sobrien# @(#) Copyright (c) 2011, Simon J. Gerraty 546283Sdfr# 698944Sobrien# This file is provided in the hope that it will 798944Sobrien# be of use. There is absolutely NO WARRANTY. 898944Sobrien# Permission to copy, redistribute or otherwise 998944Sobrien# use this file is hereby granted provided that 1046283Sdfr# the above copyright notice and this notice are 1198944Sobrien# left intact. 1298944Sobrien# 1398944Sobrien# Please send copies of changes and bug-fixes to: 1498944Sobrien# sjg@crufty.net 1546283Sdfr# 1698944Sobrien 1798944Sobrien.if !target(__${.PARSEFILE}__) 1898944Sobrien__${.PARSEFILE}__: 1998944Sobrien 2046283Sdfr.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} != "" 2146283Sdfr# this is generally safer anyway 2246283Sdfr_dirdep = ${RELDIR}.${MACHINE} 2346283Sdfr.else 2446283Sdfr_dirdep = ${RELDIR} 2546283Sdfr.endif 2646283Sdfr 2746283SdfrCLEANFILES+= .dirdep 2846283Sdfr 2946283Sdfr# this allows us to trace dependencies back to their src dir 3098944Sobrien.dirdep: 3198944Sobrien @echo '${_dirdep}' > $@ 3246283Sdfr 3398944Sobrien.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == "" 3498944Sobrien_stage_file_basename = `basename $$f` 3598944Sobrien_stage_target_dirname = `dirname $$t` 3698944Sobrien.else 3798944Sobrien_stage_file_basename = $${f\#\#*/} 3898944Sobrien_stage_target_dirname = $${t%/*} 3946283Sdfr.endif 4098944Sobrien 4146283Sdfr_OBJROOT ?= ${OBJROOT:U${OBJTOP:H}} 4246283Sdfr.if ${_OBJROOT:M*/} != "" 4346283Sdfr_objroot ?= ${_OBJROOT:tA}/ 4446283Sdfr.else 4546283Sdfr_objroot ?= ${_OBJROOT:tA} 4646283Sdfr.endif 4746283Sdfr 4846283Sdfr# make sure this is global 4946283Sdfr_STAGED_DIRS ?= 5046283Sdfr.export _STAGED_DIRS 5146283Sdfr# add each dir we stage to to _STAGED_DIRS 5246283Sdfr# and make sure we have absolute paths so that bmake 5398944Sobrien# will match against .MAKE.META.BAILIWICK 5446283SdfrSTAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@ 5546283Sdfr# convert _STAGED_DIRS into suitable filters 5646283SdfrGENDIRDEPS_FILTER += Nnot-empty-is-important \ 5746283Sdfr ${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \ 5846283Sdfr ${_STAGED_DIRS:O:u:M${_objroot}*:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,} 5946283Sdfr 6046283SdfrLN_CP_SCRIPT = LnCp() { \ 6146283Sdfr rm -f $$2 2> /dev/null; \ 6246283Sdfr ln $$1 $$2 2> /dev/null || \ 6346283Sdfr cp -p $$1 $$2; } 6446283Sdfr 6546283Sdfr# a staging conflict should cause an error 6646283Sdfr# a warning is handy when bootstapping different options. 6746283SdfrSTAGE_CONFLICT?= ERROR 6846283Sdfr.if ${STAGE_CONFLICT:tl} == "error" 6946283SdfrSTAGE_CONFLICT_ACTION= exit 1; 7046283Sdfr.else 7146283SdfrSTAGE_CONFLICT_ACTION= 7246283Sdfr.endif 7346283Sdfr 7446283Sdfr# it is an error for more than one src dir to try and stage 7546283Sdfr# the same file 7646283SdfrSTAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \ 7746283Sdfr t=$$1; \ 7846283Sdfr if [ -s $$t.dirdep ]; then \ 7946283Sdfr cmp -s .dirdep $$t.dirdep && return; \ 8046283Sdfr echo "${STAGE_CONFLICT}: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \ 8146283Sdfr ${STAGE_CONFLICT_ACTION} \ 8246283Sdfr fi; \ 8346283Sdfr LnCp .dirdep $$t.dirdep || exit 1; } 8446283Sdfr 8598944Sobrien# common logic for staging files 8698944Sobrien# this all relies on RELDIR being set to a subdir of SRCTOP 8798944Sobrien# we use ln(1) if we can, else cp(1) 8846283SdfrSTAGE_FILE_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageFiles() { \ 89130803Smarcel case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \ 90130803Smarcel dest=$$1; shift; \ 9146283Sdfr mkdir -p $$dest; \ 9246283Sdfr [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ 9346283Sdfr for f in "$$@"; do \ 9446283Sdfr case "$$f" in */*) t=$$dest/${_stage_file_basename};; *) t=$$dest/$$f;; esac; \ 9546283Sdfr StageDirdep $$t; \ 9646283Sdfr LnCp $$f $$t || exit 1; \ 9746283Sdfr [ -z "$$mode" ] || chmod $$mode $$t; \ 9846283Sdfr done; :; } 9946283Sdfr 10046283SdfrSTAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \ 10146283Sdfr case "$$1" in "") return;; --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \ 10246283Sdfr dest=$$1; shift; \ 10346283Sdfr mkdir -p $$dest; \ 10446283Sdfr [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ 10546283Sdfr while test $$\# -ge 2; do \ 10646283Sdfr l=$$ldest$$1; shift; \ 10746283Sdfr t=$$dest/$$1; \ 10846283Sdfr case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \ 10946283Sdfr shift; \ 11046283Sdfr StageDirdep $$t; \ 11146283Sdfr rm -f $$t 2>/dev/null; \ 11246283Sdfr ln $$lnf $$l $$t || exit 1; \ 11346283Sdfr done; :; } 11446283Sdfr 11546283SdfrSTAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \ 11646283Sdfr case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \ 11746283Sdfr dest=$$1; shift; \ 11846283Sdfr mkdir -p $$dest; \ 11946283Sdfr [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ 12046283Sdfr while test $$\# -ge 2; do \ 12146283Sdfr s=$$1; shift; \ 12246283Sdfr t=$$dest/$$1; \ 12346283Sdfr case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \ 12446283Sdfr shift; \ 12546283Sdfr StageDirdep $$t; \ 12698944Sobrien LnCp $$s $$t || exit 1; \ 12746283Sdfr [ -z "$$mode" ] || chmod $$mode $$t; \ 12846283Sdfr done; :; } 12946283Sdfr 13046283Sdfr# this is simple, a list of the "staged" files depends on this, 13146283Sdfr_STAGE_BASENAME_USE: .USE ${.TARGET:T} 13246283Sdfr @${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} 13346283Sdfr 13446283Sdfr_STAGE_AS_BASENAME_USE: .USE ${.TARGET:T} 13546283Sdfr @${STAGE_AS_SCRIPT}; StageAs ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} ${STAGE_AS_${.TARGET:T}:U${.TARGET:T}} 13646283Sdfr 13746283Sdfr.if !empty(STAGE_INCSDIR) 13846283SdfrSTAGE_TARGETS += stage_incs 13946283SdfrSTAGE_INCS ?= ${.ALLSRC:N.dirdep:Nstage_*} 14046283Sdfr 14146283Sdfrstage_includes: stage_incs 14246283Sdfrstage_incs: .dirdep 14346283Sdfr @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS} 14446283Sdfr @touch $@ 14546283Sdfr.endif 14646283Sdfr 14746283Sdfr.if !empty(STAGE_LIBDIR) 14846283SdfrSTAGE_TARGETS += stage_libs 14946283Sdfr 15046283SdfrSTAGE_LIBS ?= ${.ALLSRC:N.dirdep:Nstage_*} 15198944Sobrien 15246283Sdfrstage_libs: .dirdep 15346283Sdfr @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS} 15498944Sobrien.if !defined(NO_SHLIB_LINKS) 15598944Sobrien.if !empty(SHLIB_LINKS) 15698944Sobrien @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \ 15798944Sobrien ${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@} 15898944Sobrien.elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME) 15998944Sobrien @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK} ${SYMLINKS:T} 16046283Sdfr.endif 16146283Sdfr.endif 16246283Sdfr @touch $@ 16346283Sdfr.endif 16446283Sdfr 16546283Sdfr.if !empty(STAGE_DIR) 16646283SdfrSTAGE_SETS += _default 16746283SdfrSTAGE_DIR._default = ${STAGE_DIR} 16846283SdfrSTAGE_LINKS_DIR._default = ${STAGE_LINKS_DIR:U${STAGE_OBJTOP}} 169130803SmarcelSTAGE_SYMLINKS_DIR._default = ${STAGE_SYMLINKS_DIR:U${STAGE_OBJTOP}} 17046283SdfrSTAGE_FILES._default = ${STAGE_FILES} 17146283SdfrSTAGE_LINKS._default = ${STAGE_LINKS} 17246283SdfrSTAGE_SYMLINKS._default = ${STAGE_SYMLINKS} 17346283SdfrSTAGE_FILES ?= ${.ALLSRC:N.dirdep:Nstage_*} 174130803SmarcelSTAGE_SYMLINKS ?= ${.ALLSRC:T:N.dirdep:Nstage_*} 17546283Sdfr.endif 17646283Sdfr 17746283Sdfr.if !empty(STAGE_SETS) 17846283SdfrCLEANFILES += ${STAGE_SETS:@s@stage*$s@} 17946283Sdfr 18098944Sobrien# some makefiles need to populate multiple directories 18198944Sobrien.for s in ${STAGE_SETS:O:u} 18298944SobrienSTAGE_FILES.$s ?= ${.ALLSRC:N.dirdep:Nstage_*} 18398944SobrienSTAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*} 18498944SobrienSTAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP} 18598944SobrienSTAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP} 18698944Sobrien 18798944SobrienSTAGE_TARGETS += stage_files 18846283Sdfr.if $s != "_default" 18946283Sdfrstage_files: stage_files.$s 19046283Sdfrstage_files.$s: .dirdep 19146283Sdfr.else 19246283Sdfrstage_files: .dirdep 19346283Sdfr.endif 19446283Sdfr @${STAGE_FILE_SCRIPT}; StageFiles ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_FILES.$s} 19546283Sdfr @touch $@ 19646283Sdfr 19746283SdfrSTAGE_TARGETS += stage_links 19846283Sdfr.if $s != "_default" 19946283Sdfrstage_links: stage_links.$s 20046283Sdfrstage_links.$s: .dirdep 20146283Sdfr.else 20298944Sobrienstage_links: .dirdep 20346283Sdfr.endif 20446283Sdfr @${STAGE_LINKS_SCRIPT}; StageLinks ${STAGE_LINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_LINKS.$s} 20546283Sdfr @touch $@ 20646283Sdfr 20746283SdfrSTAGE_TARGETS += stage_symlinks 20846283Sdfr.if $s != "_default" 20946283Sdfrstage_symlinks: stage_symlinks.$s 21046283Sdfrstage_symlinks.$s: .dirdep 21146283Sdfr.else 21246283Sdfrstage_symlinks: .dirdep 21346283Sdfr.endif 21446283Sdfr @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_SYMLINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_SYMLINKS.$s} 21546283Sdfr @touch $@ 21646283Sdfr 21746283Sdfr.endfor 21846283Sdfr.endif 219130803Smarcel 22046283Sdfr.if !empty(STAGE_AS_SETS) 22146283SdfrCLEANFILES += ${STAGE_AS_SETS:@s@stage*$s@} 22246283Sdfr 22346283SdfrSTAGE_TARGETS += stage_as 22446283Sdfr 22546283Sdfr# sometimes things need to be renamed as they are staged 22646283Sdfr# each ${file} will be staged as ${STAGE_AS_${file:T}} 22746283Sdfr# one could achieve the same with SYMLINKS 22898944Sobrien.for s in ${STAGE_AS_SETS:O:u} 22998944SobrienSTAGE_AS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*} 23098944Sobrien 23146283Sdfrstage_as: stage_as.$s 23246283Sdfrstage_as.$s: .dirdep 23346283Sdfr @${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS.$s:@f@$f ${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}}@} 23446283Sdfr @touch $@ 23546283Sdfr 23646283Sdfr.endfor 23746283Sdfr.endif 23846283Sdfr 23946283SdfrCLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes 24046283Sdfr 24146283Sdfr# stage_*links usually needs to follow any others. 24246283Sdfr# for non-jobs mode the order here matters 24346283Sdfrstaging: ${STAGE_TARGETS:N*_links} ${STAGE_TARGETS:M*_links} 24446283Sdfr 24546283Sdfr.if ${.MAKE.JOBS:U0} > 0 && ${STAGE_TARGETS:M*_links} != "" 24646283Sdfr# the above isn't sufficient 24746283Sdfr.for t in ${STAGE_TARGETS:N*links:O:u} 24846283Sdfr.ORDER: $t stage_links 24946283Sdfr.endfor 25046283Sdfr.endif 25146283Sdfr 25246283Sdfr# generally we want staging to wait until everything else is done 25346283SdfrSTAGING_WAIT ?= .WAIT 25446283Sdfr 25546283Sdfr.if ${.MAKE.LEVEL} > 0 25646283Sdfrall: ${STAGING_WAIT} staging 25746283Sdfr.endif 25898944Sobrien 25946283Sdfr.if exists(${.PARSEDIR}/stage-install.sh) && !defined(STAGE_INSTALL) 26046283Sdfr# this will run install(1) and then followup with .dirdep files. 26146283SdfrSTAGE_INSTALL := sh ${.PARSEDIR:tA}/stage-install.sh INSTALL="${INSTALL}" OBJDIR=${.OBJDIR:tA} 26246283Sdfr.endif 26346283Sdfr 26446283Sdfr# if ${INSTALL} gets run during 'all' assume it is for staging? 26546283Sdfr.if ${.TARGETS:Nall} == "" && defined(STAGE_INSTALL) 26646283SdfrINSTALL := ${STAGE_INSTALL} 26746283Sdfr.if target(beforeinstall) 26846283Sdfrbeforeinstall: .dirdep 26946283Sdfr.endif 27046283Sdfr.endif 27146283Sdfr.NOPATH: ${STAGE_FILES} 27246283Sdfr 27346283Sdfr.if !empty(STAGE_TARGETS) 27446283SdfrMK_STALE_STAGED?= no 27546283Sdfr.if ${MK_STALE_STAGED} == "yes" 27646283Sdfrall: stale_staged 27746283Sdfr# get a list of paths that we have just staged 27846283Sdfr# get a list of paths that we have previously staged to those same dirs 27998944Sobrien# anything in the 2nd list but not the first is stale - remove it. 28046283Sdfrstale_staged: staging .NOMETA 28146283Sdfr @egrep '^[WL] .*${STAGE_OBJTOP}' /dev/null ${.MAKE.META.FILES:M*stage_*} | \ 28246283Sdfr sed "/\.dirdep/d;s,.* '*\(${STAGE_OBJTOP}/[^ '][^ ']*\).*,\1," | \ 28346283Sdfr sort > ${.TARGET}.staged1 28446283Sdfr @grep -l '${_dirdep}' /dev/null ${_STAGED_DIRS:M${STAGE_OBJTOP}*:O:u:@d@$d/*.dirdep@} | \ 28546283Sdfr sed 's,\.dirdep,,' | sort > ${.TARGET}.staged2 28646283Sdfr @comm -13 ${.TARGET}.staged1 ${.TARGET}.staged2 > ${.TARGET}.stale 28746283Sdfr @test ! -s ${.TARGET}.stale || { \ 28846283Sdfr echo "Removing stale staged files..."; \ 28946283Sdfr sed 's,.*,& &.dirdep,' ${.TARGET}.stale | xargs rm -f; } 29046283Sdfr 29146283Sdfr.endif 29246283Sdfr.endif 29346283Sdfr.endif 29446283Sdfr