dep.h | 1 + file.c | 26 +++++++++++++++++++++++++ job.c | 2 ++ main.c | 14 ++++++++++++++ make.h | 1 + read.c | 7 ++++++- remake.c | 28 +++++++++++++++++++++++++++ tests/scripts/features/sun-targetvars | 23 ++++++++++++++++++++++ tests/scripts/features/sun-wait | 34 +++++++++++++++++++++++++++++++++ variable.c | 3 +++ 10 files changed, 138 insertions(+), 1 deletion(-) diff --git a/dep.h b/dep.h index c27423b..250cd55 100644 --- a/dep.h +++ b/dep.h @@ -44,6 +44,7 @@ struct dep unsigned int staticpattern : 1; unsigned int need_2nd_expansion : 1; unsigned int dontcare : 1; + unsigned int wait : 1; }; diff --git a/file.c b/file.c index 0a4edb2..949bced 100644 --- a/file.c +++ b/file.c @@ -454,6 +454,29 @@ split_prereqs (char *p) return new; } + + +/* Notice special dependencies. */ +static void +notice_special_deps(struct dep **d_ptr) +{ + struct dep *d; + +restart_loop: + for (; *d_ptr; d_ptr = &(*d_ptr)->next) + { + d = *d_ptr; + if (!strcmp(d->name, ".WAIT")) + { + if (d->next) + d->next->wait = 1; + *d_ptr = d->next; + free_dep(d); + goto restart_loop; + } + } +} + /* Given a list of prerequisites, enter them into the file database. If STEM is set then first expand patterns using STEM. */ struct dep * @@ -517,6 +540,9 @@ enter_prereqs (struct dep *deps, const char *stem) } } + if (sun_flag) + notice_special_deps(&deps); + /* Enter them as files, unless they need a 2nd expansion. */ for (d1 = deps; d1 != 0; d1 = d1->next) { diff --git a/job.c b/job.c index aacfb84..153772e 100644 --- a/job.c +++ b/job.c @@ -1056,6 +1056,8 @@ start_job_command (struct child *child) flags |= COMMANDS_RECURSE; else if (*p == '-') child->noerror = 1; + else if (sun_flag && (*p == '?')) /* ignored */ + ; else if (!isblank ((unsigned char)*p)) break; ++p; diff --git a/main.c b/main.c index c6989e3..7931f11 100644 --- a/main.c +++ b/main.c @@ -207,6 +207,10 @@ int inhibit_print_directory_flag = 0; int print_version_flag = 0; +/* Enable SunOS make syntax and features. */ + +int sun_flag = 0; + /* List of makefiles given with -f switches. */ static struct stringlist *makefiles = 0; @@ -368,6 +372,8 @@ static const char *const usage[] = Consider FILE to be infinitely new.\n"), N_("\ --warn-undefined-variables Warn when an undefined variable is referenced.\n"), + N_("\ + --sun Enable syntax and features of SunOS make.\n"), NULL }; @@ -424,6 +430,7 @@ static const struct command_switch switches[] = { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0, "warn-undefined-variables" }, { CHAR_MAX+6, string, &eval_strings, 1, 0, 0, 0, 0, "eval" }, + { CHAR_MAX+7, flag, &sun_flag, 1, 0, 0, 0, 0, "sun" }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -1347,7 +1354,10 @@ main (int argc, char **argv, char **envp) /* The extra indirection through $(MAKE_COMMAND) is done for hysterical raisins. */ define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0); + if (!sun_flag) define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1); + else + define_variable_cname ("MAKE", "$(MAKE_COMMAND) --sun", o_default, 1); if (command_variables != 0) { @@ -1453,6 +1463,10 @@ main (int argc, char **argv, char **envp) if (no_builtin_variables_flag) no_builtin_rules_flag = 1; + /* SunOS make always use second expansion */ + if (sun_flag) + second_expansion = 1; + /* Construct the list of include directories to search. */ construct_include_path (include_directories == 0 diff --git a/make.h b/make.h index 60ade4c..c7da9aa 100644 --- a/make.h +++ b/make.h @@ -514,6 +514,7 @@ extern int print_version_flag, print_directory_flag, check_symlink_flag; extern int warn_undefined_variables_flag, posix_pedantic, not_parallel; extern int second_expansion, clock_skew_detected, rebuilding_makefiles; extern int one_shell; +extern int sun_flag; /* can we run commands via 'sh -c xxx' or must we use batch files? */ extern int batch_mode_shell; diff --git a/read.c b/read.c index a3ad88e..5b9d03a 100644 --- a/read.c +++ b/read.c @@ -1052,6 +1052,10 @@ eval (struct ebuffer *ebuf, int set_default) if (two_colon) p2++; + /* In sunmake mode ":=" means target-specific variable, not ":" */ + if (sun_flag && (*p2 == '=')) + p2++; + /* Test to see if it's a target-specific variable. Copy the rest of the buffer over, possibly temporarily (we'll expand it later if it's not a target-specific variable). PLEN saves the length @@ -2514,7 +2518,8 @@ get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length) case '=': ++p; - wtype = w_varassign; + /* In sunmake mode ":=" acts as ":" in normal mode */ + wtype = sun_flag ? w_colon : w_varassign; break; } break; diff --git a/remake.c b/remake.c index 27d2550..c1206e0 100644 --- a/remake.c +++ b/remake.c @@ -397,6 +397,19 @@ complain (struct file *file) } } +/* Mark the dependencies as considered in this pass (to avoid skipping them + on the next pass). */ +static void +consider_deps (struct dep *d) +{ + for (; d; d = d->next) + { + if (d->file->considered != considered) + consider_deps (d->file->deps); + d->file->considered = considered; + } +} + /* Consider a single `struct file' and update it as appropriate. */ static int @@ -525,6 +538,13 @@ update_file_1 (struct file *file, unsigned int depth) int maybe_make; int dontcare = 0; + /* The code below will set the state to cs_deps_running. */ + if (d->wait && running) + { + consider_deps(d); + break; + } + check_renamed (d->file); mtime = file_mtime (d->file); @@ -599,6 +619,13 @@ update_file_1 (struct file *file, unsigned int depth) if (must_make || always_make_flag) { for (d = file->deps; d != 0; d = d->next) + { + /* The code below will set the state to cs_deps_running. */ + if (d->wait && running) + { + consider_deps(d); + break; + } if (d->file->intermediate) { int dontcare = 0; @@ -643,6 +670,7 @@ update_file_1 (struct file *file, unsigned int depth) d->changed = ((file->phony && file->cmds != 0) || file_mtime (d->file) != mtime); } + } } finish_updating (file); diff --git a/tests/scripts/features/sun-targetvars b/tests/scripts/features/sun-targetvars new file mode 100644 index 0000000..157973b --- /dev/null +++ b/tests/scripts/features/sun-targetvars @@ -0,0 +1,23 @@ +# -*-perl-*- +$description = "Check SunOS make target-specific assignment."; + +$details = "In SunOS make mode ':=' is used for target-specific variable, instead of ':' +Thus, ':=' cannot be used as variable assignment at all."; + +# SunOS make mode, $(other) is undefined: +run_make_test(' +FOO = true +all: other + @echo $(FOO) +other := FOO = false +other: + @echo $(FOO) $(other) +', +'--sun', +"false\ntrue\n"); + +# Same file, but in normal mode, $(other) is "FOO = false": +run_make_test(undef, '', "true FOO = false\ntrue\n"); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/tests/scripts/features/sun-wait b/tests/scripts/features/sun-wait new file mode 100644 index 0000000..bc2fab6 --- /dev/null +++ b/tests/scripts/features/sun-wait @@ -0,0 +1,34 @@ +# -*-perl-*- +$description = "Check .WAIT special target"; + +$details = ""; + +run_make_test(' +one: + @sleep 2; echo $@ +two: + @echo $@ + +three: one .WAIT two + @echo $@ + +four: one two + @echo $@ + +', +'--sun three', # note: one job +"one\ntwo\nthree"); + +# Same file, but 3 jobs, must be the same result due to .WAIT: +run_make_test(undef, '--sun -j3 three', "one\ntwo\nthree"); + +# Same file, but "two" should not depend on "one": +run_make_test(undef, '--sun two', "two"); + +# Same file, but "two" should end earlier: +run_make_test(undef, '--sun -j3 four', "two\none\nfour"); +# Same file, but "two" should end earlier even in mornal mode ;-) +run_make_test(undef, '-j3 four', "two\none\nfour"); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/variable.c b/variable.c index 915be20..cefa765 100644 --- a/variable.c +++ b/variable.c @@ -1422,6 +1422,9 @@ parse_variable_definition (const char *p, enum variable_flavor *flavor) switch (c) { case ':': + /* In sunmake mode ":=" is not a variable assignment */ + if (sun_flag) + return NULL; *flavor = f_simple; break; case '+':