16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * doname.c
28 *
29 * Figure out which targets are out of date and rebuild them
30 */
31
32 /*
33 * Included files
34 */
35 #include <alloca.h> /* alloca() */
36
37
38 #include <fcntl.h>
39 #include <mk/defs.h>
40 #include <mksh/i18n.h> /* get_char_semantics_value() */
41 #include <mksh/macro.h> /* getvar(), expand_value() */
42 #include <mksh/misc.h> /* getmem() */
43 #include <poll.h>
44
45
46 #include <signal.h>
47
48 # include <stropts.h>
49
50 #include <sys/errno.h>
51 #include <sys/stat.h>
52 #include <sys/types.h>
53 #include <sys/utsname.h> /* uname() */
54 #include <sys/wait.h>
55 #include <unistd.h> /* close() */
56
57 /*
58 * Defined macros
59 */
60 # define LOCALHOST "localhost"
61
62 #define MAXRULES 100
63
64 // Sleep for .1 seconds between stat()'s
65 const int STAT_RETRY_SLEEP_TIME = 100000;
66
67 /*
68 * typedefs & structs
69 */
126 * Global variables used:
127 * build_failed_seen Set if -k is on and error occurs
128 * continue_after_error Indicates that -k is on
129 * report_dependencies No error msg if -P is on
130 */
131 Doname
132 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
133 {
134 int first_time = 1;
135 (void) fflush(stdout);
136 try_again:
137 switch (doname(target, do_get, implicit, automatic)) {
138 case build_ok:
139 second_pass = 0;
140 return build_ok;
141 case build_running:
142 second_pass = 0;
143 return build_running;
144 case build_failed:
145 if (!continue_after_error) {
146 fatal(catgets(catd, 1, 13, "Target `%s' not remade because of errors"),
147 target->string_mb);
148 }
149 build_failed_seen = true;
150 second_pass = 0;
151 return build_failed;
152 case build_dont_know:
153 /*
154 * If we can't figure out how to build an automatic
155 * (hidden) dependency, we just ignore it.
156 * We later declare the target to be out of date just in
157 * case something changed.
158 * Also, don't complain if just reporting the dependencies
159 * and not building anything.
160 */
161 if (automatic || (report_dependencies_level > 0)) {
162 second_pass = 0;
163 return build_dont_know;
164 }
165 if(first_time) {
166 first_time = 0;
167 second_pass = 1;
168 goto try_again;
169 }
170 second_pass = 0;
171 if (continue_after_error && !svr4) {
172 warning(catgets(catd, 1, 14, "Don't know how to make target `%s'"),
173 target->string_mb);
174 build_failed_seen = true;
175 return build_failed;
176 }
177 fatal(catgets(catd, 1, 15, "Don't know how to make target `%s'"), target->string_mb);
178 break;
179 }
180 #ifdef lint
181 return build_failed;
182 #endif
183 }
184
185
186 void
187 enter_explicit_rule_from_dynamic_rule(Name target, Name source)
188 {
189 Property line, source_line;
190 Dependency dependency;
191
192 source_line = get_prop(source->prop, line_prop);
193 line = maybe_append_prop(target, line_prop);
194 line->body.line.sccs_command = false;
195 line->body.line.target = target;
196 if (line->body.line.command_template == NULL) {
197 line->body.line.command_template = source_line->body.line.command_template;
422 for (dependency = line->body.line.dependencies;
423 dependency != NULL;
424 dependency = dependency->next) {
425 if (dependency->automatic && !dependency->stale) {
426 auto_count++;
427 }
428 }
429 /* Create vector to hold the current autos */
430 automatics =
431 (Name *) alloca((int) (auto_count * sizeof (Name)));
432 /* Copy them */
433 for (p = automatics, dependency = line->body.line.dependencies;
434 dependency != NULL;
435 dependency = dependency->next) {
436 if (dependency->automatic && !dependency->stale) {
437 *p++ = dependency->name;
438 }
439 }
440 }
441 if (debug_level > 1) {
442 (void) printf(NOCATGETS("%*sdoname(%s)\n"),
443 recursion_level,
444 "",
445 target->string_mb);
446 }
447 recursion_level++;
448 /* Avoid infinite loops */
449 if (target->state == build_in_progress) {
450 warning(catgets(catd, 1, 16, "Infinite loop: Target `%s' depends on itself"),
451 target->string_mb);
452 return build_ok;
453 }
454 target->state = build_in_progress;
455
456 /* Activate conditional macros for the target */
457 if (!target->added_pattern_conditionals) {
458 add_pattern_conditionals(target);
459 target->added_pattern_conditionals = true;
460 }
461 if (target->conditional_cnt > 0) {
462 old_locals = (Property) alloca(target->conditional_cnt *
463 sizeof (Property_rec));
464 set_locals(target, old_locals);
465 }
466
467 /*
468 * after making the call to dynamic_dependecies unconditional we can handle
469 * target names that are same as file name. In this case $$@ in the
470 * dependencies did not mean anything. WIth this change it expands it
668 /* Use .DEFAULT rule if it is defined. */
669 if ((command == NULL) &&
670 (result == build_dont_know) &&
671 (true_target->colons == no_colon) &&
672 default_rule &&
673 !implicit) {
674 /* Make sure we have a line prop */
675 line = maybe_append_prop(target, line_prop);
676 command = line;
677 Boolean out_of_date;
678 if (true_target->is_member) {
679 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
680 line->body.line.dependency_time);
681 } else {
682 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
683 line->body.line.dependency_time);
684 }
685 if (build_unconditional || out_of_date) {
686 line->body.line.is_out_of_date = true;
687 if (debug_level > 0) {
688 (void) printf(catgets(catd, 1, 17, "%*sBuilding %s using .DEFAULT because it is out of date\n"),
689 recursion_level,
690 "",
691 true_target->string_mb);
692 }
693 }
694 line->body.line.sccs_command = false;
695 line->body.line.command_template = default_rule;
696 line->body.line.target = true_target;
697 line->body.line.star = NULL;
698 line->body.line.less = true_target;
699 line->body.line.percent = NULL;
700 }
701 }
702
703 /* We say "target up to date" if no cmd were executed for the target */
704 if (!target->is_double_colon_parent) {
705 commands_done = false;
706 }
707
708 silent = silent_all;
862 recursion_level--;
863 if (target->is_member) {
864 Property member;
865
866 /* Propagate the timestamp from the member file to the member*/
867 if ((target->stat.time != file_max_time) &&
868 ((member = get_prop(target->prop, member_prop)) != NULL) &&
869 (exists(member->body.member.member) > file_doesnt_exist)) {
870 target->stat.time =
871 member->body.member.member->stat.time;
872 }
873 }
874 /*
875 * Check if we found any new auto dependencies when we
876 * built the target.
877 */
878 if ((result == build_ok) && check_auto_dependencies(target,
879 auto_count,
880 automatics)) {
881 if (debug_level > 0) {
882 (void) printf(catgets(catd, 1, 18, "%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
883 recursion_level,
884 "",
885 true_target->string_mb);
886 }
887 rechecking_target = true;
888 saved_commands_done = commands_done;
889 goto recheck_target;
890 }
891
892 if (rechecking_target && !commands_done) {
893 commands_done = saved_commands_done;
894 }
895
896 return result;
897 }
898
899 /*
900 * DONE.
901 *
902 * check_dependencies(result, line, do_get,
1015 break;
1016 case build_dont_know:
1017 /*
1018 * If make can't figure out how to make a dependency, maybe the dependency
1019 * is out of date. In this case, we just declare the target out of date
1020 * and go on. If we really need the dependency, the make'ing of the target
1021 * will fail. This will only happen for automatic (hidden) dependencies.
1022 */
1023 if(!recheck_conditionals) {
1024 line->body.line.is_out_of_date = true;
1025 }
1026 /*
1027 * Make sure the dependency is not saved
1028 * in the state file.
1029 */
1030 dependency->stale = true;
1031 rewrite_statefile =
1032 command_changed =
1033 true;
1034 if (debug_level > 0) {
1035 (void) printf(catgets(catd, 1, 19, "Target %s rebuilt because dependency %s does not exist\n"),
1036 true_target->string_mb,
1037 dependency->name->string_mb);
1038 }
1039 break;
1040 }
1041 if (dependency->name->depends_on_conditional) {
1042 target->depends_on_conditional = true;
1043 }
1044 if (dependency->name == force) {
1045 target->stat.time =
1046 dependency->name->stat.time;
1047 }
1048 /*
1049 * Propagate new timestamp from "member" to
1050 * "lib.a(member)".
1051 */
1052 (void) exists(dependency->name);
1053
1054 /* Collect the timestamp of the youngest dependency */
1055 line->body.line.dependency_time =
1056 MAX(dependency->name->stat.time,
1057 line->body.line.dependency_time);
1058
1059 /* Correction: do not consider nanosecs for members */
1060 if(true_target->is_member || dependency->name->is_member) {
1061 line->body.line.dependency_time.tv_nsec = 0;
1062 }
1063
1064 if (debug_level > 1) {
1065 (void) printf(catgets(catd, 1, 20, "%*sDate(%s)=%s \n"),
1066 recursion_level,
1067 "",
1068 dependency->name->string_mb,
1069 time_to_string(dependency->name->
1070 stat.time));
1071 if (dependency->name->stat.time > line->body.line.dependency_time) {
1072 (void) printf(catgets(catd, 1, 21, "%*sDate-dependencies(%s) set to %s\n"),
1073 recursion_level,
1074 "",
1075 true_target->string_mb,
1076 time_to_string(line->body.line.
1077 dependency_time));
1078 }
1079 }
1080
1081 /* Build the $? list */
1082 if (true_target->is_member) {
1083 if (this_dependency_changed == true) {
1084 true_target->stat.time = dependency->name->stat.time;
1085 true_target->stat.time.tv_sec--;
1086 } else {
1087 /* Dina:
1088 * The next statement is commented
1089 * out as a fix for bug #1051032.
1090 * if dependency hasn't changed
1091 * then there's no need to invalidate
1092 * true_target. This statemnt causes
1111 }
1112 if ((build_unconditional || out_of_date) &&
1113 (dependency->name != force) &&
1114 (dependency->stale == false)) {
1115 *out_of_date_tail = ALLOC(Chain);
1116 if (dependency->name->is_member &&
1117 (get_prop(dependency->name->prop,
1118 member_prop) != NULL)) {
1119 (*out_of_date_tail)->name =
1120 get_prop(dependency->name->prop,
1121 member_prop)->
1122 body.member.member;
1123 } else {
1124 (*out_of_date_tail)->name =
1125 dependency->name;
1126 }
1127 (*out_of_date_tail)->next = NULL;
1128 out_of_date_tail = &(*out_of_date_tail)->next;
1129 if (debug_level > 0) {
1130 if (dependency->name->stat.time == file_max_time) {
1131 (void) printf(catgets(catd, 1, 22, "%*sBuilding %s because %s does not exist\n"),
1132 recursion_level,
1133 "",
1134 true_target->string_mb,
1135 dependency->name->string_mb);
1136 } else {
1137 (void) printf(catgets(catd, 1, 23, "%*sBuilding %s because it is out of date relative to %s\n"),
1138 recursion_level,
1139 "",
1140 true_target->string_mb,
1141 dependency->name->string_mb);
1142 }
1143 }
1144 }
1145 if (dependency->name == force) {
1146 force->stat.time =
1147 file_max_time;
1148 force->state = build_dont_know;
1149 }
1150 }
1151 }
1152 if (dependencies_running) {
1153 if (doing_subtree) {
1154 if (target->conditional_cnt > 0) {
1155 reset_locals(target,
1156 old_locals,
1157 get_prop(target->prop,
1187 Property tmp_line;
1188
1189 if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1190 if(tmp_line->body.line.dependency_time != file_max_time) {
1191 target->stat.time =
1192 MAX(tmp_line->body.line.dependency_time,
1193 target->stat.time);
1194 }
1195 }
1196 }
1197 }
1198 if ((true_target->is_member) && (dependency_changed == true)) {
1199 true_target->stat.time = file_no_time;
1200 }
1201 /*
1202 * After scanning all the dependencies, we check the rule
1203 * if we found one.
1204 */
1205 if (line->body.line.command_template != NULL) {
1206 if (line->body.line.command_template_redefined) {
1207 warning(catgets(catd, 1, 24, "Too many rules defined for target %s"),
1208 target->string_mb);
1209 }
1210 *command = line;
1211 /* Check if the target is out of date */
1212 Boolean out_of_date;
1213 if (true_target->is_member) {
1214 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1215 line->body.line.dependency_time);
1216 } else {
1217 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1218 line->body.line.dependency_time);
1219 }
1220 if (build_unconditional || out_of_date){
1221 if(!recheck_conditionals) {
1222 line->body.line.is_out_of_date = true;
1223 }
1224 }
1225 line->body.line.sccs_command = false;
1226 line->body.line.target = true_target;
1227 if(gnu_style) {
1407 /* Create new dependency cell if */
1408 /* this is not the first dependency */
1409 /* picked from the expansion */
1410 if (!reuse_cell) {
1411 new_depe = ALLOC(Dependency);
1412 new_depe->next = dependency->next;
1413 new_depe->automatic = false;
1414 new_depe->stale = false;
1415 new_depe->built = false;
1416 dependency->next = new_depe;
1417 dependency = new_depe;
1418 }
1419 reuse_cell = false;
1420 /* Internalize the dependency name */
1421 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1422 // include "//" and "/./"
1423 //dependency->name = GETNAME(start, p - start);
1424 dependency->name = normalize_name(start, p - start);
1425 if ((debug_level > 0) &&
1426 (first_member == NULL)) {
1427 (void) printf(catgets(catd, 1, 25, "%*sDynamic dependency `%s' for target `%s'\n"),
1428 recursion_level,
1429 "",
1430 dependency->name->string_mb,
1431 true_target->string_mb);
1432 }
1433 for (start = p; iswspace(*start); start++);
1434 p = start;
1435 }
1436 } while ((*p != (int) nul_char) &&
1437 (*p != (int) parenright_char));
1438 /* If the expansion was of lib.a(members) format we now */
1439 /* enter the proper member cells */
1440 if (first_member != NULL) {
1441 /* Scan the new dependencies and transform them from */
1442 /* "foo" to "lib.a(foo)" */
1443 for (; 1; first_member = first_member->next) {
1444 /* Build "lib.a(foo)" name */
1445 INIT_STRING_FROM_STACK(string, buffer);
1446 APPEND_NAME(lib,
1447 &string,
1448 (int) lib->hash.length);
1449 append_char((int) parenleft_char, &string);
1450 APPEND_NAME(first_member->name,
1451 &string,
1452 FIND_LENGTH);
1453 append_char((int) parenright_char, &string);
1454 member = first_member->name;
1455 /* Replace "foo" with "lib.a(foo)" */
1456 first_member->name =
1457 GETNAME(string.buffer.start, FIND_LENGTH);
1458 if (string.free_after_use) {
1459 retmem(string.buffer.start);
1460 }
1461 if (debug_level > 0) {
1462 (void) printf(catgets(catd, 1, 26, "%*sDynamic dependency `%s' for target `%s'\n"),
1463 recursion_level,
1464 "",
1465 first_member->name->
1466 string_mb,
1467 true_target->string_mb);
1468 }
1469 first_member->name->is_member = lib->is_member;
1470 /* Add member property to member */
1471 prop = maybe_append_prop(first_member->name,
1472 member_prop);
1473 prop->body.member.library = lib;
1474 prop->body.member.entry = NULL;
1475 prop->body.member.member = member;
1476 if (first_member == dependency) {
1477 break;
1478 }
1479 }
1480 }
1481 }
1482 Wstring wcb;
1599 /* If quest, then exit(1) because the target is out of date */
1600 if (quest) {
1601 if (posix) {
1602 result = execute_parallel(line, true);
1603 }
1604 exit_status = 1;
1605 exit(1);
1606 }
1607 /* We actually had to do something this time */
1608 rewrite_statefile = commands_done = true;
1609 /*
1610 * If this is an sccs command, we have to do some extra checking
1611 * and possibly complain. If the file can't be gotten because it's
1612 * checked out, we complain and behave as if the command was
1613 * executed eventhough we ignored the command.
1614 */
1615 if (!touch &&
1616 line->body.line.sccs_command &&
1617 (target->stat.time != file_doesnt_exist) &&
1618 ((target->stat.mode & 0222) != 0)) {
1619 fatal(catgets(catd, 1, 27, "%s is writable so it cannot be sccs gotten"),
1620 target->string_mb);
1621 target->has_complained = remember_only = true;
1622 }
1623 /*
1624 * If KEEP_STATE is on, we make sure we have the timestamp for
1625 * .make.state. If .make.state changes during the command run,
1626 * we reread .make.state after the command. We also setup the
1627 * environment variable that asks utilities to report dependencies.
1628 */
1629 if (!touch &&
1630 keep_state &&
1631 !remember_only) {
1632 (void) exists(make_state);
1633 if((strlen(temp_file_directory) == 1) &&
1634 (temp_file_directory[0] == '/')) {
1635 tmp_file_path[0] = '\0';
1636 } else {
1637 strcpy(tmp_file_path, temp_file_directory);
1638 }
1639 sprintf(mbs_buffer,
1640 NOCATGETS("%s/.make.dependency.%08x.%d.%d"),
1641 tmp_file_path,
1642 hostid,
1643 getpid(),
1644 file_number++);
1645 MBSTOWCS(wcs_buffer, mbs_buffer);
1646 Boolean fnd;
1647 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1648 temp_file_name->stat.is_file = true;
1649 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1650 wchar_t *to = string = ALLOC_WC(len);
1651 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1652 if (*from == (int) space_char) {
1653 *to++ = (int) backslash_char;
1654 }
1655 *to++ = *from++;
1656 }
1657 *to++ = (int) space_char;
1658 MBSTOWCS(to, target->string_mb);
1659 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1660 (void) SETVAR(sunpro_dependencies,
1810 do_assign(rule->command_line, target);
1811 } else if (report_dependencies_level == 0) {
1812 /* Execute command line. */
1813 setvar_envvar();
1814 result = dosys(rule->command_line,
1815 (Boolean) rule->ignore_error,
1816 (Boolean) rule->make_refd,
1817 /* ds 98.04.23 bug #4085164. make should always show error messages */
1818 false,
1819 /* BOOLEAN(rule->silent &&
1820 rule->ignore_error), */
1821 (Boolean) rule->always_exec,
1822 target);
1823 check_state(temp_file_name);
1824 }
1825 } else {
1826 result = build_ok;
1827 }
1828 if (result == build_failed) {
1829 if (silent || rule->silent) {
1830 (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"),
1831 rule->command_line->string_mb);
1832 }
1833 if (!rule->ignore_error && !ignore_errors) {
1834 if (!continue_after_error) {
1835 fatal(catgets(catd, 1, 244, "Command failed for target `%s'"),
1836 target->string_mb);
1837 }
1838 /*
1839 * Make sure a failing command is not
1840 * saved in .make.state.
1841 */
1842 line->body.line.command_used = NULL;
1843 break;
1844 } else {
1845 result = build_ok;
1846 }
1847 }
1848 }
1849 for (rule = command; rule != NULL; rule = cmd_tail) {
1850 cmd_tail = rule->next;
1851 free(rule);
1852 }
1853 command = NULL;
1854 if (temp_file_name != NULL) {
1855 free_name(temp_file_name);
2093 while (iswspace(*string)) {
2094 string++;
2095 }
2096 equal = string;
2097 /* Find "+=" or "=". */
2098 while (!iswspace(*equal) &&
2099 (*equal != (int) plus_char) &&
2100 (*equal != (int) equal_char)) {
2101 equal++;
2102 }
2103 /* Internalize macro name. */
2104 name = GETNAME(string, equal - string);
2105 /* Skip over "+=" "=". */
2106 while (!((*equal == (int) nul_char) ||
2107 (*equal == (int) equal_char) ||
2108 (*equal == (int) plus_char))) {
2109 equal++;
2110 }
2111 switch (*equal) {
2112 case nul_char:
2113 fatal(catgets(catd, 1, 31, "= expected in rule `%s' for target `%s'"),
2114 line->string_mb,
2115 target->string_mb);
2116 case plus_char:
2117 append = true;
2118 equal++;
2119 break;
2120 }
2121 equal++;
2122 /* Skip over whitespace in front of value. */
2123 while (iswspace(*equal)) {
2124 equal++;
2125 }
2126 /* Enter new macro value. */
2127 enter_equal(name,
2128 GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2129 append);
2130 }
2131
2132 /*
2133 * build_command_strings(target, line)
2387 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2388 if (!used->ignore_command_dependency) {
2389 ignore_all_command_dependency = false;
2390 }
2391 /* Internalize the expanded and stripped command line */
2392 new_command_line = GETNAME(start, FIND_LENGTH);
2393 if ((used->command_line == NULL) &&
2394 (line->body.line.sccs_command)) {
2395 used->command_line = new_command_line;
2396 new_command_longer = false;
2397 }
2398 /* Compare it with the old one for command consistency */
2399 if (used->command_line != new_command_line) {
2400 Name vpath_translated = vpath_translation(new_command_line);
2401 if (keep_state &&
2402 !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2403 if (debug_level > 0) {
2404 if (used->command_line != NULL
2405 && *used->command_line->string_mb !=
2406 '\0') {
2407 (void) printf(catgets(catd, 1, 32, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2408 recursion_level,
2409 "",
2410 target->string_mb,
2411 vpath_translated->string_mb,
2412 recursion_level,
2413 "",
2414 used->
2415 command_line->
2416 string_mb);
2417 } else {
2418 (void) printf(catgets(catd, 1, 33, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2419 recursion_level,
2420 "",
2421 target->string_mb,
2422 vpath_translated->string_mb,
2423 recursion_level,
2424 "");
2425 }
2426 }
2427 command_changed = true;
2428 line->body.line.is_out_of_date = true;
2429 }
2430 used->command_line = new_command_line;
2431 }
2432 if (command_line.free_after_use) {
2433 retmem(command_line.buffer.start);
2434 }
2435 }
2436 /* Check if the old command is longer than the new for */
2437 /* command consistency */
2438 if (used != NULL) {
2439 *insert = NULL;
2440 if (keep_state &&
2441 !ignore_all_command_dependency) {
2442 if (debug_level > 0) {
2443 (void) printf(catgets(catd, 1, 34, "%*sBuilding %s because new command shorter than old\n"),
2444 recursion_level,
2445 "",
2446 target->string_mb);
2447 }
2448 command_changed = true;
2449 line->body.line.is_out_of_date = true;
2450 }
2451 }
2452 /* Check if the new command is longer than the old command for */
2453 /* command consistency */
2454 if (new_command_longer &&
2455 !ignore_all_command_dependency &&
2456 keep_state) {
2457 if (debug_level > 0) {
2458 (void) printf(catgets(catd, 1, 35, "%*sBuilding %s because new command longer than old\n"),
2459 recursion_level,
2460 "",
2461 target->string_mb);
2462 }
2463 command_changed = true;
2464 line->body.line.is_out_of_date = true;
2465 }
2466 /* Unbind the magic macros */
2467 (void) SETVAR(c_at, (Name) NULL, false);
2468 (void) SETVAR(star, (Name) NULL, false);
2469 (void) SETVAR(less_name, (Name) NULL, false);
2470 (void) SETVAR(percent_name, (Name) NULL, false);
2471 (void) SETVAR(query, (Name) NULL, false);
2472 if (query_list != NULL) {
2473 delete_query_chain(query_list);
2474 }
2475 (void) SETVAR(hat, (Name) NULL, false);
2476 if (hat_list != NULL) {
2477 delete_query_chain(hat_list);
2478 }
2504 */
2505 static Doname
2506 touch_command(register Property line, register Name target, Doname result)
2507 {
2508 Name name;
2509 register Chain target_group;
2510 String_rec touch_string;
2511 wchar_t buffer[MAXPATHLEN];
2512 Name touch_cmd;
2513 Cmd_line rule;
2514
2515 for (name = target, target_group = NULL; name != NULL;) {
2516 if (!name->is_member) {
2517 /*
2518 * Build a touch command that can be passed
2519 * to dosys(). If KEEP_STATE is on, "make -t"
2520 * will save the proper command, not the
2521 * "touch" in .make.state.
2522 */
2523 INIT_STRING_FROM_STACK(touch_string, buffer);
2524 MBSTOWCS(wcs_buffer, NOCATGETS("touch "));
2525 append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2526 touch_cmd = name;
2527 if (name->has_vpath_alias_prop) {
2528 touch_cmd = get_prop(name->prop,
2529 vpath_alias_prop)->
2530 body.vpath_alias.alias;
2531 }
2532 APPEND_NAME(touch_cmd,
2533 &touch_string,
2534 FIND_LENGTH);
2535 touch_cmd = GETNAME(touch_string.buffer.start,
2536 FIND_LENGTH);
2537 if (touch_string.free_after_use) {
2538 retmem(touch_string.buffer.start);
2539 }
2540 if (!silent ||
2541 do_not_exec_rule &&
2542 (target_group == NULL)) {
2543 (void) printf("%s\n", touch_cmd->string_mb);
2544 }
2669 * Global variables used:
2670 * debug_level Should we trace activities?
2671 * recursion_level Used for tracing
2672 * sccs_get_rule The rule to used for sccs getting
2673 */
2674 static Doname
2675 sccs_get(register Name target, register Property *command)
2676 {
2677 register int result;
2678 char link[MAXPATHLEN];
2679 String_rec string;
2680 wchar_t name[MAXPATHLEN];
2681 register wchar_t *p;
2682 timestruc_t sccs_time;
2683 register Property line;
2684 int sym_link_depth = 0;
2685
2686 /* For sccs, we need to chase symlinks. */
2687 while (target->stat.is_sym_link) {
2688 if (sym_link_depth++ > 90) {
2689 fatal(catgets(catd, 1, 95, "Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2690 target->string_mb);
2691 }
2692 /* Read the value of the link. */
2693 result = readlink_vroot(target->string_mb,
2694 link,
2695 sizeof(link),
2696 NULL,
2697 VROOT_DEFAULT);
2698 if (result == -1) {
2699 fatal(catgets(catd, 1, 36, "Can't read symbolic link `%s': %s"),
2700 target->string_mb, errmsg(errno));
2701 }
2702 link[result] = 0;
2703 /* Use the value to build the proper filename. */
2704 INIT_STRING_FROM_STACK(string, name);
2705
2706 Wstring wcb(target);
2707 if ((link[0] != slash_char) &&
2708 ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) {
2709 append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2710 }
2711 append_string(link, &string, result);
2712 /* Replace the old name with the translated name. */
2713 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2714 (void) exists(target);
2715 if (string.free_after_use) {
2716 retmem(string.buffer.start);
2717 }
2718 }
2719
2751 if ((!target->has_complained &&
2752 (sccs_time != file_doesnt_exist) &&
2753 (sccs_get_rule != NULL))) {
2754 /* only checking */
2755 if (command == NULL) {
2756 return build_ok;
2757 }
2758 /*
2759 * We provide a command line for the target. The line is a
2760 * "sccs get" command from default.mk.
2761 */
2762 line = maybe_append_prop(target, line_prop);
2763 *command = line;
2764 if (sccs_time > target->stat.time) {
2765 /*
2766 * And only if the plain file is out of date do we
2767 * request execution of the command.
2768 */
2769 line->body.line.is_out_of_date = true;
2770 if (debug_level > 0) {
2771 (void) printf(catgets(catd, 1, 37, "%*sSccs getting %s because s. file is younger than source file\n"),
2772 recursion_level,
2773 "",
2774 target->string_mb);
2775 }
2776 }
2777 line->body.line.sccs_command = true;
2778 line->body.line.command_template = sccs_get_rule;
2779 if(!svr4 && (!allrules_read || posix)) {
2780 if((target->prop) &&
2781 (target->prop->body.sccs.file) &&
2782 (target->prop->body.sccs.file->string_mb)) {
2783 if((strlen(target->prop->body.sccs.file->string_mb) ==
2784 strlen(target->string_mb) + 2) &&
2785 (target->prop->body.sccs.file->string_mb[0] == 's') &&
2786 (target->prop->body.sccs.file->string_mb[1] == '.')) {
2787
2788 line->body.line.command_template = get_posix_rule;
2789 }
2790 }
2791 }
2813 * Global variables used:
2814 * dot The Name ".", used as the default dir
2815 */
2816 void
2817 read_directory_of_file(register Name file)
2818 {
2819
2820 Wstring file_string(file);
2821 wchar_t * wcb = file_string.get_string();
2822 wchar_t usr_include_buf[MAXPATHLEN];
2823 wchar_t usr_include_sys_buf[MAXPATHLEN];
2824
2825 register Name directory = dot;
2826 register wchar_t *p = (wchar_t *) wsrchr(wcb,
2827 (int) slash_char);
2828 register int length = p - wcb;
2829 static Name usr_include;
2830 static Name usr_include_sys;
2831
2832 if (usr_include == NULL) {
2833 MBSTOWCS(usr_include_buf, NOCATGETS("/usr/include"));
2834 usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
2835 MBSTOWCS(usr_include_sys_buf, NOCATGETS("/usr/include/sys"));
2836 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
2837 }
2838
2839 /*
2840 * If the filename contains a "/" we have to extract the path
2841 * Else the path defaults to ".".
2842 */
2843 if (p != NULL) {
2844 /*
2845 * Check some popular directories first to possibly
2846 * save time. Compare string length first to gain speed.
2847 */
2848 if ((usr_include->hash.length == length) &&
2849 IS_WEQUALN(usr_include_buf,
2850 wcb,
2851 length)) {
2852 directory = usr_include;
2853 } else if ((usr_include_sys->hash.length == length) &&
2854 IS_WEQUALN(usr_include_sys_buf,
2855 wcb,
2948 register Boolean saved_conditional_macro_used;
2949 Chain cond_name;
2950 Chain cond_chain;
2951
2952 if (target->dont_activate_cond_values) {
2953 return;
2954 }
2955
2956 saved_conditional_macro_used = conditional_macro_used;
2957
2958 /* Scan the list of conditional properties and apply each one */
2959 for (conditional = get_prop(target->prop, conditional_prop), i = 0;
2960 conditional != NULL;
2961 conditional = get_prop(conditional->next, conditional_prop),
2962 i++) {
2963 /* Save the old value */
2964 old_locals[i].body.macro =
2965 maybe_append_prop(conditional->body.conditional.name,
2966 macro_prop)->body.macro;
2967 if (debug_level > 1) {
2968 (void) printf(catgets(catd, 1, 38, "%*sActivating conditional value: "),
2969 recursion_level,
2970 "");
2971 }
2972 /* Set the conditional value. Macros are expanded when the */
2973 /* macro is refd as usual */
2974 if ((conditional->body.conditional.name != virtual_root) ||
2975 (conditional->body.conditional.value != virtual_root)) {
2976 (void) SETVAR(conditional->body.conditional.name,
2977 conditional->body.conditional.value,
2978 (Boolean) conditional->body.conditional.append);
2979 }
2980 cond_name = ALLOC(Chain);
2981 cond_name->name = conditional->body.conditional.name;
2982 }
2983 /* Put this target on the front of the chain of conditional targets */
2984 cond_chain = ALLOC(Chain);
2985 cond_chain->name = target;
2986 cond_chain->next = conditional_targets;
2987 conditional_targets = cond_chain;
2988 conditional_macro_used = saved_conditional_macro_used;
3004 */
3005 void
3006 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3007 {
3008 register Property this_conditional;
3009 Chain cond_chain;
3010
3011 if (target->dont_activate_cond_values) {
3012 return;
3013 }
3014
3015 /* Scan the list of conditional properties and restore the old value */
3016 /* to each one Reverse the order relative to when we assigned macros */
3017 this_conditional = get_prop(conditional->next, conditional_prop);
3018 if (this_conditional != NULL) {
3019 reset_locals(target, old_locals, this_conditional, index+1);
3020 } else {
3021 /* Remove conditional target from chain */
3022 if (conditional_targets == NULL ||
3023 conditional_targets->name != target) {
3024 warning(catgets(catd, 1, 39, "Internal error: reset target not at head of condtional_targets chain"));
3025 } else {
3026 cond_chain = conditional_targets->next;
3027 retmem_mb((caddr_t) conditional_targets);
3028 conditional_targets = cond_chain;
3029 }
3030 }
3031 get_prop(conditional->body.conditional.name->prop,
3032 macro_prop)->body.macro = old_locals[index].body.macro;
3033 if (conditional->body.conditional.name == virtual_root) {
3034 (void) SETVAR(virtual_root, getvar(virtual_root), false);
3035 }
3036 if (debug_level > 1) {
3037 if (old_locals[index].body.macro.value != NULL) {
3038 (void) printf(catgets(catd, 1, 40, "%*sdeactivating conditional value: %s= %s\n"),
3039 recursion_level,
3040 "",
3041 conditional->body.conditional.name->
3042 string_mb,
3043 old_locals[index].body.macro.value->
3044 string_mb);
3045 } else {
3046 (void) printf(catgets(catd, 1, 41, "%*sdeactivating conditional value: %s =\n"),
3047 recursion_level,
3048 "",
3049 conditional->body.conditional.name->
3050 string_mb);
3051 }
3052 }
3053 }
3054
3055 /*
3056 * check_auto_dependencies(target, auto_count, automatics)
3057 *
3058 * Returns true if the target now has a dependency
3059 * it didn't previously have (saved on automatics).
3060 *
3061 * Return value:
3062 * true if new dependency found
3063 *
3064 * Parameters:
3065 * target Target we check
3066 * auto_count Number of old automatic vars
|
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * doname.c
28 *
29 * Figure out which targets are out of date and rebuild them
30 */
31
32 /*
33 * Included files
34 */
35 #include <alloca.h> /* alloca() */
36 #include <fcntl.h>
37 #include <mk/defs.h>
38 #include <mksh/i18n.h> /* get_char_semantics_value() */
39 #include <mksh/macro.h> /* getvar(), expand_value() */
40 #include <mksh/misc.h> /* getmem() */
41 #include <poll.h>
42 #include <libintl.h>
43 #include <signal.h>
44 #include <stropts.h>
45 #include <sys/errno.h>
46 #include <sys/stat.h>
47 #include <sys/types.h>
48 #include <sys/utsname.h> /* uname() */
49 #include <sys/wait.h>
50 #include <unistd.h> /* close() */
51
52 /*
53 * Defined macros
54 */
55 # define LOCALHOST "localhost"
56
57 #define MAXRULES 100
58
59 // Sleep for .1 seconds between stat()'s
60 const int STAT_RETRY_SLEEP_TIME = 100000;
61
62 /*
63 * typedefs & structs
64 */
121 * Global variables used:
122 * build_failed_seen Set if -k is on and error occurs
123 * continue_after_error Indicates that -k is on
124 * report_dependencies No error msg if -P is on
125 */
126 Doname
127 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
128 {
129 int first_time = 1;
130 (void) fflush(stdout);
131 try_again:
132 switch (doname(target, do_get, implicit, automatic)) {
133 case build_ok:
134 second_pass = 0;
135 return build_ok;
136 case build_running:
137 second_pass = 0;
138 return build_running;
139 case build_failed:
140 if (!continue_after_error) {
141 fatal(gettext("Target `%s' not remade because of errors"),
142 target->string_mb);
143 }
144 build_failed_seen = true;
145 second_pass = 0;
146 return build_failed;
147 case build_dont_know:
148 /*
149 * If we can't figure out how to build an automatic
150 * (hidden) dependency, we just ignore it.
151 * We later declare the target to be out of date just in
152 * case something changed.
153 * Also, don't complain if just reporting the dependencies
154 * and not building anything.
155 */
156 if (automatic || (report_dependencies_level > 0)) {
157 second_pass = 0;
158 return build_dont_know;
159 }
160 if(first_time) {
161 first_time = 0;
162 second_pass = 1;
163 goto try_again;
164 }
165 second_pass = 0;
166 if (continue_after_error && !svr4) {
167 warning(gettext("Don't know how to make target `%s'"),
168 target->string_mb);
169 build_failed_seen = true;
170 return build_failed;
171 }
172 fatal(gettext("Don't know how to make target `%s'"), target->string_mb);
173 break;
174 }
175 #ifdef lint
176 return build_failed;
177 #endif
178 }
179
180
181 void
182 enter_explicit_rule_from_dynamic_rule(Name target, Name source)
183 {
184 Property line, source_line;
185 Dependency dependency;
186
187 source_line = get_prop(source->prop, line_prop);
188 line = maybe_append_prop(target, line_prop);
189 line->body.line.sccs_command = false;
190 line->body.line.target = target;
191 if (line->body.line.command_template == NULL) {
192 line->body.line.command_template = source_line->body.line.command_template;
417 for (dependency = line->body.line.dependencies;
418 dependency != NULL;
419 dependency = dependency->next) {
420 if (dependency->automatic && !dependency->stale) {
421 auto_count++;
422 }
423 }
424 /* Create vector to hold the current autos */
425 automatics =
426 (Name *) alloca((int) (auto_count * sizeof (Name)));
427 /* Copy them */
428 for (p = automatics, dependency = line->body.line.dependencies;
429 dependency != NULL;
430 dependency = dependency->next) {
431 if (dependency->automatic && !dependency->stale) {
432 *p++ = dependency->name;
433 }
434 }
435 }
436 if (debug_level > 1) {
437 (void) printf("%*sdoname(%s)\n",
438 recursion_level,
439 "",
440 target->string_mb);
441 }
442 recursion_level++;
443 /* Avoid infinite loops */
444 if (target->state == build_in_progress) {
445 warning(gettext("Infinite loop: Target `%s' depends on itself"),
446 target->string_mb);
447 return build_ok;
448 }
449 target->state = build_in_progress;
450
451 /* Activate conditional macros for the target */
452 if (!target->added_pattern_conditionals) {
453 add_pattern_conditionals(target);
454 target->added_pattern_conditionals = true;
455 }
456 if (target->conditional_cnt > 0) {
457 old_locals = (Property) alloca(target->conditional_cnt *
458 sizeof (Property_rec));
459 set_locals(target, old_locals);
460 }
461
462 /*
463 * after making the call to dynamic_dependecies unconditional we can handle
464 * target names that are same as file name. In this case $$@ in the
465 * dependencies did not mean anything. WIth this change it expands it
663 /* Use .DEFAULT rule if it is defined. */
664 if ((command == NULL) &&
665 (result == build_dont_know) &&
666 (true_target->colons == no_colon) &&
667 default_rule &&
668 !implicit) {
669 /* Make sure we have a line prop */
670 line = maybe_append_prop(target, line_prop);
671 command = line;
672 Boolean out_of_date;
673 if (true_target->is_member) {
674 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
675 line->body.line.dependency_time);
676 } else {
677 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
678 line->body.line.dependency_time);
679 }
680 if (build_unconditional || out_of_date) {
681 line->body.line.is_out_of_date = true;
682 if (debug_level > 0) {
683 (void) printf(gettext("%*sBuilding %s using .DEFAULT because it is out of date\n"),
684 recursion_level,
685 "",
686 true_target->string_mb);
687 }
688 }
689 line->body.line.sccs_command = false;
690 line->body.line.command_template = default_rule;
691 line->body.line.target = true_target;
692 line->body.line.star = NULL;
693 line->body.line.less = true_target;
694 line->body.line.percent = NULL;
695 }
696 }
697
698 /* We say "target up to date" if no cmd were executed for the target */
699 if (!target->is_double_colon_parent) {
700 commands_done = false;
701 }
702
703 silent = silent_all;
857 recursion_level--;
858 if (target->is_member) {
859 Property member;
860
861 /* Propagate the timestamp from the member file to the member*/
862 if ((target->stat.time != file_max_time) &&
863 ((member = get_prop(target->prop, member_prop)) != NULL) &&
864 (exists(member->body.member.member) > file_doesnt_exist)) {
865 target->stat.time =
866 member->body.member.member->stat.time;
867 }
868 }
869 /*
870 * Check if we found any new auto dependencies when we
871 * built the target.
872 */
873 if ((result == build_ok) && check_auto_dependencies(target,
874 auto_count,
875 automatics)) {
876 if (debug_level > 0) {
877 (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
878 recursion_level,
879 "",
880 true_target->string_mb);
881 }
882 rechecking_target = true;
883 saved_commands_done = commands_done;
884 goto recheck_target;
885 }
886
887 if (rechecking_target && !commands_done) {
888 commands_done = saved_commands_done;
889 }
890
891 return result;
892 }
893
894 /*
895 * DONE.
896 *
897 * check_dependencies(result, line, do_get,
1010 break;
1011 case build_dont_know:
1012 /*
1013 * If make can't figure out how to make a dependency, maybe the dependency
1014 * is out of date. In this case, we just declare the target out of date
1015 * and go on. If we really need the dependency, the make'ing of the target
1016 * will fail. This will only happen for automatic (hidden) dependencies.
1017 */
1018 if(!recheck_conditionals) {
1019 line->body.line.is_out_of_date = true;
1020 }
1021 /*
1022 * Make sure the dependency is not saved
1023 * in the state file.
1024 */
1025 dependency->stale = true;
1026 rewrite_statefile =
1027 command_changed =
1028 true;
1029 if (debug_level > 0) {
1030 (void) printf(gettext("Target %s rebuilt because dependency %s does not exist\n"),
1031 true_target->string_mb,
1032 dependency->name->string_mb);
1033 }
1034 break;
1035 }
1036 if (dependency->name->depends_on_conditional) {
1037 target->depends_on_conditional = true;
1038 }
1039 if (dependency->name == force) {
1040 target->stat.time =
1041 dependency->name->stat.time;
1042 }
1043 /*
1044 * Propagate new timestamp from "member" to
1045 * "lib.a(member)".
1046 */
1047 (void) exists(dependency->name);
1048
1049 /* Collect the timestamp of the youngest dependency */
1050 line->body.line.dependency_time =
1051 MAX(dependency->name->stat.time,
1052 line->body.line.dependency_time);
1053
1054 /* Correction: do not consider nanosecs for members */
1055 if(true_target->is_member || dependency->name->is_member) {
1056 line->body.line.dependency_time.tv_nsec = 0;
1057 }
1058
1059 if (debug_level > 1) {
1060 (void) printf(gettext("%*sDate(%s)=%s \n"),
1061 recursion_level,
1062 "",
1063 dependency->name->string_mb,
1064 time_to_string(dependency->name->
1065 stat.time));
1066 if (dependency->name->stat.time > line->body.line.dependency_time) {
1067 (void) printf(gettext("%*sDate-dependencies(%s) set to %s\n"),
1068 recursion_level,
1069 "",
1070 true_target->string_mb,
1071 time_to_string(line->body.line.
1072 dependency_time));
1073 }
1074 }
1075
1076 /* Build the $? list */
1077 if (true_target->is_member) {
1078 if (this_dependency_changed == true) {
1079 true_target->stat.time = dependency->name->stat.time;
1080 true_target->stat.time.tv_sec--;
1081 } else {
1082 /* Dina:
1083 * The next statement is commented
1084 * out as a fix for bug #1051032.
1085 * if dependency hasn't changed
1086 * then there's no need to invalidate
1087 * true_target. This statemnt causes
1106 }
1107 if ((build_unconditional || out_of_date) &&
1108 (dependency->name != force) &&
1109 (dependency->stale == false)) {
1110 *out_of_date_tail = ALLOC(Chain);
1111 if (dependency->name->is_member &&
1112 (get_prop(dependency->name->prop,
1113 member_prop) != NULL)) {
1114 (*out_of_date_tail)->name =
1115 get_prop(dependency->name->prop,
1116 member_prop)->
1117 body.member.member;
1118 } else {
1119 (*out_of_date_tail)->name =
1120 dependency->name;
1121 }
1122 (*out_of_date_tail)->next = NULL;
1123 out_of_date_tail = &(*out_of_date_tail)->next;
1124 if (debug_level > 0) {
1125 if (dependency->name->stat.time == file_max_time) {
1126 (void) printf(gettext("%*sBuilding %s because %s does not exist\n"),
1127 recursion_level,
1128 "",
1129 true_target->string_mb,
1130 dependency->name->string_mb);
1131 } else {
1132 (void) printf(gettext("%*sBuilding %s because it is out of date relative to %s\n"),
1133 recursion_level,
1134 "",
1135 true_target->string_mb,
1136 dependency->name->string_mb);
1137 }
1138 }
1139 }
1140 if (dependency->name == force) {
1141 force->stat.time =
1142 file_max_time;
1143 force->state = build_dont_know;
1144 }
1145 }
1146 }
1147 if (dependencies_running) {
1148 if (doing_subtree) {
1149 if (target->conditional_cnt > 0) {
1150 reset_locals(target,
1151 old_locals,
1152 get_prop(target->prop,
1182 Property tmp_line;
1183
1184 if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1185 if(tmp_line->body.line.dependency_time != file_max_time) {
1186 target->stat.time =
1187 MAX(tmp_line->body.line.dependency_time,
1188 target->stat.time);
1189 }
1190 }
1191 }
1192 }
1193 if ((true_target->is_member) && (dependency_changed == true)) {
1194 true_target->stat.time = file_no_time;
1195 }
1196 /*
1197 * After scanning all the dependencies, we check the rule
1198 * if we found one.
1199 */
1200 if (line->body.line.command_template != NULL) {
1201 if (line->body.line.command_template_redefined) {
1202 warning(gettext("Too many rules defined for target %s"),
1203 target->string_mb);
1204 }
1205 *command = line;
1206 /* Check if the target is out of date */
1207 Boolean out_of_date;
1208 if (true_target->is_member) {
1209 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1210 line->body.line.dependency_time);
1211 } else {
1212 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1213 line->body.line.dependency_time);
1214 }
1215 if (build_unconditional || out_of_date){
1216 if(!recheck_conditionals) {
1217 line->body.line.is_out_of_date = true;
1218 }
1219 }
1220 line->body.line.sccs_command = false;
1221 line->body.line.target = true_target;
1222 if(gnu_style) {
1402 /* Create new dependency cell if */
1403 /* this is not the first dependency */
1404 /* picked from the expansion */
1405 if (!reuse_cell) {
1406 new_depe = ALLOC(Dependency);
1407 new_depe->next = dependency->next;
1408 new_depe->automatic = false;
1409 new_depe->stale = false;
1410 new_depe->built = false;
1411 dependency->next = new_depe;
1412 dependency = new_depe;
1413 }
1414 reuse_cell = false;
1415 /* Internalize the dependency name */
1416 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1417 // include "//" and "/./"
1418 //dependency->name = GETNAME(start, p - start);
1419 dependency->name = normalize_name(start, p - start);
1420 if ((debug_level > 0) &&
1421 (first_member == NULL)) {
1422 (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1423 recursion_level,
1424 "",
1425 dependency->name->string_mb,
1426 true_target->string_mb);
1427 }
1428 for (start = p; iswspace(*start); start++);
1429 p = start;
1430 }
1431 } while ((*p != (int) nul_char) &&
1432 (*p != (int) parenright_char));
1433 /* If the expansion was of lib.a(members) format we now */
1434 /* enter the proper member cells */
1435 if (first_member != NULL) {
1436 /* Scan the new dependencies and transform them from */
1437 /* "foo" to "lib.a(foo)" */
1438 for (; 1; first_member = first_member->next) {
1439 /* Build "lib.a(foo)" name */
1440 INIT_STRING_FROM_STACK(string, buffer);
1441 APPEND_NAME(lib,
1442 &string,
1443 (int) lib->hash.length);
1444 append_char((int) parenleft_char, &string);
1445 APPEND_NAME(first_member->name,
1446 &string,
1447 FIND_LENGTH);
1448 append_char((int) parenright_char, &string);
1449 member = first_member->name;
1450 /* Replace "foo" with "lib.a(foo)" */
1451 first_member->name =
1452 GETNAME(string.buffer.start, FIND_LENGTH);
1453 if (string.free_after_use) {
1454 retmem(string.buffer.start);
1455 }
1456 if (debug_level > 0) {
1457 (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1458 recursion_level,
1459 "",
1460 first_member->name->
1461 string_mb,
1462 true_target->string_mb);
1463 }
1464 first_member->name->is_member = lib->is_member;
1465 /* Add member property to member */
1466 prop = maybe_append_prop(first_member->name,
1467 member_prop);
1468 prop->body.member.library = lib;
1469 prop->body.member.entry = NULL;
1470 prop->body.member.member = member;
1471 if (first_member == dependency) {
1472 break;
1473 }
1474 }
1475 }
1476 }
1477 Wstring wcb;
1594 /* If quest, then exit(1) because the target is out of date */
1595 if (quest) {
1596 if (posix) {
1597 result = execute_parallel(line, true);
1598 }
1599 exit_status = 1;
1600 exit(1);
1601 }
1602 /* We actually had to do something this time */
1603 rewrite_statefile = commands_done = true;
1604 /*
1605 * If this is an sccs command, we have to do some extra checking
1606 * and possibly complain. If the file can't be gotten because it's
1607 * checked out, we complain and behave as if the command was
1608 * executed eventhough we ignored the command.
1609 */
1610 if (!touch &&
1611 line->body.line.sccs_command &&
1612 (target->stat.time != file_doesnt_exist) &&
1613 ((target->stat.mode & 0222) != 0)) {
1614 fatal(gettext("%s is writable so it cannot be sccs gotten"),
1615 target->string_mb);
1616 target->has_complained = remember_only = true;
1617 }
1618 /*
1619 * If KEEP_STATE is on, we make sure we have the timestamp for
1620 * .make.state. If .make.state changes during the command run,
1621 * we reread .make.state after the command. We also setup the
1622 * environment variable that asks utilities to report dependencies.
1623 */
1624 if (!touch &&
1625 keep_state &&
1626 !remember_only) {
1627 (void) exists(make_state);
1628 if((strlen(temp_file_directory) == 1) &&
1629 (temp_file_directory[0] == '/')) {
1630 tmp_file_path[0] = '\0';
1631 } else {
1632 strcpy(tmp_file_path, temp_file_directory);
1633 }
1634 sprintf(mbs_buffer,
1635 "%s/.make.dependency.%08x.%d.%d",
1636 tmp_file_path,
1637 hostid,
1638 getpid(),
1639 file_number++);
1640 MBSTOWCS(wcs_buffer, mbs_buffer);
1641 Boolean fnd;
1642 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1643 temp_file_name->stat.is_file = true;
1644 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1645 wchar_t *to = string = ALLOC_WC(len);
1646 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1647 if (*from == (int) space_char) {
1648 *to++ = (int) backslash_char;
1649 }
1650 *to++ = *from++;
1651 }
1652 *to++ = (int) space_char;
1653 MBSTOWCS(to, target->string_mb);
1654 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1655 (void) SETVAR(sunpro_dependencies,
1805 do_assign(rule->command_line, target);
1806 } else if (report_dependencies_level == 0) {
1807 /* Execute command line. */
1808 setvar_envvar();
1809 result = dosys(rule->command_line,
1810 (Boolean) rule->ignore_error,
1811 (Boolean) rule->make_refd,
1812 /* ds 98.04.23 bug #4085164. make should always show error messages */
1813 false,
1814 /* BOOLEAN(rule->silent &&
1815 rule->ignore_error), */
1816 (Boolean) rule->always_exec,
1817 target);
1818 check_state(temp_file_name);
1819 }
1820 } else {
1821 result = build_ok;
1822 }
1823 if (result == build_failed) {
1824 if (silent || rule->silent) {
1825 (void) printf(gettext("The following command caused the error:\n%s\n"),
1826 rule->command_line->string_mb);
1827 }
1828 if (!rule->ignore_error && !ignore_errors) {
1829 if (!continue_after_error) {
1830 fatal(gettext("Command failed for target `%s'"),
1831 target->string_mb);
1832 }
1833 /*
1834 * Make sure a failing command is not
1835 * saved in .make.state.
1836 */
1837 line->body.line.command_used = NULL;
1838 break;
1839 } else {
1840 result = build_ok;
1841 }
1842 }
1843 }
1844 for (rule = command; rule != NULL; rule = cmd_tail) {
1845 cmd_tail = rule->next;
1846 free(rule);
1847 }
1848 command = NULL;
1849 if (temp_file_name != NULL) {
1850 free_name(temp_file_name);
2088 while (iswspace(*string)) {
2089 string++;
2090 }
2091 equal = string;
2092 /* Find "+=" or "=". */
2093 while (!iswspace(*equal) &&
2094 (*equal != (int) plus_char) &&
2095 (*equal != (int) equal_char)) {
2096 equal++;
2097 }
2098 /* Internalize macro name. */
2099 name = GETNAME(string, equal - string);
2100 /* Skip over "+=" "=". */
2101 while (!((*equal == (int) nul_char) ||
2102 (*equal == (int) equal_char) ||
2103 (*equal == (int) plus_char))) {
2104 equal++;
2105 }
2106 switch (*equal) {
2107 case nul_char:
2108 fatal(gettext("= expected in rule `%s' for target `%s'"),
2109 line->string_mb,
2110 target->string_mb);
2111 case plus_char:
2112 append = true;
2113 equal++;
2114 break;
2115 }
2116 equal++;
2117 /* Skip over whitespace in front of value. */
2118 while (iswspace(*equal)) {
2119 equal++;
2120 }
2121 /* Enter new macro value. */
2122 enter_equal(name,
2123 GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2124 append);
2125 }
2126
2127 /*
2128 * build_command_strings(target, line)
2382 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2383 if (!used->ignore_command_dependency) {
2384 ignore_all_command_dependency = false;
2385 }
2386 /* Internalize the expanded and stripped command line */
2387 new_command_line = GETNAME(start, FIND_LENGTH);
2388 if ((used->command_line == NULL) &&
2389 (line->body.line.sccs_command)) {
2390 used->command_line = new_command_line;
2391 new_command_longer = false;
2392 }
2393 /* Compare it with the old one for command consistency */
2394 if (used->command_line != new_command_line) {
2395 Name vpath_translated = vpath_translation(new_command_line);
2396 if (keep_state &&
2397 !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2398 if (debug_level > 0) {
2399 if (used->command_line != NULL
2400 && *used->command_line->string_mb !=
2401 '\0') {
2402 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2403 recursion_level,
2404 "",
2405 target->string_mb,
2406 vpath_translated->string_mb,
2407 recursion_level,
2408 "",
2409 used->
2410 command_line->
2411 string_mb);
2412 } else {
2413 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2414 recursion_level,
2415 "",
2416 target->string_mb,
2417 vpath_translated->string_mb,
2418 recursion_level,
2419 "");
2420 }
2421 }
2422 command_changed = true;
2423 line->body.line.is_out_of_date = true;
2424 }
2425 used->command_line = new_command_line;
2426 }
2427 if (command_line.free_after_use) {
2428 retmem(command_line.buffer.start);
2429 }
2430 }
2431 /* Check if the old command is longer than the new for */
2432 /* command consistency */
2433 if (used != NULL) {
2434 *insert = NULL;
2435 if (keep_state &&
2436 !ignore_all_command_dependency) {
2437 if (debug_level > 0) {
2438 (void) printf(gettext("%*sBuilding %s because new command shorter than old\n"),
2439 recursion_level,
2440 "",
2441 target->string_mb);
2442 }
2443 command_changed = true;
2444 line->body.line.is_out_of_date = true;
2445 }
2446 }
2447 /* Check if the new command is longer than the old command for */
2448 /* command consistency */
2449 if (new_command_longer &&
2450 !ignore_all_command_dependency &&
2451 keep_state) {
2452 if (debug_level > 0) {
2453 (void) printf(gettext("%*sBuilding %s because new command longer than old\n"),
2454 recursion_level,
2455 "",
2456 target->string_mb);
2457 }
2458 command_changed = true;
2459 line->body.line.is_out_of_date = true;
2460 }
2461 /* Unbind the magic macros */
2462 (void) SETVAR(c_at, (Name) NULL, false);
2463 (void) SETVAR(star, (Name) NULL, false);
2464 (void) SETVAR(less_name, (Name) NULL, false);
2465 (void) SETVAR(percent_name, (Name) NULL, false);
2466 (void) SETVAR(query, (Name) NULL, false);
2467 if (query_list != NULL) {
2468 delete_query_chain(query_list);
2469 }
2470 (void) SETVAR(hat, (Name) NULL, false);
2471 if (hat_list != NULL) {
2472 delete_query_chain(hat_list);
2473 }
2499 */
2500 static Doname
2501 touch_command(register Property line, register Name target, Doname result)
2502 {
2503 Name name;
2504 register Chain target_group;
2505 String_rec touch_string;
2506 wchar_t buffer[MAXPATHLEN];
2507 Name touch_cmd;
2508 Cmd_line rule;
2509
2510 for (name = target, target_group = NULL; name != NULL;) {
2511 if (!name->is_member) {
2512 /*
2513 * Build a touch command that can be passed
2514 * to dosys(). If KEEP_STATE is on, "make -t"
2515 * will save the proper command, not the
2516 * "touch" in .make.state.
2517 */
2518 INIT_STRING_FROM_STACK(touch_string, buffer);
2519 MBSTOWCS(wcs_buffer, "touch ");
2520 append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2521 touch_cmd = name;
2522 if (name->has_vpath_alias_prop) {
2523 touch_cmd = get_prop(name->prop,
2524 vpath_alias_prop)->
2525 body.vpath_alias.alias;
2526 }
2527 APPEND_NAME(touch_cmd,
2528 &touch_string,
2529 FIND_LENGTH);
2530 touch_cmd = GETNAME(touch_string.buffer.start,
2531 FIND_LENGTH);
2532 if (touch_string.free_after_use) {
2533 retmem(touch_string.buffer.start);
2534 }
2535 if (!silent ||
2536 do_not_exec_rule &&
2537 (target_group == NULL)) {
2538 (void) printf("%s\n", touch_cmd->string_mb);
2539 }
2664 * Global variables used:
2665 * debug_level Should we trace activities?
2666 * recursion_level Used for tracing
2667 * sccs_get_rule The rule to used for sccs getting
2668 */
2669 static Doname
2670 sccs_get(register Name target, register Property *command)
2671 {
2672 register int result;
2673 char link[MAXPATHLEN];
2674 String_rec string;
2675 wchar_t name[MAXPATHLEN];
2676 register wchar_t *p;
2677 timestruc_t sccs_time;
2678 register Property line;
2679 int sym_link_depth = 0;
2680
2681 /* For sccs, we need to chase symlinks. */
2682 while (target->stat.is_sym_link) {
2683 if (sym_link_depth++ > 90) {
2684 fatal(gettext("Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2685 target->string_mb);
2686 }
2687 /* Read the value of the link. */
2688 result = readlink_vroot(target->string_mb,
2689 link,
2690 sizeof(link),
2691 NULL,
2692 VROOT_DEFAULT);
2693 if (result == -1) {
2694 fatal(gettext("Can't read symbolic link `%s': %s"),
2695 target->string_mb, errmsg(errno));
2696 }
2697 link[result] = 0;
2698 /* Use the value to build the proper filename. */
2699 INIT_STRING_FROM_STACK(string, name);
2700
2701 Wstring wcb(target);
2702 if ((link[0] != slash_char) &&
2703 ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) {
2704 append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2705 }
2706 append_string(link, &string, result);
2707 /* Replace the old name with the translated name. */
2708 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2709 (void) exists(target);
2710 if (string.free_after_use) {
2711 retmem(string.buffer.start);
2712 }
2713 }
2714
2746 if ((!target->has_complained &&
2747 (sccs_time != file_doesnt_exist) &&
2748 (sccs_get_rule != NULL))) {
2749 /* only checking */
2750 if (command == NULL) {
2751 return build_ok;
2752 }
2753 /*
2754 * We provide a command line for the target. The line is a
2755 * "sccs get" command from default.mk.
2756 */
2757 line = maybe_append_prop(target, line_prop);
2758 *command = line;
2759 if (sccs_time > target->stat.time) {
2760 /*
2761 * And only if the plain file is out of date do we
2762 * request execution of the command.
2763 */
2764 line->body.line.is_out_of_date = true;
2765 if (debug_level > 0) {
2766 (void) printf(gettext("%*sSccs getting %s because s. file is younger than source file\n"),
2767 recursion_level,
2768 "",
2769 target->string_mb);
2770 }
2771 }
2772 line->body.line.sccs_command = true;
2773 line->body.line.command_template = sccs_get_rule;
2774 if(!svr4 && (!allrules_read || posix)) {
2775 if((target->prop) &&
2776 (target->prop->body.sccs.file) &&
2777 (target->prop->body.sccs.file->string_mb)) {
2778 if((strlen(target->prop->body.sccs.file->string_mb) ==
2779 strlen(target->string_mb) + 2) &&
2780 (target->prop->body.sccs.file->string_mb[0] == 's') &&
2781 (target->prop->body.sccs.file->string_mb[1] == '.')) {
2782
2783 line->body.line.command_template = get_posix_rule;
2784 }
2785 }
2786 }
2808 * Global variables used:
2809 * dot The Name ".", used as the default dir
2810 */
2811 void
2812 read_directory_of_file(register Name file)
2813 {
2814
2815 Wstring file_string(file);
2816 wchar_t * wcb = file_string.get_string();
2817 wchar_t usr_include_buf[MAXPATHLEN];
2818 wchar_t usr_include_sys_buf[MAXPATHLEN];
2819
2820 register Name directory = dot;
2821 register wchar_t *p = (wchar_t *) wsrchr(wcb,
2822 (int) slash_char);
2823 register int length = p - wcb;
2824 static Name usr_include;
2825 static Name usr_include_sys;
2826
2827 if (usr_include == NULL) {
2828 MBSTOWCS(usr_include_buf, "/usr/include");
2829 usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
2830 MBSTOWCS(usr_include_sys_buf, "/usr/include/sys");
2831 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
2832 }
2833
2834 /*
2835 * If the filename contains a "/" we have to extract the path
2836 * Else the path defaults to ".".
2837 */
2838 if (p != NULL) {
2839 /*
2840 * Check some popular directories first to possibly
2841 * save time. Compare string length first to gain speed.
2842 */
2843 if ((usr_include->hash.length == length) &&
2844 IS_WEQUALN(usr_include_buf,
2845 wcb,
2846 length)) {
2847 directory = usr_include;
2848 } else if ((usr_include_sys->hash.length == length) &&
2849 IS_WEQUALN(usr_include_sys_buf,
2850 wcb,
2943 register Boolean saved_conditional_macro_used;
2944 Chain cond_name;
2945 Chain cond_chain;
2946
2947 if (target->dont_activate_cond_values) {
2948 return;
2949 }
2950
2951 saved_conditional_macro_used = conditional_macro_used;
2952
2953 /* Scan the list of conditional properties and apply each one */
2954 for (conditional = get_prop(target->prop, conditional_prop), i = 0;
2955 conditional != NULL;
2956 conditional = get_prop(conditional->next, conditional_prop),
2957 i++) {
2958 /* Save the old value */
2959 old_locals[i].body.macro =
2960 maybe_append_prop(conditional->body.conditional.name,
2961 macro_prop)->body.macro;
2962 if (debug_level > 1) {
2963 (void) printf(gettext("%*sActivating conditional value: "),
2964 recursion_level,
2965 "");
2966 }
2967 /* Set the conditional value. Macros are expanded when the */
2968 /* macro is refd as usual */
2969 if ((conditional->body.conditional.name != virtual_root) ||
2970 (conditional->body.conditional.value != virtual_root)) {
2971 (void) SETVAR(conditional->body.conditional.name,
2972 conditional->body.conditional.value,
2973 (Boolean) conditional->body.conditional.append);
2974 }
2975 cond_name = ALLOC(Chain);
2976 cond_name->name = conditional->body.conditional.name;
2977 }
2978 /* Put this target on the front of the chain of conditional targets */
2979 cond_chain = ALLOC(Chain);
2980 cond_chain->name = target;
2981 cond_chain->next = conditional_targets;
2982 conditional_targets = cond_chain;
2983 conditional_macro_used = saved_conditional_macro_used;
2999 */
3000 void
3001 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3002 {
3003 register Property this_conditional;
3004 Chain cond_chain;
3005
3006 if (target->dont_activate_cond_values) {
3007 return;
3008 }
3009
3010 /* Scan the list of conditional properties and restore the old value */
3011 /* to each one Reverse the order relative to when we assigned macros */
3012 this_conditional = get_prop(conditional->next, conditional_prop);
3013 if (this_conditional != NULL) {
3014 reset_locals(target, old_locals, this_conditional, index+1);
3015 } else {
3016 /* Remove conditional target from chain */
3017 if (conditional_targets == NULL ||
3018 conditional_targets->name != target) {
3019 warning(gettext("Internal error: reset target not at head of condtional_targets chain"));
3020 } else {
3021 cond_chain = conditional_targets->next;
3022 retmem_mb((caddr_t) conditional_targets);
3023 conditional_targets = cond_chain;
3024 }
3025 }
3026 get_prop(conditional->body.conditional.name->prop,
3027 macro_prop)->body.macro = old_locals[index].body.macro;
3028 if (conditional->body.conditional.name == virtual_root) {
3029 (void) SETVAR(virtual_root, getvar(virtual_root), false);
3030 }
3031 if (debug_level > 1) {
3032 if (old_locals[index].body.macro.value != NULL) {
3033 (void) printf(gettext("%*sdeactivating conditional value: %s= %s\n"),
3034 recursion_level,
3035 "",
3036 conditional->body.conditional.name->
3037 string_mb,
3038 old_locals[index].body.macro.value->
3039 string_mb);
3040 } else {
3041 (void) printf(gettext("%*sdeactivating conditional value: %s =\n"),
3042 recursion_level,
3043 "",
3044 conditional->body.conditional.name->
3045 string_mb);
3046 }
3047 }
3048 }
3049
3050 /*
3051 * check_auto_dependencies(target, auto_count, automatics)
3052 *
3053 * Returns true if the target now has a dependency
3054 * it didn't previously have (saved on automatics).
3055 *
3056 * Return value:
3057 * true if new dependency found
3058 *
3059 * Parameters:
3060 * target Target we check
3061 * auto_count Number of old automatic vars
|