Annotation of src/usr.bin/make/targ.c, Revision 1.53
1.31 espie 1: /* $OpenPackages$ */
1.49 espie 2: /* $OpenBSD$ */
1.6 millert 3: /* $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $ */
1.1 deraadt 4:
5: /*
1.31 espie 6: * Copyright (c) 1999 Marc Espie.
7: *
8: * Extensive code changes for the OpenBSD project.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
23: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
31: /*
1.5 millert 32: * Copyright (c) 1988, 1989, 1990, 1993
33: * The Regents of the University of California. All rights reserved.
1.1 deraadt 34: * Copyright (c) 1989 by Berkeley Softworks
35: * All rights reserved.
36: *
37: * This code is derived from software contributed to Berkeley by
38: * Adam de Boor.
39: *
40: * Redistribution and use in source and binary forms, with or without
41: * modification, are permitted provided that the following conditions
42: * are met:
43: * 1. Redistributions of source code must retain the above copyright
44: * notice, this list of conditions and the following disclaimer.
45: * 2. Redistributions in binary form must reproduce the above copyright
46: * notice, this list of conditions and the following disclaimer in the
47: * documentation and/or other materials provided with the distribution.
1.38 millert 48: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 49: * may be used to endorse or promote products derived from this software
50: * without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62: * SUCH DAMAGE.
63: */
64:
65: /*-
66: * targ.c --
1.27 espie 67: * Target nodes are kept into a hash table.
1.1 deraadt 68: *
69: * Interface:
1.31 espie 70: * Targ_Init Initialization procedure.
1.1 deraadt 71: *
1.31 espie 72: * Targ_End Cleanup the module
1.1 deraadt 73: *
1.31 espie 74: * Targ_NewGN Create a new GNode for the passed target
75: * (string). The node is *not* placed in the
76: * hash table, though all its fields are
77: * initialized.
1.1 deraadt 78: *
1.31 espie 79: * Targ_FindNode Find the node for a given target, creating
80: * and storing it if it doesn't exist and the
81: * flags are right (TARG_CREATE)
1.1 deraadt 82: *
1.31 espie 83: * Targ_FindList Given a list of names, find nodes for all
84: * of them, creating nodes if needed.
1.1 deraadt 85: *
1.32 espie 86: * Targ_Ignore Return true if errors should be ignored when
1.31 espie 87: * creating the given target.
1.1 deraadt 88: *
1.32 espie 89: * Targ_Silent Return true if we should be silent when
1.31 espie 90: * creating the given target.
1.1 deraadt 91: *
1.32 espie 92: * Targ_Precious Return true if the target is precious and
1.31 espie 93: * should not be removed if we are interrupted.
1.1 deraadt 94: *
95: * Debugging:
1.31 espie 96: * Targ_PrintGraph Print out the entire graphm all variables
97: * and statistics for the directory cache. Should
98: * print something for suffixes, too, but...
1.1 deraadt 99: */
100:
1.34 espie 101: #include <limits.h>
1.32 espie 102: #include <stddef.h>
103: #include <stdio.h>
1.40 espie 104: #include <stdint.h>
1.33 espie 105: #include <string.h>
1.32 espie 106: #include "config.h"
107: #include "defines.h"
108: #include "ohash.h"
109: #include "stats.h"
110: #include "suff.h"
111: #include "var.h"
112: #include "targ.h"
113: #include "memory.h"
114: #include "gnode.h"
115: #include "extern.h"
116: #include "timestamp.h"
117: #include "lst.h"
1.46 espie 118: #include "node_int.h"
119: #include "nodehashconsts.h"
1.37 espie 120: #ifdef CLEANUP
121: #include <stdlib.h>
122: #endif
1.31 espie 123:
124: static struct ohash targets; /* a hash table of same */
1.46 espie 125: struct ohash_info gnode_info = {
126: offsetof(GNode, name), NULL, hash_alloc, hash_free, element_alloc
1.42 espie 127: };
1.1 deraadt 128:
1.31 espie 129: static void TargPrintOnlySrc(GNode *);
130: static void TargPrintName(void *);
131: static void TargPrintNode(GNode *, int);
1.10 espie 132: #ifdef CLEANUP
1.37 espie 133: static LIST allTargets;
1.31 espie 134: static void TargFreeGN(void *);
1.10 espie 135: #endif
1.48 espie 136: #define Targ_FindConstantNode(n, f) Targ_FindNodeh(n, sizeof(n), K_##n, f)
1.52 espie 137: static const char *status_to_string(GNode *);
1.48 espie 138:
1.1 deraadt 139:
1.46 espie 140: GNode *begin_node, *end_node, *interrupt_node, *DEFAULT;
141:
1.1 deraadt 142: void
1.39 espie 143: Targ_Init(void)
1.1 deraadt 144: {
1.42 espie 145: /* A small make file already creates 200 targets. */
146: ohash_init(&targets, 10, &gnode_info);
1.37 espie 147: #ifdef CLEANUP
1.42 espie 148: Lst_Init(&allTargets);
1.37 espie 149: #endif
1.46 espie 150: begin_node = Targ_FindConstantNode(NODE_BEGIN, TARG_CREATE);
151: begin_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
152: end_node = Targ_FindConstantNode(NODE_END, TARG_CREATE);
153: end_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
154: interrupt_node = Targ_FindConstantNode(NODE_INTERRUPT, TARG_CREATE);
155: interrupt_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
156: DEFAULT = Targ_FindConstantNode(NODE_DEFAULT, TARG_CREATE);
157: DEFAULT->type |= OP_DUMMY | OP_NOTMAIN| OP_TRANSFORM | OP_NODEFAULT;
158:
1.1 deraadt 159: }
160:
1.32 espie 161: #ifdef CLEANUP
1.1 deraadt 162: void
1.39 espie 163: Targ_End(void)
1.1 deraadt 164: {
1.42 espie 165: Lst_Every(&allTargets, TargFreeGN);
166: ohash_delete(&targets);
1.32 espie 167: }
1.10 espie 168: #endif
1.1 deraadt 169:
170: GNode *
1.46 espie 171: Targ_NewGNi(const char *name, const char *ename)
1.1 deraadt 172: {
1.42 espie 173: GNode *gn;
1.1 deraadt 174:
1.42 espie 175: gn = ohash_create_entry(&gnode_info, name, &ename);
176: gn->path = NULL;
1.46 espie 177: if (name[0] == '-' && name[1] == 'l')
1.42 espie 178: gn->type = OP_LIB;
1.46 espie 179: else
1.42 espie 180: gn->type = 0;
1.46 espie 181:
182: gn->special = SPECIAL_NONE;
183: gn->unmade = 0;
1.51 espie 184: gn->must_make = false;
1.53 ! espie 185: gn->built_status = UNKNOWN;
1.42 espie 186: gn->childMade = false;
1.46 espie 187: gn->order = 0;
1.42 espie 188: ts_set_out_of_date(gn->mtime);
189: ts_set_out_of_date(gn->cmtime);
190: Lst_Init(&gn->cohorts);
191: Lst_Init(&gn->parents);
192: Lst_Init(&gn->children);
193: Lst_Init(&gn->successors);
194: Lst_Init(&gn->preds);
195: SymTable_Init(&gn->context);
196: gn->lineno = 0;
197: gn->fname = NULL;
1.50 espie 198: gn->impliedsrc = NULL;
1.42 espie 199: Lst_Init(&gn->commands);
200: gn->suffix = NULL;
1.1 deraadt 201:
1.31 espie 202: #ifdef STATS_GN_CREATION
1.42 espie 203: STAT_GN_COUNT++;
1.10 espie 204: #endif
1.1 deraadt 205:
1.37 espie 206: #ifdef CLEANUP
1.42 espie 207: Lst_AtEnd(&allTargets, gn);
1.37 espie 208: #endif
1.42 espie 209: return gn;
1.1 deraadt 210: }
211:
1.10 espie 212: #ifdef CLEANUP
1.1 deraadt 213: static void
1.39 espie 214: TargFreeGN(void *gnp)
1.1 deraadt 215: {
1.42 espie 216: GNode *gn = (GNode *)gnp;
1.1 deraadt 217:
1.42 espie 218: efree(gn->path);
219: Lst_Destroy(&gn->cohorts, NOFREE);
220: Lst_Destroy(&gn->parents, NOFREE);
221: Lst_Destroy(&gn->children, NOFREE);
222: Lst_Destroy(&gn->successors, NOFREE);
223: Lst_Destroy(&gn->preds, NOFREE);
224: Lst_Destroy(&gn->commands, NOFREE);
225: SymTable_Destroy(&gn->context);
226: free(gn);
1.1 deraadt 227: }
1.10 espie 228: #endif
1.1 deraadt 229:
1.46 espie 230: GNode *
231: Targ_FindNodei(const char *name, const char *ename, int flags)
232: {
233: uint32_t hv;
234:
235: hv = ohash_interval(name, &ename);
236: return Targ_FindNodeih(name, ename, hv, flags);
237: }
1.1 deraadt 238:
239: GNode *
1.46 espie 240: Targ_FindNodeih(const char *name, const char *ename, uint32_t hv, int flags)
1.1 deraadt 241: {
1.46 espie 242: GNode *gn;
1.42 espie 243: unsigned int slot;
1.27 espie 244:
1.46 espie 245: slot = ohash_lookup_interval(&targets, name, ename, hv);
1.27 espie 246:
1.42 espie 247: gn = ohash_find(&targets, slot);
1.31 espie 248:
1.42 espie 249: if (gn == NULL && (flags & TARG_CREATE)) {
250: gn = Targ_NewGNi(name, ename);
251: ohash_insert(&targets, slot, gn);
252: }
1.1 deraadt 253:
1.42 espie 254: return gn;
1.1 deraadt 255: }
256:
1.20 espie 257: void
1.46 espie 258: Targ_FindList(Lst nodes, Lst names)
1.1 deraadt 259: {
1.46 espie 260: LstNode ln;
261: GNode *gn;
1.42 espie 262: char *name;
263:
264: for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {
265: name = (char *)Lst_Datum(ln);
266: gn = Targ_FindNode(name, TARG_CREATE);
267: /* Note: Lst_AtEnd must come before the Lst_Concat so the nodes
268: * are added to the list in the order in which they were
269: * encountered in the makefile. */
270: Lst_AtEnd(nodes, gn);
271: if (gn->type & OP_DOUBLEDEP)
272: Lst_Concat(nodes, &gn->cohorts);
273: }
1.1 deraadt 274: }
275:
1.32 espie 276: bool
1.39 espie 277: Targ_Ignore(GNode *gn)
1.1 deraadt 278: {
1.42 espie 279: if (ignoreErrors || gn->type & OP_IGNORE)
280: return true;
281: else
282: return false;
1.1 deraadt 283: }
284:
1.32 espie 285: bool
1.39 espie 286: Targ_Silent(GNode *gn)
1.1 deraadt 287: {
1.42 espie 288: if (beSilent || gn->type & OP_SILENT)
289: return true;
290: else
291: return false;
1.1 deraadt 292: }
293:
1.32 espie 294: bool
1.39 espie 295: Targ_Precious(GNode *gn)
1.1 deraadt 296: {
1.42 espie 297: if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP)))
298: return true;
299: else
300: return false;
1.1 deraadt 301: }
302:
1.17 espie 303: static void
1.39 espie 304: TargPrintName(void *gnp)
1.1 deraadt 305: {
1.42 espie 306: GNode *gn = (GNode *)gnp;
307: printf("%s ", gn->name);
1.1 deraadt 308: }
309:
310:
1.17 espie 311: void
1.39 espie 312: Targ_PrintCmd(void *cmd)
1.1 deraadt 313: {
1.42 espie 314: printf("\t%s\n", (char *)cmd);
1.1 deraadt 315: }
316:
317: void
1.39 espie 318: Targ_PrintType(int type)
1.1 deraadt 319: {
1.42 espie 320: int tbit;
1.5 millert 321:
1.46 espie 322: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
323: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
1.42 espie 324:
325: type &= ~OP_OPMASK;
326:
327: while (type) {
328: tbit = 1 << (ffs(type) - 1);
329: type &= ~tbit;
330:
331: switch (tbit) {
332: PRINTBIT(OPTIONAL);
333: PRINTBIT(USE);
334: PRINTBIT(EXEC);
335: PRINTBIT(IGNORE);
336: PRINTBIT(PRECIOUS);
337: PRINTBIT(SILENT);
338: PRINTBIT(MAKE);
339: PRINTBIT(JOIN);
340: PRINTBIT(INVISIBLE);
341: PRINTBIT(NOTMAIN);
342: PRINTDBIT(LIB);
343: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.45 espie 344: case OP_MEMBER:
345: if (DEBUG(TARG))
346: printf(".MEMBER ");
1.42 espie 347: break;
348: PRINTDBIT(ARCHV);
349: }
1.46 espie 350: }
1.1 deraadt 351: }
1.52 espie 352: static const char *
353: status_to_string(GNode *gn)
354: {
355: switch (gn->built_status) {
1.53 ! espie 356: case UNKNOWN:
! 357: return "unknown";
1.52 espie 358: case MADE:
359: return "made";
360: case UPTODATE:
361: return "up-to-date";
362: case ERROR:
363: return "error when made";
364: case ABORTED:
365: return "aborted";
366: default:
367: return "other status";
368: }
369: }
1.1 deraadt 370:
1.17 espie 371: static void
1.39 espie 372: TargPrintNode(GNode *gn, int pass)
1.1 deraadt 373: {
1.42 espie 374: if (OP_NOP(gn->type))
375: return;
1.1 deraadt 376: printf("#\n");
377: if (pass == 2) {
1.46 espie 378: printf("# %d unmade children\n", gn->unmade);
1.42 espie 379: if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
380: if (!is_out_of_date(gn->mtime)) {
381: printf("# last modified %s: %s\n",
1.46 espie 382: time_to_string(gn->mtime),
1.52 espie 383: status_to_string(gn));
1.53 ! espie 384: } else if (gn->built_status != UNKNOWN) {
1.42 espie 385: printf("# non-existent (maybe): %s\n",
1.52 espie 386: status_to_string(gn));
1.42 espie 387: } else {
388: printf("# unmade\n");
389: }
390: }
1.1 deraadt 391: }
1.19 espie 392: if (!Lst_IsEmpty(&gn->parents)) {
1.42 espie 393: printf("# parents: ");
394: Lst_Every(&gn->parents, TargPrintName);
395: fputc('\n', stdout);
1.1 deraadt 396: }
1.50 espie 397: if (gn->impliedsrc)
398: printf("# implied source: %s\n", gn->impliedsrc->name);
1.5 millert 399:
1.1 deraadt 400: printf("%-16s", gn->name);
401: switch (gn->type & OP_OPMASK) {
1.42 espie 402: case OP_DEPENDS:
1.1 deraadt 403: printf(": "); break;
1.42 espie 404: case OP_FORCE:
1.1 deraadt 405: printf("! "); break;
1.42 espie 406: case OP_DOUBLEDEP:
1.1 deraadt 407: printf(":: "); break;
408: }
1.17 espie 409: Targ_PrintType(gn->type);
1.19 espie 410: Lst_Every(&gn->children, TargPrintName);
1.17 espie 411: fputc('\n', stdout);
1.19 espie 412: Lst_Every(&gn->commands, Targ_PrintCmd);
1.1 deraadt 413: printf("\n\n");
1.27 espie 414: if (gn->type & OP_DOUBLEDEP) {
1.42 espie 415: LstNode ln;
1.31 espie 416:
1.42 espie 417: for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln))
418: TargPrintNode((GNode *)Lst_Datum(ln), pass);
1.27 espie 419: }
1.1 deraadt 420: }
421:
1.17 espie 422: static void
1.39 espie 423: TargPrintOnlySrc(GNode *gn)
1.1 deraadt 424: {
1.47 espie 425: if (OP_NOP(gn->type) && gn->special == SPECIAL_NONE &&
426: !(gn->type & OP_DUMMY))
1.42 espie 427: printf("#\t%s [%s]\n", gn->name,
428: gn->path != NULL ? gn->path : gn->name);
1.1 deraadt 429: }
430:
431: void
1.39 espie 432: Targ_PrintGraph(int pass) /* Which pass this is. 1 => no processing
1.31 espie 433: * 2 => processing done */
1.1 deraadt 434: {
1.42 espie 435: GNode *gn;
436: unsigned int i;
1.27 espie 437:
1.42 espie 438: printf("#*** Input graph:\n");
439: for (gn = ohash_first(&targets, &i); gn != NULL;
440: gn = ohash_next(&targets, &i))
441: TargPrintNode(gn, pass);
442: printf("\n\n");
443: printf("#\n# Files that are only sources:\n");
444: for (gn = ohash_first(&targets, &i); gn != NULL;
445: gn = ohash_next(&targets, &i))
1.46 espie 446: TargPrintOnlySrc(gn);
1.42 espie 447: Var_Dump();
448: printf("\n");
1.46 espie 449: #ifdef DEBUG_DIRECTORY_CACHE
450: Dir_PrintDirectories();
451: printf("\n");
452: #endif
1.42 espie 453: Suff_PrintAll();
1.49 espie 454: }
455:
456: static char *curdir, *objdir;
457: static size_t curdir_len, objdir_len;
458:
459: void
460: Targ_setdirs(const char *c, const char *o)
461: {
462: curdir_len = strlen(c);
463: curdir = emalloc(curdir_len+2);
464: memcpy(curdir, c, curdir_len);
465: curdir[curdir_len++] = '/';
466: curdir[curdir_len] = 0;
467:
468: objdir_len = strlen(o);
469: objdir = emalloc(objdir_len+2);
470: memcpy(objdir, o, objdir_len);
471: objdir[objdir_len++] = '/';
472: objdir[objdir_len] = 0;
473: }
474:
475: void
476: look_harder_for_target(GNode *gn)
477: {
478: GNode *extra, *cgn;
479: LstNode ln;
480:
481: if (gn->type & OP_RESOLVED)
482: return;
483: gn->type |= OP_RESOLVED;
484: if (strncmp(gn->name, objdir, objdir_len) == 0) {
485: extra = Targ_FindNode(gn->name + objdir_len, TARG_NOCREATE);
486: if (extra != NULL) {
487: if (Lst_IsEmpty(&gn->commands))
488: Lst_Concat(&gn->commands, &extra->commands);
489: for (ln = Lst_First(&extra->children); ln != NULL;
490: ln = Lst_Adv(ln)) {
491: cgn = (GNode *)Lst_Datum(ln);
492:
493: if (Lst_AddNew(&gn->children, cgn)) {
494: Lst_AtEnd(&cgn->parents, gn);
495: gn->unmade++;
496: }
497: }
498: }
499: }
1.1 deraadt 500: }