[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.9

1.9     ! espie       1: /*     $OpenBSD: engine.c,v 1.5 2007/09/17 09:28:36 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:
                     55: static void MakeTimeStamp(void *, void *);
                     56: static void MakeAddAllSrc(void *, void *);
1.6       espie      57: static int rewrite_time(const char *);
1.1       espie      58:
                     59: bool
1.3       espie      60: Job_CheckCommands(GNode *gn, void (*abortProc)(char *, ...))
1.1       espie      61: {
1.3       espie      62:        if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
1.9     ! espie      63:            (gn->type & (OP_NODEFAULT | OP_LIB)) == 0) {
1.3       espie      64:                /*
                     65:                 * No commands. Look for .DEFAULT rule from which we might infer
                     66:                 * commands
                     67:                 */
1.9     ! espie      68:                if ((DEFAULT->type & OP_DUMMY) == 0 &&
        !            69:                    !Lst_IsEmpty(&DEFAULT->commands)) {
1.3       espie      70:                        /*
                     71:                         * Make only looks for a .DEFAULT if the node was never
                     72:                         * the target of an operator, so that's what we do too.
                     73:                         * If a .DEFAULT was given, we substitute its commands
                     74:                         * for gn's commands and set the IMPSRC variable to be
                     75:                         * the target's name The DEFAULT node acts like a
                     76:                         * transformation rule, in that gn also inherits any
                     77:                         * attributes or sources attached to .DEFAULT itself.
                     78:                         */
                     79:                        Make_HandleUse(DEFAULT, gn);
                     80:                        Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), gn);
                     81:                } else if (is_out_of_date(Dir_MTime(gn))) {
                     82:                        /*
                     83:                         * The node wasn't the target of an operator we have no
                     84:                         * .DEFAULT rule to go on and the target doesn't
                     85:                         * already exist. There's nothing more we can do for
                     86:                         * this branch. If the -k flag wasn't given, we stop in
                     87:                         * our tracks, otherwise we just don't update this
                     88:                         * node's parents so they never get examined.
                     89:                         */
1.5       espie      90:                        static const char msg[] =
1.3       espie      91:                            "make: don't know how to make";
                     92:
                     93:                        if (gn->type & OP_OPTIONAL) {
1.5       espie      94:                                (void)fprintf(stdout, "%s %s(ignored)\n", msg,
1.3       espie      95:                                    gn->name);
                     96:                                (void)fflush(stdout);
                     97:                        } else if (keepgoing) {
1.5       espie      98:                                (void)fprintf(stdout, "%s %s(continuing)\n",
1.3       espie      99:                                    msg, gn->name);
                    100:                                (void)fflush(stdout);
                    101:                                return false;
                    102:                        } else {
1.5       espie     103:                                (*abortProc)("%s %s. Stop in %s.", msg,
1.3       espie     104:                                    gn->name, Var_Value(".CURDIR"));
                    105:                                return false;
                    106:                        }
                    107:                }
1.1       espie     108:        }
1.3       espie     109:        return true;
1.1       espie     110: }
                    111:
1.6       espie     112: /* touch files the hard way, by writing stuff to them */
                    113: static int
                    114: rewrite_time(const char *name)
                    115: {
                    116:        int fd;
                    117:        char c;
                    118:
                    119:        fd = open(name, O_RDWR | O_CREAT, 0666);
                    120:        if (fd < 0)
                    121:                return -1;
                    122:        /*
                    123:         * Read and write a byte to the file to change
                    124:         * the modification time.
                    125:         */
                    126:        if (read(fd, &c, 1) == 1) {
                    127:                (void)lseek(fd, 0, SEEK_SET);
                    128:                (void)write(fd, &c, 1);
                    129:        }
                    130:
                    131:        (void)close(fd);
                    132:        return 0;
                    133: }
                    134:
