diff options
author | Ron Yorston <rmy@pobox.com> | 2024-05-28 11:54:51 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-05-28 11:54:51 +0100 |
commit | 208d9858409f823d533d1e95396dde00be03d7d3 (patch) | |
tree | 34c0ea21c8d1b23c2bc72909843b12bd1c0cb9ca | |
parent | 0224cfd5e5c8157e5bc74a81027fa508687abfbf (diff) | |
download | busybox-w32-208d9858409f823d533d1e95396dde00be03d7d3.tar.gz busybox-w32-208d9858409f823d533d1e95396dde00be03d7d3.tar.bz2 busybox-w32-208d9858409f823d533d1e95396dde00be03d7d3.zip |
make: fixes to -t option
The -t option (in general) causes targets to be touched instead of
having build commands run to create them. There were two problems.
The flag variable 'ssilent' in docmds was too small (uint8_t) to
contain the value of 'dotouch' (uint32_t). Truncation of the
value resulted in build commands being echoed when they shouldn't
have been.
The POSIX specification is unclear as to how build commands with
a '+' prefix interact with touch. The rationale indicates that
this feature was imported from GNU make, so the behaviour has been
made to match what it does: if a '+' build command is run the
target is not touched.
The code has been rearranged to move the call to touch() up into
docmds().
Adds 48 bytes.
-rw-r--r-- | miscutils/make.c | 67 | ||||
-rwxr-xr-x | testsuite/make.tests | 26 |
2 files changed, 60 insertions, 33 deletions
diff --git a/miscutils/make.c b/miscutils/make.c index 056cb2909..70fd30440 100644 --- a/miscutils/make.c +++ b/miscutils/make.c | |||
@@ -2295,6 +2295,31 @@ remove_target(void) | |||
2295 | } | 2295 | } |
2296 | 2296 | ||
2297 | /* | 2297 | /* |
2298 | * Update the modification time of a file to now. | ||
2299 | */ | ||
2300 | static void | ||
2301 | touch(struct name *np) | ||
2302 | { | ||
2303 | if (dryrun || !silent) | ||
2304 | printf("touch %s\n", np->n_name); | ||
2305 | |||
2306 | if (!dryrun) { | ||
2307 | const struct timespec timebuf[2] = {{0, UTIME_NOW}, {0, UTIME_NOW}}; | ||
2308 | |||
2309 | if (utimensat(AT_FDCWD, np->n_name, timebuf, 0) < 0) { | ||
2310 | if (errno == ENOENT) { | ||
2311 | int fd = open(np->n_name, O_RDWR | O_CREAT, 0666); | ||
2312 | if (fd >= 0) { | ||
2313 | close(fd); | ||
2314 | return; | ||
2315 | } | ||
2316 | } | ||
2317 | warning("touch %s failed", np->n_name); | ||
2318 | } | ||
2319 | } | ||
2320 | } | ||
2321 | |||
2322 | /* | ||
2298 | * Do commands to make a target | 2323 | * Do commands to make a target |
2299 | */ | 2324 | */ |
2300 | static int | 2325 | static int |
@@ -2304,7 +2329,7 @@ docmds(struct name *np, struct cmd *cp) | |||
2304 | char *q, *command; | 2329 | char *q, *command; |
2305 | 2330 | ||
2306 | for (; cp; cp = cp->c_next) { | 2331 | for (; cp; cp = cp->c_next) { |
2307 | uint8_t ssilent, signore, sdomake; | 2332 | uint32_t ssilent, signore, sdomake; |
2308 | 2333 | ||
2309 | // Location of command in makefile (for use in error messages) | 2334 | // Location of command in makefile (for use in error messages) |
2310 | makefile = cp->c_makefile; | 2335 | makefile = cp->c_makefile; |
@@ -2380,44 +2405,24 @@ docmds(struct name *np, struct cmd *cp) | |||
2380 | } | 2405 | } |
2381 | } | 2406 | } |
2382 | } | 2407 | } |
2383 | if (sdomake || dryrun || dotouch) | 2408 | if (sdomake || dryrun) |
2384 | estat = MAKE_DIDSOMETHING; | 2409 | estat = MAKE_DIDSOMETHING; |
2385 | free(command); | 2410 | free(command); |
2386 | } | 2411 | } |
2387 | makefile = NULL; | ||
2388 | return estat; | ||
2389 | } | ||
2390 | |||
2391 | /* | ||
2392 | * Update the modification time of a file to now. | ||
2393 | */ | ||
2394 | static void | ||
2395 | touch(struct name *np) | ||
2396 | { | ||
2397 | if (dryrun || !silent) | ||
2398 | printf("touch %s\n", np->n_name); | ||
2399 | 2412 | ||
2400 | if (!dryrun) { | 2413 | if (dotouch && !(np->n_flag & N_PHONY) && !(estat & MAKE_DIDSOMETHING)) { |
2401 | const struct timespec timebuf[2] = {{0, UTIME_NOW}, {0, UTIME_NOW}}; | 2414 | touch(np); |
2402 | 2415 | estat = MAKE_DIDSOMETHING; | |
2403 | if (utimensat(AT_FDCWD, np->n_name, timebuf, 0) < 0) { | ||
2404 | if (errno == ENOENT) { | ||
2405 | int fd = open(np->n_name, O_RDWR | O_CREAT, 0666); | ||
2406 | if (fd >= 0) { | ||
2407 | close(fd); | ||
2408 | return; | ||
2409 | } | ||
2410 | } | ||
2411 | warning("touch %s failed", np->n_name); | ||
2412 | } | ||
2413 | } | 2416 | } |
2417 | |||
2418 | makefile = NULL; | ||
2419 | return estat; | ||
2414 | } | 2420 | } |
2415 | 2421 | ||
2416 | static int | 2422 | static int |
2417 | make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, | 2423 | make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, |
2418 | char *dedup, struct name *implicit) | 2424 | char *dedup, struct name *implicit) |
2419 | { | 2425 | { |
2420 | int estat; | ||
2421 | char *name, *member = NULL, *base = NULL, *prereq = NULL; | 2426 | char *name, *member = NULL, *base = NULL, *prereq = NULL; |
2422 | 2427 | ||
2423 | name = splitlib(np->n_name, &member); | 2428 | name = splitlib(np->n_name, &member); |
@@ -2457,11 +2462,7 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, | |||
2457 | setmacro("*", base, 0 | M_VALID); | 2462 | setmacro("*", base, 0 | M_VALID); |
2458 | free(name); | 2463 | free(name); |
2459 | 2464 | ||
2460 | estat = docmds(np, cp); | 2465 | return docmds(np, cp); |
2461 | if (dotouch && !(np->n_flag & N_PHONY)) | ||
2462 | touch(np); | ||
2463 | |||
2464 | return estat; | ||
2465 | } | 2466 | } |
2466 | 2467 | ||
2467 | /* | 2468 | /* |
diff --git a/testsuite/make.tests b/testsuite/make.tests index 33e730602..c2b62532a 100755 --- a/testsuite/make.tests +++ b/testsuite/make.tests | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | . ./testing.sh | 3 | . ./testing.sh |
4 | unset MAKEFLAGS | 4 | unset MAKEFLAGS |
5 | rm -rf make.tempdir | ||
5 | 6 | ||
6 | # testing "test name" "command" "expected result" "file input" "stdin" | 7 | # testing "test name" "command" "expected result" "file input" "stdin" |
7 | 8 | ||
@@ -116,6 +117,31 @@ baz: | |||
116 | @: | 117 | @: |
117 | ' | 118 | ' |
118 | 119 | ||
120 | # The -t option touches files that are out-of-date unless the target | ||
121 | # has no commands or they're already up-to-date. | ||
122 | mkdir make.tempdir && cd make.tempdir || exit 1 | ||
123 | touch baz | ||
124 | testing "make check -t option" \ | ||
125 | "make -t -f - 2>/dev/null" "touch bar\n" "" ' | ||
126 | all: foo bar baz | ||
127 | foo: | ||
128 | bar: | ||
129 | @echo bar | ||
130 | baz: | ||
131 | @echo baz | ||
132 | ' | ||
133 | cd .. || exit 1; rm -rf make.tempdir 2>/dev/null | ||
134 | |||
135 | # Build commands with a '+' prefix are executed even with the -t option. | ||
136 | mkdir make.tempdir && cd make.tempdir || exit 1 | ||
137 | testing "make execute build command with + prefix and -t" \ | ||
138 | "make -t -f - 2>/dev/null" "OK\n" "" ' | ||
139 | all: bar | ||
140 | bar: | ||
141 | @+echo OK | ||
142 | ' | ||
143 | cd .. || exit 1; rm -rf make.tempdir 2>/dev/null | ||
144 | |||
119 | # A macro created using ::= remembers it's of type immediate-expansion. | 145 | # A macro created using ::= remembers it's of type immediate-expansion. |
120 | # Immediate expansion also occurs when += is used to append to such a macro. | 146 | # Immediate expansion also occurs when += is used to append to such a macro. |
121 | testing "make appending to immediate-expansion macro" \ | 147 | testing "make appending to immediate-expansion macro" \ |