#!/usr/bin/env python3 # Copyright 2022 The IREE Authors # # Licensed under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # This scans the IREE source tree for long path lengths, which are problematic # on Windows: https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation # # We ultimately care that the build system is happy, but CMake on Windows in # particular does not actually give early or easy to understand error messages, # and developers/CI using Linux may still want to see warnings. We'll use # relative directory path length as a reasonable heuristic for "will the build # system be happy?", since CMake tends to create paths like this: # `iree/compiler/.../Foo/CMakeFiles/iree_compiler_Foo_Foo.objects.dir/bar.obj`. # Note that 'Foo' appears three times in that path, so that's typically the best # place to trim characters (and not file names). # # To check that all relative paths are shorter than the default limit: # python check_path_lengths.py # # To check that all relative paths are shorter than a custom limit: # python check_path_lengths.py --limit=50 import argparse import os import pathlib import sys def parse_arguments(): parser = argparse.ArgumentParser(description="Path length checker") # The default limit was selected based on repository state when this script # was added. If the max path length decreases, consider lowering this too. parser.add_argument( "--limit", help="Path length limit (inclusive)", type=int, default=75 ) parser.add_argument( "--include_tests", help="Includes /test directories. False by default as these don't usually generate problematic files during the build", action="store_true", default=False, ) parser.add_argument( "--verbose", help="Outputs detailed information about path lengths", action="store_true", default=False, ) args = parser.parse_args() return args def main(args): repo_root = pathlib.Path(__file__).parent.parent.parent # Just look at the compiler directory for now, since it has historically had # by far the longest paths. walk_root = os.path.join(repo_root, "compiler") longest_path_length = -1 long_paths = [] short_paths = [] for dirpath, dirnames, _ in os.walk(walk_root): # Don't descend into test directories, since they typically don't generate # object files or binaries that could trip up the build system. if not args.include_tests and "test" in dirnames: dirnames.remove("test") path = pathlib.Path(dirpath).relative_to(repo_root).as_posix() if len(path) > args.limit: long_paths.append(path) else: short_paths.append(path) longest_path_length = max(longest_path_length, len(path)) long_paths.sort(key=len) short_paths.sort(key=len) if args.verbose and short_paths: print(f"These paths are shorter than the limit of {args.limit} characters:") for path in short_paths: print("{:3d}, {}".format(len(path), path)) if long_paths: print(f"These paths are longer than the limit of {args.limit} characters:") for path in long_paths: print("{:3d}, {}".format(len(path), path)) print( f"Error: {len(long_paths)} source paths are longer than {args.limit} characters." ) print(" Long paths can be problematic when building on Windows.") print(" Please look at the output above and trim the paths.") sys.exit(1) else: print(f"All path lengths are under the limit of {args.limit} characters.") if __name__ == "__main__": main(parse_arguments())