meta.stage.mk revision 256281
11590Srgrimes# $Id: meta.stage.mk,v 1.30 2013/04/19 16:32:57 sjg Exp $
21590Srgrimes#
31590Srgrimes#	@(#) Copyright (c) 2011, Simon J. Gerraty
41590Srgrimes#
51590Srgrimes#	This file is provided in the hope that it will
61590Srgrimes#	be of use.  There is absolutely NO WARRANTY.
71590Srgrimes#	Permission to copy, redistribute or otherwise
81590Srgrimes#	use this file is hereby granted provided that 
91590Srgrimes#	the above copyright notice and this notice are
101590Srgrimes#	left intact. 
111590Srgrimes#      
121590Srgrimes#	Please send copies of changes and bug-fixes to:
131590Srgrimes#	sjg@crufty.net
141590Srgrimes#
151590Srgrimes
161590Srgrimes.if !target(__${.PARSEFILE}__)
171590Srgrimes__${.PARSEFILE}__:
181590Srgrimes
191590Srgrimes.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} != ""
201590Srgrimes# this is generally safer anyway
211590Srgrimes_dirdep = ${RELDIR}.${MACHINE}
221590Srgrimes.else
231590Srgrimes_dirdep = ${RELDIR}
241590Srgrimes.endif
251590Srgrimes
261590Srgrimes# this allows us to trace dependencies back to their src dir
271590Srgrimes.dirdep:
281590Srgrimes	@echo '${_dirdep}' > $@
291590Srgrimes
301590Srgrimes.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == ""
311590Srgrimes_stage_file_basename = `basename $$f`
321590Srgrimes_stage_target_dirname = `dirname $$t`
331590Srgrimes.else
341590Srgrimes_stage_file_basename = $${f\#\#*/}
351590Srgrimes_stage_target_dirname = $${t%/*}
361590Srgrimes.endif
371590Srgrimes
3841568Sarchie_objroot ?= ${_OBJROOT:tA}
391590Srgrimes# make sure this is global
401590Srgrimes_STAGED_DIRS ?=
411590Srgrimes.export _STAGED_DIRS
421590Srgrimes# add each dir we stage to to _STAGED_DIRS
431590Srgrimes# and make sure we have absolute paths so that bmake
4456597Smharo# will match against .MAKE.META.BAILIWICK
4541568SarchieSTAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@
4656597Smharo# convert _STAGED_DIRS into suitable filters
471590SrgrimesGENDIRDEPS_FILTER += Nnot-empty-is-important \
4899112Sobrien	${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \
4999112Sobrien	${_STAGED_DIRS:O:u:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,}
501590Srgrimes
511590SrgrimesLN_CP_SCRIPT = LnCp() { \
5278158Sroam  rm -f $$2 2> /dev/null; \
531590Srgrimes  ln $$1 $$2 2> /dev/null || \
541590Srgrimes  cp -p $$1 $$2; }
551590Srgrimes
561590Srgrimes# it is an error for more than one src dir to try and stage
5778158Sroam# the same file
581590SrgrimesSTAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \
59129678Spjd  t=$$1; \
60132201Stjr  if [ -s $$t.dirdep ]; then \
611590Srgrimes	cmp -s .dirdep $$t.dirdep && return; \
621590Srgrimes	echo "ERROR: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \
631590Srgrimes	exit 1; \
6456597Smharo  fi; \
6523693Speter  LnCp .dirdep $$t.dirdep || exit 1; }
661590Srgrimes
6778158Sroam# common logic for staging files
6878158Sroam# this all relies on RELDIR being set to a subdir of SRCTOP
6978158Sroam# we use ln(1) if we can, else cp(1)
7078158SroamSTAGE_FILE_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageFiles() { \
7178158Sroam  case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \
7278158Sroam  dest=$$1; shift; \
73128772Skientzle  mkdir -p $$dest; \
7492920Simp  [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
75129678Spjd  for f in "$$@"; do \
7692920Simp	case "$$f" in */*) t=$$dest/${_stage_file_basename};; *) t=$$dest/$$f;; esac; \
7792920Simp	StageDirdep $$t; \
7892920Simp	LnCp $$f $$t || exit 1; \
791590Srgrimes	[ -z "$$mode" ] || chmod $$mode $$t; \
801590Srgrimes  done; :; }
81100822Sdwmalone
821590SrgrimesSTAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \
8332097Sjkh  case "$$1" in "") return;; --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \
8432097Sjkh  dest=$$1; shift; \
8537952Sdes  mkdir -p $$dest; \
8632097Sjkh  [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
8732097Sjkh  while test $$\# -ge 2; do \
8832097Sjkh	l=$$ldest$$1; shift; \
89108453Smike	t=$$dest/$$1; \
9032097Sjkh	case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
9187216Smarkm	shift; \
921590Srgrimes	StageDirdep $$t; \
93132201Stjr	rm -f $$t 2>/dev/null; \
94132201Stjr	ln $$lnf $$l $$t || exit 1; \
9556597Smharo  done; :; }
96128772Skientzle
971590SrgrimesSTAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \
9832097Sjkh  case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \
9919120Sscrappy  dest=$$1; shift; \
10078158Sroam  mkdir -p $$dest; \
101128772Skientzle  [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
102129986Sphk  while test $$\# -ge 2; do \
1031590Srgrimes	s=$$1; shift; \
10432097Sjkh	t=$$dest/$$1; \
10532097Sjkh	case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
10632097Sjkh	shift; \
10778158Sroam	StageDirdep $$t; \
10878158Sroam	LnCp $$s $$t || exit 1; \
10978158Sroam	[ -z "$$mode" ] || chmod $$mode $$t; \
11032097Sjkh  done; :; }
11132097Sjkh
11232097Sjkh# this is simple, a list of the "staged" files depends on this,
11332097Sjkh_STAGE_BASENAME_USE:	.USE ${.TARGET:T}
11432097Sjkh	@${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T}
11532097Sjkh
11632097Sjkh.if !empty(STAGE_INCSDIR)
11732097SjkhSTAGE_TARGETS += stage_incs
11832097SjkhSTAGE_INCS ?= ${.ALLSRC:N.dirdep}
11932097Sjkh
12032097Sjkhstage_incs:	.dirdep
12132097Sjkh	@${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS}
12232097Sjkh	@touch $@
12332097Sjkh.endif
12432097Sjkh
12532097Sjkh.if !empty(STAGE_LIBDIR)
12632097SjkhSTAGE_TARGETS += stage_libs
12732097Sjkh
12832097SjkhSTAGE_LIBS ?= ${.ALLSRC:N.dirdep}
12932097Sjkh
13032097Sjkhstage_libs:	.dirdep
13158601Scharnier	@${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS}
13232097Sjkh.if !empty(SHLIB_LINKS)
13332097Sjkh	@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \
13432097Sjkh	${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@}
13532097Sjkh.elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME)
13632097Sjkh	@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK} ${SYMLINKS:T}
13732097Sjkh.endif
13856597Smharo	@touch $@
13956597Smharo.endif
14056597Smharo
14156597Smharo.if !empty(STAGE_DIR)
14256597SmharoSTAGE_SETS += _default
143112855SobrienSTAGE_DIR._default = ${STAGE_DIR}
144112855SobrienSTAGE_LINKS_DIR._default = ${STAGE_LINKS_DIR:U${STAGE_OBJTOP}}
14556597SmharoSTAGE_SYMLINKS_DIR._default = ${STAGE_SYMLINKS_DIR:U${STAGE_OBJTOP}}
146129986SphkSTAGE_FILES._default = ${STAGE_FILES}
147129986SphkSTAGE_LINKS._default = ${STAGE_LINKS}
148129986SphkSTAGE_SYMLINKS._default = ${STAGE_SYMLINKS}
149129986SphkSTAGE_FILES ?= ${.ALLSRC:N.dirdep:Nstage_*}
15056597SmharoSTAGE_SYMLINKS ?= ${.ALLSRC:T:N.dirdep:Nstage_*}
15156597Smharo.endif
15256597Smharo
15356597Smharo.if !empty(STAGE_SETS)
15456597SmharoCLEANFILES += ${STAGE_SETS:@s@stage*$s@}
15532097Sjkh
15632097Sjkh# some makefiles need to populate multiple directories
15719120Sscrappy.for s in ${STAGE_SETS:O:u}
1581590SrgrimesSTAGE_FILES.$s ?= ${.ALLSRC:N.dirdep}
15932097SjkhSTAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep}
1601590SrgrimesSTAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP}
1611590SrgrimesSTAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP}
1621590Srgrimes
1631590SrgrimesSTAGE_TARGETS += stage_files
1641590Srgrimes.if $s != "_default"
1651590Srgrimesstage_files:	stage_files.$s
1661590Srgrimesstage_files.$s:	.dirdep
1671590Srgrimes.else
1681590Srgrimesstage_files:	.dirdep
1691590Srgrimes.endif
1701590Srgrimes	@${STAGE_FILE_SCRIPT}; StageFiles ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_FILES.$s}
1711590Srgrimes	@touch $@
1721590Srgrimes
1731590SrgrimesSTAGE_TARGETS += stage_links
1741590Srgrimes.if $s != "_default"
17532097Sjkhstage_links:	stage_links.$s
17632097Sjkhstage_links.$s:	.dirdep
17732097Sjkh.else
17832097Sjkhstage_links:	.dirdep
17932097Sjkh.endif
18032097Sjkh	@${STAGE_LINKS_SCRIPT}; StageLinks ${STAGE_LINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_LINKS.$s}
18132097Sjkh	@touch $@
1821590Srgrimes
1831590SrgrimesSTAGE_TARGETS += stage_symlinks
18432097Sjkh.if $s != "_default"
18532097Sjkhstage_symlinks:	stage_symlinks.$s
1861590Srgrimesstage_symlinks.$s:	.dirdep
1871590Srgrimes.else
18832097Sjkhstage_symlinks:	.dirdep
18932097Sjkh.endif
19032097Sjkh	@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_SYMLINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_SYMLINKS.$s}
19132097Sjkh	@touch $@
19232097Sjkh
1931590Srgrimes.endfor
19419120Sscrappy.endif
1951590Srgrimes
19632097Sjkh.if !empty(STAGE_AS_SETS)
19719120SscrappyCLEANFILES += ${STAGE_AS_SETS:@s@stage*$s@}
19819120Sscrappy
19919120SscrappySTAGE_TARGETS += stage_as
20032097Sjkh
2011590Srgrimes# sometimes things need to be renamed as they are staged
2021590Srgrimes# each ${file} will be staged as ${STAGE_AS_${file:T}}
2031590Srgrimes# one could achieve the same with SYMLINKS
2041590Srgrimes.for s in ${STAGE_AS_SETS:O:u}
20587216SmarkmSTAGE_AS.$s ?= ${.ALLSRC:N.dirdep}
2061590Srgrimes
2071590Srgrimesstage_as:	stage_as.$s
2081590Srgrimesstage_as.$s:	.dirdep
20932097Sjkh	@${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS.$s:@f@$f ${STAGE_AS_${f:T}:U${f:T}}@}
2101590Srgrimes	@touch $@
2111590Srgrimes
21232097Sjkh.endfor
213128772Skientzle.endif
2141590Srgrimes
21532097SjkhCLEANFILES += ${STAGE_TARGETS}
2161590Srgrimes
21732097Sjkh# stage_*links usually needs to follow any others.
2181590Srgrimes.for t in ${STAGE_TARGETS:N*links:O:u}
21932097Sjkh.ORDER: $t stage_links
22078158Sroam.ORDER: $t stage_symlinks
22178158Sroam.endfor
2221590Srgrimes
22332097Sjkh# make sure this exists
22478158Sroamstaging:
22578158Sroam
22678158Sroam# generally we want staging to wait until everything else is done
22732097SjkhSTAGING_WAIT ?= .WAIT
22832097Sjkh
229128772Skientzleall: ${STAGING_WAIT} staging
23058601Scharnier
23156597Smharo.if exists(${.PARSEDIR}/stage-install.sh) && !defined(STAGE_INSTALL)
23258522Smharo# this will run install(1) and then followup with .dirdep files.
23356597SmharoSTAGE_INSTALL := sh ${.PARSEDIR:tA}/stage-install.sh INSTALL="${INSTALL}" OBJDIR=${.OBJDIR:tA}
23456597Smharo.endif
23532097Sjkh
23632097Sjkh# if ${INSTALL} gets run during 'all' assume it is for staging?
23732097Sjkh.if ${.TARGETS:Nall} == "" && defined(STAGE_INSTALL)
23856597SmharoINSTALL := ${STAGE_INSTALL}
23958601Scharnier.if target(beforeinstall)
24032097Sjkhbeforeinstall: .dirdep
24132097Sjkh.endif
24232097Sjkh.endif
24332097Sjkh
24432097Sjkh.endif
24532097Sjkh