1*2c3632d1SSimon J. Gerraty /* $NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $ */ 23955d011SMarcel Moolenaar 33955d011SMarcel Moolenaar /* 43955d011SMarcel Moolenaar * Copyright (c) 1988, 1989, 1990, 1993 53955d011SMarcel Moolenaar * The Regents of the University of California. All rights reserved. 63955d011SMarcel Moolenaar * 73955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 83955d011SMarcel Moolenaar * Adam de Boor. 93955d011SMarcel Moolenaar * 103955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 113955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 123955d011SMarcel Moolenaar * are met: 133955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 143955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 153955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 163955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 173955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 183955d011SMarcel Moolenaar * 3. Neither the name of the University nor the names of its contributors 193955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 203955d011SMarcel Moolenaar * without specific prior written permission. 213955d011SMarcel Moolenaar * 223955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 233955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 243955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 253955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 263955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 273955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 283955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 293955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 303955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 313955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 323955d011SMarcel Moolenaar * SUCH DAMAGE. 333955d011SMarcel Moolenaar */ 343955d011SMarcel Moolenaar 353955d011SMarcel Moolenaar /* 363955d011SMarcel Moolenaar * Copyright (c) 1989 by Berkeley Softworks 373955d011SMarcel Moolenaar * All rights reserved. 383955d011SMarcel Moolenaar * 393955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 403955d011SMarcel Moolenaar * Adam de Boor. 413955d011SMarcel Moolenaar * 423955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 433955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 443955d011SMarcel Moolenaar * are met: 453955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 463955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 473955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 483955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 493955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 503955d011SMarcel Moolenaar * 3. All advertising materials mentioning features or use of this software 513955d011SMarcel Moolenaar * must display the following acknowledgement: 523955d011SMarcel Moolenaar * This product includes software developed by the University of 533955d011SMarcel Moolenaar * California, Berkeley and its contributors. 543955d011SMarcel Moolenaar * 4. Neither the name of the University nor the names of its contributors 553955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 563955d011SMarcel Moolenaar * without specific prior written permission. 573955d011SMarcel Moolenaar * 583955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 593955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 603955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 613955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 623955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 633955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 643955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 653955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 663955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 673955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 683955d011SMarcel Moolenaar * SUCH DAMAGE. 693955d011SMarcel Moolenaar */ 703955d011SMarcel Moolenaar 713955d011SMarcel Moolenaar #ifndef MAKE_NATIVE 72*2c3632d1SSimon J. Gerraty static char rcsid[] = "$NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $"; 733955d011SMarcel Moolenaar #else 743955d011SMarcel Moolenaar #include <sys/cdefs.h> 753955d011SMarcel Moolenaar #ifndef lint 763955d011SMarcel Moolenaar #if 0 773955d011SMarcel Moolenaar static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93"; 783955d011SMarcel Moolenaar #else 79*2c3632d1SSimon J. Gerraty __RCSID("$NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $"); 803955d011SMarcel Moolenaar #endif 813955d011SMarcel Moolenaar #endif /* not lint */ 823955d011SMarcel Moolenaar #endif 833955d011SMarcel Moolenaar 843955d011SMarcel Moolenaar /*- 853955d011SMarcel Moolenaar * make.c -- 863955d011SMarcel Moolenaar * The functions which perform the examination of targets and 873955d011SMarcel Moolenaar * their suitability for creation 883955d011SMarcel Moolenaar * 893955d011SMarcel Moolenaar * Interface: 903955d011SMarcel Moolenaar * Make_Run Initialize things for the module and recreate 913955d011SMarcel Moolenaar * whatever needs recreating. Returns TRUE if 923955d011SMarcel Moolenaar * work was (or would have been) done and FALSE 933955d011SMarcel Moolenaar * otherwise. 943955d011SMarcel Moolenaar * 953955d011SMarcel Moolenaar * Make_Update Update all parents of a given child. Performs 963955d011SMarcel Moolenaar * various bookkeeping chores like the updating 973955d011SMarcel Moolenaar * of the cmgn field of the parent, filling 983955d011SMarcel Moolenaar * of the IMPSRC context variable, etc. It will 993955d011SMarcel Moolenaar * place the parent on the toBeMade queue if it 1003955d011SMarcel Moolenaar * should be. 1013955d011SMarcel Moolenaar * 1023955d011SMarcel Moolenaar * Make_TimeStamp Function to set the parent's cmgn field 1033955d011SMarcel Moolenaar * based on a child's modification time. 1043955d011SMarcel Moolenaar * 1053955d011SMarcel Moolenaar * Make_DoAllVar Set up the various local variables for a 1063955d011SMarcel Moolenaar * target, including the .ALLSRC variable, making 1073955d011SMarcel Moolenaar * sure that any variable that needs to exist 1083955d011SMarcel Moolenaar * at the very least has the empty value. 1093955d011SMarcel Moolenaar * 1103955d011SMarcel Moolenaar * Make_OODate Determine if a target is out-of-date. 1113955d011SMarcel Moolenaar * 1123955d011SMarcel Moolenaar * Make_HandleUse See if a child is a .USE node for a parent 1133955d011SMarcel Moolenaar * and perform the .USE actions if so. 1143955d011SMarcel Moolenaar * 1153955d011SMarcel Moolenaar * Make_ExpandUse Expand .USE nodes 1163955d011SMarcel Moolenaar */ 1173955d011SMarcel Moolenaar 1183955d011SMarcel Moolenaar #include "make.h" 119*2c3632d1SSimon J. Gerraty #include "enum.h" 1203955d011SMarcel Moolenaar #include "dir.h" 1213955d011SMarcel Moolenaar #include "job.h" 1223955d011SMarcel Moolenaar 1233955d011SMarcel Moolenaar static unsigned int checked = 1;/* Sequence # to detect recursion */ 1243955d011SMarcel Moolenaar static Lst toBeMade; /* The current fringe of the graph. These 1253955d011SMarcel Moolenaar * are nodes which await examination by 1263955d011SMarcel Moolenaar * MakeOODate. It is added to by 1273955d011SMarcel Moolenaar * Make_Update and subtracted from by 1283955d011SMarcel Moolenaar * MakeStartJobs */ 1293955d011SMarcel Moolenaar 1303955d011SMarcel Moolenaar static int MakeAddChild(void *, void *); 1313955d011SMarcel Moolenaar static int MakeFindChild(void *, void *); 1323955d011SMarcel Moolenaar static int MakeUnmark(void *, void *); 1333955d011SMarcel Moolenaar static int MakeAddAllSrc(void *, void *); 1343955d011SMarcel Moolenaar static int MakeTimeStamp(void *, void *); 1353955d011SMarcel Moolenaar static int MakeHandleUse(void *, void *); 1363955d011SMarcel Moolenaar static Boolean MakeStartJobs(void); 1373955d011SMarcel Moolenaar static int MakePrintStatus(void *, void *); 1383955d011SMarcel Moolenaar static int MakeCheckOrder(void *, void *); 1393955d011SMarcel Moolenaar static int MakeBuildChild(void *, void *); 1403955d011SMarcel Moolenaar static int MakeBuildParent(void *, void *); 1413955d011SMarcel Moolenaar 1423955d011SMarcel Moolenaar MAKE_ATTR_DEAD static void 1433955d011SMarcel Moolenaar make_abort(GNode *gn, int line) 1443955d011SMarcel Moolenaar { 1453955d011SMarcel Moolenaar static int two = 2; 1463955d011SMarcel Moolenaar 1473955d011SMarcel Moolenaar fprintf(debug_file, "make_abort from line %d\n", line); 1483955d011SMarcel Moolenaar Targ_PrintNode(gn, &two); 1493955d011SMarcel Moolenaar Lst_ForEach(toBeMade, Targ_PrintNode, &two); 1503955d011SMarcel Moolenaar Targ_PrintGraph(3); 1513955d011SMarcel Moolenaar abort(); 1523955d011SMarcel Moolenaar } 1533955d011SMarcel Moolenaar 154*2c3632d1SSimon J. Gerraty ENUM_VALUE_RTTI_8(GNodeMade, 155*2c3632d1SSimon J. Gerraty UNMADE, DEFERRED, REQUESTED, BEINGMADE, 156*2c3632d1SSimon J. Gerraty MADE, UPTODATE, ERROR, ABORTED); 157*2c3632d1SSimon J. Gerraty 158*2c3632d1SSimon J. Gerraty ENUM_FLAGS_RTTI_31(GNodeType, 159*2c3632d1SSimon J. Gerraty OP_DEPENDS, OP_FORCE, OP_DOUBLEDEP, 160*2c3632d1SSimon J. Gerraty /* OP_OPMASK is omitted since it combines other flags */ 161*2c3632d1SSimon J. Gerraty OP_OPTIONAL, OP_USE, OP_EXEC, OP_IGNORE, 162*2c3632d1SSimon J. Gerraty OP_PRECIOUS, OP_SILENT, OP_MAKE, OP_JOIN, 163*2c3632d1SSimon J. Gerraty OP_MADE, OP_SPECIAL, OP_USEBEFORE, OP_INVISIBLE, 164*2c3632d1SSimon J. Gerraty OP_NOTMAIN, OP_PHONY, OP_NOPATH, OP_WAIT, 165*2c3632d1SSimon J. Gerraty OP_NOMETA, OP_META, OP_NOMETA_CMP, OP_SUBMAKE, 166*2c3632d1SSimon J. Gerraty OP_TRANSFORM, OP_MEMBER, OP_LIB, OP_ARCHV, 167*2c3632d1SSimon J. Gerraty OP_HAS_COMMANDS, OP_SAVE_CMDS, OP_DEPS_FOUND, OP_MARK); 168*2c3632d1SSimon J. Gerraty 169*2c3632d1SSimon J. Gerraty ENUM_FLAGS_RTTI_10(GNodeFlags, 170*2c3632d1SSimon J. Gerraty REMAKE, CHILDMADE, FORCE, DONE_WAIT, 171*2c3632d1SSimon J. Gerraty DONE_ORDER, FROM_DEPEND, DONE_ALLSRC, CYCLE, 172*2c3632d1SSimon J. Gerraty DONECYCLE, INTERNAL); 173*2c3632d1SSimon J. Gerraty 174*2c3632d1SSimon J. Gerraty void 175*2c3632d1SSimon J. Gerraty GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn, 176*2c3632d1SSimon J. Gerraty const char *suffix) 177*2c3632d1SSimon J. Gerraty { 178*2c3632d1SSimon J. Gerraty char type_buf[GNodeType_ToStringSize]; 179*2c3632d1SSimon J. Gerraty char flags_buf[GNodeFlags_ToStringSize]; 180*2c3632d1SSimon J. Gerraty 181*2c3632d1SSimon J. Gerraty fprintf(f, "%smade %s, type %s, flags %s%s", 182*2c3632d1SSimon J. Gerraty prefix, 183*2c3632d1SSimon J. Gerraty Enum_ValueToString(gn->made, GNodeMade_ToStringSpecs), 184*2c3632d1SSimon J. Gerraty Enum_FlagsToString(type_buf, sizeof type_buf, 185*2c3632d1SSimon J. Gerraty gn->type, GNodeType_ToStringSpecs), 186*2c3632d1SSimon J. Gerraty Enum_FlagsToString(flags_buf, sizeof flags_buf, 187*2c3632d1SSimon J. Gerraty gn->flags, GNodeFlags_ToStringSpecs), 188*2c3632d1SSimon J. Gerraty suffix); 189*2c3632d1SSimon J. Gerraty } 190*2c3632d1SSimon J. Gerraty 1913955d011SMarcel Moolenaar /*- 1923955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1933955d011SMarcel Moolenaar * Make_TimeStamp -- 1943955d011SMarcel Moolenaar * Set the cmgn field of a parent node based on the mtime stamp in its 1953955d011SMarcel Moolenaar * child. Called from MakeOODate via Lst_ForEach. 1963955d011SMarcel Moolenaar * 1973955d011SMarcel Moolenaar * Input: 1983955d011SMarcel Moolenaar * pgn the current parent 1993955d011SMarcel Moolenaar * cgn the child we've just examined 2003955d011SMarcel Moolenaar * 2013955d011SMarcel Moolenaar * Results: 2023955d011SMarcel Moolenaar * Always returns 0. 2033955d011SMarcel Moolenaar * 2043955d011SMarcel Moolenaar * Side Effects: 2053955d011SMarcel Moolenaar * The cmgn of the parent node will be changed if the mtime 2063955d011SMarcel Moolenaar * field of the child is greater than it. 2073955d011SMarcel Moolenaar *----------------------------------------------------------------------- 2083955d011SMarcel Moolenaar */ 2093955d011SMarcel Moolenaar int 2103955d011SMarcel Moolenaar Make_TimeStamp(GNode *pgn, GNode *cgn) 2113955d011SMarcel Moolenaar { 2123955d011SMarcel Moolenaar if (pgn->cmgn == NULL || cgn->mtime > pgn->cmgn->mtime) { 2133955d011SMarcel Moolenaar pgn->cmgn = cgn; 2143955d011SMarcel Moolenaar } 2153841c287SSimon J. Gerraty return 0; 2163955d011SMarcel Moolenaar } 2173955d011SMarcel Moolenaar 2183955d011SMarcel Moolenaar /* 2193955d011SMarcel Moolenaar * Input: 2203955d011SMarcel Moolenaar * pgn the current parent 2213955d011SMarcel Moolenaar * cgn the child we've just examined 2223955d011SMarcel Moolenaar * 2233955d011SMarcel Moolenaar */ 2243955d011SMarcel Moolenaar static int 2253955d011SMarcel Moolenaar MakeTimeStamp(void *pgn, void *cgn) 2263955d011SMarcel Moolenaar { 2273955d011SMarcel Moolenaar return Make_TimeStamp((GNode *)pgn, (GNode *)cgn); 2283955d011SMarcel Moolenaar } 229*2c3632d1SSimon J. Gerraty 2303955d011SMarcel Moolenaar /*- 2313955d011SMarcel Moolenaar *----------------------------------------------------------------------- 2323955d011SMarcel Moolenaar * Make_OODate -- 2333955d011SMarcel Moolenaar * See if a given node is out of date with respect to its sources. 2343955d011SMarcel Moolenaar * Used by Make_Run when deciding which nodes to place on the 2353955d011SMarcel Moolenaar * toBeMade queue initially and by Make_Update to screen out USE and 2363955d011SMarcel Moolenaar * EXEC nodes. In the latter case, however, any other sort of node 2373955d011SMarcel Moolenaar * must be considered out-of-date since at least one of its children 2383955d011SMarcel Moolenaar * will have been recreated. 2393955d011SMarcel Moolenaar * 2403955d011SMarcel Moolenaar * Input: 2413955d011SMarcel Moolenaar * gn the node to check 2423955d011SMarcel Moolenaar * 2433955d011SMarcel Moolenaar * Results: 2443955d011SMarcel Moolenaar * TRUE if the node is out of date. FALSE otherwise. 2453955d011SMarcel Moolenaar * 2463955d011SMarcel Moolenaar * Side Effects: 2473955d011SMarcel Moolenaar * The mtime field of the node and the cmgn field of its parents 2483955d011SMarcel Moolenaar * will/may be changed. 2493955d011SMarcel Moolenaar *----------------------------------------------------------------------- 2503955d011SMarcel Moolenaar */ 2513955d011SMarcel Moolenaar Boolean 2523955d011SMarcel Moolenaar Make_OODate(GNode *gn) 2533955d011SMarcel Moolenaar { 2543955d011SMarcel Moolenaar Boolean oodate; 2553955d011SMarcel Moolenaar 2563955d011SMarcel Moolenaar /* 2573955d011SMarcel Moolenaar * Certain types of targets needn't even be sought as their datedness 2583955d011SMarcel Moolenaar * doesn't depend on their modification time... 2593955d011SMarcel Moolenaar */ 2603955d011SMarcel Moolenaar if ((gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC)) == 0) { 2613955d011SMarcel Moolenaar (void)Dir_MTime(gn, 1); 2623955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 2633955d011SMarcel Moolenaar if (gn->mtime != 0) { 2643955d011SMarcel Moolenaar fprintf(debug_file, "modified %s...", Targ_FmtTime(gn->mtime)); 2653955d011SMarcel Moolenaar } else { 2663955d011SMarcel Moolenaar fprintf(debug_file, "non-existent..."); 2673955d011SMarcel Moolenaar } 2683955d011SMarcel Moolenaar } 2693955d011SMarcel Moolenaar } 2703955d011SMarcel Moolenaar 2713955d011SMarcel Moolenaar /* 2723955d011SMarcel Moolenaar * A target is remade in one of the following circumstances: 2733955d011SMarcel Moolenaar * its modification time is smaller than that of its youngest child 2743955d011SMarcel Moolenaar * and it would actually be run (has commands or type OP_NOP) 2753955d011SMarcel Moolenaar * it's the object of a force operator 2763955d011SMarcel Moolenaar * it has no children, was on the lhs of an operator and doesn't exist 2773955d011SMarcel Moolenaar * already. 2783955d011SMarcel Moolenaar * 2793955d011SMarcel Moolenaar * Libraries are only considered out-of-date if the archive module says 2803955d011SMarcel Moolenaar * they are. 2813955d011SMarcel Moolenaar * 2823955d011SMarcel Moolenaar * These weird rules are brought to you by Backward-Compatibility and 2833955d011SMarcel Moolenaar * the strange people who wrote 'Make'. 2843955d011SMarcel Moolenaar */ 2853955d011SMarcel Moolenaar if (gn->type & (OP_USE|OP_USEBEFORE)) { 2863955d011SMarcel Moolenaar /* 2873955d011SMarcel Moolenaar * If the node is a USE node it is *never* out of date 2883955d011SMarcel Moolenaar * no matter *what*. 2893955d011SMarcel Moolenaar */ 2903955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 2913955d011SMarcel Moolenaar fprintf(debug_file, ".USE node..."); 2923955d011SMarcel Moolenaar } 2933955d011SMarcel Moolenaar oodate = FALSE; 2943955d011SMarcel Moolenaar } else if ((gn->type & OP_LIB) && 2953955d011SMarcel Moolenaar ((gn->mtime==0) || Arch_IsLib(gn))) { 2963955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 2973955d011SMarcel Moolenaar fprintf(debug_file, "library..."); 2983955d011SMarcel Moolenaar } 2993955d011SMarcel Moolenaar 3003955d011SMarcel Moolenaar /* 3013955d011SMarcel Moolenaar * always out of date if no children and :: target 3023955d011SMarcel Moolenaar * or non-existent. 3033955d011SMarcel Moolenaar */ 3043955d011SMarcel Moolenaar oodate = (gn->mtime == 0 || Arch_LibOODate(gn) || 3053955d011SMarcel Moolenaar (gn->cmgn == NULL && (gn->type & OP_DOUBLEDEP))); 3063955d011SMarcel Moolenaar } else if (gn->type & OP_JOIN) { 3073955d011SMarcel Moolenaar /* 3083955d011SMarcel Moolenaar * A target with the .JOIN attribute is only considered 3093955d011SMarcel Moolenaar * out-of-date if any of its children was out-of-date. 3103955d011SMarcel Moolenaar */ 3113955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 3123955d011SMarcel Moolenaar fprintf(debug_file, ".JOIN node..."); 3133955d011SMarcel Moolenaar } 3143955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 3153955d011SMarcel Moolenaar fprintf(debug_file, "source %smade...", gn->flags & CHILDMADE ? "" : "not "); 3163955d011SMarcel Moolenaar } 3173955d011SMarcel Moolenaar oodate = (gn->flags & CHILDMADE) ? TRUE : FALSE; 3183955d011SMarcel Moolenaar } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) { 3193955d011SMarcel Moolenaar /* 3203955d011SMarcel Moolenaar * A node which is the object of the force (!) operator or which has 3213955d011SMarcel Moolenaar * the .EXEC attribute is always considered out-of-date. 3223955d011SMarcel Moolenaar */ 3233955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 3243955d011SMarcel Moolenaar if (gn->type & OP_FORCE) { 3253955d011SMarcel Moolenaar fprintf(debug_file, "! operator..."); 3263955d011SMarcel Moolenaar } else if (gn->type & OP_PHONY) { 3273955d011SMarcel Moolenaar fprintf(debug_file, ".PHONY node..."); 3283955d011SMarcel Moolenaar } else { 3293955d011SMarcel Moolenaar fprintf(debug_file, ".EXEC node..."); 3303955d011SMarcel Moolenaar } 3313955d011SMarcel Moolenaar } 3323955d011SMarcel Moolenaar oodate = TRUE; 3333955d011SMarcel Moolenaar } else if ((gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime) || 3343955d011SMarcel Moolenaar (gn->cmgn == NULL && 3353955d011SMarcel Moolenaar ((gn->mtime == 0 && !(gn->type & OP_OPTIONAL)) 3363955d011SMarcel Moolenaar || gn->type & OP_DOUBLEDEP))) 3373955d011SMarcel Moolenaar { 3383955d011SMarcel Moolenaar /* 3393955d011SMarcel Moolenaar * A node whose modification time is less than that of its 3403955d011SMarcel Moolenaar * youngest child or that has no children (cmgn == NULL) and 3413955d011SMarcel Moolenaar * either doesn't exist (mtime == 0) and it isn't optional 3423955d011SMarcel Moolenaar * or was the object of a * :: operator is out-of-date. 3433955d011SMarcel Moolenaar * Why? Because that's the way Make does it. 3443955d011SMarcel Moolenaar */ 3453955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 3463955d011SMarcel Moolenaar if (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime) { 3473955d011SMarcel Moolenaar fprintf(debug_file, "modified before source %s...", 34845447996SSimon J. Gerraty gn->cmgn->path ? gn->cmgn->path : gn->cmgn->name); 3493955d011SMarcel Moolenaar } else if (gn->mtime == 0) { 3503955d011SMarcel Moolenaar fprintf(debug_file, "non-existent and no sources..."); 3513955d011SMarcel Moolenaar } else { 3523955d011SMarcel Moolenaar fprintf(debug_file, ":: operator and no sources..."); 3533955d011SMarcel Moolenaar } 3543955d011SMarcel Moolenaar } 3553955d011SMarcel Moolenaar oodate = TRUE; 3563955d011SMarcel Moolenaar } else { 3573955d011SMarcel Moolenaar /* 3583955d011SMarcel Moolenaar * When a non-existing child with no sources 3593955d011SMarcel Moolenaar * (such as a typically used FORCE source) has been made and 3603955d011SMarcel Moolenaar * the target of the child (usually a directory) has the same 3613955d011SMarcel Moolenaar * timestamp as the timestamp just given to the non-existing child 3623955d011SMarcel Moolenaar * after it was considered made. 3633955d011SMarcel Moolenaar */ 3643955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 3653955d011SMarcel Moolenaar if (gn->flags & FORCE) 3663955d011SMarcel Moolenaar fprintf(debug_file, "non existing child..."); 3673955d011SMarcel Moolenaar } 3683955d011SMarcel Moolenaar oodate = (gn->flags & FORCE) ? TRUE : FALSE; 3693955d011SMarcel Moolenaar } 3703955d011SMarcel Moolenaar 3713955d011SMarcel Moolenaar #ifdef USE_META 3723955d011SMarcel Moolenaar if (useMeta) { 3733955d011SMarcel Moolenaar oodate = meta_oodate(gn, oodate); 3743955d011SMarcel Moolenaar } 3753955d011SMarcel Moolenaar #endif 3763955d011SMarcel Moolenaar 3773955d011SMarcel Moolenaar /* 3783955d011SMarcel Moolenaar * If the target isn't out-of-date, the parents need to know its 3793955d011SMarcel Moolenaar * modification time. Note that targets that appear to be out-of-date 3803955d011SMarcel Moolenaar * but aren't, because they have no commands and aren't of type OP_NOP, 3813955d011SMarcel Moolenaar * have their mtime stay below their children's mtime to keep parents from 3823955d011SMarcel Moolenaar * thinking they're out-of-date. 3833955d011SMarcel Moolenaar */ 3843955d011SMarcel Moolenaar if (!oodate) { 3853955d011SMarcel Moolenaar Lst_ForEach(gn->parents, MakeTimeStamp, gn); 3863955d011SMarcel Moolenaar } 3873955d011SMarcel Moolenaar 3883841c287SSimon J. Gerraty return oodate; 3893955d011SMarcel Moolenaar } 390*2c3632d1SSimon J. Gerraty 3913955d011SMarcel Moolenaar /*- 3923955d011SMarcel Moolenaar *----------------------------------------------------------------------- 3933955d011SMarcel Moolenaar * MakeAddChild -- 3943955d011SMarcel Moolenaar * Function used by Make_Run to add a child to the list l. 3953955d011SMarcel Moolenaar * It will only add the child if its make field is FALSE. 3963955d011SMarcel Moolenaar * 3973955d011SMarcel Moolenaar * Input: 3983955d011SMarcel Moolenaar * gnp the node to add 3993955d011SMarcel Moolenaar * lp the list to which to add it 4003955d011SMarcel Moolenaar * 4013955d011SMarcel Moolenaar * Results: 4023955d011SMarcel Moolenaar * Always returns 0 4033955d011SMarcel Moolenaar * 4043955d011SMarcel Moolenaar * Side Effects: 4053955d011SMarcel Moolenaar * The given list is extended 4063955d011SMarcel Moolenaar *----------------------------------------------------------------------- 4073955d011SMarcel Moolenaar */ 4083955d011SMarcel Moolenaar static int 4093955d011SMarcel Moolenaar MakeAddChild(void *gnp, void *lp) 4103955d011SMarcel Moolenaar { 4113955d011SMarcel Moolenaar GNode *gn = (GNode *)gnp; 4123955d011SMarcel Moolenaar Lst l = (Lst) lp; 4133955d011SMarcel Moolenaar 4143955d011SMarcel Moolenaar if ((gn->flags & REMAKE) == 0 && !(gn->type & (OP_USE|OP_USEBEFORE))) { 4153955d011SMarcel Moolenaar if (DEBUG(MAKE)) 4163955d011SMarcel Moolenaar fprintf(debug_file, "MakeAddChild: need to examine %s%s\n", 4173955d011SMarcel Moolenaar gn->name, gn->cohort_num); 418*2c3632d1SSimon J. Gerraty Lst_Enqueue(l, gn); 4193955d011SMarcel Moolenaar } 4203841c287SSimon J. Gerraty return 0; 4213955d011SMarcel Moolenaar } 422*2c3632d1SSimon J. Gerraty 4233955d011SMarcel Moolenaar /*- 4243955d011SMarcel Moolenaar *----------------------------------------------------------------------- 4253955d011SMarcel Moolenaar * MakeFindChild -- 4263955d011SMarcel Moolenaar * Function used by Make_Run to find the pathname of a child 4273955d011SMarcel Moolenaar * that was already made. 4283955d011SMarcel Moolenaar * 4293955d011SMarcel Moolenaar * Input: 4303955d011SMarcel Moolenaar * gnp the node to find 4313955d011SMarcel Moolenaar * 4323955d011SMarcel Moolenaar * Results: 4333955d011SMarcel Moolenaar * Always returns 0 4343955d011SMarcel Moolenaar * 4353955d011SMarcel Moolenaar * Side Effects: 4363955d011SMarcel Moolenaar * The path and mtime of the node and the cmgn of the parent are 4373955d011SMarcel Moolenaar * updated; the unmade children count of the parent is decremented. 4383955d011SMarcel Moolenaar *----------------------------------------------------------------------- 4393955d011SMarcel Moolenaar */ 4403955d011SMarcel Moolenaar static int 4413955d011SMarcel Moolenaar MakeFindChild(void *gnp, void *pgnp) 4423955d011SMarcel Moolenaar { 4433955d011SMarcel Moolenaar GNode *gn = (GNode *)gnp; 4443955d011SMarcel Moolenaar GNode *pgn = (GNode *)pgnp; 4453955d011SMarcel Moolenaar 4463955d011SMarcel Moolenaar (void)Dir_MTime(gn, 0); 4473955d011SMarcel Moolenaar Make_TimeStamp(pgn, gn); 4483955d011SMarcel Moolenaar pgn->unmade--; 4493955d011SMarcel Moolenaar 4503841c287SSimon J. Gerraty return 0; 4513955d011SMarcel Moolenaar } 452*2c3632d1SSimon J. Gerraty 453*2c3632d1SSimon J. Gerraty /* Called by Make_Run and SuffApplyTransform on the downward pass to handle 454*2c3632d1SSimon J. Gerraty * .USE and transformation nodes, by copying the child node's commands, type 455*2c3632d1SSimon J. Gerraty * flags and children to the parent node. 4563955d011SMarcel Moolenaar * 457*2c3632d1SSimon J. Gerraty * A .USE node is much like an explicit transformation rule, except its 458*2c3632d1SSimon J. Gerraty * commands are always added to the target node, even if the target already 459*2c3632d1SSimon J. Gerraty * has commands. 4603955d011SMarcel Moolenaar * 4613955d011SMarcel Moolenaar * Input: 4623955d011SMarcel Moolenaar * cgn The .USE node 4633955d011SMarcel Moolenaar * pgn The target of the .USE node 4643955d011SMarcel Moolenaar */ 4653955d011SMarcel Moolenaar void 4663955d011SMarcel Moolenaar Make_HandleUse(GNode *cgn, GNode *pgn) 4673955d011SMarcel Moolenaar { 4683955d011SMarcel Moolenaar LstNode ln; /* An element in the children list */ 4693955d011SMarcel Moolenaar 4703955d011SMarcel Moolenaar #ifdef DEBUG_SRC 4713955d011SMarcel Moolenaar if ((cgn->type & (OP_USE|OP_USEBEFORE|OP_TRANSFORM)) == 0) { 4723955d011SMarcel Moolenaar fprintf(debug_file, "Make_HandleUse: called for plain node %s\n", cgn->name); 4733955d011SMarcel Moolenaar return; 4743955d011SMarcel Moolenaar } 4753955d011SMarcel Moolenaar #endif 4763955d011SMarcel Moolenaar 4773955d011SMarcel Moolenaar if ((cgn->type & (OP_USE|OP_USEBEFORE)) || Lst_IsEmpty(pgn->commands)) { 4783955d011SMarcel Moolenaar if (cgn->type & OP_USEBEFORE) { 479*2c3632d1SSimon J. Gerraty /* .USEBEFORE */ 480*2c3632d1SSimon J. Gerraty Lst_PrependAll(pgn->commands, cgn->commands); 4813955d011SMarcel Moolenaar } else { 482*2c3632d1SSimon J. Gerraty /* .USE, or target has no commands */ 483*2c3632d1SSimon J. Gerraty Lst_AppendAll(pgn->commands, cgn->commands); 4843955d011SMarcel Moolenaar } 4853955d011SMarcel Moolenaar } 4863955d011SMarcel Moolenaar 487*2c3632d1SSimon J. Gerraty Lst_Open(cgn->children); 4883955d011SMarcel Moolenaar while ((ln = Lst_Next(cgn->children)) != NULL) { 489*2c3632d1SSimon J. Gerraty GNode *gn = LstNode_Datum(ln); 4903955d011SMarcel Moolenaar 4913955d011SMarcel Moolenaar /* 4923955d011SMarcel Moolenaar * Expand variables in the .USE node's name 4933955d011SMarcel Moolenaar * and save the unexpanded form. 4943955d011SMarcel Moolenaar * We don't need to do this for commands. 4953955d011SMarcel Moolenaar * They get expanded properly when we execute. 4963955d011SMarcel Moolenaar */ 4973955d011SMarcel Moolenaar if (gn->uname == NULL) { 4983955d011SMarcel Moolenaar gn->uname = gn->name; 4993955d011SMarcel Moolenaar } else { 5003955d011SMarcel Moolenaar free(gn->name); 5013955d011SMarcel Moolenaar } 502*2c3632d1SSimon J. Gerraty gn->name = Var_Subst(gn->uname, pgn, VARE_WANTRES); 503*2c3632d1SSimon J. Gerraty if (gn->uname && strcmp(gn->name, gn->uname) != 0) { 5043955d011SMarcel Moolenaar /* See if we have a target for this node. */ 505*2c3632d1SSimon J. Gerraty GNode *tgn = Targ_FindNode(gn->name, TARG_NOCREATE); 5063955d011SMarcel Moolenaar if (tgn != NULL) 5073955d011SMarcel Moolenaar gn = tgn; 5083955d011SMarcel Moolenaar } 5093955d011SMarcel Moolenaar 510*2c3632d1SSimon J. Gerraty Lst_Append(pgn->children, gn); 511*2c3632d1SSimon J. Gerraty Lst_Append(gn->parents, pgn); 5123955d011SMarcel Moolenaar pgn->unmade += 1; 5133955d011SMarcel Moolenaar } 5143955d011SMarcel Moolenaar Lst_Close(cgn->children); 5153955d011SMarcel Moolenaar 5163955d011SMarcel Moolenaar pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_USEBEFORE|OP_TRANSFORM); 5173955d011SMarcel Moolenaar } 5183955d011SMarcel Moolenaar 5193955d011SMarcel Moolenaar /*- 5203955d011SMarcel Moolenaar *----------------------------------------------------------------------- 5213955d011SMarcel Moolenaar * MakeHandleUse -- 5223955d011SMarcel Moolenaar * Callback function for Lst_ForEach, used by Make_Run on the downward 5233955d011SMarcel Moolenaar * pass to handle .USE nodes. Should be called before the children 5243955d011SMarcel Moolenaar * are enqueued to be looked at by MakeAddChild. 5253955d011SMarcel Moolenaar * This function calls Make_HandleUse to copy the .USE node's commands, 5263955d011SMarcel Moolenaar * type flags and children to the parent node. 5273955d011SMarcel Moolenaar * 5283955d011SMarcel Moolenaar * Input: 5293955d011SMarcel Moolenaar * cgnp the child we've just examined 5303955d011SMarcel Moolenaar * pgnp the current parent 5313955d011SMarcel Moolenaar * 5323955d011SMarcel Moolenaar * Results: 5333955d011SMarcel Moolenaar * returns 0. 5343955d011SMarcel Moolenaar * 5353955d011SMarcel Moolenaar * Side Effects: 5363955d011SMarcel Moolenaar * After expansion, .USE child nodes are removed from the parent 5373955d011SMarcel Moolenaar * 5383955d011SMarcel Moolenaar *----------------------------------------------------------------------- 5393955d011SMarcel Moolenaar */ 5403955d011SMarcel Moolenaar static int 5413955d011SMarcel Moolenaar MakeHandleUse(void *cgnp, void *pgnp) 5423955d011SMarcel Moolenaar { 5433955d011SMarcel Moolenaar GNode *cgn = (GNode *)cgnp; 5443955d011SMarcel Moolenaar GNode *pgn = (GNode *)pgnp; 5453955d011SMarcel Moolenaar LstNode ln; /* An element in the children list */ 5463955d011SMarcel Moolenaar int unmarked; 5473955d011SMarcel Moolenaar 5483955d011SMarcel Moolenaar unmarked = ((cgn->type & OP_MARK) == 0); 5493955d011SMarcel Moolenaar cgn->type |= OP_MARK; 5503955d011SMarcel Moolenaar 5513955d011SMarcel Moolenaar if ((cgn->type & (OP_USE|OP_USEBEFORE)) == 0) 5523841c287SSimon J. Gerraty return 0; 5533955d011SMarcel Moolenaar 5543955d011SMarcel Moolenaar if (unmarked) 5553955d011SMarcel Moolenaar Make_HandleUse(cgn, pgn); 5563955d011SMarcel Moolenaar 5573955d011SMarcel Moolenaar /* 5583955d011SMarcel Moolenaar * This child node is now "made", so we decrement the count of 5593955d011SMarcel Moolenaar * unmade children in the parent... We also remove the child 5603955d011SMarcel Moolenaar * from the parent's list to accurately reflect the number of decent 5613955d011SMarcel Moolenaar * children the parent has. This is used by Make_Run to decide 5623955d011SMarcel Moolenaar * whether to queue the parent or examine its children... 5633955d011SMarcel Moolenaar */ 564*2c3632d1SSimon J. Gerraty if ((ln = Lst_FindDatum(pgn->children, cgn)) != NULL) { 5653955d011SMarcel Moolenaar Lst_Remove(pgn->children, ln); 5663955d011SMarcel Moolenaar pgn->unmade--; 5673955d011SMarcel Moolenaar } 5683841c287SSimon J. Gerraty return 0; 5693955d011SMarcel Moolenaar } 5703955d011SMarcel Moolenaar 5713955d011SMarcel Moolenaar 5723955d011SMarcel Moolenaar /*- 5733955d011SMarcel Moolenaar *----------------------------------------------------------------------- 5743955d011SMarcel Moolenaar * Make_Recheck -- 5753955d011SMarcel Moolenaar * Check the modification time of a gnode, and update it as described 5763955d011SMarcel Moolenaar * in the comments below. 5773955d011SMarcel Moolenaar * 5783955d011SMarcel Moolenaar * Results: 579db29cad8SSimon J. Gerraty * returns 0 if the gnode does not exist, or its filesystem 5803955d011SMarcel Moolenaar * time if it does. 5813955d011SMarcel Moolenaar * 5823955d011SMarcel Moolenaar * Side Effects: 5833955d011SMarcel Moolenaar * the gnode's modification time and path name are affected. 5843955d011SMarcel Moolenaar * 5853955d011SMarcel Moolenaar *----------------------------------------------------------------------- 5863955d011SMarcel Moolenaar */ 5873955d011SMarcel Moolenaar time_t 5883955d011SMarcel Moolenaar Make_Recheck(GNode *gn) 5893955d011SMarcel Moolenaar { 5903955d011SMarcel Moolenaar time_t mtime = Dir_MTime(gn, 1); 5913955d011SMarcel Moolenaar 5923955d011SMarcel Moolenaar #ifndef RECHECK 5933955d011SMarcel Moolenaar /* 5943955d011SMarcel Moolenaar * We can't re-stat the thing, but we can at least take care of rules 5953955d011SMarcel Moolenaar * where a target depends on a source that actually creates the 5963955d011SMarcel Moolenaar * target, but only if it has changed, e.g. 5973955d011SMarcel Moolenaar * 5983955d011SMarcel Moolenaar * parse.h : parse.o 5993955d011SMarcel Moolenaar * 6003955d011SMarcel Moolenaar * parse.o : parse.y 6013955d011SMarcel Moolenaar * yacc -d parse.y 6023955d011SMarcel Moolenaar * cc -c y.tab.c 6033955d011SMarcel Moolenaar * mv y.tab.o parse.o 6043955d011SMarcel Moolenaar * cmp -s y.tab.h parse.h || mv y.tab.h parse.h 6053955d011SMarcel Moolenaar * 6063955d011SMarcel Moolenaar * In this case, if the definitions produced by yacc haven't changed 6073955d011SMarcel Moolenaar * from before, parse.h won't have been updated and gn->mtime will 6083955d011SMarcel Moolenaar * reflect the current modification time for parse.h. This is 6093955d011SMarcel Moolenaar * something of a kludge, I admit, but it's a useful one.. 6103955d011SMarcel Moolenaar * XXX: People like to use a rule like 6113955d011SMarcel Moolenaar * 6123955d011SMarcel Moolenaar * FRC: 6133955d011SMarcel Moolenaar * 6143955d011SMarcel Moolenaar * To force things that depend on FRC to be made, so we have to 6153955d011SMarcel Moolenaar * check for gn->children being empty as well... 6163955d011SMarcel Moolenaar */ 6173955d011SMarcel Moolenaar if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) { 6183955d011SMarcel Moolenaar gn->mtime = now; 6193955d011SMarcel Moolenaar } 6203955d011SMarcel Moolenaar #else 6213955d011SMarcel Moolenaar /* 6223955d011SMarcel Moolenaar * This is what Make does and it's actually a good thing, as it 6233955d011SMarcel Moolenaar * allows rules like 6243955d011SMarcel Moolenaar * 6253955d011SMarcel Moolenaar * cmp -s y.tab.h parse.h || cp y.tab.h parse.h 6263955d011SMarcel Moolenaar * 6273955d011SMarcel Moolenaar * to function as intended. Unfortunately, thanks to the stateless 6283955d011SMarcel Moolenaar * nature of NFS (by which I mean the loose coupling of two clients 6293955d011SMarcel Moolenaar * using the same file from a common server), there are times 6303955d011SMarcel Moolenaar * when the modification time of a file created on a remote 6313955d011SMarcel Moolenaar * machine will not be modified before the local stat() implied by 6323955d011SMarcel Moolenaar * the Dir_MTime occurs, thus leading us to believe that the file 6333955d011SMarcel Moolenaar * is unchanged, wreaking havoc with files that depend on this one. 6343955d011SMarcel Moolenaar * 6353955d011SMarcel Moolenaar * I have decided it is better to make too much than to make too 6363955d011SMarcel Moolenaar * little, so this stuff is commented out unless you're sure it's ok. 6373955d011SMarcel Moolenaar * -- ardeb 1/12/88 6383955d011SMarcel Moolenaar */ 6393955d011SMarcel Moolenaar /* 6403955d011SMarcel Moolenaar * Christos, 4/9/92: If we are saving commands pretend that 6413955d011SMarcel Moolenaar * the target is made now. Otherwise archives with ... rules 6423955d011SMarcel Moolenaar * don't work! 6433955d011SMarcel Moolenaar */ 6443955d011SMarcel Moolenaar if (NoExecute(gn) || (gn->type & OP_SAVE_CMDS) || 6453955d011SMarcel Moolenaar (mtime == 0 && !(gn->type & OP_WAIT))) { 6463955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 6473955d011SMarcel Moolenaar fprintf(debug_file, " recheck(%s): update time from %s to now\n", 6483955d011SMarcel Moolenaar gn->name, Targ_FmtTime(gn->mtime)); 6493955d011SMarcel Moolenaar } 6503955d011SMarcel Moolenaar gn->mtime = now; 6513955d011SMarcel Moolenaar } 6523955d011SMarcel Moolenaar else { 6533955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 6543955d011SMarcel Moolenaar fprintf(debug_file, " recheck(%s): current update time: %s\n", 6553955d011SMarcel Moolenaar gn->name, Targ_FmtTime(gn->mtime)); 6563955d011SMarcel Moolenaar } 6573955d011SMarcel Moolenaar } 6583955d011SMarcel Moolenaar #endif 6593955d011SMarcel Moolenaar return mtime; 6603955d011SMarcel Moolenaar } 6613955d011SMarcel Moolenaar 6623955d011SMarcel Moolenaar /*- 6633955d011SMarcel Moolenaar *----------------------------------------------------------------------- 6643955d011SMarcel Moolenaar * Make_Update -- 6653955d011SMarcel Moolenaar * Perform update on the parents of a node. Used by JobFinish once 6663955d011SMarcel Moolenaar * a node has been dealt with and by MakeStartJobs if it finds an 6673955d011SMarcel Moolenaar * up-to-date node. 6683955d011SMarcel Moolenaar * 6693955d011SMarcel Moolenaar * Input: 6703955d011SMarcel Moolenaar * cgn the child node 6713955d011SMarcel Moolenaar * 6723955d011SMarcel Moolenaar * Results: 6733955d011SMarcel Moolenaar * Always returns 0 6743955d011SMarcel Moolenaar * 6753955d011SMarcel Moolenaar * Side Effects: 6763955d011SMarcel Moolenaar * The unmade field of pgn is decremented and pgn may be placed on 6773955d011SMarcel Moolenaar * the toBeMade queue if this field becomes 0. 6783955d011SMarcel Moolenaar * 6793955d011SMarcel Moolenaar * If the child was made, the parent's flag CHILDMADE field will be 6803955d011SMarcel Moolenaar * set true. 6813955d011SMarcel Moolenaar * 6823955d011SMarcel Moolenaar * If the child is not up-to-date and still does not exist, 6833955d011SMarcel Moolenaar * set the FORCE flag on the parents. 6843955d011SMarcel Moolenaar * 6853955d011SMarcel Moolenaar * If the child wasn't made, the cmgn field of the parent will be 6863955d011SMarcel Moolenaar * altered if the child's mtime is big enough. 6873955d011SMarcel Moolenaar * 6883955d011SMarcel Moolenaar * Finally, if the child is the implied source for the parent, the 6893955d011SMarcel Moolenaar * parent's IMPSRC variable is set appropriately. 6903955d011SMarcel Moolenaar * 6913955d011SMarcel Moolenaar *----------------------------------------------------------------------- 6923955d011SMarcel Moolenaar */ 6933955d011SMarcel Moolenaar void 6943955d011SMarcel Moolenaar Make_Update(GNode *cgn) 6953955d011SMarcel Moolenaar { 6963955d011SMarcel Moolenaar GNode *pgn; /* the parent node */ 697*2c3632d1SSimon J. Gerraty const char *cname; /* the child's name */ 698*2c3632d1SSimon J. Gerraty LstNode ln; /* Element in parents and implicitParents lists */ 6993955d011SMarcel Moolenaar time_t mtime = -1; 7003955d011SMarcel Moolenaar char *p1; 7013955d011SMarcel Moolenaar Lst parents; 7023955d011SMarcel Moolenaar GNode *centurion; 7033955d011SMarcel Moolenaar 7043955d011SMarcel Moolenaar /* It is save to re-examine any nodes again */ 7053955d011SMarcel Moolenaar checked++; 7063955d011SMarcel Moolenaar 7073955d011SMarcel Moolenaar cname = Var_Value(TARGET, cgn, &p1); 708*2c3632d1SSimon J. Gerraty bmake_free(p1); 7093955d011SMarcel Moolenaar 7103955d011SMarcel Moolenaar if (DEBUG(MAKE)) 7113955d011SMarcel Moolenaar fprintf(debug_file, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num); 7123955d011SMarcel Moolenaar 7133955d011SMarcel Moolenaar /* 7143955d011SMarcel Moolenaar * If the child was actually made, see what its modification time is 7153955d011SMarcel Moolenaar * now -- some rules won't actually update the file. If the file still 7163955d011SMarcel Moolenaar * doesn't exist, make its mtime now. 7173955d011SMarcel Moolenaar */ 7183955d011SMarcel Moolenaar if (cgn->made != UPTODATE) { 7193955d011SMarcel Moolenaar mtime = Make_Recheck(cgn); 7203955d011SMarcel Moolenaar } 7213955d011SMarcel Moolenaar 7223955d011SMarcel Moolenaar /* 7233955d011SMarcel Moolenaar * If this is a `::' node, we must consult its first instance 7243955d011SMarcel Moolenaar * which is where all parents are linked. 7253955d011SMarcel Moolenaar */ 7263955d011SMarcel Moolenaar if ((centurion = cgn->centurion) != NULL) { 7273955d011SMarcel Moolenaar if (!Lst_IsEmpty(cgn->parents)) 7283955d011SMarcel Moolenaar Punt("%s%s: cohort has parents", cgn->name, cgn->cohort_num); 7293955d011SMarcel Moolenaar centurion->unmade_cohorts -= 1; 7303955d011SMarcel Moolenaar if (centurion->unmade_cohorts < 0) 7313955d011SMarcel Moolenaar Error("Graph cycles through centurion %s", centurion->name); 7323955d011SMarcel Moolenaar } else { 7333955d011SMarcel Moolenaar centurion = cgn; 7343955d011SMarcel Moolenaar } 7353955d011SMarcel Moolenaar parents = centurion->parents; 7363955d011SMarcel Moolenaar 7373955d011SMarcel Moolenaar /* If this was a .ORDER node, schedule the RHS */ 7383955d011SMarcel Moolenaar Lst_ForEach(centurion->order_succ, MakeBuildParent, Lst_First(toBeMade)); 7393955d011SMarcel Moolenaar 7403955d011SMarcel Moolenaar /* Now mark all the parents as having one less unmade child */ 741*2c3632d1SSimon J. Gerraty Lst_Open(parents); 7423955d011SMarcel Moolenaar while ((ln = Lst_Next(parents)) != NULL) { 743*2c3632d1SSimon J. Gerraty pgn = LstNode_Datum(ln); 7443955d011SMarcel Moolenaar if (DEBUG(MAKE)) 7453955d011SMarcel Moolenaar fprintf(debug_file, "inspect parent %s%s: flags %x, " 7463955d011SMarcel Moolenaar "type %x, made %d, unmade %d ", 7473955d011SMarcel Moolenaar pgn->name, pgn->cohort_num, pgn->flags, 7483955d011SMarcel Moolenaar pgn->type, pgn->made, pgn->unmade-1); 7493955d011SMarcel Moolenaar 7503955d011SMarcel Moolenaar if (!(pgn->flags & REMAKE)) { 7513955d011SMarcel Moolenaar /* This parent isn't needed */ 7523955d011SMarcel Moolenaar if (DEBUG(MAKE)) 7533955d011SMarcel Moolenaar fprintf(debug_file, "- not needed\n"); 7543955d011SMarcel Moolenaar continue; 7553955d011SMarcel Moolenaar } 7563955d011SMarcel Moolenaar if (mtime == 0 && !(cgn->type & OP_WAIT)) 7573955d011SMarcel Moolenaar pgn->flags |= FORCE; 7583955d011SMarcel Moolenaar 7593955d011SMarcel Moolenaar /* 7603955d011SMarcel Moolenaar * If the parent has the .MADE attribute, its timestamp got 7613955d011SMarcel Moolenaar * updated to that of its newest child, and its unmake 7623955d011SMarcel Moolenaar * child count got set to zero in Make_ExpandUse(). 7633955d011SMarcel Moolenaar * However other things might cause us to build one of its 7643955d011SMarcel Moolenaar * children - and so we mustn't do any processing here when 7653955d011SMarcel Moolenaar * the child build finishes. 7663955d011SMarcel Moolenaar */ 7673955d011SMarcel Moolenaar if (pgn->type & OP_MADE) { 7683955d011SMarcel Moolenaar if (DEBUG(MAKE)) 7693955d011SMarcel Moolenaar fprintf(debug_file, "- .MADE\n"); 7703955d011SMarcel Moolenaar continue; 7713955d011SMarcel Moolenaar } 7723955d011SMarcel Moolenaar 7733955d011SMarcel Moolenaar if ( ! (cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE))) { 7743955d011SMarcel Moolenaar if (cgn->made == MADE) 7753955d011SMarcel Moolenaar pgn->flags |= CHILDMADE; 7763955d011SMarcel Moolenaar (void)Make_TimeStamp(pgn, cgn); 7773955d011SMarcel Moolenaar } 7783955d011SMarcel Moolenaar 7793955d011SMarcel Moolenaar /* 7803955d011SMarcel Moolenaar * A parent must wait for the completion of all instances 7813955d011SMarcel Moolenaar * of a `::' dependency. 7823955d011SMarcel Moolenaar */ 7833955d011SMarcel Moolenaar if (centurion->unmade_cohorts != 0 || centurion->made < MADE) { 7843955d011SMarcel Moolenaar if (DEBUG(MAKE)) 7853955d011SMarcel Moolenaar fprintf(debug_file, 7863955d011SMarcel Moolenaar "- centurion made %d, %d unmade cohorts\n", 7873955d011SMarcel Moolenaar centurion->made, centurion->unmade_cohorts); 7883955d011SMarcel Moolenaar continue; 7893955d011SMarcel Moolenaar } 7903955d011SMarcel Moolenaar 7913955d011SMarcel Moolenaar /* One more child of this parent is now made */ 7923955d011SMarcel Moolenaar pgn->unmade -= 1; 7933955d011SMarcel Moolenaar if (pgn->unmade < 0) { 7943955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 7953955d011SMarcel Moolenaar fprintf(debug_file, "Graph cycles through %s%s\n", 7963955d011SMarcel Moolenaar pgn->name, pgn->cohort_num); 7973955d011SMarcel Moolenaar Targ_PrintGraph(2); 7983955d011SMarcel Moolenaar } 7993955d011SMarcel Moolenaar Error("Graph cycles through %s%s", pgn->name, pgn->cohort_num); 8003955d011SMarcel Moolenaar } 8013955d011SMarcel Moolenaar 8023955d011SMarcel Moolenaar /* We must always rescan the parents of .WAIT and .ORDER nodes. */ 8033955d011SMarcel Moolenaar if (pgn->unmade != 0 && !(centurion->type & OP_WAIT) 8043955d011SMarcel Moolenaar && !(centurion->flags & DONE_ORDER)) { 8053955d011SMarcel Moolenaar if (DEBUG(MAKE)) 8063955d011SMarcel Moolenaar fprintf(debug_file, "- unmade children\n"); 8073955d011SMarcel Moolenaar continue; 8083955d011SMarcel Moolenaar } 8093955d011SMarcel Moolenaar if (pgn->made != DEFERRED) { 8103955d011SMarcel Moolenaar /* 8113955d011SMarcel Moolenaar * Either this parent is on a different branch of the tree, 8123955d011SMarcel Moolenaar * or it on the RHS of a .WAIT directive 8133955d011SMarcel Moolenaar * or it is already on the toBeMade list. 8143955d011SMarcel Moolenaar */ 8153955d011SMarcel Moolenaar if (DEBUG(MAKE)) 8163955d011SMarcel Moolenaar fprintf(debug_file, "- not deferred\n"); 8173955d011SMarcel Moolenaar continue; 8183955d011SMarcel Moolenaar } 819*2c3632d1SSimon J. Gerraty assert(pgn->order_pred != NULL); 820*2c3632d1SSimon J. Gerraty if (Lst_ForEach(pgn->order_pred, MakeCheckOrder, 0)) { 8213955d011SMarcel Moolenaar /* A .ORDER rule stops us building this */ 8223955d011SMarcel Moolenaar continue; 8233955d011SMarcel Moolenaar } 8243955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 8253955d011SMarcel Moolenaar static int two = 2; 8263955d011SMarcel Moolenaar fprintf(debug_file, "- %s%s made, schedule %s%s (made %d)\n", 8273955d011SMarcel Moolenaar cgn->name, cgn->cohort_num, 8283955d011SMarcel Moolenaar pgn->name, pgn->cohort_num, pgn->made); 8293955d011SMarcel Moolenaar Targ_PrintNode(pgn, &two); 8303955d011SMarcel Moolenaar } 8313955d011SMarcel Moolenaar /* Ok, we can schedule the parent again */ 8323955d011SMarcel Moolenaar pgn->made = REQUESTED; 833*2c3632d1SSimon J. Gerraty Lst_Enqueue(toBeMade, pgn); 8343955d011SMarcel Moolenaar } 8353955d011SMarcel Moolenaar Lst_Close(parents); 8363955d011SMarcel Moolenaar 8373955d011SMarcel Moolenaar /* 8383955d011SMarcel Moolenaar * Set the .PREFIX and .IMPSRC variables for all the implied parents 8393955d011SMarcel Moolenaar * of this node. 8403955d011SMarcel Moolenaar */ 841*2c3632d1SSimon J. Gerraty Lst_Open(cgn->implicitParents); 842*2c3632d1SSimon J. Gerraty { 843*2c3632d1SSimon J. Gerraty const char *cpref = Var_Value(PREFIX, cgn, &p1); 8443955d011SMarcel Moolenaar 845*2c3632d1SSimon J. Gerraty while ((ln = Lst_Next(cgn->implicitParents)) != NULL) { 846*2c3632d1SSimon J. Gerraty pgn = LstNode_Datum(ln); 8473955d011SMarcel Moolenaar if (pgn->flags & REMAKE) { 8483841c287SSimon J. Gerraty Var_Set(IMPSRC, cname, pgn); 8493955d011SMarcel Moolenaar if (cpref != NULL) 8503841c287SSimon J. Gerraty Var_Set(PREFIX, cpref, pgn); 8513955d011SMarcel Moolenaar } 8523955d011SMarcel Moolenaar } 853*2c3632d1SSimon J. Gerraty bmake_free(p1); 854*2c3632d1SSimon J. Gerraty Lst_Close(cgn->implicitParents); 8553955d011SMarcel Moolenaar } 8563955d011SMarcel Moolenaar } 857*2c3632d1SSimon J. Gerraty 8583955d011SMarcel Moolenaar /*- 8593955d011SMarcel Moolenaar *----------------------------------------------------------------------- 8603955d011SMarcel Moolenaar * MakeAddAllSrc -- 8613955d011SMarcel Moolenaar * Add a child's name to the ALLSRC and OODATE variables of the given 8623955d011SMarcel Moolenaar * node. Called from Make_DoAllVar via Lst_ForEach. A child is added only 8633955d011SMarcel Moolenaar * if it has not been given the .EXEC, .USE or .INVISIBLE attributes. 8643955d011SMarcel Moolenaar * .EXEC and .USE children are very rarely going to be files, so... 8653955d011SMarcel Moolenaar * If the child is a .JOIN node, its ALLSRC is propagated to the parent. 8663955d011SMarcel Moolenaar * 8673955d011SMarcel Moolenaar * A child is added to the OODATE variable if its modification time is 8683955d011SMarcel Moolenaar * later than that of its parent, as defined by Make, except if the 8693955d011SMarcel Moolenaar * parent is a .JOIN node. In that case, it is only added to the OODATE 8703955d011SMarcel Moolenaar * variable if it was actually made (since .JOIN nodes don't have 8713955d011SMarcel Moolenaar * modification times, the comparison is rather unfair...).. 8723955d011SMarcel Moolenaar * 8733955d011SMarcel Moolenaar * Results: 8743955d011SMarcel Moolenaar * Always returns 0 8753955d011SMarcel Moolenaar * 8763955d011SMarcel Moolenaar * Side Effects: 8773955d011SMarcel Moolenaar * The ALLSRC variable for the given node is extended. 8783955d011SMarcel Moolenaar *----------------------------------------------------------------------- 8793955d011SMarcel Moolenaar */ 8803955d011SMarcel Moolenaar static int 8813955d011SMarcel Moolenaar MakeUnmark(void *cgnp, void *pgnp MAKE_ATTR_UNUSED) 8823955d011SMarcel Moolenaar { 8833955d011SMarcel Moolenaar GNode *cgn = (GNode *)cgnp; 8843955d011SMarcel Moolenaar 8853955d011SMarcel Moolenaar cgn->type &= ~OP_MARK; 8863841c287SSimon J. Gerraty return 0; 8873955d011SMarcel Moolenaar } 8883955d011SMarcel Moolenaar 8893955d011SMarcel Moolenaar /* 8903955d011SMarcel Moolenaar * Input: 8913955d011SMarcel Moolenaar * cgnp The child to add 8923955d011SMarcel Moolenaar * pgnp The parent to whose ALLSRC variable it should 8933955d011SMarcel Moolenaar * be added 8943955d011SMarcel Moolenaar * 8953955d011SMarcel Moolenaar */ 8963955d011SMarcel Moolenaar static int 8973955d011SMarcel Moolenaar MakeAddAllSrc(void *cgnp, void *pgnp) 8983955d011SMarcel Moolenaar { 8993955d011SMarcel Moolenaar GNode *cgn = (GNode *)cgnp; 9003955d011SMarcel Moolenaar GNode *pgn = (GNode *)pgnp; 9013955d011SMarcel Moolenaar 9023955d011SMarcel Moolenaar if (cgn->type & OP_MARK) 9033841c287SSimon J. Gerraty return 0; 9043955d011SMarcel Moolenaar cgn->type |= OP_MARK; 9053955d011SMarcel Moolenaar 9063955d011SMarcel Moolenaar if ((cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE|OP_INVISIBLE)) == 0) { 907*2c3632d1SSimon J. Gerraty const char *child, *allsrc; 9083955d011SMarcel Moolenaar char *p1 = NULL, *p2 = NULL; 9093955d011SMarcel Moolenaar 9103955d011SMarcel Moolenaar if (cgn->type & OP_ARCHV) 9113955d011SMarcel Moolenaar child = Var_Value(MEMBER, cgn, &p1); 9123955d011SMarcel Moolenaar else 9133955d011SMarcel Moolenaar child = cgn->path ? cgn->path : cgn->name; 9143955d011SMarcel Moolenaar if (cgn->type & OP_JOIN) { 9153955d011SMarcel Moolenaar allsrc = Var_Value(ALLSRC, cgn, &p2); 9163955d011SMarcel Moolenaar } else { 9173955d011SMarcel Moolenaar allsrc = child; 9183955d011SMarcel Moolenaar } 9193955d011SMarcel Moolenaar if (allsrc != NULL) 9203955d011SMarcel Moolenaar Var_Append(ALLSRC, allsrc, pgn); 921*2c3632d1SSimon J. Gerraty bmake_free(p2); 9223955d011SMarcel Moolenaar if (pgn->type & OP_JOIN) { 9233955d011SMarcel Moolenaar if (cgn->made == MADE) { 9243955d011SMarcel Moolenaar Var_Append(OODATE, child, pgn); 9253955d011SMarcel Moolenaar } 9263955d011SMarcel Moolenaar } else if ((pgn->mtime < cgn->mtime) || 9273955d011SMarcel Moolenaar (cgn->mtime >= now && cgn->made == MADE)) 9283955d011SMarcel Moolenaar { 9293955d011SMarcel Moolenaar /* 9303955d011SMarcel Moolenaar * It goes in the OODATE variable if the parent is younger than the 9313955d011SMarcel Moolenaar * child or if the child has been modified more recently than 9323955d011SMarcel Moolenaar * the start of the make. This is to keep pmake from getting 9333955d011SMarcel Moolenaar * confused if something else updates the parent after the 9343955d011SMarcel Moolenaar * make starts (shouldn't happen, I know, but sometimes it 9353955d011SMarcel Moolenaar * does). In such a case, if we've updated the kid, the parent 9363955d011SMarcel Moolenaar * is likely to have a modification time later than that of 9373955d011SMarcel Moolenaar * the kid and anything that relies on the OODATE variable will 9383955d011SMarcel Moolenaar * be hosed. 9393955d011SMarcel Moolenaar * 9403955d011SMarcel Moolenaar * XXX: This will cause all made children to go in the OODATE 9413955d011SMarcel Moolenaar * variable, even if they're not touched, if RECHECK isn't defined, 9423955d011SMarcel Moolenaar * since cgn->mtime is set to now in Make_Update. According to 9433955d011SMarcel Moolenaar * some people, this is good... 9443955d011SMarcel Moolenaar */ 9453955d011SMarcel Moolenaar Var_Append(OODATE, child, pgn); 9463955d011SMarcel Moolenaar } 947*2c3632d1SSimon J. Gerraty bmake_free(p1); 9483955d011SMarcel Moolenaar } 9493841c287SSimon J. Gerraty return 0; 9503955d011SMarcel Moolenaar } 951*2c3632d1SSimon J. Gerraty 9523955d011SMarcel Moolenaar /*- 9533955d011SMarcel Moolenaar *----------------------------------------------------------------------- 9543955d011SMarcel Moolenaar * Make_DoAllVar -- 9553955d011SMarcel Moolenaar * Set up the ALLSRC and OODATE variables. Sad to say, it must be 9563955d011SMarcel Moolenaar * done separately, rather than while traversing the graph. This is 9573955d011SMarcel Moolenaar * because Make defined OODATE to contain all sources whose modification 9583955d011SMarcel Moolenaar * times were later than that of the target, *not* those sources that 9593955d011SMarcel Moolenaar * were out-of-date. Since in both compatibility and native modes, 9603955d011SMarcel Moolenaar * the modification time of the parent isn't found until the child 9613955d011SMarcel Moolenaar * has been dealt with, we have to wait until now to fill in the 9623955d011SMarcel Moolenaar * variable. As for ALLSRC, the ordering is important and not 9633955d011SMarcel Moolenaar * guaranteed when in native mode, so it must be set here, too. 9643955d011SMarcel Moolenaar * 9653955d011SMarcel Moolenaar * Results: 9663955d011SMarcel Moolenaar * None 9673955d011SMarcel Moolenaar * 9683955d011SMarcel Moolenaar * Side Effects: 9693955d011SMarcel Moolenaar * The ALLSRC and OODATE variables of the given node is filled in. 9703955d011SMarcel Moolenaar * If the node is a .JOIN node, its TARGET variable will be set to 9713955d011SMarcel Moolenaar * match its ALLSRC variable. 9723955d011SMarcel Moolenaar *----------------------------------------------------------------------- 9733955d011SMarcel Moolenaar */ 9743955d011SMarcel Moolenaar void 9753955d011SMarcel Moolenaar Make_DoAllVar(GNode *gn) 9763955d011SMarcel Moolenaar { 9773955d011SMarcel Moolenaar if (gn->flags & DONE_ALLSRC) 9783955d011SMarcel Moolenaar return; 9793955d011SMarcel Moolenaar 9803955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeUnmark, gn); 9813955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeAddAllSrc, gn); 9823955d011SMarcel Moolenaar 9833955d011SMarcel Moolenaar if (!Var_Exists (OODATE, gn)) { 9843841c287SSimon J. Gerraty Var_Set(OODATE, "", gn); 9853955d011SMarcel Moolenaar } 9863955d011SMarcel Moolenaar if (!Var_Exists (ALLSRC, gn)) { 9873841c287SSimon J. Gerraty Var_Set(ALLSRC, "", gn); 9883955d011SMarcel Moolenaar } 9893955d011SMarcel Moolenaar 9903955d011SMarcel Moolenaar if (gn->type & OP_JOIN) { 9913955d011SMarcel Moolenaar char *p1; 9923841c287SSimon J. Gerraty Var_Set(TARGET, Var_Value(ALLSRC, gn, &p1), gn); 993*2c3632d1SSimon J. Gerraty bmake_free(p1); 9943955d011SMarcel Moolenaar } 9953955d011SMarcel Moolenaar gn->flags |= DONE_ALLSRC; 9963955d011SMarcel Moolenaar } 997*2c3632d1SSimon J. Gerraty 9983955d011SMarcel Moolenaar /*- 9993955d011SMarcel Moolenaar *----------------------------------------------------------------------- 10003955d011SMarcel Moolenaar * MakeStartJobs -- 10013955d011SMarcel Moolenaar * Start as many jobs as possible. 10023955d011SMarcel Moolenaar * 10033955d011SMarcel Moolenaar * Results: 10043955d011SMarcel Moolenaar * If the query flag was given to pmake, no job will be started, 10053955d011SMarcel Moolenaar * but as soon as an out-of-date target is found, this function 10063955d011SMarcel Moolenaar * returns TRUE. At all other times, this function returns FALSE. 10073955d011SMarcel Moolenaar * 10083955d011SMarcel Moolenaar * Side Effects: 10093955d011SMarcel Moolenaar * Nodes are removed from the toBeMade queue and job table slots 10103955d011SMarcel Moolenaar * are filled. 10113955d011SMarcel Moolenaar * 10123955d011SMarcel Moolenaar *----------------------------------------------------------------------- 10133955d011SMarcel Moolenaar */ 10143955d011SMarcel Moolenaar 10153955d011SMarcel Moolenaar static int 10163955d011SMarcel Moolenaar MakeCheckOrder(void *v_bn, void *ignore MAKE_ATTR_UNUSED) 10173955d011SMarcel Moolenaar { 10183955d011SMarcel Moolenaar GNode *bn = v_bn; 10193955d011SMarcel Moolenaar 10203955d011SMarcel Moolenaar if (bn->made >= MADE || !(bn->flags & REMAKE)) 10213955d011SMarcel Moolenaar return 0; 10223955d011SMarcel Moolenaar if (DEBUG(MAKE)) 10233955d011SMarcel Moolenaar fprintf(debug_file, "MakeCheckOrder: Waiting for .ORDER node %s%s\n", 10243955d011SMarcel Moolenaar bn->name, bn->cohort_num); 10253955d011SMarcel Moolenaar return 1; 10263955d011SMarcel Moolenaar } 10273955d011SMarcel Moolenaar 10283955d011SMarcel Moolenaar static int 10293955d011SMarcel Moolenaar MakeBuildChild(void *v_cn, void *toBeMade_next) 10303955d011SMarcel Moolenaar { 10313955d011SMarcel Moolenaar GNode *cn = v_cn; 10323955d011SMarcel Moolenaar 10333955d011SMarcel Moolenaar if (DEBUG(MAKE)) 10343955d011SMarcel Moolenaar fprintf(debug_file, "MakeBuildChild: inspect %s%s, made %d, type %x\n", 10353955d011SMarcel Moolenaar cn->name, cn->cohort_num, cn->made, cn->type); 10363955d011SMarcel Moolenaar if (cn->made > DEFERRED) 10373955d011SMarcel Moolenaar return 0; 10383955d011SMarcel Moolenaar 10393955d011SMarcel Moolenaar /* If this node is on the RHS of a .ORDER, check LHSs. */ 1040*2c3632d1SSimon J. Gerraty assert(cn->order_pred); 1041*2c3632d1SSimon J. Gerraty if (Lst_ForEach(cn->order_pred, MakeCheckOrder, 0)) { 10423955d011SMarcel Moolenaar /* Can't build this (or anything else in this child list) yet */ 10433955d011SMarcel Moolenaar cn->made = DEFERRED; 104459a02420SSimon J. Gerraty return 0; /* but keep looking */ 10453955d011SMarcel Moolenaar } 10463955d011SMarcel Moolenaar 10473955d011SMarcel Moolenaar if (DEBUG(MAKE)) 10483955d011SMarcel Moolenaar fprintf(debug_file, "MakeBuildChild: schedule %s%s\n", 10493955d011SMarcel Moolenaar cn->name, cn->cohort_num); 10503955d011SMarcel Moolenaar 10513955d011SMarcel Moolenaar cn->made = REQUESTED; 10523955d011SMarcel Moolenaar if (toBeMade_next == NULL) 1053*2c3632d1SSimon J. Gerraty Lst_Append(toBeMade, cn); 10543955d011SMarcel Moolenaar else 10553955d011SMarcel Moolenaar Lst_InsertBefore(toBeMade, toBeMade_next, cn); 10563955d011SMarcel Moolenaar 10573955d011SMarcel Moolenaar if (cn->unmade_cohorts != 0) 10583955d011SMarcel Moolenaar Lst_ForEach(cn->cohorts, MakeBuildChild, toBeMade_next); 10593955d011SMarcel Moolenaar 10603955d011SMarcel Moolenaar /* 10613955d011SMarcel Moolenaar * If this node is a .WAIT node with unmade chlidren 10623955d011SMarcel Moolenaar * then don't add the next sibling. 10633955d011SMarcel Moolenaar */ 10643955d011SMarcel Moolenaar return cn->type & OP_WAIT && cn->unmade > 0; 10653955d011SMarcel Moolenaar } 10663955d011SMarcel Moolenaar 106759a02420SSimon J. Gerraty /* When a .ORDER LHS node completes we do this on each RHS */ 10683955d011SMarcel Moolenaar static int 10693955d011SMarcel Moolenaar MakeBuildParent(void *v_pn, void *toBeMade_next) 10703955d011SMarcel Moolenaar { 10713955d011SMarcel Moolenaar GNode *pn = v_pn; 10723955d011SMarcel Moolenaar 10733955d011SMarcel Moolenaar if (pn->made != DEFERRED) 10743955d011SMarcel Moolenaar return 0; 10753955d011SMarcel Moolenaar 10763955d011SMarcel Moolenaar if (MakeBuildChild(pn, toBeMade_next) == 0) { 10773955d011SMarcel Moolenaar /* Mark so that when this node is built we reschedule its parents */ 10783955d011SMarcel Moolenaar pn->flags |= DONE_ORDER; 10793955d011SMarcel Moolenaar } 10803955d011SMarcel Moolenaar 10813955d011SMarcel Moolenaar return 0; 10823955d011SMarcel Moolenaar } 10833955d011SMarcel Moolenaar 10843955d011SMarcel Moolenaar static Boolean 10853955d011SMarcel Moolenaar MakeStartJobs(void) 10863955d011SMarcel Moolenaar { 10873955d011SMarcel Moolenaar GNode *gn; 10883955d011SMarcel Moolenaar int have_token = 0; 10893955d011SMarcel Moolenaar 10903955d011SMarcel Moolenaar while (!Lst_IsEmpty(toBeMade)) { 10913955d011SMarcel Moolenaar /* Get token now to avoid cycling job-list when we only have 1 token */ 10923955d011SMarcel Moolenaar if (!have_token && !Job_TokenWithdraw()) 10933955d011SMarcel Moolenaar break; 10943955d011SMarcel Moolenaar have_token = 1; 10953955d011SMarcel Moolenaar 1096*2c3632d1SSimon J. Gerraty gn = Lst_Dequeue(toBeMade); 10973955d011SMarcel Moolenaar if (DEBUG(MAKE)) 10983955d011SMarcel Moolenaar fprintf(debug_file, "Examining %s%s...\n", 10993955d011SMarcel Moolenaar gn->name, gn->cohort_num); 11003955d011SMarcel Moolenaar 11013955d011SMarcel Moolenaar if (gn->made != REQUESTED) { 11023955d011SMarcel Moolenaar if (DEBUG(MAKE)) 11033955d011SMarcel Moolenaar fprintf(debug_file, "state %d\n", gn->made); 11043955d011SMarcel Moolenaar 11053955d011SMarcel Moolenaar make_abort(gn, __LINE__); 11063955d011SMarcel Moolenaar } 11073955d011SMarcel Moolenaar 11083955d011SMarcel Moolenaar if (gn->checked == checked) { 11093955d011SMarcel Moolenaar /* We've already looked at this node since a job finished... */ 11103955d011SMarcel Moolenaar if (DEBUG(MAKE)) 11113955d011SMarcel Moolenaar fprintf(debug_file, "already checked %s%s\n", 11123955d011SMarcel Moolenaar gn->name, gn->cohort_num); 11133955d011SMarcel Moolenaar gn->made = DEFERRED; 11143955d011SMarcel Moolenaar continue; 11153955d011SMarcel Moolenaar } 11163955d011SMarcel Moolenaar gn->checked = checked; 11173955d011SMarcel Moolenaar 11183955d011SMarcel Moolenaar if (gn->unmade != 0) { 11193955d011SMarcel Moolenaar /* 11203955d011SMarcel Moolenaar * We can't build this yet, add all unmade children to toBeMade, 11213955d011SMarcel Moolenaar * just before the current first element. 11223955d011SMarcel Moolenaar */ 11233955d011SMarcel Moolenaar gn->made = DEFERRED; 11243955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeBuildChild, Lst_First(toBeMade)); 11253955d011SMarcel Moolenaar /* and drop this node on the floor */ 11263955d011SMarcel Moolenaar if (DEBUG(MAKE)) 11273955d011SMarcel Moolenaar fprintf(debug_file, "dropped %s%s\n", gn->name, gn->cohort_num); 11283955d011SMarcel Moolenaar continue; 11293955d011SMarcel Moolenaar } 11303955d011SMarcel Moolenaar 11313955d011SMarcel Moolenaar gn->made = BEINGMADE; 11323955d011SMarcel Moolenaar if (Make_OODate(gn)) { 11333955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 11343955d011SMarcel Moolenaar fprintf(debug_file, "out-of-date\n"); 11353955d011SMarcel Moolenaar } 11363955d011SMarcel Moolenaar if (queryFlag) { 11373841c287SSimon J. Gerraty return TRUE; 11383955d011SMarcel Moolenaar } 11393955d011SMarcel Moolenaar Make_DoAllVar(gn); 11403955d011SMarcel Moolenaar Job_Make(gn); 11413955d011SMarcel Moolenaar have_token = 0; 11423955d011SMarcel Moolenaar } else { 11433955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 11443955d011SMarcel Moolenaar fprintf(debug_file, "up-to-date\n"); 11453955d011SMarcel Moolenaar } 11463955d011SMarcel Moolenaar gn->made = UPTODATE; 11473955d011SMarcel Moolenaar if (gn->type & OP_JOIN) { 11483955d011SMarcel Moolenaar /* 11493955d011SMarcel Moolenaar * Even for an up-to-date .JOIN node, we need it to have its 11503955d011SMarcel Moolenaar * context variables so references to it get the correct 11513955d011SMarcel Moolenaar * value for .TARGET when building up the context variables 11523955d011SMarcel Moolenaar * of its parent(s)... 11533955d011SMarcel Moolenaar */ 11543955d011SMarcel Moolenaar Make_DoAllVar(gn); 11553955d011SMarcel Moolenaar } 11563955d011SMarcel Moolenaar Make_Update(gn); 11573955d011SMarcel Moolenaar } 11583955d011SMarcel Moolenaar } 11593955d011SMarcel Moolenaar 11603955d011SMarcel Moolenaar if (have_token) 11613955d011SMarcel Moolenaar Job_TokenReturn(); 11623955d011SMarcel Moolenaar 11633841c287SSimon J. Gerraty return FALSE; 11643955d011SMarcel Moolenaar } 1165*2c3632d1SSimon J. Gerraty 11663955d011SMarcel Moolenaar /*- 11673955d011SMarcel Moolenaar *----------------------------------------------------------------------- 11683955d011SMarcel Moolenaar * MakePrintStatus -- 11693955d011SMarcel Moolenaar * Print the status of a top-level node, viz. it being up-to-date 11703955d011SMarcel Moolenaar * already or not created due to an error in a lower level. 11713955d011SMarcel Moolenaar * Callback function for Make_Run via Lst_ForEach. 11723955d011SMarcel Moolenaar * 11733955d011SMarcel Moolenaar * Input: 11743955d011SMarcel Moolenaar * gnp Node to examine 11753955d011SMarcel Moolenaar * cyclep True if gn->unmade being non-zero implies a 11763955d011SMarcel Moolenaar * cycle in the graph, not an error in an 11773955d011SMarcel Moolenaar * inferior. 11783955d011SMarcel Moolenaar * 11793955d011SMarcel Moolenaar * Results: 11803955d011SMarcel Moolenaar * Always returns 0. 11813955d011SMarcel Moolenaar * 11823955d011SMarcel Moolenaar * Side Effects: 11833955d011SMarcel Moolenaar * A message may be printed. 11843955d011SMarcel Moolenaar * 11853955d011SMarcel Moolenaar *----------------------------------------------------------------------- 11863955d011SMarcel Moolenaar */ 11873955d011SMarcel Moolenaar static int 11883955d011SMarcel Moolenaar MakePrintStatusOrder(void *ognp, void *gnp) 11893955d011SMarcel Moolenaar { 11903955d011SMarcel Moolenaar GNode *ogn = ognp; 11913955d011SMarcel Moolenaar GNode *gn = gnp; 11923955d011SMarcel Moolenaar 11933955d011SMarcel Moolenaar if (!(ogn->flags & REMAKE) || ogn->made > REQUESTED) 11943955d011SMarcel Moolenaar /* not waiting for this one */ 11953955d011SMarcel Moolenaar return 0; 11963955d011SMarcel Moolenaar 1197*2c3632d1SSimon J. Gerraty printf(" `%s%s' has .ORDER dependency against %s%s ", 1198*2c3632d1SSimon J. Gerraty gn->name, gn->cohort_num, ogn->name, ogn->cohort_num); 1199*2c3632d1SSimon J. Gerraty GNode_FprintDetails(stdout, "(", ogn, ")\n"); 1200*2c3632d1SSimon J. Gerraty 1201*2c3632d1SSimon J. Gerraty if (DEBUG(MAKE) && debug_file != stdout) { 1202*2c3632d1SSimon J. Gerraty fprintf(debug_file, " `%s%s' has .ORDER dependency against %s%s ", 1203*2c3632d1SSimon J. Gerraty gn->name, gn->cohort_num, ogn->name, ogn->cohort_num); 1204*2c3632d1SSimon J. Gerraty GNode_FprintDetails(debug_file, "(", ogn, ")\n"); 1205*2c3632d1SSimon J. Gerraty } 12063955d011SMarcel Moolenaar return 0; 12073955d011SMarcel Moolenaar } 12083955d011SMarcel Moolenaar 12093955d011SMarcel Moolenaar static int 12103955d011SMarcel Moolenaar MakePrintStatus(void *gnp, void *v_errors) 12113955d011SMarcel Moolenaar { 12123955d011SMarcel Moolenaar GNode *gn = (GNode *)gnp; 12133955d011SMarcel Moolenaar int *errors = v_errors; 12143955d011SMarcel Moolenaar 12153955d011SMarcel Moolenaar if (gn->flags & DONECYCLE) 12163955d011SMarcel Moolenaar /* We've completely processed this node before, don't do it again. */ 12173955d011SMarcel Moolenaar return 0; 12183955d011SMarcel Moolenaar 12193955d011SMarcel Moolenaar if (gn->unmade == 0) { 12203955d011SMarcel Moolenaar gn->flags |= DONECYCLE; 12213955d011SMarcel Moolenaar switch (gn->made) { 12223955d011SMarcel Moolenaar case UPTODATE: 12233955d011SMarcel Moolenaar printf("`%s%s' is up to date.\n", gn->name, gn->cohort_num); 12243955d011SMarcel Moolenaar break; 12253955d011SMarcel Moolenaar case MADE: 12263955d011SMarcel Moolenaar break; 12273955d011SMarcel Moolenaar case UNMADE: 12283955d011SMarcel Moolenaar case DEFERRED: 12293955d011SMarcel Moolenaar case REQUESTED: 12303955d011SMarcel Moolenaar case BEINGMADE: 12313955d011SMarcel Moolenaar (*errors)++; 1232*2c3632d1SSimon J. Gerraty printf("`%s%s' was not built", gn->name, gn->cohort_num); 1233*2c3632d1SSimon J. Gerraty GNode_FprintDetails(stdout, " (", gn, ")!\n"); 1234*2c3632d1SSimon J. Gerraty if (DEBUG(MAKE) && debug_file != stdout) { 1235*2c3632d1SSimon J. Gerraty fprintf(debug_file, "`%s%s' was not built", 1236*2c3632d1SSimon J. Gerraty gn->name, gn->cohort_num); 1237*2c3632d1SSimon J. Gerraty GNode_FprintDetails(debug_file, " (", gn, ")!\n"); 1238*2c3632d1SSimon J. Gerraty } 12393955d011SMarcel Moolenaar /* Most likely problem is actually caused by .ORDER */ 12403955d011SMarcel Moolenaar Lst_ForEach(gn->order_pred, MakePrintStatusOrder, gn); 12413955d011SMarcel Moolenaar break; 12423955d011SMarcel Moolenaar default: 12433955d011SMarcel Moolenaar /* Errors - already counted */ 12443955d011SMarcel Moolenaar printf("`%s%s' not remade because of errors.\n", 12453955d011SMarcel Moolenaar gn->name, gn->cohort_num); 12463955d011SMarcel Moolenaar if (DEBUG(MAKE) && debug_file != stdout) 12473955d011SMarcel Moolenaar fprintf(debug_file, "`%s%s' not remade because of errors.\n", 12483955d011SMarcel Moolenaar gn->name, gn->cohort_num); 12493955d011SMarcel Moolenaar break; 12503955d011SMarcel Moolenaar } 12513955d011SMarcel Moolenaar return 0; 12523955d011SMarcel Moolenaar } 12533955d011SMarcel Moolenaar 12543955d011SMarcel Moolenaar if (DEBUG(MAKE)) 12553955d011SMarcel Moolenaar fprintf(debug_file, "MakePrintStatus: %s%s has %d unmade children\n", 12563955d011SMarcel Moolenaar gn->name, gn->cohort_num, gn->unmade); 12573955d011SMarcel Moolenaar /* 12583955d011SMarcel Moolenaar * If printing cycles and came to one that has unmade children, 12593955d011SMarcel Moolenaar * print out the cycle by recursing on its children. 12603955d011SMarcel Moolenaar */ 12613955d011SMarcel Moolenaar if (!(gn->flags & CYCLE)) { 12623955d011SMarcel Moolenaar /* Fist time we've seen this node, check all children */ 12633955d011SMarcel Moolenaar gn->flags |= CYCLE; 12643955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakePrintStatus, errors); 12653955d011SMarcel Moolenaar /* Mark that this node needn't be processed again */ 12663955d011SMarcel Moolenaar gn->flags |= DONECYCLE; 12673955d011SMarcel Moolenaar return 0; 12683955d011SMarcel Moolenaar } 12693955d011SMarcel Moolenaar 12703955d011SMarcel Moolenaar /* Only output the error once per node */ 12713955d011SMarcel Moolenaar gn->flags |= DONECYCLE; 12723955d011SMarcel Moolenaar Error("Graph cycles through `%s%s'", gn->name, gn->cohort_num); 12733955d011SMarcel Moolenaar if ((*errors)++ > 100) 12743955d011SMarcel Moolenaar /* Abandon the whole error report */ 12753955d011SMarcel Moolenaar return 1; 12763955d011SMarcel Moolenaar 12773955d011SMarcel Moolenaar /* Reporting for our children will give the rest of the loop */ 12783955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakePrintStatus, errors); 12793955d011SMarcel Moolenaar return 0; 12803955d011SMarcel Moolenaar } 1281*2c3632d1SSimon J. Gerraty 12823955d011SMarcel Moolenaar 12833955d011SMarcel Moolenaar /*- 12843955d011SMarcel Moolenaar *----------------------------------------------------------------------- 12853955d011SMarcel Moolenaar * Make_ExpandUse -- 12863955d011SMarcel Moolenaar * Expand .USE nodes and create a new targets list 12873955d011SMarcel Moolenaar * 12883955d011SMarcel Moolenaar * Input: 12893955d011SMarcel Moolenaar * targs the initial list of targets 12903955d011SMarcel Moolenaar * 12913955d011SMarcel Moolenaar * Side Effects: 12923955d011SMarcel Moolenaar *----------------------------------------------------------------------- 12933955d011SMarcel Moolenaar */ 12943955d011SMarcel Moolenaar void 12953955d011SMarcel Moolenaar Make_ExpandUse(Lst targs) 12963955d011SMarcel Moolenaar { 12973955d011SMarcel Moolenaar GNode *gn; /* a temporary pointer */ 12983955d011SMarcel Moolenaar Lst examine; /* List of targets to examine */ 12993955d011SMarcel Moolenaar 1300*2c3632d1SSimon J. Gerraty examine = Lst_Copy(targs, NULL); 13013955d011SMarcel Moolenaar 13023955d011SMarcel Moolenaar /* 13033955d011SMarcel Moolenaar * Make an initial downward pass over the graph, marking nodes to be made 13043955d011SMarcel Moolenaar * as we go down. We call Suff_FindDeps to find where a node is and 13053955d011SMarcel Moolenaar * to get some children for it if it has none and also has no commands. 13063955d011SMarcel Moolenaar * If the node is a leaf, we stick it on the toBeMade queue to 13073955d011SMarcel Moolenaar * be looked at in a minute, otherwise we add its children to our queue 13083955d011SMarcel Moolenaar * and go on about our business. 13093955d011SMarcel Moolenaar */ 13103955d011SMarcel Moolenaar while (!Lst_IsEmpty(examine)) { 1311*2c3632d1SSimon J. Gerraty gn = Lst_Dequeue(examine); 13123955d011SMarcel Moolenaar 13133955d011SMarcel Moolenaar if (gn->flags & REMAKE) 13143955d011SMarcel Moolenaar /* We've looked at this one already */ 13153955d011SMarcel Moolenaar continue; 13163955d011SMarcel Moolenaar gn->flags |= REMAKE; 13173955d011SMarcel Moolenaar if (DEBUG(MAKE)) 13183955d011SMarcel Moolenaar fprintf(debug_file, "Make_ExpandUse: examine %s%s\n", 13193955d011SMarcel Moolenaar gn->name, gn->cohort_num); 13203955d011SMarcel Moolenaar 1321*2c3632d1SSimon J. Gerraty if (gn->type & OP_DOUBLEDEP) 1322*2c3632d1SSimon J. Gerraty Lst_PrependAll(examine, gn->cohorts); 13233955d011SMarcel Moolenaar 13243955d011SMarcel Moolenaar /* 13253955d011SMarcel Moolenaar * Apply any .USE rules before looking for implicit dependencies 13263955d011SMarcel Moolenaar * to make sure everything has commands that should... 13273955d011SMarcel Moolenaar * Make sure that the TARGET is set, so that we can make 13283955d011SMarcel Moolenaar * expansions. 13293955d011SMarcel Moolenaar */ 13303955d011SMarcel Moolenaar if (gn->type & OP_ARCHV) { 13313955d011SMarcel Moolenaar char *eoa, *eon; 13323955d011SMarcel Moolenaar eoa = strchr(gn->name, '('); 13333955d011SMarcel Moolenaar eon = strchr(gn->name, ')'); 13343955d011SMarcel Moolenaar if (eoa == NULL || eon == NULL) 13353955d011SMarcel Moolenaar continue; 13363955d011SMarcel Moolenaar *eoa = '\0'; 13373955d011SMarcel Moolenaar *eon = '\0'; 13383841c287SSimon J. Gerraty Var_Set(MEMBER, eoa + 1, gn); 13393841c287SSimon J. Gerraty Var_Set(ARCHIVE, gn->name, gn); 13403955d011SMarcel Moolenaar *eoa = '('; 13413955d011SMarcel Moolenaar *eon = ')'; 13423955d011SMarcel Moolenaar } 13433955d011SMarcel Moolenaar 13443955d011SMarcel Moolenaar (void)Dir_MTime(gn, 0); 13453841c287SSimon J. Gerraty Var_Set(TARGET, gn->path ? gn->path : gn->name, gn); 13463955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeUnmark, gn); 13473955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeHandleUse, gn); 13483955d011SMarcel Moolenaar 13493955d011SMarcel Moolenaar if ((gn->type & OP_MADE) == 0) 13503955d011SMarcel Moolenaar Suff_FindDeps(gn); 13513955d011SMarcel Moolenaar else { 13523955d011SMarcel Moolenaar /* Pretend we made all this node's children */ 13533955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeFindChild, gn); 13543955d011SMarcel Moolenaar if (gn->unmade != 0) 13553955d011SMarcel Moolenaar printf("Warning: %s%s still has %d unmade children\n", 13563955d011SMarcel Moolenaar gn->name, gn->cohort_num, gn->unmade); 13573955d011SMarcel Moolenaar } 13583955d011SMarcel Moolenaar 13593955d011SMarcel Moolenaar if (gn->unmade != 0) 13603955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeAddChild, examine); 13613955d011SMarcel Moolenaar } 13623955d011SMarcel Moolenaar 1363*2c3632d1SSimon J. Gerraty Lst_Free(examine); 13643955d011SMarcel Moolenaar } 13653955d011SMarcel Moolenaar 13663955d011SMarcel Moolenaar /*- 13673955d011SMarcel Moolenaar *----------------------------------------------------------------------- 13683955d011SMarcel Moolenaar * Make_ProcessWait -- 13693955d011SMarcel Moolenaar * Convert .WAIT nodes into dependencies 13703955d011SMarcel Moolenaar * 13713955d011SMarcel Moolenaar * Input: 13723955d011SMarcel Moolenaar * targs the initial list of targets 13733955d011SMarcel Moolenaar * 13743955d011SMarcel Moolenaar *----------------------------------------------------------------------- 13753955d011SMarcel Moolenaar */ 13763955d011SMarcel Moolenaar 13773955d011SMarcel Moolenaar static int 13783955d011SMarcel Moolenaar link_parent(void *cnp, void *pnp) 13793955d011SMarcel Moolenaar { 13803955d011SMarcel Moolenaar GNode *cn = cnp; 13813955d011SMarcel Moolenaar GNode *pn = pnp; 13823955d011SMarcel Moolenaar 1383*2c3632d1SSimon J. Gerraty Lst_Append(pn->children, cn); 1384*2c3632d1SSimon J. Gerraty Lst_Append(cn->parents, pn); 13853955d011SMarcel Moolenaar pn->unmade++; 13863955d011SMarcel Moolenaar return 0; 13873955d011SMarcel Moolenaar } 13883955d011SMarcel Moolenaar 13893955d011SMarcel Moolenaar static int 13903955d011SMarcel Moolenaar add_wait_dep(void *v_cn, void *v_wn) 13913955d011SMarcel Moolenaar { 13923955d011SMarcel Moolenaar GNode *cn = v_cn; 13933955d011SMarcel Moolenaar GNode *wn = v_wn; 13943955d011SMarcel Moolenaar 13953955d011SMarcel Moolenaar if (cn == wn) 13963955d011SMarcel Moolenaar return 1; 13973955d011SMarcel Moolenaar 13983955d011SMarcel Moolenaar if (cn == NULL || wn == NULL) { 13993955d011SMarcel Moolenaar printf("bad wait dep %p %p\n", cn, wn); 14003955d011SMarcel Moolenaar exit(4); 14013955d011SMarcel Moolenaar } 14023955d011SMarcel Moolenaar if (DEBUG(MAKE)) 14033955d011SMarcel Moolenaar fprintf(debug_file, ".WAIT: add dependency %s%s -> %s\n", 14043955d011SMarcel Moolenaar cn->name, cn->cohort_num, wn->name); 14053955d011SMarcel Moolenaar 1406*2c3632d1SSimon J. Gerraty Lst_Append(wn->children, cn); 14073955d011SMarcel Moolenaar wn->unmade++; 1408*2c3632d1SSimon J. Gerraty Lst_Append(cn->parents, wn); 14093955d011SMarcel Moolenaar return 0; 14103955d011SMarcel Moolenaar } 14113955d011SMarcel Moolenaar 14123955d011SMarcel Moolenaar static void 14133955d011SMarcel Moolenaar Make_ProcessWait(Lst targs) 14143955d011SMarcel Moolenaar { 14153955d011SMarcel Moolenaar GNode *pgn; /* 'parent' node we are examining */ 14163955d011SMarcel Moolenaar GNode *cgn; /* Each child in turn */ 14173955d011SMarcel Moolenaar LstNode owln; /* Previous .WAIT node */ 14183955d011SMarcel Moolenaar Lst examine; /* List of targets to examine */ 14193955d011SMarcel Moolenaar LstNode ln; 14203955d011SMarcel Moolenaar 14213955d011SMarcel Moolenaar /* 14223955d011SMarcel Moolenaar * We need all the nodes to have a common parent in order for the 14233955d011SMarcel Moolenaar * .WAIT and .ORDER scheduling to work. 14243955d011SMarcel Moolenaar * Perhaps this should be done earlier... 14253955d011SMarcel Moolenaar */ 14263955d011SMarcel Moolenaar 14273955d011SMarcel Moolenaar pgn = Targ_NewGN(".MAIN"); 14283955d011SMarcel Moolenaar pgn->flags = REMAKE; 14293955d011SMarcel Moolenaar pgn->type = OP_PHONY | OP_DEPENDS; 14303955d011SMarcel Moolenaar /* Get it displayed in the diag dumps */ 1431*2c3632d1SSimon J. Gerraty Lst_Prepend(Targ_List(), pgn); 14323955d011SMarcel Moolenaar 14333955d011SMarcel Moolenaar Lst_ForEach(targs, link_parent, pgn); 14343955d011SMarcel Moolenaar 14353955d011SMarcel Moolenaar /* Start building with the 'dummy' .MAIN' node */ 14363955d011SMarcel Moolenaar MakeBuildChild(pgn, NULL); 14373955d011SMarcel Moolenaar 1438*2c3632d1SSimon J. Gerraty examine = Lst_Init(); 1439*2c3632d1SSimon J. Gerraty Lst_Append(examine, pgn); 14403955d011SMarcel Moolenaar 14413955d011SMarcel Moolenaar while (!Lst_IsEmpty(examine)) { 1442*2c3632d1SSimon J. Gerraty pgn = Lst_Dequeue(examine); 14433955d011SMarcel Moolenaar 14443955d011SMarcel Moolenaar /* We only want to process each child-list once */ 14453955d011SMarcel Moolenaar if (pgn->flags & DONE_WAIT) 14463955d011SMarcel Moolenaar continue; 14473955d011SMarcel Moolenaar pgn->flags |= DONE_WAIT; 14483955d011SMarcel Moolenaar if (DEBUG(MAKE)) 14493955d011SMarcel Moolenaar fprintf(debug_file, "Make_ProcessWait: examine %s\n", pgn->name); 14503955d011SMarcel Moolenaar 1451*2c3632d1SSimon J. Gerraty if (pgn->type & OP_DOUBLEDEP) 1452*2c3632d1SSimon J. Gerraty Lst_PrependAll(examine, pgn->cohorts); 14533955d011SMarcel Moolenaar 14543955d011SMarcel Moolenaar owln = Lst_First(pgn->children); 14553955d011SMarcel Moolenaar Lst_Open(pgn->children); 14563955d011SMarcel Moolenaar for (; (ln = Lst_Next(pgn->children)) != NULL; ) { 1457*2c3632d1SSimon J. Gerraty cgn = LstNode_Datum(ln); 14583955d011SMarcel Moolenaar if (cgn->type & OP_WAIT) { 14593955d011SMarcel Moolenaar /* Make the .WAIT node depend on the previous children */ 14603955d011SMarcel Moolenaar Lst_ForEachFrom(pgn->children, owln, add_wait_dep, cgn); 14613955d011SMarcel Moolenaar owln = ln; 14623955d011SMarcel Moolenaar } else { 1463*2c3632d1SSimon J. Gerraty Lst_Append(examine, cgn); 14643955d011SMarcel Moolenaar } 14653955d011SMarcel Moolenaar } 14663955d011SMarcel Moolenaar Lst_Close(pgn->children); 14673955d011SMarcel Moolenaar } 14683955d011SMarcel Moolenaar 1469*2c3632d1SSimon J. Gerraty Lst_Free(examine); 14703955d011SMarcel Moolenaar } 14713955d011SMarcel Moolenaar 14723955d011SMarcel Moolenaar /*- 14733955d011SMarcel Moolenaar *----------------------------------------------------------------------- 14743955d011SMarcel Moolenaar * Make_Run -- 14753955d011SMarcel Moolenaar * Initialize the nodes to remake and the list of nodes which are 14763955d011SMarcel Moolenaar * ready to be made by doing a breadth-first traversal of the graph 14773955d011SMarcel Moolenaar * starting from the nodes in the given list. Once this traversal 14783955d011SMarcel Moolenaar * is finished, all the 'leaves' of the graph are in the toBeMade 14793955d011SMarcel Moolenaar * queue. 14803955d011SMarcel Moolenaar * Using this queue and the Job module, work back up the graph, 14813955d011SMarcel Moolenaar * calling on MakeStartJobs to keep the job table as full as 14823955d011SMarcel Moolenaar * possible. 14833955d011SMarcel Moolenaar * 14843955d011SMarcel Moolenaar * Input: 14853955d011SMarcel Moolenaar * targs the initial list of targets 14863955d011SMarcel Moolenaar * 14873955d011SMarcel Moolenaar * Results: 14883955d011SMarcel Moolenaar * TRUE if work was done. FALSE otherwise. 14893955d011SMarcel Moolenaar * 14903955d011SMarcel Moolenaar * Side Effects: 14913955d011SMarcel Moolenaar * The make field of all nodes involved in the creation of the given 14923955d011SMarcel Moolenaar * targets is set to 1. The toBeMade list is set to contain all the 14933955d011SMarcel Moolenaar * 'leaves' of these subgraphs. 14943955d011SMarcel Moolenaar *----------------------------------------------------------------------- 14953955d011SMarcel Moolenaar */ 14963955d011SMarcel Moolenaar Boolean 14973955d011SMarcel Moolenaar Make_Run(Lst targs) 14983955d011SMarcel Moolenaar { 14993955d011SMarcel Moolenaar int errors; /* Number of errors the Job module reports */ 15003955d011SMarcel Moolenaar 15013955d011SMarcel Moolenaar /* Start trying to make the current targets... */ 1502*2c3632d1SSimon J. Gerraty toBeMade = Lst_Init(); 15033955d011SMarcel Moolenaar 15043955d011SMarcel Moolenaar Make_ExpandUse(targs); 15053955d011SMarcel Moolenaar Make_ProcessWait(targs); 15063955d011SMarcel Moolenaar 15073955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 15083955d011SMarcel Moolenaar fprintf(debug_file, "#***# full graph\n"); 15093955d011SMarcel Moolenaar Targ_PrintGraph(1); 15103955d011SMarcel Moolenaar } 15113955d011SMarcel Moolenaar 15123955d011SMarcel Moolenaar if (queryFlag) { 15133955d011SMarcel Moolenaar /* 15143955d011SMarcel Moolenaar * We wouldn't do any work unless we could start some jobs in the 15153955d011SMarcel Moolenaar * next loop... (we won't actually start any, of course, this is just 15163955d011SMarcel Moolenaar * to see if any of the targets was out of date) 15173955d011SMarcel Moolenaar */ 15183841c287SSimon J. Gerraty return MakeStartJobs(); 15193955d011SMarcel Moolenaar } 15203955d011SMarcel Moolenaar /* 15213955d011SMarcel Moolenaar * Initialization. At the moment, no jobs are running and until some 15223955d011SMarcel Moolenaar * get started, nothing will happen since the remaining upward 15233955d011SMarcel Moolenaar * traversal of the graph is performed by the routines in job.c upon 15243955d011SMarcel Moolenaar * the finishing of a job. So we fill the Job table as much as we can 15253955d011SMarcel Moolenaar * before going into our loop. 15263955d011SMarcel Moolenaar */ 15273955d011SMarcel Moolenaar (void)MakeStartJobs(); 15283955d011SMarcel Moolenaar 15293955d011SMarcel Moolenaar /* 15303955d011SMarcel Moolenaar * Main Loop: The idea here is that the ending of jobs will take 15313955d011SMarcel Moolenaar * care of the maintenance of data structures and the waiting for output 15323955d011SMarcel Moolenaar * will cause us to be idle most of the time while our children run as 15333955d011SMarcel Moolenaar * much as possible. Because the job table is kept as full as possible, 15343955d011SMarcel Moolenaar * the only time when it will be empty is when all the jobs which need 15353955d011SMarcel Moolenaar * running have been run, so that is the end condition of this loop. 15363955d011SMarcel Moolenaar * Note that the Job module will exit if there were any errors unless the 15373955d011SMarcel Moolenaar * keepgoing flag was given. 15383955d011SMarcel Moolenaar */ 15393955d011SMarcel Moolenaar while (!Lst_IsEmpty(toBeMade) || jobTokensRunning > 0) { 15403955d011SMarcel Moolenaar Job_CatchOutput(); 15413955d011SMarcel Moolenaar (void)MakeStartJobs(); 15423955d011SMarcel Moolenaar } 15433955d011SMarcel Moolenaar 15443955d011SMarcel Moolenaar errors = Job_Finish(); 15453955d011SMarcel Moolenaar 15463955d011SMarcel Moolenaar /* 15473955d011SMarcel Moolenaar * Print the final status of each target. E.g. if it wasn't made 15483955d011SMarcel Moolenaar * because some inferior reported an error. 15493955d011SMarcel Moolenaar */ 15503955d011SMarcel Moolenaar if (DEBUG(MAKE)) 15513955d011SMarcel Moolenaar fprintf(debug_file, "done: errors %d\n", errors); 15523955d011SMarcel Moolenaar if (errors == 0) { 15533955d011SMarcel Moolenaar Lst_ForEach(targs, MakePrintStatus, &errors); 15543955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 15553955d011SMarcel Moolenaar fprintf(debug_file, "done: errors %d\n", errors); 15563955d011SMarcel Moolenaar if (errors) 15573955d011SMarcel Moolenaar Targ_PrintGraph(4); 15583955d011SMarcel Moolenaar } 15593955d011SMarcel Moolenaar } 15603955d011SMarcel Moolenaar return errors != 0; 15613955d011SMarcel Moolenaar } 1562