Print this page
make: remove maketool support
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/doname.cc
+++ new/usr/src/cmd/make/bin/doname.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * doname.c
28 28 *
29 29 * Figure out which targets are out of date and rebuild them
30 30 */
31 31
32 32 /*
33 33 * Included files
34 34 */
35 35 #include <alloca.h> /* alloca() */
36 36
37 37
38 38 #include <fcntl.h>
39 39 #include <mk/defs.h>
40 40 #include <mksh/i18n.h> /* get_char_semantics_value() */
41 41 #include <mksh/macro.h> /* getvar(), expand_value() */
42 42 #include <mksh/misc.h> /* getmem() */
43 43 #include <poll.h>
44 44
45 45
46 46 #include <signal.h>
47 47
48 48 # include <stropts.h>
49 49
50 50 #include <sys/errno.h>
51 51 #include <sys/stat.h>
52 52 #include <sys/types.h>
53 53 #include <sys/utsname.h> /* uname() */
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
54 54 #include <sys/wait.h>
55 55 #include <unistd.h> /* close() */
56 56
57 57 /*
58 58 * Defined macros
59 59 */
60 60 # define LOCALHOST "localhost"
61 61
62 62 #define MAXRULES 100
63 63
64 -#define SEND_MTOOL_MSG(cmds)
65 -
66 64 // Sleep for .1 seconds between stat()'s
67 65 const int STAT_RETRY_SLEEP_TIME = 100000;
68 66
69 67 /*
70 68 * typedefs & structs
71 69 */
72 70
73 71 /*
74 72 * Static variables
75 73 */
76 74 static char hostName[MAXNAMELEN] = "";
77 75 static char userName[MAXNAMELEN] = "";
78 76
79 77
80 78 static int second_pass = 0;
81 79
82 80 /*
83 81 * File table of contents
84 82 */
85 83 extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
86 84 extern Doname doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
87 85 static Boolean check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals);
88 86 void dynamic_dependencies(Name target);
89 87 static Doname run_command(register Property line, Boolean print_machine);
90 88 extern Doname execute_serial(Property line);
91 89 extern Name vpath_translation(register Name cmd);
92 90 extern void check_state(Name temp_file_name);
93 91 static void read_dependency_file(register Name filename);
94 92 static void check_read_state_file(void);
95 93 static void do_assign(register Name line, register Name target);
96 94 static void build_command_strings(Name target, register Property line);
97 95 static Doname touch_command(register Property line, register Name target, Doname result);
98 96 extern void update_target(Property line, Doname result);
99 97 static Doname sccs_get(register Name target, register Property *command);
100 98 extern void read_directory_of_file(register Name file);
101 99 static void add_pattern_conditionals(register Name target);
102 100 extern void set_locals(register Name target, register Property old_locals);
103 101 extern void reset_locals(register Name target, register Property old_locals, register Property conditional, register int index);
104 102 extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics);
105 103 static void delete_query_chain(Chain ch);
106 104
107 105 // From read2.cc
108 106 extern Name normalize_name(register wchar_t *name_string, register int length);
109 107
110 108
111 109
112 110 /*
113 111 * DONE.
114 112 *
115 113 * doname_check(target, do_get, implicit, automatic)
116 114 *
117 115 * Will call doname() and then inspect the return value
118 116 *
119 117 * Return value:
120 118 * Indication if the build failed or not
121 119 *
122 120 * Parameters:
123 121 * target The target to build
124 122 * do_get Passed thru to doname()
125 123 * implicit Passed thru to doname()
126 124 * automatic Are we building a hidden dependency?
127 125 *
128 126 * Global variables used:
129 127 * build_failed_seen Set if -k is on and error occurs
130 128 * continue_after_error Indicates that -k is on
131 129 * report_dependencies No error msg if -P is on
132 130 */
133 131 Doname
134 132 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
135 133 {
136 134 int first_time = 1;
137 135 (void) fflush(stdout);
138 136 try_again:
139 137 switch (doname(target, do_get, implicit, automatic)) {
140 138 case build_ok:
141 139 second_pass = 0;
142 140 return build_ok;
143 141 case build_running:
144 142 second_pass = 0;
145 143 return build_running;
146 144 case build_failed:
147 145 if (!continue_after_error) {
148 146 fatal(catgets(catd, 1, 13, "Target `%s' not remade because of errors"),
149 147 target->string_mb);
150 148 }
151 149 build_failed_seen = true;
152 150 second_pass = 0;
153 151 return build_failed;
154 152 case build_dont_know:
155 153 /*
156 154 * If we can't figure out how to build an automatic
157 155 * (hidden) dependency, we just ignore it.
158 156 * We later declare the target to be out of date just in
159 157 * case something changed.
160 158 * Also, don't complain if just reporting the dependencies
161 159 * and not building anything.
162 160 */
163 161 if (automatic || (report_dependencies_level > 0)) {
164 162 second_pass = 0;
165 163 return build_dont_know;
166 164 }
167 165 if(first_time) {
168 166 first_time = 0;
169 167 second_pass = 1;
170 168 goto try_again;
171 169 }
172 170 second_pass = 0;
173 171 if (continue_after_error && !svr4) {
174 172 warning(catgets(catd, 1, 14, "Don't know how to make target `%s'"),
175 173 target->string_mb);
176 174 build_failed_seen = true;
177 175 return build_failed;
178 176 }
179 177 fatal(catgets(catd, 1, 15, "Don't know how to make target `%s'"), target->string_mb);
180 178 break;
181 179 }
182 180 #ifdef lint
183 181 return build_failed;
184 182 #endif
185 183 }
186 184
187 185
188 186 void
189 187 enter_explicit_rule_from_dynamic_rule(Name target, Name source)
190 188 {
191 189 Property line, source_line;
192 190 Dependency dependency;
193 191
194 192 source_line = get_prop(source->prop, line_prop);
195 193 line = maybe_append_prop(target, line_prop);
196 194 line->body.line.sccs_command = false;
197 195 line->body.line.target = target;
198 196 if (line->body.line.command_template == NULL) {
199 197 line->body.line.command_template = source_line->body.line.command_template;
200 198 for (dependency = source_line->body.line.dependencies;
201 199 dependency != NULL;
202 200 dependency = dependency->next) {
203 201 enter_dependency(line, dependency->name, false);
204 202 }
205 203 line->body.line.less = target;
206 204 }
207 205 line->body.line.percent = NULL;
208 206 }
209 207
210 208
211 209
212 210 Name
213 211 find_dyntarget(Name target)
214 212 {
215 213 Dyntarget p;
216 214 int i;
217 215 String_rec string;
218 216 wchar_t buffer[STRING_BUFFER_LENGTH];
219 217 wchar_t *pp, * bufend;
220 218 wchar_t tbuffer[MAXPATHLEN];
221 219 Wstring wcb(target);
222 220
223 221 for (p = dyntarget_list; p != NULL; p = p->next) {
224 222 INIT_STRING_FROM_STACK(string, buffer);
225 223 expand_value(p->name, &string, false);
226 224 i = 0;
227 225 pp = string.buffer.start;
228 226 bufend = pp + STRING_BUFFER_LENGTH;
229 227 while((*pp != nul_char) && (pp < bufend)) {
230 228 if(iswspace(*pp)) {
231 229 tbuffer[i] = nul_char;
232 230 if(i > 0) {
233 231 if (wcb.equal(tbuffer)) {
234 232 enter_explicit_rule_from_dynamic_rule(target, p->name);
235 233 return(target);
236 234 }
237 235 }
238 236 pp++;
239 237 i = 0;
240 238 continue;
241 239 }
242 240 tbuffer[i] = *pp;
243 241 i++;
244 242 pp++;
245 243 if(*pp == nul_char) {
246 244 tbuffer[i] = nul_char;
247 245 if(i > 0) {
248 246 if (wcb.equal(tbuffer)) {
249 247 enter_explicit_rule_from_dynamic_rule(target, p->name);
250 248 return(target);
251 249 }
252 250 }
253 251 break;
254 252 }
255 253 }
256 254 }
257 255 return(NULL);
258 256 }
259 257
260 258 /*
261 259 * DONE.
262 260 *
263 261 * doname(target, do_get, implicit)
264 262 *
265 263 * Chases all files the target depends on and builds any that
266 264 * are out of date. If the target is out of date it is then rebuilt.
267 265 *
268 266 * Return value:
269 267 * Indiates if build failed or nt
270 268 *
271 269 * Parameters:
272 270 * target Target to build
273 271 * do_get Run sccs get is nessecary
274 272 * implicit doname is trying to find an implicit rule
275 273 *
276 274 * Global variables used:
277 275 * assign_done True if command line assgnment has happened
278 276 * commands_done Preserved for the case that we need local value
279 277 * debug_level Should we trace make's actions?
280 278 * default_rule The rule for ".DEFAULT", used as last resort
281 279 * empty_name The Name "", used when looking for single sfx
282 280 * keep_state Indicates that .KEEP_STATE is on
283 281 * parallel True if building in parallel
284 282 * recursion_level Used for tracing
285 283 * report_dependencies make -P is on
286 284 */
287 285 Doname
288 286 doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
289 287 {
290 288 Doname result = build_dont_know;
291 289 Chain out_of_date_list = NULL;
292 290 Chain target_group;
293 291 Property old_locals = NULL;
294 292 register Property line;
295 293 Property command = NULL;
296 294 register Dependency dependency;
297 295 Name less = NULL;
298 296 Name true_target = target;
299 297 Name *automatics = NULL;
300 298 register int auto_count;
301 299 Boolean rechecking_target = false;
302 300 Boolean saved_commands_done;
303 301 Boolean restart = false;
304 302 Boolean save_parallel = parallel;
305 303 Boolean doing_subtree = false;
306 304
307 305 Boolean recheck_conditionals = false;
308 306
309 307 if (target->state == build_running) {
310 308 return build_running;
311 309 }
312 310 line = get_prop(target->prop, line_prop);
313 311 if (line != NULL) {
314 312 /*
315 313 * If this target is a member of target group and one of the
316 314 * other members of the group is running, mark this target
317 315 * as running.
318 316 */
319 317 for (target_group = line->body.line.target_group;
320 318 target_group != NULL;
321 319 target_group = target_group->next) {
322 320 if (is_running(target_group->name)) {
323 321 target->state = build_running;
324 322 add_pending(target,
325 323 recursion_level,
326 324 do_get,
327 325 implicit,
328 326 false);
329 327 return build_running;
330 328 }
331 329 }
332 330 }
333 331 /*
334 332 * If the target is a constructed one for a "::" target,
335 333 * we need to consider that.
336 334 */
337 335 if (target->has_target_prop) {
338 336 true_target = get_prop(target->prop,
339 337 target_prop)->body.target.target;
340 338 if (true_target->colon_splits > 0) {
341 339 /* Make sure we have a valid time for :: targets */
342 340 Property time;
343 341
344 342 time = get_prop(true_target->prop, time_prop);
345 343 if (time != NULL) {
346 344 true_target->stat.time = time->body.time.time;
347 345 }
348 346 }
349 347 }
350 348 (void) exists(true_target);
351 349 /*
352 350 * If the target has been processed, we don't need to do it again,
353 351 * unless it depends on conditional macros or a delayed assignment,
354 352 * or it has been done when KEEP_STATE is on.
355 353 */
356 354 if (target->state == build_ok) {
357 355 if((!keep_state || (!target->depends_on_conditional && !assign_done))) {
358 356 return build_ok;
359 357 } else {
360 358 recheck_conditionals = true;
361 359 }
362 360 }
363 361 if (target->state == build_subtree) {
364 362 /* A dynamic macro subtree is being built */
365 363 target->state = build_dont_know;
366 364 doing_subtree = true;
367 365 if (!target->checking_subtree) {
368 366 /*
369 367 * This target has been started before and therefore
370 368 * not all dependencies have to be built.
371 369 */
372 370 restart = true;
373 371 }
374 372 } else if (target->state == build_pending) {
375 373 target->state = build_dont_know;
376 374 restart = true;
377 375 /*
378 376 } else if (parallel &&
379 377 keep_state &&
380 378 (target->conditional_cnt > 0)) {
381 379 if (!parallel_ok(target, false)) {
382 380 add_subtree(target, recursion_level, do_get, implicit);
383 381 target->state = build_running;
384 382 return build_running;
385 383 }
386 384 */
387 385 }
388 386 /*
389 387 * If KEEP_STATE is on, we have to rebuild the target if the
390 388 * building of it caused new automatic dependencies to be reported.
391 389 * This is where we restart the build.
392 390 */
393 391 if (line != NULL) {
394 392 line->body.line.percent = NULL;
395 393 }
396 394 recheck_target:
397 395 /* Init all local variables */
398 396 result = build_dont_know;
399 397 out_of_date_list = NULL;
400 398 command = NULL;
401 399 less = NULL;
402 400 auto_count = 0;
403 401 if (!restart && line != NULL) {
404 402 /*
405 403 * If this target has never been built before, mark all
406 404 * of the dependencies as never built.
407 405 */
408 406 for (dependency = line->body.line.dependencies;
409 407 dependency != NULL;
410 408 dependency = dependency->next) {
411 409 dependency->built = false;
412 410 }
413 411 }
414 412 /* Save the set of automatic depes defined for this target */
415 413 if (keep_state &&
416 414 (line != NULL) &&
417 415 (line->body.line.dependencies != NULL)) {
418 416 Name *p;
419 417
420 418 /*
421 419 * First run thru the dependency list to see how many
422 420 * autos there are.
423 421 */
424 422 for (dependency = line->body.line.dependencies;
425 423 dependency != NULL;
426 424 dependency = dependency->next) {
427 425 if (dependency->automatic && !dependency->stale) {
428 426 auto_count++;
429 427 }
430 428 }
431 429 /* Create vector to hold the current autos */
432 430 automatics =
433 431 (Name *) alloca((int) (auto_count * sizeof (Name)));
434 432 /* Copy them */
435 433 for (p = automatics, dependency = line->body.line.dependencies;
436 434 dependency != NULL;
437 435 dependency = dependency->next) {
438 436 if (dependency->automatic && !dependency->stale) {
439 437 *p++ = dependency->name;
440 438 }
441 439 }
442 440 }
443 441 if (debug_level > 1) {
444 442 (void) printf(NOCATGETS("%*sdoname(%s)\n"),
445 443 recursion_level,
446 444 "",
447 445 target->string_mb);
448 446 }
449 447 recursion_level++;
450 448 /* Avoid infinite loops */
451 449 if (target->state == build_in_progress) {
452 450 warning(catgets(catd, 1, 16, "Infinite loop: Target `%s' depends on itself"),
453 451 target->string_mb);
454 452 return build_ok;
455 453 }
456 454 target->state = build_in_progress;
457 455
458 456 /* Activate conditional macros for the target */
459 457 if (!target->added_pattern_conditionals) {
460 458 add_pattern_conditionals(target);
461 459 target->added_pattern_conditionals = true;
462 460 }
463 461 if (target->conditional_cnt > 0) {
464 462 old_locals = (Property) alloca(target->conditional_cnt *
465 463 sizeof (Property_rec));
466 464 set_locals(target, old_locals);
467 465 }
468 466
469 467 /*
470 468 * after making the call to dynamic_dependecies unconditional we can handle
471 469 * target names that are same as file name. In this case $$@ in the
472 470 * dependencies did not mean anything. WIth this change it expands it
473 471 * as expected.
474 472 */
475 473 if (!target->has_depe_list_expanded)
476 474 {
477 475 dynamic_dependencies(target);
478 476 }
479 477
480 478 /*
481 479 * FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT
482 480 * COMMANDS TO RUN
483 481 */
484 482 if ((line = get_prop(target->prop, line_prop)) != NULL) {
485 483 if (check_dependencies(&result,
486 484 line,
487 485 do_get,
488 486 target,
489 487 true_target,
490 488 doing_subtree,
491 489 &out_of_date_list,
492 490 old_locals,
493 491 implicit,
494 492 &command,
495 493 less,
496 494 rechecking_target,
497 495 recheck_conditionals)) {
498 496 return build_running;
499 497 }
500 498 if (line->body.line.query != NULL) {
501 499 delete_query_chain(line->body.line.query);
502 500 }
503 501 line->body.line.query = out_of_date_list;
504 502 }
505 503
506 504
507 505 /*
508 506 * If the target is a :: type, do not try to find the rule for the target,
509 507 * all actions will be taken by separate branches.
510 508 * Else, we try to find an implicit rule using various methods,
511 509 * we quit as soon as one is found.
512 510 *
513 511 * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target
514 512 * being rechecked - the target is being rechecked means that it already
515 513 * has explicit dependencies derived from an implicit rule found
516 514 * in previous step.
517 515 */
518 516 if (target->colon_splits == 0 && !rechecking_target) {
519 517 /* Look for percent matched rule */
520 518 if ((result == build_dont_know) &&
521 519 (command == NULL)) {
522 520 switch (find_percent_rule(
523 521 target,
524 522 &command,
525 523 recheck_conditionals)) {
526 524 case build_failed:
527 525 result = build_failed;
528 526 break;
529 527 case build_running:
530 528 target->state = build_running;
531 529 add_pending(target,
532 530 --recursion_level,
533 531 do_get,
534 532 implicit,
535 533 false);
536 534 if (target->conditional_cnt > 0) {
537 535 reset_locals(target,
538 536 old_locals,
539 537 get_prop(target->prop,
540 538 conditional_prop),
541 539 0);
542 540 }
543 541 return build_running;
544 542 case build_ok:
545 543 result = build_ok;
546 544 break;
547 545 }
548 546 }
549 547 /* Look for double suffix rule */
550 548 if (result == build_dont_know) {
551 549 Property member;
552 550
553 551 if (target->is_member &&
554 552 ((member = get_prop(target->prop, member_prop)) !=
555 553 NULL)) {
556 554 switch (find_ar_suffix_rule(target,
557 555 member->body.
558 556 member.member,
559 557 &command,
560 558 recheck_conditionals)) {
561 559 case build_failed:
562 560 result = build_failed;
563 561 break;
564 562 case build_running:
565 563 target->state = build_running;
566 564 add_pending(target,
567 565 --recursion_level,
568 566 do_get,
569 567 implicit,
570 568 false);
571 569 if (target->conditional_cnt > 0) {
572 570 reset_locals(target,
573 571 old_locals,
574 572 get_prop(target->prop,
575 573 conditional_prop),
576 574 0);
577 575 }
578 576 return build_running;
579 577 default:
580 578 /* ALWAYS bind $% for old style */
581 579 /* ar rules */
582 580 if (line == NULL) {
583 581 line =
584 582 maybe_append_prop(target,
585 583 line_prop);
586 584 }
587 585 line->body.line.percent =
588 586 member->body.member.member;
589 587 break;
590 588 }
591 589 } else {
592 590 switch (find_double_suffix_rule(target,
593 591 &command,
594 592 recheck_conditionals)) {
595 593 case build_failed:
596 594 result = build_failed;
597 595 break;
598 596 case build_running:
599 597 target->state = build_running;
600 598 add_pending(target,
601 599 --recursion_level,
602 600 do_get,
603 601 implicit,
604 602 false);
605 603 if (target->conditional_cnt > 0) {
606 604 reset_locals(target,
607 605 old_locals,
608 606 get_prop(target->
609 607 prop,
610 608 conditional_prop),
611 609 0);
612 610 }
613 611 return build_running;
614 612 }
615 613 }
616 614 }
617 615 /* Look for single suffix rule */
618 616
619 617 /* /tolik/
620 618 * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules.
621 619 * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc"
622 620 */
623 621 /* /tolik, 06.21.96/
624 622 * Regression! See BugId 1255360
625 623 * If more than one percent rules are defined for the same target then
626 624 * the behaviour of 'make' with my previous fix may be different from one
627 625 * of the 'old make'.
628 626 * The global variable second_pass (maybe it should be an argument to doname())
629 627 * is intended to avoid this regression. It is set in doname_check().
630 628 * First, 'make' will work as it worked before. Only when it is
631 629 * going to say "don't know how to make target" it sets second_pass to true and
632 630 * run 'doname' again but now trying to use Single Suffix Rules.
633 631 */
634 632 if ((result == build_dont_know) && !automatic && (!implicit || second_pass) &&
635 633 ((line == NULL) ||
636 634 ((line->body.line.target != NULL) &&
637 635 !line->body.line.target->has_regular_dependency))) {
638 636 switch (find_suffix_rule(target,
639 637 target,
640 638 empty_name,
641 639 &command,
642 640 recheck_conditionals)) {
643 641 case build_failed:
644 642 result = build_failed;
645 643 break;
646 644 case build_running:
647 645 target->state = build_running;
648 646 add_pending(target,
649 647 --recursion_level,
650 648 do_get,
651 649 implicit,
652 650 false);
653 651 if (target->conditional_cnt > 0) {
654 652 reset_locals(target,
655 653 old_locals,
656 654 get_prop(target->prop,
657 655 conditional_prop),
658 656 0);
659 657 }
660 658 return build_running;
661 659 }
662 660 }
663 661 /* Try to sccs get */
664 662 if ((command == NULL) &&
665 663 (result == build_dont_know) &&
666 664 do_get) {
667 665 result = sccs_get(target, &command);
668 666 }
669 667
670 668 /* Use .DEFAULT rule if it is defined. */
671 669 if ((command == NULL) &&
672 670 (result == build_dont_know) &&
673 671 (true_target->colons == no_colon) &&
674 672 default_rule &&
675 673 !implicit) {
676 674 /* Make sure we have a line prop */
677 675 line = maybe_append_prop(target, line_prop);
678 676 command = line;
679 677 Boolean out_of_date;
680 678 if (true_target->is_member) {
681 679 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
682 680 line->body.line.dependency_time);
683 681 } else {
684 682 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
685 683 line->body.line.dependency_time);
686 684 }
687 685 if (build_unconditional || out_of_date) {
688 686 line->body.line.is_out_of_date = true;
689 687 if (debug_level > 0) {
690 688 (void) printf(catgets(catd, 1, 17, "%*sBuilding %s using .DEFAULT because it is out of date\n"),
691 689 recursion_level,
692 690 "",
693 691 true_target->string_mb);
694 692 }
695 693 }
696 694 line->body.line.sccs_command = false;
697 695 line->body.line.command_template = default_rule;
698 696 line->body.line.target = true_target;
699 697 line->body.line.star = NULL;
700 698 line->body.line.less = true_target;
701 699 line->body.line.percent = NULL;
702 700 }
703 701 }
704 702
705 703 /* We say "target up to date" if no cmd were executed for the target */
706 704 if (!target->is_double_colon_parent) {
707 705 commands_done = false;
708 706 }
709 707
710 708 silent = silent_all;
711 709 ignore_errors = ignore_errors_all;
712 710 if (posix)
713 711 {
714 712 if (!silent)
715 713 {
716 714 silent = (Boolean) target->silent_mode;
717 715 }
718 716 if (!ignore_errors)
719 717 {
720 718 ignore_errors = (Boolean) target->ignore_error_mode;
721 719 }
722 720 }
723 721
724 722 int doname_dyntarget = 0;
725 723 r_command:
726 724 /* Run commands if any. */
727 725 if ((command != NULL) &&
728 726 (command->body.line.command_template != NULL)) {
729 727 if (result != build_failed) {
730 728 result = run_command(command,
731 729 (Boolean) ((parallel || save_parallel) && !silent));
732 730 }
733 731 switch (result) {
734 732 case build_running:
735 733 add_running(target,
736 734 true_target,
737 735 command,
738 736 --recursion_level,
739 737 auto_count,
740 738 automatics,
741 739 do_get,
742 740 implicit);
743 741 target->state = build_running;
744 742 if ((line = get_prop(target->prop,
745 743 line_prop)) != NULL) {
746 744 if (line->body.line.query != NULL) {
747 745 delete_query_chain(line->body.line.query);
748 746 }
749 747 line->body.line.query = NULL;
750 748 }
751 749 if (target->conditional_cnt > 0) {
752 750 reset_locals(target,
753 751 old_locals,
754 752 get_prop(target->prop,
755 753 conditional_prop),
756 754 0);
757 755 }
758 756 return build_running;
759 757 case build_serial:
760 758 add_serial(target,
761 759 --recursion_level,
762 760 do_get,
763 761 implicit);
764 762 target->state = build_running;
765 763 line = get_prop(target->prop, line_prop);
766 764 if (line != NULL) {
767 765 if (line->body.line.query != NULL) {
768 766 delete_query_chain(line->body.line.query);
769 767 }
770 768 line->body.line.query = NULL;
771 769 }
772 770 if (target->conditional_cnt > 0) {
773 771 reset_locals(target,
774 772 old_locals,
775 773 get_prop(target->prop,
776 774 conditional_prop),
777 775 0);
778 776 }
779 777 return build_running;
780 778 case build_ok:
781 779 /* If all went OK set a nice timestamp */
782 780 if (true_target->stat.time == file_doesnt_exist) {
783 781 true_target->stat.time = file_max_time;
784 782 }
785 783 break;
786 784 }
787 785 } else {
788 786 /*
789 787 * If no command was found for the target, and it doesn't
790 788 * exist, and it is mentioned as a target in the makefile,
791 789 * we say it is extremely new and that it is OK.
792 790 */
793 791 if (target->colons != no_colon) {
794 792 if (true_target->stat.time == file_doesnt_exist){
795 793 true_target->stat.time = file_max_time;
796 794 }
797 795 result = build_ok;
798 796 }
799 797 /*
800 798 * Trying dynamic targets.
801 799 */
802 800 if(!doname_dyntarget) {
803 801 doname_dyntarget = 1;
804 802 Name dtarg = find_dyntarget(target);
805 803 if(dtarg!=NULL) {
806 804 if (!target->has_depe_list_expanded) {
807 805 dynamic_dependencies(target);
808 806 }
809 807 if ((line = get_prop(target->prop, line_prop)) != NULL) {
810 808 if (check_dependencies(&result,
811 809 line,
812 810 do_get,
813 811 target,
814 812 true_target,
815 813 doing_subtree,
816 814 &out_of_date_list,
817 815 old_locals,
818 816 implicit,
819 817 &command,
820 818 less,
821 819 rechecking_target,
822 820 recheck_conditionals))
823 821 {
824 822 return build_running;
825 823 }
826 824 if (line->body.line.query != NULL) {
827 825 delete_query_chain(line->body.line.query);
828 826 }
829 827 line->body.line.query = out_of_date_list;
830 828 }
831 829 goto r_command;
832 830 }
833 831 }
834 832 /*
835 833 * If the file exists, it is OK that we couldnt figure
836 834 * out how to build it.
837 835 */
838 836 (void) exists(target);
839 837 if ((target->stat.time != file_doesnt_exist) &&
840 838 (result == build_dont_know)) {
841 839 result = build_ok;
842 840 }
843 841 }
844 842
845 843 /*
846 844 * Some of the following is duplicated in the function finish_doname.
847 845 * If anything is changed here, check to see if it needs to be
848 846 * changed there.
849 847 */
850 848 if ((line = get_prop(target->prop, line_prop)) != NULL) {
851 849 if (line->body.line.query != NULL) {
852 850 delete_query_chain(line->body.line.query);
853 851 }
854 852 line->body.line.query = NULL;
855 853 }
856 854 target->state = result;
857 855 parallel = save_parallel;
858 856 if (target->conditional_cnt > 0) {
859 857 reset_locals(target,
860 858 old_locals,
861 859 get_prop(target->prop, conditional_prop),
862 860 0);
863 861 }
864 862 recursion_level--;
865 863 if (target->is_member) {
866 864 Property member;
867 865
868 866 /* Propagate the timestamp from the member file to the member*/
869 867 if ((target->stat.time != file_max_time) &&
870 868 ((member = get_prop(target->prop, member_prop)) != NULL) &&
871 869 (exists(member->body.member.member) > file_doesnt_exist)) {
872 870 target->stat.time =
873 871 member->body.member.member->stat.time;
874 872 }
875 873 }
876 874 /*
877 875 * Check if we found any new auto dependencies when we
878 876 * built the target.
879 877 */
880 878 if ((result == build_ok) && check_auto_dependencies(target,
881 879 auto_count,
882 880 automatics)) {
883 881 if (debug_level > 0) {
884 882 (void) printf(catgets(catd, 1, 18, "%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
885 883 recursion_level,
886 884 "",
887 885 true_target->string_mb);
888 886 }
889 887 rechecking_target = true;
890 888 saved_commands_done = commands_done;
891 889 goto recheck_target;
892 890 }
893 891
894 892 if (rechecking_target && !commands_done) {
895 893 commands_done = saved_commands_done;
896 894 }
897 895
898 896 return result;
899 897 }
900 898
901 899 /*
902 900 * DONE.
903 901 *
904 902 * check_dependencies(result, line, do_get,
905 903 * target, true_target, doing_subtree, out_of_date_tail,
906 904 * old_locals, implicit, command, less, rechecking_target)
907 905 *
908 906 * Return value:
909 907 * True returned if some dependencies left running
910 908 *
911 909 * Parameters:
912 910 * result Pointer to cell we update if build failed
913 911 * line We get the dependencies from here
914 912 * do_get Allow use of sccs get in recursive doname()
915 913 * target The target to chase dependencies for
916 914 * true_target The real one for :: and lib(member)
917 915 * doing_subtree True if building a conditional macro subtree
918 916 * out_of_date_tail Used to set the $? list
919 917 * old_locals Used for resetting the local macros
920 918 * implicit Called when scanning for implicit rules?
921 919 * command Place to stuff command
922 920 * less Set to $< value
923 921 *
924 922 * Global variables used:
925 923 * command_changed Set if we suspect .make.state needs rewrite
926 924 * debug_level Should we trace actions?
927 925 * force The Name " FORCE", compared against
928 926 * recursion_level Used for tracing
929 927 * rewrite_statefile Set if .make.state needs rewriting
930 928 * wait_name The Name ".WAIT", compared against
931 929 */
932 930 static Boolean
933 931 check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals)
934 932 {
935 933 Boolean dependencies_running;
936 934 register Dependency dependency;
937 935 Doname dep_result;
938 936 Boolean dependency_changed = false;
939 937
940 938 line->body.line.dependency_time = file_doesnt_exist;
941 939 if (line->body.line.query != NULL) {
942 940 delete_query_chain(line->body.line.query);
943 941 }
944 942 line->body.line.query = NULL;
945 943 line->body.line.is_out_of_date = false;
946 944 dependencies_running = false;
947 945 /*
948 946 * Run thru all the dependencies and call doname() recursively
949 947 * on each of them.
950 948 */
951 949 for (dependency = line->body.line.dependencies;
952 950 dependency != NULL;
953 951 dependency = dependency->next) {
954 952 Boolean this_dependency_changed = false;
955 953
956 954 if (!dependency->automatic &&
957 955 (rechecking_target || target->rechecking_target)) {
958 956 /*
959 957 * We only bother with the autos when rechecking
960 958 */
961 959 continue;
962 960 }
963 961
964 962 if (dependency->name == wait_name) {
965 963 /*
966 964 * The special target .WAIT means finish all of
967 965 * the prior dependencies before continuing.
968 966 */
969 967 if (dependencies_running) {
970 968 break;
971 969 }
972 970 } else if ((!parallel_ok(dependency->name, false)) &&
973 971 (dependencies_running)) {
974 972 /*
975 973 * If we can't execute the current dependency in
976 974 * parallel, hold off the dependency processing
977 975 * to preserve the order of the dependencies.
978 976 */
979 977 break;
980 978 } else {
981 979 timestruc_t depe_time = file_doesnt_exist;
982 980
983 981
984 982 if (true_target->is_member) {
985 983 depe_time = exists(dependency->name);
986 984 }
987 985 if (dependency->built ||
988 986 (dependency->name->state == build_failed)) {
989 987 dep_result = (Doname) dependency->name->state;
990 988 } else {
991 989 dep_result = doname_check(dependency->name,
992 990 do_get,
993 991 false,
994 992 (Boolean) dependency->automatic);
995 993 }
996 994 if (true_target->is_member || dependency->name->is_member) {
997 995 /* should compare only secs, cause lib members does not have nsec time resolution */
998 996 if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
999 997 this_dependency_changed =
1000 998 dependency_changed =
1001 999 true;
1002 1000 }
1003 1001 } else {
1004 1002 if (depe_time != dependency->name->stat.time) {
1005 1003 this_dependency_changed =
1006 1004 dependency_changed =
1007 1005 true;
1008 1006 }
1009 1007 }
1010 1008 dependency->built = true;
1011 1009 switch (dep_result) {
1012 1010 case build_running:
1013 1011 dependencies_running = true;
1014 1012 continue;
1015 1013 case build_failed:
1016 1014 *result = build_failed;
1017 1015 break;
1018 1016 case build_dont_know:
1019 1017 /*
1020 1018 * If make can't figure out how to make a dependency, maybe the dependency
1021 1019 * is out of date. In this case, we just declare the target out of date
1022 1020 * and go on. If we really need the dependency, the make'ing of the target
1023 1021 * will fail. This will only happen for automatic (hidden) dependencies.
1024 1022 */
1025 1023 if(!recheck_conditionals) {
1026 1024 line->body.line.is_out_of_date = true;
1027 1025 }
1028 1026 /*
1029 1027 * Make sure the dependency is not saved
1030 1028 * in the state file.
1031 1029 */
1032 1030 dependency->stale = true;
1033 1031 rewrite_statefile =
1034 1032 command_changed =
1035 1033 true;
1036 1034 if (debug_level > 0) {
1037 1035 (void) printf(catgets(catd, 1, 19, "Target %s rebuilt because dependency %s does not exist\n"),
1038 1036 true_target->string_mb,
1039 1037 dependency->name->string_mb);
1040 1038 }
1041 1039 break;
1042 1040 }
1043 1041 if (dependency->name->depends_on_conditional) {
1044 1042 target->depends_on_conditional = true;
1045 1043 }
1046 1044 if (dependency->name == force) {
1047 1045 target->stat.time =
1048 1046 dependency->name->stat.time;
1049 1047 }
1050 1048 /*
1051 1049 * Propagate new timestamp from "member" to
1052 1050 * "lib.a(member)".
1053 1051 */
1054 1052 (void) exists(dependency->name);
1055 1053
1056 1054 /* Collect the timestamp of the youngest dependency */
1057 1055 line->body.line.dependency_time =
1058 1056 MAX(dependency->name->stat.time,
1059 1057 line->body.line.dependency_time);
1060 1058
1061 1059 /* Correction: do not consider nanosecs for members */
1062 1060 if(true_target->is_member || dependency->name->is_member) {
1063 1061 line->body.line.dependency_time.tv_nsec = 0;
1064 1062 }
1065 1063
1066 1064 if (debug_level > 1) {
1067 1065 (void) printf(catgets(catd, 1, 20, "%*sDate(%s)=%s \n"),
1068 1066 recursion_level,
1069 1067 "",
1070 1068 dependency->name->string_mb,
1071 1069 time_to_string(dependency->name->
1072 1070 stat.time));
1073 1071 if (dependency->name->stat.time > line->body.line.dependency_time) {
1074 1072 (void) printf(catgets(catd, 1, 21, "%*sDate-dependencies(%s) set to %s\n"),
1075 1073 recursion_level,
1076 1074 "",
1077 1075 true_target->string_mb,
1078 1076 time_to_string(line->body.line.
1079 1077 dependency_time));
1080 1078 }
1081 1079 }
1082 1080
1083 1081 /* Build the $? list */
1084 1082 if (true_target->is_member) {
1085 1083 if (this_dependency_changed == true) {
1086 1084 true_target->stat.time = dependency->name->stat.time;
1087 1085 true_target->stat.time.tv_sec--;
1088 1086 } else {
1089 1087 /* Dina:
1090 1088 * The next statement is commented
1091 1089 * out as a fix for bug #1051032.
1092 1090 * if dependency hasn't changed
1093 1091 * then there's no need to invalidate
1094 1092 * true_target. This statemnt causes
1095 1093 * make to take much longer to process
1096 1094 * an already-built archive. Soren
1097 1095 * said it was a quick fix for some
1098 1096 * problem he doesn't remember.
1099 1097 true_target->stat.time = file_no_time;
1100 1098 */
1101 1099 (void) exists(true_target);
1102 1100 }
1103 1101 } else {
1104 1102 (void) exists(true_target);
1105 1103 }
1106 1104 Boolean out_of_date;
1107 1105 if (true_target->is_member || dependency->name->is_member) {
1108 1106 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1109 1107 dependency->name->stat.time);
1110 1108 } else {
1111 1109 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1112 1110 dependency->name->stat.time);
1113 1111 }
1114 1112 if ((build_unconditional || out_of_date) &&
1115 1113 (dependency->name != force) &&
1116 1114 (dependency->stale == false)) {
1117 1115 *out_of_date_tail = ALLOC(Chain);
1118 1116 if (dependency->name->is_member &&
1119 1117 (get_prop(dependency->name->prop,
1120 1118 member_prop) != NULL)) {
1121 1119 (*out_of_date_tail)->name =
1122 1120 get_prop(dependency->name->prop,
1123 1121 member_prop)->
1124 1122 body.member.member;
1125 1123 } else {
1126 1124 (*out_of_date_tail)->name =
1127 1125 dependency->name;
1128 1126 }
1129 1127 (*out_of_date_tail)->next = NULL;
1130 1128 out_of_date_tail = &(*out_of_date_tail)->next;
1131 1129 if (debug_level > 0) {
1132 1130 if (dependency->name->stat.time == file_max_time) {
1133 1131 (void) printf(catgets(catd, 1, 22, "%*sBuilding %s because %s does not exist\n"),
1134 1132 recursion_level,
1135 1133 "",
1136 1134 true_target->string_mb,
1137 1135 dependency->name->string_mb);
1138 1136 } else {
1139 1137 (void) printf(catgets(catd, 1, 23, "%*sBuilding %s because it is out of date relative to %s\n"),
1140 1138 recursion_level,
1141 1139 "",
1142 1140 true_target->string_mb,
1143 1141 dependency->name->string_mb);
1144 1142 }
1145 1143 }
1146 1144 }
1147 1145 if (dependency->name == force) {
1148 1146 force->stat.time =
1149 1147 file_max_time;
1150 1148 force->state = build_dont_know;
1151 1149 }
1152 1150 }
1153 1151 }
1154 1152 if (dependencies_running) {
1155 1153 if (doing_subtree) {
1156 1154 if (target->conditional_cnt > 0) {
1157 1155 reset_locals(target,
1158 1156 old_locals,
1159 1157 get_prop(target->prop,
1160 1158 conditional_prop),
1161 1159 0);
1162 1160 }
1163 1161 return true;
1164 1162 } else {
1165 1163 target->state = build_running;
1166 1164 add_pending(target,
1167 1165 --recursion_level,
1168 1166 do_get,
1169 1167 implicit,
1170 1168 false);
1171 1169 if (target->conditional_cnt > 0) {
1172 1170 reset_locals(target,
1173 1171 old_locals,
1174 1172 get_prop(target->prop,
1175 1173 conditional_prop),
1176 1174 0);
1177 1175 }
1178 1176 return true;
1179 1177 }
1180 1178 }
1181 1179 /*
1182 1180 * Collect the timestamp of the youngest double colon target
1183 1181 * dependency.
1184 1182 */
1185 1183 if (target->is_double_colon_parent) {
1186 1184 for (dependency = line->body.line.dependencies;
1187 1185 dependency != NULL;
1188 1186 dependency = dependency->next) {
1189 1187 Property tmp_line;
1190 1188
1191 1189 if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1192 1190 if(tmp_line->body.line.dependency_time != file_max_time) {
1193 1191 target->stat.time =
1194 1192 MAX(tmp_line->body.line.dependency_time,
1195 1193 target->stat.time);
1196 1194 }
1197 1195 }
1198 1196 }
1199 1197 }
1200 1198 if ((true_target->is_member) && (dependency_changed == true)) {
1201 1199 true_target->stat.time = file_no_time;
1202 1200 }
1203 1201 /*
1204 1202 * After scanning all the dependencies, we check the rule
1205 1203 * if we found one.
1206 1204 */
1207 1205 if (line->body.line.command_template != NULL) {
1208 1206 if (line->body.line.command_template_redefined) {
1209 1207 warning(catgets(catd, 1, 24, "Too many rules defined for target %s"),
1210 1208 target->string_mb);
1211 1209 }
1212 1210 *command = line;
1213 1211 /* Check if the target is out of date */
1214 1212 Boolean out_of_date;
1215 1213 if (true_target->is_member) {
1216 1214 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1217 1215 line->body.line.dependency_time);
1218 1216 } else {
1219 1217 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1220 1218 line->body.line.dependency_time);
1221 1219 }
1222 1220 if (build_unconditional || out_of_date){
1223 1221 if(!recheck_conditionals) {
1224 1222 line->body.line.is_out_of_date = true;
1225 1223 }
1226 1224 }
1227 1225 line->body.line.sccs_command = false;
1228 1226 line->body.line.target = true_target;
1229 1227 if(gnu_style) {
1230 1228
1231 1229 // set $< for explicit rule
1232 1230 if(line->body.line.dependencies != NULL) {
1233 1231 less = line->body.line.dependencies->name;
1234 1232 }
1235 1233
1236 1234 // set $* for explicit rule
1237 1235 Name target_body;
1238 1236 Name tt = true_target;
1239 1237 Property member;
1240 1238 register wchar_t *target_end;
1241 1239 register Dependency suffix;
1242 1240 register int suffix_length;
1243 1241 Wstring targ_string;
1244 1242 Wstring suf_string;
1245 1243
1246 1244 if (true_target->is_member &&
1247 1245 ((member = get_prop(target->prop, member_prop)) !=
1248 1246 NULL)) {
1249 1247 tt = member->body.member.member;
1250 1248 }
1251 1249 targ_string.init(tt);
1252 1250 target_end = targ_string.get_string() + tt->hash.length;
1253 1251 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
1254 1252 suffix_length = suffix->name->hash.length;
1255 1253 suf_string.init(suffix->name);
1256 1254 if (tt->hash.length < suffix_length) {
1257 1255 continue;
1258 1256 } else if (!IS_WEQUALN(suf_string.get_string(),
1259 1257 (target_end - suffix_length),
1260 1258 suffix_length)) {
1261 1259 continue;
1262 1260 }
1263 1261 target_body = GETNAME(
1264 1262 targ_string.get_string(),
1265 1263 (int)(tt->hash.length - suffix_length)
1266 1264 );
1267 1265 line->body.line.star = target_body;
1268 1266 }
1269 1267
1270 1268 // set result = build_ok so that implicit rules are not used.
1271 1269 if(*result == build_dont_know) {
1272 1270 *result = build_ok;
1273 1271 }
1274 1272 }
1275 1273 if (less != NULL) {
1276 1274 line->body.line.less = less;
1277 1275 }
1278 1276 }
1279 1277
1280 1278 return false;
1281 1279 }
1282 1280
1283 1281 /*
1284 1282 * dynamic_dependencies(target)
1285 1283 *
1286 1284 * Checks if any dependency contains a macro ref
1287 1285 * If so, it replaces the dependency with the expanded version.
1288 1286 * Here, "$@" gets translated to target->string. That is
1289 1287 * the current name on the left of the colon in the
1290 1288 * makefile. Thus,
1291 1289 * xyz: s.$@.c
1292 1290 * translates into
1293 1291 * xyz: s.xyz.c
1294 1292 *
1295 1293 * Also, "$(@F)" translates to the same thing without a preceeding
1296 1294 * directory path (if one exists).
1297 1295 * Note, to enter "$@" on a dependency line in a makefile
1298 1296 * "$$@" must be typed. This is because make expands
1299 1297 * macros in dependency lists upon reading them.
1300 1298 * dynamic_dependencies() also expands file wildcards.
1301 1299 * If there are any Shell meta characters in the name,
1302 1300 * search the directory, and replace the dependency
1303 1301 * with the set of files the pattern matches
1304 1302 *
1305 1303 * Parameters:
1306 1304 * target Target to sanitize dependencies for
1307 1305 *
1308 1306 * Global variables used:
1309 1307 * c_at The Name "@", used to set macro value
1310 1308 * debug_level Should we trace actions?
1311 1309 * dot The Name ".", used to read directory
1312 1310 * recursion_level Used for tracing
1313 1311 */
1314 1312 void
1315 1313 dynamic_dependencies(Name target)
1316 1314 {
1317 1315 wchar_t pattern[MAXPATHLEN];
1318 1316 register wchar_t *p;
1319 1317 Property line;
1320 1318 register Dependency dependency;
1321 1319 register Dependency *remove;
1322 1320 String_rec string;
1323 1321 wchar_t buffer[MAXPATHLEN];
1324 1322 register Boolean set_at = false;
1325 1323 register wchar_t *start;
1326 1324 Dependency new_depe;
1327 1325 register Boolean reuse_cell;
1328 1326 Dependency first_member;
1329 1327 Name directory;
1330 1328 Name lib;
1331 1329 Name member;
1332 1330 Property prop;
1333 1331 Name true_target = target;
1334 1332 wchar_t *library;
1335 1333
1336 1334 if ((line = get_prop(target->prop, line_prop)) == NULL) {
1337 1335 return;
1338 1336 }
1339 1337 /* If the target is constructed from a "::" target we consider that */
1340 1338 if (target->has_target_prop) {
1341 1339 true_target = get_prop(target->prop,
1342 1340 target_prop)->body.target.target;
1343 1341 }
1344 1342 /* Scan all dependencies and process the ones that contain "$" chars */
1345 1343 for (dependency = line->body.line.dependencies;
1346 1344 dependency != NULL;
1347 1345 dependency = dependency->next) {
1348 1346 if (!dependency->name->dollar) {
1349 1347 continue;
1350 1348 }
1351 1349 target->has_depe_list_expanded = true;
1352 1350
1353 1351 /* The make macro $@ is bound to the target name once per */
1354 1352 /* invocation of dynamic_dependencies() */
1355 1353 if (!set_at) {
1356 1354 (void) SETVAR(c_at, true_target, false);
1357 1355 set_at = true;
1358 1356 }
1359 1357 /* Expand this dependency string */
1360 1358 INIT_STRING_FROM_STACK(string, buffer);
1361 1359 expand_value(dependency->name, &string, false);
1362 1360 /* Scan the expanded string. It could contain whitespace */
1363 1361 /* which mean it expands to several dependencies */
1364 1362 start = string.buffer.start;
1365 1363 while (iswspace(*start)) {
1366 1364 start++;
1367 1365 }
1368 1366 /* Remove the cell (later) if the macro was empty */
1369 1367 if (start[0] == (int) nul_char) {
1370 1368 dependency->name = NULL;
1371 1369 }
1372 1370
1373 1371 /* azv 10/26/95 to fix bug BID_1170218 */
1374 1372 if ((start[0] == (int) period_char) &&
1375 1373 (start[1] == (int) slash_char)) {
1376 1374 start += 2;
1377 1375 }
1378 1376 /* azv */
1379 1377
1380 1378 first_member = NULL;
1381 1379 /* We use the original dependency cell for the first */
1382 1380 /* dependency from the expansion */
1383 1381 reuse_cell = true;
1384 1382 /* We also have to deal with dependencies that expand to */
1385 1383 /* lib.a(members) notation */
1386 1384 for (p = start; *p != (int) nul_char; p++) {
1387 1385 if ((*p == (int) parenleft_char)) {
1388 1386 lib = GETNAME(start, p - start);
1389 1387 lib->is_member = true;
1390 1388 first_member = dependency;
1391 1389 start = p + 1;
1392 1390 while (iswspace(*start)) {
1393 1391 start++;
1394 1392 }
1395 1393 break;
1396 1394 }
1397 1395 }
1398 1396 do {
1399 1397 /* First skip whitespace */
1400 1398 for (p = start; *p != (int) nul_char; p++) {
1401 1399 if ((*p == (int) nul_char) ||
1402 1400 iswspace(*p) ||
1403 1401 (*p == (int) parenright_char)) {
1404 1402 break;
1405 1403 }
1406 1404 }
1407 1405 /* Enter dependency from expansion */
1408 1406 if (p != start) {
1409 1407 /* Create new dependency cell if */
1410 1408 /* this is not the first dependency */
1411 1409 /* picked from the expansion */
1412 1410 if (!reuse_cell) {
1413 1411 new_depe = ALLOC(Dependency);
1414 1412 new_depe->next = dependency->next;
1415 1413 new_depe->automatic = false;
1416 1414 new_depe->stale = false;
1417 1415 new_depe->built = false;
1418 1416 dependency->next = new_depe;
1419 1417 dependency = new_depe;
1420 1418 }
1421 1419 reuse_cell = false;
1422 1420 /* Internalize the dependency name */
1423 1421 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1424 1422 // include "//" and "/./"
1425 1423 //dependency->name = GETNAME(start, p - start);
1426 1424 dependency->name = normalize_name(start, p - start);
1427 1425 if ((debug_level > 0) &&
1428 1426 (first_member == NULL)) {
1429 1427 (void) printf(catgets(catd, 1, 25, "%*sDynamic dependency `%s' for target `%s'\n"),
1430 1428 recursion_level,
1431 1429 "",
1432 1430 dependency->name->string_mb,
1433 1431 true_target->string_mb);
1434 1432 }
1435 1433 for (start = p; iswspace(*start); start++);
1436 1434 p = start;
1437 1435 }
1438 1436 } while ((*p != (int) nul_char) &&
1439 1437 (*p != (int) parenright_char));
1440 1438 /* If the expansion was of lib.a(members) format we now */
1441 1439 /* enter the proper member cells */
1442 1440 if (first_member != NULL) {
1443 1441 /* Scan the new dependencies and transform them from */
1444 1442 /* "foo" to "lib.a(foo)" */
1445 1443 for (; 1; first_member = first_member->next) {
1446 1444 /* Build "lib.a(foo)" name */
1447 1445 INIT_STRING_FROM_STACK(string, buffer);
1448 1446 APPEND_NAME(lib,
1449 1447 &string,
1450 1448 (int) lib->hash.length);
1451 1449 append_char((int) parenleft_char, &string);
1452 1450 APPEND_NAME(first_member->name,
1453 1451 &string,
1454 1452 FIND_LENGTH);
1455 1453 append_char((int) parenright_char, &string);
1456 1454 member = first_member->name;
1457 1455 /* Replace "foo" with "lib.a(foo)" */
1458 1456 first_member->name =
1459 1457 GETNAME(string.buffer.start, FIND_LENGTH);
1460 1458 if (string.free_after_use) {
1461 1459 retmem(string.buffer.start);
1462 1460 }
1463 1461 if (debug_level > 0) {
1464 1462 (void) printf(catgets(catd, 1, 26, "%*sDynamic dependency `%s' for target `%s'\n"),
1465 1463 recursion_level,
1466 1464 "",
1467 1465 first_member->name->
1468 1466 string_mb,
1469 1467 true_target->string_mb);
1470 1468 }
1471 1469 first_member->name->is_member = lib->is_member;
1472 1470 /* Add member property to member */
1473 1471 prop = maybe_append_prop(first_member->name,
1474 1472 member_prop);
1475 1473 prop->body.member.library = lib;
1476 1474 prop->body.member.entry = NULL;
1477 1475 prop->body.member.member = member;
1478 1476 if (first_member == dependency) {
1479 1477 break;
1480 1478 }
1481 1479 }
1482 1480 }
1483 1481 }
1484 1482 Wstring wcb;
1485 1483 /* Then scan all the dependencies again. This time we want to expand */
1486 1484 /* shell file wildcards */
1487 1485 for (remove = &line->body.line.dependencies, dependency = *remove;
1488 1486 dependency != NULL;
1489 1487 dependency = *remove) {
1490 1488 if (dependency->name == NULL) {
1491 1489 dependency = *remove = (*remove)->next;
1492 1490 continue;
1493 1491 }
1494 1492 /* If dependency name string contains shell wildcards */
1495 1493 /* replace the name with the expansion */
1496 1494 if (dependency->name->wildcard) {
1497 1495 wcb.init(dependency->name);
1498 1496 if ((start = (wchar_t *) wschr(wcb.get_string(),
1499 1497 (int) parenleft_char)) != NULL) {
1500 1498 /* lib(*) type pattern */
1501 1499 library = buffer;
1502 1500 (void) wsncpy(buffer,
1503 1501 wcb.get_string(),
1504 1502 start - wcb.get_string());
1505 1503 buffer[start-wcb.get_string()] =
1506 1504 (int) nul_char;
1507 1505 (void) wsncpy(pattern,
1508 1506 start + 1,
1509 1507 (int) (dependency->name->hash.length-(start-wcb.get_string())-2));
1510 1508 pattern[dependency->name->hash.length -
1511 1509 (start-wcb.get_string()) - 2] =
1512 1510 (int) nul_char;
1513 1511 } else {
1514 1512 library = NULL;
1515 1513 (void) wsncpy(pattern,
1516 1514 wcb.get_string(),
1517 1515 (int) dependency->name->hash.length);
1518 1516 pattern[dependency->name->hash.length] =
1519 1517 (int) nul_char;
1520 1518 }
1521 1519 start = (wchar_t *) wsrchr(pattern, (int) slash_char);
1522 1520 if (start == NULL) {
1523 1521 directory = dot;
1524 1522 p = pattern;
1525 1523 } else {
1526 1524 directory = GETNAME(pattern, start-pattern);
1527 1525 p = start+1;
1528 1526 }
1529 1527 /* The expansion is handled by the read_dir() routine*/
1530 1528 if (read_dir(directory, p, line, library)) {
1531 1529 *remove = (*remove)->next;
1532 1530 } else {
1533 1531 remove = &dependency->next;
1534 1532 }
1535 1533 } else {
1536 1534 remove = &dependency->next;
1537 1535 }
1538 1536 }
1539 1537
1540 1538 /* Then unbind $@ */
1541 1539 (void) SETVAR(c_at, (Name) NULL, false);
1542 1540 }
1543 1541
1544 1542 /*
1545 1543 * DONE.
1546 1544 *
1547 1545 * run_command(line)
1548 1546 *
1549 1547 * Takes one Cmd_line and runs the commands from it.
1550 1548 *
1551 1549 * Return value:
1552 1550 * Indicates if the command failed or not
1553 1551 *
1554 1552 * Parameters:
1555 1553 * line The command line to run
1556 1554 *
1557 1555 * Global variables used:
1558 1556 * commands_done Set if we do run command
1559 1557 * current_line Set to the line we run a command from
1560 1558 * current_target Set to the target we run a command for
1561 1559 * file_number Used to form temp file name
1562 1560 * keep_state Indicates that .KEEP_STATE is on
1563 1561 * make_state The Name ".make.state", used to check timestamp
1564 1562 * parallel True if currently building in parallel
1565 1563 * parallel_process_cnt Count of parallel processes running
1566 1564 * quest Indicates that make -q is on
1567 1565 * rewrite_statefile Set if we do run a command
1568 1566 * sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value
1569 1567 * temp_file_directory Used to form temp fie name
1570 1568 * temp_file_name Set to the name of the temp file
1571 1569 * touch Indicates that make -t is on
1572 1570 */
1573 1571 static Doname
1574 1572 run_command(register Property line, Boolean)
1575 1573 {
1576 1574 register Doname result = build_ok;
1577 1575 register Boolean remember_only = false;
1578 1576 register Name target = line->body.line.target;
1579 1577 wchar_t *string;
1580 1578 char tmp_file_path[MAXPATHLEN];
1581 1579
1582 1580 if (!line->body.line.is_out_of_date && target->rechecking_target) {
1583 1581 target->rechecking_target = false;
1584 1582 return build_ok;
1585 1583 }
1586 1584
1587 1585 /*
1588 1586 * Build the command if we know the target is out of date,
1589 1587 * or if we want to check cmd consistency.
1590 1588 */
1591 1589 if (line->body.line.is_out_of_date || keep_state) {
1592 1590 /* Hack for handling conditional macros in DMake. */
1593 1591 if (!line->body.line.dont_rebuild_command_used) {
1594 1592 build_command_strings(target, line);
1595 1593 }
1596 1594 }
1597 1595 /* Never mind */
1598 1596 if (!line->body.line.is_out_of_date) {
1599 1597 return build_ok;
1600 1598 }
1601 1599 /* If quest, then exit(1) because the target is out of date */
1602 1600 if (quest) {
1603 1601 if (posix) {
1604 1602 result = execute_parallel(line, true);
1605 1603 }
1606 1604 exit_status = 1;
1607 1605 exit(1);
1608 1606 }
1609 1607 /* We actually had to do something this time */
1610 1608 rewrite_statefile = commands_done = true;
1611 1609 /*
1612 1610 * If this is an sccs command, we have to do some extra checking
1613 1611 * and possibly complain. If the file can't be gotten because it's
1614 1612 * checked out, we complain and behave as if the command was
1615 1613 * executed eventhough we ignored the command.
1616 1614 */
1617 1615 if (!touch &&
1618 1616 line->body.line.sccs_command &&
1619 1617 (target->stat.time != file_doesnt_exist) &&
1620 1618 ((target->stat.mode & 0222) != 0)) {
1621 1619 fatal(catgets(catd, 1, 27, "%s is writable so it cannot be sccs gotten"),
1622 1620 target->string_mb);
1623 1621 target->has_complained = remember_only = true;
1624 1622 }
1625 1623 /*
1626 1624 * If KEEP_STATE is on, we make sure we have the timestamp for
1627 1625 * .make.state. If .make.state changes during the command run,
1628 1626 * we reread .make.state after the command. We also setup the
1629 1627 * environment variable that asks utilities to report dependencies.
1630 1628 */
1631 1629 if (!touch &&
1632 1630 keep_state &&
1633 1631 !remember_only) {
1634 1632 (void) exists(make_state);
1635 1633 if((strlen(temp_file_directory) == 1) &&
1636 1634 (temp_file_directory[0] == '/')) {
1637 1635 tmp_file_path[0] = '\0';
1638 1636 } else {
1639 1637 strcpy(tmp_file_path, temp_file_directory);
1640 1638 }
1641 1639 sprintf(mbs_buffer,
1642 1640 NOCATGETS("%s/.make.dependency.%08x.%d.%d"),
1643 1641 tmp_file_path,
1644 1642 hostid,
1645 1643 getpid(),
1646 1644 file_number++);
1647 1645 MBSTOWCS(wcs_buffer, mbs_buffer);
1648 1646 Boolean fnd;
1649 1647 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1650 1648 temp_file_name->stat.is_file = true;
1651 1649 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1652 1650 wchar_t *to = string = ALLOC_WC(len);
1653 1651 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1654 1652 if (*from == (int) space_char) {
1655 1653 *to++ = (int) backslash_char;
1656 1654 }
1657 1655 *to++ = *from++;
1658 1656 }
1659 1657 *to++ = (int) space_char;
1660 1658 MBSTOWCS(to, target->string_mb);
1661 1659 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1662 1660 (void) SETVAR(sunpro_dependencies,
1663 1661 sprodep_name,
1664 1662 false);
1665 1663 retmem(string);
1666 1664 } else {
1667 1665 temp_file_name = NULL;
1668 1666 }
1669 1667
1670 1668 /*
1671 1669 * In case we are interrupted, we need to know what was going on.
1672 1670 */
1673 1671 current_target = target;
1674 1672 /*
1675 1673 * We also need to be able to save an empty command instead of the
1676 1674 * interrupted one in .make.state.
1677 1675 */
1678 1676 current_line = line;
1679 1677 if (remember_only) {
1680 1678 /* Empty block!!! */
1681 1679 } else if (touch) {
1682 1680 result = touch_command(line, target, result);
1683 1681 if (posix) {
1684 1682 result = execute_parallel(line, true);
1685 1683 }
1686 1684 } else {
1687 1685 /*
1688 1686 * If this is not a touch run, we need to execute the
1689 1687 * proper command(s) for the target.
1690 1688 */
1691 1689 if (parallel) {
1692 1690 if (!parallel_ok(target, true)) {
1693 1691 /*
1694 1692 * We are building in parallel, but
1695 1693 * this target must be built in serial.
1696 1694 */
1697 1695 /*
1698 1696 * If nothing else is building,
1699 1697 * do this one, else wait.
1700 1698 */
1701 1699 if (parallel_process_cnt == 0) {
1702 1700 result = execute_parallel(line, true, target->localhost);
1703 1701 } else {
1704 1702 current_target = NULL;
1705 1703 current_line = NULL;
1706 1704 /*
1707 1705 line->body.line.command_used = NULL;
1708 1706 */
1709 1707 line->body.line.dont_rebuild_command_used = true;
1710 1708 return build_serial;
1711 1709 }
1712 1710 } else {
1713 1711 result = execute_parallel(line, false);
1714 1712 switch (result) {
1715 1713 case build_running:
1716 1714 return build_running;
1717 1715 case build_serial:
1718 1716 if (parallel_process_cnt == 0) {
1719 1717 result = execute_parallel(line, true, target->localhost);
1720 1718 } else {
1721 1719 current_target = NULL;
1722 1720 current_line = NULL;
1723 1721 target->parallel = false;
1724 1722 line->body.line.command_used =
1725 1723 NULL;
1726 1724 return build_serial;
1727 1725 }
1728 1726 }
1729 1727 }
1730 1728 } else {
1731 1729 result = execute_parallel(line, true, target->localhost);
1732 1730 }
1733 1731 }
1734 1732 temp_file_name = NULL;
1735 1733 if (report_dependencies_level == 0){
1736 1734 update_target(line, result);
1737 1735 }
1738 1736 current_target = NULL;
1739 1737 current_line = NULL;
1740 1738 return result;
1741 1739 }
1742 1740
1743 1741 /*
1744 1742 * execute_serial(line)
1745 1743 *
1746 1744 * Runs thru the command line for the target and
1747 1745 * executes the rules one by one.
1748 1746 *
1749 1747 * Return value:
1750 1748 * The result of the command build
1751 1749 *
1752 1750 * Parameters:
1753 1751 * line The command to execute
1754 1752 *
1755 1753 * Static variables used:
1756 1754 *
1757 1755 * Global variables used:
1758 1756 * continue_after_error -k flag
1759 1757 * do_not_exec_rule -n flag
1760 1758 * report_dependencies -P flag
1761 1759 * silent Don't echo commands before executing
1762 1760 * temp_file_name Temp file for auto dependencies
1763 1761 * vpath_defined If true, translate path for command
1764 1762 */
1765 1763 Doname
↓ open down ↓ |
1690 lines elided |
↑ open up ↑ |
1766 1764 execute_serial(Property line)
1767 1765 {
1768 1766 int child_pid = 0;
1769 1767 Boolean printed_serial;
1770 1768 Doname result = build_ok;
1771 1769 Cmd_line rule, cmd_tail, command = NULL;
1772 1770 char mbstring[MAXPATHLEN];
1773 1771 int filed;
1774 1772 Name target = line->body.line.target;
1775 1773
1776 - SEND_MTOOL_MSG(
1777 - if (!sent_rsrc_info_msg) {
1778 - if (userName[0] == '\0') {
1779 - avo_get_user(userName, NULL);
1780 - }
1781 - if (hostName[0] == '\0') {
1782 - strcpy(hostName, avo_hostname());
1783 - }
1784 - send_rsrc_info_msg(1, hostName, userName);
1785 - sent_rsrc_info_msg = 1;
1786 - }
1787 - send_job_start_msg(line);
1788 - job_result_msg = new Avo_MToolJobResultMsg();
1789 - );
1790 -
1791 1774 target->has_recursive_dependency = false;
1792 1775 // We have to create a copy of the rules chain for processing because
1793 1776 // the original one can be destroyed during .make.state file rereading.
1794 1777 for (rule = line->body.line.command_used;
1795 1778 rule != NULL;
1796 1779 rule = rule->next) {
1797 1780 if (command == NULL) {
1798 1781 command = cmd_tail = ALLOC(Cmd_line);
1799 1782 } else {
1800 1783 cmd_tail->next = ALLOC(Cmd_line);
1801 1784 cmd_tail = cmd_tail->next;
1802 1785 }
1803 1786 *cmd_tail = *rule;
1804 1787 }
1805 1788 if (command) {
1806 1789 cmd_tail->next = NULL;
1807 1790 }
1808 1791 for (rule = command; rule != NULL; rule = rule->next) {
1809 1792 if (posix && (touch || quest) && !rule->always_exec) {
1810 1793 continue;
1811 1794 }
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1812 1795 if (vpath_defined) {
1813 1796 rule->command_line =
1814 1797 vpath_translation(rule->command_line);
1815 1798 }
1816 1799 /* Echo command line, maybe. */
1817 1800 if ((rule->command_line->hash.length > 0) &&
1818 1801 !silent &&
1819 1802 (!rule->silent || do_not_exec_rule) &&
1820 1803 (report_dependencies_level == 0)) {
1821 1804 (void) printf("%s\n", rule->command_line->string_mb);
1822 - SEND_MTOOL_MSG(
1823 - job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb));
1824 - );
1825 1805 }
1826 1806 if (rule->command_line->hash.length > 0) {
1827 - SEND_MTOOL_MSG(
1828 - (void) sprintf(mbstring,
1829 - NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"),
1830 - tmpdir,
1831 - getpid(),
1832 - file_number++);
1833 -
1834 - int tmp_fd = mkstemp(mbstring);
1835 - if(tmp_fd) {
1836 - (void) close(tmp_fd);
1837 - }
1838 -
1839 - stdout_file = strdup(mbstring);
1840 - stderr_file = NULL;
1841 - child_pid = pollResults(stdout_file,
1842 - (char *)NULL,
1843 - (char *)NULL);
1844 - );
1845 1807 /* Do assignment if command line prefixed with "=" */
1846 1808 if (rule->assign) {
1847 1809 result = build_ok;
1848 1810 do_assign(rule->command_line, target);
1849 1811 } else if (report_dependencies_level == 0) {
1850 1812 /* Execute command line. */
1851 1813 setvar_envvar();
1852 1814 result = dosys(rule->command_line,
1853 1815 (Boolean) rule->ignore_error,
1854 1816 (Boolean) rule->make_refd,
1855 1817 /* ds 98.04.23 bug #4085164. make should always show error messages */
1856 1818 false,
1857 1819 /* BOOLEAN(rule->silent &&
1858 1820 rule->ignore_error), */
1859 1821 (Boolean) rule->always_exec,
1860 - target,
1861 - send_mtool_msgs);
1822 + target);
1862 1823 check_state(temp_file_name);
1863 1824 }
1864 - SEND_MTOOL_MSG(
1865 - append_job_result_msg(job_result_msg);
1866 - if (child_pid > 0) {
1867 - kill(child_pid, SIGUSR1);
1868 - while (!((waitpid(child_pid, 0, 0) == -1)
1869 - && (errno == ECHILD)));
1870 - }
1871 - child_pid = 0;
1872 - (void) unlink(stdout_file);
1873 - retmem_mb(stdout_file);
1874 - stdout_file = NULL;
1875 - );
1876 1825 } else {
1877 1826 result = build_ok;
1878 1827 }
1879 1828 if (result == build_failed) {
1880 1829 if (silent || rule->silent) {
1881 1830 (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"),
1882 1831 rule->command_line->string_mb);
1883 - SEND_MTOOL_MSG(
1884 - job_result_msg->appendOutput(AVO_STRDUP(catgets(catd, 1, 243, "The following command caused the error:")));
1885 - job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb));
1886 - );
1887 1832 }
1888 1833 if (!rule->ignore_error && !ignore_errors) {
1889 1834 if (!continue_after_error) {
1890 - SEND_MTOOL_MSG(
1891 - job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
1892 - xdr_msg = (RWCollectable*)
1893 - job_result_msg;
1894 - xdr(&xdrs, xdr_msg);
1895 - (void) fflush(mtool_msgs_fp);
1896 - delete job_result_msg;
1897 - );
1898 1835 fatal(catgets(catd, 1, 244, "Command failed for target `%s'"),
1899 1836 target->string_mb);
1900 1837 }
1901 1838 /*
1902 1839 * Make sure a failing command is not
1903 1840 * saved in .make.state.
1904 1841 */
1905 1842 line->body.line.command_used = NULL;
1906 1843 break;
1907 1844 } else {
1908 1845 result = build_ok;
1909 1846 }
1910 1847 }
1911 1848 }
1912 1849 for (rule = command; rule != NULL; rule = cmd_tail) {
1913 1850 cmd_tail = rule->next;
1914 1851 free(rule);
1915 1852 }
1916 1853 command = NULL;
1917 - SEND_MTOOL_MSG(
1918 - job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
1919 - xdr_msg = (RWCollectable*) job_result_msg;
1920 - xdr(&xdrs, xdr_msg);
1921 - (void) fflush(mtool_msgs_fp);
1922 -
1923 - delete job_result_msg;
1924 - );
1925 1854 if (temp_file_name != NULL) {
1926 1855 free_name(temp_file_name);
1927 1856 }
1928 1857 temp_file_name = NULL;
1929 1858
1930 1859 Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
1931 1860 if(spro != NULL) {
1932 1861 Name val = spro->body.macro.value;
1933 1862 if(val != NULL) {
1934 1863 free_name(val);
1935 1864 spro->body.macro.value = NULL;
1936 1865 }
1937 1866 }
1938 1867 spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
1939 1868 if(spro) {
1940 1869 char *val = spro->body.env_mem.value;
1941 1870 if(val != NULL) {
1942 1871 /*
1943 1872 * Do not return memory allocated for SUNPRO_DEPENDENCIES
1944 1873 * It will be returned in setvar_daemon() in macro.cc
1945 1874 */
1946 1875 // retmem_mb(val);
1947 1876 spro->body.env_mem.value = NULL;
1948 1877 }
1949 1878 }
1950 1879
1951 1880 return result;
1952 1881 }
1953 1882
1954 1883
1955 1884
1956 1885 /*
1957 1886 * vpath_translation(cmd)
1958 1887 *
1959 1888 * Translates one command line by
1960 1889 * checking each word. If the word has an alias it is translated.
1961 1890 *
1962 1891 * Return value:
1963 1892 * The translated command
1964 1893 *
1965 1894 * Parameters:
1966 1895 * cmd Command to translate
1967 1896 *
1968 1897 * Global variables used:
1969 1898 */
1970 1899 Name
1971 1900 vpath_translation(register Name cmd)
1972 1901 {
1973 1902 wchar_t buffer[STRING_BUFFER_LENGTH];
1974 1903 String_rec new_cmd;
1975 1904 wchar_t *p;
1976 1905 wchar_t *start;
1977 1906
1978 1907 if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) {
1979 1908 return cmd;
1980 1909 }
1981 1910 INIT_STRING_FROM_STACK(new_cmd, buffer);
1982 1911
1983 1912 Wstring wcb(cmd);
1984 1913 p = wcb.get_string();
1985 1914
1986 1915 while (*p != (int) nul_char) {
1987 1916 while (iswspace(*p) && (*p != (int) nul_char)) {
1988 1917 append_char(*p++, &new_cmd);
1989 1918 }
1990 1919 start = p;
1991 1920 while (!iswspace(*p) && (*p != (int) nul_char)) {
1992 1921 p++;
1993 1922 }
1994 1923 cmd = GETNAME(start, p - start);
1995 1924 if (cmd->has_vpath_alias_prop) {
1996 1925 cmd = get_prop(cmd->prop, vpath_alias_prop)->
1997 1926 body.vpath_alias.alias;
1998 1927 APPEND_NAME(cmd,
1999 1928 &new_cmd,
2000 1929 (int) cmd->hash.length);
2001 1930 } else {
2002 1931 append_string(start, &new_cmd, p - start);
2003 1932 }
2004 1933 }
2005 1934 cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH);
2006 1935 if (new_cmd.free_after_use) {
2007 1936 retmem(new_cmd.buffer.start);
2008 1937 }
2009 1938 return cmd;
2010 1939 }
2011 1940
2012 1941 /*
2013 1942 * check_state(temp_file_name)
2014 1943 *
2015 1944 * Reads and checks the state changed by the previously executed command.
2016 1945 *
2017 1946 * Parameters:
2018 1947 * temp_file_name The auto dependency temp file
2019 1948 *
2020 1949 * Global variables used:
2021 1950 */
2022 1951 void
2023 1952 check_state(Name temp_file_name)
2024 1953 {
2025 1954 if (!keep_state) {
2026 1955 return;
2027 1956 }
2028 1957
2029 1958 /*
2030 1959 * Then read the temp file that now might
2031 1960 * contain dependency reports from utilities
2032 1961 */
2033 1962 read_dependency_file(temp_file_name);
2034 1963
2035 1964 /*
2036 1965 * And reread .make.state if it
2037 1966 * changed (the command ran recursive makes)
2038 1967 */
2039 1968 check_read_state_file();
2040 1969 if (temp_file_name != NULL) {
2041 1970 (void) unlink(temp_file_name->string_mb);
2042 1971 }
2043 1972 }
2044 1973
2045 1974 /*
2046 1975 * read_dependency_file(filename)
2047 1976 *
2048 1977 * Read the temp file used for reporting dependencies to make
2049 1978 *
2050 1979 * Parameters:
2051 1980 * filename The name of the file with the state info
2052 1981 *
2053 1982 * Global variables used:
2054 1983 * makefile_type The type of makefile being read
2055 1984 * read_trace_level Debug flag
2056 1985 * temp_file_number The always increasing number for unique files
2057 1986 * trace_reader Debug flag
2058 1987 */
2059 1988 static void
2060 1989 read_dependency_file(register Name filename)
2061 1990 {
2062 1991 register Makefile_type save_makefile_type;
2063 1992
2064 1993 if (filename == NULL) {
2065 1994 return;
2066 1995 }
2067 1996 filename->stat.time = file_no_time;
2068 1997 if (exists(filename) > file_doesnt_exist) {
2069 1998 save_makefile_type = makefile_type;
2070 1999 makefile_type = reading_cpp_file;
2071 2000 if (read_trace_level > 1) {
2072 2001 trace_reader = true;
2073 2002 }
2074 2003 temp_file_number++;
2075 2004 (void) read_simple_file(filename,
2076 2005 false,
2077 2006 false,
2078 2007 false,
2079 2008 false,
2080 2009 false,
2081 2010 false);
2082 2011 trace_reader = false;
2083 2012 makefile_type = save_makefile_type;
2084 2013 }
2085 2014 }
2086 2015
2087 2016 /*
2088 2017 * check_read_state_file()
2089 2018 *
2090 2019 * Check if .make.state has changed
2091 2020 * If it has we reread it
2092 2021 *
2093 2022 * Parameters:
2094 2023 *
2095 2024 * Global variables used:
2096 2025 * make_state Make state file name
2097 2026 * makefile_type Type of makefile being read
2098 2027 * read_trace_level Debug flag
2099 2028 * trace_reader Debug flag
2100 2029 */
2101 2030 static void
2102 2031 check_read_state_file(void)
2103 2032 {
2104 2033 timestruc_t previous = make_state->stat.time;
2105 2034 register Makefile_type save_makefile_type;
2106 2035 register Property makefile;
2107 2036
2108 2037 make_state->stat.time = file_no_time;
2109 2038 if ((exists(make_state) == file_doesnt_exist) ||
2110 2039 (make_state->stat.time == previous)) {
2111 2040 return;
2112 2041 }
2113 2042 save_makefile_type = makefile_type;
2114 2043 makefile_type = rereading_statefile;
2115 2044 /* Make sure we clear the old cached contents of .make.state */
2116 2045 makefile = maybe_append_prop(make_state, makefile_prop);
2117 2046 if (makefile->body.makefile.contents != NULL) {
2118 2047 retmem(makefile->body.makefile.contents);
2119 2048 makefile->body.makefile.contents = NULL;
2120 2049 }
2121 2050 if (read_trace_level > 1) {
2122 2051 trace_reader = true;
2123 2052 }
2124 2053 temp_file_number++;
2125 2054 (void) read_simple_file(make_state,
2126 2055 false,
2127 2056 false,
2128 2057 false,
2129 2058 false,
2130 2059 false,
2131 2060 true);
2132 2061 trace_reader = false;
2133 2062 makefile_type = save_makefile_type;
2134 2063 }
2135 2064
2136 2065 /*
2137 2066 * do_assign(line, target)
2138 2067 *
2139 2068 * Handles runtime assignments for command lines prefixed with "=".
2140 2069 *
2141 2070 * Parameters:
2142 2071 * line The command that contains an assignment
2143 2072 * target The Name of the target, used for error reports
2144 2073 *
2145 2074 * Global variables used:
2146 2075 * assign_done Set to indicate doname needs to reprocess
2147 2076 */
2148 2077 static void
2149 2078 do_assign(register Name line, register Name target)
2150 2079 {
2151 2080 Wstring wcb(line);
2152 2081 register wchar_t *string = wcb.get_string();
2153 2082 register wchar_t *equal;
2154 2083 register Name name;
2155 2084 register Boolean append = false;
2156 2085
2157 2086 /*
2158 2087 * If any runtime assignments are done, doname() must reprocess all
2159 2088 * targets in the future since the macro values used to build the
2160 2089 * command lines for the targets might have changed.
2161 2090 */
2162 2091 assign_done = true;
2163 2092 /* Skip white space. */
2164 2093 while (iswspace(*string)) {
2165 2094 string++;
2166 2095 }
2167 2096 equal = string;
2168 2097 /* Find "+=" or "=". */
2169 2098 while (!iswspace(*equal) &&
2170 2099 (*equal != (int) plus_char) &&
2171 2100 (*equal != (int) equal_char)) {
2172 2101 equal++;
2173 2102 }
2174 2103 /* Internalize macro name. */
2175 2104 name = GETNAME(string, equal - string);
2176 2105 /* Skip over "+=" "=". */
2177 2106 while (!((*equal == (int) nul_char) ||
2178 2107 (*equal == (int) equal_char) ||
2179 2108 (*equal == (int) plus_char))) {
2180 2109 equal++;
2181 2110 }
2182 2111 switch (*equal) {
2183 2112 case nul_char:
2184 2113 fatal(catgets(catd, 1, 31, "= expected in rule `%s' for target `%s'"),
2185 2114 line->string_mb,
2186 2115 target->string_mb);
2187 2116 case plus_char:
2188 2117 append = true;
2189 2118 equal++;
2190 2119 break;
2191 2120 }
2192 2121 equal++;
2193 2122 /* Skip over whitespace in front of value. */
2194 2123 while (iswspace(*equal)) {
2195 2124 equal++;
2196 2125 }
2197 2126 /* Enter new macro value. */
2198 2127 enter_equal(name,
2199 2128 GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2200 2129 append);
2201 2130 }
2202 2131
2203 2132 /*
2204 2133 * build_command_strings(target, line)
2205 2134 *
2206 2135 * Builds the command string to used when
2207 2136 * building a target. If the string is different from the previous one
2208 2137 * is_out_of_date is set.
2209 2138 *
2210 2139 * Parameters:
2211 2140 * target Target to build commands for
2212 2141 * line Where to stuff result
2213 2142 *
2214 2143 * Global variables used:
2215 2144 * c_at The Name "@", used to set macro value
2216 2145 * command_changed Set if command is different from old
2217 2146 * debug_level Should we trace activities?
2218 2147 * do_not_exec_rule Always echo when running -n
2219 2148 * empty_name The Name "", used for empty rule
2220 2149 * funny Semantics of characters
2221 2150 * ignore_errors Used to init field for line
2222 2151 * is_conditional Set to false befor evaling macro, checked
2223 2152 * after expanding macros
2224 2153 * keep_state Indicates that .KEEP_STATE is on
2225 2154 * make_word_mentioned Set by macro eval, inits field for cmd
2226 2155 * query The Name "?", used to set macro value
2227 2156 * query_mentioned Set by macro eval, inits field for cmd
2228 2157 * recursion_level Used for tracing
2229 2158 * silent Used to init field for line
2230 2159 */
2231 2160 static void
2232 2161 build_command_strings(Name target, register Property line)
2233 2162 {
2234 2163 String_rec command_line;
2235 2164 register Cmd_line command_template = line->body.line.command_template;
2236 2165 register Cmd_line *insert = &line->body.line.command_used;
2237 2166 register Cmd_line used = *insert;
2238 2167 wchar_t buffer[STRING_BUFFER_LENGTH];
2239 2168 wchar_t *start;
2240 2169 Name new_command_line;
2241 2170 register Boolean new_command_longer = false;
2242 2171 register Boolean ignore_all_command_dependency = true;
2243 2172 Property member;
2244 2173 static Name less_name;
2245 2174 static Name percent_name;
2246 2175 static Name star;
2247 2176 Name tmp_name;
2248 2177
2249 2178 if (less_name == NULL) {
2250 2179 MBSTOWCS(wcs_buffer, "<");
2251 2180 less_name = GETNAME(wcs_buffer, FIND_LENGTH);
2252 2181 MBSTOWCS(wcs_buffer, "%");
2253 2182 percent_name = GETNAME(wcs_buffer, FIND_LENGTH);
2254 2183 MBSTOWCS(wcs_buffer, "*");
2255 2184 star = GETNAME(wcs_buffer, FIND_LENGTH);
2256 2185 }
2257 2186
2258 2187 /* We have to check if a target depends on conditional macros */
2259 2188 /* Targets that do must be reprocessed by doname() each time around */
2260 2189 /* since the macro values used when building the target might have */
2261 2190 /* changed */
2262 2191 conditional_macro_used = false;
2263 2192 /* If we are building a lib.a(member) target $@ should be bound */
2264 2193 /* to lib.a */
2265 2194 if (target->is_member &&
2266 2195 ((member = get_prop(target->prop, member_prop)) != NULL)) {
2267 2196 target = member->body.member.library;
2268 2197 }
2269 2198 /* If we are building a "::" help target $@ should be bound to */
2270 2199 /* the real target name */
2271 2200 /* A lib.a(member) target is never :: */
2272 2201 if (target->has_target_prop) {
2273 2202 target = get_prop(target->prop, target_prop)->
2274 2203 body.target.target;
2275 2204 }
2276 2205 /* Bind the magic macros that make supplies */
2277 2206 tmp_name = target;
2278 2207 if(tmp_name != NULL) {
2279 2208 if (tmp_name->has_vpath_alias_prop) {
2280 2209 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2281 2210 body.vpath_alias.alias;
2282 2211 }
2283 2212 }
2284 2213 (void) SETVAR(c_at, tmp_name, false);
2285 2214
2286 2215 tmp_name = line->body.line.star;
2287 2216 if(tmp_name != NULL) {
2288 2217 if (tmp_name->has_vpath_alias_prop) {
2289 2218 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2290 2219 body.vpath_alias.alias;
2291 2220 }
2292 2221 }
2293 2222 (void) SETVAR(star, tmp_name, false);
2294 2223
2295 2224 tmp_name = line->body.line.less;
2296 2225 if(tmp_name != NULL) {
2297 2226 if (tmp_name->has_vpath_alias_prop) {
2298 2227 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2299 2228 body.vpath_alias.alias;
2300 2229 }
2301 2230 }
2302 2231 (void) SETVAR(less_name, tmp_name, false);
2303 2232
2304 2233 tmp_name = line->body.line.percent;
2305 2234 if(tmp_name != NULL) {
2306 2235 if (tmp_name->has_vpath_alias_prop) {
2307 2236 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2308 2237 body.vpath_alias.alias;
2309 2238 }
2310 2239 }
2311 2240 (void) SETVAR(percent_name, tmp_name, false);
2312 2241
2313 2242 /* $? is seldom used and it is expensive to build */
2314 2243 /* so we store the list form and build the string on demand */
2315 2244 Chain query_list = NULL;
2316 2245 Chain *query_list_tail = &query_list;
2317 2246
2318 2247 for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) {
2319 2248 *query_list_tail = ALLOC(Chain);
2320 2249 (*query_list_tail)->name = ch->name;
2321 2250 if ((*query_list_tail)->name->has_vpath_alias_prop) {
2322 2251 (*query_list_tail)->name =
2323 2252 get_prop((*query_list_tail)->name->prop,
2324 2253 vpath_alias_prop)->body.vpath_alias.alias;
2325 2254 }
2326 2255 (*query_list_tail)->next = NULL;
2327 2256 query_list_tail = &(*query_list_tail)->next;
2328 2257 }
2329 2258 (void) setvar_daemon(query,
2330 2259 (Name) query_list,
2331 2260 false,
2332 2261 chain_daemon,
2333 2262 false,
2334 2263 debug_level);
2335 2264
2336 2265 /* build $^ */
2337 2266 Chain hat_list = NULL;
2338 2267 Chain *hat_list_tail = &hat_list;
2339 2268
2340 2269 for (Dependency dependency = line->body.line.dependencies;
2341 2270 dependency != NULL;
2342 2271 dependency = dependency->next) {
2343 2272 /* skip automatic dependencies */
2344 2273 if (!dependency->automatic) {
2345 2274 if ((dependency->name != force) &&
2346 2275 (dependency->stale == false)) {
2347 2276 *hat_list_tail = ALLOC(Chain);
2348 2277
2349 2278 if (dependency->name->is_member &&
2350 2279 (get_prop(dependency->name->prop, member_prop) != NULL)) {
2351 2280 (*hat_list_tail)->name =
2352 2281 get_prop(dependency->name->prop,
2353 2282 member_prop)->body.member.member;
2354 2283 } else {
2355 2284 (*hat_list_tail)->name = dependency->name;
2356 2285 }
2357 2286
2358 2287 if((*hat_list_tail)->name != NULL) {
2359 2288 if ((*hat_list_tail)->name->has_vpath_alias_prop) {
2360 2289 (*hat_list_tail)->name =
2361 2290 get_prop((*hat_list_tail)->name->prop,
2362 2291 vpath_alias_prop)->body.vpath_alias.alias;
2363 2292 }
2364 2293 }
2365 2294
2366 2295 (*hat_list_tail)->next = NULL;
2367 2296 hat_list_tail = &(*hat_list_tail)->next;
2368 2297 }
2369 2298 }
2370 2299 }
2371 2300 (void) setvar_daemon(hat,
2372 2301 (Name) hat_list,
2373 2302 false,
2374 2303 chain_daemon,
2375 2304 false,
2376 2305 debug_level);
2377 2306
2378 2307 /* We have two command sequences we need to handle */
2379 2308 /* The old one that we probably read from .make.state */
2380 2309 /* and the new one we are building that will replace the old one */
2381 2310 /* Even when KEEP_STATE is not on we build a new command sequence and store */
2382 2311 /* it in the line prop. This command sequence is then executed by */
2383 2312 /* run_command(). If KEEP_STATE is on it is also later written to */
2384 2313 /* .make.state. The routine replaces the old command line by line with the */
2385 2314 /* new one trying to reuse Cmd_lines */
2386 2315
2387 2316 /* If there is no old command_used we have to start creating */
2388 2317 /* Cmd_lines to keep the new cmd in */
2389 2318 if (used == NULL) {
2390 2319 new_command_longer = true;
2391 2320 *insert = used = ALLOC(Cmd_line);
2392 2321 used->next = NULL;
2393 2322 used->command_line = NULL;
2394 2323 insert = &used->next;
2395 2324 }
2396 2325 /* Run thru the template for the new command and build the expanded */
2397 2326 /* new command lines */
2398 2327 for (;
2399 2328 command_template != NULL;
2400 2329 command_template = command_template->next, insert = &used->next, used = *insert) {
2401 2330 /* If there is no old command_used Cmd_line we need to */
2402 2331 /* create one and say that cmd consistency failed */
2403 2332 if (used == NULL) {
2404 2333 new_command_longer = true;
2405 2334 *insert = used = ALLOC(Cmd_line);
2406 2335 used->next = NULL;
2407 2336 used->command_line = empty_name;
2408 2337 }
2409 2338 /* Prepare the Cmd_line for the processing */
2410 2339 /* The command line prefixes "@-=?" are stripped and that */
2411 2340 /* information is saved in the Cmd_line */
2412 2341 used->assign = false;
2413 2342 used->ignore_error = ignore_errors;
2414 2343 used->silent = silent;
2415 2344 used->always_exec = false;
2416 2345 /* Expand the macros in the command line */
2417 2346 INIT_STRING_FROM_STACK(command_line, buffer);
2418 2347 make_word_mentioned =
2419 2348 query_mentioned =
2420 2349 false;
2421 2350 expand_value(command_template->command_line, &command_line, true);
2422 2351 /* If the macro $(MAKE) is mentioned in the command */
2423 2352 /* "make -n" runs actually execute the command */
2424 2353 used->make_refd = make_word_mentioned;
2425 2354 used->ignore_command_dependency = query_mentioned;
2426 2355 /* Strip the prefixes */
2427 2356 start = command_line.buffer.start;
2428 2357 for (;
2429 2358 iswspace(*start) ||
2430 2359 (get_char_semantics_value(*start) & (int) command_prefix_sem);
2431 2360 start++) {
2432 2361 switch (*start) {
2433 2362 case question_char:
2434 2363 used->ignore_command_dependency = true;
2435 2364 break;
2436 2365 case exclam_char:
2437 2366 used->ignore_command_dependency = false;
2438 2367 break;
2439 2368 case equal_char:
2440 2369 used->assign = true;
2441 2370 break;
2442 2371 case hyphen_char:
2443 2372 used->ignore_error = true;
2444 2373 break;
2445 2374 case at_char:
2446 2375 if (!do_not_exec_rule) {
2447 2376 used->silent = true;
2448 2377 }
2449 2378 break;
2450 2379 case plus_char:
2451 2380 if(posix) {
2452 2381 used->always_exec = true;
2453 2382 }
2454 2383 break;
2455 2384 }
2456 2385 }
2457 2386 /* If all command lines of the template are prefixed with "?"*/
2458 2387 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2459 2388 if (!used->ignore_command_dependency) {
2460 2389 ignore_all_command_dependency = false;
2461 2390 }
2462 2391 /* Internalize the expanded and stripped command line */
2463 2392 new_command_line = GETNAME(start, FIND_LENGTH);
2464 2393 if ((used->command_line == NULL) &&
2465 2394 (line->body.line.sccs_command)) {
2466 2395 used->command_line = new_command_line;
2467 2396 new_command_longer = false;
2468 2397 }
2469 2398 /* Compare it with the old one for command consistency */
2470 2399 if (used->command_line != new_command_line) {
2471 2400 Name vpath_translated = vpath_translation(new_command_line);
2472 2401 if (keep_state &&
2473 2402 !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2474 2403 if (debug_level > 0) {
2475 2404 if (used->command_line != NULL
2476 2405 && *used->command_line->string_mb !=
2477 2406 '\0') {
2478 2407 (void) printf(catgets(catd, 1, 32, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2479 2408 recursion_level,
2480 2409 "",
2481 2410 target->string_mb,
2482 2411 vpath_translated->string_mb,
2483 2412 recursion_level,
2484 2413 "",
2485 2414 used->
2486 2415 command_line->
2487 2416 string_mb);
2488 2417 } else {
2489 2418 (void) printf(catgets(catd, 1, 33, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2490 2419 recursion_level,
2491 2420 "",
2492 2421 target->string_mb,
2493 2422 vpath_translated->string_mb,
2494 2423 recursion_level,
2495 2424 "");
2496 2425 }
2497 2426 }
2498 2427 command_changed = true;
2499 2428 line->body.line.is_out_of_date = true;
2500 2429 }
2501 2430 used->command_line = new_command_line;
2502 2431 }
2503 2432 if (command_line.free_after_use) {
2504 2433 retmem(command_line.buffer.start);
2505 2434 }
2506 2435 }
2507 2436 /* Check if the old command is longer than the new for */
2508 2437 /* command consistency */
2509 2438 if (used != NULL) {
2510 2439 *insert = NULL;
2511 2440 if (keep_state &&
2512 2441 !ignore_all_command_dependency) {
2513 2442 if (debug_level > 0) {
2514 2443 (void) printf(catgets(catd, 1, 34, "%*sBuilding %s because new command shorter than old\n"),
2515 2444 recursion_level,
2516 2445 "",
2517 2446 target->string_mb);
2518 2447 }
2519 2448 command_changed = true;
2520 2449 line->body.line.is_out_of_date = true;
2521 2450 }
2522 2451 }
2523 2452 /* Check if the new command is longer than the old command for */
2524 2453 /* command consistency */
2525 2454 if (new_command_longer &&
2526 2455 !ignore_all_command_dependency &&
2527 2456 keep_state) {
2528 2457 if (debug_level > 0) {
2529 2458 (void) printf(catgets(catd, 1, 35, "%*sBuilding %s because new command longer than old\n"),
2530 2459 recursion_level,
2531 2460 "",
2532 2461 target->string_mb);
2533 2462 }
2534 2463 command_changed = true;
2535 2464 line->body.line.is_out_of_date = true;
2536 2465 }
2537 2466 /* Unbind the magic macros */
2538 2467 (void) SETVAR(c_at, (Name) NULL, false);
2539 2468 (void) SETVAR(star, (Name) NULL, false);
2540 2469 (void) SETVAR(less_name, (Name) NULL, false);
2541 2470 (void) SETVAR(percent_name, (Name) NULL, false);
2542 2471 (void) SETVAR(query, (Name) NULL, false);
2543 2472 if (query_list != NULL) {
2544 2473 delete_query_chain(query_list);
2545 2474 }
2546 2475 (void) SETVAR(hat, (Name) NULL, false);
2547 2476 if (hat_list != NULL) {
2548 2477 delete_query_chain(hat_list);
2549 2478 }
2550 2479
2551 2480 if (conditional_macro_used) {
2552 2481 target->conditional_macro_list = cond_macro_list;
2553 2482 cond_macro_list = NULL;
2554 2483 target->depends_on_conditional = true;
2555 2484 }
2556 2485 }
2557 2486
2558 2487 /*
2559 2488 * touch_command(line, target, result)
2560 2489 *
2561 2490 * If this is an "make -t" run we do this.
2562 2491 * We touch all targets in the target group ("foo + fie:") if any.
2563 2492 *
2564 2493 * Return value:
2565 2494 * Indicates if the command failed or not
2566 2495 *
2567 2496 * Parameters:
2568 2497 * line The command line to update
2569 2498 * target The target we are touching
2570 2499 * result Initial value for the result we return
2571 2500 *
2572 2501 * Global variables used:
2573 2502 * do_not_exec_rule Indicates that -n is on
2574 2503 * silent Do not echo commands
2575 2504 */
↓ open down ↓ |
641 lines elided |
↑ open up ↑ |
2576 2505 static Doname
2577 2506 touch_command(register Property line, register Name target, Doname result)
2578 2507 {
2579 2508 Name name;
2580 2509 register Chain target_group;
2581 2510 String_rec touch_string;
2582 2511 wchar_t buffer[MAXPATHLEN];
2583 2512 Name touch_cmd;
2584 2513 Cmd_line rule;
2585 2514
2586 -
2587 - SEND_MTOOL_MSG(
2588 - if (!sent_rsrc_info_msg) {
2589 - if (userName[0] == '\0') {
2590 - avo_get_user(userName, NULL);
2591 - }
2592 - if (hostName[0] == '\0') {
2593 - strcpy(hostName, avo_hostname());
2594 - }
2595 - send_rsrc_info_msg(1, hostName, userName);
2596 - sent_rsrc_info_msg = 1;
2597 - }
2598 - send_job_start_msg(line);
2599 - job_result_msg = new Avo_MToolJobResultMsg();
2600 - );
2601 2515 for (name = target, target_group = NULL; name != NULL;) {
2602 2516 if (!name->is_member) {
2603 2517 /*
2604 2518 * Build a touch command that can be passed
2605 2519 * to dosys(). If KEEP_STATE is on, "make -t"
2606 2520 * will save the proper command, not the
2607 2521 * "touch" in .make.state.
2608 2522 */
2609 2523 INIT_STRING_FROM_STACK(touch_string, buffer);
2610 2524 MBSTOWCS(wcs_buffer, NOCATGETS("touch "));
2611 2525 append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2612 2526 touch_cmd = name;
2613 2527 if (name->has_vpath_alias_prop) {
2614 2528 touch_cmd = get_prop(name->prop,
2615 2529 vpath_alias_prop)->
2616 2530 body.vpath_alias.alias;
2617 2531 }
2618 2532 APPEND_NAME(touch_cmd,
2619 2533 &touch_string,
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
2620 2534 FIND_LENGTH);
2621 2535 touch_cmd = GETNAME(touch_string.buffer.start,
2622 2536 FIND_LENGTH);
2623 2537 if (touch_string.free_after_use) {
2624 2538 retmem(touch_string.buffer.start);
2625 2539 }
2626 2540 if (!silent ||
2627 2541 do_not_exec_rule &&
2628 2542 (target_group == NULL)) {
2629 2543 (void) printf("%s\n", touch_cmd->string_mb);
2630 - SEND_MTOOL_MSG(
2631 - job_result_msg->appendOutput(AVO_STRDUP(touch_cmd->string_mb));
2632 - );
2633 2544 }
2634 2545 /* Run the touch command, or simulate it */
2635 2546 if (!do_not_exec_rule) {
2636 -
2637 - SEND_MTOOL_MSG(
2638 - (void) sprintf(mbstring,
2639 - NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"),
2640 - tmpdir,
2641 - getpid(),
2642 - file_number++);
2643 -
2644 - int tmp_fd = mkstemp(mbstring);
2645 - if(tmp_fd) {
2646 - (void) close(tmp_fd);
2647 - }
2648 -
2649 - stdout_file = strdup(mbstring);
2650 - stderr_file = NULL;
2651 - child_pid = pollResults(stdout_file,
2652 - (char *)NULL,
2653 - (char *)NULL);
2654 - );
2655 -
2656 2547 result = dosys(touch_cmd,
2657 2548 false,
2658 2549 false,
2659 2550 false,
2660 2551 false,
2661 - name,
2662 - send_mtool_msgs);
2663 -
2664 - SEND_MTOOL_MSG(
2665 - append_job_result_msg(job_result_msg);
2666 - if (child_pid > 0) {
2667 - kill(child_pid, SIGUSR1);
2668 - while (!((waitpid(child_pid, 0, 0) == -1)
2669 - && (errno == ECHILD)));
2670 - }
2671 - child_pid = 0;
2672 - (void) unlink(stdout_file);
2673 - retmem_mb(stdout_file);
2674 - stdout_file = NULL;
2675 - );
2676 -
2552 + name);
2677 2553 } else {
2678 2554 result = build_ok;
2679 2555 }
2680 2556 } else {
2681 2557 result = build_ok;
2682 2558 }
2683 2559 if (target_group == NULL) {
2684 2560 target_group = line->body.line.target_group;
2685 2561 } else {
2686 2562 target_group = target_group->next;
2687 2563 }
2688 2564 if (target_group != NULL) {
2689 2565 name = target_group->name;
2690 2566 } else {
2691 2567 name = NULL;
2692 2568 }
2693 2569 }
2694 - SEND_MTOOL_MSG(
2695 - job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
2696 - xdr_msg = (RWCollectable*) job_result_msg;
2697 - xdr(&xdrs, xdr_msg);
2698 - (void) fflush(mtool_msgs_fp);
2699 - delete job_result_msg;
2700 - );
2701 2570 return result;
2702 2571 }
2703 2572
2704 2573 /*
2705 2574 * update_target(line, result)
2706 2575 *
2707 2576 * updates the status of a target after executing its commands.
2708 2577 *
2709 2578 * Parameters:
2710 2579 * line The command line block to update
2711 2580 * result Indicates that build is OK so can update
2712 2581 *
2713 2582 * Global variables used:
2714 2583 * do_not_exec_rule Indicates that -n is on
2715 2584 * touch Fake the new timestamp if we are just touching
2716 2585 */
2717 2586 void
2718 2587 update_target(Property line, Doname result)
2719 2588 {
2720 2589 Name target;
2721 2590 Chain target_group;
2722 2591 Property line2;
2723 2592 timestruc_t old_stat_time;
2724 2593 Property member;
2725 2594
2726 2595 /*
2727 2596 * [tolik] Additional fix for bug 1063790. It was fixed
2728 2597 * for serial make long ago, but DMake dumps core when
2729 2598 * target is a symlink and sccs file is newer then target.
2730 2599 * In this case, finish_children() calls update_target()
2731 2600 * with line==NULL.
2732 2601 */
2733 2602 if(line == NULL) {
2734 2603 /* XXX. Should we do anything here? */
2735 2604 return;
2736 2605 }
2737 2606
2738 2607 target = line->body.line.target;
2739 2608
2740 2609 if ((result == build_ok) && (line->body.line.command_used != NULL)) {
2741 2610 if (do_not_exec_rule ||
2742 2611 touch ||
2743 2612 (target->is_member &&
2744 2613 (line->body.line.command_template != NULL) &&
2745 2614 (line->body.line.command_template->command_line->string_mb[0] == 0) &&
2746 2615 (line->body.line.command_template->next == NULL))) {
2747 2616 /* If we are simulating execution we need to fake a */
2748 2617 /* new timestamp for the target we didnt build */
2749 2618 target->stat.time = file_max_time;
2750 2619 } else {
2751 2620 /*
2752 2621 * If we really built the target we read the new
2753 2622 * timestamp.
2754 2623 * Fix for bug #1110906: if .c file is newer than
2755 2624 * the corresponding .o file which is in an archive
2756 2625 * file, make will compile the .c file but it won't
2757 2626 * update the object in the .a file.
2758 2627 */
2759 2628 old_stat_time = target->stat.time;
2760 2629 target->stat.time = file_no_time;
2761 2630 (void) exists(target);
2762 2631 if ((target->is_member) &&
2763 2632 (target->stat.time == old_stat_time)) {
2764 2633 member = get_prop(target->prop, member_prop);
2765 2634 if (member != NULL) {
2766 2635 target->stat.time = member->body.member.library->stat.time;
2767 2636 target->stat.time.tv_sec++;
2768 2637 }
2769 2638 }
2770 2639 }
2771 2640 /* If the target is part of a group we need to propagate the */
2772 2641 /* result of the run to all members */
2773 2642 for (target_group = line->body.line.target_group;
2774 2643 target_group != NULL;
2775 2644 target_group = target_group->next) {
2776 2645 target_group->name->stat.time = target->stat.time;
2777 2646 line2 = maybe_append_prop(target_group->name,
2778 2647 line_prop);
2779 2648 line2->body.line.command_used =
2780 2649 line->body.line.command_used;
2781 2650 line2->body.line.target = target_group->name;
2782 2651 }
2783 2652 }
2784 2653 target->has_built = true;
2785 2654 }
2786 2655
2787 2656 /*
2788 2657 * sccs_get(target, command)
2789 2658 *
2790 2659 * Figures out if it possible to sccs get a file
2791 2660 * and builds the command to do it if it is.
2792 2661 *
2793 2662 * Return value:
2794 2663 * Indicates if sccs get failed or not
2795 2664 *
2796 2665 * Parameters:
2797 2666 * target Target to get
2798 2667 * command Where to deposit command to use
2799 2668 *
2800 2669 * Global variables used:
2801 2670 * debug_level Should we trace activities?
2802 2671 * recursion_level Used for tracing
2803 2672 * sccs_get_rule The rule to used for sccs getting
2804 2673 */
2805 2674 static Doname
2806 2675 sccs_get(register Name target, register Property *command)
2807 2676 {
2808 2677 register int result;
2809 2678 char link[MAXPATHLEN];
2810 2679 String_rec string;
2811 2680 wchar_t name[MAXPATHLEN];
2812 2681 register wchar_t *p;
2813 2682 timestruc_t sccs_time;
2814 2683 register Property line;
2815 2684 int sym_link_depth = 0;
2816 2685
2817 2686 /* For sccs, we need to chase symlinks. */
2818 2687 while (target->stat.is_sym_link) {
2819 2688 if (sym_link_depth++ > 90) {
2820 2689 fatal(catgets(catd, 1, 95, "Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2821 2690 target->string_mb);
2822 2691 }
2823 2692 /* Read the value of the link. */
2824 2693 result = readlink_vroot(target->string_mb,
2825 2694 link,
2826 2695 sizeof(link),
2827 2696 NULL,
2828 2697 VROOT_DEFAULT);
2829 2698 if (result == -1) {
2830 2699 fatal(catgets(catd, 1, 36, "Can't read symbolic link `%s': %s"),
2831 2700 target->string_mb, errmsg(errno));
2832 2701 }
2833 2702 link[result] = 0;
2834 2703 /* Use the value to build the proper filename. */
2835 2704 INIT_STRING_FROM_STACK(string, name);
2836 2705
2837 2706 Wstring wcb(target);
2838 2707 if ((link[0] != slash_char) &&
2839 2708 ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) {
2840 2709 append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2841 2710 }
2842 2711 append_string(link, &string, result);
2843 2712 /* Replace the old name with the translated name. */
2844 2713 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2845 2714 (void) exists(target);
2846 2715 if (string.free_after_use) {
2847 2716 retmem(string.buffer.start);
2848 2717 }
2849 2718 }
2850 2719
2851 2720 /*
2852 2721 * read_dir() also reads the ?/SCCS dir and saves information
2853 2722 * about which files have SCSC/s. files.
2854 2723 */
2855 2724 if (target->stat.has_sccs == DONT_KNOW_SCCS) {
2856 2725 read_directory_of_file(target);
2857 2726 }
2858 2727 switch (target->stat.has_sccs) {
2859 2728 case DONT_KNOW_SCCS:
2860 2729 /* We dont know by now there is no SCCS/s.* */
2861 2730 target->stat.has_sccs = NO_SCCS;
2862 2731 case NO_SCCS:
2863 2732 /*
2864 2733 * If there is no SCCS/s.* but the plain file exists,
2865 2734 * we say things are OK.
2866 2735 */
2867 2736 if (target->stat.time > file_doesnt_exist) {
2868 2737 return build_ok;
2869 2738 }
2870 2739 /* If we cant find the plain file, we give up. */
2871 2740 return build_dont_know;
2872 2741 case HAS_SCCS:
2873 2742 /*
2874 2743 * Pay dirt. We now need to figure out if the plain file
2875 2744 * is out of date relative to the SCCS/s.* file.
2876 2745 */
2877 2746 sccs_time = exists(get_prop(target->prop,
2878 2747 sccs_prop)->body.sccs.file);
2879 2748 break;
2880 2749 }
2881 2750
2882 2751 if ((!target->has_complained &&
2883 2752 (sccs_time != file_doesnt_exist) &&
2884 2753 (sccs_get_rule != NULL))) {
2885 2754 /* only checking */
2886 2755 if (command == NULL) {
2887 2756 return build_ok;
2888 2757 }
2889 2758 /*
2890 2759 * We provide a command line for the target. The line is a
2891 2760 * "sccs get" command from default.mk.
2892 2761 */
2893 2762 line = maybe_append_prop(target, line_prop);
2894 2763 *command = line;
2895 2764 if (sccs_time > target->stat.time) {
2896 2765 /*
2897 2766 * And only if the plain file is out of date do we
2898 2767 * request execution of the command.
2899 2768 */
2900 2769 line->body.line.is_out_of_date = true;
2901 2770 if (debug_level > 0) {
2902 2771 (void) printf(catgets(catd, 1, 37, "%*sSccs getting %s because s. file is younger than source file\n"),
2903 2772 recursion_level,
2904 2773 "",
2905 2774 target->string_mb);
2906 2775 }
2907 2776 }
2908 2777 line->body.line.sccs_command = true;
2909 2778 line->body.line.command_template = sccs_get_rule;
2910 2779 if(!svr4 && (!allrules_read || posix)) {
2911 2780 if((target->prop) &&
2912 2781 (target->prop->body.sccs.file) &&
2913 2782 (target->prop->body.sccs.file->string_mb)) {
2914 2783 if((strlen(target->prop->body.sccs.file->string_mb) ==
2915 2784 strlen(target->string_mb) + 2) &&
2916 2785 (target->prop->body.sccs.file->string_mb[0] == 's') &&
2917 2786 (target->prop->body.sccs.file->string_mb[1] == '.')) {
2918 2787
2919 2788 line->body.line.command_template = get_posix_rule;
2920 2789 }
2921 2790 }
2922 2791 }
2923 2792 line->body.line.target = target;
2924 2793 /*
2925 2794 * Also make sure the rule is build with $* and $<
2926 2795 * bound properly.
2927 2796 */
2928 2797 line->body.line.star = NULL;
2929 2798 line->body.line.less = NULL;
2930 2799 line->body.line.percent = NULL;
2931 2800 return build_ok;
2932 2801 }
2933 2802 return build_dont_know;
2934 2803 }
2935 2804
2936 2805 /*
2937 2806 * read_directory_of_file(file)
2938 2807 *
2939 2808 * Reads the directory the specified file lives in.
2940 2809 *
2941 2810 * Parameters:
2942 2811 * file The file we need to read dir for
2943 2812 *
2944 2813 * Global variables used:
2945 2814 * dot The Name ".", used as the default dir
2946 2815 */
2947 2816 void
2948 2817 read_directory_of_file(register Name file)
2949 2818 {
2950 2819
2951 2820 Wstring file_string(file);
2952 2821 wchar_t * wcb = file_string.get_string();
2953 2822 wchar_t usr_include_buf[MAXPATHLEN];
2954 2823 wchar_t usr_include_sys_buf[MAXPATHLEN];
2955 2824
2956 2825 register Name directory = dot;
2957 2826 register wchar_t *p = (wchar_t *) wsrchr(wcb,
2958 2827 (int) slash_char);
2959 2828 register int length = p - wcb;
2960 2829 static Name usr_include;
2961 2830 static Name usr_include_sys;
2962 2831
2963 2832 if (usr_include == NULL) {
2964 2833 MBSTOWCS(usr_include_buf, NOCATGETS("/usr/include"));
2965 2834 usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
2966 2835 MBSTOWCS(usr_include_sys_buf, NOCATGETS("/usr/include/sys"));
2967 2836 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
2968 2837 }
2969 2838
2970 2839 /*
2971 2840 * If the filename contains a "/" we have to extract the path
2972 2841 * Else the path defaults to ".".
2973 2842 */
2974 2843 if (p != NULL) {
2975 2844 /*
2976 2845 * Check some popular directories first to possibly
2977 2846 * save time. Compare string length first to gain speed.
2978 2847 */
2979 2848 if ((usr_include->hash.length == length) &&
2980 2849 IS_WEQUALN(usr_include_buf,
2981 2850 wcb,
2982 2851 length)) {
2983 2852 directory = usr_include;
2984 2853 } else if ((usr_include_sys->hash.length == length) &&
2985 2854 IS_WEQUALN(usr_include_sys_buf,
2986 2855 wcb,
2987 2856 length)) {
2988 2857 directory = usr_include_sys;
2989 2858 } else {
2990 2859 directory = GETNAME(wcb, length);
2991 2860 }
2992 2861 }
2993 2862 (void) read_dir(directory,
2994 2863 (wchar_t *) NULL,
2995 2864 (Property) NULL,
2996 2865 (wchar_t *) NULL);
2997 2866 }
2998 2867
2999 2868 /*
3000 2869 * add_pattern_conditionals(target)
3001 2870 *
3002 2871 * Scan the list of conditionals defined for pattern targets and add any
3003 2872 * that match this target to its list of conditionals.
3004 2873 *
3005 2874 * Parameters:
3006 2875 * target The target we should add conditionals for
3007 2876 *
3008 2877 * Global variables used:
3009 2878 * conditionals The list of pattern conditionals
3010 2879 */
3011 2880 static void
3012 2881 add_pattern_conditionals(register Name target)
3013 2882 {
3014 2883 register Property conditional;
3015 2884 Property new_prop;
3016 2885 Property *previous;
3017 2886 Name_rec dummy;
3018 2887 wchar_t *pattern;
3019 2888 wchar_t *percent;
3020 2889 int length;
3021 2890
3022 2891 Wstring wcb(target);
3023 2892 Wstring wcb1;
3024 2893
3025 2894 for (conditional = get_prop(conditionals->prop, conditional_prop);
3026 2895 conditional != NULL;
3027 2896 conditional = get_prop(conditional->next, conditional_prop)) {
3028 2897 wcb1.init(conditional->body.conditional.target);
3029 2898 pattern = wcb1.get_string();
3030 2899 if (pattern[1] != 0) {
3031 2900 percent = (wchar_t *) wschr(pattern, (int) percent_char);
3032 2901 if (!wcb.equaln(pattern, percent-pattern) ||
3033 2902 !IS_WEQUAL(wcb.get_string(wcb.length()-wslen(percent+1)), percent+1)) {
3034 2903 continue;
3035 2904 }
3036 2905 }
3037 2906 for (previous = &target->prop;
3038 2907 *previous != NULL;
3039 2908 previous = &(*previous)->next) {
3040 2909 if (((*previous)->type == conditional_prop) &&
3041 2910 ((*previous)->body.conditional.sequence >
3042 2911 conditional->body.conditional.sequence)) {
3043 2912 break;
3044 2913 }
3045 2914 }
3046 2915 if (*previous == NULL) {
3047 2916 new_prop = append_prop(target, conditional_prop);
3048 2917 } else {
3049 2918 dummy.prop = NULL;
3050 2919 new_prop = append_prop(&dummy, conditional_prop);
3051 2920 new_prop->next = *previous;
3052 2921 *previous = new_prop;
3053 2922 }
3054 2923 target->conditional_cnt++;
3055 2924 new_prop->body.conditional = conditional->body.conditional;
3056 2925 }
3057 2926 }
3058 2927
3059 2928 /*
3060 2929 * set_locals(target, old_locals)
3061 2930 *
3062 2931 * Sets any conditional macros for the target.
3063 2932 * Each target carries a possibly empty set of conditional properties.
3064 2933 *
3065 2934 * Parameters:
3066 2935 * target The target to set conditional macros for
3067 2936 * old_locals Space to store old values in
3068 2937 *
3069 2938 * Global variables used:
3070 2939 * debug_level Should we trace activity?
3071 2940 * is_conditional We need to preserve this value
3072 2941 * recursion_level Used for tracing
3073 2942 */
3074 2943 void
3075 2944 set_locals(register Name target, register Property old_locals)
3076 2945 {
3077 2946 register Property conditional;
3078 2947 register int i;
3079 2948 register Boolean saved_conditional_macro_used;
3080 2949 Chain cond_name;
3081 2950 Chain cond_chain;
3082 2951
3083 2952 if (target->dont_activate_cond_values) {
3084 2953 return;
3085 2954 }
3086 2955
3087 2956 saved_conditional_macro_used = conditional_macro_used;
3088 2957
3089 2958 /* Scan the list of conditional properties and apply each one */
3090 2959 for (conditional = get_prop(target->prop, conditional_prop), i = 0;
3091 2960 conditional != NULL;
3092 2961 conditional = get_prop(conditional->next, conditional_prop),
3093 2962 i++) {
3094 2963 /* Save the old value */
3095 2964 old_locals[i].body.macro =
3096 2965 maybe_append_prop(conditional->body.conditional.name,
3097 2966 macro_prop)->body.macro;
3098 2967 if (debug_level > 1) {
3099 2968 (void) printf(catgets(catd, 1, 38, "%*sActivating conditional value: "),
3100 2969 recursion_level,
3101 2970 "");
3102 2971 }
3103 2972 /* Set the conditional value. Macros are expanded when the */
3104 2973 /* macro is refd as usual */
3105 2974 if ((conditional->body.conditional.name != virtual_root) ||
3106 2975 (conditional->body.conditional.value != virtual_root)) {
3107 2976 (void) SETVAR(conditional->body.conditional.name,
3108 2977 conditional->body.conditional.value,
3109 2978 (Boolean) conditional->body.conditional.append);
3110 2979 }
3111 2980 cond_name = ALLOC(Chain);
3112 2981 cond_name->name = conditional->body.conditional.name;
3113 2982 }
3114 2983 /* Put this target on the front of the chain of conditional targets */
3115 2984 cond_chain = ALLOC(Chain);
3116 2985 cond_chain->name = target;
3117 2986 cond_chain->next = conditional_targets;
3118 2987 conditional_targets = cond_chain;
3119 2988 conditional_macro_used = saved_conditional_macro_used;
3120 2989 }
3121 2990
3122 2991 /*
3123 2992 * reset_locals(target, old_locals, conditional, index)
3124 2993 *
3125 2994 * Removes any conditional macros for the target.
3126 2995 *
3127 2996 * Parameters:
3128 2997 * target The target we are retoring values for
3129 2998 * old_locals The values to restore
3130 2999 * conditional The first conditional block for the target
3131 3000 * index into the old_locals vector
3132 3001 * Global variables used:
3133 3002 * debug_level Should we trace activities?
3134 3003 * recursion_level Used for tracing
3135 3004 */
3136 3005 void
3137 3006 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3138 3007 {
3139 3008 register Property this_conditional;
3140 3009 Chain cond_chain;
3141 3010
3142 3011 if (target->dont_activate_cond_values) {
3143 3012 return;
3144 3013 }
3145 3014
3146 3015 /* Scan the list of conditional properties and restore the old value */
3147 3016 /* to each one Reverse the order relative to when we assigned macros */
3148 3017 this_conditional = get_prop(conditional->next, conditional_prop);
3149 3018 if (this_conditional != NULL) {
3150 3019 reset_locals(target, old_locals, this_conditional, index+1);
3151 3020 } else {
3152 3021 /* Remove conditional target from chain */
3153 3022 if (conditional_targets == NULL ||
3154 3023 conditional_targets->name != target) {
3155 3024 warning(catgets(catd, 1, 39, "Internal error: reset target not at head of condtional_targets chain"));
3156 3025 } else {
3157 3026 cond_chain = conditional_targets->next;
3158 3027 retmem_mb((caddr_t) conditional_targets);
3159 3028 conditional_targets = cond_chain;
3160 3029 }
3161 3030 }
3162 3031 get_prop(conditional->body.conditional.name->prop,
3163 3032 macro_prop)->body.macro = old_locals[index].body.macro;
3164 3033 if (conditional->body.conditional.name == virtual_root) {
3165 3034 (void) SETVAR(virtual_root, getvar(virtual_root), false);
3166 3035 }
3167 3036 if (debug_level > 1) {
3168 3037 if (old_locals[index].body.macro.value != NULL) {
3169 3038 (void) printf(catgets(catd, 1, 40, "%*sdeactivating conditional value: %s= %s\n"),
3170 3039 recursion_level,
3171 3040 "",
3172 3041 conditional->body.conditional.name->
3173 3042 string_mb,
3174 3043 old_locals[index].body.macro.value->
3175 3044 string_mb);
3176 3045 } else {
3177 3046 (void) printf(catgets(catd, 1, 41, "%*sdeactivating conditional value: %s =\n"),
3178 3047 recursion_level,
3179 3048 "",
3180 3049 conditional->body.conditional.name->
3181 3050 string_mb);
3182 3051 }
3183 3052 }
3184 3053 }
3185 3054
3186 3055 /*
3187 3056 * check_auto_dependencies(target, auto_count, automatics)
3188 3057 *
3189 3058 * Returns true if the target now has a dependency
3190 3059 * it didn't previously have (saved on automatics).
3191 3060 *
3192 3061 * Return value:
3193 3062 * true if new dependency found
3194 3063 *
3195 3064 * Parameters:
3196 3065 * target Target we check
3197 3066 * auto_count Number of old automatic vars
3198 3067 * automatics Saved old automatics
3199 3068 *
3200 3069 * Global variables used:
3201 3070 * keep_state Indicates that .KEEP_STATE is on
3202 3071 */
3203 3072 Boolean
3204 3073 check_auto_dependencies(Name target, int auto_count, Name *automatics)
3205 3074 {
3206 3075 Name *p;
3207 3076 int n;
3208 3077 Property line;
3209 3078 Dependency dependency;
3210 3079
3211 3080 if (keep_state) {
3212 3081 if ((line = get_prop(target->prop, line_prop)) == NULL) {
3213 3082 return false;
3214 3083 }
3215 3084 /* Go thru new list of automatic depes */
3216 3085 for (dependency = line->body.line.dependencies;
3217 3086 dependency != NULL;
3218 3087 dependency = dependency->next) {
3219 3088 /* And make sure that each one existed before we */
3220 3089 /* built the target */
3221 3090 if (dependency->automatic && !dependency->stale) {
3222 3091 for (n = auto_count, p = automatics;
3223 3092 n > 0;
3224 3093 n--) {
3225 3094 if (*p++ == dependency->name) {
3226 3095 /* If we can find it on the */
3227 3096 /* saved list of autos we */
3228 3097 /* are OK */
3229 3098 goto not_new;
3230 3099 }
3231 3100 }
3232 3101 /* But if we scan over the old list */
3233 3102 /* of auto. without finding it it is */
3234 3103 /* new and we must check it */
3235 3104 return true;
3236 3105 }
3237 3106 not_new:;
3238 3107 }
3239 3108 return false;
3240 3109 } else {
3241 3110 return false;
3242 3111 }
3243 3112 }
3244 3113
3245 3114
3246 3115 // Recursively delete each of the Chain struct on the chain.
3247 3116
3248 3117 static void
3249 3118 delete_query_chain(Chain ch)
3250 3119 {
3251 3120 if (ch == NULL) {
3252 3121 return;
3253 3122 } else {
3254 3123 delete_query_chain(ch->next);
3255 3124 retmem_mb((char *) ch);
3256 3125 }
3257 3126 }
3258 3127
3259 3128 Doname
3260 3129 target_can_be_built(register Name target) {
3261 3130 Doname result = build_dont_know;
3262 3131 Name true_target = target;
3263 3132 Property line;
3264 3133
3265 3134 if (target == wait_name) {
3266 3135 return(build_ok);
3267 3136 }
3268 3137 /*
3269 3138 * If the target is a constructed one for a "::" target,
3270 3139 * we need to consider that.
3271 3140 */
3272 3141 if (target->has_target_prop) {
3273 3142 true_target = get_prop(target->prop,
3274 3143 target_prop)->body.target.target;
3275 3144 }
3276 3145
3277 3146 (void) exists(true_target);
3278 3147
3279 3148 if (true_target->state == build_running) {
3280 3149 return(build_running);
3281 3150 }
3282 3151 if (true_target->stat.time != file_doesnt_exist) {
3283 3152 result = build_ok;
3284 3153 }
3285 3154
3286 3155 /* get line property for the target */
3287 3156 line = get_prop(true_target->prop, line_prop);
3288 3157
3289 3158 /* first check for explicit rule */
3290 3159 if (line != NULL && line->body.line.command_template != NULL) {
3291 3160 result = build_ok;
3292 3161 }
3293 3162 /* try to find pattern rule */
3294 3163 if (result == build_dont_know) {
3295 3164 result = find_percent_rule(target, NULL, false);
3296 3165 }
3297 3166
3298 3167 /* try to find double suffix rule */
3299 3168 if (result == build_dont_know) {
3300 3169 if (target->is_member) {
3301 3170 Property member = get_prop(target->prop, member_prop);
3302 3171 if (member != NULL && member->body.member.member != NULL) {
3303 3172 result = find_ar_suffix_rule(target, member->body.member.member, NULL, false);
3304 3173 } else {
3305 3174 result = find_double_suffix_rule(target, NULL, false);
3306 3175 }
3307 3176 } else {
3308 3177 result = find_double_suffix_rule(target, NULL, false);
3309 3178 }
3310 3179 }
3311 3180
3312 3181 /* try to find suffix rule */
3313 3182 if ((result == build_dont_know) && second_pass) {
3314 3183 result = find_suffix_rule(target, target, empty_name, NULL, false);
3315 3184 }
3316 3185
3317 3186 /* check for sccs */
3318 3187 if (result == build_dont_know) {
3319 3188 result = sccs_get(target, NULL);
3320 3189 }
3321 3190
3322 3191 /* try to find dyn target */
3323 3192 if (result == build_dont_know) {
3324 3193 Name dtarg = find_dyntarget(target);
3325 3194 if (dtarg != NULL) {
3326 3195 result = target_can_be_built(dtarg);
3327 3196 }
3328 3197 }
3329 3198
3330 3199 /* check whether target was mentioned in makefile */
3331 3200 if (result == build_dont_know) {
3332 3201 if (target->colons != no_colon) {
3333 3202 result = build_ok;
3334 3203 }
3335 3204 }
3336 3205
3337 3206 /* result */
3338 3207 return result;
3339 3208 }
↓ open down ↓ |
629 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX