Annotation of src/usr.bin/make/engine.c, Revision 1.3
1.3 ! espie 1: /* $OpenBSD: engine.c,v 1.2 2007/09/16 12:09:36 espie Exp $ */
1.1 espie 2: /*
3: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
4: * Copyright (c) 1988, 1989 by Adam de Boor
5: * Copyright (c) 1989 by Berkeley Softworks
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Adam de Boor.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #include <limits.h>
37: #include <stdio.h>
38: #include <errno.h>
39: #include <fcntl.h>
40: #include <unistd.h>
41: #include <string.h>
42: #include "config.h"
43: #include "defines.h"
44: #include "dir.h"
45: #include "engine.h"
46: #include "arch.h"
47: #include "gnode.h"
48: #include "targ.h"
49: #include "var.h"
50: #include "extern.h"
51: #include "lst.h"
52: #include "timestamp.h"
53: #include "make.h"
54: #include "main.h"
55:
56: static void MakeTimeStamp(void *, void *);
57: static void MakeAddAllSrc(void *, void *);
58:
59: /*-
60: *-----------------------------------------------------------------------
61: * Job_CheckCommands --
62: * Make sure the given node has all the commands it needs.
63: *
64: * Results:
65: * true if the commands list is/was ok.
66: *
67: * Side Effects:
68: * The node will have commands from the .DEFAULT rule added to it
69: * if it needs them.
70: *-----------------------------------------------------------------------
71: */
72: bool
1.3 ! espie 73: Job_CheckCommands(GNode *gn, void (*abortProc)(char *, ...))
1.1 espie 74: {
1.3 ! espie 75: if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
! 76: (gn->type & OP_LIB) == 0) {
! 77: /*
! 78: * No commands. Look for .DEFAULT rule from which we might infer
! 79: * commands
! 80: */
! 81: if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) {
! 82: /*
! 83: * Make only looks for a .DEFAULT if the node was never
! 84: * the target of an operator, so that's what we do too.
! 85: * If a .DEFAULT was given, we substitute its commands
! 86: * for gn's commands and set the IMPSRC variable to be
! 87: * the target's name The DEFAULT node acts like a
! 88: * transformation rule, in that gn also inherits any
! 89: * attributes or sources attached to .DEFAULT itself.
! 90: */
! 91: Make_HandleUse(DEFAULT, gn);
! 92: Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), gn);
! 93: } else if (is_out_of_date(Dir_MTime(gn))) {
! 94: /*
! 95: * The node wasn't the target of an operator we have no
! 96: * .DEFAULT rule to go on and the target doesn't
! 97: * already exist. There's nothing more we can do for
! 98: * this branch. If the -k flag wasn't given, we stop in
! 99: * our tracks, otherwise we just don't update this
! 100: * node's parents so they never get examined.
! 101: */
! 102: static const char msg[] =
! 103: "make: don't know how to make";
! 104:
! 105: if (gn->type & OP_OPTIONAL) {
! 106: (void)fprintf(stdout, "%s %s(ignored)\n", msg,
! 107: gn->name);
! 108: (void)fflush(stdout);
! 109: } else if (keepgoing) {
! 110: (void)fprintf(stdout, "%s %s(continuing)\n",
! 111: msg, gn->name);
! 112: (void)fflush(stdout);
! 113: return false;
! 114: } else {
! 115: (*abortProc)("%s %s. Stop in %s.", msg,
! 116: gn->name, Var_Value(".CURDIR"));
! 117: return false;
! 118: }
! 119: }
1.1 espie 120: }
1.3 ! espie 121: return true;
1.1 espie 122: }
123:
124: /*-
125: *-----------------------------------------------------------------------
126: * Job_Touch --
127: * Touch the given target. Called by JobStart when the -t flag was
128: * given
129: *
130: * Side Effects:
131: * The data modification of the file is changed. In addition, if the
132: * file did not exist, it is created.
133: *-----------------------------------------------------------------------
134: */
135: void
1.3 ! espie 136: Job_Touch(GNode *gn, bool silent)
1.1 espie 137: {
1.3 ! espie 138: int streamID; /* ID of stream opened to do the touch */
1.1 espie 139:
1.3 ! espie 140: if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
! 141: /*
! 142: * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual"
! 143: * targets and, as such, shouldn't really be created.
! 144: */
! 145: return;
! 146: }
1.1 espie 147:
1.3 ! espie 148: if (!silent) {
! 149: (void)fprintf(stdout, "touch %s\n", gn->name);
! 150: (void)fflush(stdout);
! 151: }
1.1 espie 152:
1.3 ! espie 153: if (noExecute) {
! 154: return;
! 155: }
1.1 espie 156:
1.3 ! espie 157: if (gn->type & OP_ARCHV) {
! 158: Arch_Touch(gn);
! 159: } else if (gn->type & OP_LIB) {
! 160: Arch_TouchLib(gn);
! 161: } else {
! 162: const char *file = gn->path != NULL ? gn->path : gn->name;
! 163:
! 164: if (set_times(file) == -1){
! 165: streamID = open(file, O_RDWR | O_CREAT, 0666);
! 166:
! 167: if (streamID >= 0) {
! 168: char c;
! 169:
! 170: /*
! 171: * Read and write a byte to the file to change
! 172: * the modification time, then close the file.
! 173: */
! 174: if (read(streamID, &c, 1) == 1) {
! 175: (void)lseek(streamID, 0, SEEK_SET);
! 176: (void)write(streamID, &c, 1);
! 177: }
! 178:
! 179: (void)close(streamID);
! 180: } else {
! 181: (void)fprintf(stdout,
! 182: "*** couldn't touch %s: %s", file,
! 183: strerror(errno));
! 184: (void)fflush(stdout);
! 185: }
1.1 espie 186: }
187: }
188: }
189:
190: /*-
191: *-----------------------------------------------------------------------
192: * Make_TimeStamp --
193: * Set the cmtime field of a parent node based on the mtime stamp in its
194: * child.
195: *
196: * Side Effects:
197: * The cmtime of the parent node will be changed if the mtime
198: * field of the child is greater than it.
199: *-----------------------------------------------------------------------
200: */
201: void
202: Make_TimeStamp(
203: GNode *pgn, /* the current parent */
204: GNode *cgn) /* the child we've just examined */
205: {
1.3 ! espie 206: if (is_strictly_before(pgn->cmtime, cgn->mtime))
! 207: pgn->cmtime = cgn->mtime;
1.1 espie 208: }
209:
210: /*-
211: *-----------------------------------------------------------------------
212: * Make_HandleUse --
213: * Function called by Make_Run and SuffApplyTransform on the downward
214: * pass to handle .USE and transformation nodes. A callback function
215: * for Lst_ForEach, it implements the .USE and transformation
216: * functionality by copying the node's commands, type flags
217: * and children to the parent node. Should be called before the
218: * children are enqueued to be looked at by MakeAddChild.
219: *
220: * A .USE node is much like an explicit transformation rule, except
221: * its commands are always added to the target node, even if the
222: * target already has commands.
223: *
224: * Side Effects:
225: * Children and commands may be added to the parent and the parent's
226: * type may be changed.
227: *
228: *-----------------------------------------------------------------------
229: */
230: void
231: Make_HandleUse(
232: GNode *cgn, /* The .USE node */
233: GNode *pgn) /* The target of the .USE node */
234: {
1.3 ! espie 235: GNode *gn; /* A child of the .USE node */
! 236: LstNode ln; /* An element in the children list */
1.1 espie 237:
1.3 ! espie 238: if (cgn->type & (OP_USE|OP_TRANSFORM)) {
! 239: if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) {
! 240: /* .USE or transformation and target has no commands --
! 241: * append the child's commands to the parent. */
! 242: Lst_Concat(&pgn->commands, &cgn->commands);
! 243: }
1.1 espie 244:
1.3 ! espie 245: for (ln = Lst_First(&cgn->children); ln != NULL;
! 246: ln = Lst_Adv(ln)) {
! 247: gn = (GNode *)Lst_Datum(ln);
! 248:
! 249: if (Lst_AddNew(&pgn->children, gn)) {
! 250: Lst_AtEnd(&gn->parents, pgn);
! 251: pgn->unmade += 1;
! 252: }
! 253: }
1.1 espie 254:
1.3 ! espie 255: pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
1.1 espie 256:
1.3 ! espie 257: /*
! 258: * This child node is now "made", so we decrement the count of
! 259: * unmade children in the parent... We also remove the child
! 260: * from the parent's list to accurately reflect the number of
! 261: * decent children the parent has. This is used by Make_Run to
! 262: * decide whether to queue the parent or examine its
! 263: * children...
! 264: */
! 265: if (cgn->type & OP_USE) {
! 266: pgn->unmade--;
! 267: }
1.1 espie 268: }
269: }
270:
271: /*-
272: *-----------------------------------------------------------------------
273: * MakeAddAllSrc --
274: * Add a child's name to the ALLSRC and OODATE variables of the given
275: * node. Called from Make_DoAllVar via Lst_ForEach. A child is added only
276: * if it has not been given the .EXEC, .USE or .INVISIBLE attributes.
277: * .EXEC and .USE children are very rarely going to be files, so...
278: * A child is added to the OODATE variable if its modification time is
279: * later than that of its parent, as defined by Make, except if the
280: * parent is a .JOIN node. In that case, it is only added to the OODATE
281: * variable if it was actually made (since .JOIN nodes don't have
282: * modification times, the comparison is rather unfair...)..
283: *
284: * Side Effects:
285: * The ALLSRC variable for the given node is extended.
286: *-----------------------------------------------------------------------
287: */
288: static void
289: MakeAddAllSrc(
290: void *cgnp, /* The child to add */
291: void *pgnp) /* The parent to whose ALLSRC variable it should be */
292: /* added */
293: {
1.3 ! espie 294: GNode *cgn = (GNode *)cgnp;
! 295: GNode *pgn = (GNode *)pgnp;
! 296: if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
! 297: const char *child;
! 298:
! 299: if (OP_NOP(cgn->type) ||
! 300: (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) {
! 301: /*
! 302: * this node is only source; use the specific pathname
! 303: * for it
! 304: */
! 305: child = cgn->path != NULL ? cgn->path : cgn->name;
! 306: }
1.1 espie 307:
1.3 ! espie 308: Varq_Append(ALLSRC_INDEX, child, pgn);
! 309: if (pgn->type & OP_JOIN) {
! 310: if (cgn->made == MADE) {
! 311: Varq_Append(OODATE_INDEX, child, pgn);
! 312: }
! 313: } else if (is_strictly_before(pgn->mtime, cgn->mtime) ||
! 314: (!is_strictly_before(cgn->mtime, now) &&
! 315: cgn->made == MADE)) {
! 316: /*
! 317: * It goes in the OODATE variable if the parent is
! 318: * younger than the child or if the child has been
! 319: * modified more recently than the start of the make.
! 320: * This is to keep pmake from getting confused if
! 321: * something else updates the parent after the make
! 322: * starts (shouldn't happen, I know, but sometimes it
! 323: * does). In such a case, if we've updated the kid, the
! 324: * parent is likely to have a modification time later
! 325: * than that of the kid and anything that relies on the
! 326: * OODATE variable will be hosed.
! 327: *
! 328: */
! 329: Varq_Append(OODATE_INDEX, child, pgn);
! 330: }
1.1 espie 331: }
332: }
333:
334: /*-
335: *-----------------------------------------------------------------------
336: * Make_DoAllVar --
337: * Set up the ALLSRC and OODATE variables. Sad to say, it must be
338: * done separately, rather than while traversing the graph. This is
339: * because Make defined OODATE to contain all sources whose modification
340: * times were later than that of the target, *not* those sources that
341: * were out-of-date. Since in both compatibility and native modes,
342: * the modification time of the parent isn't found until the child
343: * has been dealt with, we have to wait until now to fill in the
344: * variable. As for ALLSRC, the ordering is important and not
345: * guaranteed when in native mode, so it must be set here, too.
346: *
347: * Side Effects:
348: * The ALLSRC and OODATE variables of the given node is filled in.
349: * If the node is a .JOIN node, its TARGET variable will be set to
350: * match its ALLSRC variable.
351: *-----------------------------------------------------------------------
352: */
353: void
354: Make_DoAllVar(GNode *gn)
355: {
1.3 ! espie 356: Lst_ForEach(&gn->children, MakeAddAllSrc, gn);
1.1 espie 357:
1.3 ! espie 358: if (Varq_Value(OODATE_INDEX, gn) == NULL)
! 359: Varq_Set(OODATE_INDEX, "", gn);
! 360: if (Varq_Value(ALLSRC_INDEX, gn) == NULL)
! 361: Varq_Set(ALLSRC_INDEX, "", gn);
1.1 espie 362:
1.3 ! espie 363: if (gn->type & OP_JOIN)
! 364: Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), gn);
1.1 espie 365: }
366:
367: /* Wrapper to call Make_TimeStamp from a forEach loop. */
368: static void
369: MakeTimeStamp(
370: void *pgn, /* the current parent */
371: void *cgn) /* the child we've just examined */
372: {
1.3 ! espie 373: Make_TimeStamp((GNode *)pgn, (GNode *)cgn);
1.1 espie 374: }
375:
376: /*-
377: *-----------------------------------------------------------------------
378: * Make_OODate --
379: * See if a given node is out of date with respect to its sources.
380: * Used by Make_Run when deciding which nodes to place on the
381: * toBeMade queue initially and by Make_Update to screen out USE and
382: * EXEC nodes. In the latter case, however, any other sort of node
383: * must be considered out-of-date since at least one of its children
384: * will have been recreated.
385: *
386: * Results:
387: * true if the node is out of date. false otherwise.
388: *
389: * Side Effects:
390: * The mtime field of the node and the cmtime field of its parents
391: * will/may be changed.
392: *-----------------------------------------------------------------------
393: */
394: bool
395: Make_OODate(GNode *gn) /* the node to check */
396: {
1.3 ! espie 397: bool oodate;
1.1 espie 398:
399: /*
1.3 ! espie 400: * Certain types of targets needn't even be sought as their datedness
! 401: * doesn't depend on their modification time...
1.1 espie 402: */
1.3 ! espie 403: if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
! 404: (void)Dir_MTime(gn);
! 405: if (DEBUG(MAKE)) {
! 406: if (!is_out_of_date(gn->mtime)) {
! 407: printf("modified %s...",
! 408: time_to_string(gn->mtime));
! 409: } else {
! 410: printf("non-existent...");
! 411: }
! 412: }
1.1 espie 413: }
414:
415: /*
1.3 ! espie 416: * A target is remade in one of the following circumstances:
! 417: * its modification time is smaller than that of its youngest child
! 418: * and it would actually be run (has commands or type OP_NOP)
! 419: * it's the object of a force operator
! 420: * it has no children, was on the lhs of an operator and doesn't
! 421: * exist already.
! 422: *
! 423: * Libraries are only considered out-of-date if the archive module says
! 424: * they are.
! 425: *
! 426: * These weird rules are brought to you by Backward-Compatibility and
! 427: * the strange people who wrote 'Make'.
1.1 espie 428: */
1.3 ! espie 429: if (gn->type & OP_USE) {
! 430: /*
! 431: * If the node is a USE node it is *never* out of date
! 432: * no matter *what*.
! 433: */
! 434: if (DEBUG(MAKE)) {
! 435: printf(".USE node...");
! 436: }
! 437: oodate = false;
! 438: } else if ((gn->type & OP_LIB) && Arch_IsLib(gn)) {
! 439: if (DEBUG(MAKE)) {
! 440: printf("library...");
! 441: }
1.1 espie 442:
1.3 ! espie 443: /*
! 444: * always out of date if no children and :: target
! 445: */
! 446:
! 447: oodate = Arch_LibOODate(gn) ||
! 448: (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP));
! 449: } else if (gn->type & OP_JOIN) {
! 450: /*
! 451: * A target with the .JOIN attribute is only considered
! 452: * out-of-date if any of its children was out-of-date.
! 453: */
! 454: if (DEBUG(MAKE)) {
! 455: printf(".JOIN node...");
! 456: }
! 457: oodate = gn->childMade;
! 458: } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
! 459: /*
! 460: * A node which is the object of the force (!) operator or
! 461: * which has the .EXEC attribute is always considered
! 462: * out-of-date.
! 463: */
! 464: if (DEBUG(MAKE)) {
! 465: if (gn->type & OP_FORCE) {
! 466: printf("! operator...");
! 467: } else if (gn->type & OP_PHONY) {
! 468: printf(".PHONY node...");
! 469: } else {
! 470: printf(".EXEC node...");
! 471: }
! 472: }
! 473: oodate = true;
! 474: } else if (is_strictly_before(gn->mtime, gn->cmtime) ||
! 475: (is_out_of_date(gn->cmtime) &&
! 476: (is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP)))) {
! 477: /*
! 478: * A node whose modification time is less than that of its
! 479: * youngest child or that has no children (cmtime ==
! 480: * OUT_OF_DATE) and either doesn't exist (mtime == OUT_OF_DATE)
! 481: * or was the object of a :: operator is out-of-date. Why?
! 482: * Because that's the way Make does it.
! 483: */
! 484: if (DEBUG(MAKE)) {
! 485: if (is_strictly_before(gn->mtime, gn->cmtime)) {
! 486: printf("modified before source...");
! 487: } else if (is_out_of_date(gn->mtime)) {
! 488: printf("non-existent and no sources...");
! 489: } else {
! 490: printf(":: operator and no sources...");
! 491: }
! 492: }
! 493: oodate = true;
! 494: } else {
1.1 espie 495: #if 0
1.3 ! espie 496: /* WHY? */
! 497: if (DEBUG(MAKE)) {
! 498: printf("source %smade...", gn->childMade ? "" : "not ");
! 499: }
! 500: oodate = gn->childMade;
1.1 espie 501: #else
1.3 ! espie 502: oodate = false;
1.1 espie 503: #endif /* 0 */
1.3 ! espie 504: }
1.1 espie 505:
1.3 ! espie 506: /*
! 507: * If the target isn't out-of-date, the parents need to know its
! 508: * modification time. Note that targets that appear to be out-of-date
! 509: * but aren't, because they have no commands and aren't of type OP_NOP,
! 510: * have their mtime stay below their children's mtime to keep parents
! 511: * from thinking they're out-of-date.
! 512: */
! 513: if (!oodate)
! 514: Lst_ForEach(&gn->parents, MakeTimeStamp, gn);
1.1 espie 515:
1.3 ! espie 516: return oodate;
1.1 espie 517: }
518: