From c6b525f2afde0833d21b3f0132961a3b0178bbbb Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 22 May 2024 12:44:01 +0100 Subject: make: set $< and $* for target rules POSIX only requires $< and $* to be set for inference rules, not target rules. As an extension allow them to be set for target rules, as in GNU make. This may or may not be useful. In POSIX mode, when $< and $* are only set for inference rules, they're set to an empty string for target rules. This avoids the possibility of stale values being used. Adds 64-80 bytes. (GitHub issue #407) --- miscutils/make.c | 33 +++++++++++++++++++++++++++------ testsuite/make.tests | 13 +++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/miscutils/make.c b/miscutils/make.c index f594e196b..c69dcec8a 100644 --- a/miscutils/make.c +++ b/miscutils/make.c @@ -2298,7 +2298,7 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, char *dedup, struct name *implicit) { int estat; - char *name, *member = NULL, *base; + char *name, *member = NULL, *base = NULL, *prereq = NULL; name = splitlib(np->n_name, &member); setmacro("?", oodate, 0 | M_VALID); @@ -2308,12 +2308,33 @@ make1(struct name *np, struct cmd *cp, char *oodate, char *allsrc, } setmacro("%", member, 0 | M_VALID); setmacro("@", name, 0 | M_VALID); - if (implicit) { - setmacro("<", implicit->n_name, 0 | M_VALID); + if (implicit || !posix) { + char *s; + + // As an extension, if we're not dealing with an implicit + // rule set $< to the first out-of-date prerequisite. + if (implicit == NULL) { + if (oodate) { + s = strchr(oodate, ' '); + if (s) + *s = '\0'; + prereq = oodate; + } + } else + prereq = implicit->n_name; + base = member ? member : name; - *suffix(base) = '\0'; - setmacro("*", base, 0 | M_VALID); - } + s = suffix(base); + // As an extension, if we're not dealing with an implicit + // rule and the target ends with a known suffix, remove it + // and set $* to the stem, else to an empty string. + if (implicit == NULL && !is_suffix(s)) + base = NULL; + else + *s = '\0'; + } + setmacro("<", prereq, 0 | M_VALID); + setmacro("*", base, 0 | M_VALID); free(name); estat = docmds(np, cp); diff --git a/testsuite/make.tests b/testsuite/make.tests index fdbb4ccfc..5119a77d3 100755 --- a/testsuite/make.tests +++ b/testsuite/make.tests @@ -540,6 +540,19 @@ bar: @echo $(BAR) ' +# $* and $< are supported for target rules +mkdir make.tempdir && cd make.tempdir || exit 1 +touch src.c src.h +testing 'make support $* and $< for target rules' \ + "make -f -" "src.c src.h\nsrc.o\nsrc\nsrc.c\n" "" ' +src.o: src.c src.h + @echo "$?" + @echo "$@" + @echo "$*" + @echo "$<" +' +cd .. || exit 1; rm -rf make.tempdir 2>/dev/null + # An empty original suffix indicates that every word should have # the new suffix added. If neither suffix is provided the words # remain unchanged. -- cgit v1.2.3-55-g6feb