Index: debuginfo-tests/CMakeLists.txt =================================================================== --- /dev/null +++ debuginfo-tests/CMakeLists.txt @@ -0,0 +1,38 @@ +# Test runner infrastructure for debug info integration tests. This +# configures the test trees for use by Lit, and delegates to LLVM's +# lit test handlers. + +if (CMAKE_CFG_INTDIR STREQUAL ".") + set(LLVM_BUILD_MODE ".") +else () + set(LLVM_BUILD_MODE "%(build_mode)s") +endif () + +set(DEBUGINFO_TESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(DEBUGINFO_TESTS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) + + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + ) + +set(DEBUGINFO_TESTS_DEPS + clang + llvm-config + FileCheck + count + not + ) + +if (LLVM_PROJECT_LLD_ENABLED) + list(APPEND DEBUGINFO_TESTS_DEPS lld) +endif() + +add_lit_testsuite(check-debuginfo "Running debug info integration tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${DEBUGINFO_TESTS_DEPS} + ARGS ${DEBUGINFO_TEST_EXTRA_ARGS} + ) + +set_target_properties(check-debuginfo PROPERTIES FOLDER "Debug info tests") Index: debuginfo-tests/lit.cfg =================================================================== --- /dev/null +++ debuginfo-tests/lit.cfg @@ -0,0 +1,301 @@ +# -*- Python -*- + +import os +import platform +import re +import subprocess +import tempfile + +import lit.formats +import lit.util + +# Configuration file for the 'lit' test runner. + +# name: The name of this test suite. +config.name = 'Debug Info Tests' + +# Choose between lit's internal shell pipeline runner and a real shell. If +# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. +use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") +if use_lit_shell: + # 0 is external, "" is default, and everything else is internal. + execute_external = (use_lit_shell == "0") +else: + # Otherwise we default to internal on Windows and external elsewhere, as + # bash on Windows is usually very slow. + execute_external = (not sys.platform in ['win32']) + +# testFormat: The test format to use to interpret tests. +# +# For now we require '&&' between commands, until they get globally killed and +# the test runner updated. +config.test_format = lit.formats.ShTest(execute_external) + +# suffixes: A list of file extensions to treat as test files. +config.suffixes = ['.c', '.cpp', '.cppm', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap', '.test', '.rs'] + +# excludes: A list of directories to exclude from the testsuite. The 'Inputs' +# subdirectories contain auxiliary inputs for various tests in their parent +# directories. +config.excludes = ['Inputs', 'CMakeLists.txt', 'README.txt', 'LICENSE.txt'] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) + +# test_exec_root: The root path where tests should be run. +debuginfo_obj_root = getattr(config, 'debuginfo_obj_root', None) +if debuginfo_obj_root is not None: + config.test_exec_root = debuginfo_obj_root + +# Set llvm_{src,obj}_root for use by others. +config.llvm_src_root = getattr(config, 'llvm_src_root', None) +config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) + +# Clear some environment variables that might affect Clang. +# +# This first set of vars are read by Clang, but shouldn't affect tests +# that aren't specifically looking for these features, or are required +# simply to run the tests at all. +# +# FIXME: Should we have a tool that enforces this? + +# safe_env_vars = ('TMPDIR', 'TEMP', 'TMP', 'USERPROFILE', 'PWD', +# 'MACOSX_DEPLOYMENT_TARGET', 'IPHONEOS_DEPLOYMENT_TARGET', +# 'VCINSTALLDIR', 'VC100COMNTOOLS', 'VC90COMNTOOLS', +# 'VC80COMNTOOLS') +possibly_dangerous_env_vars = ['COMPILER_PATH', 'RC_DEBUG_OPTIONS', + 'CINDEXTEST_PREAMBLE_FILE', 'LIBRARY_PATH', + 'CPATH', 'C_INCLUDE_PATH', 'CPLUS_INCLUDE_PATH', + 'OBJC_INCLUDE_PATH', 'OBJCPLUS_INCLUDE_PATH', + 'LIBCLANG_TIMING', 'LIBCLANG_OBJTRACKING', + 'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX', + 'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS', + 'LIBCLANG_RESOURCE_USAGE', + 'LIBCLANG_CODE_COMPLETION_LOGGING'] +# Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it. +if platform.system() != 'Windows': + possibly_dangerous_env_vars.append('INCLUDE') +for name in possibly_dangerous_env_vars: + if name in config.environment: + del config.environment[name] + +# Tweak the PATH to include the tools dir and the scripts dir. +if debuginfo_obj_root is not None: + llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) + if not llvm_tools_dir: + lit_config.fatal('No LLVM tools dir set!') + path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH'])) + config.environment['PATH'] = path + llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) + if not llvm_libs_dir: + lit_config.fatal('No LLVM libs dir set!') + path = os.path.pathsep.join((llvm_libs_dir, + config.environment.get('LD_LIBRARY_PATH',''))) + config.environment['LD_LIBRARY_PATH'] = path + +### + +# Discover the 'clang' and 'clangcc' to use. + +import os + +def inferClang(PATH): + # Determine which clang to use. + clang = os.getenv('CLANG') + + # If the user set clang in the environment, definitely use that and don't + # try to validate. + if clang: + return clang + + # Otherwise look in the path. + clang = lit.util.which('clang', PATH) + + if not clang: + lit_config.fatal("couldn't find 'clang' program, try setting " + "CLANG in your environment") + + return clang + +config.clang = inferClang(config.environment['PATH']).replace('\\', '/') +if not lit_config.quiet: + lit_config.note('using clang: %r' % config.clang) + +config.substitutions.append( ('%PATH%', config.environment['PATH']) ) + +# Note that when substituting %clang_cc1 also fill in the include directory of +# the builtin headers. Those are part of even a freestanding environment, but +# Clang relies on the driver to locate them. +def getClangBuiltinIncludeDir(clang): + # FIXME: Rather than just getting the version, we should have clang print + # out its resource dir here in an easy to scrape form. + cmd = subprocess.Popen([clang, '-print-file-name=include'], + stdout=subprocess.PIPE, + env=config.environment) + if not cmd.stdout: + lit_config.fatal("Couldn't find the include dir for Clang ('%s')" % clang) + dir = cmd.stdout.read().strip() + if sys.platform in ['win32'] and execute_external: + # Don't pass dosish path separator to msys bash.exe. + dir = dir.replace('\\', '/') + # Ensure the result is an ascii string, across Python2.5+ - Python3. + return str(dir.decode('ascii')) + +def makeItaniumABITriple(triple): + m = re.match(r'(\w+)-(\w+)-(\w+)', triple) + if not m: + lit_config.fatal("Could not turn '%s' into Itanium ABI triple" % triple) + if m.group(3).lower() != 'win32': + # All non-win32 triples use the Itanium ABI. + return triple + return m.group(1) + '-' + m.group(2) + '-mingw32' + +def makeMSABITriple(triple): + m = re.match(r'(\w+)-(\w+)-(\w+)', triple) + if not m: + lit_config.fatal("Could not turn '%s' into MS ABI triple" % triple) + isa = m.group(1).lower() + vendor = m.group(2).lower() + os = m.group(3).lower() + if os == 'win32': + # If the OS is win32, we're done. + return triple + if isa.startswith('x86') or isa == 'amd64' or re.match(r'i\d86', isa): + # For x86 ISAs, adjust the OS. + return isa + '-' + vendor + '-win32' + # -win32 is not supported for non-x86 targets; use a default. + return 'i686-pc-win32' + +config.substitutions.append( ('%clang_cc1', + '%s -cc1 -internal-isystem %s -nostdsysteminc' + % (config.clang, getClangBuiltinIncludeDir(config.clang))) ) +config.substitutions.append( ('%clang_cpp', ' ' + config.clang + ' --driver-mode=cpp ')) +config.substitutions.append( ('%clang_cl', ' ' + config.clang + ' --driver-mode=cl ')) +config.substitutions.append( ('%clangxx', ' ' + config.clang + ' --driver-mode=g++ ')) +config.substitutions.append( ('%clang', ' ' + config.clang + ' ') ) +config.substitutions.append( ('%test_debuginfo', ' ' + config.llvm_src_root + '/utils/test_debuginfo.pl ') ) +config.substitutions.append( ('%itanium_abi_triple', makeItaniumABITriple(config.target_triple)) ) +config.substitutions.append( ('%ms_abi_triple', makeMSABITriple(config.target_triple)) ) +config.substitutions.append( ('%resource_dir', getClangBuiltinIncludeDir(config.clang)) ) +config.substitutions.append( ('%python', config.python_executable) ) + +# The host triple might not be set, at least if we're compiling clang from +# an already installed llvm. +if config.host_triple and config.host_triple != '@LLVM_HOST_TRIPLE@': + config.substitutions.append( ('%target_itanium_abi_host_triple', '--target=%s' % makeItaniumABITriple(config.host_triple)) ) +else: + config.substitutions.append( ('%target_itanium_abi_host_triple', '') ) + +# FIXME: Find nicer way to prohibit this. +config.substitutions.append( + (' clang ', """*** Do not use 'clang' in tests, use '%clang'. ***""") ) +config.substitutions.append( + (' clang\+\+ ', """*** Do not use 'clang++' in tests, use '%clangxx'. ***""")) +config.substitutions.append( + (' clang-cc ', + """*** Do not use 'clang-cc' in tests, use '%clang_cc1'. ***""") ) +config.substitutions.append( + (' clang -cc1 -analyze ', + """*** Do not use 'clang -cc1 -analyze' in tests, use '%clang_analyze_cc1'. ***""") ) +config.substitutions.append( + (' clang -cc1 ', + """*** Do not use 'clang -cc1' in tests, use '%clang_cc1'. ***""") ) +config.substitutions.append( + (' %clang-cc1 ', + """*** invalid substitution, use '%clang_cc1'. ***""") ) +config.substitutions.append( + (' %clang-cpp ', + """*** invalid substitution, use '%clang_cpp'. ***""") ) +config.substitutions.append( + (' %clang-cl ', + """*** invalid substitution, use '%clang_cl'. ***""") ) + +# For each occurrence of a clang tool name as its own word, replace it +# with the full path to the build directory holding that tool. This +# ensures that we are testing the tools just built and not some random +# tools that might happen to be in the user's PATH. + +# Regex assertions to reject neighbor hyphens/dots (seen in some tests). +# For example, don't match 'clang-check-' or '.clang-format'. +NoPreHyphenDot = r"(?