1.1       espie     135: void
1.3       espie     136: Job_Touch(GNode *gn, bool silent)
1.1       espie     137: {
1.3       espie     138:        if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
                    139:                /*
1.9     ! espie     140:                 * .JOIN, .USE, and .OPTIONAL targets are "virtual" targets
        !           141:                 * and, as such, shouldn't really be created.
1.3       espie     142:                 */
                    143:                return;
                    144:        }
1.1       espie     145:
1.3       espie     146:        if (!silent) {
                    147:                (void)fprintf(stdout, "touch %s\n", gn->name);
                    148:                (void)fflush(stdout);
                    149:        }
1.1       espie     150:
1.3       espie     151:        if (noExecute) {
                    152:                return;
                    153:        }
1.1       espie     154:
1.3       espie     155:        if (gn->type & OP_ARCHV) {
                    156:                Arch_Touch(gn);
                    157:        } else if (gn->type & OP_LIB) {
                    158:                Arch_TouchLib(gn);
                    159:        } else {
                    160:                const char *file = gn->path != NULL ? gn->path : gn->name;
                    161:
                    162:                if (set_times(file) == -1){
1.6       espie     163:                        if (rewrite_time(file) == -1) {
1.5       espie     164:                                (void)fprintf(stdout,
                    165:                                    "*** couldn't touch %s: %s", file,
1.3       espie     166:                                    strerror(errno));
                    167:                                (void)fflush(stdout);
1.9     ! espie     168:                        }
1.1       espie     169:                }
                    170:        }
                    171: }
                    172:
                    173: void
1.7       espie     174: Make_TimeStamp(GNode *parent, GNode *child)
1.1       espie     175: {
1.8       espie     176:        if (is_strictly_before(parent->cmtime, child->mtime))
                    177:                parent->cmtime = child->mtime;
1.1       espie     178: }
                    179:
                    180: void
1.9     ! espie     181: Make_HandleUse(GNode   *cgn,   /* The .USE node */
1.1       espie     182:     GNode      *pgn)   /* The target of the .USE node */
                    183: {
1.3       espie     184:        GNode   *gn;    /* A child of the .USE node */
                    185:        LstNode ln;     /* An element in the children list */
1.1       espie     186:
1.3       espie     187:        if (cgn->type & (OP_USE|OP_TRANSFORM)) {
                    188:                if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) {
1.9     ! espie     189:                        /* .USE or transformation and target has no commands
        !           190:                         * -- append the child's commands to the parent.  */
1.3       espie     191:                        Lst_Concat(&pgn->commands, &cgn->commands);
                    192:                }
1.1       espie     193:
1.5       espie     194:                for (ln = Lst_First(&cgn->children); ln != NULL;
1.3       espie     195:                    ln = Lst_Adv(ln)) {
                    196:                        gn = (GNode *)Lst_Datum(ln);
                    197:
                    198:                        if (Lst_AddNew(&pgn->children, gn)) {
                    199:                                Lst_AtEnd(&gn->parents, pgn);
1.4       espie     200:                                pgn->unmade++;
1.3       espie     201:                        }
                    202:                }
1.1       espie     203:
1.3       espie     204:                pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
1.1       espie     205:
1.3       espie     206:                /*
                    207:                 * This child node is now "made", so we decrement the count of
                    208:                 * unmade children in the parent... We also remove the child
                    209:                 * from the parent's list to accurately reflect the number of
                    210:                 * decent children the parent has. This is used by Make_Run to
1.9     ! espie     211:                 * decide whether to queue the parent or examine its children...
1.3       espie     212:                 */
1.9     ! espie     213:                if (cgn->type & OP_USE)
1.3       espie     214:                        pgn->unmade--;
1.1       espie     215:        }
                    216: }
                    217:
                    218: static void
