Annotation of src/usr.bin/make/compat.c, Revision 1.72
1.36 espie 1: /* $OpenPackages$ */
1.61 espie 2: /* $OpenBSD$ */
1.8 millert 3: /* $NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $ */
1.1 deraadt 4:
5: /*
6: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
7: * Copyright (c) 1988, 1989 by Adam de Boor
8: * Copyright (c) 1989 by Berkeley Softworks
9: * All rights reserved.
10: *
11: * This code is derived from software contributed to Berkeley by
12: * Adam de Boor.
13: *
14: * Redistribution and use in source and binary forms, with or without
15: * modification, are permitted provided that the following conditions
16: * are met:
17: * 1. Redistributions of source code must retain the above copyright
18: * notice, this list of conditions and the following disclaimer.
19: * 2. Redistributions in binary form must reproduce the above copyright
20: * notice, this list of conditions and the following disclaimer in the
21: * documentation and/or other materials provided with the distribution.
1.49 millert 22: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: */
38:
1.39 espie 39: #include <limits.h>
1.37 espie 40: #include <signal.h>
41: #include <stdio.h>
1.39 espie 42: #include <stdlib.h>
1.37 espie 43: #include "config.h"
44: #include "defines.h"
45: #include "dir.h"
1.55 espie 46: #include "engine.h"
1.37 espie 47: #include "compat.h"
48: #include "suff.h"
49: #include "var.h"
50: #include "targ.h"
1.70 espie 51: #include "targequiv.h"
1.37 espie 52: #include "error.h"
53: #include "extern.h"
54: #include "gnode.h"
55: #include "timestamp.h"
56: #include "lst.h"
1.1 deraadt 57:
1.36 espie 58: static void CompatMake(void *, void *);
1.60 espie 59:
1.1 deraadt 60: /*-
61: *-----------------------------------------------------------------------
62: * CompatMake --
63: * Make a target.
64: *
65: * Side Effects:
66: * If an error is detected and not being ignored, the process exits.
67: *-----------------------------------------------------------------------
68: */
1.26 espie 69: static void
1.50 espie 70: CompatMake(void *gnp, /* The node to make */
71: void *pgnp) /* Parent to abort if necessary */
1.1 deraadt 72: {
1.57 espie 73: GNode *gn = (GNode *)gnp;
74: GNode *pgn = (GNode *)pgnp;
75:
1.70 espie 76: GNode *sib;
77: bool cmdsOk;
78:
79: if (DEBUG(MAKE))
80: printf("CompatMake(%s, %s)\n", pgn ? pgn->name : "NULL",
81: gn->name);
82:
83: /* XXX some loops are not loops, people write dependencies
84: * between siblings to make sure they get built.
85: * Also, we don't recognize direct loops.
86: */
87: if (gn == pgn)
88: return;
1.63 espie 89: look_harder_for_target(gn);
90:
1.70 espie 91: if (pgn != NULL && is_sibling(gn, pgn))
92: return;
93:
94: if (pgn == NULL)
95: pgn = gn;
96:
1.57 espie 97: if (pgn->type & OP_MADE) {
1.70 espie 98: sib = gn;
99: do {
1.72 ! espie 100: sib->mtime = gn->mtime;
1.70 espie 101: sib->built_status = UPTODATE;
102: sib = sib->sibling;
103: } while (sib != gn);
1.57 espie 104: }
105:
106: if (gn->type & OP_USE) {
107: Make_HandleUse(gn, pgn);
1.68 espie 108: } else if (gn->built_status == UNKNOWN) {
1.57 espie 109: /* First mark ourselves to be made, then apply whatever
1.60 espie 110: * transformations the suffix module thinks are necessary.
111: * Once that's done, we can descend and make all our children.
112: * If any of them has an error but the -k flag was given,
1.67 espie 113: * our 'must_make' field will be set false again. This is our
1.60 espie 114: * signal to not attempt to do anything but abort our
115: * parent as well. */
1.67 espie 116: gn->must_make = true;
117: gn->built_status = BEINGMADE;
1.70 espie 118: /* note that, in case we have siblings, we only check all
119: * children for all siblings, but we don't try to apply
120: * any other rule.
121: */
122: sib = gn;
123: do {
124: Suff_FindDeps(sib);
125: Lst_ForEach(&sib->children, CompatMake, gn);
126: sib = sib->sibling;
127: } while (sib != gn);
128:
1.67 espie 129: if (!gn->must_make) {
1.70 espie 130: Error("Build for %s aborted", gn->name);
1.67 espie 131: gn->built_status = ABORTED;
132: pgn->must_make = false;
1.57 espie 133: return;
134: }
1.5 millert 135:
1.57 espie 136: /* All the children were made ok. Now cmtime contains the
137: * modification time of the newest child, we need to find out
1.60 espie 138: * if we exist and when we were modified last. The criteria
139: * for datedness are defined by the Make_OODate function. */
1.57 espie 140: if (DEBUG(MAKE))
141: printf("Examining %s...", gn->name);
1.60 espie 142: if (!Make_OODate(gn)) {
1.67 espie 143: gn->built_status = UPTODATE;
1.57 espie 144: if (DEBUG(MAKE))
145: printf("up-to-date.\n");
146: return;
147: } else if (DEBUG(MAKE))
148: printf("out-of-date.\n");
149:
1.60 espie 150: /* If the user is just seeing if something is out-of-date,
151: * exit now to tell him/her "yes". */
1.57 espie 152: if (queryFlag)
153: exit(-1);
154:
1.70 espie 155: /* normally, we run the job, but if we can't find any
156: * commands, we defer to siblings instead.
157: */
158: sib = gn;
159: do {
160: /* We need to be re-made. We also have to make sure
161: * we've got a $? variable. To be nice, we also define
162: * the $> variable using Make_DoAllVar().
163: */
164: Make_DoAllVar(sib);
165: cmdsOk = Job_CheckCommands(sib);
166: if (cmdsOk || (gn->type & OP_OPTIONAL))
167: break;
168:
169: sib = sib->sibling;
170: } while (sib != gn);
1.57 espie 171:
1.70 espie 172: if (cmdsOk) {
1.62 espie 173: /* Our commands are ok, but we still have to worry
174: * about the -t flag... */
175: if (!touchFlag)
1.70 espie 176: run_gnode(sib);
177: else {
178: Job_Touch(sib);
179: if (gn != sib)
180: Job_Touch(gn);
181: }
182: } else {
183: job_failure(gn, Fatal);
184: sib->built_status = ERROR;
185: }
186:
187: /* copy over what we just did */
188: gn->built_status = sib->built_status;
1.57 espie 189:
1.67 espie 190: if (gn->built_status != ERROR) {
1.57 espie 191: /* If the node was made successfully, mark it so,
1.60 espie 192: * update its modification time and timestamp all
193: * its parents.
194: * This is to keep its state from affecting that of
195: * its parent. */
1.67 espie 196: gn->built_status = MADE;
1.70 espie 197: sib->built_status = MADE;
1.57 espie 198: /* This is what Make does and it's actually a good
199: * thing, as it allows rules like
200: *
201: * cmp -s y.tab.h parse.h || cp y.tab.h parse.h
202: *
203: * to function as intended. Unfortunately, thanks to
1.60 espie 204: * the stateless nature of NFS (and the speed of
205: * this program), there are times when the
206: * modification time of a file created on a remote
207: * machine will not be modified before the stat()
208: * implied by the Dir_MTime occurs, thus leading us
209: * to believe that the file is unchanged, wreaking
210: * havoc with files that depend on this one.
1.57 espie 211: */
212: if (noExecute || is_out_of_date(Dir_MTime(gn)))
1.72 ! espie 213: ts_set_from_now(gn->mtime);
1.57 espie 214: if (is_strictly_before(gn->mtime, gn->cmtime))
215: gn->mtime = gn->cmtime;
1.70 espie 216: if (sib != gn) {
217: if (noExecute || is_out_of_date(Dir_MTime(sib)))
1.72 ! espie 218: ts_set_from_now(sib->mtime);
1.70 espie 219: if (is_strictly_before(sib->mtime, sib->cmtime))
220: sib->mtime = sib->cmtime;
221: }
1.57 espie 222: if (DEBUG(MAKE))
1.59 espie 223: printf("update time: %s\n",
1.57 espie 224: time_to_string(gn->mtime));
225: if (!(gn->type & OP_EXEC)) {
226: pgn->childMade = true;
227: Make_TimeStamp(pgn, gn);
228: }
229: } else if (keepgoing)
1.67 espie 230: pgn->must_make = false;
1.57 espie 231: else {
1.36 espie 232:
1.57 espie 233: if (gn->lineno)
234: printf("\n\nStop in %s (line %lu of %s).\n",
235: Var_Value(".CURDIR"),
236: (unsigned long)gn->lineno,
237: gn->fname);
238: else
1.59 espie 239: printf("\n\nStop in %s.\n",
1.57 espie 240: Var_Value(".CURDIR"));
241: exit(1);
242: }
1.67 espie 243: } else if (gn->built_status == ERROR)
244: /* Already had an error when making this beastie. Tell the
245: * parent to abort. */
246: pgn->must_make = false;
1.57 espie 247: else {
1.67 espie 248: switch (gn->built_status) {
1.57 espie 249: case BEINGMADE:
1.70 espie 250: Error("Graph cycles through %s", gn->name);
1.67 espie 251: gn->built_status = ERROR;
252: pgn->must_make = false;
1.57 espie 253: break;
254: case MADE:
255: if ((gn->type & OP_EXEC) == 0) {
256: pgn->childMade = true;
257: Make_TimeStamp(pgn, gn);
258: }
259: break;
260: case UPTODATE:
261: if ((gn->type & OP_EXEC) == 0)
262: Make_TimeStamp(pgn, gn);
263: break;
264: default:
265: break;
266: }
1.1 deraadt 267: }
268: }
1.36 espie 269:
1.1 deraadt 270: void
1.50 espie 271: Compat_Run(Lst targs) /* List of target nodes to re-create */
1.1 deraadt 272: {
1.60 espie 273: GNode *gn = NULL; /* Current root target */
274: int errors; /* Number of targets not remade due to errors */
1.57 espie 275:
1.71 espie 276: setup_engine(0);
1.57 espie 277: /* If the user has defined a .BEGIN target, execute the commands
278: * attached to it. */
279: if (!queryFlag) {
1.69 espie 280: if (run_gnode(begin_node) == ERROR) {
1.60 espie 281: printf("\n\nStop.\n");
282: exit(1);
1.57 espie 283: }
284: }
285:
286: /* For each entry in the list of targets to create, call CompatMake on
1.67 espie 287: * it to create the thing. CompatMake will leave the 'built_status'
288: * field of gn in one of several states:
1.57 espie 289: * UPTODATE gn was already up-to-date
290: * MADE gn was recreated successfully
1.60 espie 291: * ERROR An error occurred while gn was being
292: * created
1.59 espie 293: * ABORTED gn was not remade because one of its
1.60 espie 294: * inferiors could not be made due to errors.
1.57 espie 295: */
296: errors = 0;
297: while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) {
1.70 espie 298: CompatMake(gn, NULL);
1.57 espie 299:
1.67 espie 300: if (gn->built_status == UPTODATE)
1.57 espie 301: printf("`%s' is up to date.\n", gn->name);
1.67 espie 302: else if (gn->built_status == ABORTED) {
1.59 espie 303: printf("`%s' not remade because of errors.\n",
1.57 espie 304: gn->name);
1.58 espie 305: errors++;
1.57 espie 306: }
307: }
308:
309: /* If the user has defined a .END target, run its commands. */
310: if (errors == 0)
1.69 espie 311: run_gnode(end_node);
1.1 deraadt 312: }