[LIT] Use forward slashes in substitutions when LLVM_WINDOWS_PREFER_FORWARD_SLASH is set (#179865)
When building with `-DLLVM_WINDOWS_PREFER_FORWARD_SLASH=ON`, tools like lld output paths with forward slashes on Windows. However, lit's default substitutions (`%t`, `%p`) typically use backslashes on Windows, causing FileCheck failures in tests that strictly match path separators. This patch propagates the `LLVM_WINDOWS_PREFER_FORWARD_SLASH` build flag to llvm-lit via `builtin_parameters`. It also updates lit's TestRunner to respect the 'use_normalized_slashes' parameter. When enabled, lit normalizes paths in substitutions to use forward slashes, ensuring that test expectations align with the tool output. With this fix, the number of failed tests with `-DLLVM_WINDOWS_PREFER_FORWARD_SLASH=ON` changes as follow: - The total number of failed tests: 303 -> 168 - Break down: - `Builtins-i386-windows` tests: 99 -> 0 - `Clang` tests: 28 -> 5 - `Clang Tools` tests: 7 -> 1 - `LLVM` tests: 6 -> 4 - `lld` tests: 2 -> 0 - Other failed tests: - `glang`: 1 - `Clang-Unit`: 5 - `Clangd`: 3 - `Clangd Unit Tests`: 150 - `LLVM-Unit`: 1
This commit is contained in:
parent
75b0cf39b2
commit
4ea39c43e1
@ -216,6 +216,8 @@ class LitConfig(object):
|
||||
# Step out of _write_message, and then out of wrapper.
|
||||
f = f.f_back.f_back
|
||||
file = os.path.abspath(inspect.getsourcefile(f))
|
||||
if lit.util.pythonize_bool(self.params.get("use_normalized_slashes")):
|
||||
file = file.replace("\\", "/")
|
||||
line = inspect.getlineno(f)
|
||||
sys.stderr.write(
|
||||
"%s: %s:%d: %s: %s\n" % (self.progname, file, line, kind, message)
|
||||
|
||||
@ -89,12 +89,13 @@ class ShellEnvironment(object):
|
||||
we maintain a dir stack for pushd/popd.
|
||||
"""
|
||||
|
||||
def __init__(self, cwd, env, umask=-1, ulimit=None):
|
||||
def __init__(self, cwd, env, umask=-1, ulimit=None, normalize_slashes=False):
|
||||
self.cwd = cwd
|
||||
self.env = dict(env)
|
||||
self.umask = umask
|
||||
self.dirStack = []
|
||||
self.ulimit = ulimit if ulimit else {}
|
||||
self.normalize_slashes = normalize_slashes
|
||||
|
||||
def change_dir(self, newdir):
|
||||
if os.path.isabs(newdir):
|
||||
@ -723,7 +724,7 @@ def processRedirects(cmd, stdin_source, cmd_shenv, opened_files):
|
||||
return std_fds
|
||||
|
||||
|
||||
def _expandLateSubstitutions(cmd, arguments, cwd):
|
||||
def _expandLateSubstitutions(cmd, arguments, cwd, normalize_slashes=False):
|
||||
for i, arg in enumerate(arguments):
|
||||
if not isinstance(arg, str):
|
||||
continue
|
||||
@ -732,6 +733,8 @@ def _expandLateSubstitutions(cmd, arguments, cwd):
|
||||
filePath = match.group(1)
|
||||
if not os.path.isabs(filePath):
|
||||
filePath = os.path.join(cwd, filePath)
|
||||
if normalize_slashes:
|
||||
filePath = filePath.replace("\\", "/")
|
||||
try:
|
||||
with open(filePath) as fileHandle:
|
||||
return fileHandle.read()
|
||||
@ -815,7 +818,9 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
|
||||
not_crash = False
|
||||
|
||||
# Expand all late substitutions.
|
||||
args = _expandLateSubstitutions(j, args, cmd_shenv.cwd)
|
||||
args = _expandLateSubstitutions(
|
||||
j, args, cmd_shenv.cwd, cmd_shenv.normalize_slashes
|
||||
)
|
||||
|
||||
while True:
|
||||
if args[0] == "env":
|
||||
@ -826,7 +831,12 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
|
||||
# env FOO=1 llc < %s | env BAR=2 llvm-mc | FileCheck %s
|
||||
# env FOO=1 %{another_env_plus_cmd} | FileCheck %s
|
||||
if cmd_shenv is shenv:
|
||||
cmd_shenv = ShellEnvironment(shenv.cwd, shenv.env, shenv.umask)
|
||||
cmd_shenv = ShellEnvironment(
|
||||
shenv.cwd,
|
||||
shenv.env,
|
||||
shenv.umask,
|
||||
normalize_slashes=shenv.normalize_slashes,
|
||||
)
|
||||
args = updateEnv(cmd_shenv, args)
|
||||
if not args:
|
||||
# Return the environment variables if no argument is provided.
|
||||
@ -1225,7 +1235,10 @@ def executeScriptInternal(
|
||||
|
||||
results = []
|
||||
timeoutInfo = None
|
||||
shenv = ShellEnvironment(cwd, test.config.environment)
|
||||
normalize_slashes = litConfig.params.get("use_normalized_slashes", False)
|
||||
shenv = ShellEnvironment(
|
||||
cwd, test.config.environment, normalize_slashes=normalize_slashes
|
||||
)
|
||||
shenv.env["LIT_CURRENT_TESTCASE"] = test.getFullName()
|
||||
|
||||
exitCode, timeoutInfo = executeShCmd(
|
||||
@ -1524,11 +1537,25 @@ def getDefaultSubstitutions(test, tmpDir, tmpBase, normalize_slashes=False):
|
||||
substitutions.append(("%{s:basename}", sourceBaseName))
|
||||
substitutions.append(("%{t:stem}", tmpBaseName))
|
||||
|
||||
fs_sep = os.path.sep
|
||||
if normalize_slashes:
|
||||
fs_sep = "/"
|
||||
|
||||
substitutions.extend(
|
||||
[
|
||||
("%{fs-src-root}", pathlib.Path(sourcedir).anchor),
|
||||
("%{fs-tmp-root}", pathlib.Path(tmpBase).anchor),
|
||||
("%{fs-sep}", os.path.sep),
|
||||
(
|
||||
"%{fs-src-root}",
|
||||
pathlib.Path(sourcedir).anchor.replace("\\", "/")
|
||||
if normalize_slashes
|
||||
else pathlib.Path(sourcedir).anchor,
|
||||
),
|
||||
(
|
||||
"%{fs-tmp-root}",
|
||||
pathlib.Path(tmpBase).anchor.replace("\\", "/")
|
||||
if normalize_slashes
|
||||
else pathlib.Path(tmpBase).anchor,
|
||||
),
|
||||
("%{fs-sep}", fs_sep),
|
||||
]
|
||||
)
|
||||
|
||||
@ -2465,7 +2492,11 @@ def executeShTest(
|
||||
tmpDir, tmpBase = getTempPaths(test)
|
||||
substitutions = list(extra_substitutions)
|
||||
substitutions += getDefaultSubstitutions(
|
||||
test, tmpDir, tmpBase, normalize_slashes=useExternalSh
|
||||
test,
|
||||
tmpDir,
|
||||
tmpBase,
|
||||
normalize_slashes=useExternalSh
|
||||
or litConfig.params.get("use_normalized_slashes", False),
|
||||
)
|
||||
conditions = {feature: True for feature in test.config.available_features}
|
||||
script = applySubstitutions(
|
||||
|
||||
@ -57,6 +57,10 @@ class LLVMConfig(object):
|
||||
self.lit_config.diagnostic_level_enabled("note")
|
||||
and lit_path_displayed is False
|
||||
):
|
||||
if lit.util.pythonize_bool(
|
||||
self.lit_config.params.get("use_normalized_slashes")
|
||||
):
|
||||
path = path.replace("\\", "/")
|
||||
self.lit_config.note("using lit tools: {}".format(path))
|
||||
lit_path_displayed = True
|
||||
|
||||
@ -557,6 +561,10 @@ class LLVMConfig(object):
|
||||
|
||||
if tool:
|
||||
tool = os.path.normpath(tool)
|
||||
if lit.util.pythonize_bool(
|
||||
self.lit_config.params.get("use_normalized_slashes")
|
||||
):
|
||||
tool = tool.replace("\\", "/")
|
||||
if not quiet:
|
||||
self.lit_config.note("using {}: {}".format(name, tool))
|
||||
return tool
|
||||
|
||||
@ -64,14 +64,21 @@ for attribute in ("llvm_tools_dir", "lit_tools_dir"):
|
||||
# within %{inputs}'s test suites. Thus, %{lit} clears environment variables
|
||||
# that can affect FileCheck's output. It also includes "--order=lexical -j1"
|
||||
# to ensure predictable test order, as it is often required for FileCheck
|
||||
# matches.
|
||||
# matches. It also specifies "-D use_normalized_slashes={0,1}" to be aligned
|
||||
# with the slashes in the substitutions (e.g, %t, %p) for Windows since it
|
||||
# switches between forward slashes and backslashes based on
|
||||
# LLVM_WINDOWS_PREFER_FORWARD_SLASH build config.
|
||||
config.substitutions.append(("%{inputs}", "Inputs"))
|
||||
config.substitutions.append(("%{lit}", "%{lit-no-order-opt} --order=lexical"))
|
||||
use_normalized_slashes = "0"
|
||||
if lit.util.pythonize_bool(lit_config.params.get("use_normalized_slashes")):
|
||||
use_normalized_slashes = "1"
|
||||
config.substitutions.append(
|
||||
(
|
||||
"%{lit-no-order-opt}",
|
||||
"{env} %{{python}} {lit} -j1".format(
|
||||
env="env -u FILECHECK_OPTS", lit=os.path.join(lit_path, "lit.py")
|
||||
"{env} %{{python}} {lit} -j1 -D use_normalized_slashes={use_normalized_slashes}".format(
|
||||
env="env -u FILECHECK_OPTS", lit=os.path.join(lit_path, "lit.py"),
|
||||
use_normalized_slashes=use_normalized_slashes,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# TODO(boomanaiden154): This sometimes fails, possibly due to buffers not being flushed.
|
||||
# ALLOW_RETRIES: 2
|
||||
|
||||
# RUN: env LIT_USE_INTERNAL_SHELL=1 not %{lit} -v %{inputs}/shtest-readfile | FileCheck -match-full-lines -DTEMP_PATH=%S%{fs-sep}Inputs%{fs-sep}shtest-readfile%{fs-sep}Output %s
|
||||
# RUN: env LIT_USE_INTERNAL_SHELL=1 not %{lit} -v %{inputs}/shtest-readfile | FileCheck -match-full-lines -DTEMP_PATH=%/S/Inputs/shtest-readfile/Output %s
|
||||
|
||||
# CHECK: -- Testing: 5 tests{{.*}}
|
||||
|
||||
|
||||
@ -25,6 +25,11 @@ builtin_parameters['config_map'] = config_map
|
||||
llvm_source_root = path(r'@LLVM_SOURCE_DIR@')
|
||||
sys.path.insert(0, os.path.join(llvm_source_root, 'utils', 'lit'))
|
||||
|
||||
import lit.util
|
||||
|
||||
if lit.util.pythonize_bool('@LLVM_WINDOWS_PREFER_FORWARD_SLASH@'):
|
||||
builtin_parameters['use_normalized_slashes'] = True
|
||||
|
||||
if __name__=='__main__':
|
||||
from lit.main import main
|
||||
main(builtin_parameters)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user