Merge pull request #1657 from QuLogic/ninja-escape

ninja: Fix quoting newlines and $
pull/1745/head
Jussi Pakkanen 8 years ago committed by GitHub
commit 69c5931a8d
  1. 7
      docs/markdown/Release-notes-for-0.41.0.md
  2. 24
      mesonbuild/backend/ninjabackend.py
  3. 28
      test cases/common/149 special characters/check_quoting.py
  4. 2
      test cases/common/149 special characters/installed_files.txt
  5. 37
      test cases/common/149 special characters/meson.build

@ -17,3 +17,10 @@ Native support for linking against LLVM using the `dependency` function.
The `fallback` keyword in `vcs_tag` is now optional. If not given, its value
defaults to the return value of `meson.project_version()`.
## Better quoting of special characters in ninja command invocations
The ninja backend now quotes special characters that may be interpreted by
ninja itself, providing better interoperability with custom commands. This
support may not be perfect; please report any issues found with special
characters to the issue tracker.

@ -38,7 +38,12 @@ else:
rmfile_prefix = 'rm -f {} &&'
def ninja_quote(text):
return text.replace(' ', '$ ').replace(':', '$:')
for char in ('$', ' ', ':'):
text = text.replace(char, '$' + char)
if '\n' in text:
raise MesonException('Ninja does not support newlines in rules. '
'Please report this error with a test case to the Meson bug tracker.')
return text
class NinjaBuildElement:
@ -480,12 +485,16 @@ int dummy;
# If the target requires capturing stdout, then use the serialized
# executable wrapper to capture that output and save it to a file.
#
# If the command line requires a newline, also use the wrapper, as
# ninja does not support them in its build rule syntax.
#
# Windows doesn't have -rpath, so for EXEs that need DLLs built within
# the project, we need to set PATH so the DLLs are found. We use
# a serialized executable wrapper for that and check if the
# CustomTarget command needs extra paths first.
if target.capture or ((mesonlib.is_windows() or mesonlib.is_cygwin()) and
self.determine_windows_extra_paths(target.command[0])):
if (target.capture or any('\n' in c for c in cmd) or
((mesonlib.is_windows() or mesonlib.is_cygwin()) and
self.determine_windows_extra_paths(target.command[0]))):
exe_data = self.serialize_executable(target.command[0], cmd[1:],
# All targets are built from the build dir
self.environment.get_build_dir(),
@ -1448,12 +1457,13 @@ int dummy;
def generate_swift_compile_rules(self, compiler, outfile):
rule = 'rule %s_COMPILER\n' % compiler.get_language()
full_exe = [sys.executable,
self.environment.get_build_command(),
full_exe = [ninja_quote(sys.executable),
ninja_quote(self.environment.get_build_command()),
'--internal',
'dirchanger',
'$RUNDIR'] + compiler.get_exelist()
invoc = ' '.join([ninja_quote(i) for i in full_exe])
'$RUNDIR']
invoc = (' '.join(full_exe) + ' ' +
' '.join(ninja_quote(i) for i in compiler.get_exelist()))
command = ' command = %s $ARGS $in\n' % invoc
description = ' description = Compiling Swift source $in.\n'
outfile.write(rule)

@ -0,0 +1,28 @@
#!/usr/bin/env python3
import sys
expected = {
'newline': '\n',
'dollar': '$',
'colon': ':',
'space': ' ',
'multi1': ' ::$$ ::$$',
'multi2': ' ::$$\n\n \n\n::$$',
}
output = None
for arg in sys.argv[1:]:
try:
name, value = arg.split('=', 1)
except ValueError:
output = arg
continue
if expected[name] != value:
raise RuntimeError('{!r} is {!r} but should be {!r}'.format(name, value, expected[name]))
if output is not None:
with open(output, 'w') as f:
f.write('Success!')

@ -0,0 +1,2 @@
usr/share/result
usr/share/result2

@ -0,0 +1,37 @@
project('ninja special characters' ,'c')
python = import('python3').find_python()
# Without newlines, this should appear directly in build.ninja.
gen = custom_target('gen',
command : [
python,
files('check_quoting.py'),
'dollar=$',
'colon=:',
'space= ',
'''multi1= ::$$ ::$$''',
'@OUTPUT@'],
output : 'result',
install : true,
install_dir : get_option('datadir'))
# With newlines, this should go through the exe wrapper.
gen2 = custom_target('gen2',
command : [
python,
files('check_quoting.py'),
'''newline=
''',
'dollar=$',
'colon=:',
'space= ',
'''multi2= ::$$
::$$''',
'@OUTPUT@'],
output : 'result2',
install : true,
install_dir : get_option('datadir'))
Loading…
Cancel
Save