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