aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-10-18 15:00:36 +0100
committerRon Yorston <rmy@pobox.com>2022-10-18 15:00:36 +0100
commit92a127e9f96598b86a4327b70783b9769eaa94fe (patch)
tree16405c528c5d5712fc1784dfdb5477567592d201
parentb749a2c0eb47b648805500c23ffbe4550e976a57 (diff)
downloadbusybox-w32-92a127e9f96598b86a4327b70783b9769eaa94fe.tar.gz
busybox-w32-92a127e9f96598b86a4327b70783b9769eaa94fe.tar.bz2
busybox-w32-92a127e9f96598b86a4327b70783b9769eaa94fe.zip
make: support $+ and $^ as POSIX 202X features
Austin Group defect reports 514 and 1520 have both been accepted. Together these introduce the internal macros $+ and $^: - $+ lists all prerequisites, with duplicates retained; - $^ lists all prerequisites, with duplicates removed. $^ had already been implemented as a non-POSIX extension, it now becomes a POSIX 202X extension. $+ has been added as a POSIX 202X extension. Neither of the above defect reports mentions how $? should handle duplicate prerequisites. In POSIX mode duplicates are retained. Removal of duplicates is implemented as a non-POSIX extension to match existing practice in other versions of make.
-rw-r--r--miscutils/make.c33
-rwxr-xr-xtestsuite/make.tests12
2 files changed, 31 insertions, 14 deletions
diff --git a/miscutils/make.c b/miscutils/make.c
index 21d0ede51..8e3778461 100644
--- a/miscutils/make.c
+++ b/miscutils/make.c
@@ -1927,15 +1927,17 @@ touch(struct name *np)
1927 1927
1928static int 1928static int
1929make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, 1929make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc,
1930 struct name *implicit) 1930 char *dedup, struct name *implicit)
1931{ 1931{
1932 int estat = 0; // 0 exit status is success 1932 int estat = 0; // 0 exit status is success
1933 char *name, *member = NULL, *base; 1933 char *name, *member = NULL, *base;
1934 1934
1935 name = splitlib(np->n_name, &member); 1935 name = splitlib(np->n_name, &member);
1936 setmacro("?", oodate, 0 | M_VALID); 1936 setmacro("?", oodate, 0 | M_VALID);
1937 if (!posix) 1937 if (!posix) {
1938 setmacro("^", allsrc, 0 | M_VALID); 1938 setmacro("+", allsrc, 0 | M_VALID);
1939 setmacro("^", dedup, 0 | M_VALID);
1940 }
1939 setmacro("%", member, 0 | M_VALID); 1941 setmacro("%", member, 0 | M_VALID);
1940 setmacro("@", name, 0 | M_VALID); 1942 setmacro("@", name, 0 | M_VALID);
1941 if (implicit) { 1943 if (implicit) {
@@ -1993,6 +1995,7 @@ make(struct name *np, int level)
1993 struct cmd *sc_cmd = NULL; // commands for single-colon rule 1995 struct cmd *sc_cmd = NULL; // commands for single-colon rule
1994 char *oodate = NULL; 1996 char *oodate = NULL;
1995 char *allsrc = NULL; 1997 char *allsrc = NULL;
1998 char *dedup = NULL;
1996 struct timespec dtim = {1, 0}; 1999 struct timespec dtim = {1, 0};
1997 bool didsomething = 0; 2000 bool didsomething = 0;
1998 bool estat = 0; // 0 exit status is success 2001 bool estat = 0; // 0 exit status is success
@@ -2080,17 +2083,17 @@ make(struct name *np, int level)
2080 // Make prerequisite 2083 // Make prerequisite
2081 estat |= make(dp->d_name, level + 1); 2084 estat |= make(dp->d_name, level + 1);
2082 2085
2083 // Make strings of out-of-date prerequisites (for $?) 2086 // Make strings of out-of-date prerequisites (for $?),
2084 // and all prerequisites (for $^). But not if we were 2087 // all prerequisites (for $+) and deduplicated prerequisites
2085 // invoked with -q. 2088 // (for $^). But not if we were invoked with -q.
2086 if (!quest 2089 if (!quest) {
2087 // Skip duplicate entries.
2088 && (posix || !(dp->d_name->n_flag & N_MARK))
2089 ) {
2090 if (timespec_le(&np->n_tim, &dp->d_name->n_tim)) { 2090 if (timespec_le(&np->n_tim, &dp->d_name->n_tim)) {
2091 oodate = xappendword(oodate, dp->d_name->n_name); 2091 if (posix || !(dp->d_name->n_flag & N_MARK))
2092 oodate = xappendword(oodate, dp->d_name->n_name);
2092 } 2093 }
2093 allsrc = xappendword(allsrc, dp->d_name->n_name); 2094 allsrc = xappendword(allsrc, dp->d_name->n_name);
2095 if (!(dp->d_name->n_flag & N_MARK))
2096 dedup = xappendword(dedup, dp->d_name->n_name);
2094 dp->d_name->n_flag |= N_MARK; 2097 dp->d_name->n_flag |= N_MARK;
2095 } 2098 }
2096 dtim = *timespec_max(&dtim, &dp->d_name->n_tim); 2099 dtim = *timespec_max(&dtim, &dp->d_name->n_tim);
@@ -2099,7 +2102,7 @@ make(struct name *np, int level)
2099 if (!quest && ((np->n_flag & N_PHONY) || 2102 if (!quest && ((np->n_flag & N_PHONY) ||
2100 timespec_le(&np->n_tim, &dtim))) { 2103 timespec_le(&np->n_tim, &dtim))) {
2101 if (estat == 0) { 2104 if (estat == 0) {
2102 estat = make1(np, rp->r_cmd, oodate, allsrc, locdep); 2105 estat = make1(np, rp->r_cmd, oodate, allsrc, dedup, locdep);
2103 dtim = (struct timespec){1, 0}; 2106 dtim = (struct timespec){1, 0};
2104 didsomething = 1; 2107 didsomething = 1;
2105 } 2108 }
@@ -2107,7 +2110,8 @@ make(struct name *np, int level)
2107 oodate = NULL; 2110 oodate = NULL;
2108 } 2111 }
2109 free(allsrc); 2112 free(allsrc);
2110 allsrc = NULL; 2113 free(dedup);
2114 allsrc = dedup = NULL;
2111 if (locdep) { 2115 if (locdep) {
2112 rp->r_dep = rp->r_dep->d_next; 2116 rp->r_dep = rp->r_dep->d_next;
2113 rp->r_cmd = NULL; 2117 rp->r_cmd = NULL;
@@ -2132,7 +2136,7 @@ make(struct name *np, int level)
2132 if (!doinclude) 2136 if (!doinclude)
2133 bb_error_msg("nothing to be done for %s", np->n_name); 2137 bb_error_msg("nothing to be done for %s", np->n_name);
2134 } else { 2138 } else {
2135 estat = make1(np, sc_cmd, oodate, allsrc, impdep); 2139 estat = make1(np, sc_cmd, oodate, allsrc, dedup, impdep);
2136 clock_gettime(CLOCK_REALTIME, &np->n_tim); 2140 clock_gettime(CLOCK_REALTIME, &np->n_tim);
2137 } 2141 }
2138 } else if (!doinclude) { 2142 } else if (!doinclude) {
@@ -2145,6 +2149,7 @@ make(struct name *np, int level)
2145 printf("%s: '%s' is up to date\n", applet_name, np->n_name); 2149 printf("%s: '%s' is up to date\n", applet_name, np->n_name);
2146 } 2150 }
2147 free(allsrc); 2151 free(allsrc);
2152 free(dedup);
2148 return estat; 2153 return estat;
2149} 2154}
2150 2155
diff --git a/testsuite/make.tests b/testsuite/make.tests
index 3d0d14dd0..67617f8a2 100755
--- a/testsuite/make.tests
+++ b/testsuite/make.tests
@@ -255,6 +255,18 @@ mk:
255-include mk 255-include mk
256' 256'
257 257
258# $^ skips duplicate prerequisites, $+ doesn't
259mkdir make.tempdir && cd make.tempdir || exit 1
260touch file1 file2 file3
261testing "make skip duplicate entries in \$^ but not \$+" \
262 "make -f -" \
263 "file1 file2 file3\nfile1 file2 file2 file3 file3\n" "" '
264target: file1 file2 file2 file3 file3
265 @echo $^
266 @echo $+
267'
268cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
269
258# Nested macro expansion is allowed. This should be compatible 270# Nested macro expansion is allowed. This should be compatible
259# with other implementations. 271# with other implementations.
260testing "make nested macro expansion" \ 272testing "make nested macro expansion" \