diff options
author | Ron Yorston <rmy@pobox.com> | 2024-10-17 11:27:35 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-10-17 11:27:35 +0100 |
commit | 030d8f8ea9d4c2a896efad2b327a3308f7fd8c1b (patch) | |
tree | c69d60d369f0f590d8d052ba175fe3721bb97d4b /miscutils/make.c | |
parent | 4f13a5c9ea4994bd44ff91d3a6200113f863977b (diff) | |
download | busybox-w32-030d8f8ea9d4c2a896efad2b327a3308f7fd8c1b.tar.gz busybox-w32-030d8f8ea9d4c2a896efad2b327a3308f7fd8c1b.tar.bz2 busybox-w32-030d8f8ea9d4c2a896efad2b327a3308f7fd8c1b.zip |
make: improve chaining of implicit rules
Running 'make thing.z' with the following makefile:
.SUFFIXES: .x .y .z
.x.y:
cp $< $@
.y.x:
cp $< $@
.y.z:
cp $< $@
resulted in infinite recursion and a segfault. Follow GNU make and
don't allow any implicit rule to appear more than once in a chain.
Adds 16-32 bytes.
Diffstat (limited to 'miscutils/make.c')
-rw-r--r-- | miscutils/make.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/miscutils/make.c b/miscutils/make.c index 868cab5e2..4a8643a83 100644 --- a/miscutils/make.c +++ b/miscutils/make.c | |||
@@ -1016,14 +1016,30 @@ dyndep(struct name *np, struct rule *imprule) | |||
1016 | newsuff = dp->d_name->n_name; | 1016 | newsuff = dp->d_name->n_name; |
1017 | sp = findname(auto_concat(newsuff, suff)); | 1017 | sp = findname(auto_concat(newsuff, suff)); |
1018 | if (sp && sp->n_rule) { | 1018 | if (sp && sp->n_rule) { |
1019 | struct name *ip; | ||
1020 | int got_ip; | ||
1021 | |||
1022 | // Has rule already been used in this chain? | ||
1023 | if ((sp->n_flag & N_MARK)) | ||
1024 | continue; | ||
1025 | |||
1019 | // Generate a name for an implicit prerequisite | 1026 | // Generate a name for an implicit prerequisite |
1020 | struct name *ip = newname(auto_concat(base, newsuff)); | 1027 | ip = newname(auto_concat(base, newsuff)); |
1021 | if ((ip->n_flag & N_DOING)) | 1028 | if ((ip->n_flag & N_DOING)) |
1022 | continue; | 1029 | continue; |
1030 | |||
1023 | if (!ip->n_tim.tv_sec) | 1031 | if (!ip->n_tim.tv_sec) |
1024 | modtime(ip); | 1032 | modtime(ip); |
1025 | if (!chain ? ip->n_tim.tv_sec || (ip->n_flag & N_TARGET) : | 1033 | |
1026 | dyndep(ip, NULL) != NULL) { | 1034 | if (!chain) { |
1035 | got_ip = ip->n_tim.tv_sec || (ip->n_flag & N_TARGET); | ||
1036 | } else { | ||
1037 | sp->n_flag |= N_MARK; | ||
1038 | got_ip = dyndep(ip, NULL) != NULL; | ||
1039 | sp->n_flag &= ~N_MARK; | ||
1040 | } | ||
1041 | |||
1042 | if (got_ip) { | ||
1027 | // Prerequisite exists or we know how to make it | 1043 | // Prerequisite exists or we know how to make it |
1028 | if (imprule) { | 1044 | if (imprule) { |
1029 | dp = NULL; | 1045 | dp = NULL; |