Skip to content

Commit 8470a66

Browse files
committed
[windows] Avoid %r for quoting module-cache-path in Windows.
%r returns a representation of the object that is valid Python syntax. For numbers and strings this representation is very compatible with Unix shells, but for Windows, the quoting performed by Python will not be compatible. For example the Windows path separator `\` will be escaped as `\\`, which is not necessary for Windows and might make some tests that try to match path fail. Python 3.3 has `shlex.quote`, which was previously available as `pipes.quote` in earlier Python versions. `pipes.quote` was indeed used in several points of the `lit.cfg` file. For Windows, one need to do their own quoting. This change introduces `shell_quote` which uses `shlex.quote` or `pipes.quote` in Unix depending on the Python version, and provides an implementation of `shell_quote` for Windows. It replaces every usage of `pipes.quotes` for `shell_quote`, and modifies the value of `mcp_opt` to use `shell_quote` and not `%r`. This should fix the test `Driver\working-directory.swift` in the Windows Visual Studio 2017 builder.
1 parent a373e85 commit 8470a66

File tree

2 files changed

+84
-46
lines changed

2 files changed

+84
-46
lines changed

test/Driver/working-directory.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@
6060
// -output-file-map itself
6161
// RUN: echo "{\"main.swift\": {\"object\": \"main-modified.o\"}}" > %t/ofmo2.json
6262
// RUN: touch %t/main.swift
63-
// RUN: cd %S && %swiftc_driver -driver-print-jobs -working-directory %/t -c main.swift -output-file-map ofmo2.json | %FileCheck %s -check-prefix=OUTPUT_FILE_MAP_2
63+
// RUN: cd %S && %swiftc_driver -driver-print-jobs -working-directory %/t -c main.swift -output-file-map ofmo2.json | %FileCheck %s -check-prefix=OUTPUT_FILE_MAP_2 --enable-yaml-compatibility
6464
// -output-file-map= is an alias for -output-file-map
65-
// RUN: cd %S && %swiftc_driver -driver-print-jobs -working-directory %/t -c main.swift -output-file-map=ofmo2.json | %FileCheck %s -check-prefix=OUTPUT_FILE_MAP_2
65+
// RUN: cd %S && %swiftc_driver -driver-print-jobs -working-directory %/t -c main.swift -output-file-map=ofmo2.json | %FileCheck %s -check-prefix=OUTPUT_FILE_MAP_2 --enable-yaml-compatibility
6666
// OUTPUT_FILE_MAP_2: BUILD_DIR{{.*}}main-modified.o
6767

6868
// RUN: %empty-directory(%t/sub)

test/lit.cfg

+82-44
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,27 @@ def get_lldb_python_interpreter(lldb_build_root):
110110
return None
111111
return python_path
112112

113+
if not platform.system() == 'Windows':
114+
# Python 3.3 has shlex.quote, while previous Python have pipes.quote
115+
if sys.version_info[0:2] >= (3, 2):
116+
shell_quote = shlex.quote
117+
else:
118+
shell_quote = pipes.quote
119+
else:
120+
# In Windows neither pipe.quote nor shlex.quote works.
121+
def shell_quote(s):
122+
# Quote the argument if it is empty, or contains a quote or a space.
123+
if len(s) == 0 or re.search(r'["\s]', s):
124+
s = '"' + s.replace('"', r'\"') + '"'
125+
return s
126+
127+
def escape_for_substitute_captures(s):
128+
# SubstituteCaptures strings are used as replacement patterns for regular
129+
# expressions. In them escapes like \1, \2 are used as references, but that
130+
# means that simple \ will try to be interpreted, so we need to escape them
131+
# with \\.
132+
return s.replace("\\", "\\\\")
133+
113134
###
114135

115136
# Check that the object root is known.
@@ -380,7 +401,7 @@ config.sil_test_options = os.environ.get('SIL_TEST_OPTIONS', '')
380401

381402
config.clang_module_cache_path = make_path(config.swift_test_results_dir, "clang-module-cache")
382403
shutil.rmtree(config.clang_module_cache_path, ignore_errors=True)
383-
mcp_opt = "-module-cache-path %r" % config.clang_module_cache_path
404+
mcp_opt = "-module-cache-path %s" % shell_quote(config.clang_module_cache_path)
384405
clang_mcp_opt = "-fmodules-cache-path=%r" % config.clang_module_cache_path
385406
lit_config.note("Using Clang module cache: " + config.clang_module_cache_path)
386407
lit_config.note("Using test results dir: " + config.swift_test_results_dir)
@@ -396,7 +417,7 @@ config.substitutions.append( ('%llvm_obj_root', config.llvm_obj_root) )
396417
config.substitutions.append( ('%llvm_src_root', config.llvm_src_root) )
397418
config.substitutions.append( ('%swift_obj_root', config.swift_obj_root) )
398419
config.substitutions.append( ('%swift_src_root', config.swift_src_root) )
399-
config.substitutions.append( ('%{python}', pipes.quote(sys.executable)) )
420+
config.substitutions.append( ('%{python}', shell_quote(sys.executable)) )
400421
config.substitutions.append( ('%{python.unquoted}', sys.executable) )
401422
config.substitutions.append( ('%mcp_opt', mcp_opt) )
402423
config.substitutions.append( ('%swift_driver_plain', "%r" % config.swift) )
@@ -1096,7 +1117,8 @@ elif run_os in ['windows-msvc']:
10961117
subst_target_swift_frontend_mock_sdk_after = ''
10971118

10981119
config.target_build_swift_dylib = \
1099-
SubstituteCaptures("%s -parse-as-library -emit-library -o \\1" % (config.target_build_swift))
1120+
SubstituteCaptures(r"%s -parse-as-library -emit-library -o \1" % (
1121+
escape_for_substitute_captures(config.target_build_swift)))
11001122
config.target_add_rpath = r''
11011123

11021124
config.target_clang = \
@@ -1280,7 +1302,7 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android':
12801302
toolchain_directory = make_path(
12811303
config.android_ndk_path, "toolchains", toolchain_directory_name,
12821304
"prebuilt", prebuilt_directory)
1283-
tools_directory = pipes.quote(make_path(
1305+
tools_directory = shell_quote(make_path(
12841306
toolchain_directory, ndk_platform_triple, "bin"))
12851307
lit_config.note("Testing Android " + config.variant_triple)
12861308
config.target_object_format = "elf"
@@ -1290,20 +1312,20 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android':
12901312
config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract")
12911313
config.target_sdk_name = "android"
12921314
android_link_paths_opt = "-L {} -L {} -L {}".format(
1293-
pipes.quote(make_path(
1315+
shell_quote(make_path(
12941316
config.android_ndk_path, "sources", "cxx-stl", "llvm-libc++",
12951317
"libs", ndk_platform_tuple)),
1296-
pipes.quote(make_path(
1318+
shell_quote(make_path(
12971319
toolchain_directory, "lib", "gcc", ndk_platform_triple,
12981320
"{}.x".format(config.android_ndk_gcc_version))),
1299-
pipes.quote(make_path(
1321+
shell_quote(make_path(
13001322
toolchain_directory, ndk_platform_triple, "lib")))
13011323
# Since NDK r14 the headers are unified under $NDK_PATH/sysroot, so the -sdk
13021324
# switch is not enough. Additionally we have to include both the unified
13031325
# sysroot, and the architecture sysroot.
1304-
unified_android_include_path = pipes.quote(make_path(
1326+
unified_android_include_path = shell_quote(make_path(
13051327
config.android_ndk_path, "sysroot", "usr", "include"))
1306-
architecture_android_include_path = pipes.quote(make_path(
1328+
architecture_android_include_path = shell_quote(make_path(
13071329
config.android_ndk_path, "sysroot", "usr", "include",
13081330
ndk_platform_triple))
13091331
android_include_paths_opt = "-I {} -I {}".format(
@@ -1749,21 +1771,27 @@ if not kIsWindows:
17491771

17501772
if not getattr(config, 'target_run_simple_swift', None):
17511773
config.target_run_simple_swift_parameterized = SubstituteCaptures(
1752-
"%%empty-directory(%%t) && "
1753-
"%s %s %%s \\1 -o %%t/a.out -module-name main && "
1754-
"%s %%t/a.out && "
1755-
"%s %%t/a.out"
1756-
% (config.target_build_swift, mcp_opt, config.target_codesign, config.target_run)
1774+
r"%%empty-directory(%%t) && "
1775+
r"%s %s %%s \1 -o %%t/a.out -module-name main && "
1776+
r"%s %%t/a.out && "
1777+
r"%s %%t/a.out"
1778+
% (escape_for_substitute_captures(config.target_build_swift),
1779+
escape_for_substitute_captures(mcp_opt),
1780+
escape_for_substitute_captures(config.target_codesign),
1781+
escape_for_substitute_captures(config.target_run))
17571782
)
17581783
config.target_run_simple_swiftgyb_parameterized = SubstituteCaptures(
1759-
"%%empty-directory(%%t) && "
1760-
"%%gyb %%s -o %%t/main.swift && "
1761-
"%%line-directive %%t/main.swift -- "
1762-
"%s %s %%t/main.swift \\1 -o %%t/a.out -module-name main && "
1763-
"%s %%t/a.out && "
1764-
"%%line-directive %%t/main.swift -- "
1765-
"%s %%t/a.out"
1766-
% (config.target_build_swift, mcp_opt, config.target_codesign, config.target_run)
1784+
r"%%empty-directory(%%t) && "
1785+
r"%%gyb %%s -o %%t/main.swift && "
1786+
r"%%line-directive %%t/main.swift -- "
1787+
r"%s %s %%t/main.swift \1 -o %%t/a.out -module-name main && "
1788+
r"%s %%t/a.out && "
1789+
r"%%line-directive %%t/main.swift -- "
1790+
r"%s %%t/a.out"
1791+
% (escape_for_substitute_captures(config.target_build_swift),
1792+
escape_for_substitute_captures(mcp_opt),
1793+
escape_for_substitute_captures(config.target_codesign),
1794+
escape_for_substitute_captures(config.target_run))
17671795
)
17681796

17691797
config.target_run_simple_swift = (
@@ -1804,7 +1832,7 @@ config.target_resilience_test = (
18041832
'%s %s --target-build-swift "%s" --target-run "%s" --t %%t --S %%S '
18051833
'--s %%s --lib-prefix "%s" --lib-suffix "%s" --target-codesign "%s" '
18061834
'--additional-compile-flags "%s" --triple "%s"'
1807-
% (pipes.quote(sys.executable), config.rth, config.target_build_swift,
1835+
% (shell_quote(sys.executable), config.rth, config.target_build_swift,
18081836
config.target_run, config.target_shared_library_prefix,
18091837
config.target_shared_library_suffix, config.target_codesign,
18101838
rth_flags, config.variant_triple))
@@ -1833,8 +1861,9 @@ config.substitutions.append(('%target-swift-emit-ir\(mock-sdk:([^)]+)\)',
18331861
SubstituteCaptures(r'%target-swift-frontend(mock-sdk:\1) -emit-ir -verify-syntax-tree')))
18341862
config.substitutions.append(('%target-swift-emit-ir', '%target-swift-frontend -emit-ir -verify-syntax-tree'))
18351863
config.substitutions.append(('%target-swift-frontend\(mock-sdk:([^)]+)\)',
1836-
SubstituteCaptures(r'%s \1 %s' % (subst_target_swift_frontend_mock_sdk,
1837-
subst_target_swift_frontend_mock_sdk_after))))
1864+
SubstituteCaptures(r'%s \1 %s' % (
1865+
escape_for_substitute_captures(subst_target_swift_frontend_mock_sdk),
1866+
escape_for_substitute_captures(subst_target_swift_frontend_mock_sdk_after)))))
18381867
config.substitutions.append(('%target-swift-frontend', config.target_swift_frontend))
18391868

18401869

@@ -1872,22 +1901,23 @@ else:
18721901
SubstituteCaptures(r'ln \1 \2 || cp \1 \2')))
18731902

18741903
config.substitutions.append(('%utils', config.swift_utils))
1875-
config.substitutions.append(('%line-directive', '%s %s' % (pipes.quote(sys.executable), config.line_directive)))
1876-
config.substitutions.append(('%gyb', '%s %s' % (pipes.quote(sys.executable), config.gyb)))
1904+
config.substitutions.append(('%line-directive', '%s %s' % (shell_quote(sys.executable), config.line_directive)))
1905+
config.substitutions.append(('%gyb', '%s %s' % (shell_quote(sys.executable), config.gyb)))
18771906
config.substitutions.append(('%round-trip-syntax-test',
1878-
'%s %s' % (pipes.quote(sys.executable),
1907+
'%s %s' % (shell_quote(sys.executable),
18791908
config.round_trip_syntax_test)))
1880-
config.substitutions.append(('%rth', '%s %s' % (pipes.quote(sys.executable), config.rth)))
1909+
config.substitutions.append(('%rth', '%s %s' % (shell_quote(sys.executable), config.rth)))
18811910
config.substitutions.append(('%scale-test',
18821911
'{} {} --swiftc-binary={} --tmpdir=%t'.format(
1883-
pipes.quote(sys.executable), config.scale_test,
1912+
shell_quote(sys.executable), config.scale_test,
18841913
config.swiftc)))
18851914
config.substitutions.append(('%empty-directory\(([^)]+)\)',
18861915
SubstituteCaptures(r'rm -rf "\1" && mkdir -p "\1"')))
18871916

18881917
config.substitutions.append(('%target-sil-opt\(mock-sdk:([^)]+)\)',
1889-
SubstituteCaptures(r'%s \1 %s' % (subst_target_sil_opt_mock_sdk,
1890-
subst_target_sil_opt_mock_sdk_after))))
1918+
SubstituteCaptures(r'%s \1 %s' % (
1919+
escape_for_substitute_captures(subst_target_sil_opt_mock_sdk),
1920+
escape_for_substitute_captures(subst_target_sil_opt_mock_sdk_after)))))
18911921
# NOTE: This needs to be appended after the mock-sdk expansion to ensure that we
18921922
# first expand the mock-sdk when lit is processing.
18931923
config.substitutions.append(('%target-sil-opt', config.target_sil_opt))
@@ -1897,9 +1927,10 @@ config.substitutions.append(('%target-sil-llvm-gen', config.target_sil_llvm_gen)
18971927
config.substitutions.append(('%target-sil-nm', config.target_sil_nm))
18981928

18991929
config.substitutions.append(('%target-swift-ide-test\(mock-sdk:([^)]+)\)',
1900-
SubstituteCaptures(r'%s \1 %s -swift-version %s' % (subst_target_swift_ide_test_mock_sdk,
1901-
subst_target_swift_ide_test_mock_sdk_after,
1902-
swift_version))))
1930+
SubstituteCaptures(r'%s \1 %s -swift-version %s' % (
1931+
escape_for_substitute_captures(subst_target_swift_ide_test_mock_sdk),
1932+
escape_for_substitute_captures(subst_target_swift_ide_test_mock_sdk_after),
1933+
escape_for_substitute_captures(swift_version)))))
19031934
config.substitutions.append(('%target-swift-ide-test', "%s -swift-version %s" % (config.target_swift_ide_test, swift_version)))
19041935

19051936
config.substitutions.append(('%target-swift-symbolgraph-extract', config.target_swift_symbolgraph_extract))
@@ -1944,8 +1975,9 @@ config.substitutions.append(('%target-object-format', config.target_object_forma
19441975
config.substitutions.append(('%{target-shared-library-prefix}', config.target_shared_library_prefix))
19451976
config.substitutions.append(('%{target-shared-library-suffix}', config.target_shared_library_suffix))
19461977
config.substitutions.insert(0, ('%target-library-name\(([^)]+)\)',
1947-
SubstituteCaptures(r'%s\1%s' % (config.target_shared_library_prefix,
1948-
config.target_shared_library_suffix))))
1978+
SubstituteCaptures(r'%s\1%s' % (
1979+
escape_for_substitute_captures(config.target_shared_library_prefix),
1980+
escape_for_substitute_captures(config.target_shared_library_suffix)))))
19491981
config.substitutions.append(('%target-rpath\(([^)]+)\)',
19501982
SubstituteCaptures(config.target_add_rpath)))
19511983

@@ -1958,14 +1990,20 @@ if hasattr(config, 'otool_classic'):
19581990
config.substitutions.append(('%otool-classic', config.otool_classic))
19591991

19601992
config.substitutions.append(('%FileCheck',
1961-
'%s %r --sanitize BUILD_DIR=%r --sanitize SOURCE_DIR=%r --use-filecheck %r %s' % (
1962-
pipes.quote(sys.executable),
1963-
config.PathSanitizingFileCheck,
1964-
swift_obj_root,
1965-
config.swift_src_root,
1966-
config.filecheck,
1993+
'%s %s --sanitize BUILD_DIR=%s --sanitize SOURCE_DIR=%s --use-filecheck %s %s' % (
1994+
shell_quote(sys.executable),
1995+
shell_quote(config.PathSanitizingFileCheck),
1996+
# LLVM Lit performs realpath with the config path, so all paths are relative
1997+
# to the real path. swift_obj_root and swift_src_root come from CMake, which
1998+
# might not do real path. Because we have to match what Lit uses against what
1999+
# we provide we use realpath here. Because PathSanitizingFileCheck only
2000+
# understands sanitize patterns with forward slashes, and realpath normalizes
2001+
# the slashes, we have to replace them back to forward slashes.
2002+
shell_quote(os.path.realpath(swift_obj_root).replace("\\", "/")),
2003+
shell_quote(os.path.realpath(config.swift_src_root).replace("\\", "/")),
2004+
shell_quote(config.filecheck),
19672005
'--enable-windows-compatibility' if kIsWindows else '')))
1968-
config.substitutions.append(('%raw-FileCheck', pipes.quote(config.filecheck)))
2006+
config.substitutions.append(('%raw-FileCheck', shell_quote(config.filecheck)))
19692007
config.substitutions.append(('%import-libdispatch', getattr(config, 'import_libdispatch', '')))
19702008

19712009
if config.lldb_build_root != "":

0 commit comments

Comments
 (0)