summaryrefslogtreecommitdiff
path: root/src/rule.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2022-09-12 18:18:49 -0400
committerPaul Smith <psmith@gnu.org>2022-09-12 18:35:29 -0400
commitf6ea899d83bf00fe9201fde0ca9cf7af8e443677 (patch)
tree62f8077c6c3e9aac1c2a4c18f7ebcc619d6cfbcb /src/rule.c
parentee861a4e9f523d06d26ed612ad1a93b6ecb408de (diff)
downloadmake-git-f6ea899d83bf00fe9201fde0ca9cf7af8e443677.tar.gz
[SV 13862] Implement the .WAIT special target
The next version of the POSIX standard defines parallel execution and requires the .WAIT special target as is implemented in some other versions of make. This implementation behaves similarly to others in that it does not create a relationship between targets in the dependency graph, so that the same two targets may be run in parallel if they appear as prerequisites elsewhere without .WAIT between them. Now that we support .WAIT it's trivial to also support prerequisites of the .NOTPARALLEL special target, which forces the prerequisites of those targets to be run serially (as if .WAIT was specified between each one). * NEWS: Announce the new .WAIT and .NOTPARALLEL support. * doc/make.texi (Parallel Disable): A new section to discuss ways in which parallel execution can be controlled. Modify cross-refs to refer to this section. * src/dep.h (struct dep): Add a new wait_here boolean. (parse_file_seq): Add PARSEFS_WAIT to check for .WAIT dependencies. * src/file.c (split_prereqs): Use PARSEFS_WAIT. (snap_deps): If .NOTPARALLEL has prerequisites, set .WAIT between each of _their_ prerequisites. (print_prereqs): Add back in .WAIT when printing prerequisites. * src/implicit.c (struct patdeps): Preserve wait_here. (pattern_search): Ditto. Use PARSEFS_WAIT when parsing prereqs for pattern rule expansion. * src/read.c (check_specials): Don't give up early: remembering to update these options is not worth the rare speedup. (check_special_file): If .WAIT is given as a target show an error-- once--if it has prereqs or commands. (record_files): Call check_special_file on each target. (parse_file_seq): If PARSEFS_WAIT is given, look for .WAIT prereqs. If we see one assume that we are building a struct dep chain and set the wait_here option while not putting it into the list. * src/remake.c (update_file_1): If wait_here is set and we are still running, then stop trying to build this target's prerequisites. * src/rule.c (get_rule_defn): Add .WAIT to the prerequisite list. * src/shuffle.c (shuffle_deps): Don't shuffle the prerequisite list if .WAIT appears anywhere in it. * tests/scripts/targets/WAIT: Add a test suite for this feature.
Diffstat (limited to 'src/rule.c')
-rw-r--r--src/rule.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/src/rule.c b/src/rule.c
index a491b83d..d4d28fa2 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -65,21 +65,22 @@ static size_t maxsuffix;
space separated rule prerequisites, followed by a pipe, followed by
order-only prerequisites, if present. */
-const char *get_rule_defn (struct rule *r)
+const char *
+get_rule_defn (struct rule *r)
{
if (r->_defn == NULL)
{
+ size_t len = 8; /* Reserve for ":: ", " | ", and nul. */
unsigned int k;
- ptrdiff_t len = 8; // Reserve for ":: ", " | " and the null terminator.
char *p;
const char *sep = "";
const struct dep *dep, *ood = 0;
for (k = 0; k < r->num; ++k)
- len += r->lens[k] + 1; // Add one for a space.
+ len += r->lens[k] + 1;
for (dep = r->deps; dep; dep = dep->next)
- len += strlen (dep_name (dep)) + 1; // Add one for a space.
+ len += strlen (dep_name (dep)) + (dep->wait_here ? CSTRLEN (" .WAIT") : 0) + 1;
p = r->_defn = xmalloc (len);
for (k = 0; k < r->num; ++k, sep = " ")
@@ -91,18 +92,25 @@ const char *get_rule_defn (struct rule *r)
/* Copy all normal dependencies; note any order-only deps. */
for (dep = r->deps; dep; dep = dep->next)
if (dep->ignore_mtime == 0)
- p = mempcpy (mempcpy (p, " ", 1), dep_name (dep),
- strlen (dep_name (dep)));
+ {
+ if (dep->wait_here)
+ p = mempcpy (p, STRING_SIZE_TUPLE (" .WAIT"));
+ p = mempcpy (mempcpy (p, " ", 1), dep_name (dep),
+ strlen (dep_name (dep)));
+ }
else if (ood == 0)
ood = dep;
/* Copy order-only deps, if we have any. */
for (sep = " | "; ood; ood = ood->next, sep = " ")
if (ood->ignore_mtime)
- p = mempcpy (mempcpy (p, sep, strlen (sep)), dep_name (ood),
- strlen (dep_name (ood)));
+ {
+ p = mempcpy (p, sep, strlen (sep));
+ if (ood->wait_here)
+ p = mempcpy (p, STRING_SIZE_TUPLE (".WAIT "));
+ p = mempcpy (p, dep_name (ood), strlen (dep_name (ood)));
+ }
*p = '\0';
- assert (p - r->_defn < len);
}
return r->_defn;