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