targ.c revision 1.140 1 /* $NetBSD: targ.c,v 1.140 2020/11/22 20:01:46 rillig Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
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 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 /*
36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved.
38 *
39 * This code is derived from software contributed to Berkeley by
40 * Adam de Boor.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE.
69 */
70
71 /*
72 * Maintaining the targets and sources, which are both implemented as GNode.
73 *
74 * Interface:
75 * Targ_Init Initialize the module.
76 *
77 * Targ_End Clean up the module.
78 *
79 * Targ_List Return the list of all targets so far.
80 *
81 * GNode_New Create a new GNode for the passed target
82 * (string). The node is *not* placed in the
83 * hash table, though all its fields are
84 * initialized.
85 *
86 * Targ_FindNode Find the node, or return NULL.
87 *
88 * Targ_GetNode Find the node, or create it.
89 *
90 * Targ_NewInternalNode
91 * Create an internal node.
92 *
93 * Targ_FindList Given a list of names, find nodes for all
94 * of them, creating them as necessary.
95 *
96 * Targ_Ignore Return TRUE if errors should be ignored when
97 * creating the given target.
98 *
99 * Targ_Silent Return TRUE if we should be silent when
100 * creating the given target.
101 *
102 * Targ_Precious Return TRUE if the target is precious and
103 * should not be removed if we are interrupted.
104 *
105 * Targ_Propagate Propagate information between related nodes.
106 * Should be called after the makefiles are parsed
107 * but before any action is taken.
108 *
109 * Debugging:
110 * Targ_PrintGraph
111 * Print out the entire graphm all variables and
112 * statistics for the directory cache. Should print
113 * something for suffixes, too, but...
114 */
115
116 #include <time.h>
117
118 #include "make.h"
119 #include "dir.h"
120
121 /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
122 MAKE_RCSID("$NetBSD: targ.c,v 1.140 2020/11/22 20:01:46 rillig Exp $");
123
124 /*
125 * All target nodes that appeared on the left-hand side of one of the
126 * dependency operators ':', '::', '!'.
127 */
128 static GNodeList *allTargets;
129 static HashTable allTargetsByName;
130
131 #ifdef CLEANUP
132 static GNodeList *allNodes;
133
134 static void GNode_Free(void *);
135 #endif
136
137 void
138 Targ_Init(void)
139 {
140 allTargets = Lst_New();
141 HashTable_Init(&allTargetsByName);
142 #ifdef CLEANUP
143 allNodes = Lst_New();
144 #endif
145 }
146
147 void
148 Targ_End(void)
149 {
150 Targ_Stats();
151 #ifdef CLEANUP
152 Lst_Free(allTargets);
153 HashTable_Done(&allTargetsByName);
154 Lst_Destroy(allNodes, GNode_Free);
155 #endif
156 }
157
158 void
159 Targ_Stats(void)
160 {
161 HashTable_DebugStats(&allTargetsByName, "targets");
162 }
163
164 /*
165 * Return the list of all targets, which are all nodes that appear on the
166 * left-hand side of a dependency declaration such as "target: source".
167 * The returned list does not contain pure sources.
168 */
169 GNodeList *
170 Targ_List(void)
171 {
172 return allTargets;
173 }
174
175 /* Create a new graph node, but don't register it anywhere.
176 *
177 * Graph nodes that appear on the left-hand side of a dependency line such
178 * as "target: source" are called targets. XXX: In some cases (like the
179 * .ALLTARGETS variable), all nodes are called targets as well, even if they
180 * never appear on the left-hand side. This is a mistake.
181 *
182 * Typical names for graph nodes are:
183 * "src.c" (an ordinary file)
184 * "clean" (a .PHONY target)
185 * ".END" (a special hook target)
186 * "-lm" (a library)
187 * "libc.a(isspace.o)" (an archive member)
188 */
189 GNode *
190 GNode_New(const char *name)
191 {
192 GNode *gn;
193
194 gn = bmake_malloc(sizeof *gn);
195 gn->name = bmake_strdup(name);
196 gn->uname = NULL;
197 gn->path = NULL;
198 gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : 0;
199 gn->flags = 0;
200 gn->made = UNMADE;
201 gn->unmade = 0;
202 gn->mtime = 0;
203 gn->youngestChild = NULL;
204 gn->implicitParents = Lst_New();
205 gn->parents = Lst_New();
206 gn->children = Lst_New();
207 gn->order_pred = Lst_New();
208 gn->order_succ = Lst_New();
209 gn->cohorts = Lst_New();
210 gn->cohort_num[0] = '\0';
211 gn->unmade_cohorts = 0;
212 gn->centurion = NULL;
213 gn->checked_seqno = 0;
214 HashTable_Init(&gn->vars);
215 gn->commands = Lst_New();
216 gn->suffix = NULL;
217 gn->fname = NULL;
218 gn->lineno = 0;
219
220 #ifdef CLEANUP
221 Lst_Append(allNodes, gn);
222 #endif
223
224 return gn;
225 }
226
227 #ifdef CLEANUP
228 static void
229 GNode_Free(void *gnp)
230 {
231 GNode *gn = gnp;
232
233 free(gn->name);
234 free(gn->uname);
235 free(gn->path);
236 /* gn->youngestChild is not owned by this node. */
237 Lst_Free(gn->implicitParents); /* Do not free the nodes themselves, */
238 Lst_Free(gn->parents); /* as they are not owned by this node. */
239 Lst_Free(gn->children); /* likewise */
240 Lst_Free(gn->order_pred); /* likewise */
241 Lst_Free(gn->order_succ); /* likewise */
242 Lst_Free(gn->cohorts); /* likewise */
243 HashTable_Done(&gn->vars); /* Do not free the variables themselves,
244 * even though they are owned by this node.
245 * XXX: they should probably be freed. */
246 Lst_Free(gn->commands); /* Do not free the commands themselves,
247 * as they may be shared with other nodes. */
248 /* gn->suffix is not owned by this node. */
249 /* XXX: gn->suffix should be unreferenced here. This requires a thorough
250 * check that the reference counting is done correctly in all places,
251 * otherwise a suffix might be freed too early. */
252
253 free(gn);
254 }
255 #endif
256
257 /* Get the existing global node, or return NULL. */
258 GNode *
259 Targ_FindNode(const char *name)
260 {
261 return HashTable_FindValue(&allTargetsByName, name);
262 }
263
264 /* Get the existing global node, or create it. */
265 GNode *
266 Targ_GetNode(const char *name)
267 {
268 Boolean isNew;
269 HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew);
270 if (!isNew)
271 return HashEntry_Get(he);
272
273 {
274 GNode *gn = Targ_NewInternalNode(name);
275 HashEntry_Set(he, gn);
276 return gn;
277 }
278 }
279
280 /*
281 * Create a node, register it in .ALLTARGETS but don't store it in the
282 * table of global nodes. This means it cannot be found by name.
283 *
284 * This is used for internal nodes, such as cohorts or .WAIT nodes.
285 */
286 GNode *
287 Targ_NewInternalNode(const char *name)
288 {
289 GNode *gn = GNode_New(name);
290 Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
291 Lst_Append(allTargets, gn);
292 DEBUG1(TARG, "Adding \"%s\" to all targets.\n", gn->name);
293 if (doing_depend)
294 gn->flags |= FROM_DEPEND;
295 return gn;
296 }
297
298 /*
299 * Return the .END node, which contains the commands to be run when
300 * everything else has been made.
301 */
302 GNode *Targ_GetEndNode(void)
303 {
304 /* Save the node locally to avoid having to search for it all the time. */
305 static GNode *endNode = NULL;
306 if (endNode == NULL) {
307 endNode = Targ_GetNode(".END");
308 endNode->type = OP_SPECIAL;
309 }
310 return endNode;
311 }
312
313 /* Return the named nodes, creating them as necessary. */
314 GNodeList *
315 Targ_FindList(StringList *names)
316 {
317 StringListNode *ln;
318 GNodeList *nodes = Lst_New();
319 for (ln = names->first; ln != NULL; ln = ln->next) {
320 const char *name = ln->datum;
321 GNode *gn = Targ_GetNode(name);
322 Lst_Append(nodes, gn);
323 }
324 return nodes;
325 }
326
327 /* Return true if should ignore errors when creating gn. */
328 Boolean
329 Targ_Ignore(const GNode *gn)
330 {
331 return opts.ignoreErrors || gn->type & OP_IGNORE;
332 }
333
334 /* Return true if be silent when creating gn. */
335 Boolean
336 Targ_Silent(const GNode *gn)
337 {
338 return opts.beSilent || gn->type & OP_SILENT;
339 }
340
341 /* See if the given target is precious. */
342 Boolean
343 Targ_Precious(const GNode *gn)
344 {
345 /* XXX: Why are '::' targets precious? */
346 return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP);
347 }
348
349 /*
350 * The main target to be made; only for debugging output.
351 * See mainNode in parse.c for the definitive source.
352 */
353 static GNode *mainTarg;
354
355 /* Remember the main target to make; only used for debugging. */
356 void
357 Targ_SetMain(GNode *gn)
358 {
359 mainTarg = gn;
360 }
361
362 static void
363 PrintNodeNames(GNodeList *gnodes)
364 {
365 GNodeListNode *node;
366
367 for (node = gnodes->first; node != NULL; node = node->next) {
368 GNode *gn = node->datum;
369 debug_printf(" %s%s", gn->name, gn->cohort_num);
370 }
371 }
372
373 static void
374 PrintNodeNamesLine(const char *label, GNodeList *gnodes)
375 {
376 if (Lst_IsEmpty(gnodes))
377 return;
378 debug_printf("# %s:", label);
379 PrintNodeNames(gnodes);
380 debug_printf("\n");
381 }
382
383 void
384 Targ_PrintCmds(GNode *gn)
385 {
386 StringListNode *ln;
387 for (ln = gn->commands->first; ln != NULL; ln = ln->next) {
388 const char *cmd = ln->datum;
389 debug_printf("\t%s\n", cmd);
390 }
391 }
392
393 /* Format a modification time in some reasonable way and return it.
394 * The time is placed in a static area, so it is overwritten with each call. */
395 char *
396 Targ_FmtTime(time_t tm)
397 {
398 struct tm *parts;
399 static char buf[128];
400
401 /* TODO: Add special case for 0, which often means ENOENT, to make it
402 * independent from time zones. */
403 parts = localtime(&tm);
404 (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
405 return buf;
406 }
407
408 /* Print out a type field giving only those attributes the user can set. */
409 void
410 Targ_PrintType(int type)
411 {
412 int tbit;
413
414 #define PRINTBIT(attr) case CONCAT(OP_,attr): debug_printf(" ." #attr); break
415 #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))debug_printf(" ." #attr); break
416
417 type &= ~OP_OPMASK;
418
419 while (type) {
420 tbit = 1 << (ffs(type) - 1);
421 type &= ~tbit;
422
423 switch(tbit) {
424 PRINTBIT(OPTIONAL);
425 PRINTBIT(USE);
426 PRINTBIT(EXEC);
427 PRINTBIT(IGNORE);
428 PRINTBIT(PRECIOUS);
429 PRINTBIT(SILENT);
430 PRINTBIT(MAKE);
431 PRINTBIT(JOIN);
432 PRINTBIT(INVISIBLE);
433 PRINTBIT(NOTMAIN);
434 PRINTDBIT(LIB);
435 /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
436 case OP_MEMBER: if (DEBUG(TARG))debug_printf(" .MEMBER"); break;
437 PRINTDBIT(ARCHV);
438 PRINTDBIT(MADE);
439 PRINTDBIT(PHONY);
440 }
441 }
442 }
443
444 static const char *
445 made_name(GNodeMade made)
446 {
447 switch (made) {
448 case UNMADE: return "unmade";
449 case DEFERRED: return "deferred";
450 case REQUESTED: return "requested";
451 case BEINGMADE: return "being made";
452 case MADE: return "made";
453 case UPTODATE: return "up-to-date";
454 case ERROR: return "error when made";
455 case ABORTED: return "aborted";
456 default: return "unknown enum_made value";
457 }
458 }
459
460 static const char *
461 GNode_OpName(const GNode *gn)
462 {
463 switch (gn->type & OP_OPMASK) {
464 case OP_DEPENDS:
465 return ":";
466 case OP_FORCE:
467 return "!";
468 case OP_DOUBLEDEP:
469 return "::";
470 }
471 return "";
472 }
473
474 /* Print the contents of a node. */
475 void
476 Targ_PrintNode(GNode *gn, int pass)
477 {
478 debug_printf("# %s%s", gn->name, gn->cohort_num);
479 GNode_FprintDetails(opts.debug_file, ", ", gn, "\n");
480 if (gn->flags == 0)
481 return;
482
483 if (GNode_IsTarget(gn)) {
484 debug_printf("#\n");
485 if (gn == mainTarg) {
486 debug_printf("# *** MAIN TARGET ***\n");
487 }
488 if (pass >= 2) {
489 if (gn->unmade > 0) {
490 debug_printf("# %d unmade children\n", gn->unmade);
491 } else {
492 debug_printf("# No unmade children\n");
493 }
494 if (!(gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
495 if (gn->mtime != 0) {
496 debug_printf("# last modified %s: %s\n",
497 Targ_FmtTime(gn->mtime),
498 made_name(gn->made));
499 } else if (gn->made != UNMADE) {
500 debug_printf("# non-existent (maybe): %s\n",
501 made_name(gn->made));
502 } else {
503 debug_printf("# unmade\n");
504 }
505 }
506 PrintNodeNamesLine("implicit parents", gn->implicitParents);
507 } else {
508 if (gn->unmade)
509 debug_printf("# %d unmade children\n", gn->unmade);
510 }
511 PrintNodeNamesLine("parents", gn->parents);
512 PrintNodeNamesLine("order_pred", gn->order_pred);
513 PrintNodeNamesLine("order_succ", gn->order_succ);
514
515 debug_printf("%-16s%s", gn->name, GNode_OpName(gn));
516 Targ_PrintType(gn->type);
517 PrintNodeNames(gn->children);
518 debug_printf("\n");
519 Targ_PrintCmds(gn);
520 debug_printf("\n\n");
521 if (gn->type & OP_DOUBLEDEP) {
522 Targ_PrintNodes(gn->cohorts, pass);
523 }
524 }
525 }
526
527 void
528 Targ_PrintNodes(GNodeList *gnodes, int pass)
529 {
530 GNodeListNode *ln;
531 for (ln = gnodes->first; ln != NULL; ln = ln->next)
532 Targ_PrintNode(ln->datum, pass);
533 }
534
535 /* Print only those targets that are just a source. */
536 static void
537 PrintOnlySources(void)
538 {
539 GNodeListNode *ln;
540
541 for (ln = allTargets->first; ln != NULL; ln = ln->next) {
542 GNode *gn = ln->datum;
543 if (GNode_IsTarget(gn))
544 continue;
545
546 debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn));
547 Targ_PrintType(gn->type);
548 debug_printf("\n");
549 }
550 }
551
552 /* Input:
553 * pass 1 => before processing
554 * 2 => after processing
555 * 3 => after processing, an error occurred
556 */
557 void
558 Targ_PrintGraph(int pass)
559 {
560 debug_printf("#*** Input graph:\n");
561 Targ_PrintNodes(allTargets, pass);
562 debug_printf("\n");
563 debug_printf("\n");
564
565 debug_printf("#\n");
566 debug_printf("# Files that are only sources:\n");
567 PrintOnlySources();
568
569 debug_printf("#*** Global Variables:\n");
570 Var_Dump(VAR_GLOBAL);
571
572 debug_printf("#*** Command-line Variables:\n");
573 Var_Dump(VAR_CMDLINE);
574
575 debug_printf("\n");
576 Dir_PrintDirectories();
577 debug_printf("\n");
578
579 Suff_PrintAll();
580 }
581
582 /* Propagate some type information to cohort nodes (those from the '::'
583 * dependency operator).
584 *
585 * Should be called after the makefiles are parsed but before any action is
586 * taken. */
587 void
588 Targ_Propagate(void)
589 {
590 GNodeListNode *ln, *cln;
591
592 for (ln = allTargets->first; ln != NULL; ln = ln->next) {
593 GNode *gn = ln->datum;
594 GNodeType type = gn->type;
595
596 if (!(type & OP_DOUBLEDEP))
597 continue;
598
599 for (cln = gn->cohorts->first; cln != NULL; cln = cln->next) {
600 GNode *cohort = cln->datum;
601
602 cohort->type |= type & ~OP_OPMASK;
603 }
604 }
605 }
606