1.9     ! espie     219: MakeAddAllSrc(void *cgnp, void *pgnp)
1.1       espie     220: {
1.9     ! espie     221:        GNode   *child = (GNode *)cgnp;
        !           222:        GNode   *parent = (GNode *)pgnp;
        !           223:        if ((child->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
        !           224:                const char *target;
1.3       espie     225:
1.9     ! espie     226:                if (OP_NOP(child->type) ||
        !           227:                    (target = Varq_Value(TARGET_INDEX, child)) == NULL) {
1.3       espie     228:                        /*
                    229:                         * this node is only source; use the specific pathname
                    230:                         * for it
                    231:                         */
1.9     ! espie     232:                        target = child->path != NULL ? child->path :
        !           233:                            child->name;
1.3       espie     234:                }
1.1       espie     235:
1.9     ! espie     236:                Varq_Append(ALLSRC_INDEX, target, parent);
        !           237:                if (parent->type & OP_JOIN) {
        !           238:                        if (child->made == MADE)
        !           239:                                Varq_Append(OODATE_INDEX, target, parent);
        !           240:                } else if (is_strictly_before(parent->mtime, child->mtime) ||
        !           241:                   (!is_strictly_before(child->mtime, now) &&
        !           242:                   child->made == MADE)) {
1.3       espie     243:                        /*
                    244:                         * It goes in the OODATE variable if the parent is
                    245:                         * younger than the child or if the child has been
                    246:                         * modified more recently than the start of the make.
1.9     ! espie     247:                         * This is to keep make from getting confused if
        !           248:                         * something else updates the parent after the
        !           249:                         * make starts (shouldn't happen, I know, but sometimes
        !           250:                         * it does). In such a case, if we've updated the kid,
        !           251:                         * the parent is likely to have a modification time
        !           252:                         * later than that of the kid and anything that relies
        !           253:                         * on the OODATE variable will be hosed.
1.3       espie     254:                         */
1.9     ! espie     255:                        Varq_Append(OODATE_INDEX, target, parent);
1.3       espie     256:                }
1.1       espie     257:        }
                    258: }
                    259:
                    260: void
                    261: Make_DoAllVar(GNode *gn)
                    262: {
1.3       espie     263:        Lst_ForEach(&gn->children, MakeAddAllSrc, gn);
1.1       espie     264:
1.3       espie     265:        if (Varq_Value(OODATE_INDEX, gn) == NULL)
                    266:                Varq_Set(OODATE_INDEX, "", gn);
                    267:        if (Varq_Value(ALLSRC_INDEX, gn) == NULL)
                    268:                Varq_Set(ALLSRC_INDEX, "", gn);
1.1       espie     269:
1.3       espie     270:        if (gn->type & OP_JOIN)
                    271:                Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), gn);
1.1       espie     272: }
                    273:
                    274: /* Wrapper to call Make_TimeStamp from a forEach loop. */
                    275: static void
1.9     ! espie     276: MakeTimeStamp(void *parent, void *child)
1.1       espie     277: {
1.9     ! espie     278:     Make_TimeStamp((GNode *)parent, (GNode *)child);
1.1       espie     279: }
                    280:
                    281: bool
