| 1 |  |  | /*	$OpenBSD: make.c,v 1.70 2015/08/21 02:19:49 jsg Exp $	*/ | 
    
    | 2 |  |  | /*	$NetBSD: make.c,v 1.10 1996/11/06 17:59:15 christos Exp $	*/ | 
    
    | 3 |  |  |  | 
    
    | 4 |  |  | /* | 
    
    | 5 |  |  |  * Copyright (c) 1988, 1989, 1990, 1993 | 
    
    | 6 |  |  |  *	The Regents of the University of California.  All rights reserved. | 
    
    | 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. | 
    
    | 21 |  |  |  * 3. Neither the name of the University nor the names of its contributors | 
    
    | 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 |  |  |  | 
    
    | 38 |  |  | /*- | 
    
    | 39 |  |  |  * make.c -- | 
    
    | 40 |  |  |  *	The functions which perform the examination of targets and | 
    
    | 41 |  |  |  *	their suitability for creation | 
    
    | 42 |  |  |  * | 
    
    | 43 |  |  |  * Interface: | 
    
    | 44 |  |  |  *	Make_Run		Initialize things for the module and recreate | 
    
    | 45 |  |  |  *				whatever needs recreating. Returns true if | 
    
    | 46 |  |  |  *				work was (or would have been) done and | 
    
    | 47 |  |  |  *				false | 
    
    | 48 |  |  |  *				otherwise. | 
    
    | 49 |  |  |  * | 
    
    | 50 |  |  |  *	Make_Update		Update all parents of a given child. Performs | 
    
    | 51 |  |  |  *				various bookkeeping chores like finding the | 
    
    | 52 |  |  |  *				youngest child of the parent, filling | 
    
    | 53 |  |  |  *				the IMPSRC context variable, etc. It will | 
    
    | 54 |  |  |  *				place the parent on the toBeMade queue if it | 
    
    | 55 |  |  |  *				should be. | 
    
    | 56 |  |  |  * | 
    
    | 57 |  |  |  */ | 
    
    | 58 |  |  |  | 
    
    | 59 |  |  | #include <limits.h> | 
    
    | 60 |  |  | #include <signal.h> | 
    
    | 61 |  |  | #include <stddef.h> | 
    
    | 62 |  |  | #include <stdint.h> | 
    
    | 63 |  |  | #include <stdio.h> | 
    
    | 64 |  |  | #include <stdlib.h> | 
    
    | 65 |  |  | #include <string.h> | 
    
    | 66 |  |  | #include <ohash.h> | 
    
    | 67 |  |  | #include "config.h" | 
    
    | 68 |  |  | #include "defines.h" | 
    
    | 69 |  |  | #include "dir.h" | 
    
    | 70 |  |  | #include "job.h" | 
    
    | 71 |  |  | #include "suff.h" | 
    
    | 72 |  |  | #include "var.h" | 
    
    | 73 |  |  | #include "error.h" | 
    
    | 74 |  |  | #include "make.h" | 
    
    | 75 |  |  | #include "gnode.h" | 
    
    | 76 |  |  | #include "extern.h" | 
    
    | 77 |  |  | #include "timestamp.h" | 
    
    | 78 |  |  | #include "engine.h" | 
    
    | 79 |  |  | #include "lst.h" | 
    
    | 80 |  |  | #include "targ.h" | 
    
    | 81 |  |  | #include "targequiv.h" | 
    
    | 82 |  |  | #include "garray.h" | 
    
    | 83 |  |  | #include "memory.h" | 
    
    | 84 |  |  |  | 
    
    | 85 |  |  | /* what gets added each time. Kept as one static array so that it doesn't | 
    
    | 86 |  |  |  * get resized every time. | 
    
    | 87 |  |  |  */ | 
    
    | 88 |  |  | static struct growableArray examine; | 
    
    | 89 |  |  | /* The current fringe of the graph. These are nodes which await examination by | 
    
    | 90 |  |  |  * MakeOODate. It is added to by Make_Update and subtracted from by | 
    
    | 91 |  |  |  * MakeStartJobs */ | 
    
    | 92 |  |  | static struct growableArray toBeMade; | 
    
    | 93 |  |  |  | 
    
    | 94 |  |  | /* Hold back on nodes where equivalent stuff is already building... */ | 
    
    | 95 |  |  | static struct growableArray heldBack; | 
    
    | 96 |  |  |  | 
    
    | 97 |  |  | static struct ohash targets;	/* stuff we must build */ | 
    
    | 98 |  |  |  | 
    
    | 99 |  |  | static void MakeAddChild(void *, void *); | 
    
    | 100 |  |  | static void MakeHandleUse(void *, void *); | 
    
    | 101 |  |  | static bool MakeStartJobs(void); | 
    
    | 102 |  |  | static void MakePrintStatus(void *, void *); | 
    
    | 103 |  |  | static bool try_to_make_node(GNode *); | 
    
    | 104 |  |  | static void add_targets_to_make(Lst); | 
    
    | 105 |  |  |  | 
    
    | 106 |  |  | static bool has_unmade_predecessor(GNode *); | 
    
    | 107 |  |  | static void requeue_successors(GNode *); | 
    
    | 108 |  |  | static void random_setup(void); | 
    
    | 109 |  |  |  | 
    
    | 110 |  |  | static bool randomize_queue; | 
    
    | 111 |  |  | long random_delay = 0; | 
    
    | 112 |  |  |  | 
    
    | 113 |  |  | bool | 
    
    | 114 |  |  | no_jobs_left() | 
    
    | 115 |  |  | { | 
    
    | 116 |  |  | 	return Array_IsEmpty(&toBeMade); | 
    
    | 117 |  |  | } | 
    
    | 118 |  |  |  | 
    
    | 119 |  |  | static void | 
    
    | 120 |  |  | random_setup() | 
    
    | 121 |  |  | { | 
    
    | 122 |  |  | 	randomize_queue = Var_Definedi("RANDOM_ORDER", NULL); | 
    
    | 123 |  |  |  | 
    
    | 124 |  |  | /* no random delay in the new engine for now */ | 
    
    | 125 |  |  | #if 0 | 
    
    | 126 |  |  | 	if (Var_Definedi("RANDOM_DELAY", NULL)) | 
    
    | 127 |  |  | 		random_delay = strtonum(Var_Value("RANDOM_DELAY"), 0, 1000, | 
    
    | 128 |  |  | 		    NULL) * 1000000; | 
    
    | 129 |  |  | #endif | 
    
    | 130 |  |  |  | 
    
    | 131 |  |  | } | 
    
    | 132 |  |  |  | 
    
    | 133 |  |  | static void | 
    
    | 134 |  |  | randomize_garray(struct growableArray *g) | 
    
    | 135 |  |  | { | 
    
    | 136 |  |  | 	/* This is a fairly standard algorithm to randomize an array. */ | 
    
    | 137 |  |  | 	unsigned int i, v; | 
    
    | 138 |  |  | 	GNode *e; | 
    
    | 139 |  |  |  | 
    
    | 140 |  |  | 	for (i = g->n; i > 0; i--) { | 
    
    | 141 |  |  | 		v = arc4random_uniform(i); | 
    
    | 142 |  |  | 		if (v == i-1) | 
    
    | 143 |  |  | 			continue; | 
    
    | 144 |  |  | 		else { | 
    
    | 145 |  |  | 			e = g->a[i-1]; | 
    
    | 146 |  |  | 			g->a[i-1] = g->a[v]; | 
    
    | 147 |  |  | 			g->a[v] = e; | 
    
    | 148 |  |  | 		} | 
    
    | 149 |  |  | 	} | 
    
    | 150 |  |  | } | 
    
    | 151 |  |  |  | 
    
    | 152 |  |  | static bool | 
    
    | 153 |  |  | has_unmade_predecessor(GNode *gn) | 
    
    | 154 |  |  | { | 
    
    | 155 |  |  | 	LstNode ln; | 
    
    | 156 |  |  |  | 
    
    | 157 |  |  | 	if (Lst_IsEmpty(&gn->preds)) | 
    
    | 158 |  |  | 		return false; | 
    
    | 159 |  |  |  | 
    
    | 160 |  |  |  | 
    
    | 161 |  |  | 	for (ln = Lst_First(&gn->preds); ln != NULL; ln = Lst_Adv(ln)) { | 
    
    | 162 |  |  | 		GNode	*pgn = (GNode *)Lst_Datum(ln); | 
    
    | 163 |  |  |  | 
    
    | 164 |  |  | 		if (pgn->must_make && pgn->built_status == UNKNOWN) { | 
    
    | 165 |  |  | 			if (DEBUG(MAKE)) | 
    
    | 166 |  |  | 				printf("predecessor %s not made yet.\n", | 
    
    | 167 |  |  | 				    pgn->name); | 
    
    | 168 |  |  | 			return true; | 
    
    | 169 |  |  | 		} | 
    
    | 170 |  |  | 	} | 
    
    | 171 |  |  | 	return false; | 
    
    | 172 |  |  | } | 
    
    | 173 |  |  |  | 
    
    | 174 |  |  | static void | 
    
    | 175 |  |  | requeue_successors(GNode *gn) | 
    
    | 176 |  |  | { | 
    
    | 177 |  |  | 	LstNode ln; | 
    
    | 178 |  |  | 	/* Deal with successor nodes. If any is marked for making and has an | 
    
    | 179 |  |  | 	 * unmade count of 0, has not been made and isn't in the examination | 
    
    | 180 |  |  | 	 * queue, it means we need to place it in the queue as it restrained | 
    
    | 181 |  |  | 	 * itself before.	*/ | 
    
    | 182 |  |  | 	for (ln = Lst_First(&gn->successors); ln != NULL; ln = Lst_Adv(ln)) { | 
    
    | 183 |  |  | 		GNode	*succ = (GNode *)Lst_Datum(ln); | 
    
    | 184 |  |  |  | 
    
    | 185 |  |  | 		if (succ->must_make && succ->unmade == 0 | 
    
    | 186 |  |  | 		    && succ->built_status == UNKNOWN) | 
    
    | 187 |  |  | 			Array_PushNew(&toBeMade, succ); | 
    
    | 188 |  |  | 	} | 
    
    | 189 |  |  | } | 
    
    | 190 |  |  |  | 
    
    | 191 |  |  | static void | 
    
    | 192 |  |  | requeue(GNode *gn) | 
    
    | 193 |  |  | { | 
    
    | 194 |  |  | 	/* this is where we go inside the array and move things around */ | 
    
    | 195 |  |  | 	unsigned int i, j; | 
    
    | 196 |  |  |  | 
    
    | 197 |  |  | 	for (i = 0, j = 0; i < heldBack.n; i++, j++) { | 
    
    | 198 |  |  | 		if (heldBack.a[i]->watched == gn) { | 
    
    | 199 |  |  | 			j--; | 
    
    | 200 |  |  | 			heldBack.a[i]->built_status = UNKNOWN; | 
    
    | 201 |  |  | 			if (DEBUG(HELDJOBS)) | 
    
    | 202 |  |  | 				printf("%s finished, releasing: %s\n", | 
    
    | 203 |  |  | 				    gn->name, heldBack.a[i]->name); | 
    
    | 204 |  |  | 			Array_Push(&toBeMade, heldBack.a[i]); | 
    
    | 205 |  |  | 			continue; | 
    
    | 206 |  |  | 		} | 
    
    | 207 |  |  | 		heldBack.a[j] = heldBack.a[i]; | 
    
    | 208 |  |  | 	} | 
    
    | 209 |  |  | 	heldBack.n = j; | 
    
    | 210 |  |  | } | 
    
    | 211 |  |  |  | 
    
    | 212 |  |  | /*- | 
    
    | 213 |  |  |  *----------------------------------------------------------------------- | 
    
    | 214 |  |  |  * Make_Update	-- | 
    
    | 215 |  |  |  *	Perform update on the parents of a node. Used by JobFinish once | 
    
    | 216 |  |  |  *	a node has been dealt with and by MakeStartJobs if it finds an | 
    
    | 217 |  |  |  *	up-to-date node. | 
    
    | 218 |  |  |  * | 
    
    | 219 |  |  |  * Results: | 
    
    | 220 |  |  |  *	Always returns 0 | 
    
    | 221 |  |  |  * | 
    
    | 222 |  |  |  * Side Effects: | 
    
    | 223 |  |  |  *	The unmade field of pgn is decremented and pgn may be placed on | 
    
    | 224 |  |  |  *	the toBeMade queue if this field becomes 0. | 
    
    | 225 |  |  |  * | 
    
    | 226 |  |  |  *	If the child was made, the parent's childMade field will be set to | 
    
    | 227 |  |  |  *	true | 
    
    | 228 |  |  |  *----------------------------------------------------------------------- | 
    
    | 229 |  |  |  */ | 
    
    | 230 |  |  | void | 
    
    | 231 |  |  | Make_Update(GNode *cgn)	/* the child node */ | 
    
    | 232 |  |  | { | 
    
    | 233 |  |  | 	GNode	*pgn;	/* the parent node */ | 
    
    | 234 |  |  | 	LstNode	ln;	/* Element in parents list */ | 
    
    | 235 |  |  |  | 
    
    | 236 |  |  | 	/* | 
    
    | 237 |  |  | 	 * If the child was actually made, see what its modification time is | 
    
    | 238 |  |  | 	 * now -- some rules won't actually update the file. If the file still | 
    
    | 239 |  |  | 	 * doesn't exist, make its mtime now. | 
    
    | 240 |  |  | 	 */ | 
    
    | 241 |  |  | 	if (cgn->built_status != UPTODATE) { | 
    
    | 242 |  |  | 		/* | 
    
    | 243 |  |  | 		 * This is what Make does and it's actually a good thing, as it | 
    
    | 244 |  |  | 		 * allows rules like | 
    
    | 245 |  |  | 		 * | 
    
    | 246 |  |  | 		 *	cmp -s y.tab.h parse.h || cp y.tab.h parse.h | 
    
    | 247 |  |  | 		 * | 
    
    | 248 |  |  | 		 * to function as intended. Unfortunately, thanks to the | 
    
    | 249 |  |  | 		 * stateless nature of NFS, there are times when the | 
    
    | 250 |  |  | 		 * modification time of a file created on a remote machine | 
    
    | 251 |  |  | 		 * will not be modified before the local stat() implied by | 
    
    | 252 |  |  | 		 * the Dir_MTime occurs, thus leading us to believe that the | 
    
    | 253 |  |  | 		 * file is unchanged, wreaking havoc with files that depend | 
    
    | 254 |  |  | 		 * on this one. | 
    
    | 255 |  |  | 		 */ | 
    
    | 256 |  |  | 		if (noExecute || is_out_of_date(Dir_MTime(cgn))) | 
    
    | 257 |  |  | 			clock_gettime(CLOCK_REALTIME, &cgn->mtime); | 
    
    | 258 |  |  | 		if (DEBUG(MAKE)) | 
    
    | 259 |  |  | 			printf("update time: %s\n", | 
    
    | 260 |  |  | 			    time_to_string(&cgn->mtime)); | 
    
    | 261 |  |  | 	} | 
    
    | 262 |  |  |  | 
    
    | 263 |  |  | 	requeue(cgn); | 
    
    | 264 |  |  | 	/* SIB: this is where I should mark the build as finished */ | 
    
    | 265 |  |  | 	for (ln = Lst_First(&cgn->parents); ln != NULL; ln = Lst_Adv(ln)) { | 
    
    | 266 |  |  | 		pgn = (GNode *)Lst_Datum(ln); | 
    
    | 267 |  |  | 		/* SIB: there should be a siblings loop there */ | 
    
    | 268 |  |  | 		pgn->unmade--; | 
    
    | 269 |  |  | 		if (pgn->must_make) { | 
    
    | 270 |  |  | 			if (DEBUG(MAKE)) | 
    
    | 271 |  |  | 				printf("%s--=%d ", | 
    
    | 272 |  |  | 				    pgn->name, pgn->unmade); | 
    
    | 273 |  |  |  | 
    
    | 274 |  |  | 			if ( ! (cgn->type & (OP_EXEC|OP_USE))) { | 
    
    | 275 |  |  | 				if (cgn->built_status == MADE) | 
    
    | 276 |  |  | 					pgn->childMade = true; | 
    
    | 277 |  |  | 				(void)Make_TimeStamp(pgn, cgn); | 
    
    | 278 |  |  | 			} | 
    
    | 279 |  |  | 			if (pgn->unmade == 0) { | 
    
    | 280 |  |  | 				/* | 
    
    | 281 |  |  | 				 * Queue the node up -- any unmade | 
    
    | 282 |  |  | 				 * predecessors will be dealt with in | 
    
    | 283 |  |  | 				 * MakeStartJobs. | 
    
    | 284 |  |  | 				 */ | 
    
    | 285 |  |  | 				if (DEBUG(MAKE)) | 
    
    | 286 |  |  | 					printf("QUEUING "); | 
    
    | 287 |  |  | 				Array_Push(&toBeMade, pgn); | 
    
    | 288 |  |  | 			} else if (pgn->unmade < 0) { | 
    
    | 289 |  |  | 				Error("Child %s discovered graph cycles through %s", cgn->name, pgn->name); | 
    
    | 290 |  |  | 			} | 
    
    | 291 |  |  | 		} | 
    
    | 292 |  |  | 	} | 
    
    | 293 |  |  | 	if (DEBUG(MAKE)) | 
    
    | 294 |  |  | 		printf("\n"); | 
    
    | 295 |  |  | 	requeue_successors(cgn); | 
    
    | 296 |  |  | } | 
    
    | 297 |  |  |  | 
    
    | 298 |  |  | static bool | 
    
    | 299 |  |  | try_to_make_node(GNode *gn) | 
    
    | 300 |  |  | { | 
    
    | 301 |  |  | 	if (DEBUG(MAKE)) | 
    
    | 302 |  |  | 		printf("Examining %s...", gn->name); | 
    
    | 303 |  |  |  | 
    
    | 304 |  |  | 	if (gn->built_status == HELDBACK) { | 
    
    | 305 |  |  | 		if (DEBUG(HELDJOBS)) | 
    
    | 306 |  |  | 			printf("%s already held back ???\n", gn->name); | 
    
    | 307 |  |  | 		return false; | 
    
    | 308 |  |  | 	} | 
    
    | 309 |  |  |  | 
    
    | 310 |  |  | 	if (gn->unmade != 0) { | 
    
    | 311 |  |  | 		if (DEBUG(MAKE)) | 
    
    | 312 |  |  | 			printf(" Requeuing (%d)\n", gn->unmade); | 
    
    | 313 |  |  | 		add_targets_to_make(&gn->children); | 
    
    | 314 |  |  | 		Array_Push(&toBeMade, gn); | 
    
    | 315 |  |  | 		return false; | 
    
    | 316 |  |  | 	} | 
    
    | 317 |  |  | 	if (has_been_built(gn)) { | 
    
    | 318 |  |  | 		if (DEBUG(MAKE)) | 
    
    | 319 |  |  | 			printf(" already made\n"); | 
    
    | 320 |  |  | 		return false; | 
    
    | 321 |  |  | 	} | 
    
    | 322 |  |  | 	if (has_unmade_predecessor(gn)) { | 
    
    | 323 |  |  | 		if (DEBUG(MAKE)) | 
    
    | 324 |  |  | 			printf(" Dropping for now\n"); | 
    
    | 325 |  |  | 		return false; | 
    
    | 326 |  |  | 	} | 
    
    | 327 |  |  |  | 
    
    | 328 |  |  | 	/* SIB: this is where there should be a siblings loop */ | 
    
    | 329 |  |  | 	if (gn->unmade != 0) { | 
    
    | 330 |  |  | 		if (DEBUG(MAKE)) | 
    
    | 331 |  |  | 			printf(" Requeuing (after deps: %d)\n", gn->unmade); | 
    
    | 332 |  |  | 		add_targets_to_make(&gn->children); | 
    
    | 333 |  |  | 		return false; | 
    
    | 334 |  |  | 	} | 
    
    | 335 |  |  | 	/* this is where we hold back nodes */ | 
    
    | 336 |  |  | 	if (gn->groupling != NULL) { | 
    
    | 337 |  |  | 		GNode *gn2; | 
    
    | 338 |  |  | 		for (gn2 = gn->groupling; gn2 != gn; gn2 = gn2->groupling) | 
    
    | 339 |  |  | 			if (gn2->built_status == BUILDING) { | 
    
    | 340 |  |  | 				gn->watched = gn2; | 
    
    | 341 |  |  | 				gn->built_status = HELDBACK; | 
    
    | 342 |  |  | 				if (DEBUG(HELDJOBS)) | 
    
    | 343 |  |  | 					printf("Holding back job %s, " | 
    
    | 344 |  |  | 					    "groupling to %s\n", | 
    
    | 345 |  |  | 					    gn->name, gn2->name); | 
    
    | 346 |  |  | 				Array_Push(&heldBack, gn); | 
    
    | 347 |  |  | 				return false; | 
    
    | 348 |  |  | 			} | 
    
    | 349 |  |  | 	} | 
    
    | 350 |  |  | 	if (gn->sibling != gn) { | 
    
    | 351 |  |  | 		GNode *gn2; | 
    
    | 352 |  |  | 		for (gn2 = gn->sibling; gn2 != gn; gn2 = gn2->sibling) | 
    
    | 353 |  |  | 			if (gn2->built_status == BUILDING) { | 
    
    | 354 |  |  | 				gn->watched = gn2; | 
    
    | 355 |  |  | 				gn->built_status = HELDBACK; | 
    
    | 356 |  |  | 				if (DEBUG(HELDJOBS)) | 
    
    | 357 |  |  | 					printf("Holding back job %s, " | 
    
    | 358 |  |  | 					    "sibling to %s\n", | 
    
    | 359 |  |  | 					    gn->name, gn2->name); | 
    
    | 360 |  |  | 				Array_Push(&heldBack, gn); | 
    
    | 361 |  |  | 				return false; | 
    
    | 362 |  |  | 			} | 
    
    | 363 |  |  | 	} | 
    
    | 364 |  |  | 	if (Make_OODate(gn)) { | 
    
    | 365 |  |  | 		if (DEBUG(MAKE)) | 
    
    | 366 |  |  | 			printf("out-of-date\n"); | 
    
    | 367 |  |  | 		if (queryFlag) | 
    
    | 368 |  |  | 			return true; | 
    
    | 369 |  |  | 		/* SIB: this is where commands should get prepared */ | 
    
    | 370 |  |  | 		Make_DoAllVar(gn); | 
    
    | 371 |  |  | 		Job_Make(gn); | 
    
    | 372 |  |  | 	} else { | 
    
    | 373 |  |  | 		if (DEBUG(MAKE)) | 
    
    | 374 |  |  | 			printf("up-to-date\n"); | 
    
    | 375 |  |  | 		gn->built_status = UPTODATE; | 
    
    | 376 |  |  | 		if (gn->type & OP_JOIN) { | 
    
    | 377 |  |  | 			/* | 
    
    | 378 |  |  | 			 * Even for an up-to-date .JOIN node, we need it | 
    
    | 379 |  |  | 			 * to have its context variables so references | 
    
    | 380 |  |  | 			 * to it get the correct value for .TARGET when | 
    
    | 381 |  |  | 			 * building up the context variables of its | 
    
    | 382 |  |  | 			 * parent(s)... | 
    
    | 383 |  |  | 			 */ | 
    
    | 384 |  |  | 			Make_DoAllVar(gn); | 
    
    | 385 |  |  | 		} | 
    
    | 386 |  |  |  | 
    
    | 387 |  |  | 		Make_Update(gn); | 
    
    | 388 |  |  | 	} | 
    
    | 389 |  |  | 	return false; | 
    
    | 390 |  |  | } | 
    
    | 391 |  |  |  | 
    
    | 392 |  |  | /* | 
    
    | 393 |  |  |  *----------------------------------------------------------------------- | 
    
    | 394 |  |  |  * MakeStartJobs -- | 
    
    | 395 |  |  |  *	Start as many jobs as possible. | 
    
    | 396 |  |  |  * | 
    
    | 397 |  |  |  * Results: | 
    
    | 398 |  |  |  *	If the query flag was given to pmake, no job will be started, | 
    
    | 399 |  |  |  *	but as soon as an out-of-date target is found, this function | 
    
    | 400 |  |  |  *	returns true. At all other times, this function returns false. | 
    
    | 401 |  |  |  * | 
    
    | 402 |  |  |  * Side Effects: | 
    
    | 403 |  |  |  *	Nodes are removed from the toBeMade queue and job table slots | 
    
    | 404 |  |  |  *	are filled. | 
    
    | 405 |  |  |  *----------------------------------------------------------------------- | 
    
    | 406 |  |  |  */ | 
    
    | 407 |  |  | static bool | 
    
    | 408 |  |  | MakeStartJobs(void) | 
    
    | 409 |  |  | { | 
    
    | 410 |  |  | 	GNode	*gn; | 
    
    | 411 |  |  |  | 
    
    | 412 |  |  | 	while (can_start_job() && (gn = Array_Pop(&toBeMade)) != NULL) { | 
    
    | 413 |  |  | 		if (try_to_make_node(gn)) | 
    
    | 414 |  |  | 			return true; | 
    
    | 415 |  |  | 	} | 
    
    | 416 |  |  | 	return false; | 
    
    | 417 |  |  | } | 
    
    | 418 |  |  |  | 
    
    | 419 |  |  | /*- | 
    
    | 420 |  |  |  *----------------------------------------------------------------------- | 
    
    | 421 |  |  |  * MakePrintStatus -- | 
    
    | 422 |  |  |  *	Print the status of a top-level node, viz. it being up-to-date | 
    
    | 423 |  |  |  *	already or not created due to an error in a lower level. | 
    
    | 424 |  |  |  *	Callback function for Make_Run via Lst_ForEach. | 
    
    | 425 |  |  |  * | 
    
    | 426 |  |  |  * Side Effects: | 
    
    | 427 |  |  |  *	A message may be printed. | 
    
    | 428 |  |  |  *----------------------------------------------------------------------- | 
    
    | 429 |  |  |  */ | 
    
    | 430 |  |  | static void | 
    
    | 431 |  |  | MakePrintStatus( | 
    
    | 432 |  |  |     void *gnp,		    /* Node to examine */ | 
    
    | 433 |  |  |     void *cyclep)	    /* True if gn->unmade being non-zero implies | 
    
    | 434 |  |  | 			     * a cycle in the graph, not an error in an | 
    
    | 435 |  |  | 			     * inferior */ | 
    
    | 436 |  |  | { | 
    
    | 437 |  |  | 	GNode	*gn = gnp; | 
    
    | 438 |  |  | 	bool 	*cp = cyclep; | 
    
    | 439 |  |  | 	bool	cycle = *cp; | 
    
    | 440 |  |  | 	if (gn->built_status == UPTODATE) { | 
    
    | 441 |  |  | 		printf("`%s' is up to date.\n", gn->name); | 
    
    | 442 |  |  | 	} else if (gn->unmade != 0) { | 
    
    | 443 |  |  | 		if (cycle) { | 
    
    | 444 |  |  | 			bool t = true; | 
    
    | 445 |  |  | 			/* | 
    
    | 446 |  |  | 			 * If printing cycles and came to one that has unmade | 
    
    | 447 |  |  | 			 * children, print out the cycle by recursing on its | 
    
    | 448 |  |  | 			 * children. Note a cycle like: | 
    
    | 449 |  |  | 			 *	a : b | 
    
    | 450 |  |  | 			 *	b : c | 
    
    | 451 |  |  | 			 *	c : b | 
    
    | 452 |  |  | 			 * will cause this to erroneously complain about a | 
    
    | 453 |  |  | 			 * being in the cycle, but this is a good approximation. | 
    
    | 454 |  |  | 			 */ | 
    
    | 455 |  |  | 			if (gn->built_status == CYCLE) { | 
    
    | 456 |  |  | 				Error("Graph cycles through `%s'", gn->name); | 
    
    | 457 |  |  | 				gn->built_status = ENDCYCLE; | 
    
    | 458 |  |  | 				Lst_ForEach(&gn->children, MakePrintStatus, &t); | 
    
    | 459 |  |  | 				gn->built_status = UNKNOWN; | 
    
    | 460 |  |  | 			} else if (gn->built_status != ENDCYCLE) { | 
    
    | 461 |  |  | 				gn->built_status = CYCLE; | 
    
    | 462 |  |  | 				Lst_ForEach(&gn->children, MakePrintStatus, &t); | 
    
    | 463 |  |  | 			} | 
    
    | 464 |  |  | 		} else { | 
    
    | 465 |  |  | 			printf("`%s' not remade because of errors.\n", | 
    
    | 466 |  |  | 			    gn->name); | 
    
    | 467 |  |  | 		} | 
    
    | 468 |  |  | 	} | 
    
    | 469 |  |  | } | 
    
    | 470 |  |  |  | 
    
    | 471 |  |  |  | 
    
    | 472 |  |  | static void | 
    
    | 473 |  |  | MakeAddChild(void *to_addp, void *ap) | 
    
    | 474 |  |  | { | 
    
    | 475 |  |  | 	GNode *gn = to_addp; | 
    
    | 476 |  |  | 	struct growableArray *a = ap; | 
    
    | 477 |  |  |  | 
    
    | 478 |  |  | 	if (!gn->must_make && !(gn->type & OP_USE)) | 
    
    | 479 |  |  | 		Array_Push(a, gn); | 
    
    | 480 |  |  | } | 
    
    | 481 |  |  |  | 
    
    | 482 |  |  | static void | 
    
    | 483 |  |  | MakeHandleUse(void *cgnp, void *pgnp) | 
    
    | 484 |  |  | { | 
    
    | 485 |  |  | 	GNode *cgn = cgnp; | 
    
    | 486 |  |  | 	GNode *pgn = pgnp; | 
    
    | 487 |  |  |  | 
    
    | 488 |  |  | 	if (cgn->type & OP_USE) | 
    
    | 489 |  |  | 		Make_HandleUse(cgn, pgn); | 
    
    | 490 |  |  | } | 
    
    | 491 |  |  |  | 
    
    | 492 |  |  | /* Add stuff to the toBeMade queue. we try to sort things so that stuff | 
    
    | 493 |  |  |  * that can be done directly is done right away.  This won't be perfect, | 
    
    | 494 |  |  |  * since some dependencies are only discovered later (e.g., SuffFindDeps). | 
    
    | 495 |  |  |  */ | 
    
    | 496 |  |  | static void | 
    
    | 497 |  |  | add_targets_to_make(Lst todo) | 
    
    | 498 |  |  | { | 
    
    | 499 |  |  | 	GNode *gn; | 
    
    | 500 |  |  |  | 
    
    | 501 |  |  | 	unsigned int slot; | 
    
    | 502 |  |  |  | 
    
    | 503 |  |  | 	AppendList2Array(todo, &examine); | 
    
    | 504 |  |  |  | 
    
    | 505 |  |  | 	while ((gn = Array_Pop(&examine)) != NULL) { | 
    
    | 506 |  |  | 		if (gn->must_make) 	/* already known */ | 
    
    | 507 |  |  | 			continue; | 
    
    | 508 |  |  | 		gn->must_make = true; | 
    
    | 509 |  |  |  | 
    
    | 510 |  |  | 		slot = ohash_qlookup(&targets, gn->name); | 
    
    | 511 |  |  | 		if (!ohash_find(&targets, slot)) | 
    
    | 512 |  |  | 			ohash_insert(&targets, slot, gn); | 
    
    | 513 |  |  |  | 
    
    | 514 |  |  |  | 
    
    | 515 |  |  | 		look_harder_for_target(gn); | 
    
    | 516 |  |  | 		kludge_look_harder_for_target(gn); | 
    
    | 517 |  |  | 		/* | 
    
    | 518 |  |  | 		 * Apply any .USE rules before looking for implicit | 
    
    | 519 |  |  | 		 * dependencies to make sure everything that should have | 
    
    | 520 |  |  | 		 * commands has commands ... | 
    
    | 521 |  |  | 		 */ | 
    
    | 522 |  |  | 		Lst_ForEach(&gn->children, MakeHandleUse, gn); | 
    
    | 523 |  |  | 		Suff_FindDeps(gn); | 
    
    | 524 |  |  | 		expand_all_children(gn); | 
    
    | 525 |  |  |  | 
    
    | 526 |  |  | 		if (gn->unmade != 0) { | 
    
    | 527 |  |  | 			if (DEBUG(MAKE)) | 
    
    | 528 |  |  | 				printf("%s: not queuing (%d unmade children)\n", | 
    
    | 529 |  |  | 				    gn->name, gn->unmade); | 
    
    | 530 |  |  | 			Lst_ForEach(&gn->children, MakeAddChild, | 
    
    | 531 |  |  | 			    &examine); | 
    
    | 532 |  |  | 		} else { | 
    
    | 533 |  |  | 			if (DEBUG(MAKE)) | 
    
    | 534 |  |  | 				printf("%s: queuing\n", gn->name); | 
    
    | 535 |  |  | 			Array_Push(&toBeMade, gn); | 
    
    | 536 |  |  | 		} | 
    
    | 537 |  |  | 	} | 
    
    | 538 |  |  | 	if (randomize_queue) | 
    
    | 539 |  |  | 		randomize_garray(&toBeMade); | 
    
    | 540 |  |  | } | 
    
    | 541 |  |  |  | 
    
    | 542 |  |  | /*- | 
    
    | 543 |  |  |  *----------------------------------------------------------------------- | 
    
    | 544 |  |  |  * Make_Run -- | 
    
    | 545 |  |  |  *	Initialize the nodes to remake and the list of nodes which are | 
    
    | 546 |  |  |  *	ready to be made by doing a breadth-first traversal of the graph | 
    
    | 547 |  |  |  *	starting from the nodes in the given list. Once this traversal | 
    
    | 548 |  |  |  *	is finished, all the 'leaves' of the graph are in the toBeMade | 
    
    | 549 |  |  |  *	queue. | 
    
    | 550 |  |  |  *	Using this queue and the Job module, work back up the graph, | 
    
    | 551 |  |  |  *	calling on MakeStartJobs to keep the job table as full as | 
    
    | 552 |  |  |  *	possible. | 
    
    | 553 |  |  |  * | 
    
    | 554 |  |  |  * Results: | 
    
    | 555 |  |  |  *	true if work was done. false otherwise. | 
    
    | 556 |  |  |  * | 
    
    | 557 |  |  |  * Side Effects: | 
    
    | 558 |  |  |  *	The must_make field of all nodes involved in the creation of the given | 
    
    | 559 |  |  |  *	targets is set to 1. The toBeMade list is set to contain all the | 
    
    | 560 |  |  |  *	'leaves' of these subgraphs. | 
    
    | 561 |  |  |  *----------------------------------------------------------------------- | 
    
    | 562 |  |  |  */ | 
    
    | 563 |  |  | bool | 
    
    | 564 |  |  | Make_Run(Lst targs)		/* the initial list of targets */ | 
    
    | 565 |  |  | { | 
    
    | 566 |  |  | 	bool problem;	/* errors occurred */ | 
    
    | 567 |  |  | 	GNode *gn; | 
    
    | 568 |  |  | 	unsigned int i; | 
    
    | 569 |  |  | 	bool cycle; | 
    
    | 570 |  |  |  | 
    
    | 571 |  |  | 	/* wild guess at initial sizes */ | 
    
    | 572 |  |  | 	Array_Init(&toBeMade, 500); | 
    
    | 573 |  |  | 	Array_Init(&examine, 150); | 
    
    | 574 |  |  | 	Array_Init(&heldBack, 100); | 
    
    | 575 |  |  | 	ohash_init(&targets, 10, &gnode_info); | 
    
    | 576 |  |  | 	if (DEBUG(PARALLEL)) | 
    
    | 577 |  |  | 		random_setup(); | 
    
    | 578 |  |  |  | 
    
    | 579 |  |  | 	add_targets_to_make(targs); | 
    
    | 580 |  |  | 	if (queryFlag) { | 
    
    | 581 |  |  | 		/* | 
    
    | 582 |  |  | 		 * We wouldn't do any work unless we could start some jobs in | 
    
    | 583 |  |  | 		 * the next loop... (we won't actually start any, of course, | 
    
    | 584 |  |  | 		 * this is just to see if any of the targets was out of date) | 
    
    | 585 |  |  | 		 */ | 
    
    | 586 |  |  | 		return MakeStartJobs(); | 
    
    | 587 |  |  | 	} else { | 
    
    | 588 |  |  | 		/* | 
    
    | 589 |  |  | 		 * Initialization. At the moment, no jobs are running and until | 
    
    | 590 |  |  | 		 * some get started, nothing will happen since the remaining | 
    
    | 591 |  |  | 		 * upward traversal of the graph is performed by the routines | 
    
    | 592 |  |  | 		 * in job.c upon the finishing of a job. So we fill the Job | 
    
    | 593 |  |  | 		 * table as much as we can before going into our loop. | 
    
    | 594 |  |  | 		 */ | 
    
    | 595 |  |  | 		(void)MakeStartJobs(); | 
    
    | 596 |  |  | 	} | 
    
    | 597 |  |  |  | 
    
    | 598 |  |  | 	/* | 
    
    | 599 |  |  | 	 * Main Loop: The idea here is that the ending of jobs will take | 
    
    | 600 |  |  | 	 * care of the maintenance of data structures and the waiting for output | 
    
    | 601 |  |  | 	 * will cause us to be idle most of the time while our children run as | 
    
    | 602 |  |  | 	 * much as possible. Because the job table is kept as full as possible, | 
    
    | 603 |  |  | 	 * the only time when it will be empty is when all the jobs which need | 
    
    | 604 |  |  | 	 * running have been run, so that is the end condition of this loop. | 
    
    | 605 |  |  | 	 * Note that the Job module will exit if there were any errors unless | 
    
    | 606 |  |  | 	 * the keepgoing flag was given. | 
    
    | 607 |  |  | 	 */ | 
    
    | 608 |  |  | 	while (!Job_Empty()) { | 
    
    | 609 |  |  | 		handle_running_jobs(); | 
    
    | 610 |  |  | 		(void)MakeStartJobs(); | 
    
    | 611 |  |  | 	} | 
    
    | 612 |  |  |  | 
    
    | 613 |  |  | 	problem = Job_Finish(); | 
    
    | 614 |  |  | 	cycle = false; | 
    
    | 615 |  |  |  | 
    
    | 616 |  |  | 	for (gn = ohash_first(&targets, &i); gn != NULL; | 
    
    | 617 |  |  | 	    gn = ohash_next(&targets, &i)) { | 
    
    | 618 |  |  | 	    	if (has_been_built(gn)) | 
    
    | 619 |  |  | 			continue; | 
    
    | 620 |  |  | 		cycle = true; | 
    
    | 621 |  |  | 		problem = true; | 
    
    | 622 |  |  | 	    	printf("Error: target %s unaccounted for (%s)\n", | 
    
    | 623 |  |  | 		    gn->name, status_to_string(gn)); | 
    
    | 624 |  |  | 	} | 
    
    | 625 |  |  | 	/* | 
    
    | 626 |  |  | 	 * Print the final status of each target. E.g. if it wasn't made | 
    
    | 627 |  |  | 	 * because some inferior reported an error. | 
    
    | 628 |  |  | 	 */ | 
    
    | 629 |  |  | 	Lst_ForEach(targs, MakePrintStatus, &cycle); | 
    
    | 630 |  |  | 	if (problem) | 
    
    | 631 |  |  | 		Fatal("Errors while building"); | 
    
    | 632 |  |  |  | 
    
    | 633 |  |  | 	return true; | 
    
    | 634 |  |  | } |