tech-toolchain archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: 10.1 make oddity
Am 09.06.2026 um 01:13 schrieb Mouse:
> I recently tried to help someone set up some of my infrastructure on a
> 10.1 machine. I got reports of some bizarre messages from make. So I
> tried it on a 9.1 machine. I got the same messages:
>
> make: Unclosed substitution for (; missing)
> make: Unclosed substitution for (; missing)
> make: "/home/mouse/z.local/lib/make/local-prog" line 115: Need an operator
>
> Here's a cut-down test case:
>
> V = a.1
> D = /tmp
>
> .MAIN: dummy
>
> .PHONY: dummy
> dummy:
>
> .for x in $V
> $(x:C;^(.*)\.([0-9].*)$;$D/cat\2/\1.0;): \
> $(x:C;^.*\.([0-9].*)$;$D/cat\1;) \
> $(x:C;\.([0-9].*)$;.cat\1;)
> cp $(x:C;\.([0-9].*)$;.cat\1;) $(.TARGET)
> .endfor
>
> On a hunch, I tried replacing the ;s with ^Bs (as in, tr \; \\2 for the test
> case) - and the symptom went away.
> make(1) on 9.1 says that :C is just like :S except that it uses
> regexes. I *think* I originated this code, long ago, and my version of
> it does indeed work with semicolons as delimiters.
According to my make-archive, there was indeed a time where your test
ran successfully:
> 1998.09.18.20.35.12
> | exit status 0
> 2008.12.21.10.44.10
Then, in December of 2008, the handling of .for loops changed, and since
then, your test failed:
> 2008.12.21.18.06.53
> | make: Unknown modifier ' '
> | make: "/home/rillig/proj/make-archive/mouse.mk" line 8: Missing dependency operator
> | make: Fatal errors encountered -- cannot continue
> |
> | make: stopped in /home/rillig/proj/make-archive
> | exit status 1
> 2009.10.02.07.43.15
More than a year earlier, make's parser was changed to look for ";" in
dependency lines, to support shell commands in the same line:
> target: sources; cc -o target -c sources
Finding that semicolon has always been messy, since its first appearance
in parse.c 1.127 from 2007.01.01.21.47.32, where a comment said:
> No attempt is made to avoid ';' inside substitution patterns.
It improved a bit in parse.c 1.158 from 2009.10.07.16.40.30, where the
comment changed to:
> Attempt to avoid ';' inside substitution patterns.
But still, the code for finding a semicolon didn't cover all edge cases,
as it didn't simply call Var_Parse but instead grew its own parser for
balanced parentheses and braces. Since 2009, that code counts "$(" as
opening and every ")" as closing. For your test case, this means:
> $(x:C;^(.*)\.([0-9].*)$;$D/cat\2/\1.0;): \
> $(x:C;^.*\.([0-9].*)$;$D/cat\1;) \
> $(x:C;\.([0-9].*)$;.cat\1;)
The "$(" is interpreted as an opening parenthesis, but the following "("
is not. The ")" after the ".*" is interpreted as closing, so we're back
at depth 0.
The following "(" is not opening, and the following ")" is not closing,
as we're already at depth 0.
The "$;" is then not interpreted as an expression with variable name
";", instead this semicolon is interpreted as terminating the dependency
line, starting the shell command.
> but it appears this is not actually true. What are the actual
> restrictions? Or is this a bug that needs fixing? Or am I completely
> confused here somehow?
I consider the ad-hoc semicolon finder a bug.
I have a patch ready that fixes the code to use the existing expression
parser. With this fix, your test results in this dependency:
> /tmp/cat1/a.0: /tmp/cat1 a.cat1
That looks good to me.
Roland
Home |
Main Index |
Thread Index |
Old Index