1.9     ! espie     282: Make_OODate(GNode *gn)
1.1       espie     283: {
1.9     ! espie     284:        bool        oodate;
1.1       espie     285:
                    286:        /*
1.3       espie     287:         * Certain types of targets needn't even be sought as their datedness
                    288:         * doesn't depend on their modification time...
1.1       espie     289:         */
1.3       espie     290:        if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
                    291:                (void)Dir_MTime(gn);
                    292:                if (DEBUG(MAKE)) {
1.9     ! espie     293:                        if (!is_out_of_date(gn->mtime))
1.5       espie     294:                                printf("modified %s...",
1.3       espie     295:                                    time_to_string(gn->mtime));
1.9     ! espie     296:                        else
1.3       espie     297:                                printf("non-existent...");
                    298:                }
1.1       espie     299:        }
                    300:
                    301:        /*
1.3       espie     302:         * A target is remade in one of the following circumstances:
1.9     ! espie     303:         * - its modification time is smaller than that of its youngest child
        !           304:         *   and it would actually be run (has commands or type OP_NOP)
        !           305:         * - it's the object of a force operator
        !           306:         * - it has no children, was on the lhs of an operator and doesn't
        !           307:         *   exist already.
1.3       espie     308:         *
                    309:         * Libraries are only considered out-of-date if the archive module says
                    310:         * they are.
1.1       espie     311:         */
1.3       espie     312:        if (gn->type & OP_USE) {
                    313:                /*
                    314:                 * If the node is a USE node it is *never* out of date
                    315:                 * no matter *what*.
                    316:                 */
1.9     ! espie     317:                if (DEBUG(MAKE))
1.3       espie     318:                        printf(".USE node...");
                    319:                oodate = false;
                    320:        } else if ((gn->type & OP_LIB) && Arch_IsLib(gn)) {
1.9     ! espie     321:                if (DEBUG(MAKE))
        !           322:                    printf("library...");
1.3       espie     323:
1.9     ! espie     324:                /* always out of date if no children and :: target */
1.3       espie     325:                oodate = Arch_LibOODate(gn) ||
                    326:                    (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP));
                    327:        } else if (gn->type & OP_JOIN) {
                    328:                /*
                    329:                 * A target with the .JOIN attribute is only considered
                    330:                 * out-of-date if any of its children was out-of-date.
                    331:                 */
1.9     ! espie     332:                if (DEBUG(MAKE))
1.3       espie     333:                        printf(".JOIN node...");
                    334:                oodate = gn->childMade;
                    335:        } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
                    336:                /*
1.9     ! espie     337:                 * A node which is the object of the force (!) operator or which
        !           338:                 * has the .EXEC attribute is always considered out-of-date.
1.3       espie     339:                 */
                    340:                if (DEBUG(MAKE)) {
1.9     ! espie     341:                        if (gn->type & OP_FORCE)
1.3       espie     342:                                printf("! operator...");
1.9     ! espie     343:                        else if (gn->type & OP_PHONY)
1.3       espie     344:                                printf(".PHONY node...");
1.9     ! espie     345:                        else
1.3       espie     346:                                printf(".EXEC node...");
                    347:                }
                    348:                oodate = true;
                    349:        } else if (is_strictly_before(gn->mtime, gn->cmtime) ||
1.9     ! espie     350:           (is_out_of_date(gn->cmtime) &&
1.3       espie     351:            (is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP)))) {
                    352:                /*
                    353:                 * A node whose modification time is less than that of its
                    354:                 * youngest child or that has no children (cmtime ==
                    355:                 * OUT_OF_DATE) and either doesn't exist (mtime == OUT_OF_DATE)
1.9     ! espie     356:                 * or was the object of a :: operator is out-of-date.
1.3       espie     357:                 */
                    358:                if (DEBUG(MAKE)) {
1.9     ! espie     359:                        if (is_strictly_before(gn->mtime, gn->cmtime))
1.3       espie     360:                                printf("modified before source...");
1.9     ! espie     361:                        else if (is_out_of_date(gn->mtime))
1.3       espie     362:                                printf("non-existent and no sources...");
1.9     ! espie     363:                        else
1.3       espie     364:                                printf(":: operator and no sources...");
                    365:                }
                    366:                oodate = true;
                    367:        } else {
                    368:                oodate = false;
                    369:        }
1.1       espie     370:
1.3       espie     371:        /*
                    372:         * If the target isn't out-of-date, the parents need to know its
                    373:         * modification time. Note that targets that appear to be out-of-date
                    374:         * but aren't, because they have no commands and aren't of type OP_NOP,
                    375:         * have their mtime stay below their children's mtime to keep parents
                    376:         * from thinking they're out-of-date.
                    377:         */
                    378:        if (!oodate)
                    379:                Lst_ForEach(&gn->parents, MakeTimeStamp, gn);
1.1       espie     380:
1.3       espie     381:        return oodate;
1.1       espie     382: }
                    383: