[BACK]Return to engine.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Annotation of src/usr.bin/make/engine.c, Revision 1.2

1.2     ! espie       1: /*     $OpenBSD: engine.c,v 1.1 2007/09/16 10:39:07 espie Exp $ */
1.1       espie       2: /*
                      3:  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
                      4:  * Copyright (c) 1988, 1989 by Adam de Boor
                      5:  * Copyright (c) 1989 by Berkeley Softworks
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * Adam de Boor.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #include <limits.h>
                     37: #include <stdio.h>
                     38: #include <errno.h>
                     39: #include <fcntl.h>
                     40: #include <unistd.h>
                     41: #include <string.h>
                     42: #include "config.h"
                     43: #include "defines.h"
                     44: #include "dir.h"
                     45: #include "engine.h"
                     46: #include "arch.h"
                     47: #include "gnode.h"
                     48: #include "targ.h"
                     49: #include "var.h"
                     50: #include "extern.h"
                     51: #include "lst.h"
                     52: #include "timestamp.h"
                     53: #include "make.h"
                     54: #include "main.h"
                     55:
                     56: static void MakeTimeStamp(void *, void *);
                     57: static void MakeAddAllSrc(void *, void *);
                     58:
                     59: /*-
                     60:  *-----------------------------------------------------------------------
                     61:  * Job_CheckCommands --
                     62:  *     Make sure the given node has all the commands it needs.
                     63:  *
                     64:  * Results:
                     65:  *     true if the commands list is/was ok.
                     66:  *
                     67:  * Side Effects:
                     68:  *     The node will have commands from the .DEFAULT rule added to it
                     69:  *     if it needs them.
                     70:  *-----------------------------------------------------------------------
                     71:  */
                     72: bool
                     73: Job_CheckCommands(GNode *gn,           /* The target whose commands need
                     74:                                         * verifying */
                     75:     void (*abortProc)(char *, ...))    /* Function to abort with message */
                     76: {
                     77:     if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
                     78:        (gn->type & OP_LIB) == 0) {
                     79:        /*
                     80:         * No commands. Look for .DEFAULT rule from which we might infer
                     81:         * commands
                     82:         */
                     83:        if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) {
                     84:            /*
                     85:             * Make only looks for a .DEFAULT if the node was never the
                     86:             * target of an operator, so that's what we do too. If
                     87:             * a .DEFAULT was given, we substitute its commands for gn's
                     88:             * commands and set the IMPSRC variable to be the target's name
                     89:             * The DEFAULT node acts like a transformation rule, in that
                     90:             * gn also inherits any attributes or sources attached to
                     91:             * .DEFAULT itself.
                     92:             */
                     93:            Make_HandleUse(DEFAULT, gn);
                     94:            Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), gn);
                     95:        } else if (is_out_of_date(Dir_MTime(gn))) {
                     96:            /*
                     97:             * The node wasn't the target of an operator we have no .DEFAULT
                     98:             * rule to go on and the target doesn't already exist. There's
                     99:             * nothing more we can do for this branch. If the -k flag wasn't
                    100:             * given, we stop in our tracks, otherwise we just don't update
                    101:             * this node's parents so they never get examined.
                    102:             */
                    103:            static const char msg[] = "make: don't know how to make";
                    104:
                    105:            if (gn->type & OP_OPTIONAL) {
                    106:                (void)fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);
                    107:                (void)fflush(stdout);
                    108:            } else if (keepgoing) {
                    109:                (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);
                    110:                (void)fflush(stdout);
                    111:                return false;
                    112:            } else {
                    113:                (*abortProc)("%s %s. Stop in %s.", msg, gn->name,
                    114:                        Var_Value(".CURDIR"));
                    115:                return false;
                    116:            }
                    117:        }
                    118:     }
                    119:     return true;
                    120: }
                    121:
                    122: /*-
                    123:  *-----------------------------------------------------------------------
                    124:  * Job_Touch --
                    125:  *     Touch the given target. Called by JobStart when the -t flag was
                    126:  *     given
                    127:  *
                    128:  * Side Effects:
                    129:  *     The data modification of the file is changed. In addition, if the
                    130:  *     file did not exist, it is created.
                    131:  *-----------------------------------------------------------------------
                    132:  */
                    133: void
                    134: Job_Touch(GNode *gn,           /* the node of the file to touch */
                    135:     bool silent)               /* true if should not print messages */
                    136: {
                    137:     int          streamID;     /* ID of stream opened to do the touch */
                    138:
                    139:     if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
                    140:        /*
                    141:         * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
                    142:         * and, as such, shouldn't really be created.
                    143:         */
                    144:        return;
                    145:     }
                    146:
                    147:     if (!silent) {
                    148:        (void)fprintf(stdout, "touch %s\n", gn->name);
                    149:        (void)fflush(stdout);
                    150:     }
                    151:
                    152:     if (noExecute) {
                    153:        return;
                    154:     }
                    155:
                    156:     if (gn->type & OP_ARCHV) {
                    157:        Arch_Touch(gn);
                    158:     } else if (gn->type & OP_LIB) {
                    159:        Arch_TouchLib(gn);
                    160:     } else {
                    161:        const char *file = gn->path != NULL ? gn->path : gn->name;
                    162:
                    163:        if (set_times(file) == -1){
                    164:            streamID = open(file, O_RDWR | O_CREAT, 0666);
                    165:
                    166:            if (streamID >= 0) {
                    167:                char    c;
                    168:
                    169:                /*
                    170:                 * Read and write a byte to the file to change the
                    171:                 * modification time, then close the file.
                    172:                 */
                    173:                if (read(streamID, &c, 1) == 1) {
                    174:                    (void)lseek(streamID, 0, SEEK_SET);
                    175:                    (void)write(streamID, &c, 1);
                    176:                }
                    177:
                    178:                (void)close(streamID);
                    179:            } else {
                    180:                (void)fprintf(stdout, "*** couldn't touch %s: %s",
                    181:                               file, strerror(errno));
                    182:                (void)fflush(stdout);
                    183:            }
                    184:        }
                    185:     }
                    186: }
                    187:
                    188: /*-
                    189:  *-----------------------------------------------------------------------
                    190:  * Make_TimeStamp --
                    191:  *     Set the cmtime field of a parent node based on the mtime stamp in its
                    192:  *     child.
                    193:  *
                    194:  * Side Effects:
                    195:  *     The cmtime of the parent node will be changed if the mtime
                    196:  *     field of the child is greater than it.
                    197:  *-----------------------------------------------------------------------
                    198:  */
                    199: void
                    200: Make_TimeStamp(
                    201:     GNode *pgn, /* the current parent */
                    202:     GNode *cgn) /* the child we've just examined */
                    203: {
                    204:     if (is_strictly_before(pgn->cmtime, cgn->mtime))
                    205:        pgn->cmtime = cgn->mtime;
                    206: }
                    207:
                    208: /*-
                    209:  *-----------------------------------------------------------------------
                    210:  * Make_HandleUse --
                    211:  *     Function called by Make_Run and SuffApplyTransform on the downward
                    212:  *     pass to handle .USE and transformation nodes. A callback function
                    213:  *     for Lst_ForEach, it implements the .USE and transformation
                    214:  *     functionality by copying the node's commands, type flags
                    215:  *     and children to the parent node. Should be called before the
                    216:  *     children are enqueued to be looked at by MakeAddChild.
                    217:  *
                    218:  *     A .USE node is much like an explicit transformation rule, except
                    219:  *     its commands are always added to the target node, even if the
                    220:  *     target already has commands.
                    221:  *
                    222:  * Side Effects:
                    223:  *     Children and commands may be added to the parent and the parent's
                    224:  *     type may be changed.
                    225:  *
                    226:  *-----------------------------------------------------------------------
                    227:  */
                    228: void
                    229: Make_HandleUse(
                    230:     GNode      *cgn,   /* The .USE node */
                    231:     GNode      *pgn)   /* The target of the .USE node */
                    232: {
                    233:     GNode      *gn;    /* A child of the .USE node */
                    234:     LstNode    ln;     /* An element in the children list */
                    235:
                    236:     if (cgn->type & (OP_USE|OP_TRANSFORM)) {
                    237:        if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) {
                    238:            /* .USE or transformation and target has no commands -- append
                    239:             * the child's commands to the parent.  */
                    240:            Lst_Concat(&pgn->commands, &cgn->commands);
                    241:        }
                    242:
                    243:        for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Adv(ln)) {
                    244:            gn = (GNode *)Lst_Datum(ln);
                    245:
                    246:            if (Lst_AddNew(&pgn->children, gn)) {
                    247:                Lst_AtEnd(&gn->parents, pgn);
                    248:                pgn->unmade += 1;
                    249:            }
                    250:        }
                    251:
                    252:        pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
                    253:
                    254:        /*
                    255:         * This child node is now "made", so we decrement the count of
                    256:         * unmade children in the parent... We also remove the child
                    257:         * from the parent's list to accurately reflect the number of decent
                    258:         * children the parent has. This is used by Make_Run to decide
                    259:         * whether to queue the parent or examine its children...
                    260:         */
                    261:        if (cgn->type & OP_USE) {
                    262:            pgn->unmade--;
                    263:        }
                    264:     }
                    265: }
                    266:
                    267: /*-
                    268:  *-----------------------------------------------------------------------
                    269:  * MakeAddAllSrc --
                    270:  *     Add a child's name to the ALLSRC and OODATE variables of the given
                    271:  *     node. Called from Make_DoAllVar via Lst_ForEach. A child is added only
                    272:  *     if it has not been given the .EXEC, .USE or .INVISIBLE attributes.
                    273:  *     .EXEC and .USE children are very rarely going to be files, so...
                    274:  *     A child is added to the OODATE variable if its modification time is
                    275:  *     later than that of its parent, as defined by Make, except if the
                    276:  *     parent is a .JOIN node. In that case, it is only added to the OODATE
                    277:  *     variable if it was actually made (since .JOIN nodes don't have
                    278:  *     modification times, the comparison is rather unfair...)..
                    279:  *
                    280:  * Side Effects:
                    281:  *     The ALLSRC variable for the given node is extended.
                    282:  *-----------------------------------------------------------------------
                    283:  */
                    284: static void
                    285: MakeAddAllSrc(
                    286:     void *cgnp, /* The child to add */
                    287:     void *pgnp) /* The parent to whose ALLSRC variable it should be */
                    288:                        /* added */
                    289: {
                    290:     GNode      *cgn = (GNode *)cgnp;
                    291:     GNode      *pgn = (GNode *)pgnp;
                    292:     if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
                    293:        const char *child;
                    294:
                    295:        if (OP_NOP(cgn->type) ||
                    296:            (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) {
                    297:            /*
                    298:             * this node is only source; use the specific pathname for it
                    299:             */
                    300:            child = cgn->path != NULL ? cgn->path : cgn->name;
                    301:        }
                    302:
                    303:        Varq_Append(ALLSRC_INDEX, child, pgn);
                    304:        if (pgn->type & OP_JOIN) {
                    305:            if (cgn->made == MADE) {
                    306:                Varq_Append(OODATE_INDEX, child, pgn);
                    307:            }
                    308:        } else if (is_strictly_before(pgn->mtime, cgn->mtime) ||
                    309:                   (!is_strictly_before(cgn->mtime, now) && cgn->made == MADE))
                    310:        {
                    311:            /*
                    312:             * It goes in the OODATE variable if the parent is younger than the
                    313:             * child or if the child has been modified more recently than
                    314:             * the start of the make. This is to keep pmake from getting
                    315:             * confused if something else updates the parent after the
                    316:             * make starts (shouldn't happen, I know, but sometimes it
                    317:             * does). In such a case, if we've updated the kid, the parent
                    318:             * is likely to have a modification time later than that of
                    319:             * the kid and anything that relies on the OODATE variable will
                    320:             * be hosed.
                    321:             *
                    322:             */
                    323:            Varq_Append(OODATE_INDEX, child, pgn);
                    324:        }
                    325:     }
                    326: }
                    327:
                    328: /*-
                    329:  *-----------------------------------------------------------------------
                    330:  * Make_DoAllVar --
                    331:  *     Set up the ALLSRC and OODATE variables. Sad to say, it must be
                    332:  *     done separately, rather than while traversing the graph. This is
                    333:  *     because Make defined OODATE to contain all sources whose modification
                    334:  *     times were later than that of the target, *not* those sources that
                    335:  *     were out-of-date. Since in both compatibility and native modes,
                    336:  *     the modification time of the parent isn't found until the child
                    337:  *     has been dealt with, we have to wait until now to fill in the
                    338:  *     variable. As for ALLSRC, the ordering is important and not
                    339:  *     guaranteed when in native mode, so it must be set here, too.
                    340:  *
                    341:  * Side Effects:
                    342:  *     The ALLSRC and OODATE variables of the given node is filled in.
                    343:  *     If the node is a .JOIN node, its TARGET variable will be set to
                    344:  *     match its ALLSRC variable.
                    345:  *-----------------------------------------------------------------------
                    346:  */
                    347: void
                    348: Make_DoAllVar(GNode *gn)
                    349: {
                    350:     Lst_ForEach(&gn->children, MakeAddAllSrc, gn);
                    351:
                    352:     if (Varq_Value(OODATE_INDEX, gn) == NULL)
                    353:        Varq_Set(OODATE_INDEX, "", gn);
                    354:     if (Varq_Value(ALLSRC_INDEX, gn) == NULL)
                    355:        Varq_Set(ALLSRC_INDEX, "", gn);
                    356:
                    357:     if (gn->type & OP_JOIN)
                    358:        Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), gn);
                    359: }
                    360:
                    361: /* Wrapper to call Make_TimeStamp from a forEach loop. */
                    362: static void
                    363: MakeTimeStamp(
                    364:     void *pgn, /* the current parent */
                    365:     void *cgn) /* the child we've just examined */
                    366: {
                    367:     Make_TimeStamp((GNode *)pgn, (GNode *)cgn);
                    368: }
                    369:
                    370: /*-
                    371:  *-----------------------------------------------------------------------
                    372:  * Make_OODate --
                    373:  *     See if a given node is out of date with respect to its sources.
                    374:  *     Used by Make_Run when deciding which nodes to place on the
                    375:  *     toBeMade queue initially and by Make_Update to screen out USE and
                    376:  *     EXEC nodes. In the latter case, however, any other sort of node
                    377:  *     must be considered out-of-date since at least one of its children
                    378:  *     will have been recreated.
                    379:  *
                    380:  * Results:
                    381:  *     true if the node is out of date. false otherwise.
                    382:  *
                    383:  * Side Effects:
                    384:  *     The mtime field of the node and the cmtime field of its parents
                    385:  *     will/may be changed.
                    386:  *-----------------------------------------------------------------------
                    387:  */
                    388: bool
                    389: Make_OODate(GNode *gn) /* the node to check */
                    390: {
                    391:     bool           oodate;
                    392:
                    393:     /*
                    394:      * Certain types of targets needn't even be sought as their datedness
                    395:      * doesn't depend on their modification time...
                    396:      */
                    397:     if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
                    398:        (void)Dir_MTime(gn);
                    399:        if (DEBUG(MAKE)) {
                    400:            if (!is_out_of_date(gn->mtime)) {
1.2     ! espie     401:                printf("modified %s...", time_to_string(gn->mtime));
1.1       espie     402:            } else {
                    403:                printf("non-existent...");
                    404:            }
                    405:        }
                    406:     }
                    407:
                    408:     /*
                    409:      * A target is remade in one of the following circumstances:
                    410:      * its modification time is smaller than that of its youngest child
                    411:      *     and it would actually be run (has commands or type OP_NOP)
                    412:      * it's the object of a force operator
                    413:      * it has no children, was on the lhs of an operator and doesn't exist
                    414:      *     already.
                    415:      *
                    416:      * Libraries are only considered out-of-date if the archive module says
                    417:      * they are.
                    418:      *
                    419:      * These weird rules are brought to you by Backward-Compatibility and
                    420:      * the strange people who wrote 'Make'.
                    421:      */
                    422:     if (gn->type & OP_USE) {
                    423:        /*
                    424:         * If the node is a USE node it is *never* out of date
                    425:         * no matter *what*.
                    426:         */
                    427:        if (DEBUG(MAKE)) {
                    428:            printf(".USE node...");
                    429:        }
                    430:        oodate = false;
                    431:     } else if ((gn->type & OP_LIB) && Arch_IsLib(gn)) {
                    432:        if (DEBUG(MAKE)) {
                    433:            printf("library...");
                    434:        }
                    435:
                    436:        /*
                    437:         * always out of date if no children and :: target
                    438:         */
                    439:
                    440:        oodate = Arch_LibOODate(gn) ||
                    441:            (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP));
                    442:     } else if (gn->type & OP_JOIN) {
                    443:        /*
                    444:         * A target with the .JOIN attribute is only considered
                    445:         * out-of-date if any of its children was out-of-date.
                    446:         */
                    447:        if (DEBUG(MAKE)) {
                    448:            printf(".JOIN node...");
                    449:        }
                    450:        oodate = gn->childMade;
                    451:     } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
                    452:        /*
                    453:         * A node which is the object of the force (!) operator or which has
                    454:         * the .EXEC attribute is always considered out-of-date.
                    455:         */
                    456:        if (DEBUG(MAKE)) {
                    457:            if (gn->type & OP_FORCE) {
                    458:                printf("! operator...");
                    459:            } else if (gn->type & OP_PHONY) {
                    460:                printf(".PHONY node...");
                    461:            } else {
                    462:                printf(".EXEC node...");
                    463:            }
                    464:        }
                    465:        oodate = true;
                    466:     } else if (is_strictly_before(gn->mtime, gn->cmtime) ||
                    467:               (is_out_of_date(gn->cmtime) &&
                    468:                (is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP))))
                    469:     {
                    470:        /*
                    471:         * A node whose modification time is less than that of its
                    472:         * youngest child or that has no children (cmtime == OUT_OF_DATE) and
                    473:         * either doesn't exist (mtime == OUT_OF_DATE) or was the object of a
                    474:         * :: operator is out-of-date. Why? Because that's the way Make does
                    475:         * it.
                    476:         */
                    477:        if (DEBUG(MAKE)) {
                    478:            if (is_strictly_before(gn->mtime, gn->cmtime)) {
                    479:                printf("modified before source...");
                    480:            } else if (is_out_of_date(gn->mtime)) {
                    481:                printf("non-existent and no sources...");
                    482:            } else {
                    483:                printf(":: operator and no sources...");
                    484:            }
                    485:        }
                    486:        oodate = true;
                    487:     } else {
                    488: #if 0
                    489:        /* WHY? */
                    490:        if (DEBUG(MAKE)) {
                    491:            printf("source %smade...", gn->childMade ? "" : "not ");
                    492:        }
                    493:        oodate = gn->childMade;
                    494: #else
                    495:        oodate = false;
                    496: #endif /* 0 */
                    497:     }
                    498:
                    499:     /*
                    500:      * If the target isn't out-of-date, the parents need to know its
                    501:      * modification time. Note that targets that appear to be out-of-date
                    502:      * but aren't, because they have no commands and aren't of type OP_NOP,
                    503:      * have their mtime stay below their children's mtime to keep parents from
                    504:      * thinking they're out-of-date.
                    505:      */
                    506:     if (!oodate)
                    507:        Lst_ForEach(&gn->parents, MakeTimeStamp, gn);
                    508:
                    509:     return oodate;
                    510: }
                    511: