[Scons-users] Command-line argument escaping doesn't fully respect parentheses or single quotes

Mats Wichmann mats at wichmann.us
Thu Aug 1 09:39:35 EDT 2019

On 8/1/19 3:46 AM, Abigail Bunyan via Scons-users wrote:
> The following SConstruct fails to compile on POSIX, with SCons 2.3.0 to 3.1.0:
>     env = Environment()
>     env.Tool("textfile")
>     env.Textfile("test.c", ["int main() { return foo(0); }"])
>     env.Append(CPPDEFINES={"foo(x)": "x"})
>     env.Program("test", "test.c")
> The error is:
>     gcc -o test.o -c -Dfoo(x)=x test.c
>     sh: 1: Syntax error: "(" unexpected
>     scons: *** [test.o] Error 2
> It's possible to work around it by adding our own escaping - meaning that these
> quotes aren't being properly escaped either:
>     env.Append(CPPDEFINES={"'foo(x)'": "x"})
> I don't know if the escaping that SCons applies is insufficient, or it's not
> applying it at all in this case, or if it shouldn't be using `sh` and should
> just directly be calling `gcc`.

Probably points #2 and #3 both, though the latter may be just my opinion.

The posix "escape" function ends up only called on the source and target
(the filenames) because of the logic which is pretty convoluted
(coincidentally, subst the subject of current work) - and that escape
function doesn't know to worry about parens anyway, possibly because
it's only expecting strings representing filenames.

The gcc manual is pretty clear on what you're trying to do -

If you wish to define a function-like macro on the command line, write
its argument list with surrounding parentheses before the equals sign
(if any). Parentheses are meaningful to most shells, so you should quote
the option. With sh and csh, -D'name(args…)=definition' works.

and... personally, I don't understand why already-expanded command lines
need to be invoked through a shell.  It's not that scons is calling
subprocess with the shell=True argument, is that it's actually building
a command line that starts with "sh -c"

More information about the Scons-users mailing list