aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-05-06 12:06:35 +0200
committerGitHub <noreply@github.com>2017-05-06 12:06:35 +0200
commit69c5931a8d5c714f2cbc717e372c5170531d879e (patch)
tree1d5f9a119df143858e0a3a2e5bfccaf9bb019a27
parent08d05bd82dfea8c58847a71c6f2362274aadd812 (diff)
parentf9708cf1ba01b4240f391fdb61a77fa22b8b037f (diff)
downloadmeson-69c5931a8d5c714f2cbc717e372c5170531d879e.zip
meson-69c5931a8d5c714f2cbc717e372c5170531d879e.tar.gz
meson-69c5931a8d5c714f2cbc717e372c5170531d879e.tar.bz2
Merge pull request #1657 from QuLogic/ninja-escape
ninja: Fix quoting newlines and $
-rw-r--r--docs/markdown/Release-notes-for-0.41.0.md7
-rw-r--r--mesonbuild/backend/ninjabackend.py24
-rw-r--r--test cases/common/149 special characters/check_quoting.py28
-rw-r--r--test cases/common/149 special characters/installed_files.txt2
-rw-r--r--test cases/common/149 special characters/meson.build37
5 files changed, 91 insertions, 7 deletions
diff --git a/docs/markdown/Release-notes-for-0.41.0.md b/docs/markdown/Release-notes-for-0.41.0.md
index 9c02cdc..a2a64de 100644
--- a/docs/markdown/Release-notes-for-0.41.0.md
+++ b/docs/markdown/Release-notes-for-0.41.0.md
@@ -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.
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index eaf4cac..dad752b 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -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)
diff --git a/test cases/common/149 special characters/check_quoting.py b/test cases/common/149 special characters/check_quoting.py
new file mode 100644
index 0000000..d6e50ea
--- /dev/null
+++ b/test cases/common/149 special characters/check_quoting.py
@@ -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!')
diff --git a/test cases/common/149 special characters/installed_files.txt b/test cases/common/149 special characters/installed_files.txt
new file mode 100644
index 0000000..f677881
--- /dev/null
+++ b/test cases/common/149 special characters/installed_files.txt
@@ -0,0 +1,2 @@
+usr/share/result
+usr/share/result2
diff --git a/test cases/common/149 special characters/meson.build b/test cases/common/149 special characters/meson.build
new file mode 100644
index 0000000..ecba650
--- /dev/null
+++ b/test cases/common/149 special characters/meson.build
@@ -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'))