xref: /openbsd-src/usr.bin/make/engine.c (revision 7e440d195958617aa4d56ce3f25adf45e0335334)
1*7e440d19Scheloha /*	$OpenBSD: engine.c,v 1.74 2024/04/09 15:08:21 cheloha Exp $ */
2a6b963c8Sespie /*
3a6b963c8Sespie  * Copyright (c) 2012 Marc Espie.
4a6b963c8Sespie  *
5a6b963c8Sespie  * Extensive code modifications for the OpenBSD project.
6a6b963c8Sespie  *
7a6b963c8Sespie  * Redistribution and use in source and binary forms, with or without
8a6b963c8Sespie  * modification, are permitted provided that the following conditions
9a6b963c8Sespie  * are met:
10a6b963c8Sespie  * 1. Redistributions of source code must retain the above copyright
11a6b963c8Sespie  *    notice, this list of conditions and the following disclaimer.
12a6b963c8Sespie  * 2. Redistributions in binary form must reproduce the above copyright
13a6b963c8Sespie  *    notice, this list of conditions and the following disclaimer in the
14a6b963c8Sespie  *    documentation and/or other materials provided with the distribution.
15a6b963c8Sespie  *
16a6b963c8Sespie  * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
17a6b963c8Sespie  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a6b963c8Sespie  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a6b963c8Sespie  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
20a6b963c8Sespie  * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a6b963c8Sespie  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a6b963c8Sespie  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a6b963c8Sespie  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a6b963c8Sespie  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a6b963c8Sespie  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a6b963c8Sespie  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a6b963c8Sespie  */
28a6f1883eSespie /*
29a6f1883eSespie  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
30a6f1883eSespie  * Copyright (c) 1988, 1989 by Adam de Boor
31a6f1883eSespie  * Copyright (c) 1989 by Berkeley Softworks
32a6f1883eSespie  * All rights reserved.
33a6f1883eSespie  *
34a6f1883eSespie  * This code is derived from software contributed to Berkeley by
35a6f1883eSespie  * Adam de Boor.
36a6f1883eSespie  *
37a6f1883eSespie  * Redistribution and use in source and binary forms, with or without
38a6f1883eSespie  * modification, are permitted provided that the following conditions
39a6f1883eSespie  * are met:
40a6f1883eSespie  * 1. Redistributions of source code must retain the above copyright
41a6f1883eSespie  *    notice, this list of conditions and the following disclaimer.
42a6f1883eSespie  * 2. Redistributions in binary form must reproduce the above copyright
43a6f1883eSespie  *    notice, this list of conditions and the following disclaimer in the
44a6f1883eSespie  *    documentation and/or other materials provided with the distribution.
45a6f1883eSespie  * 3. Neither the name of the University nor the names of its contributors
46a6f1883eSespie  *    may be used to endorse or promote products derived from this software
47a6f1883eSespie  *    without specific prior written permission.
48a6f1883eSespie  *
49a6f1883eSespie  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50a6f1883eSespie  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51a6f1883eSespie  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52a6f1883eSespie  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53a6f1883eSespie  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54a6f1883eSespie  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55a6f1883eSespie  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56a6f1883eSespie  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57a6f1883eSespie  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58a6f1883eSespie  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59a6f1883eSespie  * SUCH DAMAGE.
60a6f1883eSespie  */
61a6f1883eSespie 
6232e144d7Sespie #include <sys/types.h>
63a6b963c8Sespie #include <sys/time.h>
6432e144d7Sespie #include <sys/wait.h>
656c2dbbdaSespie #include <assert.h>
6632e144d7Sespie #include <ctype.h>
67a6f1883eSespie #include <errno.h>
68a6f1883eSespie #include <fcntl.h>
691f89b472Sespie #include <limits.h>
7032e144d7Sespie #include <signal.h>
711f89b472Sespie #include <stdint.h>
721f89b472Sespie #include <stdio.h>
731f89b472Sespie #include <stdlib.h>
741f89b472Sespie #include <string.h>
751f89b472Sespie #include <unistd.h>
76a6f1883eSespie #include "defines.h"
77e2e5a33cSespie #include "cmd_exec.h"
78a6f1883eSespie #include "dir.h"
79a6f1883eSespie #include "engine.h"
80a6f1883eSespie #include "arch.h"
81a6f1883eSespie #include "gnode.h"
82a6f1883eSespie #include "targ.h"
83a6f1883eSespie #include "var.h"
84a6f1883eSespie #include "extern.h"
85a6f1883eSespie #include "lst.h"
86a6f1883eSespie #include "timestamp.h"
87438dc521Sespie #include "main.h"
88a6f1883eSespie #include "make.h"
8932e144d7Sespie #include "pathnames.h"
9032e144d7Sespie #include "error.h"
9132e144d7Sespie #include "memory.h"
923d97cd1aSespie #include "buf.h"
931ef353c6Sespie #include "job.h"
94a6b963c8Sespie #include "lowparse.h"
95a6f1883eSespie 
96a6f1883eSespie static void MakeTimeStamp(void *, void *);
97fd5a6224Sespie static int rewrite_time(const char *);
981bae8e1fSespie static void list_parents(GNode *, FILE *);
9932e144d7Sespie 
100b12bcd0dSespie /* XXX due to a bug in make's logic, targets looking like *.a or -l*
101b12bcd0dSespie  * have been silently dropped when make couldn't figure them out.
102b12bcd0dSespie  * Now, we warn about them until all Makefile bugs have been fixed.
103b12bcd0dSespie  */
104b12bcd0dSespie static bool
drop_silently(const char * s)105b12bcd0dSespie drop_silently(const char *s)
106b12bcd0dSespie {
107b12bcd0dSespie 	size_t len;
108b12bcd0dSespie 
109b12bcd0dSespie 	if (s[0] == '-' && s[1] == 'l')
110b12bcd0dSespie 		return true;
111b12bcd0dSespie 
112b12bcd0dSespie 	len = strlen(s);
113b12bcd0dSespie 	if (len >=2 && s[len-2] == '.' && s[len-1] == 'a')
114b12bcd0dSespie 		return true;
115b12bcd0dSespie 	return false;
116b12bcd0dSespie }
117b12bcd0dSespie 
118a6f1883eSespie bool
node_find_valid_commands(GNode * gn)119a6b963c8Sespie node_find_valid_commands(GNode *gn)
120a6f1883eSespie {
121694f1218Sespie 	if (DEBUG(DOUBLE) && (gn->type & OP_DOUBLE))
122694f1218Sespie 		fprintf(stderr, "Warning: target %s had >1 lists of "
123694f1218Sespie 		    "shell commands (ignoring later ones)\n", gn->name);
1241bae8e1fSespie 	if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands)) {
125b12bcd0dSespie 		if (drop_silently(gn->name)) {
1261bae8e1fSespie 			printf("Warning: target %s", gn->name);
1271bae8e1fSespie 			list_parents(gn, stdout);
128b12bcd0dSespie 			printf(" does not have any command (BUG)\n");
1291bae8e1fSespie 			return true;
1301bae8e1fSespie 		}
131a6f1883eSespie 		/*
132a6f1883eSespie 		 * No commands. Look for .DEFAULT rule from which we might infer
133a6f1883eSespie 		 * commands
134a6f1883eSespie 		 */
135323bf4e3Sespie 		if ((gn->type & OP_NODEFAULT) == 0 &&
136323bf4e3Sespie 		    (DEFAULT->type & OP_DUMMY) == 0 &&
137866fd206Sespie 		    !Lst_IsEmpty(&DEFAULT->commands)) {
138a6f1883eSespie 			/*
139df7262edSespie 			 * Make only looks for a .DEFAULT if the node was never
140df7262edSespie 			 * the target of an operator, so that's what we do too.
141df7262edSespie 			 * If a .DEFAULT was given, we substitute its commands
142df7262edSespie 			 * for gn's commands and set the IMPSRC variable to be
143df7262edSespie 			 * the target's name The DEFAULT node acts like a
144df7262edSespie 			 * transformation rule, in that gn also inherits any
145df7262edSespie 			 * attributes or sources attached to .DEFAULT itself.
146a6f1883eSespie 			 */
147a6f1883eSespie 			Make_HandleUse(DEFAULT, gn);
1483d97cd1aSespie 			Var(IMPSRC_INDEX, gn) = Var(TARGET_INDEX, gn);
149a6f1883eSespie 		} else if (is_out_of_date(Dir_MTime(gn))) {
150a6f1883eSespie 			/*
151df7262edSespie 			 * The node wasn't the target of an operator we have no
152df7262edSespie 			 * .DEFAULT rule to go on and the target doesn't
153df7262edSespie 			 * already exist. There's nothing more we can do for
1546c2dbbdaSespie 			 * this branch.
1556c2dbbdaSespie 			 */
1566c2dbbdaSespie 			 return false;
1576c2dbbdaSespie 	    	}
1586c2dbbdaSespie 	}
1596c2dbbdaSespie 	return true;
1606c2dbbdaSespie }
1616c2dbbdaSespie 
1621bae8e1fSespie static void
list_parents(GNode * gn,FILE * out)1631bae8e1fSespie list_parents(GNode *gn, FILE *out)
1641bae8e1fSespie {
1651bae8e1fSespie 	LstNode ln;
1661bae8e1fSespie 	bool first = true;
1671bae8e1fSespie 
1681bae8e1fSespie 	for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln)) {
1691bae8e1fSespie 		GNode *p = Lst_Datum(ln);
1701bae8e1fSespie 		if (!p->must_make)
1711bae8e1fSespie 			continue;
1721bae8e1fSespie 		if (first) {
1731bae8e1fSespie 			fprintf(out, " (prerequisite of:");
1741bae8e1fSespie 			first = false;
1751bae8e1fSespie 		}
1761bae8e1fSespie 		fprintf(out, " %s", p->name);
1771bae8e1fSespie 	}
1781bae8e1fSespie 	if (!first)
1791bae8e1fSespie 		fprintf(out, ")");
1801bae8e1fSespie }
1811bae8e1fSespie 
1826c2dbbdaSespie void
node_failure(GNode * gn)183a6b963c8Sespie node_failure(GNode *gn)
1846c2dbbdaSespie {
1856c2dbbdaSespie 	/*
1866c2dbbdaSespie 	 If the -k flag wasn't given, we stop in
187df7262edSespie 	 * our tracks, otherwise we just don't update this
188df7262edSespie 	 * node's parents so they never get examined.
189a6f1883eSespie 	 */
1901bae8e1fSespie 	const char *diag;
1911bae8e1fSespie 	FILE *out;
192a6f1883eSespie 
193a6f1883eSespie 	if (gn->type & OP_OPTIONAL) {
1941bae8e1fSespie 		out = stdout;
1951bae8e1fSespie 		diag = "(ignored)";
196a6f1883eSespie 	} else if (keepgoing) {
1971bae8e1fSespie 		out = stdout;
1981bae8e1fSespie 		diag = "(continuing)";
199a6f1883eSespie 	} else {
2001bae8e1fSespie 		out = stderr;
2011bae8e1fSespie 		diag = "";
2021bae8e1fSespie 	}
2031bae8e1fSespie 	fprintf(out, "make: don't know how to make %s", gn->name);
2041bae8e1fSespie 	list_parents(gn, out);
2051bae8e1fSespie 	fprintf(out, "%s\n", diag);
2061bae8e1fSespie 	if (out == stdout)
2071bae8e1fSespie 		fflush(stdout);
2081bae8e1fSespie 	else {
209a6b963c8Sespie 		print_errors();
210438dc521Sespie 		dump_unreadable();
211a6b963c8Sespie 		Punt(NULL);
212a6f1883eSespie 	}
213a6f1883eSespie }
214a6b963c8Sespie 
215fd5a6224Sespie /* touch files the hard way, by writing stuff to them */
216fd5a6224Sespie static int
rewrite_time(const char * name)217fd5a6224Sespie rewrite_time(const char *name)
218fd5a6224Sespie {
219fd5a6224Sespie 	int fd;
220fd5a6224Sespie 	char c;
221fd5a6224Sespie 
222fd5a6224Sespie 	fd = open(name, O_RDWR | O_CREAT, 0666);
223fd5a6224Sespie 	if (fd < 0)
224fd5a6224Sespie 		return -1;
225fd5a6224Sespie 	/*
226fd5a6224Sespie 	 * Read and write a byte to the file to change
227fd5a6224Sespie 	 * the modification time.
228fd5a6224Sespie 	 */
229fd5a6224Sespie 	if (read(fd, &c, 1) == 1) {
230fd5a6224Sespie 		(void)lseek(fd, 0, SEEK_SET);
231fd5a6224Sespie 		(void)write(fd, &c, 1);
232fd5a6224Sespie 	}
233fd5a6224Sespie 
234fd5a6224Sespie 	(void)close(fd);
235fd5a6224Sespie 	return 0;
236fd5a6224Sespie }
237fd5a6224Sespie 
238a6f1883eSespie void
Job_Touch(GNode * gn)239cae88e06Sespie Job_Touch(GNode *gn)
240a6f1883eSespie {
241a6b963c8Sespie 	handle_all_signals();
24218cc0328Sespie 	if (gn->type & (OP_USE|OP_OPTIONAL|OP_PHONY)) {
243a6f1883eSespie 		/*
244866fd206Sespie 		 * .JOIN, .USE, and .OPTIONAL targets are "virtual" targets
245866fd206Sespie 		 * and, as such, shouldn't really be created.
24678086188Sespie 		 * Likewise, .PHONY targets are not really files
247a6f1883eSespie 		 */
248a6f1883eSespie 		return;
249a6f1883eSespie 	}
250a6f1883eSespie 
2514b65af26Sespie 	if (!Targ_Silent(gn)) {
252a6f1883eSespie 		(void)fprintf(stdout, "touch %s\n", gn->name);
253a6f1883eSespie 		(void)fflush(stdout);
254a6f1883eSespie 	}
255a6f1883eSespie 
256a6f1883eSespie 	if (noExecute) {
257a6f1883eSespie 		return;
258a6f1883eSespie 	}
259a6f1883eSespie 
260a6f1883eSespie 	if (gn->type & OP_ARCHV) {
261a6f1883eSespie 		Arch_Touch(gn);
262a6f1883eSespie 	} else {
263a6f1883eSespie 		const char *file = gn->path != NULL ? gn->path : gn->name;
264a6f1883eSespie 
265*7e440d19Scheloha 		if (utimes(file, NULL) == -1){
266fd5a6224Sespie 			if (rewrite_time(file) == -1) {
26719e54df6Sgsoares 				(void)fprintf(stderr,
268df7262edSespie 				    "*** couldn't touch %s: %s", file,
269df7262edSespie 				    strerror(errno));
270a6f1883eSespie 		    	}
271a6f1883eSespie 		}
272a6f1883eSespie 	}
273a6f1883eSespie }
274a6f1883eSespie 
275a6f1883eSespie void
Make_TimeStamp(GNode * parent,GNode * child)276687d3c4eSespie Make_TimeStamp(GNode *parent, GNode *child)
277a6f1883eSespie {
27823a9ff7bSespie 	if (is_strictly_before(parent->youngest->mtime, child->mtime)) {
2791ea29b92Sespie  		parent->youngest = child;
2801ea29b92Sespie 	}
281a6f1883eSespie }
282a6f1883eSespie 
283a6f1883eSespie void
Make_HandleUse(GNode * cgn,GNode * pgn)284866fd206Sespie Make_HandleUse(GNode	*cgn,	/* The .USE node */
285a6f1883eSespie     GNode	*pgn)	/* The target of the .USE node */
286a6f1883eSespie {
287a6f1883eSespie 	GNode	*gn;	/* A child of the .USE node */
288a6f1883eSespie 	LstNode	ln;	/* An element in the children list */
289a6f1883eSespie 
2906c2dbbdaSespie 	assert(cgn->type & (OP_USE|OP_TRANSFORM));
2916c2dbbdaSespie 
29268097c0dSespie 	if (pgn == NULL)
29368097c0dSespie 		Fatal("Trying to apply .USE to '%s' without a parent",
29468097c0dSespie 		    cgn->name);
29568097c0dSespie 
296a6f1883eSespie 	if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) {
297866fd206Sespie 		/* .USE or transformation and target has no commands
298866fd206Sespie 		 * -- append the child's commands to the parent.  */
299a6f1883eSespie 		Lst_Concat(&pgn->commands, &cgn->commands);
300a6f1883eSespie 	}
301a6f1883eSespie 
302df7262edSespie 	for (ln = Lst_First(&cgn->children); ln != NULL;
303df7262edSespie 	    ln = Lst_Adv(ln)) {
304568f6c05Sespie 		gn = Lst_Datum(ln);
305a6f1883eSespie 
306a6f1883eSespie 		if (Lst_AddNew(&pgn->children, gn)) {
307a6f1883eSespie 			Lst_AtEnd(&gn->parents, pgn);
308194f6eccSespie 			pgn->children_left++;
309a6f1883eSespie 		}
310a6f1883eSespie 	}
311a6f1883eSespie 
312694f1218Sespie 	if (DEBUG(DOUBLE) && (cgn->type & OP_DOUBLE))
313694f1218Sespie 		fprintf(stderr,
314694f1218Sespie 		    "Warning: .USE %s expanded in %s had >1 lists of "
315694f1218Sespie 		    "shell commands (ignoring later ones)\n",
316694f1218Sespie 		    cgn->name, pgn->name);
317694f1218Sespie 	pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM|OP_DOUBLE);
318a6f1883eSespie 
319a6f1883eSespie 	/*
320194f6eccSespie 	 * This child node is now built, so we decrement the count of
321194f6eccSespie 	 * not yet built children in the parent... We also remove the child
322df7262edSespie 	 * from the parent's list to accurately reflect the number of
323194f6eccSespie 	 * remaining children the parent has. This is used by Make_Run to
324866fd206Sespie 	 * decide whether to queue the parent or examine its children...
325a6f1883eSespie 	 */
326866fd206Sespie 	if (cgn->type & OP_USE)
327194f6eccSespie 		pgn->children_left--;
328a6f1883eSespie }
329a6f1883eSespie 
3303d97cd1aSespie void
Make_DoAllVar(GNode * gn)3313d97cd1aSespie Make_DoAllVar(GNode *gn)
332a6f1883eSespie {
3333d97cd1aSespie 	GNode *child;
3343d97cd1aSespie 	LstNode ln;
3353d97cd1aSespie 	BUFFER allsrc, oodate;
3363d97cd1aSespie 	char *target;
3373d97cd1aSespie 	bool do_oodate;
3383d97cd1aSespie 	int oodate_count, allsrc_count = 0;
339a6f1883eSespie 
3403d97cd1aSespie 	oodate_count = 0;
3413d97cd1aSespie 	allsrc_count = 0;
3423d97cd1aSespie 
343466b8ac5Sespie 	Var(OODATE_INDEX, gn) = "";
344466b8ac5Sespie 	Var(ALLSRC_INDEX, gn) = "";
345466b8ac5Sespie 
3463d97cd1aSespie 	for (ln = Lst_First(&gn->children); ln != NULL; ln = Lst_Adv(ln)) {
347568f6c05Sespie 		child = Lst_Datum(ln);
34818cc0328Sespie 		if ((child->type & (OP_USE|OP_INVISIBLE)) != 0)
3493d97cd1aSespie 			continue;
350866fd206Sespie 		if (OP_NOP(child->type) ||
3513d97cd1aSespie 		    (target = Var(TARGET_INDEX, child)) == NULL) {
352a6f1883eSespie 			/*
353df7262edSespie 			 * this node is only source; use the specific pathname
354df7262edSespie 			 * for it
355a6f1883eSespie 			 */
356866fd206Sespie 			target = child->path != NULL ? child->path :
357866fd206Sespie 			    child->name;
358a6f1883eSespie 		}
359a6f1883eSespie 
360a6f1883eSespie 		/*
3613d97cd1aSespie 		 * It goes in the OODATE variable if the parent is younger than
3623d97cd1aSespie 		 * the child or if the child has been modified more recently
3633d97cd1aSespie 		 * than the start of the make.  This is to keep make from
3643d97cd1aSespie 		 * getting confused if something else updates the parent after
3653d97cd1aSespie 		 * the make starts (shouldn't happen, I know, but sometimes it
3663d97cd1aSespie 		 * does). In such a case, if we've updated the kid, the parent
3673d97cd1aSespie 		 * is likely to have a modification time later than that of the
3683d97cd1aSespie 		 * kid and anything that relies on the OODATE variable will be
3693d97cd1aSespie 		 * hosed.
370a6f1883eSespie 		 */
3713d97cd1aSespie 		do_oodate = false;
37218cc0328Sespie 		if (is_strictly_before(gn->mtime, child->mtime) ||
3734c9de429Sespie 		   (!is_strictly_before(child->mtime, starttime) &&
374ed90eef3Sespie 		   child->built_status == REBUILT))
3753d97cd1aSespie 		   	do_oodate = true;
3763d97cd1aSespie 		if (do_oodate) {
3773d97cd1aSespie 			oodate_count++;
3783d97cd1aSespie 			if (oodate_count == 1)
3793d97cd1aSespie 				Var(OODATE_INDEX, gn) = target;
3803d97cd1aSespie 			else {
3813d97cd1aSespie 				if (oodate_count == 2) {
3823d97cd1aSespie 					Buf_Init(&oodate, 0);
3833d97cd1aSespie 					Buf_AddString(&oodate,
3843d97cd1aSespie 					    Var(OODATE_INDEX, gn));
385a6f1883eSespie 				}
3863d97cd1aSespie 				Buf_AddSpace(&oodate);
3873d97cd1aSespie 				Buf_AddString(&oodate, target);
3883d97cd1aSespie 			}
3893d97cd1aSespie 		}
3903d97cd1aSespie 		allsrc_count++;
3913d97cd1aSespie 		if (allsrc_count == 1)
3923d97cd1aSespie 			Var(ALLSRC_INDEX, gn) = target;
3933d97cd1aSespie 		else {
3943d97cd1aSespie 			if (allsrc_count == 2) {
3953d97cd1aSespie 				Buf_Init(&allsrc, 0);
3963d97cd1aSespie 				Buf_AddString(&allsrc,
3973d97cd1aSespie 				    Var(ALLSRC_INDEX, gn));
3983d97cd1aSespie 			}
3993d97cd1aSespie 			Buf_AddSpace(&allsrc);
4003d97cd1aSespie 			Buf_AddString(&allsrc, target);
401a6f1883eSespie 		}
402a6f1883eSespie 	}
403a6f1883eSespie 
4043d97cd1aSespie 	if (allsrc_count > 1)
4053d97cd1aSespie 		Var(ALLSRC_INDEX, gn) = Buf_Retrieve(&allsrc);
4063d97cd1aSespie 	if (oodate_count > 1)
4073d97cd1aSespie 		Var(OODATE_INDEX, gn) = Buf_Retrieve(&oodate);
408a6f1883eSespie 
4094d303f06Sespie 	if (gn->impliedsrc)
4103d97cd1aSespie 		Var(IMPSRC_INDEX, gn) = Var(TARGET_INDEX, gn->impliedsrc);
411a6f1883eSespie }
412a6f1883eSespie 
413a6f1883eSespie /* Wrapper to call Make_TimeStamp from a forEach loop.	*/
414a6f1883eSespie static void
MakeTimeStamp(void * parent,void * child)415866fd206Sespie MakeTimeStamp(void *parent, void *child)
416a6f1883eSespie {
4177f5855dcSespie     Make_TimeStamp(parent, child);
418a6f1883eSespie }
419a6f1883eSespie 
420a6f1883eSespie bool
Make_OODate(GNode * gn)421866fd206Sespie Make_OODate(GNode *gn)
422a6f1883eSespie {
423a6f1883eSespie 	bool	    oodate;
424a6f1883eSespie 
425a6f1883eSespie 	/*
426a6f1883eSespie 	 * Certain types of targets needn't even be sought as their datedness
427a6f1883eSespie 	 * doesn't depend on their modification time...
428a6f1883eSespie 	 */
42918cc0328Sespie 	if ((gn->type & (OP_USE|OP_PHONY)) == 0) {
430a6f1883eSespie 		(void)Dir_MTime(gn);
431a6f1883eSespie 		if (DEBUG(MAKE)) {
432866fd206Sespie 			if (!is_out_of_date(gn->mtime))
433df7262edSespie 				printf("modified %s...",
4344c9de429Sespie 				    time_to_string(&gn->mtime));
435866fd206Sespie 			else
436a6f1883eSespie 				printf("non-existent...");
437a6f1883eSespie 		}
438a6f1883eSespie 	}
439a6f1883eSespie 
440a6f1883eSespie 	/*
441194f6eccSespie 	 * A target is rebuilt in one of the following circumstances:
442866fd206Sespie 	 * - its modification time is smaller than that of its youngest child
443a6f1883eSespie 	 *   and it would actually be run (has commands or type OP_NOP)
444866fd206Sespie 	 * - it's the object of a force operator
445866fd206Sespie 	 * - it has no children, was on the lhs of an operator and doesn't
446df7262edSespie 	 *   exist already.
447a6f1883eSespie 	 *
448a6f1883eSespie 	 */
449a6f1883eSespie 	if (gn->type & OP_USE) {
450a6f1883eSespie 		/*
451a6f1883eSespie 		 * If the node is a USE node it is *never* out of date
452a6f1883eSespie 		 * no matter *what*.
453a6f1883eSespie 		 */
454866fd206Sespie 		if (DEBUG(MAKE))
455a6f1883eSespie 			printf(".USE node...");
456a6f1883eSespie 		oodate = false;
45718cc0328Sespie 	} else if (gn->type & (OP_FORCE|OP_PHONY)) {
458a6f1883eSespie 		/*
459866fd206Sespie 		 * A node which is the object of the force (!) operator or which
460866fd206Sespie 		 * has the .EXEC attribute is always considered out-of-date.
461a6f1883eSespie 		 */
462a6f1883eSespie 		if (DEBUG(MAKE)) {
463866fd206Sespie 			if (gn->type & OP_FORCE)
464a6f1883eSespie 				printf("! operator...");
465866fd206Sespie 			else if (gn->type & OP_PHONY)
466a6f1883eSespie 				printf(".PHONY node...");
467866fd206Sespie 			else
468a6f1883eSespie 				printf(".EXEC node...");
469a6f1883eSespie 		}
470a6f1883eSespie 		oodate = true;
47123a9ff7bSespie 	} else if (is_strictly_before(gn->mtime, gn->youngest->mtime) ||
47223a9ff7bSespie 	   (gn == gn->youngest &&
473df7262edSespie 	    (is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP)))) {
474a6f1883eSespie 		/*
475a6f1883eSespie 		 * A node whose modification time is less than that of its
47623a9ff7bSespie 		 * youngest child or that has no children (gn->youngest == gn)
47723a9ff7bSespie 		 * and either doesn't exist (mtime == OUT_OF_DATE)
478866fd206Sespie 		 * or was the object of a :: operator is out-of-date.
479a6f1883eSespie 		 */
480a6f1883eSespie 		if (DEBUG(MAKE)) {
48123a9ff7bSespie 			if (is_strictly_before(gn->mtime, gn->youngest->mtime))
4821ea29b92Sespie 				printf("modified before source(%s)...",
4831ea29b92Sespie 				    gn->youngest->name);
484866fd206Sespie 			else if (is_out_of_date(gn->mtime))
485a6f1883eSespie 				printf("non-existent and no sources...");
486866fd206Sespie 			else
487a6f1883eSespie 				printf(":: operator and no sources...");
488a6f1883eSespie 		}
489a6f1883eSespie 		oodate = true;
490a6f1883eSespie 	} else {
491a6f1883eSespie 		oodate = false;
492a6f1883eSespie 	}
493a6f1883eSespie 
494a6f1883eSespie 	/*
495a6f1883eSespie 	 * If the target isn't out-of-date, the parents need to know its
496a6f1883eSespie 	 * modification time. Note that targets that appear to be out-of-date
497a6f1883eSespie 	 * but aren't, because they have no commands and aren't of type OP_NOP,
498df7262edSespie 	 * have their mtime stay below their children's mtime to keep parents
499df7262edSespie 	 * from thinking they're out-of-date.
500a6f1883eSespie 	 */
501a6f1883eSespie 	if (!oodate)
502a6f1883eSespie 		Lst_ForEach(&gn->parents, MakeTimeStamp, gn);
503a6f1883eSespie 
504a6f1883eSespie 	return oodate;
505a6f1883eSespie }
506a6f1883eSespie 
50732e144d7Sespie 
508a6b963c8Sespie void
job_attach_node(Job * job,GNode * node)509a6b963c8Sespie job_attach_node(Job *job, GNode *node)
510a6b963c8Sespie {
511a6b963c8Sespie 	job->node = node;
5121bae8e1fSespie 	job->node->built_status = BUILDING;
513a6b963c8Sespie 	job->next_cmd = Lst_First(&node->commands);
514a6b963c8Sespie 	job->exit_type = JOB_EXIT_OKAY;
515a6b963c8Sespie 	job->location = NULL;
516a6b963c8Sespie 	job->flags = 0;
517a6b963c8Sespie }
518a6b963c8Sespie 
519a6b963c8Sespie void
handle_job_status(Job * job,int status)5203bb9adb9Sespie handle_job_status(Job *job, int status)
521a6b963c8Sespie {
522b12bcd0dSespie 	bool silent;
523be710f6fSespie 	int dying;
524b12bcd0dSespie 
525b12bcd0dSespie 	/* if there's one job running and we don't keep going, no need
526b12bcd0dSespie 	 * to report right now.
527b12bcd0dSespie 	 */
528b12bcd0dSespie 	if ((job->flags & JOB_ERRCHECK) && !keepgoing && runningJobs == NULL)
529b12bcd0dSespie 		silent = !DEBUG(JOB);
530b12bcd0dSespie 	else
531b12bcd0dSespie 		silent = false;
532b12bcd0dSespie 
533a6b963c8Sespie 	debug_job_printf("Process %ld (%s) exited with status %d.\n",
534a6b963c8Sespie 	    (long)job->pid, job->node->name, status);
535a6b963c8Sespie 
536a6b963c8Sespie 	/* classify status */
537a6b963c8Sespie 	if (WIFEXITED(status)) {
538a6b963c8Sespie 		job->code = WEXITSTATUS(status);/* exited */
539be710f6fSespie 		if (job->code != 0) {
540be710f6fSespie 			/* if we're already dying from that signal, be silent */
541be710f6fSespie 			if (!silent && job->code > 128
542be710f6fSespie 			    && job->code <= 128 + _NSIG) {
543be710f6fSespie 				dying = check_dying_signal();
544be710f6fSespie 				silent = dying && job->code == dying + 128;
545be710f6fSespie 			}
546b12bcd0dSespie 			if (!silent)
547b12bcd0dSespie 				printf("*** Error %d", job->code);
548a6b963c8Sespie 			job->exit_type = JOB_EXIT_BAD;
549a6b963c8Sespie 		} else
550a6b963c8Sespie 			job->exit_type = JOB_EXIT_OKAY;
551a6b963c8Sespie 	} else {
552a6b963c8Sespie 		job->exit_type = JOB_SIGNALED;
553a6b963c8Sespie 		job->code = WTERMSIG(status);	/* signaled */
554be710f6fSespie 		/* if we're already dying from that signal, be silent */
555be710f6fSespie 		if (!silent) {
556be710f6fSespie 			dying = check_dying_signal();
557be710f6fSespie 			silent = dying && job->code == dying;
558be710f6fSespie 		}
559b12bcd0dSespie 		if (!silent)
560a6b963c8Sespie 			printf("*** Signal %d", job->code);
561a6b963c8Sespie 	}
562a6b963c8Sespie 
563a6b963c8Sespie 	/* if there is a problem, what's going on ? */
564a6b963c8Sespie 	if (job->exit_type != JOB_EXIT_OKAY) {
565b12bcd0dSespie 		if (!silent)
566b12bcd0dSespie 			printf(" in target '%s'", job->node->name);
567a6b963c8Sespie 		if (job->flags & JOB_ERRCHECK) {
568a6b963c8Sespie 			job->node->built_status = ERROR;
569a6b963c8Sespie 			if (!keepgoing) {
570b12bcd0dSespie 				if (!silent)
571a6b963c8Sespie 					printf("\n");
5727a7b8f33Sespie 				job->flags |= JOB_KEEPERROR;
573a6b963c8Sespie 				/* XXX don't free the command */
574a6b963c8Sespie 				return;
575a6b963c8Sespie 			}
576a6b963c8Sespie 			printf(", line %lu of %s", job->location->lineno,
577a6b963c8Sespie 			    job->location->fname);
5780b019757Sespie 			/* Parallel make already determined whether
5790b019757Sespie 			 * JOB_IS_EXPENSIVE, perform the computation for
5800b019757Sespie 			 * sequential make to figure out whether to display the
5810b019757Sespie 			 * command or not.  */
5827dcceccaSespie 			if ((job->flags & JOB_SILENT) && sequential)
583d211a910Sespie 				determine_expensive_job(job);
584a6b963c8Sespie 			if ((job->flags & (JOB_SILENT | JOB_IS_EXPENSIVE))
585a6b963c8Sespie 			    == JOB_SILENT)
586a6b963c8Sespie 				printf(": %s", job->cmd);
587a6b963c8Sespie 			/* Abort the current target,
588a6b963c8Sespie 			 * but let others continue.  */
589a6b963c8Sespie 			printf(" (continuing)\n");
590a6b963c8Sespie 		} else {
591a6b963c8Sespie 			/* Continue executing commands for
592a6b963c8Sespie 			 * this target.  If we return 0,
593a6b963c8Sespie 			 * this will happen...  */
594a6b963c8Sespie 			printf(" (ignored)\n");
595a6b963c8Sespie 			job->exit_type = JOB_EXIT_OKAY;
596a6b963c8Sespie 		}
597a6b963c8Sespie 	}
598a6b963c8Sespie 	free(job->cmd);
599a6b963c8Sespie }
600a6b963c8Sespie 
601a6b963c8Sespie int
run_gnode(GNode * gn)602a6b963c8Sespie run_gnode(GNode *gn)
603a6b963c8Sespie {
604a6b963c8Sespie 	if (!gn || (gn->type & OP_DUMMY))
605a6b963c8Sespie 		return NOSUCHNODE;
606a6b963c8Sespie 
607bee8c711Sespie 	Job_Make(gn);
608bee8c711Sespie 	loop_handle_running_jobs();
609a6b963c8Sespie 	return gn->built_status;
610a6b963c8Sespie }
611a6b963c8Sespie 
612a6b963c8Sespie 
613a6b963c8Sespie static bool
do_run_command(Job * job,const char * pre)6140a342675Sespie do_run_command(Job *job, const char *pre)
61532e144d7Sespie {
61632e144d7Sespie 	bool silent;	/* Don't print command */
61732e144d7Sespie 	bool doExecute;	/* Execute the command */
61832e144d7Sespie 	bool errCheck;	/* Check errors */
619a6b963c8Sespie 	pid_t cpid; 	/* Child pid */
62032e144d7Sespie 
621a6b963c8Sespie 	const char *cmd = job->cmd;
6224b65af26Sespie 	silent = Targ_Silent(job->node);
6234b65af26Sespie 	errCheck = !Targ_Ignore(job->node);
624a6b963c8Sespie 	if (job->node->type & OP_MAKE)
625a6b963c8Sespie 		doExecute = true;
626a6b963c8Sespie 	else
62732e144d7Sespie 		doExecute = !noExecute;
62832e144d7Sespie 
62932e144d7Sespie 	/* How can we execute a null command ? we warn the user that the
63032e144d7Sespie 	 * command expanded to nothing (is this the right thing to do?).  */
631f46d747cSespie 	if (*cmd == '\0') {
6320a342675Sespie 		Parse_Error(PARSE_WARNING,
6330a342675Sespie 		    "'%s' expands to '' while building %s",
6340a342675Sespie 		    pre, job->node->name);
635a6b963c8Sespie 		return false;
636f46d747cSespie 	}
63732e144d7Sespie 
63832e144d7Sespie 	for (;; cmd++) {
63932e144d7Sespie 		if (*cmd == '@')
64032e144d7Sespie 			silent = DEBUG(LOUD) ? false : true;
64132e144d7Sespie 		else if (*cmd == '-')
64232e144d7Sespie 			errCheck = false;
64332e144d7Sespie 		else if (*cmd == '+')
64432e144d7Sespie 			doExecute = true;
64532e144d7Sespie 		else
64632e144d7Sespie 			break;
64732e144d7Sespie 	}
64856afcde6Sespie 	while (ISSPACE(*cmd))
64932e144d7Sespie 		cmd++;
650a6b963c8Sespie 	/* Print the command before fork if make -n or !silent*/
651a6b963c8Sespie 	if ( noExecute || !silent)
65232e144d7Sespie 		printf("%s\n", cmd);
653a6b963c8Sespie 
654a6b963c8Sespie 	if (silent)
655a6b963c8Sespie 		job->flags |= JOB_SILENT;
656a6b963c8Sespie 	else
657a6b963c8Sespie 		job->flags &= ~JOB_SILENT;
658a6b963c8Sespie 
65932e144d7Sespie 	/* If we're not supposed to execute any commands, this is as far as
66032e144d7Sespie 	 * we go...  */
66132e144d7Sespie 	if (!doExecute)
662a6b963c8Sespie 		return false;
663a6b963c8Sespie 	/* always flush for other stuff */
664a6b963c8Sespie 	fflush(stdout);
66532e144d7Sespie 
6668a1af4f8Sespie 	/* Optimization: bypass comments entirely */
6678a1af4f8Sespie 	if (*cmd == '#')
6688a1af4f8Sespie 		return false;
6698a1af4f8Sespie 
67032e144d7Sespie 	/* Fork and execute the single command. If the fork fails, we abort.  */
67132e144d7Sespie 	switch (cpid = fork()) {
67232e144d7Sespie 	case -1:
673a6b963c8Sespie 		Punt("Could not fork");
67432e144d7Sespie 		/*NOTREACHED*/
67532e144d7Sespie 	case 0:
676868b296aSespie 		reset_signal_mask();
6771bae8e1fSespie 		/* put a random delay unless we're the only job running
6781bae8e1fSespie 		 * and there's nothing left to do.
6791bae8e1fSespie 		 */
6801bae8e1fSespie 		if (random_delay)
68180ccc038Sespie 			if (!(runningJobs == NULL && nothing_left_to_build()))
6828a774f81Snaddy 				usleep(arc4random_uniform(random_delay));
68332e144d7Sespie 		run_command(cmd, errCheck);
68432e144d7Sespie 		/*NOTREACHED*/
68532e144d7Sespie 	default:
686a6b963c8Sespie 		job->pid = cpid;
687a6b963c8Sespie 		job->next = runningJobs;
688a6b963c8Sespie 		runningJobs = job;
689a6b963c8Sespie 		if (errCheck)
690a6b963c8Sespie 			job->flags |= JOB_ERRCHECK;
6911ef353c6Sespie 		else
692a6b963c8Sespie 			job->flags &= ~JOB_ERRCHECK;
693a6b963c8Sespie 		debug_job_printf("Running %ld (%s) %s\n", (long)job->pid,
694a6b963c8Sespie 		    job->node->name, (noExecute || !silent) ? "" : cmd);
695a6b963c8Sespie 		return true;
69632e144d7Sespie 	}
69732e144d7Sespie }
698a6b963c8Sespie 
699a6b963c8Sespie bool
job_run_next(Job * job)700a6b963c8Sespie job_run_next(Job *job)
701a6b963c8Sespie {
702a6b963c8Sespie 	bool started;
703a6b963c8Sespie 	GNode *gn = job->node;
704a6b963c8Sespie 
705a6b963c8Sespie 	while (job->next_cmd != NULL) {
706a6b963c8Sespie 		struct command *command = Lst_Datum(job->next_cmd);
707a6b963c8Sespie 
708a6b963c8Sespie 		handle_all_signals();
709a6b963c8Sespie 		job->location = &command->location;
710a6b963c8Sespie 		Parse_SetLocation(job->location);
71191797de1Sespie 		job->cmd = Var_Subst(command->string, &gn->localvars, false);
712a6b963c8Sespie 		job->next_cmd = Lst_Adv(job->next_cmd);
713a6b963c8Sespie 		if (fatal_errors)
714a6b963c8Sespie 			Punt(NULL);
7150a342675Sespie 		started = do_run_command(job, command->string);
716a6b963c8Sespie 		if (started)
717a6b963c8Sespie 			return false;
718a6b963c8Sespie 		else
719a6b963c8Sespie 			free(job->cmd);
720a6b963c8Sespie 	}
721a6b963c8Sespie 	job->exit_type = JOB_EXIT_OKAY;
722a6b963c8Sespie 	return true;
723a6b963c8Sespie }
724a6b963c8Sespie 
725