diff --git a/ChangeLog b/ChangeLog index 9d54c18ca223..f0374ba707eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +2013-03-30 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130330 + Merge with NetBSD make, pick up + o meta.c: refine the handling of .OODATE in commands. + Rather than suppress command comparison for the entire script + as though .NOMETA_CMP had been used, only suppress it for the + one command line. + This allows something like ${.OODATE:M.NOMETA_CMP} to be used to + suppress comparison of a command without otherwise affecting it. + o make.1: document that + +2013-03-22 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130321 + yes, not quite right but its a cooler number. + Merge with NetBSD make, pick up + o parse.c: fix ParseGmakeExport to be portable + and add a unit-test. + * meta.c: call meta_init() before makefiles are read and if built + with filemon support set .MAKE.PATH_FILEMON to _PATH_FILEMON + this let's makefiles test for support. + Call meta_mode_init() to process .MAKE.MODE. + +2013-03-13 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130305 + Merge with NetBSD make, pick up + o run .STALE: target when a dependency from .depend is missing. + o job.c: add Job_RunTarget() for the above and .BEGIN + +2013-03-03 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130303 + Merge with NetBSD make, pick up + o main.c: set .MAKE.OS to utsname.sysname + o job.c: more checks for read and poll errors + o var.c: lose VarChangeCase() saves 4% time + +2013-03-02 Simon J. Gerraty + + * boot-strap: remove MAKEOBJDIRPREFIX from environment since we + want to use MAKEOBJDIR + 2013-01-27 Simon J. Gerraty * Merge with NetBSD make, pick up diff --git a/FILES b/FILES index b75cf1c2d61e..dedc1ac8b07c 100644 --- a/FILES +++ b/FILES @@ -102,6 +102,7 @@ unit-tests/dotwait unit-tests/error unit-tests/export unit-tests/export-all +unit-tests/export-env unit-tests/forloop unit-tests/forsubst unit-tests/hash diff --git a/Makefile b/Makefile index 360732685bcc..edf0bd8b8e68 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -# $Id: Makefile,v 1.5 2013/01/28 19:31:58 sjg Exp $ +# $Id: Makefile,v 1.10 2013/03/31 05:57:19 sjg Exp $ # Base version on src date -MAKE_VERSION= 20130123 +MAKE_VERSION= 20130330 PROG= bmake @@ -187,14 +187,14 @@ MANDIR= ${SHAREDIR}/man .if !exists(.depend) ${OBJS}: config.h .endif -.if ${MK_AUTOCONF_MK} == "yes" -.include -.endif # make sure that MAKE_VERSION gets updated. main.o: ${SRCS} ${MAKEFILE} # start-delete2 for bsd.after-import.mk +.if ${MK_AUTOCONF_MK} == "yes" +.include +.endif SHARE_MK?=${SHAREDIR}/mk MKSRC=${srcdir}/mk INSTALL?=${srcdir}/install-sh diff --git a/bmake.1 b/bmake.1 index 82cec21dca4a..2403eae7078f 100644 --- a/bmake.1 +++ b/bmake.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.210 2013/01/27 18:52:01 sjg Exp $ +.\" $NetBSD: make.1,v 1.213 2013/03/31 05:49:51 sjg Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd January 23, 2013 +.Dd March 30, 2013 .Dt MAKE 1 .Os .Sh NAME @@ -874,6 +874,13 @@ by appending their names to is re-exported whenever .Ql Va .MAKEOVERRIDES is modified. +.It Va .MAKE.PATH_FILEMON +If +.Nm +was built with +.Xr filemon 4 +support, this is set to the path of the device node. +This allows makefiles to test for this support. .It Va .MAKE.PID The process-id of .Nm . @@ -1757,6 +1764,20 @@ targets. Ignore differences in commands when deciding if target is out of date. This is useful if the command contains a value which always changes. If the number of commands change, though, the target will still be out of date. +The same effect applies to any command line that uses the variable +.Va .OODATE , +which can be used for that purpose even when not otherwise needed or desired: +.Bd -literal -offset indent + +skip-compare-for-some: + @echo this will be compared + @echo this will not ${.OODATE:M.NOMETA_CMP} + @echo this will also be compared + +.Ed +The +.Cm \&:M +pattern suppresses any expansion of the unwanted variable. .It Ic .NOPATH Do not search for the target in the directories specified by .Ic .PATH . @@ -2008,6 +2029,10 @@ If no sources are specified, the .Ic .SILENT attribute is applied to every command in the file. +.It Ic .STALE +This target gets run when a dependency file contains stale entries, having +.Va .ALLSRC +set to the name of that dependency file. .It Ic .SUFFIXES Each source specifies a suffix to .Nm . diff --git a/bmake.cat1 b/bmake.cat1 index 7800726ccf60..e446e891450c 100644 --- a/bmake.cat1 +++ b/bmake.cat1 @@ -565,6 +565,11 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS `MAKEFLAGS' is re-exported whenever `_._M_A_K_E_O_V_E_R_R_I_D_E_S' is modified. + _._M_A_K_E_._P_A_T_H___F_I_L_E_M_O_N + If bbmmaakkee was built with filemon(4) support, this is set + to the path of the device node. This allows makefiles to + test for this support. + _._M_A_K_E_._P_I_D The process-id of bbmmaakkee. _._M_A_K_E_._P_P_I_D The parent process-id of bbmmaakkee. @@ -1106,7 +1111,19 @@ SSPPEECCIIAALL SSOOUURRCCEESS ((AATTTTRRIIBBUUTTEESS)) Ignore differences in commands when deciding if target is out of date. This is useful if the command contains a value which always changes. If the number of commands change, though, the - target will still be out of date. + target will still be out of date. The same effect applies to + any command line that uses the variable _._O_O_D_A_T_E, which can be + used for that purpose even when not otherwise needed or + desired: + + + skip-compare-for-some: + @echo this will be compared + @echo this will not ${.OODATE:M.NOMETA_CMP} + @echo this will also be compared + + The ::MM pattern suppresses any expansion of the unwanted vari- + able. ..NNOOPPAATTHH Do not search for the target in the directories specified by ..PPAATTHH. @@ -1278,6 +1295,9 @@ SSPPEECCIIAALL TTAARRGGEETTSS sources are specified, the ..SSIILLEENNTT attribute is applied to every command in the file. + ..SSTTAALLEE This target gets run when a dependency file contains stale + entries, having _._A_L_L_S_R_C set to the name of that dependency file. + ..SSUUFFFFIIXXEESS Each source specifies a suffix to bbmmaakkee. If no sources are specified, any previously specified suffixes are deleted. It @@ -1340,4 +1360,4 @@ BBUUGGSS There is no way of escaping a space character in a filename. -NetBSD 5.1 January 23, 2013 NetBSD 5.1 +NetBSD 5.1 March 30, 2013 NetBSD 5.1 diff --git a/boot-strap b/boot-strap index 7eff5f65ae16..2193926d8023 100755 --- a/boot-strap +++ b/boot-strap @@ -111,7 +111,7 @@ # Simon J. Gerraty # RCSid: -# $Id: boot-strap,v 1.42 2013/01/25 20:20:33 sjg Exp $ +# $Id: boot-strap,v 1.43 2013/03/02 18:55:23 sjg Exp $ # # @(#) Copyright (c) 2001 Simon J. Gerraty # @@ -159,6 +159,9 @@ source_rc() { cmd_args="$@" +# clear some things from the environment that we care about +unset MAKEOBJDIR MAKEOBJDIRPREFIX + # --install[-host-target] will set this INSTALL_PREFIX= # other things we pass to install step diff --git a/configure b/configure index f79b26f86376..a515b278c276 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.64 for bmake 20121212. +# Generated by GNU Autoconf 2.64 for bmake 20130303. # # Report bugs to . # @@ -549,8 +549,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bmake' PACKAGE_TARNAME='bmake' -PACKAGE_VERSION='20121212' -PACKAGE_STRING='bmake 20121212' +PACKAGE_VERSION='20130303' +PACKAGE_STRING='bmake 20130303' PACKAGE_BUGREPORT='sjg@NetBSD.org' PACKAGE_URL='' @@ -1220,7 +1220,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures bmake 20121212 to adapt to many kinds of systems. +\`configure' configures bmake 20130303 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1281,7 +1281,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bmake 20121212:";; + short | recursive ) echo "Configuration of bmake 20130303:";; esac cat <<\_ACEOF @@ -1386,7 +1386,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bmake configure 20121212 +bmake configure 20130303 generated by GNU Autoconf 2.64 Copyright (C) 2009 Free Software Foundation, Inc. @@ -1907,7 +1907,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bmake $as_me 20121212, which was +It was created by bmake $as_me 20130303, which was generated by GNU Autoconf 2.64. Invocation command line was $ $0 $@ @@ -6374,7 +6374,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bmake $as_me 20121212, which was +This file was extended by bmake $as_me 20130303, which was generated by GNU Autoconf 2.64. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6434,7 +6434,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -bmake config.status 20121212 +bmake config.status 20130303 configured by $0, generated by GNU Autoconf 2.64, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.in b/configure.in index 0caafdfd07dc..ba82a75e598d 100644 --- a/configure.in +++ b/configure.in @@ -1,10 +1,10 @@ dnl dnl RCSid: -dnl $Id: configure.in,v 1.46 2012/12/28 21:28:18 sjg Exp $ +dnl $Id: configure.in,v 1.48 2013/03/04 21:25:57 sjg Exp $ dnl dnl Process this file with autoconf to produce a configure script dnl -AC_INIT([bmake], [20121212], [sjg@NetBSD.org]) +AC_INIT([bmake], [20130303], [sjg@NetBSD.org]) AC_CONFIG_HEADER(config.h) dnl make srcdir absolute diff --git a/dir.c b/dir.c index 1c56ea3e8973..7b12769c2dcf 100644 --- a/dir.c +++ b/dir.c @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.65 2012/06/12 19:21:50 joerg Exp $ */ +/* $NetBSD: dir.c,v 1.67 2013/03/05 22:01:43 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: dir.c,v 1.65 2012/06/12 19:21:50 joerg Exp $"; +static char rcsid[] = "$NetBSD: dir.c,v 1.67 2013/03/05 22:01:43 christos Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; #else -__RCSID("$NetBSD: dir.c,v 1.65 2012/06/12 19:21:50 joerg Exp $"); +__RCSID("$NetBSD: dir.c,v 1.67 2013/03/05 22:01:43 christos Exp $"); #endif #endif /* not lint */ #endif @@ -145,6 +145,7 @@ __RCSID("$NetBSD: dir.c,v 1.65 2012/06/12 19:21:50 joerg Exp $"); #include "make.h" #include "hash.h" #include "dir.h" +#include "job.h" /* * A search path consists of a Lst of Path structures. A Path structure @@ -1463,9 +1464,11 @@ Dir_MTime(GNode *gn, Boolean recheck) * so that we give that to the compiler. */ gn->path = bmake_strdup(fullName); - fprintf(stdout, - "%s: ignoring stale %s for %s, found %s\n", - progname, makeDependfile, gn->name, fullName); + if (!Job_RunTarget(".STALE", gn->fname)) + fprintf(stdout, + "%s: %s, %d: ignoring stale %s for %s, " + "found %s\n", progname, gn->fname, gn->lineno, + makeDependfile, gn->name, fullName); } } } diff --git a/job.c b/job.c index 3049e60b1611..a77eaab107ba 100644 --- a/job.c +++ b/job.c @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.165 2013/01/26 15:52:59 christos Exp $ */ +/* $NetBSD: job.c,v 1.172 2013/03/05 22:01:43 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: job.c,v 1.165 2013/01/26 15:52:59 christos Exp $"; +static char rcsid[] = "$NetBSD: job.c,v 1.172 2013/03/05 22:01:43 christos Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: job.c,v 1.165 2013/01/26 15:52:59 christos Exp $"); +__RCSID("$NetBSD: job.c,v 1.172 2013/03/05 22:01:43 christos Exp $"); #endif #endif /* not lint */ #endif @@ -142,6 +142,7 @@ __RCSID("$NetBSD: job.c,v 1.165 2013/01/26 15:52:59 christos Exp $"); #include #include "wait.h" +#include #include #include #if !defined(USE_SELECT) && defined(HAVE_POLL_H) @@ -1245,8 +1246,10 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) static const char msg[] = ": don't know how to make"; if (gn->flags & FROM_DEPEND) { - fprintf(stdout, "%s: ignoring stale %s for %s\n", - progname, makeDependfile, gn->name); + if (!Job_RunTarget(".STALE", gn->fname)) + fprintf(stdout, "%s: %s, %d: ignoring stale %s for %s\n", + progname, gn->fname, gn->lineno, makeDependfile, + gn->name); return TRUE; } @@ -2063,32 +2066,45 @@ Job_CatchOutput(void) (void)fflush(stdout); /* The first fd in the list is the job token pipe */ - nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC); + do { + nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC); + } while (nready < 0 && errno == EINTR); - if (nready < 0 || readyfd(&childExitJob)) { + if (nready < 0) + Punt("poll: %s", strerror(errno)); + + if (nready > 0 && readyfd(&childExitJob)) { char token = 0; - nready -= 1; - while (read(childExitJob.inPipe, &token, 1) == -1 && errno == EAGAIN) - continue; - if (token == DO_JOB_RESUME[0]) - /* Complete relay requested from our SIGCONT handler */ - JobRestartJobs(); - Job_CatchChildren(); + ssize_t count; + count = read(childExitJob.inPipe, &token, 1); + switch (count) { + case 0: + Punt("unexpected eof on token pipe"); + case -1: + Punt("token pipe read: %s", strerror(errno)); + case 1: + if (token == DO_JOB_RESUME[0]) + /* Complete relay requested from our SIGCONT handler */ + JobRestartJobs(); + break; + default: + abort(); + } + --nready; } - if (nready <= 0) - return; - - if (wantToken && readyfd(&tokenWaitJob)) - nready--; + Job_CatchChildren(); + if (nready == 0) + return; for (i = 2; i < nfds; i++) { if (!fds[i].revents) continue; job = jobfds[i]; - if (job->job_state != JOB_ST_RUNNING) - continue; - JobDoOutput(job, FALSE); + if (job->job_state == JOB_ST_RUNNING) + JobDoOutput(job, FALSE); + if (--nready == 0) + return; } } @@ -2179,8 +2195,6 @@ Job_SetPrefix(void) void Job_Init(void) { - GNode *begin; /* node for commands to do at the very start */ - /* Allocate space for all the job info */ job_table = bmake_malloc(maxJobs * sizeof *job_table); memset(job_table, 0, maxJobs * sizeof *job_table); @@ -2256,15 +2270,7 @@ Job_Init(void) ADDSIG(SIGCONT, JobContinueSig) #undef ADDSIG - begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); - - if (begin != NULL) { - JobRun(begin); - if (begin->made == ERROR) { - PrintOnError(begin, "\n\nStop."); - exit(1); - } - } + (void)Job_RunTarget(".BEGIN", NULL); postCommands = Targ_FindNode(".END", TARG_CREATE); } @@ -2930,6 +2936,38 @@ Job_TokenWithdraw(void) return TRUE; } +/*- + *----------------------------------------------------------------------- + * Job_RunTarget -- + * Run the named target if found. If a filename is specified, then + * set that to the sources. + * + * Results: + * None + * + * Side Effects: + * exits if the target fails. + * + *----------------------------------------------------------------------- + */ +Boolean +Job_RunTarget(const char *target, const char *fname) { + GNode *gn = Targ_FindNode(target, TARG_NOCREATE); + + if (gn == NULL) + return FALSE; + + if (fname) + Var_Set(ALLSRC, fname, gn, 0); + + JobRun(gn); + if (gn->made == ERROR) { + PrintOnError(gn, "\n\nStop."); + exit(1); + } + return TRUE; +} + #ifdef USE_SELECT int emul_poll(struct pollfd *fd, int nfd, int timeout) diff --git a/job.h b/job.h index 560b70bf7326..5323b100412b 100644 --- a/job.h +++ b/job.h @@ -1,4 +1,4 @@ -/* $NetBSD: job.h,v 1.40 2010/09/13 15:36:57 sjg Exp $ */ +/* $NetBSD: job.h,v 1.41 2013/03/05 22:01:44 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -268,5 +268,6 @@ void Job_TokenReturn(void); Boolean Job_TokenWithdraw(void); void Job_ServerStart(int, int, int); void Job_SetPrefix(void); +Boolean Job_RunTarget(const char *, const char *); #endif /* _JOB_H_ */ diff --git a/main.c b/main.c index f4bd721844cd..84c6935f81e4 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $ */ +/* $NetBSD: main.c,v 1.210 2013/03/23 05:31:29 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,7 +69,7 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $"; +static char rcsid[] = "$NetBSD: main.c,v 1.210 2013/03/23 05:31:29 sjg Exp $"; #else #include #ifndef lint @@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\ #if 0 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $"); +__RCSID("$NetBSD: main.c,v 1.210 2013/03/23 05:31:29 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -119,9 +119,7 @@ __RCSID("$NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $"); #include #include #include -#ifdef MAKE_NATIVE #include -#endif #include "wait.h" #include @@ -768,7 +766,7 @@ MakeMode(const char *mode) } #if USE_META if (strstr(mode, "meta")) - meta_init(mode); + meta_mode_init(mode); #endif } if (mp) @@ -813,9 +811,7 @@ main(int argc, char **argv) static char defsyspath[] = _PATH_DEFSYSPATH; char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ struct timeval rightnow; /* to initialize random seed */ -#ifdef MAKE_NATIVE struct utsname utsname; -#endif /* default to writing debug to stderr */ debug_file = stderr; @@ -834,7 +830,7 @@ main(int argc, char **argv) progname++; else progname = argv[0]; -#ifdef RLIMIT_NOFILE +#if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)) /* * get rid of resource limit on file descriptors */ @@ -848,6 +844,12 @@ main(int argc, char **argv) } #endif + if (uname(&utsname) == -1) { + (void)fprintf(stderr, "%s: uname failed (%s).\n", progname, + strerror(errno)); + exit(2); + } + /* * Get the name of this type of MACHINE from utsname * so we can share an executable for similar machines. @@ -858,11 +860,6 @@ main(int argc, char **argv) */ if (!machine) { #ifdef MAKE_NATIVE - if (uname(&utsname) == -1) { - (void)fprintf(stderr, "%s: uname failed (%s).\n", progname, - strerror(errno)); - exit(2); - } machine = utsname.machine; #else #ifdef MAKE_MACHINE @@ -892,6 +889,7 @@ main(int argc, char **argv) */ Var_Init(); /* Initialize the lists of variables for * parsing arguments */ + Var_Set(".MAKE.OS", utsname.sysname, VAR_GLOBAL, 0); Var_Set("MACHINE", machine, VAR_GLOBAL, 0); Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0); #ifdef MAKE_VERSION @@ -987,6 +985,9 @@ main(int argc, char **argv) } Job_SetPrefix(); +#ifdef USE_META + meta_init(); +#endif /* * First snag any flags out of the MAKE environment variable. * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's @@ -1697,7 +1698,7 @@ Finish(int errors) } /* - * enunlink -- + * eunlink -- * Remove a file carefully, avoiding directories. */ int diff --git a/make.1 b/make.1 index 198410cd5751..8c386826af1a 100644 --- a/make.1 +++ b/make.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.210 2013/01/27 18:52:01 sjg Exp $ +.\" $NetBSD: make.1,v 1.213 2013/03/31 05:49:51 sjg Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd January 23, 2013 +.Dd March 30, 2013 .Dt MAKE 1 .Os .Sh NAME @@ -874,6 +874,13 @@ by appending their names to is re-exported whenever .Ql Va .MAKEOVERRIDES is modified. +.It Va .MAKE.PATH_FILEMON +If +.Nm +was built with +.Xr filemon 4 +support, this is set to the path of the device node. +This allows makefiles to test for this support. .It Va .MAKE.PID The process-id of .Nm . @@ -1757,6 +1764,20 @@ targets. Ignore differences in commands when deciding if target is out of date. This is useful if the command contains a value which always changes. If the number of commands change, though, the target will still be out of date. +The same effect applies to any command line that uses the variable +.Va .OODATE , +which can be used for that purpose even when not otherwise needed or desired: +.Bd -literal -offset indent + +skip-compare-for-some: + @echo this will be compared + @echo this will not ${.OODATE:M.NOMETA_CMP} + @echo this will also be compared + +.Ed +The +.Cm \&:M +pattern suppresses any expansion of the unwanted variable. .It Ic .NOPATH Do not search for the target in the directories specified by .Ic .PATH . @@ -2008,6 +2029,10 @@ If no sources are specified, the .Ic .SILENT attribute is applied to every command in the file. +.It Ic .STALE +This target gets run when a dependency file contains stale entries, having +.Va .ALLSRC +set to the name of that dependency file. .It Ic .SUFFIXES Each source specifies a suffix to .Nm . diff --git a/make.h b/make.h index 384d109877b1..c9c72bcb0d51 100644 --- a/make.h +++ b/make.h @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.89 2012/06/12 19:21:51 joerg Exp $ */ +/* $NetBSD: make.h,v 1.90 2013/02/25 01:57:14 dholland Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -103,7 +103,7 @@ ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ (__GNUC__ > (x))) #else /* defined(__GNUC__) */ -#define MAKE_GNUC_PREREQx, y) 0 +#define MAKE_GNUC_PREREQ(x, y) 0 #endif /* defined(__GNUC__) */ #if MAKE_GNUC_PREREQ(2, 7) diff --git a/meta.c b/meta.c index d6110d928f41..1bbbe33ec529 100644 --- a/meta.c +++ b/meta.c @@ -1,4 +1,4 @@ -/* $NetBSD: meta.c,v 1.26 2013/01/19 04:23:37 sjg Exp $ */ +/* $NetBSD: meta.c,v 1.29 2013/03/31 05:49:51 sjg Exp $ */ /* * Implement 'meta' mode. @@ -539,8 +539,24 @@ boolValue(char *s) return TRUE; } +/* + * Initialization we need before reading makefiles. + */ void -meta_init(const char *make_mode) +meta_init() +{ +#ifdef USE_FILEMON + /* this allows makefiles to test if we have filemon support */ + Var_Set(".MAKE.PATH_FILEMON", _PATH_FILEMON, VAR_GLOBAL, 0); +#endif +} + + +/* + * Initialization we need after reading makefiles. + */ +void +meta_mode_init(const char *make_mode) { static int once = 0; char *cp; @@ -1037,6 +1053,7 @@ meta_oodate(GNode *gn, Boolean oodate) char *tp = Lst_Datum(ln); Lst_Remove(missingFiles, ln); free(tp); + ln = NULL; /* we're done with it */ } } break; @@ -1196,17 +1213,19 @@ meta_oodate(GNode *gn, Boolean oodate) oodate = TRUE; } else { char *cmd = (char *)Lst_Datum(ln); + Boolean hasOODATE = FALSE; - if (!needOODATE) { - if (strstr(cmd, "$?")) - needOODATE = TRUE; - else if ((cp = strstr(cmd, ".OODATE"))) { - /* check for $[{(].OODATE[)}] */ - if (cp > cmd + 2 && cp[-2] == '$') - needOODATE = TRUE; - } - if (needOODATE && DEBUG(META)) - fprintf(debug_file, "%s: %d: cannot compare commands using .OODATE\n", fname, lineno); + if (strstr(cmd, "$?")) + hasOODATE = TRUE; + else if ((cp = strstr(cmd, ".OODATE"))) { + /* check for $[{(].OODATE[:)}] */ + if (cp > cmd + 2 && cp[-2] == '$') + hasOODATE = TRUE; + } + if (hasOODATE) { + needOODATE = TRUE; + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno); } cmd = Var_Subst(NULL, cmd, gn, TRUE); @@ -1235,7 +1254,7 @@ meta_oodate(GNode *gn, Boolean oodate) if (buf[x - 1] == '\n') buf[x - 1] = '\0'; } - if (!needOODATE && + if (!hasOODATE && !(gn->type & OP_NOMETA_CMP) && strcmp(p, cmd) != 0) { if (DEBUG(META)) diff --git a/meta.h b/meta.h index 1ce01ca901cb..57c73ca9b5f1 100644 --- a/meta.h +++ b/meta.h @@ -1,4 +1,4 @@ -/* $NetBSD: meta.h,v 1.2 2011/03/30 22:03:49 sjg Exp $ */ +/* $NetBSD: meta.h,v 1.3 2013/03/23 05:31:29 sjg Exp $ */ /* * Things needed for 'meta' mode. @@ -41,7 +41,8 @@ typedef struct BuildMon { extern Boolean useMeta; struct Job; /* not defined yet */ -void meta_init(const char *); +void meta_init(void); +void meta_mode_init(const char *); void meta_job_start(struct Job *, GNode *); void meta_job_child(struct Job *); void meta_job_error(struct Job *, GNode *, int, int); diff --git a/mk/ChangeLog b/mk/ChangeLog index fee1c905c444..0f49477da486 100644 --- a/mk/ChangeLog +++ b/mk/ChangeLog @@ -1,3 +1,71 @@ +2013-03-30 Simon J. Gerraty + + * meta2deps.py (MetaFile.__init__): ensure self.cwd is initialized. + * install-mk (MK_VERSION): bump version + +2013-03-21 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * gendirdeps.mk: do not apply :tA to DPADD entries, since we lose + any trailing /., rather apply :tA only when needed. + * gendirdeps.mk: better mimic meta2deps handling of .dirdep files. + * meta.stage.mk (LN_CP_SCRIPT): Add LnCp to do the ln||cp dance + consistently. + * dirdeps.mk: better describe the dance in sys.mk for TARGET_SPEC. + +2013-03-18 Simon J. Gerraty + + * gendirdeps.mk: revert the dance around .MAKE.DEPENDFILE_DEFAULT + it is simpler to just not update when say building for "host" + (where we know we apply filters to DIRDEPS), and using a + non-machine qualified dependfile. + +2013-03-16 Simon J. Gerraty + + * dirdeps.mk: improve DIRDEPS filtering by allowing DEP_SKIP_DIR + and DEP_DIRDEPS_FILTER to vary by DEP_MACHINE and DEP_TARGET_SPEC + * gendirdeps.mk: ensure _objroot has trailing / if it needs it. + * meta2deps.py: if machine is "host", then also trim + self.host_target from any OBJROOTS. + + +2013-03-11 Simon J. Gerraty + + * gendirdeps.mk: if .MAKE.DEPENDFILE_DEFAULT is not machine + qualified but _DEPENDFILE is, and .MAKE.DEPENDFILE_DEFAULT exists + but _DEPENDFILE does not, compare the new _DEPENDFILE against + .MAKE.DEPENDFILE_DEFAULT and discard if the same. + +2013-03-08 Simon J. Gerraty + + * meta.stage.mk: use STAGE_TARGETS to control .ORDER + and hook to all: via staging: + +2013-03-07 Simon J. Gerraty + + * sys.dependfile.mk (.MAKE.DEPENDFILE_DEFAULT): + use a separate variable for the default .MAKE.DEPENDFILE value + so that it can be controlled independently of + .MAKE.DEPENDFILE_PREFERENCE + + * meta.stage.mk: throw error if cp fails etc. + Stage*() return early if passed no args. + .ORDER stage_* + +2013-03-03 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * gendirdeps.mk: handle multiple M2D_OBJROOTS better. + +2013-02-10 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20130210 + * import latest dirdeps.mk, gendirdeps.mk and meta2deps.py + from Juniper. + o dirdeps.mk now fully supports TARGET_SPEC consisting of more + than just MACHINE. + o no longer use DEP_MACHINE from Makefile.depend* so remove it. + 2013-01-23 Simon J. Gerraty * install-mk (MK_VERSION): bump version to 20130123 diff --git a/mk/dirdeps.mk b/mk/dirdeps.mk index 9f051e9203e7..e812416cc88e 100644 --- a/mk/dirdeps.mk +++ b/mk/dirdeps.mk @@ -1,6 +1,7 @@ -# $Id: dirdeps.mk,v 1.23 2012/11/06 05:44:03 sjg Exp $ +# $Id: dirdeps.mk,v 1.28 2013/03/25 21:11:43 sjg Exp $ -# Copyright (c) 2010-2012, Juniper Networks, Inc. +# 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 @@ -33,21 +34,31 @@ # This is what we do with DIRDEPS # DIRDEPS: -# This is a list of directories - relative to SRCTOP, it is only -# of interest to .MAKE.LEVEL 0. +# 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 . -# suffix, for example to force building something for the pseudo +# or . 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 .${MACHINE} -# and _DIRDEPS_USE below, uses the suffix to set 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 .. +# The _DIRDEPS_USE target uses the suffix to set TARGET_SPEC # correctly when visiting each entry. # -# Each entry is also converted into a set of paths to look for -# Makefile.depend. to learn the dependencies of each. -# Each Makefile.depend. sets DEP_RELDIR to be the +# 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 -# DEP_MACHINE to its suffix (), further since -# each Makefile.depend. includes dirdeps.mk, this +# 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). # @@ -55,38 +66,49 @@ # 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 -# All the description above (and below) assumes is the -# only data needed to control the build. -# This is not always the case. So in addition to setting -# MACHINE in the build environment we set TARGET_SPEC which is -# composed of the values of TARGET_SPEC_VARS separated by -# commas. The default is just MACHINE. +# The default value is just MACHINE, and for most environments +# this is sufficient. The _DIRDEPS_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 that MACHINE is needed then sys.mk needs to decompose +# 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 TARGET_SPEC_VARS -# since if there is more the value passed as MACHINE will infact -# be the TARGET_SPEC. +# 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 -# tripple used by compiler folk won't work (directly anyway). +# triple used by compiler folk won't work (directly anyway). # # For example: # -# # variables other than MACHINE might be optional +# # 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,} # .if ${.MAKE.LEVEL} == 0 @@ -100,14 +122,48 @@ # do some setup we only need once _CURDIR ?= ${.CURDIR} +# 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) -# this makes the logic below neater? +# .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} @@ -118,12 +174,12 @@ TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} .endif _default_dependfile := ${.MAKE.DEPENDFILE_PREFERENCE:[1]:T} -_machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:M*.${TARGET_SPEC}} \ - ${.MAKE.DEPENDFILE_PREFERENCE:M*.${MACHINE}} +_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 @@ -133,24 +189,45 @@ _machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:M*.${TARGET_SPEC}} \ # this is how we identify non-machine specific dependfiles -N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N${TARGET_SPEC}:N${MACHINE}:${M_ListToSkip}} +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 _last_dependfile := ${.MAKE.MAKEFILES:M*/${.MAKE.DEPENDFILE_PREFIX}*:[-1]} +.if !empty(_debug_reldir) +.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _last_dependfile='${_last_dependfile}' +.endif -# Note: if a makefile is read many times, the above -# will not work, so we also test for DEP_MACHINE==depend below. -.if empty(_last_dependfile) -# we haven't included one yet -DEP_MACHINE ?= ${TARGET_MACHINE:U${TARGET_SPEC}} -# else it should be correctly set by ${.MAKE.DEPENDFILE} -.elif ${_last_dependfile:E:${N_notmachine}} == "" || ${DEP_MACHINE:Uno:${N_notmachine}} == "" -# don't rely on manually maintained files to be correct -DEP_MACHINE := ${_DEP_MACHINE:U${TARGET_SPEC}} +.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 -# just in case -DEP_MACHINE ?= ${_last_dependfile:E} +_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 @@ -179,17 +256,18 @@ _DEP_RELDIR := ${DEP_RELDIR} SKIP_HOSTDIR ?= NSkipHostDir = ${SKIP_HOSTDIR:N*.host:S,$,.host,:N.host:${M_ListToSkip}} -NSkipHostDep = ${SKIP_HOSTDIR:R:@d@*/$d*.host@:${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} -.ifdef HOSTPROG -SKIP_DIR += ${SKIP_HOSTDIR} -.endif +DEP_SKIP_DIR = ${SKIP_DIR} \ + ${SKIP_DIR.${DEP_TARGET_SPEC}:U} \ + ${SKIP_DIR.${DEP_MACHINE}:U} \ + ${SKIP_DIRDEPS.${DEP_MACHINE}:U} -NSkipDir = ${SKIP_DIR:${M_ListToSkip}} +NSkipDir = ${DEP_SKIP_DIR:${M_ListToSkip}} .if defined(NO_DIRDEPS) || defined(NODIRDEPS) # confine ourselves to the original dir @@ -198,12 +276,15 @@ DIRDEPS_FILTER += M${_DEP_RELDIR}* # we supress 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} MACHINE_ARCH= NO_SUBDIR=1 \ + MACHINE=${.TARGET:E} \ ${.MAKE} -C ${.TARGET:R} || exit 1; \ break; \ done @@ -260,7 +341,7 @@ _this_dir := ${SRCTOP}/${DEP_RELDIR} _dep_hack := ${_this_dir}/${.MAKE.DEPENDFILE_PREFIX}.inc .-include "${_dep_hack}" -.if ${DEP_RELDIR} != ${_DEP_RELDIR} || ${DEP_MACHINE} != ${TARGET_SPEC} +.if ${DEP_RELDIR} != ${_DEP_RELDIR} || ${DEP_TARGET_SPEC} != ${TARGET_SPEC} # this should be all _machines := ${DEP_MACHINE} .else @@ -275,17 +356,23 @@ _machines += host _machines := ${_machines:O:u} .endif -# reset these each time through +.if ${TARGET_SPEC_VARS:[#]} > 1 +# we need to tweak _machines +_dm := ${DEP_MACHINE} +_machines := ${_machines:@DEP_MACHINE@${DEP_TARGET_SPEC}@} +DEP_MACHINE := ${_dm} +.endif + +# reset each time through _build_dirs = -_depdir_files = .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_MACHINE}:@m@${_CURDIR}.$m@} -.if ${DEP_MACHINE} == ${TARGET_SPEC} +_build_dirs += ${_machines:N${DEP_TARGET_SPEC}:@m@${_CURDIR}.$m@} +.if ${DEP_TARGET_SPEC} == ${TARGET_SPEC} # pickup local dependencies now .-include <.depend> .endif @@ -293,15 +380,23 @@ _build_dirs += ${_machines:N${DEP_MACHINE}:@m@${_CURDIR}.$m@} .endif .if !empty(_debug_reldir) -.info ${DEP_RELDIR}.${DEP_MACHINE}: _last_dependfile='${_last_dependfile}' -.info ${DEP_RELDIR}.${DEP_MACHINE}: DIRDEPS='${DIRDEPS}' -.info ${DEP_RELDIR}.${DEP_MACHINE}: _machines='${_machines}' +.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}:${DIRDEPS_FILTER:ts:}:O:u:@d@${SRCTOP}/$d@} +__depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:O:u:@d@${SRCTOP}/$d@} # some entries may be qualified with . # the :M*/*/*.* just tries to limit the dirs we check to likely ones. @@ -327,26 +422,8 @@ _build_dirs += \ ${__qual_depdirs:N*.host} \ ${_machines:@m@${__unqual_depdirs:@d@$d.$m@}@} -_build_dirs := ${_build_dirs:O:u} - -# this is where we will pick up more dependencies from -# the inner inline loops look complex, but save a significant -# amount of memory compared to a .for loop. -_depdir_files = -.for d in ${_build_dirs} -.if exists($d) -# easy, we're building for ${MACHINE} -_depdir_files += ${.MAKE.DEPENDFILE_PREFERENCE:T:@m@${exists($d/$m):?$d/$m:}@:[1]} -.elif exists(${d:R}) && ${d:R:T} == ${d:T:R} -# a little more complex - building for another machine -# we will ensure the file is qualified with a machine -# so that if necessary _DEP_MACHINE can be set below -_depdir_files += ${.MAKE.DEPENDFILE_PREFERENCE:T:S,.${TARGET_SPEC}$,.${d:E},:S,.${MACHINE}$,.${d:E},:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]:@m@${"${m:M*.${d:E}}":?$m:$m.${d:E}}@} -.endif -.endfor - -# clean up -_depdir_files := ${_depdir_files:O:u} +# qualify everything now +_build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u} .endif # empty DIRDEPS @@ -360,48 +437,57 @@ dirdeps: ${_build_dirs} ${_build_dirs}: _DIRDEP_USE .if !empty(_debug_reldir) -.info ${DEP_RELDIR}.${DEP_MACHINE}: ${_build_dirs} +.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:E:O:u:N$m} +.for q in ${__qual_depdirs:${M_dep_qual_fixes:ts:}:E:O:u:N$m} .if !empty(_debug_reldir) || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != "" -.info ${DEP_RELDIR}.$m: ${_build_dirs:M*.$q} +.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q} .endif ${_this_dir}.$m: ${_build_dirs:M*.$q} .endfor .endif .if !empty(_debug_reldir) -.info ${DEP_RELDIR}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m} +.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m} .endif ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m} .endfor .endif -.for d in ${_depdir_files} -.if ${.MAKE.MAKEFILES:M${d}} == "" +# Now find more dependencies - and recurse. +.for d in ${_build_dirs} +.if ${_DIRDEP_CHECKED:M$d} == "" +# once only +_DIRDEP_CHECKED += $d +# 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) +_qm := ${_m:${M_dep_qual_fixes:ts:}} .if !empty(_debug_search) -.info Looking for $d +.info Looking for ${_qm} .endif -.if exists($d) -.include <$d> -.elif exists(${d:R}) -# an unqualified file exists, we qualified it above so we can set _DEP_MACHINE -# it might be manually maintained and shared by all machine types -# tell it the machine we are interested in. -_DEP_MACHINE := ${d:E} -.if !empty(_debug_reldir) -.info loading ${d:R} for ${_DEP_MACHINE} +# 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/,.*//} +.if !empty(_debug_reldir) && ${_qm} != ${_m} +.info loading ${_m} for ${d:E} +.endif +.include <${_m}> .endif -# pretend we read $d, so we don't come by here again. -.MAKE.MAKEFILES += $d -.include <${d:R}> .endif .endif .endfor + .endif # -V .elif ${.MAKE.LEVEL} > 42 diff --git a/mk/gendirdeps.mk b/mk/gendirdeps.mk index 890f4956f38e..5742c6fbcc1d 100644 --- a/mk/gendirdeps.mk +++ b/mk/gendirdeps.mk @@ -1,6 +1,7 @@ -# $Id: gendirdeps.mk,v 1.10 2012/06/30 00:37:50 sjg Exp $ +# $Id: gendirdeps.mk,v 1.21 2013/03/28 20:01:05 sjg Exp $ -# Copyright (c) 2010, Juniper Networks, Inc. +# 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 @@ -50,7 +51,12 @@ _CURDIR ?= ${.CURDIR} _OBJDIR ?= ${.OBJDIR} _OBJTOP ?= ${OBJTOP} _OBJROOT ?= ${OBJROOT:U${_OBJTOP}} -_objroot ?= ${_OBJROOT:tA} +.if ${_OBJROOT:M*/} +_slash=/ +.else +_slash= +.endif +_objroot ?= ${_OBJROOT:tA}${_slash} _this = ${.PARSEDIR}/${.PARSEFILE} @@ -106,25 +112,26 @@ _py_d = # we can afford to do this all the time. DPDEPS ?= no META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d} \ - -R ${RELDIR} -H ${HOST_TARGET} -O ${M2D_OBJROOT} + -R ${RELDIR} -H ${HOST_TARGET} \ + ${M2D_OBJROOTS:O:u:@o@-O $o@} + .if ${DPDEPS:tl} != "no" META2DEPS_CMD += -D ${DPDEPS} .endif + +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 -M2D_OBJROOT = ${OBJTOP}/ # and tell it not to add machine qualifiers META2DEPS_ARGS += MACHINE=none -.else -.if defined(SB_OBJROOT) -M2D_OBJROOT ?= ${SB_OBJROOT} -.else -M2D_OBJROOT = ${OBJTOP}/ -.endif .endif .if defined(SB_BACKING_SB) -META2DEPS_CMD += -S ${SB_BACKING_SB}/src -O ${SB_BACKING_SB}/${SB_OBJPREFIX} +META2DEPS_CMD += -S ${SB_BACKING_SB}/src +M2D_OBJROOTS += ${SB_BACKING_SB}/${SB_OBJPREFIX} .endif META2DEPS_FILTER = sed 's,^src:,${SRCTOP}/,;s,^\([^/]\),${OBJTOP}/\1,' | .elif ${META2DEPS:E} == "sh" @@ -155,7 +162,26 @@ dir_list != cd ${_OBJDIR} && \ .if !empty(DPADD) _nonlibs := ${DPADD:T:Nlib*:N*include} .if !empty(_nonlibs) -dir_list += ${_nonlibs:@x@${DPADD:M*/$x}@:H:tA} +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} +.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 @@ -167,26 +193,28 @@ dir_list += ${_nonlibs:@x@${DPADD:M*/$x}@:H:tA} # so we add # ${"${dir_list:M*bsd/sys/${MACHINE_ARCH}/include}":?bsd/include:} # to GENDIRDEPS_DIR_LIST_XTRAS +_objtops = ${OBJTOP} ${_OBJTOP} ${_obtop} +_objtops := ${_objtops:O:u} dirdep_list = \ - ${dir_list:M${_objtop}*/*:C,${_objtop}[^/]*/,,} \ + ${_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 . suffix # (we used the pseudo machine "host" for the HOST_TARGET). -qualdir_list = \ - ${dir_list:M${_objroot}*/*/*:N${SRCTOP}*:N${_objtop}*:C,${_objroot}([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,} - -.if ${_OBJROOT} != ${_objroot} -dirdep_list += \ - ${dir_list:M${_OBJTOP}*/*:C,${_OBJTOP}[^/]*/,,} - -qualdir_list += \ - ${dir_list:M${_OBJROOT}*/*/*:N${SRCTOP}*:N${_OBJTOP}*:C,${_OBJROOT}([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,} -.endif +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 := ${dir_list:${skip_ql:${M_ListToSkip}}:M$o*/*/*:C,$o([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,} +qualdir_list += ${ql} +skip_ql+= $o* +.endfor dirdep_list := ${dirdep_list:O:u} -qualdir_list := ${qualdir_list:O:u} +qualdir_list := ${qualdir_list:N*.${MACHINE}:O:u} DIRDEPS = \ ${dirdep_list:N${RELDIR}:N${RELDIR}/*} \ @@ -207,6 +235,7 @@ DIRDEPS += \ DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:ts:}:O:u} .if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" +.info ${RELDIR}: M2D_OBJROOTS=${M2D_OBJROOTS} .info ${RELDIR}: dir_list='${dir_list}' .info ${RELDIR}: dirdep_list='${dirdep_list}' .info ${RELDIR}: qualdir_list='${qualdir_list}' @@ -263,7 +292,6 @@ CAT_DEPEND ?= .depend ${_DEPENDFILE}: ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS} @(echo '# Autogenerated - do NOT edit!'; echo; \ echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \ - echo 'DEP_MACHINE := $${.PARSEFILE:E}'; echo; \ echo 'DIRDEPS = \'; \ echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \ ${_include_src_dirdeps} \ @@ -285,7 +313,6 @@ all: ${_DEPENDFILE} ${_DEPENDFILE}: ${MAKEFILE} ${_this} @(echo '# Autogenerated - do NOT edit!'; echo; \ echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \ - echo 'DEP_MACHINE := $${.PARSEFILE:E}'; echo; \ echo 'DIRDEPS = \'; \ echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \ echo '.include '; \ diff --git a/mk/install-mk b/mk/install-mk index 7dea1fc33df3..c45c6ca828d0 100644 --- a/mk/install-mk +++ b/mk/install-mk @@ -55,7 +55,7 @@ # Simon J. Gerraty # RCSid: -# $Id: install-mk,v 1.83 2013/01/24 01:02:23 sjg Exp $ +# $Id: install-mk,v 1.88 2013/03/31 22:31:59 sjg Exp $ # # @(#) Copyright (c) 1994 Simon J. Gerraty # @@ -70,7 +70,7 @@ # sjg@crufty.net # -MK_VERSION=20130123 +MK_VERSION=20130330 OWNER= GROUP= MODE=444 diff --git a/mk/meta.stage.mk b/mk/meta.stage.mk index cf62db4311e1..0faeef34cbcc 100644 --- a/mk/meta.stage.mk +++ b/mk/meta.stage.mk @@ -1,4 +1,4 @@ -# $Id: meta.stage.mk,v 1.17 2013/01/24 01:02:23 sjg Exp $ +# $Id: meta.stage.mk,v 1.24 2013/03/23 02:25:19 sjg Exp $ # # @(#) Copyright (c) 2011, Simon J. Gerraty # @@ -48,37 +48,39 @@ GENDIRDEPS_FILTER += Nnot-empty-is-important \ ${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \ ${_STAGED_DIRS:O:u: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 = StageDirdep() { \ +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; \ - ln .dirdep $$t.dirdep 2> /dev/null || \ - cp .dirdep $$t.dirdep; } + 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 -m) mode=$$2; shift 2;; *) mode=;; esac; \ + 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; \ - rm -f $$t; \ - { ln $$f $$t 2> /dev/null || \ - cp -p $$f $$t; }; \ - $${mode:+chmod $$mode $$t}; \ + LnCp $$f $$t || exit 1; \ + [ -z "$$mode" ] || chmod $$mode $$t; \ done; :; } STAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \ - case "$$1" in --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \ + case "$$1" in "") return;; --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \ dest=$$1; shift; \ mkdir -p $$dest; \ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ @@ -89,11 +91,11 @@ STAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \ shift; \ StageDirdep $$t; \ rm -f $$t 2>/dev/null; \ - ln $$lnf $$l $$t; \ + ln $$lnf $$l $$t || exit 1; \ done; :; } STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \ - case "$$1" in -m) mode=$$2; shift 2;; *) mode=;; esac; \ + case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \ dest=$$1; shift; \ mkdir -p $$dest; \ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ @@ -103,10 +105,8 @@ STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \ case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \ shift; \ StageDirdep $$t; \ - rm -f $$t; \ - { ln $$s $$t 2> /dev/null || \ - cp -p $$s $$t; }; \ - $${mode:+chmod $$mode $$t}; \ + LnCp $$s $$t || exit 1; \ + [ -z "$$mode" ] || chmod $$mode $$t; \ done; :; } # this is simple, a list of the "staged" files depends on this, @@ -114,8 +114,7 @@ _STAGE_BASENAME_USE: .USE ${.TARGET:T} @${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} .if !empty(STAGE_INCSDIR) -CLEANFILES += stage_incs - +STAGE_TARGETS += stage_incs STAGE_INCS ?= ${.ALLSRC:N.dirdep} stage_incs: .dirdep @@ -124,7 +123,7 @@ stage_incs: .dirdep .endif .if !empty(STAGE_LIBDIR) -CLEANFILES += stage_libs +STAGE_TARGETS += stage_libs STAGE_LIBS ?= ${.ALLSRC:N.dirdep} @@ -152,7 +151,6 @@ 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 @@ -162,6 +160,7 @@ 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 @@ -171,6 +170,7 @@ stage_files: .dirdep @${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 @@ -180,6 +180,7 @@ stage_links: .dirdep @${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 @@ -195,6 +196,8 @@ stage_symlinks: .dirdep .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 @@ -209,4 +212,20 @@ stage_as.$s: .dirdep .endfor .endif +CLEANFILES += ${STAGE_TARGETS} + +# 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 + +all: ${STAGING_WAIT} staging + .endif diff --git a/mk/meta2deps.py b/mk/meta2deps.py index cb6d3213b221..6b6157c3ab4c 100755 --- a/mk/meta2deps.py +++ b/mk/meta2deps.py @@ -35,9 +35,10 @@ """ RCSid: - $Id: meta2deps.py,v 1.7 2012/11/06 05:44:03 sjg Exp $ + $Id: meta2deps.py,v 1.12 2013/03/31 22:31:59 sjg Exp $ - Copyright (c) 2011, Juniper Networks, Inc. + 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 @@ -149,6 +150,7 @@ def __init__(self, name, conf={}): MACHINE the machine we built for. set to 'none' if we are not cross-building. + More specifically if machine cannot be deduced from objdirs. HOST_TARGET when we build for the psuedo machine 'host' @@ -174,6 +176,11 @@ def __init__(self, name, conf={}): self.debug = getv(conf, 'debug', 0) self.debug_out = getv(conf, 'debug_out', sys.stderr) + self.machine = getv(conf, 'MACHINE', '') + self.curdir = getv(conf, 'CURDIR') + self.reldir = getv(conf, 'RELDIR') + self.dpdeps = getv(conf, 'DPDEPS') + if not self.conf: # some of the steps below we want to do only once self.conf = conf @@ -189,7 +196,24 @@ def __init__(self, name, conf={}): if not _srctop in self.srctops: self.srctops.append(_srctop) + trim_list = ['/' + self.machine + '/', + '/' + self.machine, + self.machine + '/', + self.machine] + + if self.machine == 'host': + trim_list += ['/' + self.host_target + '/', + '/' + self.host_target, + self.host_target + '/', + self.host_target] + 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) @@ -198,6 +222,10 @@ def __init__(self, name, conf={}): 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) + if self.debug: print >> self.debug_out, "host_target=", self.host_target print >> self.debug_out, "srctops=", self.srctops @@ -205,10 +233,6 @@ def __init__(self, name, conf={}): self.dirdep_re = re.compile(r'([^/]+)/(.+)') - self.curdir = getv(conf, 'CURDIR') - self.machine = getv(conf, 'MACHINE', '') - self.reldir = getv(conf, 'RELDIR') - self.dpdeps = getv(conf, 'DPDEPS') if self.dpdeps and not self.reldir: if self.debug: print >> self.debug_out, "need reldir:", @@ -221,6 +245,8 @@ def __init__(self, name, conf={}): if not self.reldir: self.dpdeps = None # we cannot do it? + self.cwd = os.getcwd() # make sure this is initialized + if name: self.parse() diff --git a/mk/meta2deps.sh b/mk/meta2deps.sh index e7ddd829aed4..9c76b77964dd 100755 --- a/mk/meta2deps.sh +++ b/mk/meta2deps.sh @@ -77,9 +77,10 @@ # RCSid: -# $Id: meta2deps.sh,v 1.4 2012/11/07 06:55:21 sjg Exp $ +# $Id: meta2deps.sh,v 1.5 2013/02/10 19:21:46 sjg Exp $ -# Copyright (c) 2010, Juniper Networks, Inc. +# Copyright (c) 2010-2012, 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 diff --git a/mk/sys.dependfile.mk b/mk/sys.dependfile.mk index 752a46fe8ce1..42cec61fce13 100644 --- a/mk/sys.dependfile.mk +++ b/mk/sys.dependfile.mk @@ -1,4 +1,4 @@ -# $Id: sys.dependfile.mk,v 1.4 2012/11/08 18:31:42 sjg Exp $ +# $Id: sys.dependfile.mk,v 1.5 2013/03/08 00:59:21 sjg Exp $ # # @(#) Copyright (c) 2012, Simon J. Gerraty # @@ -25,16 +25,20 @@ # All depend file names should start with this .MAKE.DEPENDFILE_PREFIX ?= Makefile.depend -# The order of preference: we will use the first one of these we find -# otherwise the 1st entry will be used by default. +# 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_PREFERENCE:[1]:E} != ${MACHINE} +.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} @@ -44,4 +48,4 @@ _e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@} .MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]} .endif .endif -.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:[1]} +.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_DEFAULT} diff --git a/parse.c b/parse.c index 0b18f5d12e68..14c868b1f9d3 100644 --- a/parse.c +++ b/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg Exp $ */ +/* $NetBSD: parse.c,v 1.188 2013/03/22 16:07:59 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg Exp $"; +static char rcsid[] = "$NetBSD: parse.c,v 1.188 2013/03/22 16:07:59 sjg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg Exp $"); +__RCSID("$NetBSD: parse.c,v 1.188 2013/03/22 16:07:59 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -213,6 +213,7 @@ typedef enum { ExShell, /* .SHELL */ Silent, /* .SILENT */ SingleShell, /* .SINGLESHELL */ + Stale, /* .STALE */ Suffixes, /* .SUFFIXES */ Wait, /* .WAIT */ Attribute /* Generic attribute */ @@ -336,6 +337,7 @@ static const struct { { ".SHELL", ExShell, 0 }, { ".SILENT", Silent, OP_SILENT }, { ".SINGLESHELL", SingleShell, 0 }, +{ ".STALE", Stale, 0 }, { ".SUFFIXES", Suffixes, 0 }, { ".USE", Attribute, OP_USE }, { ".USEBEFORE", Attribute, OP_USEBEFORE }, @@ -915,6 +917,8 @@ ParseDoOp(void *gnp, void *opp) gn->type |= op & ~OP_OPMASK; cohort = Targ_FindNode(gn->name, TARG_NOHASH); + if (doing_depend) + ParseMark(cohort); /* * Make the cohort invisible as well to avoid duplicating it into * other variables. True, parents of this target won't tend to do @@ -987,6 +991,8 @@ ParseDoSrc(int tOp, const char *src) */ snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number); gn = Targ_FindNode(wait_src, TARG_NOHASH); + if (doing_depend) + ParseMark(gn); gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN; Lst_ForEach(targets, ParseLinkSrc, gn); return; @@ -1018,6 +1024,8 @@ ParseDoSrc(int tOp, const char *src) * source and the current one. */ gn = Targ_FindNode(src, TARG_CREATE); + if (doing_depend) + ParseMark(gn); if (predecessor != NULL) { (void)Lst_AtEnd(predecessor->order_succ, gn); (void)Lst_AtEnd(gn->order_pred, predecessor); @@ -1049,6 +1057,8 @@ ParseDoSrc(int tOp, const char *src) /* Find/create the 'src' node and attach to all targets */ gn = Targ_FindNode(src, TARG_CREATE); + if (doing_depend) + ParseMark(gn); if (tOp) { gn->type |= tOp; } else { @@ -1294,6 +1304,7 @@ ParseDoDependency(char *line) * apply the .DEFAULT commands. * .PHONY The list of targets * .NOPATH Don't search for file in the path + * .STALE * .BEGIN * .END * .ERROR @@ -1304,42 +1315,45 @@ ParseDoDependency(char *line) * .ORDER Must set initial predecessor to NULL */ switch (specType) { - case ExPath: - if (paths == NULL) { - paths = Lst_Init(FALSE); - } - (void)Lst_AtEnd(paths, dirSearchPath); - break; - case Main: - if (!Lst_IsEmpty(create)) { - specType = Not; - } - break; - case Begin: - case End: - case dotError: - case Interrupt: - gn = Targ_FindNode(line, TARG_CREATE); - gn->type |= OP_NOTMAIN|OP_SPECIAL; - (void)Lst_AtEnd(targets, gn); - break; - case Default: - gn = Targ_NewGN(".DEFAULT"); - gn->type |= (OP_NOTMAIN|OP_TRANSFORM); - (void)Lst_AtEnd(targets, gn); - DEFAULT = gn; - break; - case NotParallel: - maxJobs = 1; - break; - case SingleShell: - compatMake = TRUE; - break; - case Order: - predecessor = NULL; - break; - default: - break; + case ExPath: + if (paths == NULL) { + paths = Lst_Init(FALSE); + } + (void)Lst_AtEnd(paths, dirSearchPath); + break; + case Main: + if (!Lst_IsEmpty(create)) { + specType = Not; + } + break; + case Begin: + case End: + case Stale: + case dotError: + case Interrupt: + gn = Targ_FindNode(line, TARG_CREATE); + if (doing_depend) + ParseMark(gn); + gn->type |= OP_NOTMAIN|OP_SPECIAL; + (void)Lst_AtEnd(targets, gn); + break; + case Default: + gn = Targ_NewGN(".DEFAULT"); + gn->type |= (OP_NOTMAIN|OP_TRANSFORM); + (void)Lst_AtEnd(targets, gn); + DEFAULT = gn; + break; + case NotParallel: + maxJobs = 1; + break; + case SingleShell: + compatMake = TRUE; + break; + case Order: + predecessor = NULL; + break; + default: + break; } } else if (strncmp(line, ".PATH", 5) == 0) { /* @@ -1398,6 +1412,8 @@ ParseDoDependency(char *line) } else { gn = Suff_AddTransform(targName); } + if (doing_depend) + ParseMark(gn); (void)Lst_AtEnd(targets, gn); } @@ -1445,6 +1461,7 @@ ParseDoDependency(char *line) Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); break; case Default: + case Stale: case Begin: case End: case dotError: @@ -2454,6 +2471,7 @@ ParseGmakeExport(char *line) "Variable/Value missing from \"export\""); return; } + *value++ = '\0'; /* terminate variable */ /* * Expand the value before putting it in the environment. diff --git a/unit-tests/Makefile.in b/unit-tests/Makefile.in index a64a07434383..bfd29b261397 100644 --- a/unit-tests/Makefile.in +++ b/unit-tests/Makefile.in @@ -1,6 +1,6 @@ -# $Id: Makefile.in,v 1.40 2012/12/28 21:28:19 sjg Exp $ +# $Id: Makefile.in,v 1.42 2013/03/23 02:31:13 sjg Exp $ # -# $NetBSD: Makefile,v 1.35 2012/11/09 19:08:28 sjg Exp $ +# $NetBSD: Makefile,v 1.36 2013/03/22 16:36:46 sjg Exp $ # # Unit tests for make(1) # The main targets are: @@ -28,6 +28,7 @@ SUBFILES= \ error \ export \ export-all \ + export-env \ doterror \ dotwait \ forloop \ @@ -72,10 +73,12 @@ TOOL_TR?= tr TOOL_DIFF?= diff DIFF_FLAGS?= @diff_u@ +.if defined(.PARSEDIR) # ensure consistent results from sort(1) LC_ALL= C LANG= C .export LANG LC_ALL +.endif # The driver. # We always pretend .MAKE was called 'make' diff --git a/unit-tests/export-env b/unit-tests/export-env new file mode 100644 index 000000000000..b6ce6a251cc6 --- /dev/null +++ b/unit-tests/export-env @@ -0,0 +1,24 @@ +# $Id: export-env,v 1.1.1.1 2013/03/23 02:26:59 sjg Exp $ + +# our normal .export, subsequent changes affect the environment +UT_TEST=this +.export UT_TEST +UT_TEST:= ${.PARSEFILE} + +# not so with .export-env +UT_ENV=exported +.export-env UT_ENV +UT_ENV=not-exported + +# gmake style export goes further; affects nothing but the environment +UT_EXP=before-export +export UT_EXP=exported +UT_EXP=not-exported + +all: + @echo make:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=${$v};@} + @echo env:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=$${$v};@} + + + + diff --git a/unit-tests/test.exp b/unit-tests/test.exp index 368dc3156dbb..b6fad78d21bc 100644 --- a/unit-tests/test.exp +++ b/unit-tests/test.exp @@ -43,6 +43,14 @@ UT_OK=good UT_OKDIR=unit-tests UT_TEST=export-all UT_ZOO=hoopie +make: +UT_TEST=export-env +UT_ENV=not-exported +UT_EXP=not-exported +env: +UT_TEST=export-env +UT_ENV=exported +UT_EXP=exported At first, I am happy and now: sad diff --git a/var.c b/var.c index 2e73d5ba753d..c8fd8f50c933 100644 --- a/var.c +++ b/var.c @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.172 2012/11/15 16:42:26 christos Exp $ */ +/* $NetBSD: var.c,v 1.173 2013/02/24 19:43:37 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: var.c,v 1.172 2012/11/15 16:42:26 christos Exp $"; +static char rcsid[] = "$NetBSD: var.c,v 1.173 2013/02/24 19:43:37 christos Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: var.c,v 1.172 2012/11/15 16:42:26 christos Exp $"); +__RCSID("$NetBSD: var.c,v 1.173 2013/02/24 19:43:37 christos Exp $"); #endif #endif /* not lint */ #endif @@ -309,7 +309,6 @@ static char *VarGetPattern(GNode *, Var_Parse_State *, int, const char **, int, int *, int *, VarPattern *); static char *VarQuote(char *); -static char *VarChangeCase(char *, int); static char *VarHash(char *); static char *VarModify(GNode *, Var_Parse_State *, const char *, @@ -2350,37 +2349,6 @@ VarHash(char *str) return Buf_Destroy(&buf, FALSE); } -/*- - *----------------------------------------------------------------------- - * VarChangeCase -- - * Change the string to all uppercase or all lowercase - * - * Input: - * str String to modify - * upper TRUE -> uppercase, else lowercase - * - * Results: - * The string with case changed - * - * Side Effects: - * None. - * - *----------------------------------------------------------------------- - */ -static char * -VarChangeCase(char *str, int upper) -{ - Buffer buf; - int (*modProc)(int); - - modProc = (upper ? toupper : tolower); - Buf_Init(&buf, 0); - for (; *str ; str++) { - Buf_AddByte(&buf, modProc(*str)); - } - return Buf_Destroy(&buf, FALSE); -} - static char * VarStrftime(const char *fmt, int zulu) { @@ -3057,8 +3025,16 @@ ApplyModifiers(char *nstr, const char *tstr, VarRealpath, NULL); cp = tstr + 2; termc = *cp; - } else if (tstr[1] == 'u' || tstr[1] == 'l') { - newStr = VarChangeCase(nstr, (tstr[1] == 'u')); + } else if (tstr[1] == 'u') { + char *dp = bmake_strdup(nstr); + for (newStr = dp; *dp; dp++) + *dp = toupper((unsigned char)*dp); + cp = tstr + 2; + termc = *cp; + } else if (tstr[1] == 'l') { + char *dp = bmake_strdup(nstr); + for (newStr = dp; *dp; dp++) + *dp = tolower((unsigned char)*dp); cp = tstr + 2; termc = *cp; } else if (tstr[1] == 'W' || tstr[1] == 'w') {