Annotation of src/usr.bin/make/compat.c, Revision 1.94
1.94 ! espie 1: /* $OpenBSD: compat.c,v 1.93 2020/01/26 12:41:21 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 "defines.h"
44: #include "dir.h"
1.55 espie 45: #include "engine.h"
1.77 espie 46: #include "job.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.84 espie 73: GNode *gn = gnp;
1.85 espie 74: GNode *pgn = pgnp;
1.57 espie 75:
1.70 espie 76: GNode *sib;
77: bool cmdsOk;
78:
79: if (DEBUG(MAKE))
1.73 espie 80: printf("CompatMake(%s, %s)\n", pgn ? pgn->name : "NULL",
1.70 espie 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.78 espie 89: /* handle .USE right away */
90: if (gn->type & OP_USE) {
91: Make_HandleUse(gn, pgn);
92: return;
93: }
94:
1.63 espie 95: look_harder_for_target(gn);
96:
1.70 espie 97: if (pgn != NULL && is_sibling(gn, pgn))
98: return;
99:
100: if (pgn == NULL)
101: pgn = gn;
102:
1.78 espie 103: switch(gn->built_status) {
104: case UNKNOWN:
1.88 espie 105: /* First mark ourselves to be built, then apply whatever
1.60 espie 106: * transformations the suffix module thinks are necessary.
107: * Once that's done, we can descend and make all our children.
108: * If any of them has an error but the -k flag was given,
1.92 espie 109: * we will abort. */
1.67 espie 110: gn->must_make = true;
1.87 espie 111: gn->built_status = BUILDING;
1.70 espie 112: /* note that, in case we have siblings, we only check all
113: * children for all siblings, but we don't try to apply
114: * any other rule.
115: */
116: sib = gn;
117: do {
118: Suff_FindDeps(sib);
119: Lst_ForEach(&sib->children, CompatMake, gn);
120: sib = sib->sibling;
121: } while (sib != gn);
122:
1.92 espie 123: if (gn->built_status == ABORTED) {
1.70 espie 124: Error("Build for %s aborted", gn->name);
1.92 espie 125: pgn->built_status = ABORTED;
1.57 espie 126: return;
127: }
1.5 millert 128:
1.88 espie 129: /* All the children built ok. Now youngest points to
1.80 espie 130: * the newest child, we need to find out
1.60 espie 131: * if we exist and when we were modified last. The criteria
132: * for datedness are defined by the Make_OODate function. */
1.57 espie 133: if (DEBUG(MAKE))
134: printf("Examining %s...", gn->name);
1.60 espie 135: if (!Make_OODate(gn)) {
1.67 espie 136: gn->built_status = UPTODATE;
1.57 espie 137: if (DEBUG(MAKE))
138: printf("up-to-date.\n");
139: return;
140: } else if (DEBUG(MAKE))
141: printf("out-of-date.\n");
142:
1.60 espie 143: /* If the user is just seeing if something is out-of-date,
144: * exit now to tell him/her "yes". */
1.57 espie 145: if (queryFlag)
1.75 deraadt 146: exit(1);
1.57 espie 147:
1.70 espie 148: /* normally, we run the job, but if we can't find any
149: * commands, we defer to siblings instead.
150: */
151: sib = gn;
152: do {
1.88 espie 153: /* We need to be rebuilt. We also have to make sure
1.70 espie 154: * we've got a $? variable. To be nice, we also define
1.73 espie 155: * the $> variable using Make_DoAllVar().
1.70 espie 156: */
157: Make_DoAllVar(sib);
1.77 espie 158: cmdsOk = node_find_valid_commands(sib);
1.70 espie 159: if (cmdsOk || (gn->type & OP_OPTIONAL))
160: break;
161:
162: sib = sib->sibling;
163: } while (sib != gn);
1.57 espie 164:
1.70 espie 165: if (cmdsOk) {
1.62 espie 166: /* Our commands are ok, but we still have to worry
167: * about the -t flag... */
168: if (!touchFlag)
1.70 espie 169: run_gnode(sib);
170: else {
171: Job_Touch(sib);
172: if (gn != sib)
173: Job_Touch(gn);
174: }
175: } else {
1.77 espie 176: node_failure(gn);
1.70 espie 177: sib->built_status = ERROR;
178: }
179:
180: /* copy over what we just did */
181: gn->built_status = sib->built_status;
1.57 espie 182:
1.90 espie 183: if (gn->built_status == REBUILT) {
184: /* If the node was built successfully,
1.60 espie 185: * update its modification time and timestamp all
186: * its parents.
187: * This is to keep its state from affecting that of
188: * its parent. */
1.57 espie 189: /* This is what Make does and it's actually a good
190: * thing, as it allows rules like
191: *
192: * cmp -s y.tab.h parse.h || cp y.tab.h parse.h
193: *
194: * to function as intended. Unfortunately, thanks to
1.60 espie 195: * the stateless nature of NFS (and the speed of
196: * this program), there are times when the
197: * modification time of a file created on a remote
198: * machine will not be modified before the stat()
199: * implied by the Dir_MTime occurs, thus leading us
200: * to believe that the file is unchanged, wreaking
201: * havoc with files that depend on this one.
1.57 espie 202: */
203: if (noExecute || is_out_of_date(Dir_MTime(gn)))
1.80 espie 204: clock_gettime(CLOCK_REALTIME, &gn->mtime);
1.82 espie 205: if (is_strictly_before(gn->mtime, gn->youngest->mtime))
206: gn->mtime = gn->youngest->mtime;
1.70 espie 207: if (sib != gn) {
208: if (noExecute || is_out_of_date(Dir_MTime(sib)))
1.80 espie 209: clock_gettime(CLOCK_REALTIME,
210: &sib->mtime);
211: if (is_strictly_before(sib->mtime,
1.82 espie 212: sib->youngest->mtime))
213: sib->mtime = sib->youngest->mtime;
1.70 espie 214: }
1.57 espie 215: if (DEBUG(MAKE))
1.59 espie 216: printf("update time: %s\n",
1.80 espie 217: time_to_string(&gn->mtime));
1.93 espie 218: pgn->child_rebuilt = true;
219: Make_TimeStamp(pgn, gn);
1.57 espie 220: } else if (keepgoing)
1.92 espie 221: pgn->built_status = ABORTED;
1.57 espie 222: else {
1.77 espie 223: print_errors();
1.57 espie 224: exit(1);
225: }
1.78 espie 226: break;
227: case ERROR:
1.67 espie 228: /* Already had an error when making this beastie. Tell the
229: * parent to abort. */
1.92 espie 230: pgn->built_status = ABORTED;
1.78 espie 231: break;
1.87 espie 232: case BUILDING:
1.78 espie 233: Error("Graph cycles through %s", gn->name);
234: gn->built_status = ERROR;
1.92 espie 235: pgn->built_status = ABORTED;
1.78 espie 236: break;
1.87 espie 237: case REBUILT:
1.93 espie 238: pgn->child_rebuilt = true;
239: Make_TimeStamp(pgn, gn);
1.78 espie 240: break;
241: case UPTODATE:
1.93 espie 242: Make_TimeStamp(pgn, gn);
1.78 espie 243: break;
244: default:
245: break;
1.1 deraadt 246: }
247: }
1.36 espie 248:
1.91 espie 249: void
250: Compat_Init()
251: {
252: }
253:
254: void
255: Compat_Update(GNode *gn)
256: {
257: }
258:
259: void
260: Compat_Run(Lst targs, bool *has_errors, bool *out_of_date)
1.1 deraadt 261: {
1.60 espie 262: GNode *gn = NULL; /* Current root target */
1.57 espie 263:
264: /* For each entry in the list of targets to create, call CompatMake on
1.73 espie 265: * it to create the thing. CompatMake will leave the 'built_status'
1.67 espie 266: * field of gn in one of several states:
1.57 espie 267: * UPTODATE gn was already up-to-date
1.87 espie 268: * REBUILT gn was recreated successfully
1.60 espie 269: * ERROR An error occurred while gn was being
270: * created
1.88 espie 271: * ABORTED gn was not built because one of its
272: * dependencies could not be built due
273: * to errors. */
1.86 espie 274: while ((gn = Lst_DeQueue(targs)) != NULL) {
1.70 espie 275: CompatMake(gn, NULL);
1.57 espie 276:
1.67 espie 277: if (gn->built_status == UPTODATE)
1.57 espie 278: printf("`%s' is up to date.\n", gn->name);
1.67 espie 279: else if (gn->built_status == ABORTED) {
1.59 espie 280: printf("`%s' not remade because of errors.\n",
1.57 espie 281: gn->name);
1.91 espie 282: *out_of_date = true;
283: *has_errors = true;
1.89 espie 284: } else {
1.91 espie 285: *out_of_date = true;
1.57 espie 286: }
287: }
288:
1.1 deraadt 289: }