ninja: Add ninja variable DEPFILE_UNQUOTED with unquoted DEPFILE value

It's assumed that where we use DEPFILE in command or rspfile_content, it
can be quoted by quoting the ninja variable (e.g. $DEPFILE ->
'$DEPFILE')

This is nearly always true, but not for gcc response files, where
backslash is always an escape, even inside single quotes.

So this fails if the value of DEPFILE contains backslashes (e.g. a
Windows path)

Do some special casing, adding DEPFILE_UNQUOTED, so that the value of
depfile is not shell quoted (so ninja can use it to locate the depfile
to read), but the value of DEPFILE used in command or rspfile_content is
shell/response file quoted)

(It would seem this also exists as a more general problem with built-in
ninja variables: '$out' appearing in command is fine, unless one of the
output filenames contains a single quote.  Although forbidding shell
metacharacters in filenames seems a reasonable way to solve that.)

(How does this even work, currently? Backslashes in the value of all
ninja variables, including DEPFILE were escaped, which protected them
against being treated as escapes in the gcc response file.  And
fortunately, the empty path elements indicated by a double backslash in
the value of depfile are ignored when ninja opens that file to read it.)
pull/7245/head
Jon Turney 6 years ago committed by Dan Kegel
parent abf8bf488e
commit 5ca37e7961
  1. 8
      mesonbuild/backend/ninjabackend.py

@ -93,7 +93,7 @@ rsp_threshold = 4096
# variables (or variables we use them in) is interpreted directly by ninja
# (e.g. the value of the depfile variable is a pathname that ninja will read
# from, etc.), so it must not be shell quoted.
raw_names = {'DEPFILE', 'DESC', 'pool', 'description', 'targetdep'}
raw_names = {'DEPFILE_UNQUOTED', 'DESC', 'pool', 'description', 'targetdep'}
def ninja_quote(text, is_build_line=False):
if is_build_line:
@ -180,6 +180,9 @@ class NinjaRule:
self.rsprefcount = 0
self.rspfile_quote_style = rspfile_quote_style # rspfile quoting style is 'gcc' or 'cl'
if self.depfile == '$DEPFILE':
self.depfile += '_UNQUOTED'
@staticmethod
def _quoter(x, qf = quote_func):
if isinstance(x, NinjaCommandArg):
@ -291,6 +294,9 @@ class NinjaBuildElement:
elems = [elems]
self.elems.append((name, elems))
if name == 'DEPFILE':
self.elems.append((name + '_UNQUOTED', elems))
def _should_use_rspfile(self):
# 'phony' is a rule built-in to ninja
if self.rulename == 'phony':

Loading…
Cancel
Save