1*3955d011SMarcel Moolenaar /* $NetBSD: make.c,v 1.87 2012/06/12 19:21:51 joerg Exp $ */ 2*3955d011SMarcel Moolenaar 3*3955d011SMarcel Moolenaar /* 4*3955d011SMarcel Moolenaar * Copyright (c) 1988, 1989, 1990, 1993 5*3955d011SMarcel Moolenaar * The Regents of the University of California. All rights reserved. 6*3955d011SMarcel Moolenaar * 7*3955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 8*3955d011SMarcel Moolenaar * Adam de Boor. 9*3955d011SMarcel Moolenaar * 10*3955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 11*3955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 12*3955d011SMarcel Moolenaar * are met: 13*3955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 14*3955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 15*3955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 16*3955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 17*3955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 18*3955d011SMarcel Moolenaar * 3. Neither the name of the University nor the names of its contributors 19*3955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 20*3955d011SMarcel Moolenaar * without specific prior written permission. 21*3955d011SMarcel Moolenaar * 22*3955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*3955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*3955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*3955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*3955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*3955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*3955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*3955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*3955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*3955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*3955d011SMarcel Moolenaar * SUCH DAMAGE. 33*3955d011SMarcel Moolenaar */ 34*3955d011SMarcel Moolenaar 35*3955d011SMarcel Moolenaar /* 36*3955d011SMarcel Moolenaar * Copyright (c) 1989 by Berkeley Softworks 37*3955d011SMarcel Moolenaar * All rights reserved. 38*3955d011SMarcel Moolenaar * 39*3955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 40*3955d011SMarcel Moolenaar * Adam de Boor. 41*3955d011SMarcel Moolenaar * 42*3955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 43*3955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 44*3955d011SMarcel Moolenaar * are met: 45*3955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 46*3955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 47*3955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 48*3955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 49*3955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 50*3955d011SMarcel Moolenaar * 3. All advertising materials mentioning features or use of this software 51*3955d011SMarcel Moolenaar * must display the following acknowledgement: 52*3955d011SMarcel Moolenaar * This product includes software developed by the University of 53*3955d011SMarcel Moolenaar * California, Berkeley and its contributors. 54*3955d011SMarcel Moolenaar * 4. Neither the name of the University nor the names of its contributors 55*3955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 56*3955d011SMarcel Moolenaar * without specific prior written permission. 57*3955d011SMarcel Moolenaar * 58*3955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59*3955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60*3955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61*3955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62*3955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63*3955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64*3955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65*3955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66*3955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67*3955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68*3955d011SMarcel Moolenaar * SUCH DAMAGE. 69*3955d011SMarcel Moolenaar */ 70*3955d011SMarcel Moolenaar 71*3955d011SMarcel Moolenaar #ifndef MAKE_NATIVE 72*3955d011SMarcel Moolenaar static char rcsid[] = "$NetBSD: make.c,v 1.87 2012/06/12 19:21:51 joerg Exp $"; 73*3955d011SMarcel Moolenaar #else 74*3955d011SMarcel Moolenaar #include <sys/cdefs.h> 75*3955d011SMarcel Moolenaar #ifndef lint 76*3955d011SMarcel Moolenaar #if 0 77*3955d011SMarcel Moolenaar static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93"; 78*3955d011SMarcel Moolenaar #else 79*3955d011SMarcel Moolenaar __RCSID("$NetBSD: make.c,v 1.87 2012/06/12 19:21:51 joerg Exp $"); 80*3955d011SMarcel Moolenaar #endif 81*3955d011SMarcel Moolenaar #endif /* not lint */ 82*3955d011SMarcel Moolenaar #endif 83*3955d011SMarcel Moolenaar 84*3955d011SMarcel Moolenaar /*- 85*3955d011SMarcel Moolenaar * make.c -- 86*3955d011SMarcel Moolenaar * The functions which perform the examination of targets and 87*3955d011SMarcel Moolenaar * their suitability for creation 88*3955d011SMarcel Moolenaar * 89*3955d011SMarcel Moolenaar * Interface: 90*3955d011SMarcel Moolenaar * Make_Run Initialize things for the module and recreate 91*3955d011SMarcel Moolenaar * whatever needs recreating. Returns TRUE if 92*3955d011SMarcel Moolenaar * work was (or would have been) done and FALSE 93*3955d011SMarcel Moolenaar * otherwise. 94*3955d011SMarcel Moolenaar * 95*3955d011SMarcel Moolenaar * Make_Update Update all parents of a given child. Performs 96*3955d011SMarcel Moolenaar * various bookkeeping chores like the updating 97*3955d011SMarcel Moolenaar * of the cmgn field of the parent, filling 98*3955d011SMarcel Moolenaar * of the IMPSRC context variable, etc. It will 99*3955d011SMarcel Moolenaar * place the parent on the toBeMade queue if it 100*3955d011SMarcel Moolenaar * should be. 101*3955d011SMarcel Moolenaar * 102*3955d011SMarcel Moolenaar * Make_TimeStamp Function to set the parent's cmgn field 103*3955d011SMarcel Moolenaar * based on a child's modification time. 104*3955d011SMarcel Moolenaar * 105*3955d011SMarcel Moolenaar * Make_DoAllVar Set up the various local variables for a 106*3955d011SMarcel Moolenaar * target, including the .ALLSRC variable, making 107*3955d011SMarcel Moolenaar * sure that any variable that needs to exist 108*3955d011SMarcel Moolenaar * at the very least has the empty value. 109*3955d011SMarcel Moolenaar * 110*3955d011SMarcel Moolenaar * Make_OODate Determine if a target is out-of-date. 111*3955d011SMarcel Moolenaar * 112*3955d011SMarcel Moolenaar * Make_HandleUse See if a child is a .USE node for a parent 113*3955d011SMarcel Moolenaar * and perform the .USE actions if so. 114*3955d011SMarcel Moolenaar * 115*3955d011SMarcel Moolenaar * Make_ExpandUse Expand .USE nodes 116*3955d011SMarcel Moolenaar */ 117*3955d011SMarcel Moolenaar 118*3955d011SMarcel Moolenaar #include "make.h" 119*3955d011SMarcel Moolenaar #include "hash.h" 120*3955d011SMarcel Moolenaar #include "dir.h" 121*3955d011SMarcel Moolenaar #include "job.h" 122*3955d011SMarcel Moolenaar 123*3955d011SMarcel Moolenaar static unsigned int checked = 1;/* Sequence # to detect recursion */ 124*3955d011SMarcel Moolenaar static Lst toBeMade; /* The current fringe of the graph. These 125*3955d011SMarcel Moolenaar * are nodes which await examination by 126*3955d011SMarcel Moolenaar * MakeOODate. It is added to by 127*3955d011SMarcel Moolenaar * Make_Update and subtracted from by 128*3955d011SMarcel Moolenaar * MakeStartJobs */ 129*3955d011SMarcel Moolenaar 130*3955d011SMarcel Moolenaar static int MakeAddChild(void *, void *); 131*3955d011SMarcel Moolenaar static int MakeFindChild(void *, void *); 132*3955d011SMarcel Moolenaar static int MakeUnmark(void *, void *); 133*3955d011SMarcel Moolenaar static int MakeAddAllSrc(void *, void *); 134*3955d011SMarcel Moolenaar static int MakeTimeStamp(void *, void *); 135*3955d011SMarcel Moolenaar static int MakeHandleUse(void *, void *); 136*3955d011SMarcel Moolenaar static Boolean MakeStartJobs(void); 137*3955d011SMarcel Moolenaar static int MakePrintStatus(void *, void *); 138*3955d011SMarcel Moolenaar static int MakeCheckOrder(void *, void *); 139*3955d011SMarcel Moolenaar static int MakeBuildChild(void *, void *); 140*3955d011SMarcel Moolenaar static int MakeBuildParent(void *, void *); 141*3955d011SMarcel Moolenaar 142*3955d011SMarcel Moolenaar MAKE_ATTR_DEAD static void 143*3955d011SMarcel Moolenaar make_abort(GNode *gn, int line) 144*3955d011SMarcel Moolenaar { 145*3955d011SMarcel Moolenaar static int two = 2; 146*3955d011SMarcel Moolenaar 147*3955d011SMarcel Moolenaar fprintf(debug_file, "make_abort from line %d\n", line); 148*3955d011SMarcel Moolenaar Targ_PrintNode(gn, &two); 149*3955d011SMarcel Moolenaar Lst_ForEach(toBeMade, Targ_PrintNode, &two); 150*3955d011SMarcel Moolenaar Targ_PrintGraph(3); 151*3955d011SMarcel Moolenaar abort(); 152*3955d011SMarcel Moolenaar } 153*3955d011SMarcel Moolenaar 154*3955d011SMarcel Moolenaar /*- 155*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 156*3955d011SMarcel Moolenaar * Make_TimeStamp -- 157*3955d011SMarcel Moolenaar * Set the cmgn field of a parent node based on the mtime stamp in its 158*3955d011SMarcel Moolenaar * child. Called from MakeOODate via Lst_ForEach. 159*3955d011SMarcel Moolenaar * 160*3955d011SMarcel Moolenaar * Input: 161*3955d011SMarcel Moolenaar * pgn the current parent 162*3955d011SMarcel Moolenaar * cgn the child we've just examined 163*3955d011SMarcel Moolenaar * 164*3955d011SMarcel Moolenaar * Results: 165*3955d011SMarcel Moolenaar * Always returns 0. 166*3955d011SMarcel Moolenaar * 167*3955d011SMarcel Moolenaar * Side Effects: 168*3955d011SMarcel Moolenaar * The cmgn of the parent node will be changed if the mtime 169*3955d011SMarcel Moolenaar * field of the child is greater than it. 170*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 171*3955d011SMarcel Moolenaar */ 172*3955d011SMarcel Moolenaar int 173*3955d011SMarcel Moolenaar Make_TimeStamp(GNode *pgn, GNode *cgn) 174*3955d011SMarcel Moolenaar { 175*3955d011SMarcel Moolenaar if (pgn->cmgn == NULL || cgn->mtime > pgn->cmgn->mtime) { 176*3955d011SMarcel Moolenaar pgn->cmgn = cgn; 177*3955d011SMarcel Moolenaar } 178*3955d011SMarcel Moolenaar return (0); 179*3955d011SMarcel Moolenaar } 180*3955d011SMarcel Moolenaar 181*3955d011SMarcel Moolenaar /* 182*3955d011SMarcel Moolenaar * Input: 183*3955d011SMarcel Moolenaar * pgn the current parent 184*3955d011SMarcel Moolenaar * cgn the child we've just examined 185*3955d011SMarcel Moolenaar * 186*3955d011SMarcel Moolenaar */ 187*3955d011SMarcel Moolenaar static int 188*3955d011SMarcel Moolenaar MakeTimeStamp(void *pgn, void *cgn) 189*3955d011SMarcel Moolenaar { 190*3955d011SMarcel Moolenaar return Make_TimeStamp((GNode *)pgn, (GNode *)cgn); 191*3955d011SMarcel Moolenaar } 192*3955d011SMarcel Moolenaar 193*3955d011SMarcel Moolenaar /*- 194*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 195*3955d011SMarcel Moolenaar * Make_OODate -- 196*3955d011SMarcel Moolenaar * See if a given node is out of date with respect to its sources. 197*3955d011SMarcel Moolenaar * Used by Make_Run when deciding which nodes to place on the 198*3955d011SMarcel Moolenaar * toBeMade queue initially and by Make_Update to screen out USE and 199*3955d011SMarcel Moolenaar * EXEC nodes. In the latter case, however, any other sort of node 200*3955d011SMarcel Moolenaar * must be considered out-of-date since at least one of its children 201*3955d011SMarcel Moolenaar * will have been recreated. 202*3955d011SMarcel Moolenaar * 203*3955d011SMarcel Moolenaar * Input: 204*3955d011SMarcel Moolenaar * gn the node to check 205*3955d011SMarcel Moolenaar * 206*3955d011SMarcel Moolenaar * Results: 207*3955d011SMarcel Moolenaar * TRUE if the node is out of date. FALSE otherwise. 208*3955d011SMarcel Moolenaar * 209*3955d011SMarcel Moolenaar * Side Effects: 210*3955d011SMarcel Moolenaar * The mtime field of the node and the cmgn field of its parents 211*3955d011SMarcel Moolenaar * will/may be changed. 212*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 213*3955d011SMarcel Moolenaar */ 214*3955d011SMarcel Moolenaar Boolean 215*3955d011SMarcel Moolenaar Make_OODate(GNode *gn) 216*3955d011SMarcel Moolenaar { 217*3955d011SMarcel Moolenaar Boolean oodate; 218*3955d011SMarcel Moolenaar 219*3955d011SMarcel Moolenaar /* 220*3955d011SMarcel Moolenaar * Certain types of targets needn't even be sought as their datedness 221*3955d011SMarcel Moolenaar * doesn't depend on their modification time... 222*3955d011SMarcel Moolenaar */ 223*3955d011SMarcel Moolenaar if ((gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC)) == 0) { 224*3955d011SMarcel Moolenaar (void)Dir_MTime(gn, 1); 225*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 226*3955d011SMarcel Moolenaar if (gn->mtime != 0) { 227*3955d011SMarcel Moolenaar fprintf(debug_file, "modified %s...", Targ_FmtTime(gn->mtime)); 228*3955d011SMarcel Moolenaar } else { 229*3955d011SMarcel Moolenaar fprintf(debug_file, "non-existent..."); 230*3955d011SMarcel Moolenaar } 231*3955d011SMarcel Moolenaar } 232*3955d011SMarcel Moolenaar } 233*3955d011SMarcel Moolenaar 234*3955d011SMarcel Moolenaar /* 235*3955d011SMarcel Moolenaar * A target is remade in one of the following circumstances: 236*3955d011SMarcel Moolenaar * its modification time is smaller than that of its youngest child 237*3955d011SMarcel Moolenaar * and it would actually be run (has commands or type OP_NOP) 238*3955d011SMarcel Moolenaar * it's the object of a force operator 239*3955d011SMarcel Moolenaar * it has no children, was on the lhs of an operator and doesn't exist 240*3955d011SMarcel Moolenaar * already. 241*3955d011SMarcel Moolenaar * 242*3955d011SMarcel Moolenaar * Libraries are only considered out-of-date if the archive module says 243*3955d011SMarcel Moolenaar * they are. 244*3955d011SMarcel Moolenaar * 245*3955d011SMarcel Moolenaar * These weird rules are brought to you by Backward-Compatibility and 246*3955d011SMarcel Moolenaar * the strange people who wrote 'Make'. 247*3955d011SMarcel Moolenaar */ 248*3955d011SMarcel Moolenaar if (gn->type & (OP_USE|OP_USEBEFORE)) { 249*3955d011SMarcel Moolenaar /* 250*3955d011SMarcel Moolenaar * If the node is a USE node it is *never* out of date 251*3955d011SMarcel Moolenaar * no matter *what*. 252*3955d011SMarcel Moolenaar */ 253*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 254*3955d011SMarcel Moolenaar fprintf(debug_file, ".USE node..."); 255*3955d011SMarcel Moolenaar } 256*3955d011SMarcel Moolenaar oodate = FALSE; 257*3955d011SMarcel Moolenaar } else if ((gn->type & OP_LIB) && 258*3955d011SMarcel Moolenaar ((gn->mtime==0) || Arch_IsLib(gn))) { 259*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 260*3955d011SMarcel Moolenaar fprintf(debug_file, "library..."); 261*3955d011SMarcel Moolenaar } 262*3955d011SMarcel Moolenaar 263*3955d011SMarcel Moolenaar /* 264*3955d011SMarcel Moolenaar * always out of date if no children and :: target 265*3955d011SMarcel Moolenaar * or non-existent. 266*3955d011SMarcel Moolenaar */ 267*3955d011SMarcel Moolenaar oodate = (gn->mtime == 0 || Arch_LibOODate(gn) || 268*3955d011SMarcel Moolenaar (gn->cmgn == NULL && (gn->type & OP_DOUBLEDEP))); 269*3955d011SMarcel Moolenaar } else if (gn->type & OP_JOIN) { 270*3955d011SMarcel Moolenaar /* 271*3955d011SMarcel Moolenaar * A target with the .JOIN attribute is only considered 272*3955d011SMarcel Moolenaar * out-of-date if any of its children was out-of-date. 273*3955d011SMarcel Moolenaar */ 274*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 275*3955d011SMarcel Moolenaar fprintf(debug_file, ".JOIN node..."); 276*3955d011SMarcel Moolenaar } 277*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 278*3955d011SMarcel Moolenaar fprintf(debug_file, "source %smade...", gn->flags & CHILDMADE ? "" : "not "); 279*3955d011SMarcel Moolenaar } 280*3955d011SMarcel Moolenaar oodate = (gn->flags & CHILDMADE) ? TRUE : FALSE; 281*3955d011SMarcel Moolenaar } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) { 282*3955d011SMarcel Moolenaar /* 283*3955d011SMarcel Moolenaar * A node which is the object of the force (!) operator or which has 284*3955d011SMarcel Moolenaar * the .EXEC attribute is always considered out-of-date. 285*3955d011SMarcel Moolenaar */ 286*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 287*3955d011SMarcel Moolenaar if (gn->type & OP_FORCE) { 288*3955d011SMarcel Moolenaar fprintf(debug_file, "! operator..."); 289*3955d011SMarcel Moolenaar } else if (gn->type & OP_PHONY) { 290*3955d011SMarcel Moolenaar fprintf(debug_file, ".PHONY node..."); 291*3955d011SMarcel Moolenaar } else { 292*3955d011SMarcel Moolenaar fprintf(debug_file, ".EXEC node..."); 293*3955d011SMarcel Moolenaar } 294*3955d011SMarcel Moolenaar } 295*3955d011SMarcel Moolenaar oodate = TRUE; 296*3955d011SMarcel Moolenaar } else if ((gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime) || 297*3955d011SMarcel Moolenaar (gn->cmgn == NULL && 298*3955d011SMarcel Moolenaar ((gn->mtime == 0 && !(gn->type & OP_OPTIONAL)) 299*3955d011SMarcel Moolenaar || gn->type & OP_DOUBLEDEP))) 300*3955d011SMarcel Moolenaar { 301*3955d011SMarcel Moolenaar /* 302*3955d011SMarcel Moolenaar * A node whose modification time is less than that of its 303*3955d011SMarcel Moolenaar * youngest child or that has no children (cmgn == NULL) and 304*3955d011SMarcel Moolenaar * either doesn't exist (mtime == 0) and it isn't optional 305*3955d011SMarcel Moolenaar * or was the object of a * :: operator is out-of-date. 306*3955d011SMarcel Moolenaar * Why? Because that's the way Make does it. 307*3955d011SMarcel Moolenaar */ 308*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 309*3955d011SMarcel Moolenaar if (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime) { 310*3955d011SMarcel Moolenaar fprintf(debug_file, "modified before source %s...", 311*3955d011SMarcel Moolenaar gn->cmgn->path); 312*3955d011SMarcel Moolenaar } else if (gn->mtime == 0) { 313*3955d011SMarcel Moolenaar fprintf(debug_file, "non-existent and no sources..."); 314*3955d011SMarcel Moolenaar } else { 315*3955d011SMarcel Moolenaar fprintf(debug_file, ":: operator and no sources..."); 316*3955d011SMarcel Moolenaar } 317*3955d011SMarcel Moolenaar } 318*3955d011SMarcel Moolenaar oodate = TRUE; 319*3955d011SMarcel Moolenaar } else { 320*3955d011SMarcel Moolenaar /* 321*3955d011SMarcel Moolenaar * When a non-existing child with no sources 322*3955d011SMarcel Moolenaar * (such as a typically used FORCE source) has been made and 323*3955d011SMarcel Moolenaar * the target of the child (usually a directory) has the same 324*3955d011SMarcel Moolenaar * timestamp as the timestamp just given to the non-existing child 325*3955d011SMarcel Moolenaar * after it was considered made. 326*3955d011SMarcel Moolenaar */ 327*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 328*3955d011SMarcel Moolenaar if (gn->flags & FORCE) 329*3955d011SMarcel Moolenaar fprintf(debug_file, "non existing child..."); 330*3955d011SMarcel Moolenaar } 331*3955d011SMarcel Moolenaar oodate = (gn->flags & FORCE) ? TRUE : FALSE; 332*3955d011SMarcel Moolenaar } 333*3955d011SMarcel Moolenaar 334*3955d011SMarcel Moolenaar #ifdef USE_META 335*3955d011SMarcel Moolenaar if (useMeta) { 336*3955d011SMarcel Moolenaar oodate = meta_oodate(gn, oodate); 337*3955d011SMarcel Moolenaar } 338*3955d011SMarcel Moolenaar #endif 339*3955d011SMarcel Moolenaar 340*3955d011SMarcel Moolenaar /* 341*3955d011SMarcel Moolenaar * If the target isn't out-of-date, the parents need to know its 342*3955d011SMarcel Moolenaar * modification time. Note that targets that appear to be out-of-date 343*3955d011SMarcel Moolenaar * but aren't, because they have no commands and aren't of type OP_NOP, 344*3955d011SMarcel Moolenaar * have their mtime stay below their children's mtime to keep parents from 345*3955d011SMarcel Moolenaar * thinking they're out-of-date. 346*3955d011SMarcel Moolenaar */ 347*3955d011SMarcel Moolenaar if (!oodate) { 348*3955d011SMarcel Moolenaar Lst_ForEach(gn->parents, MakeTimeStamp, gn); 349*3955d011SMarcel Moolenaar } 350*3955d011SMarcel Moolenaar 351*3955d011SMarcel Moolenaar return (oodate); 352*3955d011SMarcel Moolenaar } 353*3955d011SMarcel Moolenaar 354*3955d011SMarcel Moolenaar /*- 355*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 356*3955d011SMarcel Moolenaar * MakeAddChild -- 357*3955d011SMarcel Moolenaar * Function used by Make_Run to add a child to the list l. 358*3955d011SMarcel Moolenaar * It will only add the child if its make field is FALSE. 359*3955d011SMarcel Moolenaar * 360*3955d011SMarcel Moolenaar * Input: 361*3955d011SMarcel Moolenaar * gnp the node to add 362*3955d011SMarcel Moolenaar * lp the list to which to add it 363*3955d011SMarcel Moolenaar * 364*3955d011SMarcel Moolenaar * Results: 365*3955d011SMarcel Moolenaar * Always returns 0 366*3955d011SMarcel Moolenaar * 367*3955d011SMarcel Moolenaar * Side Effects: 368*3955d011SMarcel Moolenaar * The given list is extended 369*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 370*3955d011SMarcel Moolenaar */ 371*3955d011SMarcel Moolenaar static int 372*3955d011SMarcel Moolenaar MakeAddChild(void *gnp, void *lp) 373*3955d011SMarcel Moolenaar { 374*3955d011SMarcel Moolenaar GNode *gn = (GNode *)gnp; 375*3955d011SMarcel Moolenaar Lst l = (Lst) lp; 376*3955d011SMarcel Moolenaar 377*3955d011SMarcel Moolenaar if ((gn->flags & REMAKE) == 0 && !(gn->type & (OP_USE|OP_USEBEFORE))) { 378*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 379*3955d011SMarcel Moolenaar fprintf(debug_file, "MakeAddChild: need to examine %s%s\n", 380*3955d011SMarcel Moolenaar gn->name, gn->cohort_num); 381*3955d011SMarcel Moolenaar (void)Lst_EnQueue(l, gn); 382*3955d011SMarcel Moolenaar } 383*3955d011SMarcel Moolenaar return (0); 384*3955d011SMarcel Moolenaar } 385*3955d011SMarcel Moolenaar 386*3955d011SMarcel Moolenaar /*- 387*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 388*3955d011SMarcel Moolenaar * MakeFindChild -- 389*3955d011SMarcel Moolenaar * Function used by Make_Run to find the pathname of a child 390*3955d011SMarcel Moolenaar * that was already made. 391*3955d011SMarcel Moolenaar * 392*3955d011SMarcel Moolenaar * Input: 393*3955d011SMarcel Moolenaar * gnp the node to find 394*3955d011SMarcel Moolenaar * 395*3955d011SMarcel Moolenaar * Results: 396*3955d011SMarcel Moolenaar * Always returns 0 397*3955d011SMarcel Moolenaar * 398*3955d011SMarcel Moolenaar * Side Effects: 399*3955d011SMarcel Moolenaar * The path and mtime of the node and the cmgn of the parent are 400*3955d011SMarcel Moolenaar * updated; the unmade children count of the parent is decremented. 401*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 402*3955d011SMarcel Moolenaar */ 403*3955d011SMarcel Moolenaar static int 404*3955d011SMarcel Moolenaar MakeFindChild(void *gnp, void *pgnp) 405*3955d011SMarcel Moolenaar { 406*3955d011SMarcel Moolenaar GNode *gn = (GNode *)gnp; 407*3955d011SMarcel Moolenaar GNode *pgn = (GNode *)pgnp; 408*3955d011SMarcel Moolenaar 409*3955d011SMarcel Moolenaar (void)Dir_MTime(gn, 0); 410*3955d011SMarcel Moolenaar Make_TimeStamp(pgn, gn); 411*3955d011SMarcel Moolenaar pgn->unmade--; 412*3955d011SMarcel Moolenaar 413*3955d011SMarcel Moolenaar return (0); 414*3955d011SMarcel Moolenaar } 415*3955d011SMarcel Moolenaar 416*3955d011SMarcel Moolenaar /*- 417*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 418*3955d011SMarcel Moolenaar * Make_HandleUse -- 419*3955d011SMarcel Moolenaar * Function called by Make_Run and SuffApplyTransform on the downward 420*3955d011SMarcel Moolenaar * pass to handle .USE and transformation nodes. It implements the 421*3955d011SMarcel Moolenaar * .USE and transformation functionality by copying the node's commands, 422*3955d011SMarcel Moolenaar * type flags and children to the parent node. 423*3955d011SMarcel Moolenaar * 424*3955d011SMarcel Moolenaar * A .USE node is much like an explicit transformation rule, except 425*3955d011SMarcel Moolenaar * its commands are always added to the target node, even if the 426*3955d011SMarcel Moolenaar * target already has commands. 427*3955d011SMarcel Moolenaar * 428*3955d011SMarcel Moolenaar * Input: 429*3955d011SMarcel Moolenaar * cgn The .USE node 430*3955d011SMarcel Moolenaar * pgn The target of the .USE node 431*3955d011SMarcel Moolenaar * 432*3955d011SMarcel Moolenaar * Results: 433*3955d011SMarcel Moolenaar * none 434*3955d011SMarcel Moolenaar * 435*3955d011SMarcel Moolenaar * Side Effects: 436*3955d011SMarcel Moolenaar * Children and commands may be added to the parent and the parent's 437*3955d011SMarcel Moolenaar * type may be changed. 438*3955d011SMarcel Moolenaar * 439*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 440*3955d011SMarcel Moolenaar */ 441*3955d011SMarcel Moolenaar void 442*3955d011SMarcel Moolenaar Make_HandleUse(GNode *cgn, GNode *pgn) 443*3955d011SMarcel Moolenaar { 444*3955d011SMarcel Moolenaar LstNode ln; /* An element in the children list */ 445*3955d011SMarcel Moolenaar 446*3955d011SMarcel Moolenaar #ifdef DEBUG_SRC 447*3955d011SMarcel Moolenaar if ((cgn->type & (OP_USE|OP_USEBEFORE|OP_TRANSFORM)) == 0) { 448*3955d011SMarcel Moolenaar fprintf(debug_file, "Make_HandleUse: called for plain node %s\n", cgn->name); 449*3955d011SMarcel Moolenaar return; 450*3955d011SMarcel Moolenaar } 451*3955d011SMarcel Moolenaar #endif 452*3955d011SMarcel Moolenaar 453*3955d011SMarcel Moolenaar if ((cgn->type & (OP_USE|OP_USEBEFORE)) || Lst_IsEmpty(pgn->commands)) { 454*3955d011SMarcel Moolenaar if (cgn->type & OP_USEBEFORE) { 455*3955d011SMarcel Moolenaar /* 456*3955d011SMarcel Moolenaar * .USEBEFORE -- 457*3955d011SMarcel Moolenaar * prepend the child's commands to the parent. 458*3955d011SMarcel Moolenaar */ 459*3955d011SMarcel Moolenaar Lst cmds = pgn->commands; 460*3955d011SMarcel Moolenaar pgn->commands = Lst_Duplicate(cgn->commands, NULL); 461*3955d011SMarcel Moolenaar (void)Lst_Concat(pgn->commands, cmds, LST_CONCNEW); 462*3955d011SMarcel Moolenaar Lst_Destroy(cmds, NULL); 463*3955d011SMarcel Moolenaar } else { 464*3955d011SMarcel Moolenaar /* 465*3955d011SMarcel Moolenaar * .USE or target has no commands -- 466*3955d011SMarcel Moolenaar * append the child's commands to the parent. 467*3955d011SMarcel Moolenaar */ 468*3955d011SMarcel Moolenaar (void)Lst_Concat(pgn->commands, cgn->commands, LST_CONCNEW); 469*3955d011SMarcel Moolenaar } 470*3955d011SMarcel Moolenaar } 471*3955d011SMarcel Moolenaar 472*3955d011SMarcel Moolenaar if (Lst_Open(cgn->children) == SUCCESS) { 473*3955d011SMarcel Moolenaar while ((ln = Lst_Next(cgn->children)) != NULL) { 474*3955d011SMarcel Moolenaar GNode *tgn, *gn = (GNode *)Lst_Datum(ln); 475*3955d011SMarcel Moolenaar 476*3955d011SMarcel Moolenaar /* 477*3955d011SMarcel Moolenaar * Expand variables in the .USE node's name 478*3955d011SMarcel Moolenaar * and save the unexpanded form. 479*3955d011SMarcel Moolenaar * We don't need to do this for commands. 480*3955d011SMarcel Moolenaar * They get expanded properly when we execute. 481*3955d011SMarcel Moolenaar */ 482*3955d011SMarcel Moolenaar if (gn->uname == NULL) { 483*3955d011SMarcel Moolenaar gn->uname = gn->name; 484*3955d011SMarcel Moolenaar } else { 485*3955d011SMarcel Moolenaar if (gn->name) 486*3955d011SMarcel Moolenaar free(gn->name); 487*3955d011SMarcel Moolenaar } 488*3955d011SMarcel Moolenaar gn->name = Var_Subst(NULL, gn->uname, pgn, FALSE); 489*3955d011SMarcel Moolenaar if (gn->name && gn->uname && strcmp(gn->name, gn->uname) != 0) { 490*3955d011SMarcel Moolenaar /* See if we have a target for this node. */ 491*3955d011SMarcel Moolenaar tgn = Targ_FindNode(gn->name, TARG_NOCREATE); 492*3955d011SMarcel Moolenaar if (tgn != NULL) 493*3955d011SMarcel Moolenaar gn = tgn; 494*3955d011SMarcel Moolenaar } 495*3955d011SMarcel Moolenaar 496*3955d011SMarcel Moolenaar (void)Lst_AtEnd(pgn->children, gn); 497*3955d011SMarcel Moolenaar (void)Lst_AtEnd(gn->parents, pgn); 498*3955d011SMarcel Moolenaar pgn->unmade += 1; 499*3955d011SMarcel Moolenaar } 500*3955d011SMarcel Moolenaar Lst_Close(cgn->children); 501*3955d011SMarcel Moolenaar } 502*3955d011SMarcel Moolenaar 503*3955d011SMarcel Moolenaar pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_USEBEFORE|OP_TRANSFORM); 504*3955d011SMarcel Moolenaar } 505*3955d011SMarcel Moolenaar 506*3955d011SMarcel Moolenaar /*- 507*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 508*3955d011SMarcel Moolenaar * MakeHandleUse -- 509*3955d011SMarcel Moolenaar * Callback function for Lst_ForEach, used by Make_Run on the downward 510*3955d011SMarcel Moolenaar * pass to handle .USE nodes. Should be called before the children 511*3955d011SMarcel Moolenaar * are enqueued to be looked at by MakeAddChild. 512*3955d011SMarcel Moolenaar * This function calls Make_HandleUse to copy the .USE node's commands, 513*3955d011SMarcel Moolenaar * type flags and children to the parent node. 514*3955d011SMarcel Moolenaar * 515*3955d011SMarcel Moolenaar * Input: 516*3955d011SMarcel Moolenaar * cgnp the child we've just examined 517*3955d011SMarcel Moolenaar * pgnp the current parent 518*3955d011SMarcel Moolenaar * 519*3955d011SMarcel Moolenaar * Results: 520*3955d011SMarcel Moolenaar * returns 0. 521*3955d011SMarcel Moolenaar * 522*3955d011SMarcel Moolenaar * Side Effects: 523*3955d011SMarcel Moolenaar * After expansion, .USE child nodes are removed from the parent 524*3955d011SMarcel Moolenaar * 525*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 526*3955d011SMarcel Moolenaar */ 527*3955d011SMarcel Moolenaar static int 528*3955d011SMarcel Moolenaar MakeHandleUse(void *cgnp, void *pgnp) 529*3955d011SMarcel Moolenaar { 530*3955d011SMarcel Moolenaar GNode *cgn = (GNode *)cgnp; 531*3955d011SMarcel Moolenaar GNode *pgn = (GNode *)pgnp; 532*3955d011SMarcel Moolenaar LstNode ln; /* An element in the children list */ 533*3955d011SMarcel Moolenaar int unmarked; 534*3955d011SMarcel Moolenaar 535*3955d011SMarcel Moolenaar unmarked = ((cgn->type & OP_MARK) == 0); 536*3955d011SMarcel Moolenaar cgn->type |= OP_MARK; 537*3955d011SMarcel Moolenaar 538*3955d011SMarcel Moolenaar if ((cgn->type & (OP_USE|OP_USEBEFORE)) == 0) 539*3955d011SMarcel Moolenaar return (0); 540*3955d011SMarcel Moolenaar 541*3955d011SMarcel Moolenaar if (unmarked) 542*3955d011SMarcel Moolenaar Make_HandleUse(cgn, pgn); 543*3955d011SMarcel Moolenaar 544*3955d011SMarcel Moolenaar /* 545*3955d011SMarcel Moolenaar * This child node is now "made", so we decrement the count of 546*3955d011SMarcel Moolenaar * unmade children in the parent... We also remove the child 547*3955d011SMarcel Moolenaar * from the parent's list to accurately reflect the number of decent 548*3955d011SMarcel Moolenaar * children the parent has. This is used by Make_Run to decide 549*3955d011SMarcel Moolenaar * whether to queue the parent or examine its children... 550*3955d011SMarcel Moolenaar */ 551*3955d011SMarcel Moolenaar if ((ln = Lst_Member(pgn->children, cgn)) != NULL) { 552*3955d011SMarcel Moolenaar Lst_Remove(pgn->children, ln); 553*3955d011SMarcel Moolenaar pgn->unmade--; 554*3955d011SMarcel Moolenaar } 555*3955d011SMarcel Moolenaar return (0); 556*3955d011SMarcel Moolenaar } 557*3955d011SMarcel Moolenaar 558*3955d011SMarcel Moolenaar 559*3955d011SMarcel Moolenaar /*- 560*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 561*3955d011SMarcel Moolenaar * Make_Recheck -- 562*3955d011SMarcel Moolenaar * Check the modification time of a gnode, and update it as described 563*3955d011SMarcel Moolenaar * in the comments below. 564*3955d011SMarcel Moolenaar * 565*3955d011SMarcel Moolenaar * Results: 566*3955d011SMarcel Moolenaar * returns 0 if the gnode does not exist, or it's filesystem 567*3955d011SMarcel Moolenaar * time if it does. 568*3955d011SMarcel Moolenaar * 569*3955d011SMarcel Moolenaar * Side Effects: 570*3955d011SMarcel Moolenaar * the gnode's modification time and path name are affected. 571*3955d011SMarcel Moolenaar * 572*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 573*3955d011SMarcel Moolenaar */ 574*3955d011SMarcel Moolenaar time_t 575*3955d011SMarcel Moolenaar Make_Recheck(GNode *gn) 576*3955d011SMarcel Moolenaar { 577*3955d011SMarcel Moolenaar time_t mtime = Dir_MTime(gn, 1); 578*3955d011SMarcel Moolenaar 579*3955d011SMarcel Moolenaar #ifndef RECHECK 580*3955d011SMarcel Moolenaar /* 581*3955d011SMarcel Moolenaar * We can't re-stat the thing, but we can at least take care of rules 582*3955d011SMarcel Moolenaar * where a target depends on a source that actually creates the 583*3955d011SMarcel Moolenaar * target, but only if it has changed, e.g. 584*3955d011SMarcel Moolenaar * 585*3955d011SMarcel Moolenaar * parse.h : parse.o 586*3955d011SMarcel Moolenaar * 587*3955d011SMarcel Moolenaar * parse.o : parse.y 588*3955d011SMarcel Moolenaar * yacc -d parse.y 589*3955d011SMarcel Moolenaar * cc -c y.tab.c 590*3955d011SMarcel Moolenaar * mv y.tab.o parse.o 591*3955d011SMarcel Moolenaar * cmp -s y.tab.h parse.h || mv y.tab.h parse.h 592*3955d011SMarcel Moolenaar * 593*3955d011SMarcel Moolenaar * In this case, if the definitions produced by yacc haven't changed 594*3955d011SMarcel Moolenaar * from before, parse.h won't have been updated and gn->mtime will 595*3955d011SMarcel Moolenaar * reflect the current modification time for parse.h. This is 596*3955d011SMarcel Moolenaar * something of a kludge, I admit, but it's a useful one.. 597*3955d011SMarcel Moolenaar * XXX: People like to use a rule like 598*3955d011SMarcel Moolenaar * 599*3955d011SMarcel Moolenaar * FRC: 600*3955d011SMarcel Moolenaar * 601*3955d011SMarcel Moolenaar * To force things that depend on FRC to be made, so we have to 602*3955d011SMarcel Moolenaar * check for gn->children being empty as well... 603*3955d011SMarcel Moolenaar */ 604*3955d011SMarcel Moolenaar if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) { 605*3955d011SMarcel Moolenaar gn->mtime = now; 606*3955d011SMarcel Moolenaar } 607*3955d011SMarcel Moolenaar #else 608*3955d011SMarcel Moolenaar /* 609*3955d011SMarcel Moolenaar * This is what Make does and it's actually a good thing, as it 610*3955d011SMarcel Moolenaar * allows rules like 611*3955d011SMarcel Moolenaar * 612*3955d011SMarcel Moolenaar * cmp -s y.tab.h parse.h || cp y.tab.h parse.h 613*3955d011SMarcel Moolenaar * 614*3955d011SMarcel Moolenaar * to function as intended. Unfortunately, thanks to the stateless 615*3955d011SMarcel Moolenaar * nature of NFS (by which I mean the loose coupling of two clients 616*3955d011SMarcel Moolenaar * using the same file from a common server), there are times 617*3955d011SMarcel Moolenaar * when the modification time of a file created on a remote 618*3955d011SMarcel Moolenaar * machine will not be modified before the local stat() implied by 619*3955d011SMarcel Moolenaar * the Dir_MTime occurs, thus leading us to believe that the file 620*3955d011SMarcel Moolenaar * is unchanged, wreaking havoc with files that depend on this one. 621*3955d011SMarcel Moolenaar * 622*3955d011SMarcel Moolenaar * I have decided it is better to make too much than to make too 623*3955d011SMarcel Moolenaar * little, so this stuff is commented out unless you're sure it's ok. 624*3955d011SMarcel Moolenaar * -- ardeb 1/12/88 625*3955d011SMarcel Moolenaar */ 626*3955d011SMarcel Moolenaar /* 627*3955d011SMarcel Moolenaar * Christos, 4/9/92: If we are saving commands pretend that 628*3955d011SMarcel Moolenaar * the target is made now. Otherwise archives with ... rules 629*3955d011SMarcel Moolenaar * don't work! 630*3955d011SMarcel Moolenaar */ 631*3955d011SMarcel Moolenaar if (NoExecute(gn) || (gn->type & OP_SAVE_CMDS) || 632*3955d011SMarcel Moolenaar (mtime == 0 && !(gn->type & OP_WAIT))) { 633*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 634*3955d011SMarcel Moolenaar fprintf(debug_file, " recheck(%s): update time from %s to now\n", 635*3955d011SMarcel Moolenaar gn->name, Targ_FmtTime(gn->mtime)); 636*3955d011SMarcel Moolenaar } 637*3955d011SMarcel Moolenaar gn->mtime = now; 638*3955d011SMarcel Moolenaar } 639*3955d011SMarcel Moolenaar else { 640*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 641*3955d011SMarcel Moolenaar fprintf(debug_file, " recheck(%s): current update time: %s\n", 642*3955d011SMarcel Moolenaar gn->name, Targ_FmtTime(gn->mtime)); 643*3955d011SMarcel Moolenaar } 644*3955d011SMarcel Moolenaar } 645*3955d011SMarcel Moolenaar #endif 646*3955d011SMarcel Moolenaar return mtime; 647*3955d011SMarcel Moolenaar } 648*3955d011SMarcel Moolenaar 649*3955d011SMarcel Moolenaar /*- 650*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 651*3955d011SMarcel Moolenaar * Make_Update -- 652*3955d011SMarcel Moolenaar * Perform update on the parents of a node. Used by JobFinish once 653*3955d011SMarcel Moolenaar * a node has been dealt with and by MakeStartJobs if it finds an 654*3955d011SMarcel Moolenaar * up-to-date node. 655*3955d011SMarcel Moolenaar * 656*3955d011SMarcel Moolenaar * Input: 657*3955d011SMarcel Moolenaar * cgn the child node 658*3955d011SMarcel Moolenaar * 659*3955d011SMarcel Moolenaar * Results: 660*3955d011SMarcel Moolenaar * Always returns 0 661*3955d011SMarcel Moolenaar * 662*3955d011SMarcel Moolenaar * Side Effects: 663*3955d011SMarcel Moolenaar * The unmade field of pgn is decremented and pgn may be placed on 664*3955d011SMarcel Moolenaar * the toBeMade queue if this field becomes 0. 665*3955d011SMarcel Moolenaar * 666*3955d011SMarcel Moolenaar * If the child was made, the parent's flag CHILDMADE field will be 667*3955d011SMarcel Moolenaar * set true. 668*3955d011SMarcel Moolenaar * 669*3955d011SMarcel Moolenaar * If the child is not up-to-date and still does not exist, 670*3955d011SMarcel Moolenaar * set the FORCE flag on the parents. 671*3955d011SMarcel Moolenaar * 672*3955d011SMarcel Moolenaar * If the child wasn't made, the cmgn field of the parent will be 673*3955d011SMarcel Moolenaar * altered if the child's mtime is big enough. 674*3955d011SMarcel Moolenaar * 675*3955d011SMarcel Moolenaar * Finally, if the child is the implied source for the parent, the 676*3955d011SMarcel Moolenaar * parent's IMPSRC variable is set appropriately. 677*3955d011SMarcel Moolenaar * 678*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 679*3955d011SMarcel Moolenaar */ 680*3955d011SMarcel Moolenaar void 681*3955d011SMarcel Moolenaar Make_Update(GNode *cgn) 682*3955d011SMarcel Moolenaar { 683*3955d011SMarcel Moolenaar GNode *pgn; /* the parent node */ 684*3955d011SMarcel Moolenaar char *cname; /* the child's name */ 685*3955d011SMarcel Moolenaar LstNode ln; /* Element in parents and iParents lists */ 686*3955d011SMarcel Moolenaar time_t mtime = -1; 687*3955d011SMarcel Moolenaar char *p1; 688*3955d011SMarcel Moolenaar Lst parents; 689*3955d011SMarcel Moolenaar GNode *centurion; 690*3955d011SMarcel Moolenaar 691*3955d011SMarcel Moolenaar /* It is save to re-examine any nodes again */ 692*3955d011SMarcel Moolenaar checked++; 693*3955d011SMarcel Moolenaar 694*3955d011SMarcel Moolenaar cname = Var_Value(TARGET, cgn, &p1); 695*3955d011SMarcel Moolenaar if (p1) 696*3955d011SMarcel Moolenaar free(p1); 697*3955d011SMarcel Moolenaar 698*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 699*3955d011SMarcel Moolenaar fprintf(debug_file, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num); 700*3955d011SMarcel Moolenaar 701*3955d011SMarcel Moolenaar /* 702*3955d011SMarcel Moolenaar * If the child was actually made, see what its modification time is 703*3955d011SMarcel Moolenaar * now -- some rules won't actually update the file. If the file still 704*3955d011SMarcel Moolenaar * doesn't exist, make its mtime now. 705*3955d011SMarcel Moolenaar */ 706*3955d011SMarcel Moolenaar if (cgn->made != UPTODATE) { 707*3955d011SMarcel Moolenaar mtime = Make_Recheck(cgn); 708*3955d011SMarcel Moolenaar } 709*3955d011SMarcel Moolenaar 710*3955d011SMarcel Moolenaar /* 711*3955d011SMarcel Moolenaar * If this is a `::' node, we must consult its first instance 712*3955d011SMarcel Moolenaar * which is where all parents are linked. 713*3955d011SMarcel Moolenaar */ 714*3955d011SMarcel Moolenaar if ((centurion = cgn->centurion) != NULL) { 715*3955d011SMarcel Moolenaar if (!Lst_IsEmpty(cgn->parents)) 716*3955d011SMarcel Moolenaar Punt("%s%s: cohort has parents", cgn->name, cgn->cohort_num); 717*3955d011SMarcel Moolenaar centurion->unmade_cohorts -= 1; 718*3955d011SMarcel Moolenaar if (centurion->unmade_cohorts < 0) 719*3955d011SMarcel Moolenaar Error("Graph cycles through centurion %s", centurion->name); 720*3955d011SMarcel Moolenaar } else { 721*3955d011SMarcel Moolenaar centurion = cgn; 722*3955d011SMarcel Moolenaar } 723*3955d011SMarcel Moolenaar parents = centurion->parents; 724*3955d011SMarcel Moolenaar 725*3955d011SMarcel Moolenaar /* If this was a .ORDER node, schedule the RHS */ 726*3955d011SMarcel Moolenaar Lst_ForEach(centurion->order_succ, MakeBuildParent, Lst_First(toBeMade)); 727*3955d011SMarcel Moolenaar 728*3955d011SMarcel Moolenaar /* Now mark all the parents as having one less unmade child */ 729*3955d011SMarcel Moolenaar if (Lst_Open(parents) == SUCCESS) { 730*3955d011SMarcel Moolenaar while ((ln = Lst_Next(parents)) != NULL) { 731*3955d011SMarcel Moolenaar pgn = (GNode *)Lst_Datum(ln); 732*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 733*3955d011SMarcel Moolenaar fprintf(debug_file, "inspect parent %s%s: flags %x, " 734*3955d011SMarcel Moolenaar "type %x, made %d, unmade %d ", 735*3955d011SMarcel Moolenaar pgn->name, pgn->cohort_num, pgn->flags, 736*3955d011SMarcel Moolenaar pgn->type, pgn->made, pgn->unmade-1); 737*3955d011SMarcel Moolenaar 738*3955d011SMarcel Moolenaar if (!(pgn->flags & REMAKE)) { 739*3955d011SMarcel Moolenaar /* This parent isn't needed */ 740*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 741*3955d011SMarcel Moolenaar fprintf(debug_file, "- not needed\n"); 742*3955d011SMarcel Moolenaar continue; 743*3955d011SMarcel Moolenaar } 744*3955d011SMarcel Moolenaar if (mtime == 0 && !(cgn->type & OP_WAIT)) 745*3955d011SMarcel Moolenaar pgn->flags |= FORCE; 746*3955d011SMarcel Moolenaar 747*3955d011SMarcel Moolenaar /* 748*3955d011SMarcel Moolenaar * If the parent has the .MADE attribute, its timestamp got 749*3955d011SMarcel Moolenaar * updated to that of its newest child, and its unmake 750*3955d011SMarcel Moolenaar * child count got set to zero in Make_ExpandUse(). 751*3955d011SMarcel Moolenaar * However other things might cause us to build one of its 752*3955d011SMarcel Moolenaar * children - and so we mustn't do any processing here when 753*3955d011SMarcel Moolenaar * the child build finishes. 754*3955d011SMarcel Moolenaar */ 755*3955d011SMarcel Moolenaar if (pgn->type & OP_MADE) { 756*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 757*3955d011SMarcel Moolenaar fprintf(debug_file, "- .MADE\n"); 758*3955d011SMarcel Moolenaar continue; 759*3955d011SMarcel Moolenaar } 760*3955d011SMarcel Moolenaar 761*3955d011SMarcel Moolenaar if ( ! (cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE))) { 762*3955d011SMarcel Moolenaar if (cgn->made == MADE) 763*3955d011SMarcel Moolenaar pgn->flags |= CHILDMADE; 764*3955d011SMarcel Moolenaar (void)Make_TimeStamp(pgn, cgn); 765*3955d011SMarcel Moolenaar } 766*3955d011SMarcel Moolenaar 767*3955d011SMarcel Moolenaar /* 768*3955d011SMarcel Moolenaar * A parent must wait for the completion of all instances 769*3955d011SMarcel Moolenaar * of a `::' dependency. 770*3955d011SMarcel Moolenaar */ 771*3955d011SMarcel Moolenaar if (centurion->unmade_cohorts != 0 || centurion->made < MADE) { 772*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 773*3955d011SMarcel Moolenaar fprintf(debug_file, 774*3955d011SMarcel Moolenaar "- centurion made %d, %d unmade cohorts\n", 775*3955d011SMarcel Moolenaar centurion->made, centurion->unmade_cohorts); 776*3955d011SMarcel Moolenaar continue; 777*3955d011SMarcel Moolenaar } 778*3955d011SMarcel Moolenaar 779*3955d011SMarcel Moolenaar /* One more child of this parent is now made */ 780*3955d011SMarcel Moolenaar pgn->unmade -= 1; 781*3955d011SMarcel Moolenaar if (pgn->unmade < 0) { 782*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 783*3955d011SMarcel Moolenaar fprintf(debug_file, "Graph cycles through %s%s\n", 784*3955d011SMarcel Moolenaar pgn->name, pgn->cohort_num); 785*3955d011SMarcel Moolenaar Targ_PrintGraph(2); 786*3955d011SMarcel Moolenaar } 787*3955d011SMarcel Moolenaar Error("Graph cycles through %s%s", pgn->name, pgn->cohort_num); 788*3955d011SMarcel Moolenaar } 789*3955d011SMarcel Moolenaar 790*3955d011SMarcel Moolenaar /* We must always rescan the parents of .WAIT and .ORDER nodes. */ 791*3955d011SMarcel Moolenaar if (pgn->unmade != 0 && !(centurion->type & OP_WAIT) 792*3955d011SMarcel Moolenaar && !(centurion->flags & DONE_ORDER)) { 793*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 794*3955d011SMarcel Moolenaar fprintf(debug_file, "- unmade children\n"); 795*3955d011SMarcel Moolenaar continue; 796*3955d011SMarcel Moolenaar } 797*3955d011SMarcel Moolenaar if (pgn->made != DEFERRED) { 798*3955d011SMarcel Moolenaar /* 799*3955d011SMarcel Moolenaar * Either this parent is on a different branch of the tree, 800*3955d011SMarcel Moolenaar * or it on the RHS of a .WAIT directive 801*3955d011SMarcel Moolenaar * or it is already on the toBeMade list. 802*3955d011SMarcel Moolenaar */ 803*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 804*3955d011SMarcel Moolenaar fprintf(debug_file, "- not deferred\n"); 805*3955d011SMarcel Moolenaar continue; 806*3955d011SMarcel Moolenaar } 807*3955d011SMarcel Moolenaar if (pgn->order_pred 808*3955d011SMarcel Moolenaar && Lst_ForEach(pgn->order_pred, MakeCheckOrder, 0)) { 809*3955d011SMarcel Moolenaar /* A .ORDER rule stops us building this */ 810*3955d011SMarcel Moolenaar continue; 811*3955d011SMarcel Moolenaar } 812*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 813*3955d011SMarcel Moolenaar static int two = 2; 814*3955d011SMarcel Moolenaar fprintf(debug_file, "- %s%s made, schedule %s%s (made %d)\n", 815*3955d011SMarcel Moolenaar cgn->name, cgn->cohort_num, 816*3955d011SMarcel Moolenaar pgn->name, pgn->cohort_num, pgn->made); 817*3955d011SMarcel Moolenaar Targ_PrintNode(pgn, &two); 818*3955d011SMarcel Moolenaar } 819*3955d011SMarcel Moolenaar /* Ok, we can schedule the parent again */ 820*3955d011SMarcel Moolenaar pgn->made = REQUESTED; 821*3955d011SMarcel Moolenaar (void)Lst_EnQueue(toBeMade, pgn); 822*3955d011SMarcel Moolenaar } 823*3955d011SMarcel Moolenaar Lst_Close(parents); 824*3955d011SMarcel Moolenaar } 825*3955d011SMarcel Moolenaar 826*3955d011SMarcel Moolenaar /* 827*3955d011SMarcel Moolenaar * Set the .PREFIX and .IMPSRC variables for all the implied parents 828*3955d011SMarcel Moolenaar * of this node. 829*3955d011SMarcel Moolenaar */ 830*3955d011SMarcel Moolenaar if (Lst_Open(cgn->iParents) == SUCCESS) { 831*3955d011SMarcel Moolenaar char *cpref = Var_Value(PREFIX, cgn, &p1); 832*3955d011SMarcel Moolenaar 833*3955d011SMarcel Moolenaar while ((ln = Lst_Next(cgn->iParents)) != NULL) { 834*3955d011SMarcel Moolenaar pgn = (GNode *)Lst_Datum(ln); 835*3955d011SMarcel Moolenaar if (pgn->flags & REMAKE) { 836*3955d011SMarcel Moolenaar Var_Set(IMPSRC, cname, pgn, 0); 837*3955d011SMarcel Moolenaar if (cpref != NULL) 838*3955d011SMarcel Moolenaar Var_Set(PREFIX, cpref, pgn, 0); 839*3955d011SMarcel Moolenaar } 840*3955d011SMarcel Moolenaar } 841*3955d011SMarcel Moolenaar if (p1) 842*3955d011SMarcel Moolenaar free(p1); 843*3955d011SMarcel Moolenaar Lst_Close(cgn->iParents); 844*3955d011SMarcel Moolenaar } 845*3955d011SMarcel Moolenaar } 846*3955d011SMarcel Moolenaar 847*3955d011SMarcel Moolenaar /*- 848*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 849*3955d011SMarcel Moolenaar * MakeAddAllSrc -- 850*3955d011SMarcel Moolenaar * Add a child's name to the ALLSRC and OODATE variables of the given 851*3955d011SMarcel Moolenaar * node. Called from Make_DoAllVar via Lst_ForEach. A child is added only 852*3955d011SMarcel Moolenaar * if it has not been given the .EXEC, .USE or .INVISIBLE attributes. 853*3955d011SMarcel Moolenaar * .EXEC and .USE children are very rarely going to be files, so... 854*3955d011SMarcel Moolenaar * If the child is a .JOIN node, its ALLSRC is propagated to the parent. 855*3955d011SMarcel Moolenaar * 856*3955d011SMarcel Moolenaar * A child is added to the OODATE variable if its modification time is 857*3955d011SMarcel Moolenaar * later than that of its parent, as defined by Make, except if the 858*3955d011SMarcel Moolenaar * parent is a .JOIN node. In that case, it is only added to the OODATE 859*3955d011SMarcel Moolenaar * variable if it was actually made (since .JOIN nodes don't have 860*3955d011SMarcel Moolenaar * modification times, the comparison is rather unfair...).. 861*3955d011SMarcel Moolenaar * 862*3955d011SMarcel Moolenaar * Results: 863*3955d011SMarcel Moolenaar * Always returns 0 864*3955d011SMarcel Moolenaar * 865*3955d011SMarcel Moolenaar * Side Effects: 866*3955d011SMarcel Moolenaar * The ALLSRC variable for the given node is extended. 867*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 868*3955d011SMarcel Moolenaar */ 869*3955d011SMarcel Moolenaar static int 870*3955d011SMarcel Moolenaar MakeUnmark(void *cgnp, void *pgnp MAKE_ATTR_UNUSED) 871*3955d011SMarcel Moolenaar { 872*3955d011SMarcel Moolenaar GNode *cgn = (GNode *)cgnp; 873*3955d011SMarcel Moolenaar 874*3955d011SMarcel Moolenaar cgn->type &= ~OP_MARK; 875*3955d011SMarcel Moolenaar return (0); 876*3955d011SMarcel Moolenaar } 877*3955d011SMarcel Moolenaar 878*3955d011SMarcel Moolenaar /* 879*3955d011SMarcel Moolenaar * Input: 880*3955d011SMarcel Moolenaar * cgnp The child to add 881*3955d011SMarcel Moolenaar * pgnp The parent to whose ALLSRC variable it should 882*3955d011SMarcel Moolenaar * be added 883*3955d011SMarcel Moolenaar * 884*3955d011SMarcel Moolenaar */ 885*3955d011SMarcel Moolenaar static int 886*3955d011SMarcel Moolenaar MakeAddAllSrc(void *cgnp, void *pgnp) 887*3955d011SMarcel Moolenaar { 888*3955d011SMarcel Moolenaar GNode *cgn = (GNode *)cgnp; 889*3955d011SMarcel Moolenaar GNode *pgn = (GNode *)pgnp; 890*3955d011SMarcel Moolenaar 891*3955d011SMarcel Moolenaar if (cgn->type & OP_MARK) 892*3955d011SMarcel Moolenaar return (0); 893*3955d011SMarcel Moolenaar cgn->type |= OP_MARK; 894*3955d011SMarcel Moolenaar 895*3955d011SMarcel Moolenaar if ((cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE|OP_INVISIBLE)) == 0) { 896*3955d011SMarcel Moolenaar char *child, *allsrc; 897*3955d011SMarcel Moolenaar char *p1 = NULL, *p2 = NULL; 898*3955d011SMarcel Moolenaar 899*3955d011SMarcel Moolenaar if (cgn->type & OP_ARCHV) 900*3955d011SMarcel Moolenaar child = Var_Value(MEMBER, cgn, &p1); 901*3955d011SMarcel Moolenaar else 902*3955d011SMarcel Moolenaar child = cgn->path ? cgn->path : cgn->name; 903*3955d011SMarcel Moolenaar if (cgn->type & OP_JOIN) { 904*3955d011SMarcel Moolenaar allsrc = Var_Value(ALLSRC, cgn, &p2); 905*3955d011SMarcel Moolenaar } else { 906*3955d011SMarcel Moolenaar allsrc = child; 907*3955d011SMarcel Moolenaar } 908*3955d011SMarcel Moolenaar if (allsrc != NULL) 909*3955d011SMarcel Moolenaar Var_Append(ALLSRC, allsrc, pgn); 910*3955d011SMarcel Moolenaar if (p2) 911*3955d011SMarcel Moolenaar free(p2); 912*3955d011SMarcel Moolenaar if (pgn->type & OP_JOIN) { 913*3955d011SMarcel Moolenaar if (cgn->made == MADE) { 914*3955d011SMarcel Moolenaar Var_Append(OODATE, child, pgn); 915*3955d011SMarcel Moolenaar } 916*3955d011SMarcel Moolenaar } else if ((pgn->mtime < cgn->mtime) || 917*3955d011SMarcel Moolenaar (cgn->mtime >= now && cgn->made == MADE)) 918*3955d011SMarcel Moolenaar { 919*3955d011SMarcel Moolenaar /* 920*3955d011SMarcel Moolenaar * It goes in the OODATE variable if the parent is younger than the 921*3955d011SMarcel Moolenaar * child or if the child has been modified more recently than 922*3955d011SMarcel Moolenaar * the start of the make. This is to keep pmake from getting 923*3955d011SMarcel Moolenaar * confused if something else updates the parent after the 924*3955d011SMarcel Moolenaar * make starts (shouldn't happen, I know, but sometimes it 925*3955d011SMarcel Moolenaar * does). In such a case, if we've updated the kid, the parent 926*3955d011SMarcel Moolenaar * is likely to have a modification time later than that of 927*3955d011SMarcel Moolenaar * the kid and anything that relies on the OODATE variable will 928*3955d011SMarcel Moolenaar * be hosed. 929*3955d011SMarcel Moolenaar * 930*3955d011SMarcel Moolenaar * XXX: This will cause all made children to go in the OODATE 931*3955d011SMarcel Moolenaar * variable, even if they're not touched, if RECHECK isn't defined, 932*3955d011SMarcel Moolenaar * since cgn->mtime is set to now in Make_Update. According to 933*3955d011SMarcel Moolenaar * some people, this is good... 934*3955d011SMarcel Moolenaar */ 935*3955d011SMarcel Moolenaar Var_Append(OODATE, child, pgn); 936*3955d011SMarcel Moolenaar } 937*3955d011SMarcel Moolenaar if (p1) 938*3955d011SMarcel Moolenaar free(p1); 939*3955d011SMarcel Moolenaar } 940*3955d011SMarcel Moolenaar return (0); 941*3955d011SMarcel Moolenaar } 942*3955d011SMarcel Moolenaar 943*3955d011SMarcel Moolenaar /*- 944*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 945*3955d011SMarcel Moolenaar * Make_DoAllVar -- 946*3955d011SMarcel Moolenaar * Set up the ALLSRC and OODATE variables. Sad to say, it must be 947*3955d011SMarcel Moolenaar * done separately, rather than while traversing the graph. This is 948*3955d011SMarcel Moolenaar * because Make defined OODATE to contain all sources whose modification 949*3955d011SMarcel Moolenaar * times were later than that of the target, *not* those sources that 950*3955d011SMarcel Moolenaar * were out-of-date. Since in both compatibility and native modes, 951*3955d011SMarcel Moolenaar * the modification time of the parent isn't found until the child 952*3955d011SMarcel Moolenaar * has been dealt with, we have to wait until now to fill in the 953*3955d011SMarcel Moolenaar * variable. As for ALLSRC, the ordering is important and not 954*3955d011SMarcel Moolenaar * guaranteed when in native mode, so it must be set here, too. 955*3955d011SMarcel Moolenaar * 956*3955d011SMarcel Moolenaar * Results: 957*3955d011SMarcel Moolenaar * None 958*3955d011SMarcel Moolenaar * 959*3955d011SMarcel Moolenaar * Side Effects: 960*3955d011SMarcel Moolenaar * The ALLSRC and OODATE variables of the given node is filled in. 961*3955d011SMarcel Moolenaar * If the node is a .JOIN node, its TARGET variable will be set to 962*3955d011SMarcel Moolenaar * match its ALLSRC variable. 963*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 964*3955d011SMarcel Moolenaar */ 965*3955d011SMarcel Moolenaar void 966*3955d011SMarcel Moolenaar Make_DoAllVar(GNode *gn) 967*3955d011SMarcel Moolenaar { 968*3955d011SMarcel Moolenaar if (gn->flags & DONE_ALLSRC) 969*3955d011SMarcel Moolenaar return; 970*3955d011SMarcel Moolenaar 971*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeUnmark, gn); 972*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeAddAllSrc, gn); 973*3955d011SMarcel Moolenaar 974*3955d011SMarcel Moolenaar if (!Var_Exists (OODATE, gn)) { 975*3955d011SMarcel Moolenaar Var_Set(OODATE, "", gn, 0); 976*3955d011SMarcel Moolenaar } 977*3955d011SMarcel Moolenaar if (!Var_Exists (ALLSRC, gn)) { 978*3955d011SMarcel Moolenaar Var_Set(ALLSRC, "", gn, 0); 979*3955d011SMarcel Moolenaar } 980*3955d011SMarcel Moolenaar 981*3955d011SMarcel Moolenaar if (gn->type & OP_JOIN) { 982*3955d011SMarcel Moolenaar char *p1; 983*3955d011SMarcel Moolenaar Var_Set(TARGET, Var_Value(ALLSRC, gn, &p1), gn, 0); 984*3955d011SMarcel Moolenaar if (p1) 985*3955d011SMarcel Moolenaar free(p1); 986*3955d011SMarcel Moolenaar } 987*3955d011SMarcel Moolenaar gn->flags |= DONE_ALLSRC; 988*3955d011SMarcel Moolenaar } 989*3955d011SMarcel Moolenaar 990*3955d011SMarcel Moolenaar /*- 991*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 992*3955d011SMarcel Moolenaar * MakeStartJobs -- 993*3955d011SMarcel Moolenaar * Start as many jobs as possible. 994*3955d011SMarcel Moolenaar * 995*3955d011SMarcel Moolenaar * Results: 996*3955d011SMarcel Moolenaar * If the query flag was given to pmake, no job will be started, 997*3955d011SMarcel Moolenaar * but as soon as an out-of-date target is found, this function 998*3955d011SMarcel Moolenaar * returns TRUE. At all other times, this function returns FALSE. 999*3955d011SMarcel Moolenaar * 1000*3955d011SMarcel Moolenaar * Side Effects: 1001*3955d011SMarcel Moolenaar * Nodes are removed from the toBeMade queue and job table slots 1002*3955d011SMarcel Moolenaar * are filled. 1003*3955d011SMarcel Moolenaar * 1004*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1005*3955d011SMarcel Moolenaar */ 1006*3955d011SMarcel Moolenaar 1007*3955d011SMarcel Moolenaar static int 1008*3955d011SMarcel Moolenaar MakeCheckOrder(void *v_bn, void *ignore MAKE_ATTR_UNUSED) 1009*3955d011SMarcel Moolenaar { 1010*3955d011SMarcel Moolenaar GNode *bn = v_bn; 1011*3955d011SMarcel Moolenaar 1012*3955d011SMarcel Moolenaar if (bn->made >= MADE || !(bn->flags & REMAKE)) 1013*3955d011SMarcel Moolenaar return 0; 1014*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1015*3955d011SMarcel Moolenaar fprintf(debug_file, "MakeCheckOrder: Waiting for .ORDER node %s%s\n", 1016*3955d011SMarcel Moolenaar bn->name, bn->cohort_num); 1017*3955d011SMarcel Moolenaar return 1; 1018*3955d011SMarcel Moolenaar } 1019*3955d011SMarcel Moolenaar 1020*3955d011SMarcel Moolenaar static int 1021*3955d011SMarcel Moolenaar MakeBuildChild(void *v_cn, void *toBeMade_next) 1022*3955d011SMarcel Moolenaar { 1023*3955d011SMarcel Moolenaar GNode *cn = v_cn; 1024*3955d011SMarcel Moolenaar 1025*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1026*3955d011SMarcel Moolenaar fprintf(debug_file, "MakeBuildChild: inspect %s%s, made %d, type %x\n", 1027*3955d011SMarcel Moolenaar cn->name, cn->cohort_num, cn->made, cn->type); 1028*3955d011SMarcel Moolenaar if (cn->made > DEFERRED) 1029*3955d011SMarcel Moolenaar return 0; 1030*3955d011SMarcel Moolenaar 1031*3955d011SMarcel Moolenaar /* If this node is on the RHS of a .ORDER, check LHSs. */ 1032*3955d011SMarcel Moolenaar if (cn->order_pred && Lst_ForEach(cn->order_pred, MakeCheckOrder, 0)) { 1033*3955d011SMarcel Moolenaar /* Can't build this (or anything else in this child list) yet */ 1034*3955d011SMarcel Moolenaar cn->made = DEFERRED; 1035*3955d011SMarcel Moolenaar return 1; 1036*3955d011SMarcel Moolenaar } 1037*3955d011SMarcel Moolenaar 1038*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1039*3955d011SMarcel Moolenaar fprintf(debug_file, "MakeBuildChild: schedule %s%s\n", 1040*3955d011SMarcel Moolenaar cn->name, cn->cohort_num); 1041*3955d011SMarcel Moolenaar 1042*3955d011SMarcel Moolenaar cn->made = REQUESTED; 1043*3955d011SMarcel Moolenaar if (toBeMade_next == NULL) 1044*3955d011SMarcel Moolenaar Lst_AtEnd(toBeMade, cn); 1045*3955d011SMarcel Moolenaar else 1046*3955d011SMarcel Moolenaar Lst_InsertBefore(toBeMade, toBeMade_next, cn); 1047*3955d011SMarcel Moolenaar 1048*3955d011SMarcel Moolenaar if (cn->unmade_cohorts != 0) 1049*3955d011SMarcel Moolenaar Lst_ForEach(cn->cohorts, MakeBuildChild, toBeMade_next); 1050*3955d011SMarcel Moolenaar 1051*3955d011SMarcel Moolenaar /* 1052*3955d011SMarcel Moolenaar * If this node is a .WAIT node with unmade chlidren 1053*3955d011SMarcel Moolenaar * then don't add the next sibling. 1054*3955d011SMarcel Moolenaar */ 1055*3955d011SMarcel Moolenaar return cn->type & OP_WAIT && cn->unmade > 0; 1056*3955d011SMarcel Moolenaar } 1057*3955d011SMarcel Moolenaar 1058*3955d011SMarcel Moolenaar /* When a .ORDER RHS node completes we do this on each LHS */ 1059*3955d011SMarcel Moolenaar static int 1060*3955d011SMarcel Moolenaar MakeBuildParent(void *v_pn, void *toBeMade_next) 1061*3955d011SMarcel Moolenaar { 1062*3955d011SMarcel Moolenaar GNode *pn = v_pn; 1063*3955d011SMarcel Moolenaar 1064*3955d011SMarcel Moolenaar if (pn->made != DEFERRED) 1065*3955d011SMarcel Moolenaar return 0; 1066*3955d011SMarcel Moolenaar 1067*3955d011SMarcel Moolenaar if (MakeBuildChild(pn, toBeMade_next) == 0) { 1068*3955d011SMarcel Moolenaar /* Mark so that when this node is built we reschedule its parents */ 1069*3955d011SMarcel Moolenaar pn->flags |= DONE_ORDER; 1070*3955d011SMarcel Moolenaar } 1071*3955d011SMarcel Moolenaar 1072*3955d011SMarcel Moolenaar return 0; 1073*3955d011SMarcel Moolenaar } 1074*3955d011SMarcel Moolenaar 1075*3955d011SMarcel Moolenaar static Boolean 1076*3955d011SMarcel Moolenaar MakeStartJobs(void) 1077*3955d011SMarcel Moolenaar { 1078*3955d011SMarcel Moolenaar GNode *gn; 1079*3955d011SMarcel Moolenaar int have_token = 0; 1080*3955d011SMarcel Moolenaar 1081*3955d011SMarcel Moolenaar while (!Lst_IsEmpty (toBeMade)) { 1082*3955d011SMarcel Moolenaar /* Get token now to avoid cycling job-list when we only have 1 token */ 1083*3955d011SMarcel Moolenaar if (!have_token && !Job_TokenWithdraw()) 1084*3955d011SMarcel Moolenaar break; 1085*3955d011SMarcel Moolenaar have_token = 1; 1086*3955d011SMarcel Moolenaar 1087*3955d011SMarcel Moolenaar gn = (GNode *)Lst_DeQueue(toBeMade); 1088*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1089*3955d011SMarcel Moolenaar fprintf(debug_file, "Examining %s%s...\n", 1090*3955d011SMarcel Moolenaar gn->name, gn->cohort_num); 1091*3955d011SMarcel Moolenaar 1092*3955d011SMarcel Moolenaar if (gn->made != REQUESTED) { 1093*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1094*3955d011SMarcel Moolenaar fprintf(debug_file, "state %d\n", gn->made); 1095*3955d011SMarcel Moolenaar 1096*3955d011SMarcel Moolenaar make_abort(gn, __LINE__); 1097*3955d011SMarcel Moolenaar } 1098*3955d011SMarcel Moolenaar 1099*3955d011SMarcel Moolenaar if (gn->checked == checked) { 1100*3955d011SMarcel Moolenaar /* We've already looked at this node since a job finished... */ 1101*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1102*3955d011SMarcel Moolenaar fprintf(debug_file, "already checked %s%s\n", 1103*3955d011SMarcel Moolenaar gn->name, gn->cohort_num); 1104*3955d011SMarcel Moolenaar gn->made = DEFERRED; 1105*3955d011SMarcel Moolenaar continue; 1106*3955d011SMarcel Moolenaar } 1107*3955d011SMarcel Moolenaar gn->checked = checked; 1108*3955d011SMarcel Moolenaar 1109*3955d011SMarcel Moolenaar if (gn->unmade != 0) { 1110*3955d011SMarcel Moolenaar /* 1111*3955d011SMarcel Moolenaar * We can't build this yet, add all unmade children to toBeMade, 1112*3955d011SMarcel Moolenaar * just before the current first element. 1113*3955d011SMarcel Moolenaar */ 1114*3955d011SMarcel Moolenaar gn->made = DEFERRED; 1115*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeBuildChild, Lst_First(toBeMade)); 1116*3955d011SMarcel Moolenaar /* and drop this node on the floor */ 1117*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1118*3955d011SMarcel Moolenaar fprintf(debug_file, "dropped %s%s\n", gn->name, gn->cohort_num); 1119*3955d011SMarcel Moolenaar continue; 1120*3955d011SMarcel Moolenaar } 1121*3955d011SMarcel Moolenaar 1122*3955d011SMarcel Moolenaar gn->made = BEINGMADE; 1123*3955d011SMarcel Moolenaar if (Make_OODate(gn)) { 1124*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 1125*3955d011SMarcel Moolenaar fprintf(debug_file, "out-of-date\n"); 1126*3955d011SMarcel Moolenaar } 1127*3955d011SMarcel Moolenaar if (queryFlag) { 1128*3955d011SMarcel Moolenaar return (TRUE); 1129*3955d011SMarcel Moolenaar } 1130*3955d011SMarcel Moolenaar Make_DoAllVar(gn); 1131*3955d011SMarcel Moolenaar Job_Make(gn); 1132*3955d011SMarcel Moolenaar have_token = 0; 1133*3955d011SMarcel Moolenaar } else { 1134*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 1135*3955d011SMarcel Moolenaar fprintf(debug_file, "up-to-date\n"); 1136*3955d011SMarcel Moolenaar } 1137*3955d011SMarcel Moolenaar gn->made = UPTODATE; 1138*3955d011SMarcel Moolenaar if (gn->type & OP_JOIN) { 1139*3955d011SMarcel Moolenaar /* 1140*3955d011SMarcel Moolenaar * Even for an up-to-date .JOIN node, we need it to have its 1141*3955d011SMarcel Moolenaar * context variables so references to it get the correct 1142*3955d011SMarcel Moolenaar * value for .TARGET when building up the context variables 1143*3955d011SMarcel Moolenaar * of its parent(s)... 1144*3955d011SMarcel Moolenaar */ 1145*3955d011SMarcel Moolenaar Make_DoAllVar(gn); 1146*3955d011SMarcel Moolenaar } 1147*3955d011SMarcel Moolenaar Make_Update(gn); 1148*3955d011SMarcel Moolenaar } 1149*3955d011SMarcel Moolenaar } 1150*3955d011SMarcel Moolenaar 1151*3955d011SMarcel Moolenaar if (have_token) 1152*3955d011SMarcel Moolenaar Job_TokenReturn(); 1153*3955d011SMarcel Moolenaar 1154*3955d011SMarcel Moolenaar return (FALSE); 1155*3955d011SMarcel Moolenaar } 1156*3955d011SMarcel Moolenaar 1157*3955d011SMarcel Moolenaar /*- 1158*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1159*3955d011SMarcel Moolenaar * MakePrintStatus -- 1160*3955d011SMarcel Moolenaar * Print the status of a top-level node, viz. it being up-to-date 1161*3955d011SMarcel Moolenaar * already or not created due to an error in a lower level. 1162*3955d011SMarcel Moolenaar * Callback function for Make_Run via Lst_ForEach. 1163*3955d011SMarcel Moolenaar * 1164*3955d011SMarcel Moolenaar * Input: 1165*3955d011SMarcel Moolenaar * gnp Node to examine 1166*3955d011SMarcel Moolenaar * cyclep True if gn->unmade being non-zero implies a 1167*3955d011SMarcel Moolenaar * cycle in the graph, not an error in an 1168*3955d011SMarcel Moolenaar * inferior. 1169*3955d011SMarcel Moolenaar * 1170*3955d011SMarcel Moolenaar * Results: 1171*3955d011SMarcel Moolenaar * Always returns 0. 1172*3955d011SMarcel Moolenaar * 1173*3955d011SMarcel Moolenaar * Side Effects: 1174*3955d011SMarcel Moolenaar * A message may be printed. 1175*3955d011SMarcel Moolenaar * 1176*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1177*3955d011SMarcel Moolenaar */ 1178*3955d011SMarcel Moolenaar static int 1179*3955d011SMarcel Moolenaar MakePrintStatusOrder(void *ognp, void *gnp) 1180*3955d011SMarcel Moolenaar { 1181*3955d011SMarcel Moolenaar GNode *ogn = ognp; 1182*3955d011SMarcel Moolenaar GNode *gn = gnp; 1183*3955d011SMarcel Moolenaar 1184*3955d011SMarcel Moolenaar if (!(ogn->flags & REMAKE) || ogn->made > REQUESTED) 1185*3955d011SMarcel Moolenaar /* not waiting for this one */ 1186*3955d011SMarcel Moolenaar return 0; 1187*3955d011SMarcel Moolenaar 1188*3955d011SMarcel Moolenaar printf(" `%s%s' has .ORDER dependency against %s%s " 1189*3955d011SMarcel Moolenaar "(made %d, flags %x, type %x)\n", 1190*3955d011SMarcel Moolenaar gn->name, gn->cohort_num, 1191*3955d011SMarcel Moolenaar ogn->name, ogn->cohort_num, ogn->made, ogn->flags, ogn->type); 1192*3955d011SMarcel Moolenaar if (DEBUG(MAKE) && debug_file != stdout) 1193*3955d011SMarcel Moolenaar fprintf(debug_file, " `%s%s' has .ORDER dependency against %s%s " 1194*3955d011SMarcel Moolenaar "(made %d, flags %x, type %x)\n", 1195*3955d011SMarcel Moolenaar gn->name, gn->cohort_num, 1196*3955d011SMarcel Moolenaar ogn->name, ogn->cohort_num, ogn->made, ogn->flags, ogn->type); 1197*3955d011SMarcel Moolenaar return 0; 1198*3955d011SMarcel Moolenaar } 1199*3955d011SMarcel Moolenaar 1200*3955d011SMarcel Moolenaar static int 1201*3955d011SMarcel Moolenaar MakePrintStatus(void *gnp, void *v_errors) 1202*3955d011SMarcel Moolenaar { 1203*3955d011SMarcel Moolenaar GNode *gn = (GNode *)gnp; 1204*3955d011SMarcel Moolenaar int *errors = v_errors; 1205*3955d011SMarcel Moolenaar 1206*3955d011SMarcel Moolenaar if (gn->flags & DONECYCLE) 1207*3955d011SMarcel Moolenaar /* We've completely processed this node before, don't do it again. */ 1208*3955d011SMarcel Moolenaar return 0; 1209*3955d011SMarcel Moolenaar 1210*3955d011SMarcel Moolenaar if (gn->unmade == 0) { 1211*3955d011SMarcel Moolenaar gn->flags |= DONECYCLE; 1212*3955d011SMarcel Moolenaar switch (gn->made) { 1213*3955d011SMarcel Moolenaar case UPTODATE: 1214*3955d011SMarcel Moolenaar printf("`%s%s' is up to date.\n", gn->name, gn->cohort_num); 1215*3955d011SMarcel Moolenaar break; 1216*3955d011SMarcel Moolenaar case MADE: 1217*3955d011SMarcel Moolenaar break; 1218*3955d011SMarcel Moolenaar case UNMADE: 1219*3955d011SMarcel Moolenaar case DEFERRED: 1220*3955d011SMarcel Moolenaar case REQUESTED: 1221*3955d011SMarcel Moolenaar case BEINGMADE: 1222*3955d011SMarcel Moolenaar (*errors)++; 1223*3955d011SMarcel Moolenaar printf("`%s%s' was not built (made %d, flags %x, type %x)!\n", 1224*3955d011SMarcel Moolenaar gn->name, gn->cohort_num, gn->made, gn->flags, gn->type); 1225*3955d011SMarcel Moolenaar if (DEBUG(MAKE) && debug_file != stdout) 1226*3955d011SMarcel Moolenaar fprintf(debug_file, 1227*3955d011SMarcel Moolenaar "`%s%s' was not built (made %d, flags %x, type %x)!\n", 1228*3955d011SMarcel Moolenaar gn->name, gn->cohort_num, gn->made, gn->flags, gn->type); 1229*3955d011SMarcel Moolenaar /* Most likely problem is actually caused by .ORDER */ 1230*3955d011SMarcel Moolenaar Lst_ForEach(gn->order_pred, MakePrintStatusOrder, gn); 1231*3955d011SMarcel Moolenaar break; 1232*3955d011SMarcel Moolenaar default: 1233*3955d011SMarcel Moolenaar /* Errors - already counted */ 1234*3955d011SMarcel Moolenaar printf("`%s%s' not remade because of errors.\n", 1235*3955d011SMarcel Moolenaar gn->name, gn->cohort_num); 1236*3955d011SMarcel Moolenaar if (DEBUG(MAKE) && debug_file != stdout) 1237*3955d011SMarcel Moolenaar fprintf(debug_file, "`%s%s' not remade because of errors.\n", 1238*3955d011SMarcel Moolenaar gn->name, gn->cohort_num); 1239*3955d011SMarcel Moolenaar break; 1240*3955d011SMarcel Moolenaar } 1241*3955d011SMarcel Moolenaar return 0; 1242*3955d011SMarcel Moolenaar } 1243*3955d011SMarcel Moolenaar 1244*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1245*3955d011SMarcel Moolenaar fprintf(debug_file, "MakePrintStatus: %s%s has %d unmade children\n", 1246*3955d011SMarcel Moolenaar gn->name, gn->cohort_num, gn->unmade); 1247*3955d011SMarcel Moolenaar /* 1248*3955d011SMarcel Moolenaar * If printing cycles and came to one that has unmade children, 1249*3955d011SMarcel Moolenaar * print out the cycle by recursing on its children. 1250*3955d011SMarcel Moolenaar */ 1251*3955d011SMarcel Moolenaar if (!(gn->flags & CYCLE)) { 1252*3955d011SMarcel Moolenaar /* Fist time we've seen this node, check all children */ 1253*3955d011SMarcel Moolenaar gn->flags |= CYCLE; 1254*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakePrintStatus, errors); 1255*3955d011SMarcel Moolenaar /* Mark that this node needn't be processed again */ 1256*3955d011SMarcel Moolenaar gn->flags |= DONECYCLE; 1257*3955d011SMarcel Moolenaar return 0; 1258*3955d011SMarcel Moolenaar } 1259*3955d011SMarcel Moolenaar 1260*3955d011SMarcel Moolenaar /* Only output the error once per node */ 1261*3955d011SMarcel Moolenaar gn->flags |= DONECYCLE; 1262*3955d011SMarcel Moolenaar Error("Graph cycles through `%s%s'", gn->name, gn->cohort_num); 1263*3955d011SMarcel Moolenaar if ((*errors)++ > 100) 1264*3955d011SMarcel Moolenaar /* Abandon the whole error report */ 1265*3955d011SMarcel Moolenaar return 1; 1266*3955d011SMarcel Moolenaar 1267*3955d011SMarcel Moolenaar /* Reporting for our children will give the rest of the loop */ 1268*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakePrintStatus, errors); 1269*3955d011SMarcel Moolenaar return 0; 1270*3955d011SMarcel Moolenaar } 1271*3955d011SMarcel Moolenaar 1272*3955d011SMarcel Moolenaar 1273*3955d011SMarcel Moolenaar /*- 1274*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1275*3955d011SMarcel Moolenaar * Make_ExpandUse -- 1276*3955d011SMarcel Moolenaar * Expand .USE nodes and create a new targets list 1277*3955d011SMarcel Moolenaar * 1278*3955d011SMarcel Moolenaar * Input: 1279*3955d011SMarcel Moolenaar * targs the initial list of targets 1280*3955d011SMarcel Moolenaar * 1281*3955d011SMarcel Moolenaar * Side Effects: 1282*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1283*3955d011SMarcel Moolenaar */ 1284*3955d011SMarcel Moolenaar void 1285*3955d011SMarcel Moolenaar Make_ExpandUse(Lst targs) 1286*3955d011SMarcel Moolenaar { 1287*3955d011SMarcel Moolenaar GNode *gn; /* a temporary pointer */ 1288*3955d011SMarcel Moolenaar Lst examine; /* List of targets to examine */ 1289*3955d011SMarcel Moolenaar 1290*3955d011SMarcel Moolenaar examine = Lst_Duplicate(targs, NULL); 1291*3955d011SMarcel Moolenaar 1292*3955d011SMarcel Moolenaar /* 1293*3955d011SMarcel Moolenaar * Make an initial downward pass over the graph, marking nodes to be made 1294*3955d011SMarcel Moolenaar * as we go down. We call Suff_FindDeps to find where a node is and 1295*3955d011SMarcel Moolenaar * to get some children for it if it has none and also has no commands. 1296*3955d011SMarcel Moolenaar * If the node is a leaf, we stick it on the toBeMade queue to 1297*3955d011SMarcel Moolenaar * be looked at in a minute, otherwise we add its children to our queue 1298*3955d011SMarcel Moolenaar * and go on about our business. 1299*3955d011SMarcel Moolenaar */ 1300*3955d011SMarcel Moolenaar while (!Lst_IsEmpty (examine)) { 1301*3955d011SMarcel Moolenaar gn = (GNode *)Lst_DeQueue(examine); 1302*3955d011SMarcel Moolenaar 1303*3955d011SMarcel Moolenaar if (gn->flags & REMAKE) 1304*3955d011SMarcel Moolenaar /* We've looked at this one already */ 1305*3955d011SMarcel Moolenaar continue; 1306*3955d011SMarcel Moolenaar gn->flags |= REMAKE; 1307*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1308*3955d011SMarcel Moolenaar fprintf(debug_file, "Make_ExpandUse: examine %s%s\n", 1309*3955d011SMarcel Moolenaar gn->name, gn->cohort_num); 1310*3955d011SMarcel Moolenaar 1311*3955d011SMarcel Moolenaar if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (gn->cohorts)) { 1312*3955d011SMarcel Moolenaar /* Append all the 'cohorts' to the list of things to examine */ 1313*3955d011SMarcel Moolenaar Lst new; 1314*3955d011SMarcel Moolenaar new = Lst_Duplicate(gn->cohorts, NULL); 1315*3955d011SMarcel Moolenaar Lst_Concat(new, examine, LST_CONCLINK); 1316*3955d011SMarcel Moolenaar examine = new; 1317*3955d011SMarcel Moolenaar } 1318*3955d011SMarcel Moolenaar 1319*3955d011SMarcel Moolenaar /* 1320*3955d011SMarcel Moolenaar * Apply any .USE rules before looking for implicit dependencies 1321*3955d011SMarcel Moolenaar * to make sure everything has commands that should... 1322*3955d011SMarcel Moolenaar * Make sure that the TARGET is set, so that we can make 1323*3955d011SMarcel Moolenaar * expansions. 1324*3955d011SMarcel Moolenaar */ 1325*3955d011SMarcel Moolenaar if (gn->type & OP_ARCHV) { 1326*3955d011SMarcel Moolenaar char *eoa, *eon; 1327*3955d011SMarcel Moolenaar eoa = strchr(gn->name, '('); 1328*3955d011SMarcel Moolenaar eon = strchr(gn->name, ')'); 1329*3955d011SMarcel Moolenaar if (eoa == NULL || eon == NULL) 1330*3955d011SMarcel Moolenaar continue; 1331*3955d011SMarcel Moolenaar *eoa = '\0'; 1332*3955d011SMarcel Moolenaar *eon = '\0'; 1333*3955d011SMarcel Moolenaar Var_Set(MEMBER, eoa + 1, gn, 0); 1334*3955d011SMarcel Moolenaar Var_Set(ARCHIVE, gn->name, gn, 0); 1335*3955d011SMarcel Moolenaar *eoa = '('; 1336*3955d011SMarcel Moolenaar *eon = ')'; 1337*3955d011SMarcel Moolenaar } 1338*3955d011SMarcel Moolenaar 1339*3955d011SMarcel Moolenaar (void)Dir_MTime(gn, 0); 1340*3955d011SMarcel Moolenaar Var_Set(TARGET, gn->path ? gn->path : gn->name, gn, 0); 1341*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeUnmark, gn); 1342*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeHandleUse, gn); 1343*3955d011SMarcel Moolenaar 1344*3955d011SMarcel Moolenaar if ((gn->type & OP_MADE) == 0) 1345*3955d011SMarcel Moolenaar Suff_FindDeps(gn); 1346*3955d011SMarcel Moolenaar else { 1347*3955d011SMarcel Moolenaar /* Pretend we made all this node's children */ 1348*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeFindChild, gn); 1349*3955d011SMarcel Moolenaar if (gn->unmade != 0) 1350*3955d011SMarcel Moolenaar printf("Warning: %s%s still has %d unmade children\n", 1351*3955d011SMarcel Moolenaar gn->name, gn->cohort_num, gn->unmade); 1352*3955d011SMarcel Moolenaar } 1353*3955d011SMarcel Moolenaar 1354*3955d011SMarcel Moolenaar if (gn->unmade != 0) 1355*3955d011SMarcel Moolenaar Lst_ForEach(gn->children, MakeAddChild, examine); 1356*3955d011SMarcel Moolenaar } 1357*3955d011SMarcel Moolenaar 1358*3955d011SMarcel Moolenaar Lst_Destroy(examine, NULL); 1359*3955d011SMarcel Moolenaar } 1360*3955d011SMarcel Moolenaar 1361*3955d011SMarcel Moolenaar /*- 1362*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1363*3955d011SMarcel Moolenaar * Make_ProcessWait -- 1364*3955d011SMarcel Moolenaar * Convert .WAIT nodes into dependencies 1365*3955d011SMarcel Moolenaar * 1366*3955d011SMarcel Moolenaar * Input: 1367*3955d011SMarcel Moolenaar * targs the initial list of targets 1368*3955d011SMarcel Moolenaar * 1369*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1370*3955d011SMarcel Moolenaar */ 1371*3955d011SMarcel Moolenaar 1372*3955d011SMarcel Moolenaar static int 1373*3955d011SMarcel Moolenaar link_parent(void *cnp, void *pnp) 1374*3955d011SMarcel Moolenaar { 1375*3955d011SMarcel Moolenaar GNode *cn = cnp; 1376*3955d011SMarcel Moolenaar GNode *pn = pnp; 1377*3955d011SMarcel Moolenaar 1378*3955d011SMarcel Moolenaar Lst_AtEnd(pn->children, cn); 1379*3955d011SMarcel Moolenaar Lst_AtEnd(cn->parents, pn); 1380*3955d011SMarcel Moolenaar pn->unmade++; 1381*3955d011SMarcel Moolenaar return 0; 1382*3955d011SMarcel Moolenaar } 1383*3955d011SMarcel Moolenaar 1384*3955d011SMarcel Moolenaar static int 1385*3955d011SMarcel Moolenaar add_wait_dep(void *v_cn, void *v_wn) 1386*3955d011SMarcel Moolenaar { 1387*3955d011SMarcel Moolenaar GNode *cn = v_cn; 1388*3955d011SMarcel Moolenaar GNode *wn = v_wn; 1389*3955d011SMarcel Moolenaar 1390*3955d011SMarcel Moolenaar if (cn == wn) 1391*3955d011SMarcel Moolenaar return 1; 1392*3955d011SMarcel Moolenaar 1393*3955d011SMarcel Moolenaar if (cn == NULL || wn == NULL) { 1394*3955d011SMarcel Moolenaar printf("bad wait dep %p %p\n", cn, wn); 1395*3955d011SMarcel Moolenaar exit(4); 1396*3955d011SMarcel Moolenaar } 1397*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1398*3955d011SMarcel Moolenaar fprintf(debug_file, ".WAIT: add dependency %s%s -> %s\n", 1399*3955d011SMarcel Moolenaar cn->name, cn->cohort_num, wn->name); 1400*3955d011SMarcel Moolenaar 1401*3955d011SMarcel Moolenaar Lst_AtEnd(wn->children, cn); 1402*3955d011SMarcel Moolenaar wn->unmade++; 1403*3955d011SMarcel Moolenaar Lst_AtEnd(cn->parents, wn); 1404*3955d011SMarcel Moolenaar return 0; 1405*3955d011SMarcel Moolenaar } 1406*3955d011SMarcel Moolenaar 1407*3955d011SMarcel Moolenaar static void 1408*3955d011SMarcel Moolenaar Make_ProcessWait(Lst targs) 1409*3955d011SMarcel Moolenaar { 1410*3955d011SMarcel Moolenaar GNode *pgn; /* 'parent' node we are examining */ 1411*3955d011SMarcel Moolenaar GNode *cgn; /* Each child in turn */ 1412*3955d011SMarcel Moolenaar LstNode owln; /* Previous .WAIT node */ 1413*3955d011SMarcel Moolenaar Lst examine; /* List of targets to examine */ 1414*3955d011SMarcel Moolenaar LstNode ln; 1415*3955d011SMarcel Moolenaar 1416*3955d011SMarcel Moolenaar /* 1417*3955d011SMarcel Moolenaar * We need all the nodes to have a common parent in order for the 1418*3955d011SMarcel Moolenaar * .WAIT and .ORDER scheduling to work. 1419*3955d011SMarcel Moolenaar * Perhaps this should be done earlier... 1420*3955d011SMarcel Moolenaar */ 1421*3955d011SMarcel Moolenaar 1422*3955d011SMarcel Moolenaar pgn = Targ_NewGN(".MAIN"); 1423*3955d011SMarcel Moolenaar pgn->flags = REMAKE; 1424*3955d011SMarcel Moolenaar pgn->type = OP_PHONY | OP_DEPENDS; 1425*3955d011SMarcel Moolenaar /* Get it displayed in the diag dumps */ 1426*3955d011SMarcel Moolenaar Lst_AtFront(Targ_List(), pgn); 1427*3955d011SMarcel Moolenaar 1428*3955d011SMarcel Moolenaar Lst_ForEach(targs, link_parent, pgn); 1429*3955d011SMarcel Moolenaar 1430*3955d011SMarcel Moolenaar /* Start building with the 'dummy' .MAIN' node */ 1431*3955d011SMarcel Moolenaar MakeBuildChild(pgn, NULL); 1432*3955d011SMarcel Moolenaar 1433*3955d011SMarcel Moolenaar examine = Lst_Init(FALSE); 1434*3955d011SMarcel Moolenaar Lst_AtEnd(examine, pgn); 1435*3955d011SMarcel Moolenaar 1436*3955d011SMarcel Moolenaar while (!Lst_IsEmpty (examine)) { 1437*3955d011SMarcel Moolenaar pgn = Lst_DeQueue(examine); 1438*3955d011SMarcel Moolenaar 1439*3955d011SMarcel Moolenaar /* We only want to process each child-list once */ 1440*3955d011SMarcel Moolenaar if (pgn->flags & DONE_WAIT) 1441*3955d011SMarcel Moolenaar continue; 1442*3955d011SMarcel Moolenaar pgn->flags |= DONE_WAIT; 1443*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1444*3955d011SMarcel Moolenaar fprintf(debug_file, "Make_ProcessWait: examine %s\n", pgn->name); 1445*3955d011SMarcel Moolenaar 1446*3955d011SMarcel Moolenaar if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (pgn->cohorts)) { 1447*3955d011SMarcel Moolenaar /* Append all the 'cohorts' to the list of things to examine */ 1448*3955d011SMarcel Moolenaar Lst new; 1449*3955d011SMarcel Moolenaar new = Lst_Duplicate(pgn->cohorts, NULL); 1450*3955d011SMarcel Moolenaar Lst_Concat(new, examine, LST_CONCLINK); 1451*3955d011SMarcel Moolenaar examine = new; 1452*3955d011SMarcel Moolenaar } 1453*3955d011SMarcel Moolenaar 1454*3955d011SMarcel Moolenaar owln = Lst_First(pgn->children); 1455*3955d011SMarcel Moolenaar Lst_Open(pgn->children); 1456*3955d011SMarcel Moolenaar for (; (ln = Lst_Next(pgn->children)) != NULL; ) { 1457*3955d011SMarcel Moolenaar cgn = Lst_Datum(ln); 1458*3955d011SMarcel Moolenaar if (cgn->type & OP_WAIT) { 1459*3955d011SMarcel Moolenaar /* Make the .WAIT node depend on the previous children */ 1460*3955d011SMarcel Moolenaar Lst_ForEachFrom(pgn->children, owln, add_wait_dep, cgn); 1461*3955d011SMarcel Moolenaar owln = ln; 1462*3955d011SMarcel Moolenaar } else { 1463*3955d011SMarcel Moolenaar Lst_AtEnd(examine, cgn); 1464*3955d011SMarcel Moolenaar } 1465*3955d011SMarcel Moolenaar } 1466*3955d011SMarcel Moolenaar Lst_Close(pgn->children); 1467*3955d011SMarcel Moolenaar } 1468*3955d011SMarcel Moolenaar 1469*3955d011SMarcel Moolenaar Lst_Destroy(examine, NULL); 1470*3955d011SMarcel Moolenaar } 1471*3955d011SMarcel Moolenaar 1472*3955d011SMarcel Moolenaar /*- 1473*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1474*3955d011SMarcel Moolenaar * Make_Run -- 1475*3955d011SMarcel Moolenaar * Initialize the nodes to remake and the list of nodes which are 1476*3955d011SMarcel Moolenaar * ready to be made by doing a breadth-first traversal of the graph 1477*3955d011SMarcel Moolenaar * starting from the nodes in the given list. Once this traversal 1478*3955d011SMarcel Moolenaar * is finished, all the 'leaves' of the graph are in the toBeMade 1479*3955d011SMarcel Moolenaar * queue. 1480*3955d011SMarcel Moolenaar * Using this queue and the Job module, work back up the graph, 1481*3955d011SMarcel Moolenaar * calling on MakeStartJobs to keep the job table as full as 1482*3955d011SMarcel Moolenaar * possible. 1483*3955d011SMarcel Moolenaar * 1484*3955d011SMarcel Moolenaar * Input: 1485*3955d011SMarcel Moolenaar * targs the initial list of targets 1486*3955d011SMarcel Moolenaar * 1487*3955d011SMarcel Moolenaar * Results: 1488*3955d011SMarcel Moolenaar * TRUE if work was done. FALSE otherwise. 1489*3955d011SMarcel Moolenaar * 1490*3955d011SMarcel Moolenaar * Side Effects: 1491*3955d011SMarcel Moolenaar * The make field of all nodes involved in the creation of the given 1492*3955d011SMarcel Moolenaar * targets is set to 1. The toBeMade list is set to contain all the 1493*3955d011SMarcel Moolenaar * 'leaves' of these subgraphs. 1494*3955d011SMarcel Moolenaar *----------------------------------------------------------------------- 1495*3955d011SMarcel Moolenaar */ 1496*3955d011SMarcel Moolenaar Boolean 1497*3955d011SMarcel Moolenaar Make_Run(Lst targs) 1498*3955d011SMarcel Moolenaar { 1499*3955d011SMarcel Moolenaar int errors; /* Number of errors the Job module reports */ 1500*3955d011SMarcel Moolenaar 1501*3955d011SMarcel Moolenaar /* Start trying to make the current targets... */ 1502*3955d011SMarcel Moolenaar toBeMade = Lst_Init(FALSE); 1503*3955d011SMarcel Moolenaar 1504*3955d011SMarcel Moolenaar Make_ExpandUse(targs); 1505*3955d011SMarcel Moolenaar Make_ProcessWait(targs); 1506*3955d011SMarcel Moolenaar 1507*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 1508*3955d011SMarcel Moolenaar fprintf(debug_file, "#***# full graph\n"); 1509*3955d011SMarcel Moolenaar Targ_PrintGraph(1); 1510*3955d011SMarcel Moolenaar } 1511*3955d011SMarcel Moolenaar 1512*3955d011SMarcel Moolenaar if (queryFlag) { 1513*3955d011SMarcel Moolenaar /* 1514*3955d011SMarcel Moolenaar * We wouldn't do any work unless we could start some jobs in the 1515*3955d011SMarcel Moolenaar * next loop... (we won't actually start any, of course, this is just 1516*3955d011SMarcel Moolenaar * to see if any of the targets was out of date) 1517*3955d011SMarcel Moolenaar */ 1518*3955d011SMarcel Moolenaar return (MakeStartJobs()); 1519*3955d011SMarcel Moolenaar } 1520*3955d011SMarcel Moolenaar /* 1521*3955d011SMarcel Moolenaar * Initialization. At the moment, no jobs are running and until some 1522*3955d011SMarcel Moolenaar * get started, nothing will happen since the remaining upward 1523*3955d011SMarcel Moolenaar * traversal of the graph is performed by the routines in job.c upon 1524*3955d011SMarcel Moolenaar * the finishing of a job. So we fill the Job table as much as we can 1525*3955d011SMarcel Moolenaar * before going into our loop. 1526*3955d011SMarcel Moolenaar */ 1527*3955d011SMarcel Moolenaar (void)MakeStartJobs(); 1528*3955d011SMarcel Moolenaar 1529*3955d011SMarcel Moolenaar /* 1530*3955d011SMarcel Moolenaar * Main Loop: The idea here is that the ending of jobs will take 1531*3955d011SMarcel Moolenaar * care of the maintenance of data structures and the waiting for output 1532*3955d011SMarcel Moolenaar * will cause us to be idle most of the time while our children run as 1533*3955d011SMarcel Moolenaar * much as possible. Because the job table is kept as full as possible, 1534*3955d011SMarcel Moolenaar * the only time when it will be empty is when all the jobs which need 1535*3955d011SMarcel Moolenaar * running have been run, so that is the end condition of this loop. 1536*3955d011SMarcel Moolenaar * Note that the Job module will exit if there were any errors unless the 1537*3955d011SMarcel Moolenaar * keepgoing flag was given. 1538*3955d011SMarcel Moolenaar */ 1539*3955d011SMarcel Moolenaar while (!Lst_IsEmpty(toBeMade) || jobTokensRunning > 0) { 1540*3955d011SMarcel Moolenaar Job_CatchOutput(); 1541*3955d011SMarcel Moolenaar (void)MakeStartJobs(); 1542*3955d011SMarcel Moolenaar } 1543*3955d011SMarcel Moolenaar 1544*3955d011SMarcel Moolenaar errors = Job_Finish(); 1545*3955d011SMarcel Moolenaar 1546*3955d011SMarcel Moolenaar /* 1547*3955d011SMarcel Moolenaar * Print the final status of each target. E.g. if it wasn't made 1548*3955d011SMarcel Moolenaar * because some inferior reported an error. 1549*3955d011SMarcel Moolenaar */ 1550*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) 1551*3955d011SMarcel Moolenaar fprintf(debug_file, "done: errors %d\n", errors); 1552*3955d011SMarcel Moolenaar if (errors == 0) { 1553*3955d011SMarcel Moolenaar Lst_ForEach(targs, MakePrintStatus, &errors); 1554*3955d011SMarcel Moolenaar if (DEBUG(MAKE)) { 1555*3955d011SMarcel Moolenaar fprintf(debug_file, "done: errors %d\n", errors); 1556*3955d011SMarcel Moolenaar if (errors) 1557*3955d011SMarcel Moolenaar Targ_PrintGraph(4); 1558*3955d011SMarcel Moolenaar } 1559*3955d011SMarcel Moolenaar } 1560*3955d011SMarcel Moolenaar return errors != 0; 1561*3955d011SMarcel Moolenaar } 1562