Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154392508
D2796.id6173.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
154 KB
Referenced Files
None
Subscribers
None
D2796.id6173.diff
View Options
Index: Makefile
===================================================================
--- Makefile
+++ Makefile
@@ -99,6 +99,11 @@
#
# For more information, see the build(7) manual page.
#
+.if ${MK_META_MODE} == "yes"
+# targets/Makefile plays the role of top-level
+.include "targets/Makefile"
+.else
+
TGTS= all all-man buildenv buildenvvars buildkernel buildworld \
check-old check-old-dirs check-old-files check-old-libs \
checkdpadd clean cleandepend cleandir \
@@ -516,10 +521,22 @@
buildLINT:
${MAKE} -C ${.CURDIR}/sys/${_TARGET}/conf LINT
-.if defined(.PARSEDIR)
+# This makefile does not run in meta mode
+.MAKE.MODE= normal
+# Normally the things we run from here don't either.
+# Using -DWITH_META_FILES
+# we can buildworld with meta files created which are useful
+# for debugging, but without any of the rest of a meta mode build.
+MK_META_MODE= no
+MK_STAGING= no
+# tell meta.autodep.mk to not even think about updating anything.
+UPDATE_DEPENDFILE= NO
+.export MK_META_MODE MK_STAGING UPDATE_DEPENDFILE
+
.if make(universe)
# we do not want a failure of one branch abort all.
MAKE_JOB_ERROR_TOKEN= no
.export MAKE_JOB_ERROR_TOKEN
.endif
-.endif
+
+.endif # META_MODE
Index: etc/Makefile
===================================================================
--- etc/Makefile
+++ etc/Makefile
@@ -330,6 +330,16 @@
MTREE_CMD?= mtree
+.if ${MK_INSTALL_AS_USER} == "yes" && ${_uid} != 0
+MTREE_FILTER= sed -e 's,\([gu]\)name=,\1id=,g' \
+ -e 's,\(uid=\)[^ ]* ,\1${_uid} ,' \
+ -e 's,\(gid=\)[^ ]* ,\1${_gid} ,' \
+ -e 's,\(uid=\)[^ ]*$$,\1${_uid},' \
+ -e 's,\(gid=\)[^ ]*$$,\1${_gid},'
+.else
+MTREE_FILTER= cat
+.endif
+
MTREES= mtree/BSD.root.dist / \
mtree/BSD.var.dist /var \
mtree/BSD.usr.dist /usr \
@@ -358,7 +368,8 @@
test -d $$d || mkdir -p $$d; \
${ECHO} ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} \
-f $$m -p $$d; \
- ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -f $$m -p $$d; \
+ ${MTREE_FILTER} $$m | \
+ ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -p $$d; \
done; true
.if defined(NO_ROOT)
@set ${MTREES}; \
@@ -372,7 +383,8 @@
test -d ${DESTDIR}/$$d || mkdir -p ${DESTDIR}/$$d; \
${ECHO} "${MTREE_CMD:N-W} -C -f $$m -K uname,gname | " \
"sed s#^\.#.$$d# | ${METALOG.add}" ; \
- ${MTREE_CMD:N-W} -C -f $$m -K uname,gname | sed s#^\.#.$$d# | \
+ ${MTREE_FILTER} $$m | \
+ ${MTREE_CMD:N-W} -C -K uname,gname | sed s#^\.#.$$d# | \
${METALOG.add} ; \
done; true
.endif
Index: gnu/lib/csu/Makefile
===================================================================
--- gnu/lib/csu/Makefile
+++ gnu/lib/csu/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.MAIN: all
+
.include <src.opts.mk>
MK_SSP= no
@@ -74,4 +76,11 @@
${file} ${DESTDIR}${LIBDIR}/${file}
.endfor
+.if ${MK_STAGING} == "yes"
+STAGE_DIR= ${STAGE_LIBDIR}
+STAGE_FILES= ${OBJS} ${SOBJS} ${TGTOBJS}
+staging: stage_files
+.endif
+.NOPATH: ${CLEANFILES}
+
.include <bsd.lib.mk>
Index: gnu/usr.bin/binutils/ld/Makefile
===================================================================
--- gnu/usr.bin/binutils/ld/Makefile
+++ gnu/usr.bin/binutils/ld/Makefile
@@ -70,4 +70,6 @@
${INSTALL} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
${LDSCRIPTS:S|^|ldscripts/|} ${DESTDIR}${SCRIPTDIR}
+GENDIRDEPS_FILTER.host+= Nusr.bin/yacc
+
.include <bsd.prog.mk>
Index: include/Makefile
===================================================================
--- include/Makefile
+++ include/Makefile
@@ -128,8 +128,30 @@
_MARCHS+= x86
.endif
+.if ${MK_STAGING} == "yes"
+# tell bsd.incs.mk that we have it covered
+NO_STAGE_INCLUDES=
+.endif
+
.include <bsd.prog.mk>
+.if ${MK_STAGING} != "no" && !defined(_SKIP_BUILD)
+.if make(all)
+DESTDIR= ${STAGE_OBJTOP}
+
+all: stage_include
+installincludes: buildincludes
+buildincludes: stage_prep
+
+stage_prep:
+ @mkdir -p ${DESTDIR}${INCLUDEDIR}
+ @touch $@
+
+stage_include: .dirdep installincludes
+ @touch $@
+.endif
+.endif
+
installincludes: ${SHARED}
${SHARED}: compat
@@ -142,7 +164,10 @@
.endfor
mtree -deU ${MTREE_FOLLOWS_SYMLINKS} \
-f ${.CURDIR}/../etc/mtree/BSD.include.dist \
- -p ${DESTDIR}${INCLUDEDIR}
+ -p ${DESTDIR}${INCLUDEDIR} > /dev/null
+.if ${MK_META_MODE} == "yes"
+ touch ${.TARGET}
+.endif
copies:
.for i in ${LDIRS} ${LSUBDIRS} ${LSUBSUBDIRS} crypto machine machine/pc \
@@ -229,6 +254,9 @@
cd ${.CURDIR}/../sys/teken; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 teken.h \
${DESTDIR}${INCLUDEDIR}/teken
+.if ${MK_META_MODE} == "yes"
+ touch ${.TARGET}
+.endif
symlinks:
@${ECHO} "Setting up symlinks to kernel source tree..."
@@ -343,3 +371,15 @@
ln -fs ../../../sys/rpc/$$h \
${DESTDIR}${INCLUDEDIR}/rpc; \
done
+.if ${MK_META_MODE} == "yes"
+ touch ${.TARGET}
+.endif
+
+.if ${MACHINE} == "host"
+# we're here because we are building a sysroot...
+# we need MACHINE et al set correctly
+HOST_MACHINE!= uname -m
+HOST_MACHINE_ARCH!= uname -p
+MACHINE:= ${HOST_MACHINE}
+MACHINE_ARCH:= ${HOST_MACHINE_ARCH}
+.endif
Index: include/arpa/Makefile
===================================================================
--- include/arpa/Makefile
+++ include/arpa/Makefile
@@ -3,9 +3,7 @@
.include <src.opts.mk>
INCS= ftp.h inet.h nameser.h nameser_compat.h tftp.h
-.if ${MK_TELNET} == "no"
INCS+= telnet.h
-.endif
INCSDIR=${INCLUDEDIR}/arpa
.include <bsd.prog.mk>
Index: kerberos5/lib/libasn1/Makefile
===================================================================
--- kerberos5/lib/libasn1/Makefile
+++ kerberos5/lib/libasn1/Makefile
@@ -115,7 +115,12 @@
.hx.h:
${CP} ${.IMPSRC} ${.TARGET}
-
+
+# This makefile generates a lot of its headers
+# so tell bsd.sys.mk not to try and stage them before they are built.
+# Note: this is rare
+NO_BEFOREBUILD_INCLUDES=
+
.include <bsd.lib.mk>
.SUFFIXES: .h .c .x .hx
Index: kerberos5/lib/libhdb/Makefile
===================================================================
--- kerberos5/lib/libhdb/Makefile
+++ kerberos5/lib/libhdb/Makefile
@@ -96,6 +96,11 @@
.hx.h:
${CP} ${.IMPSRC} ${.TARGET}
+# This makefile generates a lot of its headers
+# so tell bsd.sys.mk not to try and stage them before they are built.
+# Note: this is rare
+NO_BEFOREBUILD_INCLUDES=
+
.include <bsd.lib.mk>
.SUFFIXES: .h .c .x .hx
Index: kerberos5/lib/libhx509/Makefile
===================================================================
--- kerberos5/lib/libhx509/Makefile
+++ kerberos5/lib/libhx509/Makefile
@@ -290,6 +290,11 @@
.hx.h:
${CP} ${.IMPSRC} ${.TARGET}
+# This makefile generates a lot of its headers
+# so tell bsd.sys.mk not to try and stage them before they are built.
+# Note: this is rare
+NO_BEFOREBUILD_INCLUDES=
+
.include <bsd.lib.mk>
.SUFFIXES: .h .c .x .hx
Index: lib/clang/clang.build.mk
===================================================================
--- lib/clang/clang.build.mk
+++ lib/clang/clang.build.mk
@@ -39,6 +39,24 @@
.PATH: ${LLVM_SRCS}/${SRCDIR}
+.if empty(TOOLSDIR) || !exists(${TOOLSDIR}/usr/bin/clang-tblgen)
+.if ${MACHINE} == "host" && defined(BOOTSTRAPPING_TOOLS)
+.if !empty(LEGACY_TOOLS) && exists(${LEGACY_TOOLS}/usr/bin/tblgen)
+TOOLSDIR= ${LEGACY_TOOLS}
+.endif
+.endif
+.if ${MK_STAGING} == "yes" && exists(${STAGE_HOST_OBJTOP:Uno}/usr/bin/tblgen)
+TOOLSDIR= ${STAGE_HOST_OBJTOP}
+.endif
+.if exists(${LEGACY_TOOLS:Uno}/usr/bin/tblgen)
+TOOLSDIR= ${LEGACY_TOOLS}
+.endif
+.endif
+TOOLSDIR?=
+.if !empty(TOOLSDIR) && exists(${TOOLSDIR}/usr/bin/clang-tblgen)
+TBLGEN= ${TOOLSDIR}/usr/bin/tblgen
+CLANG_TBLGEN= ${TOOLSDIR}/usr/bin/clang-tblgen
+.endif
TBLGEN?= tblgen
CLANG_TBLGEN?= clang-tblgen
@@ -227,3 +245,7 @@
SRCS+= ${TGHDRS:C/$/.inc.h/}
DPSRCS+= ${TGHDRS:C/$/.inc.h/}
CLEANFILES+= ${TGHDRS:C/$/.inc.h/} ${TGHDRS:C/$/.inc.d/}
+
+# if we are not doing explicit 'make depend', there is
+# nothing to cause these to be generated.
+beforebuild: ${SRCS:M*.inc.h}
Index: lib/clang/include/Makefile
===================================================================
--- lib/clang/include/Makefile
+++ lib/clang/include/Makefile
@@ -56,4 +56,7 @@
GENINCS= arm_neon.h
CLEANFILES= ${GENINCS}
+# avoid a circular dependency
+GENDIRDEPS_FILTER+= Nusr.bin/clang/clang-tblgen.host
+
.include <bsd.prog.mk>
Index: lib/csu/Makefile.inc
===================================================================
--- lib/csu/Makefile.inc
+++ lib/csu/Makefile.inc
@@ -7,3 +7,8 @@
NO_WMISSING_VARIABLE_DECLARATIONS=
.include "../Makefile.inc"
+
+.if ${MK_STAGING} == "yes" && ${.TARGETS:Nall} == ""
+FILES?= ${OBJS}
+FILESDIR?= ${LIBDIR}
+.endif
Index: lib/libc++/Makefile
===================================================================
--- lib/libc++/Makefile
+++ lib/libc++/Makefile
@@ -208,4 +208,8 @@
${.OBJDIR}/libstdc++.a
.endif
+# avoid cyclic dependency
+CFLAGS+= -I${LIBCXXRTDIR}
+GENDIRDEPS_FILTER= N*/libcxxrt
+
.include <bsd.lib.mk>
Index: lib/libc/Makefile
===================================================================
--- lib/libc/Makefile
+++ lib/libc/Makefile
@@ -163,6 +163,24 @@
.include <bsd.lib.mk>
+.if !defined(_SKIP_BUILD)
+# We need libutil.h, get it directly to avoid
+# recording a build dependency
+CFLAGS+= -I${.CURDIR:H}/libutil
+# Same issue with libm
+MSUN_ARCH_SUBDIR != ${MAKE} -B -C ${.CURDIR:H}/msun -V ARCH_SUBDIR
+# unfortunately msun/src contains both private and public headers
+CFLAGS+= -I${.CURDIR:H}/msun/${MSUN_ARCH_SUBDIR}
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -I${.CURDIR:H}/msun/x86
+.endif
+CFLAGS+= -I${.CURDIR:H}/msun/src
+# and we do not want to record a dependency on msun
+.if ${.MAKE.LEVEL} > 0
+GENDIRDEPS_FILTER+= N${RELDIR:H}/msun
+.endif
+.endif
+
# Disable warnings in contributed sources.
CWARNFLAGS:= ${.IMPSRC:Ngdtoa_*.c:C/^.+$/${CWARNFLAGS}/:C/^$/-w/}
# XXX For now, we don't allow libc to be compiled with
Index: lib/libpam/Makefile
===================================================================
--- lib/libpam/Makefile
+++ lib/libpam/Makefile
@@ -26,6 +26,6 @@
# The modules must be built first, because they are built into the
# static version of libpam.
-SUBDIR+= modules libpam
+SUBDIR+= modules libpam static_modules
.include <bsd.subdir.mk>
Index: lib/libpam/libpam/Makefile
===================================================================
--- lib/libpam/libpam/Makefile
+++ lib/libpam/libpam/Makefile
@@ -172,33 +172,12 @@
ADD_HEADERS= security/pam_mod_misc.h
-#
-# Static modules
-#
-# We build static versions of all modules and of openpam_static.o,
-# then link them all together into openpam_static_modules.o. None of
-# the modules export any symbols, but they store structures with
-# pointers to their service functions in a linker set which the code
-# in openpam_static.c traverses to locate the individual modules.
-#
-MODULE_DIR= ../modules
-.include "${.CURDIR}/${MODULE_DIR}/modules.inc"
-STATIC_MODULES= ${MODULES:C/.*/${MODULE_DIR}\/&\/lib&.a/}
-STATICOBJS+= openpam_static_modules.o
-CLEANFILES+= openpam_static.o \
- openpam_static_modules.o
-
-openpam_static_modules.o: openpam_static.o ${STATIC_MODULES}
- ${LD} -o ${.TARGET} -r --whole-archive ${.ALLSRC}
-
-# We can't put openpam_static.c in SRCS, but we still want to scan it
-# for dependencies.
-DPSRCS= openpam_static.c
-
# Headers
INCS= ${HEADERS} ${ADD_HEADERS}
INCSDIR= ${INCLUDEDIR}/security
+.include <src.opts.mk>
+
.if ${MK_TESTS} != "no"
SUBDIR+= tests
.endif
Index: lib/libpam/static_modules/Makefile
===================================================================
--- lib/libpam/static_modules/Makefile
+++ lib/libpam/static_modules/Makefile
@@ -1,5 +1,5 @@
#-
-# Copyright (c) 1998 Juniper Networks, Inc.
+# Copyright (c) 1998-2015 Juniper Networks, Inc.
# All rights reserved.
# Copyright (c) 2002 Networks Associates Technology, Inc.
# All rights reserved.
@@ -35,143 +35,16 @@
#
# $FreeBSD$
-OPENPAM= ${.CURDIR}/../../../contrib/openpam
-.PATH: ${OPENPAM}/include ${OPENPAM}/lib/libpam ${OPENPAM}/doc/man
+OPENPAM= ${.CURDIR:H:H:H}/contrib/openpam
+.PATH: ${OPENPAM}/lib
+.PATH: ${OPENPAM}/lib/libpam
-LIB= pam
-MK_PROFILE=no
+all:
-SRCS= openpam_asprintf.c \
- openpam_borrow_cred.c \
- openpam_check_owner_perms.c \
- openpam_configure.c \
- openpam_constants.c \
- openpam_dispatch.c \
- openpam_dynamic.c \
- openpam_features.c \
- openpam_findenv.c \
- openpam_free_data.c \
- openpam_free_envlist.c \
- openpam_get_feature.c \
- openpam_get_option.c \
- openpam_load.c \
- openpam_log.c \
- openpam_nullconv.c \
- openpam_readline.c \
- openpam_readlinev.c \
- openpam_readword.c \
- openpam_restore_cred.c \
- openpam_set_feature.c \
- openpam_set_option.c \
- openpam_straddch.c \
- openpam_strlcat.c \
- openpam_strlcpy.c \
- openpam_strlset.c \
- openpam_subst.c \
- openpam_ttyconv.c \
- openpam_vasprintf.c \
- pam_acct_mgmt.c \
- pam_authenticate.c \
- pam_chauthtok.c \
- pam_close_session.c \
- pam_end.c \
- pam_error.c \
- pam_get_authtok.c \
- pam_get_data.c \
- pam_get_item.c \
- pam_get_user.c \
- pam_getenv.c \
- pam_getenvlist.c \
- pam_info.c \
- pam_open_session.c \
- pam_prompt.c \
- pam_putenv.c \
- pam_set_data.c \
- pam_set_item.c \
- pam_setcred.c \
- pam_setenv.c \
- pam_start.c \
- pam_strerror.c \
- pam_verror.c \
- pam_vinfo.c \
- pam_vprompt.c
-# Local additions
-SRCS+= pam_debug_log.c
+SRCS = openpam_static.c
-MAN= openpam.3 \
- openpam_borrow_cred.3 \
- openpam_free_data.3 \
- openpam_free_envlist.3 \
- openpam_get_feature.3 \
- openpam_get_option.3 \
- openpam_log.3 \
- openpam_nullconv.3 \
- openpam_readline.3 \
- openpam_readlinev.3 \
- openpam_readword.3 \
- openpam_restore_cred.3 \
- openpam_set_feature.3 \
- openpam_set_option.3 \
- openpam_straddch.3 \
- openpam_subst.3 \
- openpam_ttyconv.3 \
- pam.3 \
- pam_acct_mgmt.3 \
- pam_authenticate.3 \
- pam_chauthtok.3 \
- pam_close_session.3 \
- pam_conv.3 \
- pam_end.3 \
- pam_error.3 \
- pam_get_authtok.3 \
- pam_get_data.3 \
- pam_get_item.3 \
- pam_get_user.3 \
- pam_getenv.3 \
- pam_getenvlist.3 \
- pam_info.3 \
- pam_open_session.3 \
- pam_prompt.3 \
- pam_putenv.3 \
- pam_set_data.3 \
- pam_set_item.3 \
- pam_setcred.3 \
- pam_setenv.3 \
- pam_sm_acct_mgmt.3 \
- pam_sm_authenticate.3 \
- pam_sm_chauthtok.3 \
- pam_sm_close_session.3 \
- pam_sm_open_session.3 \
- pam_sm_setcred.3 \
- pam_start.3 \
- pam_strerror.3 \
- pam_verror.3 \
- pam_vinfo.3 \
- pam_vprompt.3 \
- pam.conf.5
+MAN=
-MLINKS= pam.conf.5 pam.d.5
-
-CSTD?= c99
-CFLAGS+= -I${.CURDIR} -I${OPENPAM}/include
-CFLAGS+= -DLIB_MAJ=${SHLIB_MAJOR}
-CFLAGS+= -DOPENPAM_MODULES_DIRECTORY='"${PAM_MOD_DIR:C/\/*$//}/"'
-CFLAGS+= -DHAVE_DLFUNC=1
-CFLAGS+= -DHAVE_FDLOPEN=1
-CFLAGS+= -DHAVE_FPURGE=1
-CFLAGS+= -DHAVE_STRLCAT=1
-CFLAGS+= -DHAVE_STRLCPY=1
-
-HEADERS= security/openpam.h \
- security/openpam_attr.h \
- security/openpam_version.h \
- security/pam_appl.h \
- security/pam_constants.h \
- security/pam_modules.h \
- security/pam_types.h \
-
-ADD_HEADERS= security/pam_mod_misc.h
-
#
# Static modules
#
@@ -188,19 +61,11 @@
CLEANFILES+= openpam_static.o \
openpam_static_modules.o
+.include <bsd.prog.mk>
+
+.if empty(_SKIP_BUILD)
openpam_static_modules.o: openpam_static.o ${STATIC_MODULES}
${LD} -o ${.TARGET} -r --whole-archive ${.ALLSRC}
-# We can't put openpam_static.c in SRCS, but we still want to scan it
-# for dependencies.
-DPSRCS= openpam_static.c
-
-# Headers
-INCS= ${HEADERS} ${ADD_HEADERS}
-INCSDIR= ${INCLUDEDIR}/security
-
-.if ${MK_TESTS} != "no"
-SUBDIR+= tests
+all: ${STATICOBJS}
.endif
-
-.include <bsd.lib.mk>
Index: lib/libproc/Makefile
===================================================================
--- lib/libproc/Makefile
+++ lib/libproc/Makefile
@@ -14,6 +14,9 @@
INCS= libproc.h
CFLAGS+= -I${.CURDIR}
+# avoid cyclic dependency
+CFLAGS+= -I${.CURDIR:H}/librtld_db
+GENDIRDEPS_FILTER+= Nlib/librtld_db
.if ${MK_CXX} == "no"
CFLAGS+= -DNO_CXA_DEMANGLE
Index: lib/libtelnet/Makefile
===================================================================
--- lib/libtelnet/Makefile
+++ lib/libtelnet/Makefile
@@ -26,7 +26,4 @@
CFLAGS+= -DFORWARD -Dnet_write=telnet_net_write
.endif
-INCS= ${TELNETDIR}/arpa/telnet.h
-INCSDIR= ${INCLUDEDIR}/arpa
-
.include <bsd.lib.mk>
Index: lib/ncurses/ncurses/Makefile
===================================================================
--- lib/ncurses/ncurses/Makefile
+++ lib/ncurses/ncurses/Makefile
@@ -308,6 +308,7 @@
SYMLINKS+= libncurses${LIB_SUFFIX}_p.a ${LIBDIR}/libtinfo${LIB_SUFFIX}_p.a
.endif
+.if ${.CURDIR:T} == "ncurses"
.if defined(ENABLE_WIDEC)
DOCSDIR= ${SHAREDIR}/doc/ncurses
DOCS= ncurses-intro.html hackguide.html
@@ -317,6 +318,7 @@
.PATH: ${NCURSES_DIR}/doc/html
FILESGROUPS= DOCS
.endif
+.endif
# Generated source
.ORDER: names.c codes.c
Index: share/i18n/csmapper/Makefile.inc
===================================================================
--- share/i18n/csmapper/Makefile.inc
+++ share/i18n/csmapper/Makefile.inc
@@ -1,4 +1,9 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
CSMAPPERDIR?= /usr/share/i18n/csmapper
+.if ${MK_STAGING} == "yes"
+MKCSMAPPER= ${STAGE_HOST_OBJTOP}/usr/bin/mkcsmapper_static
+.endif
MKCSMAPPER?= ${.OBJDIR}/../../../usr.bin/mkcsmapper_static/mkcsmapper_static
Index: share/i18n/esdb/Makefile.inc
===================================================================
--- share/i18n/esdb/Makefile.inc
+++ share/i18n/esdb/Makefile.inc
@@ -1,6 +1,11 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
.PATH: ${.CURDIR}
ESDBDIR?= /usr/share/i18n/esdb
+.if ${MK_STAGING} == "yes"
+MKESDB= ${STAGE_HOST_OBJTOP}/usr/bin/mkesdb_static
+.endif
MKESDB?= ${.OBJDIR}/../../../usr.bin/mkesdb_static/mkesdb_static
Index: share/mk/Makefile
===================================================================
--- share/mk/Makefile
+++ share/mk/Makefile
@@ -4,6 +4,7 @@
.include <src.opts.mk>
FILES= \
+ auto.obj.mk \
bsd.README \
bsd.arch.inc.mk \
bsd.compiler.mk \
@@ -39,7 +40,16 @@
bsd.symver.mk \
bsd.sys.mk \
bsd.test.mk \
+ dirdeps.mk \
+ gendirdeps.mk \
+ install-new.mk \
+ meta.autodep.mk \
+ meta.stage.mk \
+ meta.subdir.mk \
+ meta.sys.mk \
+ stage-install.sh \
sys.mk \
+ sys.dependfile.mk \
version_gen.awk
NO_OBJ=
Index: share/mk/auto.obj.mk
===================================================================
--- share/mk/auto.obj.mk
+++ share/mk/auto.obj.mk
@@ -0,0 +1,64 @@
+# $Id: auto.obj.mk,v 1.10 2015/04/16 16:59:00 sjg Exp $
+#
+# @(#) Copyright (c) 2004, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+ECHO_TRACE ?= echo
+
+.ifndef Mkdirs
+# A race condition in some versions of mkdir, means that it can bail
+# if another process made a dir that mkdir expected to.
+# We repeat the mkdir -p a number of times to try and work around this.
+# We stop looping as soon as the dir exists.
+# If we get to the end of the loop, a plain mkdir will issue an error.
+Mkdirs= Mkdirs() { \
+ for d in $$*; do \
+ for i in 1 2 3 4 5 6; do \
+ mkdir -p $$d; \
+ test -d $$d && return 0; \
+ done > /dev/null 2>&1; \
+ mkdir $$d || exit $$?; \
+ done; }
+.endif
+
+# if MKOBJDIRS is set to auto (and NOOBJ isn't defined) do some magic...
+# This will automatically create objdirs as needed.
+# Skip it if we are just doing 'clean'.
+.if ${MK_AUTO_OBJ:Uno} == "yes"
+MKOBJDIRS= auto
+.endif
+.if !defined(NOOBJ) && !defined(NO_OBJ) && ${MKOBJDIRS:Uno} == auto
+# Use __objdir here so it is easier to tweak without impacting
+# the logic.
+.if !empty(MAKEOBJDIRPREFIX) && exists(${MAKEOBJDIRPREFIX})
+__objdir?= ${MAKEOBJDIRPREFIX}${.CURDIR}
+.endif
+__objdir?= ${MAKEOBJDIR:Uobj}
+__objdir:= ${__objdir:tA}
+.if ${.OBJDIR} != ${__objdir}
+# We need to chdir, make the directory if needed
+.if !exists(${__objdir}/) && \
+ (${.TARGETS} == "" || ${.TARGETS:Nclean*:N*clean:Ndestroy*} != "")
+# This will actually make it...
+__objdir_made != echo ${__objdir}/; umask ${OBJDIR_UMASK:U002}; \
+ ${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \
+ ${Mkdirs}; Mkdirs ${__objdir}
+__objdir:= ${__objdir:tA}
+.endif
+# This causes make to use the specified directory as .OBJDIR
+.OBJDIR: ${__objdir}
+.if ${.OBJDIR} != ${__objdir} && ${__objdir_made:Uno:M${__objdir}/*} != ""
+.error could not use ${__objdir}: .OBJDIR=${.OBJDIR}
+.endif
+.endif
+.endif
Index: share/mk/bsd.compiler.mk
===================================================================
--- share/mk/bsd.compiler.mk
+++ share/mk/bsd.compiler.mk
@@ -25,8 +25,14 @@
.if !target(__<bsd.compiler.mk>__)
__<bsd.compiler.mk>__:
-.if !defined(COMPILER_TYPE) || !defined(COMPILER_VERSION)
+.if ${MACHINE} == "common"
+# common is a pseudo machine for architecture independent
+# generated files - thus there is no compiler.
+COMPILER_TYPE= none
+COMPILER_VERSION= 0
+.elif !defined(COMPILER_TYPE) || !defined(COMPILER_VERSION)
_v!= ${CC} --version 2>/dev/null || echo 0.0.0
+
.if !defined(COMPILER_TYPE)
. if ${CC:T:M*gcc*}
COMPILER_TYPE:= gcc
Index: share/mk/bsd.dep.mk
===================================================================
--- share/mk/bsd.dep.mk
+++ share/mk/bsd.dep.mk
@@ -147,6 +147,15 @@
beforebuild: ${DHDRS}
.endif
+.if ${MK_META_MODE} == "yes"
+.include <meta.autodep.mk>
+# this depend: bypasses that below
+# the dependency helps when bootstrapping
+depend: beforedepend ${DPSRCS} ${SRCS} afterdepend
+beforedepend:
+afterdepend: beforedepend
+.endif
+
.if !target(depend)
.if defined(SRCS)
depend: beforedepend ${DEPENDFILE} afterdepend
Index: share/mk/bsd.files.mk
===================================================================
--- share/mk/bsd.files.mk
+++ share/mk/bsd.files.mk
@@ -23,6 +23,11 @@
${group}GRP?= ${SHAREGRP}
${group}MODE?= ${SHAREMODE}
${group}DIR?= ${BINDIR}
+.if !make(buildincludes)
+STAGE_SETS+= ${group}
+.endif
+STAGE_DIR.${group}= ${STAGE_OBJTOP}${${group}DIR}
+STAGE_SYMLINKS_DIR.${group}= ${STAGE_OBJTOP}
_${group}FILES=
.for file in ${${group}}
@@ -38,6 +43,12 @@
.else
${group}NAME_${file:T}?= ${file:T}
.endif
+.if !make(buildincludes)
+STAGE_AS_SETS+= ${group}
+.endif
+STAGE_AS_${file:T}= ${${group}NAME_${file:T}}
+stage_as.${group}: ${file}
+
installfiles-${group}: _${group}INS_${file:T}
_${group}INS_${file:T}: ${file}
${INSTALL} -o ${${group}OWN_${.ALLSRC:T}} \
@@ -49,6 +60,8 @@
.endif
.endfor
.if !empty(_${group}FILES)
+stage_files.${group}: ${_${group}FILES}
+
installfiles-${group}: _${group}INS
_${group}INS: ${_${group}FILES}
.if defined(${group}NAME)
@@ -67,4 +80,13 @@
realinstall: installfiles
.ORDER: beforeinstall installfiles
+.if ${MK_STAGING} != "no"
+.if !empty(STAGE_SETS)
+buildfiles: stage_files
+.if !empty(STAGE_AS_SETS)
+buildfiles: stage_as
+.endif
+.endif
+.endif
+
.endif # !target(__<bsd.files.mk>__)
Index: share/mk/bsd.incs.mk
===================================================================
--- share/mk/bsd.incs.mk
+++ share/mk/bsd.incs.mk
@@ -24,12 +24,15 @@
${group}GRP?= ${BINGRP}
${group}MODE?= ${NOBINMODE}
${group}DIR?= ${INCLUDEDIR}${PRIVATELIB:D/private/${LIB}}
+STAGE_SETS+= ${group}
+STAGE_DIR.${group}= ${STAGE_OBJTOP}${${group}DIR}
+STAGE_SYMLINKS_DIR.${group}= ${STAGE_OBJTOP}
_${group}INCS=
.for header in ${${group}}
.if defined(${group}OWN_${header:T}) || defined(${group}GRP_${header:T}) || \
defined(${group}MODE_${header:T}) || defined(${group}DIR_${header:T}) || \
- defined(${group}NAME_${header:T})
+ defined(${group}NAME_${header:T}) || defined(${group}NAME)
${group}OWN_${header:T}?= ${${group}OWN}
${group}GRP_${header:T}?= ${${group}GRP}
${group}MODE_${header:T}?= ${${group}MODE}
@@ -39,6 +42,11 @@
.else
${group}NAME_${header:T}?= ${header:T}
.endif
+STAGE_AS_SETS+= ${group}
+STAGE_AS_${header:T}= ${${group}NAME_${header:T}}
+stage_as.${group}: ${header}
+stage_includes: stage_as.${group}
+
installincludes: _${group}INS_${header:T}
_${group}INS_${header:T}: ${header}
${INSTALL} -C -o ${${group}OWN_${.ALLSRC:T}} \
@@ -50,6 +58,9 @@
.endif
.endfor
.if !empty(_${group}INCS)
+stage_files.${group}: ${_${group}INCS}
+stage_includes: stage_files.${group}
+
installincludes: _${group}INS
_${group}INS: ${_${group}INCS}
.if defined(${group}NAME)
@@ -81,4 +92,14 @@
realinstall: installincludes
.ORDER: beforeinstall installincludes
+.if ${MK_STAGING} != "no" && !defined(_SKIP_BUILD)
+.if !defined(NO_STAGE_INCLUDES)
+staging: stage_includes
+.if !empty(INCSLINKS)
+staging: stage_symlinks
+STAGE_SYMLINKS.INCS= ${INCSLINKS}
+.endif
+.endif
+.endif
+
.endif # ${MK_TOOLCHAIN} != "no"
Index: share/mk/bsd.init.mk
===================================================================
--- share/mk/bsd.init.mk
+++ share/mk/bsd.init.mk
@@ -9,9 +9,19 @@
.if !target(__<bsd.init.mk>__)
__<bsd.init.mk>__:
.include <bsd.opts.mk>
+.-include "local.init.mk"
.if exists(${.CURDIR}/../Makefile.inc)
.include "${.CURDIR}/../Makefile.inc"
.endif
.include <bsd.own.mk>
.MAIN: all
+
+.if ${.MAKE.LEVEL:U1} == 0 && ${BUILD_AT_LEVEL0:Uyes:tl} == "no" && !make(clean*)
+# this tells lib.mk and prog.mk to not actually build anything
+_SKIP_BUILD = not building at level 0
+.endif
+.if !empty(_SKIP_BUILD)
+.warning ${_SKIP_BUILD}
+.endif
+
.endif # !target(__<bsd.init.mk>__)
Index: share/mk/bsd.lib.mk
===================================================================
--- share/mk/bsd.lib.mk
+++ share/mk/bsd.lib.mk
@@ -126,8 +126,10 @@
${CC} ${PICFLAG} -DPIC ${CFLAGS} ${ACFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
+.if !defined(_SKIP_BUILD)
all: beforebuild .WAIT
beforebuild: objwarn
+.endif
_LIBDIR:=${LIBDIR}
_SHLIBDIR:=${SHLIBDIR}
@@ -210,10 +212,40 @@
beforelinking: ${SOBJS}
${SHLIB_NAME_FULL}: beforelinking
.endif
+
+.if defined(SHLIB_LINK)
+# ${_SHLIBDIRPREFIX} and ${_LDSCRIPTROOT} are both needed when cross-building
+# and when building 32 bits library shims. ${_SHLIBDIRPREFIX} is the directory
+# prefix where shared objects will be installed by the install target.
+#
+# ${_LDSCRIPTROOT} is the directory prefix that will be used when generating
+# ld(1) scripts. The crosstools' ld is configured to lookup libraries in an
+# alternative directory which is called "sysroot", so during buildworld binaries
+# won't be linked against the running system libraries but against the ones of
+# the current source tree. ${_LDSCRIPTROOT} behavior is twisted because of
+# the location where we store them:
+# - 64 bits libs are located under sysroot, so ${_LDSCRIPTROOT} must be empty
+# because ld(1) will manage to find them from sysroot;
+# - 32 bits shims are not, so ${_LDSCRIPTROOT} is used to specify their full
+# path, outside of sysroot.
+# Note that ld(1) scripts are generated both during buildworld and
+# installworld; in the later case ${_LDSCRIPTROOT} must be obviously empty
+# because on the target system, libraries are meant to be looked up from /.
+.if defined(SHLIB_LDSCRIPT) && !empty(SHLIB_LDSCRIPT) && exists(${.CURDIR}/${SHLIB_LDSCRIPT})
+${SHLIB_LINK:R}.ld: ${.CURDIR}/${SHLIB_LDSCRIPT}
+ sed -e 's,@@SHLIB@@,${_LDSCRIPTROOT}${_SHLIBDIR}/${SHLIB_NAME},g' \
+ -e 's,@@LIBDIR@@,${_LDSCRIPTROOT}${_LIBDIR},g' \
+ -e 's,/[^ ]*/,,g' \
+ ${.ALLSRC} > ${.TARGET}
+
+${SHLIB_NAME_FULL}: ${SHLIB_LINK:R}.ld
+.endif
+.endif
+
${SHLIB_NAME_FULL}: ${SOBJS}
@${ECHO} building shared library ${SHLIB_NAME}
@rm -f ${SHLIB_NAME} ${SHLIB_LINK}
-.if defined(SHLIB_LINK)
+.if defined(SHLIB_LINK) && !commands(${SHLIB_LINK:R}.ld)
@${INSTALL_SYMLINK} ${SHLIB_NAME} ${SHLIB_LINK}
.endif
${_LD} ${LDFLAGS} ${SSP_CFLAGS} ${SOLINKOPTS} \
@@ -258,11 +290,15 @@
.endif # !defined(INTERNALLIB)
+.if defined(_SKIP_BUILD)
+all:
+.else
all: ${_LIBS}
.if ${MK_MAN} != "no"
all: _manpages
.endif
+.endif
_EXTRADEPEND:
@TMP=_depend$$$$; \
@@ -318,32 +354,10 @@
${SHLIB_NAME}.debug ${DESTDIR}${DEBUGFILEDIR}
.endif
.if defined(SHLIB_LINK)
-# ${_SHLIBDIRPREFIX} and ${_LDSCRIPTROOT} are both needed when cross-building
-# and when building 32 bits library shims. ${_SHLIBDIRPREFIX} is the directory
-# prefix where shared objects will be installed by the install target.
-#
-# ${_LDSCRIPTROOT} is the directory prefix that will be used when generating
-# ld(1) scripts. The crosstools' ld is configured to lookup libraries in an
-# alternative directory which is called "sysroot", so during buildworld binaries
-# won't be linked against the running system libraries but against the ones of
-# the current source tree. ${_LDSCRIPTROOT} behavior is twisted because of
-# the location where we store them:
-# - 64 bits libs are located under sysroot, so ${_LDSCRIPTROOT} must be empty
-# because ld(1) will manage to find them from sysroot;
-# - 32 bits shims are not, so ${_LDSCRIPTROOT} is used to specify their full
-# path, outside of sysroot.
-# Note that ld(1) scripts are generated both during buildworld and
-# installworld; in the later case ${_LDSCRIPTROOT} must be obviously empty
-# because on the target system, libraries are meant to be looked up from /.
-.if defined(SHLIB_LDSCRIPT) && !empty(SHLIB_LDSCRIPT) && exists(${.CURDIR}/${SHLIB_LDSCRIPT})
- sed -e 's,@@SHLIB@@,${_LDSCRIPTROOT}${_SHLIBDIR}/${SHLIB_NAME},g' \
- -e 's,@@LIBDIR@@,${_LDSCRIPTROOT}${_LIBDIR},g' \
- ${.CURDIR}/${SHLIB_LDSCRIPT} > ${DESTDIR}${_LIBDIR}/${SHLIB_LINK:R}.ld
+.if commands(${SHLIB_LINK:R}.ld)
${INSTALL} -S -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
- ${_INSTALLFLAGS} ${DESTDIR}${_LIBDIR}/${SHLIB_LINK:R}.ld \
+ ${_INSTALLFLAGS} ${SHLIB_LINK:R}.ld \
${DESTDIR}${_LIBDIR}/${SHLIB_LINK}
- rm -f ${DESTDIR}${_LIBDIR}/${SHLIB_LINK:R}.ld
-
.else
.if ${_SHLIBDIR} == ${_LIBDIR}
${INSTALL_SYMLINK} ${SHLIB_NAME} ${DESTDIR}${_LIBDIR}/${SHLIB_LINK}
Index: share/mk/bsd.man.mk
===================================================================
--- share/mk/bsd.man.mk
+++ share/mk/bsd.man.mk
@@ -127,6 +127,22 @@
ZEXT= ${MCOMPRESS_EXT}
.if defined(MAN) && !empty(MAN)
+.if ${MK_STAGING_MAN} == "yes"
+staging: stage_files
+_mansets:= ${MAN:E:O:u:M*[1-9]:@s@man$s@}
+STAGE_SETS+= ${_mansets}
+.for _page in ${MAN}
+stage_files.man${_page:T:E}: ${_page}
+STAGE_DIR.man${_page:T:E}?= ${STAGE_OBJTOP}${MANDIR}${_page:T:E}${MANSUBDIR}
+.endfor
+.if !empty(MLINKS)
+STAGE_SETS+= mlinks
+staging: stage_links
+STAGE_LINKS.mlinks:= ${MLINKS:@f@${f:S,^,${MANDIR}${f:E}${MANSUBDIR}/,}@}
+stage_links.mlinks: ${_mansets:@s@stage_files.$s@}
+.endif
+.endif
+
CLEANFILES+= ${MAN:T:S/$/${MCOMPRESS_EXT}/g}
CLEANFILES+= ${MAN:T:S/$/${CATEXT}${MCOMPRESS_EXT}/g}
.for __page in ${MAN}
Index: share/mk/bsd.nls.mk
===================================================================
--- share/mk/bsd.nls.mk
+++ share/mk/bsd.nls.mk
@@ -61,6 +61,15 @@
#
# installation rules
#
+.if ${MK_STAGING_PROG} == "yes"
+.if !defined(_SKIP_BUILD)
+staging: stage_symlinks
+.endif
+STAGE_SYMLINKS.NLS= ${NLSSYMLINKS}
+STAGE_SYMLINKS_DIR.NLS= ${STAGE_OBJTOP}
+.else
+SYMLINKS+= ${NLSSYMLINKS}
+.endif
.for file in ${NLS}
NLSNAME_${file:T}= ${file:T:R}/${NLSNAME}.cat
.if defined(NLSLINKS_${file:R}) && !empty(NLSLINKS_${file:R})
@@ -67,7 +76,7 @@
NLSLINKS+= ${file:R}
.endif
.for dst in ${NLSLINKS_${file:R}}
-SYMLINKS+= ../${file:R}/${NLSNAME}.cat ${NLSDIR}/${dst}/${NLSNAME}.cat
+NLSSYMLINKS+= ../${file:R}/${NLSNAME}.cat ${NLSDIR}/${dst}/${NLSNAME}.cat
.endfor
.endfor
Index: share/mk/bsd.obj.mk
===================================================================
--- share/mk/bsd.obj.mk
+++ share/mk/bsd.obj.mk
@@ -42,7 +42,16 @@
__<bsd.obj.mk>__:
.include <bsd.own.mk>
-.if defined(MAKEOBJDIRPREFIX)
+.if ${MK_AUTO_OBJ} == "yes"
+# it is done by now
+objwarn:
+obj:
+CANONICALOBJDIR= ${.OBJDIR}
+.if defined(NO_OBJ)
+# but this makefile does not want it!
+.OBJDIR: ${.CURDIR}
+.endif
+.elif defined(MAKEOBJDIRPREFIX)
CANONICALOBJDIR:=${MAKEOBJDIRPREFIX}${.CURDIR}
.elif defined(MAKEOBJDIR) && ${MAKEOBJDIR:M/*} != ""
CANONICALOBJDIR:=${MAKEOBJDIR}
@@ -148,4 +157,51 @@
.include <bsd.subdir.mk>
+.if make(destroy*) && defined(OBJROOT)
+# this (rm -rf objdir) is much faster and more reliable than cleaning.
+
+# just in case we are playing games with these...
+_OBJDIR?= ${.OBJDIR}
+_CURDIR?= ${.CURDIR}
+
+# destroy almost everything
+destroy: destroy-all
+destroy-all:
+
+# just remove our objdir
+destroy-arch: .NOMETA
+.if ${_OBJDIR} != ${_CURDIR}
+ cd ${_CURDIR} && rm -rf ${_OBJDIR}
+.endif
+
+.if defined(HOST_OBJTOP)
+destroy-host: destroy.host
+destroy.host: .NOMETA
+ cd ${_CURDIR} && rm -rf ${HOST_OBJTOP}/${RELDIR:N.}
+.endif
+
+.if make(destroy-all) && ${RELDIR} == "."
+destroy-all: destroy-stage
+.endif
+
+# remove the stage tree
+destroy-stage: .NOMETA
+.if defined(STAGE_ROOT)
+ cd ${_CURDIR} && rm -rf ${STAGE_ROOT}
+.endif
+
+# allow parallel destruction
+_destroy_machine_list = common host ${ALL_MACHINE_LIST}
+.for m in ${_destroy_machine_list:O:u}
+destroy-all: destroy.$m
+.if !target(destroy.$m)
+destroy.$m: .NOMETA
+.if ${_OBJDIR} != ${_CURDIR}
+ cd ${_CURDIR} && rm -rf ${OBJROOT}$m*/${RELDIR:N.}
+.endif
+.endif
+.endfor
+
+.endif
+
.endif # !target(__<bsd.obj.mk>__)
Index: share/mk/bsd.opts.mk
===================================================================
--- share/mk/bsd.opts.mk
+++ share/mk/bsd.opts.mk
@@ -68,8 +68,14 @@
__DEFAULT_NO_OPTIONS = \
CTF \
DEBUG_FILES \
- INSTALL_AS_USER
+ INSTALL_AS_USER \
+ STALE_STAGED
+# meta mode related
+__DEFAULT_DEPENDENT_OPTIONS = \
+ STAGING_MAN/STAGING \
+ STAGING_PROG/STAGING \
+
.include <bsd.mkopt.mk>
#
@@ -92,6 +98,10 @@
.endif
.endfor
+.if ${MK_STAGING} == "no"
+MK_STALE_STAGED= no
+.endif
+
.endif # !_WITHOUT_SRCCONF
.endif
Index: share/mk/bsd.own.mk
===================================================================
--- share/mk/bsd.own.mk
+++ share/mk/bsd.own.mk
@@ -140,7 +140,7 @@
.if !defined(USER)
USER!= id -un
.endif
-_gid!= id -gn
+_gid!= id -g
.for x in BIN CONF DOC DTB INFO KMOD LIB MAN NLS SHARE
$xOWN= ${USER}
$xGRP= ${_gid}
Index: share/mk/bsd.prog.mk
===================================================================
--- share/mk/bsd.prog.mk
+++ share/mk/bsd.prog.mk
@@ -141,11 +141,15 @@
.endif
.endif # defined(PROG)
+.if defined(_SKIP_BUILD)
+all:
+.else
all: beforebuild .WAIT ${PROG} ${SCRIPTS}
beforebuild: objwarn
.if ${MK_MAN} != "no"
all: _manpages
.endif
+.endif
.if defined(PROG)
CLEANFILES+= ${PROG}
@@ -218,6 +222,10 @@
SCRIPTSGRP?= ${BINGRP}
SCRIPTSMODE?= ${BINMODE}
+STAGE_AS_SETS+= scripts
+stage_as.scripts: ${SCRIPTS}
+FLAGS.stage_as.scripts= -m ${SCRIPTSMODE}
+STAGE_FILES_DIR.scripts= ${STAGE_OBJTOP}
.for script in ${SCRIPTS}
.if defined(SCRIPTSNAME)
SCRIPTSNAME_${script:T}?= ${SCRIPTSNAME}
@@ -228,6 +236,7 @@
SCRIPTSOWN_${script:T}?= ${SCRIPTSOWN}
SCRIPTSGRP_${script:T}?= ${SCRIPTSGRP}
SCRIPTSMODE_${script:T}?= ${SCRIPTSMODE}
+STAGE_AS_${script:T}= ${SCRIPTSDIR_${script:T}}/${SCRIPTSNAME_${script:T}}
_scriptsinstall: _SCRIPTSINS_${script:T}
_SCRIPTSINS_${script:T}: ${script}
${INSTALL} -o ${SCRIPTSOWN_${.ALLSRC:T}} \
Index: share/mk/bsd.subdir.mk
===================================================================
--- share/mk/bsd.subdir.mk
+++ share/mk/bsd.subdir.mk
@@ -34,6 +34,15 @@
.include <bsd.init.mk>
+.if !defined(NEED_SUBDIR)
+.if ${.MAKE.LEVEL} == 0 && ${MK_META_MODE} == "yes" && !empty(SUBDIR) && !(make(clean*) || make(destroy*))
+.include <meta.subdir.mk>
+# ignore this
+_SUBDIR:
+.endif
+.endif
+.if !target(_SUBDIR)
+
DISTRIBUTION?= base
.if !target(distribute)
distribute: .MAKE
@@ -122,6 +131,8 @@
.endif
.endfor
+.endif
+
.if !target(install)
.if !target(beforeinstall)
beforeinstall:
Index: share/mk/bsd.sys.mk
===================================================================
--- share/mk/bsd.sys.mk
+++ share/mk/bsd.sys.mk
@@ -173,5 +173,113 @@
realinstall regress subdir-all subdir-depend subdir-install \
tags whereobj
-.PHONY: ${PHONY_NOTMAIN}
-.NOTMAIN: ${PHONY_NOTMAIN}
+# we don't want ${PROG} to be PHONY
+.PHONY: ${PHONY_NOTMAIN:N${PROG:U}}
+.NOTMAIN: ${PHONY_NOTMAIN:Nall}
+
+.if ${MK_STAGING} != "no"
+.if defined(_SKIP_BUILD) || (!make(all) && !make(clean*))
+_SKIP_STAGING?= yes
+.endif
+.if ${_SKIP_STAGING:Uno} == "yes"
+staging stage_libs stage_files stage_as stage_links stage_symlinks:
+.else
+# allow targets like beforeinstall to be leveraged
+DESTDIR= ${STAGE_OBJTOP}
+_SHLIBDIRPREFIX= ${STAGE_OBJTOP}
+
+.if commands(beforeinstall)
+.if !empty(_LIBS) || ${MK_STAGING_PROG} != "no"
+staging: beforeinstall
+.endif
+.endif
+
+# normally only libs and includes are staged
+.if ${MK_STAGING_PROG} != "no"
+STAGE_DIR.prog= ${STAGE_OBJTOP}${BINDIR}
+
+.if !empty(PROG) || !empty(PROGS)
+.if defined(PROGNAME)
+STAGE_AS_SETS+= prog
+STAGE_AS_${PROG}= ${PROGNAME}
+stage_as.prog: ${PROG}
+.else
+STAGE_SETS+= prog
+stage_files.prog: ${PROG}
+staging: stage_files
+.endif
+.endif
+.endif
+
+.if !empty(_LIBS) && !defined(INTERNALLIB)
+.if defined(SHLIBDIR) && ${SHLIBDIR} != ${LIBDIR} && ${_LIBS:Uno:M*.so.*} != ""
+STAGE_SETS+= shlib
+STAGE_DIR.shlib= ${STAGE_OBJTOP}${SHLIBDIR}
+STAGE_FILES.shlib+= ${_LIBS:M*.so.*}
+stage_files.shlib: ${_LIBS:M*.so.*}
+.endif
+
+.if defined(SHLIB_LINK) && commands(${SHLIB_LINK:R}.ld)
+_LDSCRIPTROOT?= ${STAGE_OBJTOP}
+STAGE_AS_SETS+= ldscript
+STAGE_AS.ldscript+= ${SHLIB_LINK:R}.ld
+stage_as.ldscript: ${SHLIB_LINK:R}.ld
+STAGE_DIR.ldscript = ${STAGE_LIBDIR}
+STAGE_AS_${SHLIB_LINK:R}.ld:= ${SHLIB_LINK}
+NO_SHLIB_LINKS=
+.endif
+
+.if target(stage_files.shlib)
+stage_libs: ${_LIBS}
+.if defined(DEBUG_FLAGS) && target(${SHLIB_NAME}.symbols)
+stage_files.shlib: ${SHLIB_NAME}.symbols
+.endif
+.else
+stage_libs: ${_LIBS}
+.endif
+.if defined(SHLIB_NAME) && defined(DEBUG_FLAGS) && target(${SHLIB_NAME}.symbols)
+stage_libs: ${SHLIB_NAME}.symbols
+.endif
+
+.endif
+
+.if !empty(INCS) || !empty(INCSGROUPS) && target(buildincludes)
+.if !defined(NO_BEFOREBUILD_INCLUDES)
+stage_includes: buildincludes
+beforebuild: stage_includes
+.endif
+.endif
+
+.for t in stage_libs stage_files stage_as
+.if target($t)
+staging: $t
+.endif
+.endfor
+
+.if !empty(STAGE_AS_SETS)
+staging: stage_as
+.endif
+
+.if !empty(_LIBS) || ${MK_STAGING_PROG} != "no"
+
+.if !empty(LINKS)
+staging: stage_links
+.if ${MAKE_VERSION} < 20131001
+stage_links.links: ${_LIBS} ${PROG}
+.endif
+STAGE_SETS+= links
+STAGE_LINKS.links= ${LINKS}
+.endif
+
+.if !empty(SYMLINKS)
+staging: stage_symlinks
+STAGE_SETS+= links
+STAGE_SYMLINKS.links= ${SYMLINKS}
+.endif
+
+.endif
+
+.include <meta.stage.mk>
+.endif
+.endif
+
Index: share/mk/bsd.test.mk
===================================================================
--- share/mk/bsd.test.mk
+++ share/mk/bsd.test.mk
@@ -91,9 +91,30 @@
.include <bsd.subdir.mk>
.endif
+.ifdef PROG
+# we came here via bsd.progs.mk below
+# parent will do staging.
+MK_STAGING= no
+.endif
+
.if !empty(PROGS) || !empty(PROGS_CXX) || !empty(SCRIPTS)
.include <bsd.progs.mk>
.endif
.include <bsd.files.mk>
+.if !defined(PROG) && ${MK_STAGING} != "no"
+.if !defined(_SKIP_BUILD)
+# this will handle staging if needed
+_SKIP_STAGING= no
+# but we don't want it to build anything
+_SKIP_BUILD=
+.endif
+.if !empty(PROGS)
+stage_files.prog: ${PROGS}
+.endif
+.include <bsd.prog.mk>
+.endif
+
+.if !target(objwarn)
.include <bsd.obj.mk>
+.endif
Index: share/mk/dirdeps.mk
===================================================================
--- share/mk/dirdeps.mk
+++ share/mk/dirdeps.mk
@@ -0,0 +1,651 @@
+# $Id: dirdeps.mk,v 1.54 2015/06/08 20:55:11 sjg Exp $
+
+# Copyright (c) 2010-2013, Juniper Networks, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Much of the complexity here is for supporting cross-building.
+# If a tree does not support that, simply using plain Makefile.depend
+# should provide sufficient clue.
+# Otherwise the recommendation is to use Makefile.depend.${MACHINE}
+# as expected below.
+
+# Note: this file gets multiply included.
+# This is what we do with DIRDEPS
+
+# DIRDEPS:
+# This is a list of directories - relative to SRCTOP, it is
+# normally only of interest to .MAKE.LEVEL 0.
+# In some cases the entry may be qualified with a .<machine>
+# or .<target_spec> suffix (see TARGET_SPEC_VARS below),
+# for example to force building something for the pseudo
+# machines "host" or "common" regardless of current ${MACHINE}.
+#
+# All unqualified entries end up being qualified with .${TARGET_SPEC}
+# and partially qualified (if TARGET_SPEC_VARS has multiple
+# entries) are also expanded to a full .<target_spec>.
+# The _DIRDEP_USE target uses the suffix to set TARGET_SPEC
+# correctly when visiting each entry.
+#
+# The fully qualified directory entries are used to construct a
+# dependency graph that will drive the build later.
+#
+# Also, for each fully qualified directory target, we will search
+# using ${.MAKE.DEPENDFILE_PREFERENCE} to find additional
+# dependencies. We use Makefile.depend (default value for
+# .MAKE.DEPENDFILE_PREFIX) to refer to these makefiles to
+# distinguish them from others.
+#
+# Each Makefile.depend file sets DEP_RELDIR to be the
+# the RELDIR (path relative to SRCTOP) for its directory, and
+# since each Makefile.depend file includes dirdeps.mk, this
+# processing is recursive and results in .MAKE.LEVEL 0 learning the
+# dependencies of the tree wrt the initial directory (_DEP_RELDIR).
+#
+# BUILD_AT_LEVEL0
+# Indicates whether .MAKE.LEVEL 0 builds anything:
+# if "no" sub-makes are used to build everything,
+# if "yes" sub-makes are only used to build for other machines.
+# It is best to use "no", but this can require fixing some
+# makefiles to not do anything at .MAKE.LEVEL 0.
+#
+# TARGET_SPEC_VARS
+# The default value is just MACHINE, and for most environments
+# this is sufficient. The _DIRDEP_USE target actually sets
+# both MACHINE and TARGET_SPEC to the suffix of the current
+# target so that in the general case TARGET_SPEC can be ignored.
+#
+# If more than MACHINE is needed then sys.mk needs to decompose
+# TARGET_SPEC and set the relevant variables accordingly.
+# It is important that MACHINE be included in and actually be
+# the first member of TARGET_SPEC_VARS. This allows other
+# variables to be considered optional, and some of the treatment
+# below relies on MACHINE being the first entry.
+# Note: TARGET_SPEC cannot contain any '.'s so the target
+# triple used by compiler folk won't work (directly anyway).
+#
+# For example:
+#
+# # Always list MACHINE first,
+# # other variables might be optional.
+# TARGET_SPEC_VARS = MACHINE TARGET_OS
+# .if ${TARGET_SPEC:Uno:M*,*} != ""
+# _tspec := ${TARGET_SPEC:S/,/ /g}
+# MACHINE := ${_tspec:[1]}
+# TARGET_OS := ${_tspec:[2]}
+# # etc.
+# # We need to stop that TARGET_SPEC affecting any submakes
+# # and deal with MACHINE=${TARGET_SPEC} in the environment.
+# TARGET_SPEC =
+# # export but do not track
+# .export-env TARGET_SPEC
+# .export ${TARGET_SPEC_VARS}
+# .for v in ${TARGET_SPEC_VARS:O:u}
+# .if empty($v)
+# .undef $v
+# .endif
+# .endfor
+# .endif
+# # make sure we know what TARGET_SPEC is
+# # as we may need it to find Makefile.depend*
+# TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
+#
+
+# touch this at your peril
+_DIRDEP_USE_LEVEL?= 0
+.if ${.MAKE.LEVEL} == ${_DIRDEP_USE_LEVEL}
+# only the first instance is interested in all this
+
+# First off, we want to know what ${MACHINE} to build for.
+# This can be complicated if we are using a mixture of ${MACHINE} specific
+# and non-specific Makefile.depend*
+
+.if !target(_DIRDEP_USE)
+# do some setup we only need once
+_CURDIR ?= ${.CURDIR}
+_OBJDIR ?= ${.OBJDIR}
+
+now_utc = ${%s:L:gmtime}
+.if !defined(start_utc)
+start_utc := ${now_utc}
+.endif
+
+# make sure these are empty to start with
+_DEP_TARGET_SPEC =
+_DIRDEP_CHECKED =
+
+# If TARGET_SPEC_VARS is other than just MACHINE
+# it should be set by sys.mk or similar by now.
+# TARGET_SPEC must not contain any '.'s.
+TARGET_SPEC_VARS ?= MACHINE
+# this is what we started with
+TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
+# this is what we mostly use below
+DEP_TARGET_SPEC = ${TARGET_SPEC_VARS:S,^,DEP_,:@v@${$v:U}@:ts,}
+# make sure we have defaults
+.for v in ${TARGET_SPEC_VARS}
+DEP_$v ?= ${$v}
+.endfor
+
+.if ${TARGET_SPEC_VARS:[#]} > 1
+# Ok, this gets more complex (putting it mildly).
+# In order to stay sane, we need to ensure that all the build_dirs
+# we compute below are fully qualified wrt DEP_TARGET_SPEC.
+# The makefiles may only partially specify (eg. MACHINE only),
+# so we need to construct a set of modifiers to fill in the gaps.
+# jot 10 should output 1 2 3 .. 10
+JOT ?= jot
+_tspec_x := ${${JOT} ${TARGET_SPEC_VARS:[#]}:L:sh}
+# this handles unqualified entries
+M_dep_qual_fixes = C;(/[^/.,]+)$$;\1.$${DEP_TARGET_SPEC};
+# there needs to be at least one item missing for these to make sense
+.for i in ${_tspec_x:[2..-1]}
+_tspec_m$i := ${TARGET_SPEC_VARS:[2..$i]:@w@[^,]+@:ts,}
+_tspec_a$i := ,${TARGET_SPEC_VARS:[$i..-1]:@v@$$$${DEP_$v}@:ts,}
+M_dep_qual_fixes += C;(\.${_tspec_m$i})$$;\1${_tspec_a$i};
+.endfor
+.else
+# A harmless? default.
+M_dep_qual_fixes = U
+.endif
+
+.if !defined(.MAKE.DEPENDFILE_PREFERENCE)
+# .MAKE.DEPENDFILE_PREFERENCE makes the logic below neater?
+# you really want this set by sys.mk or similar
+.MAKE.DEPENDFILE_PREFERENCE = ${_CURDIR}/${.MAKE.DEPENDFILE:T}
+.if ${.MAKE.DEPENDFILE:E} == "${TARGET_SPEC}"
+.if ${TARGET_SPEC} != ${MACHINE}
+.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}.$${MACHINE}
+.endif
+.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}
+.endif
+.endif
+
+_default_dependfile := ${.MAKE.DEPENDFILE_PREFERENCE:[1]:T}
+_machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:T:M*${MACHINE}*}
+
+# for machine specific dependfiles we require ${MACHINE} to be at the end
+# also for the sake of sanity we require a common prefix
+.if !defined(.MAKE.DEPENDFILE_PREFIX)
+# knowing .MAKE.DEPENDFILE_PREFIX helps
+.if !empty(_machine_dependfiles)
+.MAKE.DEPENDFILE_PREFIX := ${_machine_dependfiles:[1]:T:R}
+.else
+.MAKE.DEPENDFILE_PREFIX := ${_default_dependfile:T}
+.endif
+.endif
+
+
+# this is how we identify non-machine specific dependfiles
+N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N*${MACHINE}*:${M_ListToSkip}}
+
+.endif # !target(_DIRDEP_USE)
+
+# if we were included recursively _DEP_TARGET_SPEC should be valid.
+.if empty(_DEP_TARGET_SPEC)
+# we may or may not have included a dependfile yet
+.if defined(.INCLUDEDFROMFILE)
+_last_dependfile := ${.INCLUDEDFROMFILE:M${.MAKE.DEPENDFILE_PREFIX}*}
+.else
+_last_dependfile := ${.MAKE.MAKEFILES:M*/${.MAKE.DEPENDFILE_PREFIX}*:[-1]}
+.endif
+.if ${_debug_reldir:U0}
+.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _last_dependfile='${_last_dependfile}'
+.endif
+
+.if empty(_last_dependfile) || ${_last_dependfile:E:${N_notmachine}} == ""
+# this is all we have to work with
+DEP_MACHINE = ${TARGET_MACHINE:U${MACHINE}}
+_DEP_TARGET_SPEC := ${DEP_TARGET_SPEC}
+.else
+_DEP_TARGET_SPEC = ${_last_dependfile:${M_dep_qual_fixes:ts:}:E}
+.endif
+.if !empty(_last_dependfile)
+# record that we've read dependfile for this
+_DIRDEP_CHECKED += ${_CURDIR}.${TARGET_SPEC}
+.endif
+.endif
+
+# by now _DEP_TARGET_SPEC should be set, parse it.
+.if ${TARGET_SPEC_VARS:[#]} > 1
+# we need to parse DEP_MACHINE may or may not contain more info
+_tspec := ${_DEP_TARGET_SPEC:S/,/ /g}
+.for i in ${_tspec_x}
+DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]}
+.endfor
+.for v in ${TARGET_SPEC_VARS:O:u}
+.if empty(DEP_$v)
+.undef DEP_$v
+.endif
+.endfor
+.else
+DEP_MACHINE := ${_DEP_TARGET_SPEC}
+.endif
+
+# pickup customizations
+# as below you can use !target(_DIRDEP_USE) to protect things
+# which should only be done once.
+.-include "local.dirdeps.mk"
+
+# the first time we are included the _DIRDEP_USE target will not be defined
+# we can use this as a clue to do initialization and other one time things.
+.if !target(_DIRDEP_USE)
+# make sure this target exists
+dirdeps: beforedirdeps .WAIT
+beforedirdeps:
+
+# We normally expect to be included by Makefile.depend.*
+# which sets the DEP_* macros below.
+DEP_RELDIR ?= ${RELDIR}
+
+# this can cause lots of output!
+# set to a set of glob expressions that might match RELDIR
+DEBUG_DIRDEPS ?= no
+
+# remember the initial value of DEP_RELDIR - we test for it below.
+_DEP_RELDIR := ${DEP_RELDIR}
+
+# things we skip for host tools
+SKIP_HOSTDIR ?=
+
+NSkipHostDir = ${SKIP_HOSTDIR:N*.host*:S,$,.host*,:N.host*:S,^,${SRCTOP}/,:${M_ListToSkip}}
+
+# things we always skip
+# SKIP_DIRDEPS allows for adding entries on command line.
+SKIP_DIR += .host *.WAIT ${SKIP_DIRDEPS}
+SKIP_DIR.host += ${SKIP_HOSTDIR}
+
+DEP_SKIP_DIR = ${SKIP_DIR} \
+ ${SKIP_DIR.${DEP_TARGET_SPEC}:U} \
+ ${SKIP_DIR.${DEP_MACHINE}:U} \
+ ${SKIP_DIRDEPS.${DEP_MACHINE}:U}
+
+NSkipDir = ${DEP_SKIP_DIR:${M_ListToSkip}}
+
+.if defined(NO_DIRDEPS) || defined(NODIRDEPS) || defined(WITHOUT_DIRDEPS)
+# confine ourselves to the original dir
+DIRDEPS_FILTER += M${_DEP_RELDIR}*
+.endif
+
+# this is what we run below
+DIRDEP_MAKE?= ${.MAKE}
+
+# we suppress SUBDIR when visiting the leaves
+# we assume sys.mk will set MACHINE_ARCH
+# you can add extras to DIRDEP_USE_ENV
+# if there is no makefile in the target directory, we skip it.
+_DIRDEP_USE: .USE .MAKE
+ @for m in ${.MAKE.MAKEFILE_PREFERENCE}; do \
+ test -s ${.TARGET:R}/$$m || continue; \
+ echo "${TRACER}Checking ${.TARGET:R} for ${.TARGET:E} ..."; \
+ MACHINE_ARCH= NO_SUBDIR=1 ${DIRDEP_USE_ENV} \
+ TARGET_SPEC=${.TARGET:E} \
+ MACHINE=${.TARGET:E} \
+ ${DIRDEP_MAKE} -C ${.TARGET:R} || exit 1; \
+ break; \
+ done
+
+.ifdef ALL_MACHINES
+# this is how you limit it to only the machines we have been built for
+# previously.
+.if empty(ONLY_MACHINE_LIST)
+.if !empty(ALL_MACHINE_LIST)
+# ALL_MACHINE_LIST is the list of all legal machines - ignore anything else
+_machine_list != cd ${_CURDIR} && 'ls' -1 ${ALL_MACHINE_LIST:O:u:@m@${.MAKE.DEPENDFILE:T:R}.$m@} 2> /dev/null; echo
+.else
+_machine_list != 'ls' -1 ${_CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.* 2> /dev/null; echo
+.endif
+_only_machines := ${_machine_list:${NIgnoreFiles:UN*.bak}:E:O:u}
+.else
+_only_machines := ${ONLY_MACHINE_LIST}
+.endif
+
+.if empty(_only_machines)
+# we must be boot-strapping
+_only_machines := ${TARGET_MACHINE:U${ALL_MACHINE_LIST:U${DEP_MACHINE}}}
+.endif
+
+.else # ! ALL_MACHINES
+# if ONLY_MACHINE_LIST is set, we are limited to that
+# if TARGET_MACHINE is set - it is really the same as ONLY_MACHINE_LIST
+# otherwise DEP_MACHINE is it - so DEP_MACHINE will match.
+_only_machines := ${ONLY_MACHINE_LIST:U${TARGET_MACHINE:U${DEP_MACHINE}}:M${DEP_MACHINE}}
+.endif
+
+.if !empty(NOT_MACHINE_LIST)
+_only_machines := ${_only_machines:${NOT_MACHINE_LIST:${M_ListToSkip}}}
+.endif
+
+# make sure we have a starting place?
+DIRDEPS ?= ${RELDIR}
+.endif # target
+
+# if repeatedly building the same target,
+# we can avoid the overhead of re-computing the tree dependencies.
+MK_DIRDEPS_CACHE ?= no
+BUILD_DIRDEPS_CACHE ?= no
+BUILD_DIRDEPS ?= yes
+
+.if !defined(NO_DIRDEPS)
+.if ${MK_DIRDEPS_CACHE} == "yes"
+# this is where we will cache all our work
+DIRDEPS_CACHE?= ${_OBJDIR}/dirdeps.cache${.TARGETS:Nall:O:u:ts-:S,/,_,g:S,^,.,:N.}
+
+# just ensure this exists
+build-dirdeps:
+
+M_oneperline = @x@\\${.newline} $$x@
+
+.if ${BUILD_DIRDEPS_CACHE} == "no"
+.if !target(dirdeps-cached)
+# we do this via sub-make
+BUILD_DIRDEPS = no
+
+dirdeps: dirdeps-cached
+dirdeps-cached: ${DIRDEPS_CACHE} .MAKE
+ @echo "${TRACER}Using ${DIRDEPS_CACHE}"
+ @MAKELEVEL=${.MAKE.LEVEL} ${.MAKE} -C ${_CURDIR} -f ${DIRDEPS_CACHE} \
+ dirdeps MK_DIRDEPS_CACHE=no BUILD_DIRDEPS=no
+
+# these should generally do
+BUILD_DIRDEPS_MAKEFILE ?= ${MAKEFILE}
+BUILD_DIRDEPS_TARGETS ?= ${.TARGETS}
+
+# we need the .meta file to ensure we update if
+# any of the Makefile.depend* changed.
+# We do not want to compare the command line though.
+${DIRDEPS_CACHE}: .META .NOMETA_CMP
+ +@{ echo '# Autogenerated - do NOT edit!'; echo; \
+ echo 'BUILD_DIRDEPS=no'; echo; \
+ echo '.include <dirdeps.mk>'; \
+ } > ${.TARGET}.new
+ +@MAKELEVEL=${.MAKE.LEVEL} DIRDEPS_CACHE=${DIRDEPS_CACHE} \
+ DIRDEPS="${DIRDEPS}" \
+ MAKEFLAGS= ${.MAKE} -C ${_CURDIR} -f ${BUILD_DIRDEPS_MAKEFILE} \
+ ${BUILD_DIRDEPS_TARGETS} BUILD_DIRDEPS_CACHE=yes \
+ .MAKE.DEPENDFILE=.none \
+ 3>&1 1>&2 | sed 's,${SRCTOP},$${SRCTOP},g' >> ${.TARGET}.new && \
+ mv ${.TARGET}.new ${.TARGET}
+
+.endif
+.elif !target(_count_dirdeps)
+# we want to capture the dirdeps count in the cache
+.END: _count_dirdeps
+_count_dirdeps: .NOMETA
+ @echo '.info $${.newline}$${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]}' >&3
+
+.endif
+.elif !make(dirdeps) && !target(_count_dirdeps)
+beforedirdeps: _count_dirdeps
+_count_dirdeps: .NOMETA
+ @echo "${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]} seconds=`expr ${now_utc} - ${start_utc}`"
+
+.endif
+.endif
+
+.if ${BUILD_DIRDEPS} == "yes"
+.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@} != ""
+_debug_reldir = 1
+.else
+_debug_reldir = 0
+.endif
+.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend:L:M$x}@} != ""
+_debug_search = 1
+.else
+_debug_search = 0
+.endif
+
+# the rest is done repeatedly for every Makefile.depend we read.
+# if we are anything but the original dir we care only about the
+# machine type we were included for..
+
+.if ${DEP_RELDIR} == "."
+_this_dir := ${SRCTOP}
+.else
+_this_dir := ${SRCTOP}/${DEP_RELDIR}
+.endif
+
+# on rare occasions, there can be a need for extra help
+_dep_hack := ${_this_dir}/${.MAKE.DEPENDFILE_PREFIX}.inc
+.-include "${_dep_hack}"
+
+.if ${DEP_RELDIR} != ${_DEP_RELDIR} || ${DEP_TARGET_SPEC} != ${TARGET_SPEC}
+# this should be all
+_machines := ${DEP_MACHINE}
+.else
+# this is the machine list we actually use below
+_machines := ${_only_machines}
+
+.if defined(HOSTPROG) || ${DEP_MACHINE} == "host"
+# we need to build this guy's dependencies for host as well.
+_machines += host
+.endif
+
+_machines := ${_machines:O:u}
+.endif
+
+.if ${TARGET_SPEC_VARS:[#]} > 1
+# we need to tweak _machines
+_dm := ${DEP_MACHINE}
+# apply the same filtering that we do when qualifying DIRDEPS.
+# M_dep_qual_fixes expects .${MACHINE}* so add (and remove) '.'
+_machines := ${_machines:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,}
+DEP_MACHINE := ${_dm}
+.endif
+
+# reset each time through
+_build_dirs =
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# pickup other machines for this dir if necessary
+.if ${BUILD_AT_LEVEL0:Uyes} == "no"
+_build_dirs += ${_machines:@m@${_CURDIR}.$m@}
+.else
+_build_dirs += ${_machines:N${DEP_TARGET_SPEC}:@m@${_CURDIR}.$m@}
+.if ${DEP_TARGET_SPEC} == ${TARGET_SPEC}
+# pickup local dependencies now
+.-include <.depend>
+.endif
+.endif
+.endif
+
+.if ${_debug_reldir}
+.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: DIRDEPS='${DIRDEPS}'
+.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _machines='${_machines}'
+.endif
+
+.if !empty(DIRDEPS)
+# these we reset each time through as they can depend on DEP_MACHINE
+DEP_DIRDEPS_FILTER = \
+ ${DIRDEPS_FILTER.${DEP_TARGET_SPEC}:U} \
+ ${DIRDEPS_FILTER.${DEP_MACHINE}:U} \
+ ${DIRDEPS_FILTER:U}
+.if empty(DEP_DIRDEPS_FILTER)
+# something harmless
+DEP_DIRDEPS_FILTER = U
+.endif
+
+# this is what we start with
+__depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:C,//+,/,g:O:u:@d@${SRCTOP}/$d@}
+
+# some entries may be qualified with .<machine>
+# the :M*/*/*.* just tries to limit the dirs we check to likely ones.
+# the ${d:E:M*/*} ensures we don't consider junos/usr.sbin/mgd
+__qual_depdirs := ${__depdirs:M*/*/*.*:@d@${exists($d):?:${"${d:E:M*/*}":?:${exists(${d:R}):?$d:}}}@}
+__unqual_depdirs := ${__depdirs:${__qual_depdirs:Uno:${M_ListToSkip}}}
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# if it was called out - we likely need it.
+__hostdpadd := ${DPADD:U.:M${HOST_OBJTOP}/*:S,${HOST_OBJTOP}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host,:N.*:@d@${SRCTOP}/$d@}
+__qual_depdirs += ${__hostdpadd}
+.endif
+
+.if ${_debug_reldir}
+.info depdirs=${__depdirs}
+.info qualified=${__qual_depdirs}
+.info unqualified=${__unqual_depdirs}
+.endif
+
+# _build_dirs is what we will feed to _DIRDEP_USE
+_build_dirs += \
+ ${__qual_depdirs:M*.host:${NSkipHostDir}:N.host} \
+ ${__qual_depdirs:N*.host} \
+ ${_machines:Mhost*:@m@${__unqual_depdirs:@d@$d.$m@}@:${NSkipHostDir}:N.host} \
+ ${_machines:Nhost*:@m@${__unqual_depdirs:@d@$d.$m@}@}
+
+# qualify everything now
+_build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u}
+
+.endif # empty DIRDEPS
+
+# Normally if doing make -V something,
+# we do not want to waste time chasing DIRDEPS
+# but if we want to count the number of Makefile.depend* read, we do.
+.if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS}} == ""
+.if !empty(_build_dirs)
+.if ${BUILD_DIRDEPS_CACHE} == "yes"
+x!= { echo; echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; \
+ echo 'dirdeps: ${_build_dirs:${M_oneperline}}'; echo; } >&3; echo
+x!= { ${_build_dirs:@x@${target($x):?:echo '$x: _DIRDEP_USE';}@} echo; } >&3; echo
+.else
+# this makes it all happen
+dirdeps: ${_build_dirs}
+.endif
+${_build_dirs}: _DIRDEP_USE
+
+.if ${_debug_reldir}
+.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs}
+.endif
+
+# this builds the dependency graph
+.for m in ${_machines}
+# it would be nice to do :N${.TARGET}
+.if !empty(__qual_depdirs)
+.for q in ${__qual_depdirs:${M_dep_qual_fixes:ts:}:E:O:u:N$m}
+.if ${_debug_reldir} || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != ""
+.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q}
+.endif
+.if ${BUILD_DIRDEPS_CACHE} == "yes"
+x!= { echo; echo '${_this_dir}.$m: ${_build_dirs:M*.$q:${M_oneperline}}'; echo; } >&3; echo
+.else
+${_this_dir}.$m: ${_build_dirs:M*.$q}
+.endif
+.endfor
+.endif
+.if ${_debug_reldir}
+.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m}
+.endif
+.if ${BUILD_DIRDEPS_CACHE} == "yes"
+x!= { echo; echo '${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m:${M_oneperline}}'; echo; } >&3; echo
+.else
+${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
+.endif
+.endfor
+
+.endif
+
+# Now find more dependencies - and recurse.
+.for d in ${_build_dirs}
+.if ${_DIRDEP_CHECKED:M$d} == ""
+# once only
+_DIRDEP_CHECKED += $d
+.if ${_debug_search}
+.info checking $d
+.endif
+# Note: _build_dirs is fully qualifed so d:R is always the directory
+.if exists(${d:R})
+# Warning: there is an assumption here that MACHINE is always
+# the first entry in TARGET_SPEC_VARS.
+# If TARGET_SPEC and MACHINE are insufficient, you have a problem.
+_m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:S;${MACHINE};${d:E:C/,.*//};:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]}
+.if !empty(_m)
+# M_dep_qual_fixes isn't geared to Makefile.depend
+_qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes:ts:}}
+.if ${_debug_search}
+.info Looking for ${_qm}
+.endif
+# we pass _DEP_TARGET_SPEC to tell the next step what we want
+_DEP_TARGET_SPEC := ${d:E}
+# some makefiles may still look at this
+_DEP_MACHINE := ${d:E:C/,.*//}
+# set this "just in case"
+# we can skip :tA since we computed the path above
+DEP_RELDIR := ${_m:H:S,${SRCTOP}/,,}
+# and reset this
+DIRDEPS =
+.if ${_debug_reldir} && ${_qm} != ${_m}
+.info loading ${_m} for ${d:E}
+.endif
+.include <${_m}>
+.endif
+.endif
+.endif
+.endfor
+
+.endif # -V
+.endif # BUILD_DIRDEPS
+
+.elif ${.MAKE.LEVEL} > 42
+.error You should have stopped recursing by now.
+.else
+# we are building something
+DEP_RELDIR := ${RELDIR}
+_DEP_RELDIR := ${RELDIR}
+# pickup local dependencies
+.-include <.depend>
+.endif
+
+# bootstrapping new dependencies made easy?
+.if (make(bootstrap) || make(bootstrap-recurse)) && !target(bootstrap)
+
+.if exists(${.CURDIR}/${.MAKE.DEPENDFILE:T})
+# stop here
+${.TARGETS:Mboot*}:
+.else
+# find a Makefile.depend to use as _src
+_src != cd ${.CURDIR} && for m in ${.MAKE.DEPENDFILE_PREFERENCE:T:S,${MACHINE},*,}; do test -s $$m || continue; echo $$m; break; done; echo
+.if empty(_src)
+.error cannot find any of ${.MAKE.DEPENDFILE_PREFERENCE:T}
+.endif
+
+_src?= ${.MAKE.DEPENDFILE:T}
+
+bootstrap-this: .NOTMAIN
+ @echo Bootstrapping ${RELDIR}/${.MAKE.DEPENDFILE:T} from ${_src:T}
+ (cd ${.CURDIR} && sed 's,${_src:E},${MACHINE},g' ${_src} > ${.MAKE.DEPENDFILE:T})
+
+bootstrap: bootstrap-recurse
+bootstrap-recurse: bootstrap-this
+
+_mf := ${.PARSEFILE}
+bootstrap-recurse: .NOTMAIN .MAKE
+ @cd ${SRCTOP} && \
+ for d in `cd ${RELDIR} && ${.MAKE} -B -f ${"${.MAKEFLAGS:M-n}":?${_src}:${.MAKE.DEPENDFILE:T}} -V DIRDEPS`; do \
+ test -d $$d || d=$${d%.*}; \
+ test -d $$d || continue; \
+ echo "Checking $$d for bootstrap ..."; \
+ (cd $$d && ${.MAKE} -f ${_mf} bootstrap-recurse); \
+ done
+
+.endif
+.endif
Index: share/mk/gendirdeps.mk
===================================================================
--- share/mk/gendirdeps.mk
+++ share/mk/gendirdeps.mk
@@ -0,0 +1,346 @@
+# $Id: gendirdeps.mk,v 1.27 2015/06/08 20:55:11 sjg Exp $
+
+# Copyright (c) 2010-2013, Juniper Networks, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# This makefile [re]generates ${.MAKE.DEPENDFILE}
+#
+
+.include <install-new.mk>
+
+# Assumptions:
+# RELDIR is the relative path from ${SRCTOP} to ${_CURDIR}
+# (SRCTOP is ${SB}/src)
+# _CURDIR is the absolute version of ${.CURDIR}
+# _OBJDIR is the absolute version of ${.OBJDIR}
+# _objroot is realpath of ${_OBJTOP} without ${MACHINE}
+# this may be different from _OBJROOT if $SB/obj is a
+# symlink to another filesystem.
+# _objroot must be a prefix match for _objtop
+
+.MAIN: all
+
+# keep this simple
+.MAKE.MODE = compat
+
+all:
+
+_CURDIR ?= ${.CURDIR}
+_OBJDIR ?= ${.OBJDIR}
+_OBJTOP ?= ${OBJTOP}
+_OBJROOT ?= ${OBJROOT:U${_OBJTOP}}
+.if ${_OBJROOT:M*/}
+_slash=/
+.else
+_slash=
+.endif
+_objroot ?= ${_OBJROOT:tA}${_slash}
+
+_this = ${.PARSEDIR}/${.PARSEFILE}
+
+# remember what to make
+_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
+
+# We do _not_ want to read our own output!
+.MAKE.DEPENDFILE = /dev/null
+
+# caller should have set this
+META_FILES ?= ${.MAKE.META.FILES}
+
+.if !empty(META_FILES)
+
+.if ${.MAKE.LEVEL} > 0 && !empty(GENDIRDEPS_FILTER)
+# so we can compare below
+.-include <${_DEPENDFILE}>
+# yes, I mean :U with no value
+_DIRDEPS := ${DIRDEPS:U:O:u}
+.endif
+
+META_FILES := ${META_FILES:T:O:u}
+.export META_FILES
+
+# pickup customizations
+.-include "local.gendirdeps.mk"
+
+# these are actually prefixes that we'll skip
+# they should all be absolute paths
+SKIP_GENDIRDEPS ?=
+.if !empty(SKIP_GENDIRDEPS)
+_skip_gendirdeps = egrep -v '^(${SKIP_GENDIRDEPS:O:u:ts|})' |
+.else
+_skip_gendirdeps =
+.endif
+
+# Below we will turn _{VAR} into ${VAR} which keeps this simple
+# GENDIRDEPS_FILTER_DIR_VARS is a list of dirs to be substiuted for.
+# GENDIRDEPS_FILTER_VARS is more general.
+# In each case order matters.
+.if !empty(GENDIRDEPS_FILTER_DIR_VARS)
+GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_DIR_VARS:@v@S,${$v},_{${v}},@}
+.endif
+.if !empty(GENDIRDEPS_FILTER_VARS)
+GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_VARS:@v@S,/${$v}/,/_{${v}}/,@:NS,//,*:u}
+.endif
+
+# this (*should* be set in meta.sys.mk)
+# is the script that extracts what we want.
+META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
+META2DEPS := ${META2DEPS}
+
+.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" && ${DEBUG_GENDIRDEPS:Uno:Mmeta2d*} != ""
+_time = time
+_sh_x = sh -x
+_py_d = -ddd
+.else
+_time =
+_sh_x =
+_py_d =
+.endif
+
+.if ${META2DEPS:E} == "py"
+# we can afford to do this all the time.
+DPDEPS ?= no
+META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d}
+.if ${DPDEPS:tl} != "no"
+META2DEPS_CMD += -D ${DPDEPS}
+.endif
+META2DEPS_FILTER = sed 's,^src:,${SRCTOP}/,;s,^\([^/]\),${OBJTOP}/\1,' |
+.elif ${META2DEPS:E} == "sh"
+META2DEPS_CMD = ${_time} ${_sh_x} ${META2DEPS} OBJTOP=${_OBJTOP}
+.else
+META2DEPS_CMD ?= ${META2DEPS}
+.endif
+
+.if ${TARGET_OBJ_SPEC:U${MACHINE}} != ${MACHINE}
+META2DEPS_CMD += -T ${TARGET_OBJ_SPEC}
+.endif
+META2DEPS_CMD += \
+ -R ${RELDIR} -H ${HOST_TARGET} \
+ ${M2D_OBJROOTS:O:u:@o@-O $o@}
+
+
+M2D_OBJROOTS += ${OBJTOP} ${_OBJROOT} ${_objroot}
+.if defined(SB_OBJROOT)
+M2D_OBJROOTS += ${SB_OBJROOT}
+.endif
+.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} == ""
+# meta2deps.py only groks objroot
+# so we need to give it what it expects
+# and tell it not to add machine qualifiers
+META2DEPS_ARGS += MACHINE=none
+.endif
+.if defined(SB_BACKING_SB)
+META2DEPS_CMD += -S ${SB_BACKING_SB}/src
+M2D_OBJROOTS += ${SB_BACKING_SB}/${SB_OBJPREFIX}
+.endif
+
+# we are only interested in the dirs
+# sepecifically those we read something from.
+# we canonicalize them to keep things simple
+# if we are using a split-fs sandbox, it gets a little messier.
+_objtop := ${_OBJTOP:tA}
+dir_list != cd ${_OBJDIR} && \
+ ${META2DEPS_CMD} MACHINE=${MACHINE} \
+ SRCTOP=${SRCTOP} RELDIR=${RELDIR} CURDIR=${_CURDIR} \
+ ${META2DEPS_ARGS} \
+ ${META_FILES:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
+ sed 's,//*$$,,;s,\.${HOST_TARGET}$$,.host,'
+
+.if ${dir_list:M*ERROR\:*} != ""
+.warning ${dir_list:tW:C,.*(ERROR),\1,}
+.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,}
+# we are not going to update anything
+.else
+dpadd_dir_list=
+.if !empty(DPADD)
+_nonlibs := ${DPADD:T:Nlib*:N*include}
+.if !empty(_nonlibs)
+ddep_list =
+.for f in ${_nonlibs:@x@${DPADD:M*/$x}@}
+.if exists($f.dirdep)
+ddep_list += $f.dirdep
+.elif exists(${f:H}.dirdep)
+ddep_list += ${f:H}.dirdep
+.else
+dir_list += ${f:H:tA}
+dpadd_dir_list += ${f:H:tA}
+.endif
+.endfor
+.if !empty(ddep_list)
+ddeps != cat ${ddep_list:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
+ sed 's,//*$$,,;s,\.${HOST_TARGET}$$,.host,;s,\.${MACHINE}$$,,'
+
+.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
+.info ${RELDIR}: raw_dir_list='${dir_list}'
+.info ${RELDIR}: ddeps='${ddeps}'
+.endif
+dir_list += ${ddeps}
+.endif
+.endif
+.endif
+
+# DIRDEPS represent things that had to have been built first
+# so they should all be undir OBJTOP.
+# Note that ${_OBJTOP}/bsd/include/machine will get reported
+# to us as $SRCTOP/bsd/sys/$MACHINE_ARCH/include meaning we
+# will want to visit bsd/include
+# so we add
+# ${"${dir_list:M*bsd/sys/${MACHINE_ARCH}/include}":?bsd/include:}
+# to GENDIRDEPS_DIR_LIST_XTRAS
+_objtops = ${OBJTOP} ${_OBJTOP} ${_objtop}
+_objtops := ${_objtops:O:u}
+dirdep_list = \
+ ${_objtops:@o@${dir_list:M$o*/*:C,$o[^/]*/,,}@} \
+ ${GENDIRDEPS_DIR_LIST_XTRAS}
+
+# sort longest first
+M2D_OBJROOTS := ${M2D_OBJROOTS:O:u:[-1..1]}
+
+# anything we use from an object dir other than ours
+# needs to be qualified with its .<machine> suffix
+# (we used the pseudo machine "host" for the HOST_TARGET).
+skip_ql= ${SRCTOP}* ${_objtops:@o@$o*@}
+.for o in ${M2D_OBJROOTS:${skip_ql:${M_ListToSkip}}}
+# we need := so only skip_ql to this point applies
+ql.$o := ${dir_list:${skip_ql:${M_ListToSkip}}:M$o*/*/*:C,$o([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,}
+qualdir_list += ${ql.$o}
+.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
+.info ${RELDIR}: o=$o ${ql.$o qualdir_list:L:@v@$v=${$v}@}
+.endif
+skip_ql+= $o*
+.endfor
+
+dirdep_list := ${dirdep_list:O:u}
+qualdir_list := ${qualdir_list:N*.${MACHINE}:O:u}
+
+DIRDEPS = \
+ ${dirdep_list:N${RELDIR}:N${RELDIR}/*} \
+ ${qualdir_list:N${RELDIR}.*:N${RELDIR}/*}
+
+# We only consider things below $RELDIR/ if they have a makefile.
+# This is the same test that _DIRDEP_USE applies.
+# We have do a double test with dirdep_list as it _may_ contain
+# qualified dirs - if we got anything from a stage dir.
+# qualdir_list we know are all qualified.
+# It would be nice do peform this check for all of DIRDEPS,
+# but we cannot assume that all of the tree is present,
+# in fact we can only assume that RELDIR is.
+DIRDEPS += \
+ ${dirdep_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/$d/$m):?$d:${exists(${SRCTOP}/${d:R}/$m):?$d:}}@}@} \
+ ${qualdir_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/${d:R}/$m):?$d:}@}@}
+
+DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:ts:}:C,//+,/,g:O:u}
+
+.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
+.info ${RELDIR}: M2D_OBJROOTS=${M2D_OBJROOTS}
+.info ${RELDIR}: dir_list='${dir_list}'
+.info ${RELDIR}: dpadd_dir_list='${dpadd_dir_list}'
+.info ${RELDIR}: dirdep_list='${dirdep_list}'
+.info ${RELDIR}: qualdir_list='${qualdir_list}'
+.info ${RELDIR}: SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS}'
+.info ${RELDIR}: GENDIRDEPS_FILTER='${GENDIRDEPS_FILTER}'
+.info ${RELDIR}: FORCE_DPADD='${DPADD}'
+.info ${RELDIR}: DIRDEPS='${DIRDEPS}'
+.endif
+
+# SRC_DIRDEPS is for checkout logic
+src_dirdep_list = \
+ ${dir_list:M${SRCTOP}/*:S,${SRCTOP}/,,}
+
+SRC_DIRDEPS = \
+ ${src_dirdep_list:N${RELDIR}:N${RELDIR}/*:C,(/h)/.*,,}
+
+SRC_DIRDEPS := ${SRC_DIRDEPS:${GENDIRDEPS_SRC_FILTER:UN/*:ts:}:C,//+,/,g:O:u}
+
+# if you want to capture SRC_DIRDEPS in .MAKE.DEPENDFILE put
+# SRC_DIRDEPS_FILE = ${_DEPENDFILE}
+# in local.gendirdeps.mk
+.if ${SRC_DIRDEPS_FILE:Uno:tl} != "no"
+ECHO_SRC_DIRDEPS = echo 'SRC_DIRDEPS = \'; echo '${SRC_DIRDEPS:@d@ $d \\${.newline}@}'; echo;
+
+.if ${SRC_DIRDEPS_FILE:T} == ${_DEPENDFILE:T}
+_include_src_dirdeps = ${ECHO_SRC_DIRDEPS}
+.else
+all: ${SRC_DIRDEPS_FILE}
+.if !target(${SRC_DIRDEPS_FILE})
+${SRC_DIRDEPS_FILE}: ${META_FILES} ${_this} ${META2DEPS}
+ @(${ECHO_SRC_DIRDEPS}) > $@
+.endif
+.endif
+.endif
+_include_src_dirdeps ?=
+
+all: ${_DEPENDFILE}
+
+# if this is going to exist it would be there by now
+.if !exists(.depend)
+CAT_DEPEND = /dev/null
+.endif
+CAT_DEPEND ?= .depend
+
+.if !empty(_DIRDEPS) && ${DIRDEPS} != ${_DIRDEPS}
+# we may have changed a filter
+.PHONY: ${_DEPENDFILE}
+.endif
+
+# 'cat .depend' should suffice, but if we are mixing build modes
+# .depend may contain things we don't want.
+# The sed command at the end of the stream, allows for the filters
+# to output _{VAR} tokens which we will turn into proper ${VAR} references.
+${_DEPENDFILE}: ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
+ @(echo '# Autogenerated - do NOT edit!'; echo; \
+ echo 'DIRDEPS = \'; \
+ echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
+ ${_include_src_dirdeps} \
+ echo '.include <dirdeps.mk>'; \
+ echo; \
+ echo '.if $${DEP_RELDIR} == $${_DEP_RELDIR}'; \
+ echo '# local dependencies - needed for -jN in clean tree'; \
+ [ -s ${CAT_DEPEND} ] && { grep : ${CAT_DEPEND} | grep -v '[/\\]'; }; \
+ echo '.endif' ) | sed 's,_\([{(]\),$$\1,g' > $@.new${.MAKE.PID}
+ @${InstallNew}; InstallNew -s $@.new${.MAKE.PID}
+
+.endif # meta2deps failed
+.elif !empty(SUBDIR)
+
+DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u}
+
+all: ${_DEPENDFILE}
+
+${_DEPENDFILE}: ${MAKEFILE} ${_this}
+ @(echo '# Autogenerated - do NOT edit!'; echo; \
+ echo 'DIRDEPS = \'; \
+ echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
+ echo '.include <dirdeps.mk>'; \
+ echo ) | sed 's,_\([{(]\),$$\1,g' > $@.new
+ @${InstallNew}; InstallNew $@.new
+
+.else
+
+# nothing to do
+all ${_DEPENDFILE}:
+
+.endif
+${_DEPENDFILE}: .PRECIOUS
Index: share/mk/host-target.mk
===================================================================
--- share/mk/host-target.mk
+++ share/mk/host-target.mk
@@ -0,0 +1,35 @@
+# RCSid:
+# $Id: host-target.mk,v 1.7 2014/05/16 17:54:52 sjg Exp $
+
+# Host platform information; may be overridden
+.if !defined(_HOST_OSNAME)
+_HOST_OSNAME != uname -s
+.export _HOST_OSNAME
+.endif
+.if !defined(_HOST_OSREL)
+_HOST_OSREL != uname -r
+.export _HOST_OSREL
+.endif
+.if !defined(_HOST_ARCH)
+_HOST_ARCH != uname -p 2>/dev/null || uname -m
+# uname -p may produce garbage on linux
+.if ${_HOST_ARCH:[\#]} > 1
+_HOST_ARCH != uname -m
+.endif
+.export _HOST_ARCH
+.endif
+.if !defined(HOST_MACHINE)
+HOST_MACHINE != uname -m
+.export HOST_MACHINE
+.endif
+
+HOST_OSMAJOR := ${_HOST_OSREL:C/[^0-9].*//}
+HOST_OSTYPE := ${_HOST_OSNAME}-${_HOST_OSREL:C/\([^\)]*\)//}-${_HOST_ARCH}
+HOST_OS := ${_HOST_OSNAME}
+host_os := ${_HOST_OSNAME:tl}
+HOST_TARGET := ${host_os}${HOST_OSMAJOR}-${_HOST_ARCH}
+
+# tr is insanely non-portable, accommodate the lowest common denominator
+TR ?= tr
+toLower = ${TR} 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
+toUpper = ${TR} 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Index: share/mk/install-new.mk
===================================================================
--- share/mk/install-new.mk
+++ share/mk/install-new.mk
@@ -0,0 +1,53 @@
+# $Id: install-new.mk,v 1.3 2012/03/24 18:25:49 sjg Exp $
+#
+# @(#) Copyright (c) 2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !defined(InstallNew)
+
+# copy if src and target are different making a backup if desired
+CmpCp= CmpCp() { \
+ src=$$1 target=$$2 _bak=$$3; \
+ if ! test -s $$target || ! cmp -s $$target $$src; then \
+ trap "" 1 2 3 15; \
+ if test -s $$target; then \
+ if test "x$$_bak" != x; then \
+ rm -f $$target$$_bak; \
+ mv $$target $$target$$_bak; \
+ else \
+ rm -f $$target; \
+ fi; \
+ fi; \
+ cp $$src $$target; \
+ fi; }
+
+# If the .new file is different, we want it.
+# Note: this function will work as is for *.new$RANDOM"
+InstallNew= ${CmpCp}; InstallNew() { \
+ _t=-e; _bak=; \
+ while :; do \
+ case "$$1" in \
+ -?) _t=$$1; shift;; \
+ --bak) _bak=$$2; shift 2;; \
+ *) break;; \
+ esac; \
+ done; \
+ for new in "$$@"; do \
+ if test $$_t $$new; then \
+ target=`expr $$new : '\(.*\).new'`; \
+ CmpCp $$new $$target $$_bak; \
+ fi; \
+ rm -f $$new; \
+ done; :; }
+
+.endif
Index: share/mk/local.autodep.mk
===================================================================
--- share/mk/local.autodep.mk
+++ share/mk/local.autodep.mk
@@ -0,0 +1,24 @@
+
+.if ${.MAKE.DEPENDFILE:M*.${MACHINE}} == ""
+# by default only MACHINE0 does updates
+UPDATE_DEPENDFILE_MACHINE?= ${MACHINE0}
+.if ${MACHINE} != ${UPDATE_DEPENDFILE_MACHINE}
+UPDATE_DEPENDFILE= no
+.endif
+.endif
+
+CFLAGS+= ${CFLAGS_LAST}
+CXXFLAGS+= ${CXXFLAGS_LAST}
+LDFLAGS+= ${LDFLAGS_LAST}
+
+CLEANFILES+= .depend
+
+# handy for debugging
+.SUFFIXES: .S .c .cc .cpp .cpp-out
+
+
+.S.cpp-out .c.cpp-out: .NOMETA
+ @${CC} -E ${CFLAGS} ${.IMPSRC} | grep -v '^[[:space:]]*$$'
+
+.cc.cpp-out: .NOMETA
+ @${CXX} -E ${CXXFLAGS} ${.IMPSRC} | grep -v '^[[:space:]]*$$'
Index: share/mk/local.dirdeps.mk
===================================================================
--- share/mk/local.dirdeps.mk
+++ share/mk/local.dirdeps.mk
@@ -0,0 +1,97 @@
+.if !target(_DIRDEP_USE)
+# we are the 1st makefile
+
+.if !defined(MK_CLANG)
+.include "${SRCTOP}/share/mk/src.opts.mk"
+.endif
+
+# DEP_MACHINE is set before we get here, this may not be.
+DEP_RELDIR ?= ${RELDIR}
+
+.if ${.TARGETS:Uall:M*/*} && empty(DIRDEPS)
+# This little trick let's us do
+#
+# mk -f dirdeps.mk some/dir.i386,bsd
+#
+DIRDEPS := ${.TARGETS:M*/*}
+${.TARGETS:Nall}: all
+.endif
+
+# making universe is special
+.if defined(UNIVERSE_GUARD)
+# these should be done by now
+DIRDEPS_FILTER+= N*.host
+.endif
+
+# pseudo machines get no qualification
+.for m in host common
+M_dep_qual_fixes += C;($m),[^/.,]*$$;\1;
+.endfor
+
+#.info M_dep_qual_fixes=${M_dep_qual_fixes}
+# we want to supress these dependencies for host tools
+# but some libs are sadly needed.
+_need_host_libs= \
+ lib/libc++ \
+ lib/libcxxrt \
+ lib/libdwarf \
+ lib/libmd \
+
+N_host_libs:= ${cd ${SRCTOP} && echo lib/lib*:L:sh:${_need_host_libs:${M_ListToSkip}}:${M_ListToSkip}}
+DIRDEPS_FILTER.host = \
+ ${N_host_libs} \
+ Ninclude* \
+ Nlib/csu* \
+ Nlib/[mn]* \
+ Ngnu/lib/csu* \
+ Ngnu/lib/lib[a-r]* \
+ Nusr.bin/xinstall* \
+
+
+DIRDEPS_FILTER+= \
+ ${DIRDEPS_FILTER.xtras:U}
+.endif
+
+# reset this each time
+DIRDEPS_FILTER.xtras=
+.if ${DEP_MACHINE:Npkgs*} != ""
+DIRDEPS_FILTER.xtras+= Nusr.bin/clang/clang.host
+.endif
+
+.if ${DEP_MACHINE} != "host"
+
+# this is how we can handle optional dependencies
+.if ${DEP_RELDIR} == "lib/libc"
+DIRDEPS += lib/libc_nonshared
+.if ${MK_SSP:Uno} != "no"
+DIRDEPS += gnu/lib/libssp/libssp_nonshared
+.endif
+.else
+DIRDEPS_FILTER.xtras+= Nlib/libc_nonshared
+.endif
+
+# some optional things
+.if ${MK_CTF} == "yes" && ${DEP_RELDIR:Mcddl/usr.bin/ctf*} == ""
+DIRDEPS += \
+ cddl/usr.bin/ctfconvert.host \
+ cddl/usr.bin/ctfmerge.host
+.endif
+
+.endif
+
+.if ${MK_CLANG} == "yes" && ${DEP_RELDIR:Nlib/clang/lib*:Nlib/libc*} == ""
+DIRDEPS+= lib/clang/include
+.endif
+
+.if ${MK_STAGING} == "yes"
+# we need targets/pseudo/stage to prep the stage tree
+.if ${DEP_RELDIR} != "targets/pseudo/stage"
+DIRDEPS += targets/pseudo/stage
+.endif
+.endif
+
+DEP_MACHINE_ARCH = ${MACHINE_ARCH.${DEP_MACHINE}}
+CSU_DIR.${DEP_MACHINE_ARCH} ?= csu/${DEP_MACHINE_ARCH}
+CSU_DIR := ${CSU_DIR.${DEP_MACHINE_ARCH}}
+BOOT_MACHINE_DIR:= ${BOOT_MACHINE_DIR.${DEP_MACHINE}}
+KERNEL_NAME:= ${KERNEL_NAME.${DEP_MACHINE}}
Index: share/mk/local.gendirdeps.mk
===================================================================
--- share/mk/local.gendirdeps.mk
+++ share/mk/local.gendirdeps.mk
@@ -0,0 +1,45 @@
+# supress optional/auto dependecies
+# local.dirdeps.mk will put them in if necessary
+GENDIRDEPS_FILTER+= \
+ Ngnu/lib/libssp/libssp_nonshared \
+ Ncddl/usr.bin/ctf* \
+ Nlib/clang/include \
+ Nlib/libc_nonshared \
+ Ntargets/pseudo/stage* \
+ Ntools/*
+
+.if ${RELDIR:Mtargets*} == ""
+.if ${RELDIR:Nusr.bin/clang/*:Ngnu/usr.bin/cc/*:Nlib/clang*} != ""
+GENDIRDEPS_FILTER.host+= \
+ Nusr.bin/clang/* \
+ Ngnu/usr.bin/cc/* \
+
+.endif
+GENDIRDEPS_FILTER+= \
+ Nusr.bin/clang/clang.host \
+ Ngnu/usr.bin/cc* \
+ Ngnu/usr.bin/binutils*.host \
+
+.endif
+
+GENDIRDEPS_FILTER+= ${GENDIRDEPS_FILTER.${MACHINE}:U}
+
+# gendirdeps.mk will turn _{VAR} into ${VAR} which keeps this simple
+# order of this list matters!
+GENDIRDEPS_FILTER_DIR_VARS+= \
+ CSU_DIR \
+ BOOT_MACHINE_DIR
+
+# order of this list matters!
+GENDIRDEPS_FILTER_VARS+= \
+ KERNEL_NAME \
+ MACHINE_CPUARCH \
+ MACHINE_ARCH \
+ MACHINE
+
+GENDIRDEPS_FILTER+= ${GENDIRDEPS_FILTER_DIR_VARS:@v@S,${$v},_{${v}},@}
+GENDIRDEPS_FILTER+= ${GENDIRDEPS_FILTER_VARS:@v@S,/${$v}/,/_{${v}}/,@:NS,//,*:u}
+
+# handle the non-standard way that gnu/usr.bin/groff/tmac is staged
+GENDIRDEPS_FILTER+= C,.*usr/share/tmac.*stage,gnu/usr.bin/groff/tmac,
+
Index: share/mk/local.init.mk
===================================================================
--- share/mk/local.init.mk
+++ share/mk/local.init.mk
@@ -0,0 +1,36 @@
+
+.include "src.opts.mk"
+
+.if ${.MAKE.MODE:Unormal:Mmeta*} != ""
+.if !empty(SUBDIR) && !defined(LIB) && !defined(PROG) && ${.MAKE.MAKEFILES:M*bsd.prog.mk} == ""
+.if ${.MAKE.MODE:Mleaf*} != ""
+# we only want leaf dirs to build in meta mode... and we are not one
+.MAKE.MODE = normal
+.endif
+.endif
+.endif
+
+.if ${MK_SYSROOT} == "yes" && !empty(SYSROOT)
+CFLAGS_LAST+= --sysroot=${SYSROOT}
+CXXFLAGS_LAST+= --sysroot=${SYSROOT}
+LDADD+= --sysroot=${SYSROOT}
+.elif ${MK_STAGING} == "yes"
+CFLAGS+= -I${STAGE_INCLUDEDIR}
+LDADD+= -L${STAGE_LIBDIR}
+.endif
+.if ${MACHINE} == "host"
+# we cheat?
+LDADD+= -B/usr/lib
+CFLAGS_LAST+= -I/usr/include
+CXXFLAGS_LAST+= -I/usr/include
+.endif
+
+.if ${MACHINE} == "host"
+.if ${.MAKE.DEPENDFILE:E} != "host"
+UPDATE_DEPENDFILE?= no
+.endif
+HOST_CC?= /usr/bin/cc
+HOST_CFLAGS+= -DHOSTPROG
+CC= ${HOST_CC}
+CFLAGS+= ${HOST_CFLAGS}
+.endif
Index: share/mk/local.meta.sys.mk
===================================================================
--- share/mk/local.meta.sys.mk
+++ share/mk/local.meta.sys.mk
@@ -0,0 +1,207 @@
+# $FreeBSD$
+
+# local configuration specific to meta mode
+# XXX some of this should be in meta.sys.mk
+# we assume that MK_META_MODE=yes
+
+.if empty(OBJROOT) || ${.MAKE.LEVEL} == 0
+.if !empty(SB)
+SB_OBJROOT ?= ${SB}/obj/
+# this is what we use below
+OBJROOT ?= ${SB_OBJROOT}
+.endif
+OBJROOT ?= ${SRCTOP:H}/obj/
+.if ${OBJROOT:M*/} != ""
+OBJROOT:= ${OBJROOT:tA}/
+.else
+OBJROOT:= ${OBJROOT:H:tA}/${OBJROOT:T}
+.endif
+.export OBJROOT SRCTOP
+
+# we need HOST_TARGET etc below.
+.include <host-target.mk>
+.export HOST_TARGET
+.endif
+
+# from src/Makefile (for universe)
+TARGET_ARCHES_arm?= arm armeb armv6 armv6eb
+TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32
+TARGET_ARCHES_powerpc?= powerpc powerpc64
+TARGET_ARCHES_pc98?= i386
+
+# some corner cases
+CSU_DIR.i386 = csu/i386-elf
+BOOT_MACHINE_DIR.amd64 = boot/i386
+MACHINE_ARCH.host = ${_HOST_ARCH}
+
+# the list of machines we support
+ALL_MACHINE_LIST?= amd64 arm i386 ia64 mips pc98 powerpc sparc64
+.for m in ${ALL_MACHINE_LIST:O:u}
+MACHINE_ARCH_LIST.$m?= ${TARGET_ARCHES_${m}:U$m}
+MACHINE_ARCH.$m?= ${MACHINE_ARCH_LIST.$m:[1]}
+BOOT_MACHINE_DIR.$m ?= boot/$m
+.endfor
+
+.ifndef _TARGET_SPEC
+.if empty(MACHINE_ARCH)
+.if !empty(TARGET_ARCH)
+MACHINE_ARCH= ${TARGET_ARCH}
+.else
+MACHINE_ARCH= ${MACHINE_ARCH.${MACHINE}}
+.endif
+.endif
+MACHINE_ARCH?= ${MACHINE_ARCH.${MACHINE}}
+MACHINE_ARCH:= ${MACHINE_ARCH}
+.else
+# we got here via dirdeps
+MACHINE_ARCH:= ${MACHINE_ARCH.${MACHINE}}
+.endif
+
+# now because for universe we want to potentially
+# build for multiple MACHINE_ARCH per MACHINE
+# we need more than MACHINE in TARGET_SPEC
+TARGET_SPEC_VARS= MACHINE MACHINE_ARCH
+# see dirdeps.mk
+.if ${TARGET_SPEC:Uno:M*,*} != ""
+_tspec := ${TARGET_SPEC:S/,/ /g}
+MACHINE := ${_tspec:[1]}
+MACHINE_ARCH := ${_tspec:[2]}
+# etc.
+# We need to stop that TARGET_SPEC affecting any submakes
+# and deal with MACHINE=${TARGET_SPEC} in the environment.
+TARGET_SPEC=
+# export but do not track
+.export-env TARGET_SPEC
+.export ${TARGET_SPEC_VARS}
+.for v in ${TARGET_SPEC_VARS:O:u}
+.if empty($v)
+.undef $v
+.endif
+.endfor
+.endif
+# make sure we know what TARGET_SPEC is
+# as we may need it to find Makefile.depend*
+TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
+
+# to be consistent with src/Makefile just concatenate with '.'s
+TARGET_OBJ_SPEC:= ${TARGET_SPEC:S;,;.;g}
+OBJTOP:= ${OBJROOT}${TARGET_OBJ_SPEC}
+
+.if ${.CURDIR} == ${SRCTOP}
+RELDIR = .
+.elif ${.CURDIR:M${SRCTOP}/*}
+RELDIR := ${.CURDIR:S,${SRCTOP}/,,}
+.endif
+
+HOST_OBJTOP ?= ${OBJROOT}${HOST_TARGET}
+
+.if ${OBJTOP} == ${HOST_OBJTOP} || ${REQUESTED_MACHINE:U${MACHINE}} == "host"
+MACHINE= host
+.if ${TARGET_MACHINE:Uno} == ${HOST_TARGET}
+# not what we want
+TARGET_MACHINE= host
+.endif
+.endif
+.if ${MACHINE} == "host"
+OBJTOP := ${HOST_OBJTOP}
+.endif
+
+.if ${.MAKE.LEVEL} == 0
+PYTHON ?= /usr/local/bin/python
+.export PYTHON
+# this works best if share/mk is ready for it.
+BUILD_AT_LEVEL0= no
+
+# we want to end up with a singe stage tree for all machines
+.if ${MK_STAGING} == "yes"
+.if empty(STAGE_ROOT)
+STAGE_ROOT?= ${OBJROOT}stage
+.export STAGE_ROOT
+.endif
+.endif
+.endif
+
+.if ${MK_STAGING} == "yes"
+.if ${MACHINE} == "host"
+STAGE_MACHINE= ${HOST_TARGET}
+.else
+STAGE_MACHINE:= ${TARGET_OBJ_SPEC}
+.endif
+STAGE_OBJTOP:= ${STAGE_ROOT}/${STAGE_MACHINE}
+STAGE_COMMON_OBJTOP:= ${STAGE_ROOT}/common
+STAGE_HOST_OBJTOP:= ${STAGE_ROOT}/${HOST_TARGET}
+
+STAGE_LIBDIR= ${STAGE_OBJTOP}${_LIBDIR:U${LIBDIR:U/lib}}
+STAGE_INCLUDEDIR= ${STAGE_OBJTOP}${INCLUDEDIR:U/usr/include}
+# this is not the same as INCLUDEDIR
+STAGE_INCSDIR= ${STAGE_OBJTOP}${INCSDIR:U/include}
+# the target is usually an absolute path
+STAGE_SYMLINKS_DIR= ${STAGE_OBJTOP}
+
+LDFLAGS_LAST+= -Wl,-rpath-link -Wl,${STAGE_LIBDIR}
+.if ${MK_SYSROOT} == "yes"
+SYSROOT?= ${STAGE_OBJTOP}/
+.else
+LDFLAGS_LAST+= -L${STAGE_LIBDIR}
+.endif
+
+.endif # MK_STAGING
+
+# this is sufficient for most of the tree.
+.MAKE.DEPENDFILE_DEFAULT = ${.MAKE.DEPENDFILE_PREFIX}
+
+# but if we have a machine qualified file it should be used in preference
+.MAKE.DEPENDFILE_PREFERENCE = \
+ ${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \
+ ${.MAKE.DEPENDFILE_PREFIX}
+
+.undef .MAKE.DEPENDFILE
+
+.include "sys.dependfile.mk"
+
+.if ${.MAKE.LEVEL} > 0 && ${MACHINE} == "host" && ${.MAKE.DEPENDFILE:E} != "host"
+# we can use this but should not update it.
+UPDATE_DEPENDFILE= NO
+.endif
+
+# define the list of places that contain files we are responsible for
+.MAKE.META.BAILIWICK = ${SB} ${OBJROOT} ${STAGE_ROOT}
+
+CSU_DIR.${MACHINE_ARCH} ?= csu/${MACHINE_ARCH}
+CSU_DIR := ${CSU_DIR.${MACHINE_ARCH}}
+
+.if !empty(TIME_STAMP)
+TRACER= ${TIME_STAMP} ${:U}
+.endif
+
+# toolchains can be a pain - especially bootstrappping them
+.if ${MACHINE} == "host"
+MK_SHARED_TOOLCHAIN= no
+.endif
+.ifdef WITH_TOOLSDIR
+TOOLSDIR?= ${HOST_OBJTOP}/tools
+.elif defined(STAGE_HOST_OBJTOP) && exists(${STAGE_HOST_OBJTOP}/usr/bin)
+TOOLSDIR?= ${STAGE_HOST_OBJTOP}
+.endif
+.if ${.MAKE.LEVEL} == 0 && exists(${TOOLSDIR}/usr/bin)
+PATH:= ${PATH:S,:, ,g:@d@${exists(${TOOLSDIR}$d):?${TOOLSDIR}$d:}@:ts:}:${PATH}
+.export PATH
+.if exists(${TOOLSDIR}/usr/bin/cc)
+HOST_CC?= ${TOOLSDIR}/usr/bin/cc
+CC?= ${TOOLSDIR}/usr/bin/cc
+CXX?= ${TOOLSDIR}/usr/bin/c++
+.export HOST_CC CC CXX
+.endif
+.endif
+
+.if ${MACHINE:Nhost:Ncommon} != "" && ${MACHINE} != ${HOST_MACHINE}
+# cross-building
+.if !defined(FREEBSD_REVISION)
+FREEBSD_REVISION!= sed -n '/^REVISION=/{s,.*=,,;s,",,g;p; }' ${SRCTOP}/sys/conf/newvers.sh
+.export FREEBSD_REVISION
+.endif
+CROSS_TARGET_FLAGS= -target ${MACHINE_ARCH}-unknown-freebsd${FREEBSD_REVISION}
+CFLAGS+= ${CROSS_TARGET_FLAGS}
+ACFLAGS+= ${CROSS_TARGET_FLAGS}
+LDFLAGS+= -Wl,-m -Wl,elf_${MACHINE_ARCH}_fbsd
+.endif
Index: share/mk/local.sys.mk
===================================================================
--- share/mk/local.sys.mk
+++ share/mk/local.sys.mk
@@ -0,0 +1,61 @@
+# $FreeBSD$
+
+.if !defined(_TARGETS)
+# some things we do only once
+_TARGETS:= ${.TARGETS}
+.export _TARGETS
+.endif
+
+# some handy macros
+_this = ${.PARSEDIR:tA}/${.PARSEFILE}
+# some useful modifiers
+
+# A useful trick for testing multiple :M's against something
+# :L says to use the variable's name as its value - ie. literal
+# got = ${clean* destroy:${M_ListToMatch:S,V,.TARGETS,}}
+M_ListToMatch = L:@m@$${V:M$$m}@
+# match against our initial targets (see above)
+M_L_TARGETS = ${M_ListToMatch:S,V,_TARGETS,}
+
+# turn a list into a set of :N modifiers
+# NskipFoo = ${Foo:${M_ListToSkip}}
+M_ListToSkip= O:u:ts::S,:,:N,g:S,^,N,
+
+# type should be a builtin in any sh since about 1980,
+# AUTOCONF := ${autoconf:L:${M_whence}}
+M_type = @x@(type $$x 2> /dev/null); echo;@:sh:[0]:N* found*:[@]:C,[()],,g
+M_whence = ${M_type}:M/*:[1]
+
+# convert a path to a valid shell variable
+M_P2V = tu:C,[./-],_,g
+
+MAKE_PRINT_VAR_ON_ERROR+= \
+ .CURDIR \
+ .MAKE \
+ .OBJDIR \
+ .TARGETS \
+ DESTDIR \
+ LD_LIBRARY_PATH \
+ MACHINE \
+ MACHINE_ARCH \
+ MAKEOBJDIRPREFIX \
+ MAKESYSPATH \
+ MAKE_VERSION\
+ SRCTOP \
+ OBJTOP \
+ ${MAKE_PRINT_VAR_ON_ERROR_XTRAS}
+
+.if ${.MAKE.LEVEL} > 0
+MAKE_PRINT_VAR_ON_ERROR += .MAKE.MAKEFILES .PATH
+.endif
+
+# these are handy
+# we can use this for a cheap timestamp at the start of a target's script,
+# but not at the end - since make will expand both at the same time.
+TIME_STAMP_FMT = @ %s [%Y-%m-%d %T]
+TIME_STAMP = ${TIME_STAMP_FMT:localtime}
+# this will produce the same output but as of when date(1) is run.
+TIME_STAMP_DATE = `date '+${TIME_STAMP_FMT}'`
+TIME_STAMP_END?= ${TIME_STAMP_DATE}
+
+.include "src.sys.mk"
Index: share/mk/meta.autodep.mk
===================================================================
--- share/mk/meta.autodep.mk
+++ share/mk/meta.autodep.mk
@@ -0,0 +1,293 @@
+# $Id: meta.autodep.mk,v 1.36 2014/08/02 23:10:29 sjg Exp $
+
+#
+# @(#) Copyright (c) 2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+_this ?= ${.PARSEFILE}
+.if !target(__${_this}__)
+__${_this}__: .NOTMAIN
+
+.-include "local.autodep.mk"
+
+.if defined(SRCS)
+# it would be nice to be able to query .SUFFIXES
+OBJ_EXTENSIONS+= .o .po .lo .So
+
+# explicit dependencies help short-circuit .SUFFIX searches
+SRCS_DEP_FILTER+= N*.[hly]
+.for s in ${SRCS:${SRCS_DEP_FILTER:O:u:ts:}}
+.for e in ${OBJ_EXTENSIONS:O:u}
+.if !target(${s:T:R}$e)
+${s:T:R}$e: $s
+.endif
+.endfor
+.endfor
+.endif
+
+.if make(gendirdeps)
+# you are supposed to know what you are doing!
+UPDATE_DEPENDFILE = yes
+.elif !empty(.TARGETS) && !make(all)
+# do not update the *depend* files
+# unless we are building the entire directory or the default target.
+# NO means don't update .depend - or Makefile.depend*
+# no means update .depend but not Makefile.depend*
+UPDATE_DEPENDFILE = NO
+.elif ${.MAKEFLAGS:M-k} != ""
+# it is a bad idea to update anything
+UPDATE_DEPENDFILE = NO
+.endif
+
+_CURDIR ?= ${.CURDIR}
+_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
+
+.if ${.MAKE.LEVEL} == 0
+.if ${BUILD_AT_LEVEL0:Uyes:tl} == "no"
+UPDATE_DEPENDFILE = NO
+.endif
+.endif
+.if !exists(${_DEPENDFILE})
+_bootstrap_dirdeps = yes
+.endif
+_bootstrap_dirdeps ?= no
+UPDATE_DEPENDFILE ?= yes
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE}
+.endif
+
+.if !empty(XMAKE_META_FILE)
+.if exists(${.OBJDIR}/${XMAKE_META_FILE})
+# we cannot get accurate dependencies from an update build
+UPDATE_DEPENDFILE = NO
+.else
+META_XTRAS += ${XMAKE_META_FILE}
+.endif
+.endif
+
+.if ${_bootstrap_dirdeps} == "yes" || exists(${_DEPENDFILE})
+# if it isn't supposed to be touched by us the Makefile should have
+# UPDATE_DEPENDFILE = no
+WANT_UPDATE_DEPENDFILE ?= yes
+.endif
+
+.if ${WANT_UPDATE_DEPENDFILE:Uno:tl} != "no"
+.if ${.MAKE.MODE:Mmeta*} == "" || ${.MAKE.MODE:M*read*} != ""
+UPDATE_DEPENDFILE = no
+.endif
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE}
+.endif
+
+.if ${UPDATE_DEPENDFILE:tl} == "yes"
+# sometimes we want .meta files generated to aid debugging/error detection
+# but do not want to consider them for dependencies
+# for example the result of running configure
+# just make sure this is not empty
+META_FILE_FILTER ?= N.meta
+# never consider these
+META_FILE_FILTER += Ndirdeps.cache*
+
+.if !empty(DPADD)
+# if we have any non-libs in DPADD,
+# they probably need to be paid attention to
+.if !empty(DPLIBS)
+FORCE_DPADD = ${DPADD:${DPLIBS:${M_ListToSkip}}:${DPADD_LAST:${M_ListToSkip}}}
+.else
+_nonlibs := ${DPADD:T:Nlib*:N*include}
+.if !empty(_nonlibs)
+FORCE_DPADD += ${_nonlibs:@x@${DPADD:M*/$x}@}
+.endif
+.endif
+.endif
+
+.if !make(gendirdeps)
+.END: gendirdeps
+.endif
+
+# if we don't have OBJS, then .depend isn't useful
+.if !target(.depend) && (!empty(OBJS) || ${.ALLTARGETS:M*.o} != "")
+# some makefiles and/or targets contain
+# circular dependencies if you dig too deep
+# (as meta mode is apt to do)
+# so we provide a means of suppressing them.
+# the input to the loop below is target: dependency
+# with just one dependency per line.
+# Also some targets are not really local, or use random names.
+# Use local.autodep.mk to provide local additions!
+SUPPRESS_DEPEND += \
+ ${SB:S,/,_,g}* \
+ *:y.tab.c \
+ *.c:*.c \
+ *.h:*.h
+
+.NOPATH: .depend
+# we use ${.MAKE.META.CREATED} to trigger an update but
+# we process using ${.MAKE.META.FILES}
+# the double $$ defers initial evaluation
+# if necessary, we fake .po dependencies, just so the result
+# in Makefile.depend* is stable
+# The current objdir may be referred to in various ways
+OBJDIR_REFS += ${.OBJDIR} ${.OBJDIR:tA} ${_OBJDIR} ${RELOBJTOP}/${RELDIR}
+_depend = .depend
+# it would be nice to be able to get .SUFFIXES as ${.SUFFIXES}
+# we actually only care about the .SUFFIXES of files that might be
+# generated by tools like yacc.
+DEPEND_SUFFIXES += .c .h .cpp .hpp .cxx .hxx .cc .hh
+.depend: .NOMETA $${.MAKE.META.CREATED} ${_this}
+ @echo "Updating $@: ${.OODATE:T:[1..8]}"
+ @egrep -i '^R .*\.(${DEPEND_SUFFIXES:tl:O:u:S,^.,,:ts|})$$' /dev/null ${.MAKE.META.FILES:T:O:u:${META_FILE_FILTER:ts:}:M*o.meta} | \
+ sed -e 's, \./, ,${OBJDIR_REFS:O:u:@d@;s, $d/, ,@};/\//d' \
+ -e 's,^\([^/][^/]*\).meta...[0-9]* ,\1: ,' | \
+ sort -u | \
+ while read t d; do \
+ case "$$d:" in $$t) continue;; esac; \
+ case "$$t$$d" in ${SUPPRESS_DEPEND:U.:O:u:ts|}) continue;; esac; \
+ echo $$t $$d; \
+ done > $@.${.MAKE.PID}
+ @case "${.MAKE.META.FILES:T:M*.po.*}" in \
+ *.po.*) mv $@.${.MAKE.PID} $@;; \
+ *) { cat $@.${.MAKE.PID}; \
+ sed 's,\.So:,.o:,;s,\.o:,.po:,' $@.${.MAKE.PID}; } | sort -u > $@; \
+ rm -f $@.${.MAKE.PID};; \
+ esac
+.else
+# make sure this exists
+.depend:
+# do _not_ assume that .depend is in any fit state for us to use
+CAT_DEPEND = /dev/null
+.if ${.MAKE.LEVEL} > 0
+.export CAT_DEPEND
+.endif
+_depend =
+.endif
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,} _depend=${_depend}
+.endif
+
+.if ${UPDATE_DEPENDFILE} == "yes"
+gendirdeps: ${_DEPENDFILE}
+.endif
+
+.if !target(${_DEPENDFILE})
+.if ${_bootstrap_dirdeps} == "yes"
+# We are boot-strapping a new directory
+# Use DPADD to seed DIRDEPS
+.if !empty(DPADD)
+# anything which matches ${_OBJROOT}* but not ${_OBJTOP}*
+# needs to be qualified in DIRDEPS
+# The pseudo machine "host" is used for HOST_TARGET
+DIRDEPS = \
+ ${DPADD:M${_OBJTOP}*:H:C,${_OBJTOP}[^/]*/,,:N.:O:u} \
+ ${DPADD:M${_OBJROOT}*:N${_OBJTOP}*:H:S,${_OBJROOT},,:C,^([^/]+)/(.*),\2.\1,:S,${HOST_TARGET}$,host,:N.*:O:u}
+
+.endif
+.endif
+
+_gendirdeps_mutex =
+.if defined(NEED_GENDIRDEPS_MUTEX)
+# If a src dir gets built with multiple object dirs,
+# we need a mutex. Obviously, this is best avoided.
+# Note if .MAKE.DEPENDFILE is common for all ${MACHINE}
+# you either need to mutex, or ensure only one machine builds at a time!
+# lockf is an example of a suitable tool
+LOCKF ?= /usr/bin/lockf
+.if exists(${LOCKF})
+GENDIRDEPS_MUTEXER ?= ${LOCKF} -k
+.endif
+.if empty(GENDIRDEPS_MUTEXER)
+.error NEED_GENDIRDEPS_MUTEX defined, but GENDIRDEPS_MUTEXER not set
+.else
+_gendirdeps_mutex = ${GENDIRDEPS_MUTEXER} ${GENDIRDEPS_MUTEX:U${_CURDIR}/Makefile}
+.endif
+.endif
+
+# If we have META_XTRAS we most likely did not create them
+# but we need to behave as if we did.
+# Avoid adding glob patterns to .MAKE.META.CREATED though.
+.MAKE.META.CREATED += ${META_XTRAS:N*\**:O:u}
+
+.if make(gendirdeps)
+META_FILES = *.meta
+.elif ${OPTIMIZE_OBJECT_META_FILES:Uno:tl} == "no"
+META_FILES = ${.MAKE.META.FILES:T:N.depend*:O:u}
+.else
+# if we have 1000's of .o.meta, .So.meta etc we need only look at one set
+# it is left as an exercise for the reader to work out what this does
+META_FILES = ${.MAKE.META.FILES:T:N.depend*:N*o.meta:O:u} \
+ ${.MAKE.META.FILES:T:M*.${.MAKE.META.FILES:M*o.meta:R:E:O:u:[1]}.meta:O:u}
+.endif
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} xtras=${META_XTRAS}
+.endif
+
+.if ${.MAKE.LEVEL} > 0 && !empty(GENDIRDEPS_FILTER)
+.export GENDIRDEPS_FILTER
+.endif
+
+# we might have .../ in MAKESYSPATH
+_makesyspath:= ${_PARSEDIR}
+${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.META.CREATED}
+ @echo Checking $@: ${.OODATE:T:[1..8]}
+ @(cd . && \
+ SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS:O:u}' \
+ DPADD='${FORCE_DPADD:O:u}' ${_gendirdeps_mutex} \
+ MAKESYSPATH=${_makesyspath} \
+ ${.MAKE} -f gendirdeps.mk RELDIR=${RELDIR} _DEPENDFILE=${_DEPENDFILE} \
+ META_FILES='${META_XTRAS:T:O:u} ${META_FILES:T:O:u:${META_FILE_FILTER:ts:}}')
+ @test -s $@ && touch $@; :
+.endif
+
+.endif
+.endif
+
+.if ${_bootstrap_dirdeps} == "yes"
+.if ${BUILD_AT_LEVEL0:Uno} == "no"
+DIRDEPS+= ${RELDIR}.${TARGET_SPEC:U${MACHINE}}
+.endif
+# make sure this is included at least once
+.include <dirdeps.mk>
+.else
+${_DEPENDFILE}: .PRECIOUS
+.endif
+
+CLEANFILES += *.meta filemon.* *.db
+
+# these make it easy to gather some stats
+now_utc = ${%s:L:gmtime}
+start_utc := ${now_utc}
+
+meta_stats= meta=${empty(.MAKE.META.FILES):?0:${.MAKE.META.FILES:[#]}} \
+ created=${empty(.MAKE.META.CREATED):?0:${.MAKE.META.CREATED:[#]}}
+
+#.END: _reldir_finish
+.if target(gendirdeps)
+_reldir_finish: gendirdeps
+.endif
+_reldir_finish: .NOMETA
+ @echo "${TIME_STAMP} Finished ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}"
+
+#.ERROR: _reldir_failed
+_reldir_failed: .NOMETA
+ @echo "${TIME_STAMP} Failed ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}"
+
+.if defined(WITH_META_STATS) && ${.MAKE.LEVEL} > 0
+.END: _reldir_finish
+.ERROR: _reldir_failed
+.endif
+
+.endif
Index: share/mk/meta.stage.mk
===================================================================
--- share/mk/meta.stage.mk
+++ share/mk/meta.stage.mk
@@ -0,0 +1,279 @@
+# $Id: meta.stage.mk,v 1.35 2015/05/20 06:40:33 sjg Exp $
+#
+# @(#) Copyright (c) 2011, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} != ""
+# this is generally safer anyway
+_dirdep = ${RELDIR}.${MACHINE}
+.else
+_dirdep = ${RELDIR}
+.endif
+
+# this allows us to trace dependencies back to their src dir
+.dirdep:
+ @echo '${_dirdep}' > $@
+
+.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == ""
+_stage_file_basename = `basename $$f`
+_stage_target_dirname = `dirname $$t`
+.else
+_stage_file_basename = $${f\#\#*/}
+_stage_target_dirname = $${t%/*}
+.endif
+
+_OBJROOT ?= ${OBJROOT:U${OBJTOP:H}}
+.if ${_OBJROOT:M*/} != ""
+_objroot ?= ${_OBJROOT:tA}/
+.else
+_objroot ?= ${_OBJROOT:tA}
+.endif
+
+# make sure this is global
+_STAGED_DIRS ?=
+.export _STAGED_DIRS
+# add each dir we stage to to _STAGED_DIRS
+# and make sure we have absolute paths so that bmake
+# will match against .MAKE.META.BAILIWICK
+STAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@
+# convert _STAGED_DIRS into suitable filters
+GENDIRDEPS_FILTER += Nnot-empty-is-important \
+ ${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \
+ ${_STAGED_DIRS:O:u:M${_objroot}*:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,}
+
+LN_CP_SCRIPT = LnCp() { \
+ rm -f $$2 2> /dev/null; \
+ ln $$1 $$2 2> /dev/null || \
+ cp -p $$1 $$2; }
+
+# it is an error for more than one src dir to try and stage
+# the same file
+STAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \
+ t=$$1; \
+ if [ -s $$t.dirdep ]; then \
+ cmp -s .dirdep $$t.dirdep && return; \
+ echo "ERROR: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \
+ exit 1; \
+ fi; \
+ LnCp .dirdep $$t.dirdep || exit 1; }
+
+# common logic for staging files
+# this all relies on RELDIR being set to a subdir of SRCTOP
+# we use ln(1) if we can, else cp(1)
+STAGE_FILE_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageFiles() { \
+ case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \
+ dest=$$1; shift; \
+ mkdir -p $$dest; \
+ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
+ for f in "$$@"; do \
+ case "$$f" in */*) t=$$dest/${_stage_file_basename};; *) t=$$dest/$$f;; esac; \
+ StageDirdep $$t; \
+ LnCp $$f $$t || exit 1; \
+ [ -z "$$mode" ] || chmod $$mode $$t; \
+ done; :; }
+
+STAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \
+ case "$$1" in "") return;; --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \
+ dest=$$1; shift; \
+ mkdir -p $$dest; \
+ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
+ while test $$\# -ge 2; do \
+ l=$$ldest$$1; shift; \
+ t=$$dest/$$1; \
+ case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
+ shift; \
+ StageDirdep $$t; \
+ rm -f $$t 2>/dev/null; \
+ ln $$lnf $$l $$t || exit 1; \
+ done; :; }
+
+STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \
+ case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \
+ dest=$$1; shift; \
+ mkdir -p $$dest; \
+ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
+ while test $$\# -ge 2; do \
+ s=$$1; shift; \
+ t=$$dest/$$1; \
+ case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
+ shift; \
+ StageDirdep $$t; \
+ LnCp $$s $$t || exit 1; \
+ [ -z "$$mode" ] || chmod $$mode $$t; \
+ done; :; }
+
+# this is simple, a list of the "staged" files depends on this,
+_STAGE_BASENAME_USE: .USE ${.TARGET:T}
+ @${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T}
+
+_STAGE_AS_BASENAME_USE: .USE ${.TARGET:T}
+ @${STAGE_AS_SCRIPT}; StageAs ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} ${STAGE_AS_${.TARGET:T}:U${.TARGET:T}}
+
+.if !empty(STAGE_INCSDIR)
+STAGE_TARGETS += stage_incs
+STAGE_INCS ?= ${.ALLSRC:N.dirdep}
+
+stage_includes: stage_incs
+stage_incs: .dirdep
+ @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS}
+ @touch $@
+.endif
+
+.if !empty(STAGE_LIBDIR)
+STAGE_TARGETS += stage_libs
+
+STAGE_LIBS ?= ${.ALLSRC:N.dirdep}
+
+stage_libs: .dirdep
+ @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS}
+.if !defined(NO_SHLIB_LINKS)
+.if !empty(SHLIB_LINKS)
+ @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \
+ ${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@}
+.elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME)
+ @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK} ${SYMLINKS:T}
+.endif
+.endif
+ @touch $@
+.endif
+
+.if !empty(STAGE_DIR)
+STAGE_SETS += _default
+STAGE_DIR._default = ${STAGE_DIR}
+STAGE_LINKS_DIR._default = ${STAGE_LINKS_DIR:U${STAGE_OBJTOP}}
+STAGE_SYMLINKS_DIR._default = ${STAGE_SYMLINKS_DIR:U${STAGE_OBJTOP}}
+STAGE_FILES._default = ${STAGE_FILES}
+STAGE_LINKS._default = ${STAGE_LINKS}
+STAGE_SYMLINKS._default = ${STAGE_SYMLINKS}
+STAGE_FILES ?= ${.ALLSRC:N.dirdep:Nstage_*}
+STAGE_SYMLINKS ?= ${.ALLSRC:T:N.dirdep:Nstage_*}
+.endif
+
+.if !empty(STAGE_SETS)
+CLEANFILES += ${STAGE_SETS:@s@stage*$s@}
+
+# some makefiles need to populate multiple directories
+.for s in ${STAGE_SETS:O:u}
+STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep}
+STAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep}
+STAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP}
+STAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP}
+
+STAGE_TARGETS += stage_files
+.if $s != "_default"
+stage_files: stage_files.$s
+stage_files.$s: .dirdep
+.else
+stage_files: .dirdep
+.endif
+ @${STAGE_FILE_SCRIPT}; StageFiles ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_FILES.$s}
+ @touch $@
+
+STAGE_TARGETS += stage_links
+.if $s != "_default"
+stage_links: stage_links.$s
+stage_links.$s: .dirdep
+.else
+stage_links: .dirdep
+.endif
+ @${STAGE_LINKS_SCRIPT}; StageLinks ${STAGE_LINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_LINKS.$s}
+ @touch $@
+
+STAGE_TARGETS += stage_symlinks
+.if $s != "_default"
+stage_symlinks: stage_symlinks.$s
+stage_symlinks.$s: .dirdep
+.else
+stage_symlinks: .dirdep
+.endif
+ @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_SYMLINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_SYMLINKS.$s}
+ @touch $@
+
+.endfor
+.endif
+
+.if !empty(STAGE_AS_SETS)
+CLEANFILES += ${STAGE_AS_SETS:@s@stage*$s@}
+
+STAGE_TARGETS += stage_as
+
+# sometimes things need to be renamed as they are staged
+# each ${file} will be staged as ${STAGE_AS_${file:T}}
+# one could achieve the same with SYMLINKS
+.for s in ${STAGE_AS_SETS:O:u}
+STAGE_AS.$s ?= ${.ALLSRC:N.dirdep}
+
+stage_as: stage_as.$s
+stage_as.$s: .dirdep
+ @${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}}}@}
+ @touch $@
+
+.endfor
+.endif
+
+CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes
+
+# stage_*links usually needs to follow any others.
+.for t in ${STAGE_TARGETS:N*links:O:u}
+.ORDER: $t stage_links
+.ORDER: $t stage_symlinks
+.endfor
+
+# make sure this exists
+staging:
+
+# generally we want staging to wait until everything else is done
+STAGING_WAIT ?= .WAIT
+
+.if ${.MAKE.LEVEL} > 0
+all: ${STAGING_WAIT} staging
+.endif
+
+.if exists(${.PARSEDIR}/stage-install.sh) && !defined(STAGE_INSTALL)
+# this will run install(1) and then followup with .dirdep files.
+STAGE_INSTALL := sh ${.PARSEDIR:tA}/stage-install.sh INSTALL="${INSTALL}" OBJDIR=${.OBJDIR:tA}
+.endif
+
+# if ${INSTALL} gets run during 'all' assume it is for staging?
+.if ${.TARGETS:Nall} == "" && defined(STAGE_INSTALL)
+INSTALL := ${STAGE_INSTALL}
+.if target(beforeinstall)
+beforeinstall: .dirdep
+.endif
+.endif
+.NOPATH: ${STAGE_FILES}
+
+.if !empty(STAGE_TARGETS)
+MK_STALE_STAGED?= no
+.if ${MK_STALE_STAGED} == "yes"
+all: stale_staged
+# get a list of paths that we have just staged
+# get a list of paths that we have previously staged to those same dirs
+# anything in the 2nd list but not the first is stale - remove it.
+stale_staged: staging .NOMETA
+ @egrep '^[WL] .*${STAGE_OBJTOP}' /dev/null ${.MAKE.META.FILES:M*stage_*} | \
+ sed "/\.dirdep/d;s,.* '*\(${STAGE_OBJTOP}/[^ '][^ ']*\).*,\1," | \
+ sort > ${.TARGET}.staged1
+ @grep -l '${_dirdep}' /dev/null ${_STAGED_DIRS:M${STAGE_OBJTOP}*:O:u:@d@$d/*.dirdep@} | \
+ sed 's,\.dirdep,,' | sort > ${.TARGET}.staged2
+ @comm -13 ${.TARGET}.staged1 ${.TARGET}.staged2 > ${.TARGET}.stale
+ @test ! -s ${.TARGET}.stale || { \
+ echo "Removing stale staged files..."; \
+ sed 's,.*,& &.dirdep,' ${.TARGET}.stale | xargs rm -f; }
+
+.endif
+.endif
+.endif
Index: share/mk/meta.subdir.mk
===================================================================
--- share/mk/meta.subdir.mk
+++ share/mk/meta.subdir.mk
@@ -0,0 +1,79 @@
+# $Id: meta.subdir.mk,v 1.10 2012/07/03 05:26:46 sjg Exp $
+
+#
+# @(#) Copyright (c) 2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !defined(NO_SUBDIR) && !empty(SUBDIR)
+.if make(destroy*) || make(clean*)
+.MAKE.MODE = compat
+.if !commands(destroy)
+.-include <bsd.obj.mk>
+.endif
+.elif ${.MAKE.LEVEL} == 0
+
+.MAIN: all
+
+.if !exists(${.CURDIR}/${.MAKE.DEPENDFILE:T}) || make(gendirdeps)
+# start with this
+DIRDEPS = ${SUBDIR:N.WAIT:O:u:@d@${RELDIR}/$d@}
+
+.if make(gendirdeps)
+.include <meta.autodep.mk>
+.else
+# this is the cunning bit
+# actually it is probably a bit risky
+# since we may pickup subdirs which are not relevant
+# the alternative is a walk through the tree though
+# which is difficult without a sub-make.
+
+.if defined(BOOTSTRAP_DEPENDFILES)
+_find_name = ${.MAKE.MAKEFILE_PREFERENCE:@m@-o -name $m@:S,^-o,,1}
+DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@}
+.elif ${.MAKE.DEPENDFILE:E} == ${MACHINE} && defined(ALL_MACHINES)
+# we want to find Makefile.depend.* ie for all machines
+# and turn the dirs into dir.<machine>
+_find_name = -name '${.MAKE.DEPENDFILE:T:R}*'
+DIRDEPS = ${_subdeps:O:u:${NIgnoreFiles}:@d@${RELDIR}/${d:H}.${d:E}@:S,.${MACHINE}$,,:S,.depend$,,}
+.else
+# much simpler
+_find_name = -name ${.MAKE.DEPENDFILE:T}
+.if ${.MAKE.DEPENDFILE:E} == ${MACHINE}
+_find_name += -o -name ${.MAKE.DEPENDFILE:T:R}
+.endif
+DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@}
+.endif
+
+_subdeps != cd ${.CURDIR} && \
+ find ${SUBDIR:N.WAIT} -type f \( ${_find_name} \) -print -o \
+ -name .svn -prune 2> /dev/null; echo
+
+.if empty(_subdeps)
+DIRDEPS =
+.else
+# clean up if needed
+DIRDEPS := ${DIRDEPS:S,^./,,:S,/./,/,g:${SUBDIREPS_FILTER:Uu}}
+.endif
+# we just dealt with it, if we leave it defined,
+# dirdeps.mk will compute some interesting combinations.
+.undef ALL_MACHINES
+
+DEP_RELDIR = ${RELDIR}
+.include <dirdeps.mk>
+.endif
+.endif
+.else
+all: .PHONY
+.endif
+
+.endif
Index: share/mk/meta.sys.mk
===================================================================
--- share/mk/meta.sys.mk
+++ share/mk/meta.sys.mk
@@ -0,0 +1,142 @@
+# $Id: meta.sys.mk,v 1.19 2014/08/02 23:16:02 sjg Exp $
+
+#
+# @(#) Copyright (c) 2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# include this if you want to enable meta mode
+# for maximum benefit, requires filemon(4) driver.
+
+.if ${MAKE_VERSION:U0} > 20100901
+.if !target(.ERROR)
+
+.-include "local.meta.sys.mk"
+
+# absoulte path to what we are reading.
+_PARSEDIR = ${.PARSEDIR:tA}
+
+META_MODE += meta verbose
+.MAKE.MODE ?= ${META_MODE}
+
+.if ${.MAKE.LEVEL} == 0
+_make_mode := ${.MAKE.MODE} ${META_MODE}
+.if ${_make_mode:M*read*} != "" || ${_make_mode:M*nofilemon*} != ""
+# tell everyone we are not updating Makefile.depend*
+UPDATE_DEPENDFILE = NO
+.export UPDATE_DEPENDFILE
+.endif
+.if ${UPDATE_DEPENDFILE:Uyes:tl} == "no" && !exists(/dev/filemon)
+# we should not get upset
+META_MODE += nofilemon
+.export META_MODE
+.endif
+.endif
+
+.if !defined(NO_SILENT)
+.if ${MAKE_VERSION} > 20110818
+# only be silent when we have a .meta file
+META_MODE += silent=yes
+.else
+.SILENT:
+.endif
+.endif
+
+# make defaults .MAKE.DEPENDFILE to .depend
+# that won't work for us.
+.if ${.MAKE.DEPENDFILE} == ".depend"
+.undef .MAKE.DEPENDFILE
+.endif
+
+# if you don't cross build for multiple MACHINEs concurrently, then
+# .MAKE.DEPENDFILE = Makefile.depend
+# probably makes sense - you can set that in local.sys.mk
+.MAKE.DEPENDFILE ?= Makefile.depend.${MACHINE}
+
+# we use the pseudo machine "host" for the build host.
+# this should be taken care of before we get here
+.if ${OBJTOP:Ua} == ${HOST_OBJTOP:Ub}
+MACHINE = host
+.endif
+
+.if ${.MAKE.LEVEL} == 0
+# it can be handy to know which MACHINE kicked off the build
+# for example, if using Makefild.depend for multiple machines,
+# allowing only MACHINE0 to update can keep things simple.
+MACHINE0 := ${MACHINE}
+.export MACHINE0
+
+.if defined(PYTHON) && exists(${PYTHON})
+# we prefer the python version of this - it is much faster
+META2DEPS ?= ${.PARSEDIR}/meta2deps.py
+.else
+META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
+.endif
+META2DEPS := ${META2DEPS}
+.export META2DEPS
+.endif
+
+MAKE_PRINT_VAR_ON_ERROR += \
+ .ERROR_TARGET \
+ .ERROR_META_FILE \
+ .MAKE.LEVEL \
+ MAKEFILE \
+ .MAKE.MODE
+
+.if !defined(SB) && defined(SRCTOP)
+SB = ${SRCTOP:H}
+.endif
+ERROR_LOGDIR ?= ${SB}/error
+meta_error_log = ${ERROR_LOGDIR}/meta-${.MAKE.PID}.log
+
+# we are not interested in make telling us a failure happened elsewhere
+.ERROR: _metaError
+_metaError: .NOMETA .NOTMAIN
+ -@[ "${.ERROR_META_FILE}" ] && { \
+ grep -q 'failure has been detected in another branch' ${.ERROR_META_FILE} && exit 0; \
+ mkdir -p ${meta_error_log:H}; \
+ cp ${.ERROR_META_FILE} ${meta_error_log}; \
+ echo "ERROR: log ${meta_error_log}" >&2; }; :
+
+.endif
+
+# Are we, after all, in meta mode?
+.if ${.MAKE.MODE:Mmeta*} != ""
+MKDEP_MK = meta.autodep.mk
+
+# if we think we are updating dependencies,
+# then filemon had better be present
+.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" && !exists(/dev/filemon)
+.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded.
+.endif
+
+.if ${.MAKE.LEVEL} == 0
+# make sure dirdeps target exists and do it first
+all: dirdeps .WAIT
+dirdeps:
+.NOPATH: dirdeps
+
+.if defined(ALL_MACHINES)
+# the first .MAIN: is what counts
+# by default dirdeps is all we want at level0
+.MAIN: dirdeps
+# tell dirdeps.mk what we want
+BUILD_AT_LEVEL0 = no
+.endif
+.if ${.TARGETS:Nall} == ""
+# it works best if we do everything via sub-makes
+BUILD_AT_LEVEL0 ?= no
+.endif
+
+.endif
+.endif
+.endif
Index: share/mk/meta2deps.py
===================================================================
--- share/mk/meta2deps.py
+++ share/mk/meta2deps.py
@@ -0,0 +1,713 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+"""
+This script parses each "meta" file and extracts the
+information needed to deduce build and src dependencies.
+
+It works much the same as the original shell script, but is
+*much* more efficient.
+
+The parsing work is handled by the class MetaFile.
+We only pay attention to a subset of the information in the
+"meta" files. Specifically:
+
+'CWD' to initialize our notion.
+
+'C' to track chdir(2) on a per process basis
+
+'R' files read are what we really care about.
+ directories read, provide a clue to resolving
+ subsequent relative paths. That is if we cannot find
+ them relative to 'cwd', we check relative to the last
+ dir read.
+
+'W' files opened for write or read-write,
+ for filemon V3 and earlier.
+
+'E' files executed.
+
+'L' files linked
+
+'V' the filemon version, this record is used as a clue
+ that we have reached the interesting bit.
+
+"""
+
+"""
+RCSid:
+ $Id: meta2deps.py,v 1.18 2015/04/03 18:23:25 sjg Exp $
+
+ Copyright (c) 2011-2013, Juniper Networks, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+
+import os, re, sys
+
+def getv(dict, key, d=None):
+ """Lookup key in dict and return value or the supplied default."""
+ if key in dict:
+ return dict[key]
+ return d
+
+def resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
+ """
+ Return an absolute path, resolving via cwd or last_dir if needed.
+ """
+ if path.endswith('/.'):
+ path = path[0:-2]
+ if len(path) > 0 and path[0] == '/':
+ return path
+ if path == '.':
+ return cwd
+ if path.startswith('./'):
+ return cwd + path[1:]
+ if last_dir == cwd:
+ last_dir = None
+ for d in [last_dir, cwd]:
+ if not d:
+ continue
+ p = '/'.join([d,path])
+ if debug > 2:
+ print("looking for:", p, end=' ', file=debug_out)
+ if not os.path.exists(p):
+ if debug > 2:
+ print("nope", file=debug_out)
+ p = None
+ continue
+ if debug > 2:
+ print("found:", p, file=debug_out)
+ return p
+ return None
+
+def abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
+ """
+ Return an absolute path, resolving via cwd or last_dir if needed.
+ this gets called a lot, so we try to avoid calling realpath
+ until we know we have something.
+ """
+ rpath = resolve(path, cwd, last_dir, debug, debug_out)
+ if rpath:
+ path = rpath
+ if (path.find('/') < 0 or
+ path.find('./') > 0 or
+ path.endswith('/..') or
+ os.path.islink(path)):
+ return os.path.realpath(path)
+ return path
+
+def sort_unique(list, cmp=None, key=None, reverse=False):
+ list.sort(cmp, key, reverse)
+ nl = []
+ le = None
+ for e in list:
+ if e == le:
+ continue
+ nl.append(e)
+ return nl
+
+def add_trims(x):
+ return ['/' + x + '/',
+ '/' + x,
+ x + '/',
+ x]
+
+class MetaFile:
+ """class to parse meta files generated by bmake."""
+
+ conf = None
+ dirdep_re = None
+ host_target = None
+ srctops = []
+ objroots = []
+ excludes = []
+ seen = {}
+ obj_deps = []
+ src_deps = []
+ file_deps = []
+
+ def __init__(self, name, conf={}):
+ """if name is set we will parse it now.
+ conf can have the follwing keys:
+
+ SRCTOPS list of tops of the src tree(s).
+
+ CURDIR the src directory 'bmake' was run from.
+
+ RELDIR the relative path from SRCTOP to CURDIR
+
+ MACHINE the machine we built for.
+ set to 'none' if we are not cross-building.
+ More specifically if machine cannot be deduced from objdirs.
+
+ TARGET_SPEC
+ Sometimes MACHINE isn't enough.
+
+ HOST_TARGET
+ when we build for the pseudo machine 'host'
+ the object tree uses HOST_TARGET rather than MACHINE.
+
+ OBJROOTS a list of the common prefix for all obj dirs it might
+ end in '/' or '-'.
+
+ DPDEPS names an optional file to which per file dependencies
+ will be appended.
+ For example if 'some/path/foo.h' is read from SRCTOP
+ then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output.
+ This can allow 'bmake' to learn all the dirs within
+ the tree that depend on 'foo.h'
+
+ EXCLUDES
+ A list of paths to ignore.
+ ccache(1) can otherwise be trouble.
+
+ debug desired debug level
+
+ debug_out open file to send debug output to (sys.stderr)
+
+ """
+
+ self.name = name
+ self.debug = getv(conf, 'debug', 0)
+ self.debug_out = getv(conf, 'debug_out', sys.stderr)
+
+ self.machine = getv(conf, 'MACHINE', '')
+ self.machine_arch = getv(conf, 'MACHINE_ARCH', '')
+ self.target_spec = getv(conf, 'TARGET_SPEC', '')
+ self.curdir = getv(conf, 'CURDIR')
+ self.reldir = getv(conf, 'RELDIR')
+ self.dpdeps = getv(conf, 'DPDEPS')
+ self.line = 0
+
+ if not self.conf:
+ # some of the steps below we want to do only once
+ self.conf = conf
+ self.host_target = getv(conf, 'HOST_TARGET')
+ for srctop in getv(conf, 'SRCTOPS', []):
+ if srctop[-1] != '/':
+ srctop += '/'
+ if not srctop in self.srctops:
+ self.srctops.append(srctop)
+ _srctop = os.path.realpath(srctop)
+ if _srctop[-1] != '/':
+ _srctop += '/'
+ if not _srctop in self.srctops:
+ self.srctops.append(_srctop)
+
+ trim_list = add_trims(self.machine)
+ if self.machine == 'host':
+ trim_list += add_trims(self.host_target)
+ if self.target_spec:
+ trim_list += add_trims(self.target_spec)
+
+ for objroot in getv(conf, 'OBJROOTS', []):
+ for e in trim_list:
+ if objroot.endswith(e):
+ # this is not what we want - fix it
+ objroot = objroot[0:-len(e)]
+ if e.endswith('/'):
+ objroot += '/'
+ if not objroot in self.objroots:
+ self.objroots.append(objroot)
+ _objroot = os.path.realpath(objroot)
+ if objroot[-1] == '/':
+ _objroot += '/'
+ if not _objroot in self.objroots:
+ self.objroots.append(_objroot)
+
+ # we want the longest match
+ self.srctops.sort(reverse=True)
+ self.objroots.sort(reverse=True)
+
+ self.excludes = getv(conf, 'EXCLUDES', [])
+
+ if self.debug:
+ print("host_target=", self.host_target, file=self.debug_out)
+ print("srctops=", self.srctops, file=self.debug_out)
+ print("objroots=", self.objroots, file=self.debug_out)
+ print("excludes=", self.excludes, file=self.debug_out)
+
+ self.dirdep_re = re.compile(r'([^/]+)/(.+)')
+
+ if self.dpdeps and not self.reldir:
+ if self.debug:
+ print("need reldir:", end=' ', file=self.debug_out)
+ if self.curdir:
+ srctop = self.find_top(self.curdir, self.srctops)
+ if srctop:
+ self.reldir = self.curdir.replace(srctop,'')
+ if self.debug:
+ print(self.reldir, file=self.debug_out)
+ if not self.reldir:
+ self.dpdeps = None # we cannot do it?
+
+ self.cwd = os.getcwd() # make sure this is initialized
+ self.last_dir = self.cwd
+
+ if name:
+ self.try_parse()
+
+ def reset(self):
+ """reset state if we are being passed meta files from multiple directories."""
+ self.seen = {}
+ self.obj_deps = []
+ self.src_deps = []
+ self.file_deps = []
+
+ def dirdeps(self, sep='\n'):
+ """return DIRDEPS"""
+ return sep.strip() + sep.join(self.obj_deps)
+
+ def src_dirdeps(self, sep='\n'):
+ """return SRC_DIRDEPS"""
+ return sep.strip() + sep.join(self.src_deps)
+
+ def file_depends(self, out=None):
+ """Append DPDEPS_${file} += ${RELDIR}
+ for each file we saw, to the output file."""
+ if not self.reldir:
+ return None
+ for f in sort_unique(self.file_deps):
+ print('DPDEPS_%s += %s' % (f, self.reldir), file=out)
+
+ def seenit(self, dir):
+ """rememer that we have seen dir."""
+ self.seen[dir] = 1
+
+ def add(self, list, data, clue=''):
+ """add data to list if it isn't already there."""
+ if data not in list:
+ list.append(data)
+ if self.debug:
+ print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out)
+
+ def find_top(self, path, list):
+ """the logical tree may be split across multiple trees"""
+ for top in list:
+ if path.startswith(top):
+ if self.debug > 2:
+ print("found in", top, file=self.debug_out)
+ return top
+ return None
+
+ def find_obj(self, objroot, dir, path, input):
+ """return path within objroot, taking care of .dirdep files"""
+ ddep = None
+ for ddepf in [path + '.dirdep', dir + '/.dirdep']:
+ if not ddep and os.path.exists(ddepf):
+ ddep = open(ddepf, 'r').readline().strip('# \n')
+ if self.debug > 1:
+ print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out)
+ if ddep.endswith(self.machine):
+ ddep = ddep[0:-(1+len(self.machine))]
+ elif self.target_spec and ddep.endswith(self.target_spec):
+ ddep = ddep[0:-(1+len(self.target_spec))]
+
+ if not ddep:
+ # no .dirdeps, so remember that we've seen the raw input
+ self.seenit(input)
+ self.seenit(dir)
+ if self.machine == 'none':
+ if dir.startswith(objroot):
+ return dir.replace(objroot,'')
+ return None
+ m = self.dirdep_re.match(dir.replace(objroot,''))
+ if m:
+ ddep = m.group(2)
+ dmachine = m.group(1)
+ if dmachine != self.machine:
+ if not (self.machine == 'host' and
+ dmachine == self.host_target):
+ if self.debug > 2:
+ print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out)
+ ddep += '.' + dmachine
+
+ return ddep
+
+ def try_parse(self, name=None, file=None):
+ """give file and line number causing exception"""
+ try:
+ self.parse(name, file)
+ except:
+ # give a useful clue
+ print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr)
+ raise
+
+ def parse(self, name=None, file=None):
+ """A meta file looks like:
+
+ # Meta data file "path"
+ CMD "command-line"
+ CWD "cwd"
+ TARGET "target"
+ -- command output --
+ -- filemon acquired metadata --
+ # buildmon version 3
+ V 3
+ C "pid" "cwd"
+ E "pid" "path"
+ F "pid" "child"
+ R "pid" "path"
+ W "pid" "path"
+ X "pid" "status"
+ D "pid" "path"
+ L "pid" "src" "target"
+ M "pid" "old" "new"
+ S "pid" "path"
+ # Bye bye
+
+ We go to some effort to avoid processing a dependency more than once.
+ Of the above record types only C,E,F,L,R,V and W are of interest.
+ """
+
+ version = 0 # unknown
+ if name:
+ self.name = name;
+ if file:
+ f = file
+ cwd = self.last_dir = self.cwd
+ else:
+ f = open(self.name, 'r')
+ skip = True
+ pid_cwd = {}
+ pid_last_dir = {}
+ last_pid = 0
+
+ self.line = 0
+ if self.curdir:
+ self.seenit(self.curdir) # we ignore this
+
+ interesting = 'CEFLRV'
+ for line in f:
+ self.line += 1
+ # ignore anything we don't care about
+ if not line[0] in interesting:
+ continue
+ if self.debug > 2:
+ print("input:", line, end=' ', file=self.debug_out)
+ w = line.split()
+
+ if skip:
+ if w[0] == 'V':
+ skip = False
+ version = int(w[1])
+ """
+ if version < 4:
+ # we cannot ignore 'W' records
+ # as they may be 'rw'
+ interesting += 'W'
+ """
+ elif w[0] == 'CWD':
+ self.cwd = cwd = self.last_dir = w[1]
+ self.seenit(cwd) # ignore this
+ if self.debug:
+ print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out)
+ continue
+
+ pid = int(w[1])
+ if pid != last_pid:
+ if last_pid:
+ pid_cwd[last_pid] = cwd
+ pid_last_dir[last_pid] = self.last_dir
+ cwd = getv(pid_cwd, pid, self.cwd)
+ self.last_dir = getv(pid_last_dir, pid, self.cwd)
+ last_pid = pid
+
+ # process operations
+ if w[0] == 'F':
+ npid = int(w[2])
+ pid_cwd[npid] = cwd
+ pid_last_dir[npid] = cwd
+ last_pid = npid
+ continue
+ elif w[0] == 'C':
+ cwd = abspath(w[2], cwd, None, self.debug, self.debug_out)
+ if cwd.endswith('/.'):
+ cwd = cwd[0:-2]
+ self.last_dir = cwd
+ if self.debug > 1:
+ print("cwd=", cwd, file=self.debug_out)
+ continue
+
+ if w[2] in self.seen:
+ if self.debug > 2:
+ print("seen:", w[2], file=self.debug_out)
+ continue
+ # file operations
+ if w[0] in 'ML':
+ # these are special, tread src as read and
+ # target as write
+ self.parse_path(w[1].strip("'"), cwd, 'R', w)
+ self.parse_path(w[2].strip("'"), cwd, 'W', w)
+ continue
+ elif w[0] in 'ERWS':
+ path = w[2]
+ self.parse_path(path, cwd, w[0], w)
+
+ if not file:
+ f.close()
+
+ def parse_path(self, path, cwd, op=None, w=[]):
+ """look at a path for the op specified"""
+
+ if not op:
+ op = w[0]
+
+ # we are never interested in .dirdep files as dependencies
+ if path.endswith('.dirdep'):
+ return
+ for p in self.excludes:
+ if p and path.startswith(p):
+ if self.debug > 2:
+ print >> self.debug_out, "exclude:", p, path
+ return
+ # we don't want to resolve the last component if it is
+ # a symlink
+ path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out)
+ if not path:
+ return
+ dir,base = os.path.split(path)
+ if dir in self.seen:
+ if self.debug > 2:
+ print("seen:", dir, file=self.debug_out)
+ return
+ # we can have a path in an objdir which is a link
+ # to the src dir, we may need to add dependencies for each
+ rdir = dir
+ dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out)
+ if rdir == dir or rdir.find('./') > 0:
+ rdir = None
+ # now put path back together
+ path = '/'.join([dir,base])
+ if self.debug > 1:
+ print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out)
+ if op in 'RWS':
+ if path in [self.last_dir, cwd, self.cwd, self.curdir]:
+ if self.debug > 1:
+ print("skipping:", path, file=self.debug_out)
+ return
+ if os.path.isdir(path):
+ if op in 'RW':
+ self.last_dir = path;
+ if self.debug > 1:
+ print("ldir=", self.last_dir, file=self.debug_out)
+ return
+
+ if op in 'ERW':
+ # finally, we get down to it
+ if dir == self.cwd or dir == self.curdir:
+ return
+ srctop = self.find_top(path, self.srctops)
+ if srctop:
+ if self.dpdeps:
+ self.add(self.file_deps, path.replace(srctop,''), 'file')
+ self.add(self.src_deps, dir.replace(srctop,''), 'src')
+ self.seenit(w[2])
+ self.seenit(dir)
+ if rdir and not rdir.startswith(srctop):
+ dir = rdir # for below
+ rdir = None
+ else:
+ return
+
+ objroot = None
+ for dir in [dir,rdir]:
+ if not dir:
+ continue
+ objroot = self.find_top(dir, self.objroots)
+ if objroot:
+ break
+ if objroot:
+ ddep = self.find_obj(objroot, dir, path, w[2])
+ if ddep:
+ self.add(self.obj_deps, ddep, 'obj')
+ else:
+ # don't waste time looking again
+ self.seenit(w[2])
+ self.seenit(dir)
+
+
+def main(argv, klass=MetaFile, xopts='', xoptf=None):
+ """Simple driver for class MetaFile.
+
+ Usage:
+ script [options] [key=value ...] "meta" ...
+
+ Options and key=value pairs contribute to the
+ dictionary passed to MetaFile.
+
+ -S "SRCTOP"
+ add "SRCTOP" to the "SRCTOPS" list.
+
+ -C "CURDIR"
+
+ -O "OBJROOT"
+ add "OBJROOT" to the "OBJROOTS" list.
+
+ -m "MACHINE"
+
+ -a "MACHINE_ARCH"
+
+ -H "HOST_TARGET"
+
+ -D "DPDEPS"
+
+ -d bumps debug level
+
+ """
+ import getopt
+
+ # import Psyco if we can
+ # it can speed things up quite a bit
+ have_psyco = 0
+ try:
+ import psyco
+ psyco.full()
+ have_psyco = 1
+ except:
+ pass
+
+ conf = {
+ 'SRCTOPS': [],
+ 'OBJROOTS': [],
+ 'EXCLUDES': [],
+ }
+
+ try:
+ machine = os.environ['MACHINE']
+ if machine:
+ conf['MACHINE'] = machine
+ machine_arch = os.environ['MACHINE_ARCH']
+ if machine_arch:
+ conf['MACHINE_ARCH'] = machine_arch
+ srctop = os.environ['SB_SRC']
+ if srctop:
+ conf['SRCTOPS'].append(srctop)
+ objroot = os.environ['SB_OBJROOT']
+ if objroot:
+ conf['OBJROOTS'].append(objroot)
+ except:
+ pass
+
+ debug = 0
+ output = True
+
+ opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts)
+ for o, a in opts:
+ if o == '-a':
+ conf['MACHINE_ARCH'] = a
+ elif o == '-d':
+ debug += 1
+ elif o == '-q':
+ output = False
+ elif o == '-H':
+ conf['HOST_TARGET'] = a
+ elif o == '-S':
+ if a not in conf['SRCTOPS']:
+ conf['SRCTOPS'].append(a)
+ elif o == '-C':
+ conf['CURDIR'] = a
+ elif o == '-O':
+ if a not in conf['OBJROOTS']:
+ conf['OBJROOTS'].append(a)
+ elif o == '-R':
+ conf['RELDIR'] = a
+ elif o == '-D':
+ conf['DPDEPS'] = a
+ elif o == '-m':
+ conf['MACHINE'] = a
+ elif o == '-T':
+ conf['TARGET_SPEC'] = a
+ elif o == '-X':
+ if a not in conf['EXCLUDES']:
+ conf['EXCLUDES'].append(a)
+ elif xoptf:
+ xoptf(o, a, conf)
+
+ conf['debug'] = debug
+
+ # get any var=val assignments
+ eaten = []
+ for a in args:
+ if a.find('=') > 0:
+ k,v = a.split('=')
+ if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']:
+ if k == 'SRCTOP':
+ k = 'SRCTOPS'
+ elif k == 'OBJROOT':
+ k = 'OBJROOTS'
+ if v not in conf[k]:
+ conf[k].append(v)
+ else:
+ conf[k] = v
+ eaten.append(a)
+ continue
+ break
+
+ for a in eaten:
+ args.remove(a)
+
+ debug_out = getv(conf, 'debug_out', sys.stderr)
+
+ if debug:
+ print("config:", file=debug_out)
+ print("psyco=", have_psyco, file=debug_out)
+ for k,v in list(conf.items()):
+ print("%s=%s" % (k,v), file=debug_out)
+
+ m = None
+ for a in args:
+ if a.endswith('.meta'):
+ if not os.path.exists(a):
+ continue
+ m = klass(a, conf)
+ elif a.startswith('@'):
+ # there can actually multiple files per line
+ for line in open(a[1:]):
+ for f in line.strip().split():
+ if not os.path.exists(f):
+ continue
+ m = klass(f, conf)
+
+ if output and m:
+ print(m.dirdeps())
+
+ print(m.src_dirdeps('\nsrc:'))
+
+ dpdeps = getv(conf, 'DPDEPS')
+ if dpdeps:
+ m.file_depends(open(dpdeps, 'wb'))
+
+ return m
+
+if __name__ == '__main__':
+ try:
+ main(sys.argv)
+ except:
+ # yes, this goes to stdout
+ print("ERROR: ", sys.exc_info()[1])
+ raise
+
Index: share/mk/meta2deps.sh
===================================================================
--- share/mk/meta2deps.sh
+++ share/mk/meta2deps.sh
@@ -0,0 +1,403 @@
+#!/bin/sh
+
+# NAME:
+# meta2deps.sh - extract useful info from .meta files
+#
+# SYNOPSIS:
+# meta2deps.sh SB="SB" "meta" ...
+#
+# DESCRIPTION:
+# This script looks each "meta" file and extracts the
+# information needed to deduce build and src dependencies.
+#
+# To do this, we extract the 'CWD' record as well as all the
+# syscall traces which describe 'R'ead, 'C'hdir and 'E'xec
+# syscalls.
+#
+# The typical meta file looks like::
+#.nf
+#
+# # Meta data file "path"
+# CMD "command-line"
+# CWD "cwd"
+# TARGET "target"
+# -- command output --
+# -- filemon acquired metadata --
+# # buildmon version 2
+# V 2
+# E "pid" "path"
+# R "pid" "path"
+# C "pid" "cwd"
+# R "pid" "path"
+# X "pid" "status"
+#.fi
+#
+# The fact that all the syscall entry lines start with a single
+# character make these files quite easy to process using sed(1).
+#
+# To simplify the logic the 'CWD' line is made to look like a
+# normal 'C'hdir entry, and "cwd" is remembered so that it can
+# be prefixed to any "path" which is not absolute.
+#
+# If the "path" being read ends in '.srcrel' it is the content
+# of (actually the first line of) that file that we are
+# interested in.
+#
+# Any "path" which lies outside of the sandbox "SB" is generally
+# not of interest and is ignored.
+#
+# The output, is a set of absolute paths with "SB" like:
+#.nf
+#
+# $SB/obj-i386/bsd/gnu/lib/csu
+# $SB/obj-i386/bsd/gnu/lib/libgcc
+# $SB/obj-i386/bsd/include
+# $SB/obj-i386/bsd/lib/csu/i386-elf
+# $SB/obj-i386/bsd/lib/libc
+# $SB/src/bsd/include
+# $SB/src/bsd/sys/i386/include
+# $SB/src/bsd/sys/sys
+# $SB/src/pan-release/rtsock
+# $SB/src/pfe-shared/include/jnx
+#.fi
+#
+# Which can then be further processed by 'gendirdeps.mk'
+#
+# If we are passed 'DPDEPS='"dpdeps", then for each src file
+# outside of "CURDIR" we read, we output a line like:
+#.nf
+#
+# DPDEPS_$path += $RELDIR
+#.fi
+#
+# with "$path" geting turned into reldir's, so that we can end
+# up with a list of all the directories which depend on each src
+# file in another directory. This can allow for efficient yet
+# complete testing of changes.
+
+
+# RCSid:
+# $Id: meta2deps.sh,v 1.9 2015/04/03 18:23:25 sjg Exp $
+
+# Copyright (c) 2010-2013, Juniper Networks, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+meta2src() {
+ cat /dev/null "$@" |
+ sed -n '/^R .*\.[chyl]$/s,^..[0-9]* ,,p' |
+ sort -u
+}
+
+meta2dirs() {
+ cat /dev/null "$@" |
+ sed -n '/^R .*\/.*\.[a-z0-9][^\/]*$/s,^..[0-9]* \(.*\)/[^/]*$,\1,p' |
+ sort -u
+}
+
+add_list() {
+ sep=' '
+ suffix=
+ while :
+ do
+ case "$1" in
+ "|") sep="$1"; shift;;
+ -s) suffix="$2"; shift 2;;
+ *) break;;
+ esac
+ done
+ name=$1
+ shift
+ eval list="\$$name"
+ for top in "$@"
+ do
+ case "$sep$list$sep" in
+ *"$sep$top$suffix$sep"*) continue;;
+ esac
+ list="${list:+$list$sep}$top$suffix"
+ done
+ eval "$name=\"$list\""
+}
+
+_excludes_f() {
+ egrep -v "$EXCLUDES"
+}
+
+meta2deps() {
+ DPDEPS=
+ SRCTOPS=$SRCTOP
+ OBJROOTS=
+ EXCLUDES=
+ while :
+ do
+ case "$1" in
+ *=*) eval export "$1"; shift;;
+ -a) MACHINE_ARCH=$2; shift 2;;
+ -m) MACHINE=$2; shift 2;;
+ -C) CURDIR=$2; shift 2;;
+ -H) HOST_TARGET=$2; shift 2;;
+ -S) add_list SRCTOPS $2; shift 2;;
+ -O) add_list OBJROOTS $2; shift 2;;
+ -X) add_list EXCLUDES '|' $2; shift 2;;
+ -R) RELDIR=$2; shift 2;;
+ -T) TARGET_SPEC=$2; shift 2;;
+ *) break;;
+ esac
+ done
+
+ _th= _o=
+ case "$MACHINE" in
+ host) _ht=$HOST_TARGET;;
+ esac
+
+ for o in $OBJROOTS
+ do
+ case "$MACHINE,/$o/" in
+ host,*$HOST_TARGET*) ;;
+ *$MACHINE*|*${TARGET_SPEC:-$MACHINE}*) ;;
+ *) add_list _o $o; continue;;
+ esac
+ for x in $_ht $TARGET_SPEC $MACHINE
+ do
+ case "$o" in
+ "") continue;;
+ */$x/) add_list _o ${o%$x/}; o=;;
+ */$x) add_list _o ${o%$x}; o=;;
+ *$x/) add_list _o ${o%$x/}; o=;;
+ *$x) add_list _o ${o%$x}; o=;;
+ esac
+ done
+ done
+ OBJROOTS="$_o"
+
+ case "$OBJTOP" in
+ "")
+ for o in $OBJROOTS
+ do
+ OBJTOP=$o${TARGET_SPEC:-$MACHINE}
+ break
+ done
+ ;;
+ esac
+ src_re=
+ obj_re=
+ add_list '|' -s '/*' src_re $SRCTOPS
+ add_list '|' -s '*' obj_re $OBJROOTS
+
+ [ -z "$RELDIR" ] && unset DPDEPS
+ tf=/tmp/m2d$$-$USER
+ rm -f $tf.*
+ trap 'rm -f $tf.*; trap 0' 0
+
+ > $tf.dirdep
+ > $tf.qual
+ > $tf.srcdep
+ > $tf.srcrel
+ > $tf.dpdeps
+
+ seenit=
+ seensrc=
+ lpid=
+ case "$EXCLUDES" in
+ "") _excludes=cat;;
+ *) _excludes=_excludes_f;;
+ esac
+ # handle @list files
+ case "$@" in
+ *@[!.]*)
+ for f in "$@"
+ do
+ case "$f" in
+ *.meta) cat $f;;
+ @*) xargs cat < ${f#@};;
+ *) cat $f;;
+ esac
+ done
+ ;;
+ *) cat /dev/null "$@";;
+ esac 2> /dev/null |
+ sed -e 's,^CWD,C C,;/^[CREFLM] /!d' -e "s,',,g" |
+ $_excludes |
+ while read op pid path junk
+ do
+ : op=$op pid=$pid path=$path
+ # we track cwd and ldir (of interest) per pid
+ # CWD is bmake's cwd
+ case "$lpid,$pid" in
+ ,C) CWD=$path cwd=$path ldir=$path
+ if [ -z "$SB" ]; then
+ SB=`echo $CWD | sed 's,/obj.*,,'`
+ fi
+ SRCTOP=${SRCTOP:-$SB/src}
+ continue
+ ;;
+ $pid,$pid) ;;
+ *)
+ case "$lpid" in
+ "") ;;
+ *) eval ldir_$lpid=$ldir cwd_$lpid=$cwd;;
+ esac
+ eval ldir=\${ldir_$pid:-$CWD} cwd=\${cwd_$pid:-$CWD}
+ lpid=$pid
+ ;;
+ esac
+
+ case "$op,$path" in
+ W,*srcrel|*.dirdep) continue;;
+ C,*)
+ case "$path" in
+ /*) cwd=$path;;
+ *) cwd=`cd $cwd/$path 2> /dev/null && /bin/pwd`;;
+ esac
+ # watch out for temp dirs that no longer exist
+ test -d ${cwd:-/dev/null/no/such} || cwd=$CWD
+ continue
+ ;;
+ F,*) eval cwd_$path=$cwd ldir_$path=$ldir
+ continue
+ ;;
+ *) dir=${path%/*}
+ case "$path" in
+ $src_re|$obj_re) ;;
+ /*/stage/*) ;;
+ /*) continue;;
+ *) for path in $ldir/$path $cwd/$path
+ do
+ test -e $path && break
+ done
+ dir=${path%/*}
+ ;;
+ esac
+ ;;
+ esac
+ # avoid repeating ourselves...
+ case "$DPDEPS,$seensrc," in
+ ,*)
+ case ",$seenit," in
+ *,$dir,*) continue;;
+ esac
+ ;;
+ *,$path,*) continue;;
+ esac
+ # canonicalize if needed
+ case "/$dir/" in
+ */../*|*/./*)
+ rdir=$dir
+ dir=`cd $dir 2> /dev/null && /bin/pwd`
+ seen="$rdir,$dir"
+ ;;
+ *) seen=$dir;;
+ esac
+ case "$dir" in
+ ${CURDIR:-.}|${CURDIR:-.}/*|"") continue;;
+ $src_re)
+ # avoid repeating ourselves...
+ case "$DPDEPS,$seensrc," in
+ ,*)
+ case ",$seenit," in
+ *,$dir,*) continue;;
+ esac
+ ;;
+ esac
+ ;;
+ *)
+ case ",$seenit," in
+ *,$dir,*) continue;;
+ esac
+ ;;
+ esac
+ if [ -d $path ]; then
+ case "$path" in
+ */..) ldir=${dir%/*};;
+ *) ldir=$path;;
+ esac
+ continue
+ fi
+ [ -f $path ] || continue
+ case "$dir" in
+ $CWD) continue;; # ignore
+ $src_re)
+ seenit="$seenit,$seen"
+ echo $dir >> $tf.srcdep
+ case "$DPDEPS,$reldir,$seensrc," in
+ ,*) ;;
+ *) seensrc="$seensrc,$path"
+ echo "DPDEPS_$dir/${path##*/} += $RELDIR" >> $tf.dpdeps
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ # if there is a .dirdep we cannot skip
+ # just because we've seen the dir before.
+ if [ -s $path.dirdep ]; then
+ # this file contains:
+ # '# ${RELDIR}.<machine>'
+ echo $path.dirdep >> $tf.qual
+ continue
+ elif [ -s $dir.dirdep ]; then
+ echo $dir.dirdep >> $tf.qual
+ seenit="$seenit,$seen"
+ continue
+ fi
+ seenit="$seenit,$seen"
+ case "$dir" in
+ $obj_re)
+ echo $dir;;
+ esac
+ done > $tf.dirdep
+ _nl=echo
+ for f in $tf.dirdep $tf.qual $tf.srcdep
+ do
+ [ -s $f ] || continue
+ case $f in
+ *qual) # a list of .dirdep files
+ # we can prefix everything with $OBJTOP to
+ # tell gendirdeps.mk that these are
+ # DIRDEP entries, since they are already
+ # qualified with .<machine> as needed.
+ # We strip .$MACHINE though
+ xargs cat < $f | sort -u |
+ sed "s,^# ,,;s,^,$OBJTOP/,;s,\.${TARGET_SPEC:-$MACHINE}\$,,;s,\.$MACHINE\$,,"
+ ;;
+ *) sort -u $f;;
+ esac
+ _nl=:
+ done
+ if [ -s $tf.dpdeps ]; then
+ case "$DPDEPS" in
+ */*) ;;
+ *) echo > $DPDEPS;; # the echo is needed!
+ esac
+ sort -u $tf.dpdeps |
+ sed "s,${SRCTOP}/,,;s,${SB_BACKING_SB:-$SB}/src/,," >> $DPDEPS
+ fi
+ # ensure we produce _something_ else egrep -v gets upset
+ $_nl
+}
+
+case /$0 in
+*/meta2dep*) meta2deps "$@";;
+*/meta2dirs*) meta2dirs "$@";;
+*/meta2src*) meta2src "$@";;
+esac
Index: share/mk/src.sys.mk
===================================================================
--- share/mk/src.sys.mk
+++ share/mk/src.sys.mk
@@ -24,3 +24,5 @@
MAKESYSPATH:= ${MAKESYSPATH:S,.../share/mk,${.PARSEDIR:tA},}
.export MAKESYSPATH
.endif
+# tempting, but bsd.compiler.mk causes problems this early
+#.include "src.opts.mk"
Index: share/mk/stage-install.sh
===================================================================
--- share/mk/stage-install.sh
+++ share/mk/stage-install.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+# NAME:
+# stage-install.sh - wrapper around install
+#
+# SYNOPSIS:
+# stage-install.sh [variable="value"] "args" "dest"
+#
+# DESCRIPTION:
+# This script is a wrapper around the normal install(1).
+# Its role is to add '.dirdep' files to the destination.
+# The variables we might use are:
+#
+# INSTALL
+# Path to actual install(1), default is
+# $REAL_INSTALL
+#
+# OBJDIR
+# Path to the dir where '.dirdep' was generated,
+# default is '.'
+#
+# _DIRDEP
+# Path to actual '.dirdep' file, default is
+# $OBJDIR/.dirdep
+#
+# The "args" and "dest" are passed as is to install(1), and if a
+# '.dirdep' file exists it will be linked or copied to each
+# "file".dirdep placed in "dest" or "dest".dirdep if it happed
+# to be a file rather than a directory.
+#
+# SEE ALSO:
+# meta.stage.mk
+#
+
+# RCSid:
+# $Id: stage-install.sh,v 1.5 2013/04/19 16:32:24 sjg Exp $
+#
+# @(#) Copyright (c) 2013, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+INSTALL=${REAL_INSTALL:-install}
+OBJDIR=.
+
+while :
+do
+ case "$1" in
+ *=*) eval "$1"; shift;;
+ *) break;;
+ esac
+done
+
+# if .dirdep doesn't exist, just run install and be done
+_DIRDEP=${_DIRDEP:-$OBJDIR/.dirdep}
+[ -s $_DIRDEP ] && EXEC= || EXEC=exec
+$EXEC $INSTALL "$@" || exit 1
+
+# from meta.stage.mk
+LnCp() {
+ rm -f $2 2> /dev/null
+ ln $1 $2 2> /dev/null || cp -p $1 $2
+}
+
+StageDirdep() {
+ t=$1
+ if [ -s $t.dirdep ]; then
+ cmp -s $_DIRDEP $t.dirdep && return
+ echo "ERROR: $t installed by `cat $t.dirdep` not `cat $_DIRDEP`" >&2
+ exit 1
+ fi
+ LnCp $_DIRDEP $t.dirdep || exit 1
+}
+
+args="$@"
+while [ $# -gt 8 ]
+do
+ shift 8
+done
+eval dest=\$$#
+if [ -f $dest ]; then
+ # a file, there can be only one .dirdep needed
+ StageDirdep $dest
+elif [ -d $dest ]; then
+ for f in $args
+ do
+ test -f $f || continue
+ StageDirdep $dest/${f##*/}
+ done
+fi
Index: share/mk/sys.dependfile.mk
===================================================================
--- share/mk/sys.dependfile.mk
+++ share/mk/sys.dependfile.mk
@@ -0,0 +1,57 @@
+# $Id: sys.dependfile.mk,v 1.6 2014/08/02 18:02:06 sjg Exp $
+#
+# @(#) Copyright (c) 2012, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# This only makes sense in meta mode.
+# This allows a mixture of auto generated as well as manually edited
+# dependency files, which can be differentiated by their names.
+# As per dirdeps.mk we only require:
+# 1. a common prefix
+# 2. that machine specific files end in .${MACHINE}
+#
+# The .MAKE.DEPENDFILE_PREFERENCE below is an example.
+
+# All depend file names should start with this
+.MAKE.DEPENDFILE_PREFIX ?= Makefile.depend
+
+.if !empty(.MAKE.DEPENDFILE) && \
+ ${.MAKE.DEPENDFILE:M${.MAKE.DEPENDFILE_PREFIX}*} == ""
+# let us do our thing below...
+.undef .MAKE.DEPENDFILE
+.endif
+
+# The order of preference: we will use the first one of these we find.
+# It usually makes sense to order from most specific to least.
+.MAKE.DEPENDFILE_PREFERENCE ?= \
+ ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \
+ ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}
+
+# Normally the 1st entry is our default choice
+# Another useful default is ${.MAKE.DEPENDFILE_PREFIX}
+.MAKE.DEPENDFILE_DEFAULT ?= ${.MAKE.DEPENDFILE_PREFERENCE:[1]}
+
+_e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}
+.if !empty(_e)
+.MAKE.DEPENDFILE := ${_e:[1]}
+.elif ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}} != "" && ${.MAKE.DEPENDFILE_DEFAULT:E} != ${MACHINE}
+# MACHINE specific depend files are supported, but *not* default.
+# If any already exist, we should follow suit.
+_aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE}
+# MACHINE must be the last entry in _aml ;-)
+_e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@}
+.if !empty(_e)
+.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]}
+.endif
+.endif
+.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_DEFAULT}
Index: share/mk/sys.mk
===================================================================
--- share/mk/sys.mk
+++ share/mk/sys.mk
@@ -16,6 +16,41 @@
MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc64/powerpc/}
.endif
+
+# Some options we need now
+__DEFAULT_NO_OPTIONS= \
+ DIRDEPS_CACHE \
+ META_MODE \
+ META_FILES \
+
+
+__DEFAULT_DEPENDENT_OPTIONS= \
+ AUTO_OBJ/META_MODE \
+ STAGING/META_MODE \
+ SYSROOT/META_MODE
+
+.include <bsd.mkopt.mk>
+
+# Pull in global settings.
+__MAKE_CONF?=/etc/make.conf
+.if exists(${__MAKE_CONF})
+.include "${__MAKE_CONF}"
+.endif
+
+# Set any local definitions first. Place this early, but it needs
+# MACHINE_CPUARCH to be defined.
+.-include <local.sys.mk>
+
+.if ${MK_META_MODE} == "yes"
+.-include <meta.sys.mk>
+.elif ${MK_META_FILES} == "yes" && ${.MAKEFLAGS:U:M-B} == ""
+.MAKE.MODE= meta verbose
+.endif
+.if ${MK_AUTO_OBJ} == "yes"
+# This needs to be done early - before .PATH is computed
+.-include <auto.obj.mk>
+.endif
+
# If the special target .POSIX appears (without prerequisites or
# commands) before the first noncomment line in the makefile, make shall
# process the makefile as specified by the Posix 1003.2 specification.
@@ -325,36 +360,12 @@
rm -f ${.PREFIX}.tmp.c
${CTFCONVERT_CMD}
-# Pull in global settings.
-__MAKE_CONF?=/etc/make.conf
-.if exists(${__MAKE_CONF})
-.include "${__MAKE_CONF}"
-.endif
-# Setup anything for the FreeBSD source build, if we're building
-# inside the source tree. Needs to be after make.conf, but before
-# local stuff.
-.sinclude <src.sys.mk>
-
-# Set any local definitions first. Place this early, but it needs
-# MACHINE_CPUARCH to be defined.
-.sinclude <local.sys.mk>
-
.if defined(__MAKE_SHELL) && !empty(__MAKE_SHELL)
SHELL= ${__MAKE_SHELL}
.SHELL: path=${__MAKE_SHELL}
.endif
-.if !defined(.PARSEDIR)
-# We are not bmake, which is more aggressive about searching .PATH
-# It is sometime necessary to curb its enthusiasm with .NOPATH
-# The following allows us to quietly ignore .NOPATH when not using bmake.
-.NOTMAIN: .NOPATH
-.NOPATH:
-
-# Toggle on warnings
-.WARN: dirsyntax
-.else # is bmake
# Tell bmake to expand -V VAR by default
.MAKE.EXPAND_VARIABLES= yes
@@ -371,7 +382,6 @@
echoFlag=v errFlag=e \
path=${__MAKE_SHELL:U/bin/sh}
.endif
-.endif # bmake
.include <bsd.cpu.mk>
Index: sys/conf/kmod.mk
===================================================================
--- sys/conf/kmod.mk
+++ sys/conf/kmod.mk
@@ -253,12 +253,10 @@
.error "can't find kernel source tree"
.endif
-.for _link in ${_ILINKS}
-.PHONY: ${_link}
-${_link}: ${.OBJDIR}/${_link}
+.NOPATH: ${_ILINKS}
-${.OBJDIR}/${_link}:
- @case ${.TARGET:T} in \
+${_ILINKS}:
+ @case ${.TARGET} in \
machine) \
path=${SYSDIR}/${MACHINE}/include ;; \
*) \
@@ -267,7 +265,6 @@
path=`(cd $$path && /bin/pwd)` ; \
${ECHO} ${.TARGET:T} "->" $$path ; \
ln -sf $$path ${.TARGET:T}
-.endfor
CLEANFILES+= ${PROG} ${KMOD}.kld ${OBJS}
Index: tools/build/mk/Makefile.boot
===================================================================
--- tools/build/mk/Makefile.boot
+++ tools/build/mk/Makefile.boot
@@ -4,3 +4,6 @@
DPADD+= ${WORLDTMP}/legacy/usr/lib/libegacy.a
LDADD+= -legacy
LDFLAGS+= -L${WORLDTMP}/legacy/usr/lib
+
+# we do not want to capture dependencies refering to the above
+UPDATE_DEPENDFILE= no
Index: usr.bin/clang/clang.prog.mk
===================================================================
--- usr.bin/clang/clang.prog.mk
+++ usr.bin/clang/clang.prog.mk
@@ -14,4 +14,9 @@
BINDIR?= /usr/bin
+
+.if ${MK_SHARED_TOOLCHAIN} == "no"
+NO_SHARED= yes
+.endif
+
.include <bsd.prog.mk>
Index: usr.bin/grep/Makefile
===================================================================
--- usr.bin/grep/Makefile
+++ usr.bin/grep/Makefile
@@ -39,6 +39,7 @@
.if ${MK_LZMA_SUPPORT} != "no"
LIBADD+= lzma
+.if ${MK_BSD_GREP} == "yes"
LINKS+= ${BINDIR}/${PROG} ${BINDIR}/xzgrep \
${BINDIR}/${PROG} ${BINDIR}/xzegrep \
${BINDIR}/${PROG} ${BINDIR}/xzfgrep \
@@ -52,6 +53,7 @@
grep.1 lzgrep.1 \
grep.1 lzegrep.1 \
grep.1 lzfgrep.1
+.endif
.else
CFLAGS+= -DWITHOUT_LZMA
.endif
Index: usr.bin/top/Makefile
===================================================================
--- usr.bin/top/Makefile
+++ usr.bin/top/Makefile
@@ -25,7 +25,8 @@
CLEANFILES= sigdesc.h
SIGCONV_AWK= ${.CURDIR}/../../contrib/top/sigconv.awk
-SIGNAL_H= ${DESTDIR}/usr/include/sys/signal.h
+STAGED_INCLUDE_DIR?= ${DESTDIR}/usr/include
+SIGNAL_H= ${STAGED_INCLUDE_DIR}/sys/signal.h
sigdesc.h: ${SIGCONV_AWK} ${SIGNAL_H}
awk -f ${SIGCONV_AWK} < ${SIGNAL_H} > ${.TARGET}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 29, 7:42 AM (15 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32332162
Default Alt Text
D2796.id6173.diff (154 KB)
Attached To
Mode
D2796: Base infra for meta mode
Attached
Detach File
Event Timeline
Log In to Comment