diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2007-09-16 10:39:08 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2007-09-16 10:39:08 +0000 |
commit | 92619b2927c391fb7e94d552e365b85540a5c4c0 (patch) | |
tree | b727578db4f88a0e10abd1ba59e091bcdbc2696f | |
parent | 2cd743898ff20f9b51a56a61f2005ff0a77a263e (diff) |
first step towards sanity: take the functions common to parallel/not parallel
make outside of make.c and job.c, and create an engine.c file to hold them.
-rw-r--r-- | usr.bin/make/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/make/compat.c | 4 | ||||
-rw-r--r-- | usr.bin/make/engine.c | 511 | ||||
-rw-r--r-- | usr.bin/make/engine.h | 68 | ||||
-rw-r--r-- | usr.bin/make/job.c | 139 | ||||
-rw-r--r-- | usr.bin/make/make.c | 329 |
6 files changed, 588 insertions, 467 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile index 9fb976b96a2..afc59ae3895 100644 --- a/usr.bin/make/Makefile +++ b/usr.bin/make/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.45 2007/09/16 10:20:17 espie Exp $ +# $OpenBSD: Makefile,v 1.46 2007/09/16 10:39:07 espie Exp $ PROG= make CFLAGS+= -I${.OBJDIR} -I${.CURDIR} @@ -16,7 +16,7 @@ CFLAGS+=${CDEFS} HOSTCFLAGS+=${CDEFS} SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c direxpand.c \ - error.c for.c \ + engine.c error.c for.c \ init.c job.c lowparse.c main.c make.c memory.c parse.c \ parsevar.c str.c stats.c suff.c targ.c timestamp.c \ var.c varmodifiers.c varname.c diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c index 8a20b3d54d9..f0a33bd2a5b 100644 --- a/usr.bin/make/compat.c +++ b/usr.bin/make/compat.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: compat.c,v 1.54 2007/09/16 09:46:14 espie Exp $ */ +/* $OpenBSD: compat.c,v 1.55 2007/09/16 10:39:07 espie Exp $ */ /* $NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $ */ /* @@ -51,7 +51,7 @@ #include "config.h" #include "defines.h" #include "dir.h" -#include "job.h" +#include "engine.h" #include "compat.h" #include "suff.h" #include "var.h" diff --git a/usr.bin/make/engine.c b/usr.bin/make/engine.c new file mode 100644 index 00000000000..a2ff9aff252 --- /dev/null +++ b/usr.bin/make/engine.c @@ -0,0 +1,511 @@ +/* $OpenBSD: engine.c,v 1.1 2007/09/16 10:39:07 espie Exp $ */ +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include <limits.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include "config.h" +#include "defines.h" +#include "dir.h" +#include "engine.h" +#include "arch.h" +#include "gnode.h" +#include "targ.h" +#include "var.h" +#include "extern.h" +#include "lst.h" +#include "timestamp.h" +#include "make.h" +#include "main.h" + +static void MakeTimeStamp(void *, void *); +static void MakeAddAllSrc(void *, void *); + +/*- + *----------------------------------------------------------------------- + * Job_CheckCommands -- + * Make sure the given node has all the commands it needs. + * + * Results: + * true if the commands list is/was ok. + * + * Side Effects: + * The node will have commands from the .DEFAULT rule added to it + * if it needs them. + *----------------------------------------------------------------------- + */ +bool +Job_CheckCommands(GNode *gn, /* The target whose commands need + * verifying */ + void (*abortProc)(char *, ...)) /* Function to abort with message */ +{ + if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && + (gn->type & OP_LIB) == 0) { + /* + * No commands. Look for .DEFAULT rule from which we might infer + * commands + */ + if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { + /* + * Make only looks for a .DEFAULT if the node was never the + * target of an operator, so that's what we do too. If + * a .DEFAULT was given, we substitute its commands for gn's + * commands and set the IMPSRC variable to be the target's name + * The DEFAULT node acts like a transformation rule, in that + * gn also inherits any attributes or sources attached to + * .DEFAULT itself. + */ + Make_HandleUse(DEFAULT, gn); + Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), gn); + } else if (is_out_of_date(Dir_MTime(gn))) { + /* + * The node wasn't the target of an operator we have no .DEFAULT + * rule to go on and the target doesn't already exist. There's + * nothing more we can do for this branch. If the -k flag wasn't + * given, we stop in our tracks, otherwise we just don't update + * this node's parents so they never get examined. + */ + static const char msg[] = "make: don't know how to make"; + + if (gn->type & OP_OPTIONAL) { + (void)fprintf(stdout, "%s %s(ignored)\n", msg, gn->name); + (void)fflush(stdout); + } else if (keepgoing) { + (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); + (void)fflush(stdout); + return false; + } else { + (*abortProc)("%s %s. Stop in %s.", msg, gn->name, + Var_Value(".CURDIR")); + return false; + } + } + } + return true; +} + +/*- + *----------------------------------------------------------------------- + * Job_Touch -- + * Touch the given target. Called by JobStart when the -t flag was + * given + * + * Side Effects: + * The data modification of the file is changed. In addition, if the + * file did not exist, it is created. + *----------------------------------------------------------------------- + */ +void +Job_Touch(GNode *gn, /* the node of the file to touch */ + bool silent) /* true if should not print messages */ +{ + int streamID; /* ID of stream opened to do the touch */ + + if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) { + /* + * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets + * and, as such, shouldn't really be created. + */ + return; + } + + if (!silent) { + (void)fprintf(stdout, "touch %s\n", gn->name); + (void)fflush(stdout); + } + + if (noExecute) { + return; + } + + if (gn->type & OP_ARCHV) { + Arch_Touch(gn); + } else if (gn->type & OP_LIB) { + Arch_TouchLib(gn); + } else { + const char *file = gn->path != NULL ? gn->path : gn->name; + + if (set_times(file) == -1){ + streamID = open(file, O_RDWR | O_CREAT, 0666); + + if (streamID >= 0) { + char c; + + /* + * Read and write a byte to the file to change the + * modification time, then close the file. + */ + if (read(streamID, &c, 1) == 1) { + (void)lseek(streamID, 0, SEEK_SET); + (void)write(streamID, &c, 1); + } + + (void)close(streamID); + } else { + (void)fprintf(stdout, "*** couldn't touch %s: %s", + file, strerror(errno)); + (void)fflush(stdout); + } + } + } +} + +/*- + *----------------------------------------------------------------------- + * Make_TimeStamp -- + * Set the cmtime field of a parent node based on the mtime stamp in its + * child. + * + * Side Effects: + * The cmtime of the parent node will be changed if the mtime + * field of the child is greater than it. + *----------------------------------------------------------------------- + */ +void +Make_TimeStamp( + GNode *pgn, /* the current parent */ + GNode *cgn) /* the child we've just examined */ +{ + if (is_strictly_before(pgn->cmtime, cgn->mtime)) + pgn->cmtime = cgn->mtime; +} + +/*- + *----------------------------------------------------------------------- + * Make_HandleUse -- + * Function called by Make_Run and SuffApplyTransform on the downward + * pass to handle .USE and transformation nodes. A callback function + * for Lst_ForEach, it implements the .USE and transformation + * functionality by copying the node's commands, type flags + * and children to the parent node. Should be called before the + * children are enqueued to be looked at by MakeAddChild. + * + * A .USE node is much like an explicit transformation rule, except + * its commands are always added to the target node, even if the + * target already has commands. + * + * Side Effects: + * Children and commands may be added to the parent and the parent's + * type may be changed. + * + *----------------------------------------------------------------------- + */ +void +Make_HandleUse( + GNode *cgn, /* The .USE node */ + GNode *pgn) /* The target of the .USE node */ +{ + GNode *gn; /* A child of the .USE node */ + LstNode ln; /* An element in the children list */ + + if (cgn->type & (OP_USE|OP_TRANSFORM)) { + if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) { + /* .USE or transformation and target has no commands -- append + * the child's commands to the parent. */ + Lst_Concat(&pgn->commands, &cgn->commands); + } + + for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Adv(ln)) { + gn = (GNode *)Lst_Datum(ln); + + if (Lst_AddNew(&pgn->children, gn)) { + Lst_AtEnd(&gn->parents, pgn); + pgn->unmade += 1; + } + } + + pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM); + + /* + * This child node is now "made", so we decrement the count of + * unmade children in the parent... We also remove the child + * from the parent's list to accurately reflect the number of decent + * children the parent has. This is used by Make_Run to decide + * whether to queue the parent or examine its children... + */ + if (cgn->type & OP_USE) { + pgn->unmade--; + } + } +} + +/*- + *----------------------------------------------------------------------- + * MakeAddAllSrc -- + * Add a child's name to the ALLSRC and OODATE variables of the given + * node. Called from Make_DoAllVar via Lst_ForEach. A child is added only + * if it has not been given the .EXEC, .USE or .INVISIBLE attributes. + * .EXEC and .USE children are very rarely going to be files, so... + * A child is added to the OODATE variable if its modification time is + * later than that of its parent, as defined by Make, except if the + * parent is a .JOIN node. In that case, it is only added to the OODATE + * variable if it was actually made (since .JOIN nodes don't have + * modification times, the comparison is rather unfair...).. + * + * Side Effects: + * The ALLSRC variable for the given node is extended. + *----------------------------------------------------------------------- + */ +static void +MakeAddAllSrc( + void *cgnp, /* The child to add */ + void *pgnp) /* The parent to whose ALLSRC variable it should be */ + /* added */ +{ + GNode *cgn = (GNode *)cgnp; + GNode *pgn = (GNode *)pgnp; + if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) { + const char *child; + + if (OP_NOP(cgn->type) || + (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) { + /* + * this node is only source; use the specific pathname for it + */ + child = cgn->path != NULL ? cgn->path : cgn->name; + } + + Varq_Append(ALLSRC_INDEX, child, pgn); + if (pgn->type & OP_JOIN) { + if (cgn->made == MADE) { + Varq_Append(OODATE_INDEX, child, pgn); + } + } else if (is_strictly_before(pgn->mtime, cgn->mtime) || + (!is_strictly_before(cgn->mtime, now) && cgn->made == MADE)) + { + /* + * It goes in the OODATE variable if the parent is younger than the + * child or if the child has been modified more recently than + * the start of the make. This is to keep pmake from getting + * confused if something else updates the parent after the + * make starts (shouldn't happen, I know, but sometimes it + * does). In such a case, if we've updated the kid, the parent + * is likely to have a modification time later than that of + * the kid and anything that relies on the OODATE variable will + * be hosed. + * + */ + Varq_Append(OODATE_INDEX, child, pgn); + } + } +} + +/*- + *----------------------------------------------------------------------- + * Make_DoAllVar -- + * Set up the ALLSRC and OODATE variables. Sad to say, it must be + * done separately, rather than while traversing the graph. This is + * because Make defined OODATE to contain all sources whose modification + * times were later than that of the target, *not* those sources that + * were out-of-date. Since in both compatibility and native modes, + * the modification time of the parent isn't found until the child + * has been dealt with, we have to wait until now to fill in the + * variable. As for ALLSRC, the ordering is important and not + * guaranteed when in native mode, so it must be set here, too. + * + * Side Effects: + * The ALLSRC and OODATE variables of the given node is filled in. + * If the node is a .JOIN node, its TARGET variable will be set to + * match its ALLSRC variable. + *----------------------------------------------------------------------- + */ +void +Make_DoAllVar(GNode *gn) +{ + Lst_ForEach(&gn->children, MakeAddAllSrc, gn); + + if (Varq_Value(OODATE_INDEX, gn) == NULL) + Varq_Set(OODATE_INDEX, "", gn); + if (Varq_Value(ALLSRC_INDEX, gn) == NULL) + Varq_Set(ALLSRC_INDEX, "", gn); + + if (gn->type & OP_JOIN) + Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), gn); +} + +/* Wrapper to call Make_TimeStamp from a forEach loop. */ +static void +MakeTimeStamp( + void *pgn, /* the current parent */ + void *cgn) /* the child we've just examined */ +{ + Make_TimeStamp((GNode *)pgn, (GNode *)cgn); +} + +/*- + *----------------------------------------------------------------------- + * Make_OODate -- + * See if a given node is out of date with respect to its sources. + * Used by Make_Run when deciding which nodes to place on the + * toBeMade queue initially and by Make_Update to screen out USE and + * EXEC nodes. In the latter case, however, any other sort of node + * must be considered out-of-date since at least one of its children + * will have been recreated. + * + * Results: + * true if the node is out of date. false otherwise. + * + * Side Effects: + * The mtime field of the node and the cmtime field of its parents + * will/may be changed. + *----------------------------------------------------------------------- + */ +bool +Make_OODate(GNode *gn) /* the node to check */ +{ + bool oodate; + + /* + * Certain types of targets needn't even be sought as their datedness + * doesn't depend on their modification time... + */ + if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) { + (void)Dir_MTime(gn); + if (DEBUG(MAKE)) { + if (!is_out_of_date(gn->mtime)) { + printf("modified %s...", Targ_FmtTime(gn->mtime)); + } else { + printf("non-existent..."); + } + } + } + + /* + * A target is remade in one of the following circumstances: + * its modification time is smaller than that of its youngest child + * and it would actually be run (has commands or type OP_NOP) + * it's the object of a force operator + * it has no children, was on the lhs of an operator and doesn't exist + * already. + * + * Libraries are only considered out-of-date if the archive module says + * they are. + * + * These weird rules are brought to you by Backward-Compatibility and + * the strange people who wrote 'Make'. + */ + if (gn->type & OP_USE) { + /* + * If the node is a USE node it is *never* out of date + * no matter *what*. + */ + if (DEBUG(MAKE)) { + printf(".USE node..."); + } + oodate = false; + } else if ((gn->type & OP_LIB) && Arch_IsLib(gn)) { + if (DEBUG(MAKE)) { + printf("library..."); + } + + /* + * always out of date if no children and :: target + */ + + oodate = Arch_LibOODate(gn) || + (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP)); + } else if (gn->type & OP_JOIN) { + /* + * A target with the .JOIN attribute is only considered + * out-of-date if any of its children was out-of-date. + */ + if (DEBUG(MAKE)) { + printf(".JOIN node..."); + } + oodate = gn->childMade; + } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) { + /* + * A node which is the object of the force (!) operator or which has + * the .EXEC attribute is always considered out-of-date. + */ + if (DEBUG(MAKE)) { + if (gn->type & OP_FORCE) { + printf("! operator..."); + } else if (gn->type & OP_PHONY) { + printf(".PHONY node..."); + } else { + printf(".EXEC node..."); + } + } + oodate = true; + } else if (is_strictly_before(gn->mtime, gn->cmtime) || + (is_out_of_date(gn->cmtime) && + (is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP)))) + { + /* + * A node whose modification time is less than that of its + * youngest child or that has no children (cmtime == OUT_OF_DATE) and + * either doesn't exist (mtime == OUT_OF_DATE) or was the object of a + * :: operator is out-of-date. Why? Because that's the way Make does + * it. + */ + if (DEBUG(MAKE)) { + if (is_strictly_before(gn->mtime, gn->cmtime)) { + printf("modified before source..."); + } else if (is_out_of_date(gn->mtime)) { + printf("non-existent and no sources..."); + } else { + printf(":: operator and no sources..."); + } + } + oodate = true; + } else { +#if 0 + /* WHY? */ + if (DEBUG(MAKE)) { + printf("source %smade...", gn->childMade ? "" : "not "); + } + oodate = gn->childMade; +#else + oodate = false; +#endif /* 0 */ + } + + /* + * If the target isn't out-of-date, the parents need to know its + * modification time. Note that targets that appear to be out-of-date + * but aren't, because they have no commands and aren't of type OP_NOP, + * have their mtime stay below their children's mtime to keep parents from + * thinking they're out-of-date. + */ + if (!oodate) + Lst_ForEach(&gn->parents, MakeTimeStamp, gn); + + return oodate; +} + diff --git a/usr.bin/make/engine.h b/usr.bin/make/engine.h new file mode 100644 index 00000000000..dc53d5dae97 --- /dev/null +++ b/usr.bin/make/engine.h @@ -0,0 +1,68 @@ +#ifndef ENGINE_H +#define ENGINE_H +/* $OpenBSD: engine.h,v 1.1 2007/09/16 10:39:07 espie Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)job.h 8.1 (Berkeley) 6/6/93 + */ + +/* ok = Job_CheckCommands(node, abort); + * verify the integrity of a node's commands, pulling stuff off + * .DEFAULT and other places if necessary. + */ +extern bool Job_CheckCommands(GNode *, void (*abortProc)(char *, ...)); +/* Job_Touch(node, besilent); + * touch the path corresponding to a node or update the corresponding + * archive object. + */ +extern void Job_Touch(GNode *, bool); +/* Make_TimeStamp(parent, child); + * ensure parent is at least as recent as child. + */ +extern void Make_TimeStamp(GNode *, GNode *); +/* Make_HandleUse(user_node, usee_node); + * let user_node inherit the commands from usee_node + */ +extern void Make_HandleUse(GNode *, GNode *); + +/* old = Make_OODate(node); + * check if a given node is out-of-date. + */ +extern bool Make_OODate(GNode *); +/* Make_DoAllVar(node); + * fill all dynamic variables for a node. + */ +extern void Make_DoAllVar(GNode *); +#endif diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c index 618f2a5c88b..91a54dc553b 100644 --- a/usr.bin/make/job.c +++ b/usr.bin/make/job.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: job.c,v 1.62 2007/06/12 16:33:27 cnst Exp $ */ +/* $OpenBSD: job.c,v 1.63 2007/09/16 10:39:07 espie Exp $ */ /* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */ /* @@ -99,7 +99,6 @@ #include <ctype.h> #include <errno.h> #include <fcntl.h> -#include <limits.h> #include <signal.h> #include <stddef.h> #include <stdio.h> @@ -108,21 +107,18 @@ #include <unistd.h> #include "config.h" #include "defines.h" -#include "dir.h" #include "job.h" +#include "engine.h" #include "pathnames.h" -#include "arch.h" #include "var.h" #include "targ.h" #include "error.h" -#include "str.h" #include "lst.h" #include "extern.h" #include "gnode.h" #include "memory.h" #include "make.h" -#include "timestamp.h" -#include "main.h" +#include "str.h" #define TMPPAT "/tmp/makeXXXXXXXXXX" @@ -1112,135 +1108,6 @@ JobFinish(Job *job, /* job to finish */ /*- *----------------------------------------------------------------------- - * Job_Touch -- - * Touch the given target. Called by JobStart when the -t flag was - * given - * - * Side Effects: - * The data modification of the file is changed. In addition, if the - * file did not exist, it is created. - *----------------------------------------------------------------------- - */ -void -Job_Touch(GNode *gn, /* the node of the file to touch */ - bool silent) /* true if should not print messages */ -{ - int streamID; /* ID of stream opened to do the touch */ - - if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) { - /* - * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets - * and, as such, shouldn't really be created. - */ - return; - } - - if (!silent) { - (void)fprintf(stdout, "touch %s\n", gn->name); - (void)fflush(stdout); - } - - if (noExecute) { - return; - } - - if (gn->type & OP_ARCHV) { - Arch_Touch(gn); - } else if (gn->type & OP_LIB) { - Arch_TouchLib(gn); - } else { - const char *file = gn->path != NULL ? gn->path : gn->name; - - if (set_times(file) == -1){ - streamID = open(file, O_RDWR | O_CREAT, 0666); - - if (streamID >= 0) { - char c; - - /* - * Read and write a byte to the file to change the - * modification time, then close the file. - */ - if (read(streamID, &c, 1) == 1) { - (void)lseek(streamID, 0, SEEK_SET); - (void)write(streamID, &c, 1); - } - - (void)close(streamID); - } else { - (void)fprintf(stdout, "*** couldn't touch %s: %s", - file, strerror(errno)); - (void)fflush(stdout); - } - } - } -} - -/*- - *----------------------------------------------------------------------- - * Job_CheckCommands -- - * Make sure the given node has all the commands it needs. - * - * Results: - * true if the commands list is/was ok. - * - * Side Effects: - * The node will have commands from the .DEFAULT rule added to it - * if it needs them. - *----------------------------------------------------------------------- - */ -bool -Job_CheckCommands(GNode *gn, /* The target whose commands need - * verifying */ - void (*abortProc)(char *, ...)) /* Function to abort with message */ -{ - if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && - (gn->type & OP_LIB) == 0) { - /* - * No commands. Look for .DEFAULT rule from which we might infer - * commands - */ - if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { - /* - * Make only looks for a .DEFAULT if the node was never the - * target of an operator, so that's what we do too. If - * a .DEFAULT was given, we substitute its commands for gn's - * commands and set the IMPSRC variable to be the target's name - * The DEFAULT node acts like a transformation rule, in that - * gn also inherits any attributes or sources attached to - * .DEFAULT itself. - */ - Make_HandleUse(DEFAULT, gn); - Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), gn); - } else if (is_out_of_date(Dir_MTime(gn))) { - /* - * The node wasn't the target of an operator we have no .DEFAULT - * rule to go on and the target doesn't already exist. There's - * nothing more we can do for this branch. If the -k flag wasn't - * given, we stop in our tracks, otherwise we just don't update - * this node's parents so they never get examined. - */ - static const char msg[] = "make: don't know how to make"; - - if (gn->type & OP_OPTIONAL) { - (void)fprintf(stdout, "%s %s(ignored)\n", msg, gn->name); - (void)fflush(stdout); - } else if (keepgoing) { - (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); - (void)fflush(stdout); - return false; - } else { - (*abortProc)("%s %s. Stop in %s.", msg, gn->name, - Var_Value(".CURDIR")); - return false; - } - } - } - return true; -} - -/*- - *----------------------------------------------------------------------- * JobExec -- * Execute the shell for the given job. Called from JobStart and * JobRestart. diff --git a/usr.bin/make/make.c b/usr.bin/make/make.c index 7bd82289f21..c097a816a6e 100644 --- a/usr.bin/make/make.c +++ b/usr.bin/make/make.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: make.c,v 1.36 2007/09/16 09:46:14 espie Exp $ */ +/* $OpenBSD: make.c,v 1.37 2007/09/16 10:39:07 espie Exp $ */ /* $NetBSD: make.c,v 1.10 1996/11/06 17:59:15 christos Exp $ */ /* @@ -75,7 +75,6 @@ #include "defines.h" #include "dir.h" #include "job.h" -#include "arch.h" #include "suff.h" #include "var.h" #include "targ.h" @@ -84,6 +83,7 @@ #include "gnode.h" #include "extern.h" #include "timestamp.h" +#include "engine.h" #include "lst.h" static LIST toBeMade; /* The current fringe of the graph. These @@ -96,184 +96,11 @@ static int numNodes; /* Number of nodes to be processed. If this * true, there's a cycle in the graph */ static void MakeAddChild(void *, void *); -static void MakeAddAllSrc(void *, void *); -static void MakeTimeStamp(void *, void *); static void MakeHandleUse(void *, void *); static bool MakeStartJobs(void); static void MakePrintStatus(void *, void *); /*- *----------------------------------------------------------------------- - * Make_TimeStamp -- - * Set the cmtime field of a parent node based on the mtime stamp in its - * child. - * - * Side Effects: - * The cmtime of the parent node will be changed if the mtime - * field of the child is greater than it. - *----------------------------------------------------------------------- - */ -void -Make_TimeStamp( - GNode *pgn, /* the current parent */ - GNode *cgn) /* the child we've just examined */ -{ - if (is_strictly_before(pgn->cmtime, cgn->mtime)) - pgn->cmtime = cgn->mtime; -} - -/* Wrapper to call Make_TimeStamp from a forEach loop. */ -static void -MakeTimeStamp( - void *pgn, /* the current parent */ - void *cgn) /* the child we've just examined */ -{ - Make_TimeStamp((GNode *)pgn, (GNode *)cgn); -} - -/*- - *----------------------------------------------------------------------- - * Make_OODate -- - * See if a given node is out of date with respect to its sources. - * Used by Make_Run when deciding which nodes to place on the - * toBeMade queue initially and by Make_Update to screen out USE and - * EXEC nodes. In the latter case, however, any other sort of node - * must be considered out-of-date since at least one of its children - * will have been recreated. - * - * Results: - * true if the node is out of date. false otherwise. - * - * Side Effects: - * The mtime field of the node and the cmtime field of its parents - * will/may be changed. - *----------------------------------------------------------------------- - */ -bool -Make_OODate(GNode *gn) /* the node to check */ -{ - bool oodate; - - /* - * Certain types of targets needn't even be sought as their datedness - * doesn't depend on their modification time... - */ - if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) { - (void)Dir_MTime(gn); - if (DEBUG(MAKE)) { - if (!is_out_of_date(gn->mtime)) { - printf("modified %s...", Targ_FmtTime(gn->mtime)); - } else { - printf("non-existent..."); - } - } - } - - /* - * A target is remade in one of the following circumstances: - * its modification time is smaller than that of its youngest child - * and it would actually be run (has commands or type OP_NOP) - * it's the object of a force operator - * it has no children, was on the lhs of an operator and doesn't exist - * already. - * - * Libraries are only considered out-of-date if the archive module says - * they are. - * - * These weird rules are brought to you by Backward-Compatibility and - * the strange people who wrote 'Make'. - */ - if (gn->type & OP_USE) { - /* - * If the node is a USE node it is *never* out of date - * no matter *what*. - */ - if (DEBUG(MAKE)) { - printf(".USE node..."); - } - oodate = false; - } else if ((gn->type & OP_LIB) && Arch_IsLib(gn)) { - if (DEBUG(MAKE)) { - printf("library..."); - } - - /* - * always out of date if no children and :: target - */ - - oodate = Arch_LibOODate(gn) || - (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP)); - } else if (gn->type & OP_JOIN) { - /* - * A target with the .JOIN attribute is only considered - * out-of-date if any of its children was out-of-date. - */ - if (DEBUG(MAKE)) { - printf(".JOIN node..."); - } - oodate = gn->childMade; - } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) { - /* - * A node which is the object of the force (!) operator or which has - * the .EXEC attribute is always considered out-of-date. - */ - if (DEBUG(MAKE)) { - if (gn->type & OP_FORCE) { - printf("! operator..."); - } else if (gn->type & OP_PHONY) { - printf(".PHONY node..."); - } else { - printf(".EXEC node..."); - } - } - oodate = true; - } else if (is_strictly_before(gn->mtime, gn->cmtime) || - (is_out_of_date(gn->cmtime) && - (is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP)))) - { - /* - * A node whose modification time is less than that of its - * youngest child or that has no children (cmtime == OUT_OF_DATE) and - * either doesn't exist (mtime == OUT_OF_DATE) or was the object of a - * :: operator is out-of-date. Why? Because that's the way Make does - * it. - */ - if (DEBUG(MAKE)) { - if (is_strictly_before(gn->mtime, gn->cmtime)) { - printf("modified before source..."); - } else if (is_out_of_date(gn->mtime)) { - printf("non-existent and no sources..."); - } else { - printf(":: operator and no sources..."); - } - } - oodate = true; - } else { -#if 0 - /* WHY? */ - if (DEBUG(MAKE)) { - printf("source %smade...", gn->childMade ? "" : "not "); - } - oodate = gn->childMade; -#else - oodate = false; -#endif /* 0 */ - } - - /* - * If the target isn't out-of-date, the parents need to know its - * modification time. Note that targets that appear to be out-of-date - * but aren't, because they have no commands and aren't of type OP_NOP, - * have their mtime stay below their children's mtime to keep parents from - * thinking they're out-of-date. - */ - if (!oodate) - Lst_ForEach(&gn->parents, MakeTimeStamp, gn); - - return oodate; -} - -/*- - *----------------------------------------------------------------------- * MakeAddChild -- * Function used by Make_Run to add a child to the list l. * It will only add the child if its make field is false. @@ -294,64 +121,6 @@ MakeAddChild( Lst_EnQueue(l, gn); } -/*- - *----------------------------------------------------------------------- - * Make_HandleUse -- - * Function called by Make_Run and SuffApplyTransform on the downward - * pass to handle .USE and transformation nodes. A callback function - * for Lst_ForEach, it implements the .USE and transformation - * functionality by copying the node's commands, type flags - * and children to the parent node. Should be called before the - * children are enqueued to be looked at by MakeAddChild. - * - * A .USE node is much like an explicit transformation rule, except - * its commands are always added to the target node, even if the - * target already has commands. - * - * Side Effects: - * Children and commands may be added to the parent and the parent's - * type may be changed. - * - *----------------------------------------------------------------------- - */ -void -Make_HandleUse( - GNode *cgn, /* The .USE node */ - GNode *pgn) /* The target of the .USE node */ -{ - GNode *gn; /* A child of the .USE node */ - LstNode ln; /* An element in the children list */ - - if (cgn->type & (OP_USE|OP_TRANSFORM)) { - if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) { - /* .USE or transformation and target has no commands -- append - * the child's commands to the parent. */ - Lst_Concat(&pgn->commands, &cgn->commands); - } - - for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Adv(ln)) { - gn = (GNode *)Lst_Datum(ln); - - if (Lst_AddNew(&pgn->children, gn)) { - Lst_AtEnd(&gn->parents, pgn); - pgn->unmade += 1; - } - } - - pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM); - - /* - * This child node is now "made", so we decrement the count of - * unmade children in the parent... We also remove the child - * from the parent's list to accurately reflect the number of decent - * children the parent has. This is used by Make_Run to decide - * whether to queue the parent or examine its children... - */ - if (cgn->type & OP_USE) { - pgn->unmade--; - } - } -} static void MakeHandleUse( void *pgn, /* the current parent */ @@ -485,100 +254,6 @@ Make_Update(GNode *cgn) /* the child node */ /*- *----------------------------------------------------------------------- - * MakeAddAllSrc -- - * Add a child's name to the ALLSRC and OODATE variables of the given - * node. Called from Make_DoAllVar via Lst_ForEach. A child is added only - * if it has not been given the .EXEC, .USE or .INVISIBLE attributes. - * .EXEC and .USE children are very rarely going to be files, so... - * A child is added to the OODATE variable if its modification time is - * later than that of its parent, as defined by Make, except if the - * parent is a .JOIN node. In that case, it is only added to the OODATE - * variable if it was actually made (since .JOIN nodes don't have - * modification times, the comparison is rather unfair...).. - * - * Side Effects: - * The ALLSRC variable for the given node is extended. - *----------------------------------------------------------------------- - */ -static void -MakeAddAllSrc( - void *cgnp, /* The child to add */ - void *pgnp) /* The parent to whose ALLSRC variable it should be */ - /* added */ -{ - GNode *cgn = (GNode *)cgnp; - GNode *pgn = (GNode *)pgnp; - if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) { - const char *child; - - if (OP_NOP(cgn->type) || - (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) { - /* - * this node is only source; use the specific pathname for it - */ - child = cgn->path != NULL ? cgn->path : cgn->name; - } - - Varq_Append(ALLSRC_INDEX, child, pgn); - if (pgn->type & OP_JOIN) { - if (cgn->made == MADE) { - Varq_Append(OODATE_INDEX, child, pgn); - } - } else if (is_strictly_before(pgn->mtime, cgn->mtime) || - (!is_strictly_before(cgn->mtime, now) && cgn->made == MADE)) - { - /* - * It goes in the OODATE variable if the parent is younger than the - * child or if the child has been modified more recently than - * the start of the make. This is to keep pmake from getting - * confused if something else updates the parent after the - * make starts (shouldn't happen, I know, but sometimes it - * does). In such a case, if we've updated the kid, the parent - * is likely to have a modification time later than that of - * the kid and anything that relies on the OODATE variable will - * be hosed. - * - */ - Varq_Append(OODATE_INDEX, child, pgn); - } - } -} - -/*- - *----------------------------------------------------------------------- - * Make_DoAllVar -- - * Set up the ALLSRC and OODATE variables. Sad to say, it must be - * done separately, rather than while traversing the graph. This is - * because Make defined OODATE to contain all sources whose modification - * times were later than that of the target, *not* those sources that - * were out-of-date. Since in both compatibility and native modes, - * the modification time of the parent isn't found until the child - * has been dealt with, we have to wait until now to fill in the - * variable. As for ALLSRC, the ordering is important and not - * guaranteed when in native mode, so it must be set here, too. - * - * Side Effects: - * The ALLSRC and OODATE variables of the given node is filled in. - * If the node is a .JOIN node, its TARGET variable will be set to - * match its ALLSRC variable. - *----------------------------------------------------------------------- - */ -void -Make_DoAllVar(GNode *gn) -{ - Lst_ForEach(&gn->children, MakeAddAllSrc, gn); - - if (Varq_Value(OODATE_INDEX, gn) == NULL) - Varq_Set(OODATE_INDEX, "", gn); - if (Varq_Value(ALLSRC_INDEX, gn) == NULL) - Varq_Set(ALLSRC_INDEX, "", gn); - - if (gn->type & OP_JOIN) - Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), gn); -} - -/*- - *----------------------------------------------------------------------- * MakeStartJobs -- * Start as many jobs as possible. * |