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