diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt --- a/compiler-rt/test/CMakeLists.txt +++ b/compiler-rt/test/CMakeLists.txt @@ -1,6 +1,16 @@ # Needed for lit support in standalone builds. include(AddLLVM) +option(COMPILER_RT_TEST_STANDALONE_BUILD_LIBS + "When set to ON and testing in a standalone build, test the runtime \ + libraries built by this standalone build rather than the runtime libraries \ + shipped with the compiler (used for testing). When set to OFF and testing \ + in a standalone build, test the runtime libraries shipped with the compiler \ + (used for testing). This option has no effect if the compiler and this \ + build are configured to use the same runtime library path." + ON) +pythonize_bool(COMPILER_RT_TEST_STANDALONE_BUILD_LIBS) + pythonize_bool(LLVM_ENABLE_EXPENSIVE_CHECKS) configure_compiler_rt_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.common.configured.in diff --git a/compiler-rt/test/builtins/Unit/lit.site.cfg.py.in b/compiler-rt/test/builtins/Unit/lit.site.cfg.py.in --- a/compiler-rt/test/builtins/Unit/lit.site.cfg.py.in +++ b/compiler-rt/test/builtins/Unit/lit.site.cfg.py.in @@ -7,6 +7,7 @@ config.is_msvc = @MSVC_PYBOOL@ config.builtins_is_msvc = @BUILTINS_IS_MSVC_PYBOOL@ config.builtins_lit_source_features = "@BUILTINS_LIT_SOURCE_FEATURES@" +config.test_suite_supports_overriding_runtime_lib_path = True # Load common config for all compiler-rt lit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -21,6 +21,60 @@ import pipes sh_quote = pipes.quote +def find_compiler_libdir(): + """ + Returns the path to library resource directory used + by the compiler. + """ + if config.compiler_id != 'Clang': + lit_config.warning(f'Determining compiler\'s runtime directory is not supported for {config.compiler_id}') + # TODO: Support other compilers. + return None + def get_path_from_clang(args, allow_failure): + clang_cmd = [ + config.clang.strip(), + f'--target={config.target_triple}', + ] + clang_cmd.extend(args) + path = None + try: + result = subprocess.run( + clang_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + check=True + ) + path = result.stdout.decode().strip() + except subprocess.CalledProcessError as e: + msg = f'Failed to run {clang_cmd}\nrc:{e.returncode}\nstdout:{e.stdout}\ne.stderr{e.stderr}' + if allow_failure: + lit_config.warning(msg) + else: + lit_config.fatal(msg) + return path + + # Try using `-print-runtime-dir`. This is only supported by very new versions of Clang. + # so allow failure here. + runtime_dir = get_path_from_clang(['-print-runtime-dir'], allow_failure=True) + if runtime_dir: + if os.path.exists(runtime_dir): + return os.path.realpath(runtime_dir) + lit_config.fatal(f'Path reported by clang does not exist: {runtime_dir}') + + # Fall back for older AppleClang that doesn't support `-print-runtime-dir` + # Note `-print-file-name=` was broken for Apple + # platforms so we can't use that approach here (see https://reviews.llvm.org/D101682). + if config.host_os == 'Darwin': + lib_dir = get_path_from_clang(['-print-file-name=lib'], allow_failure=False) + runtime_dir = os.path.join(lib_dir, 'darwin') + if not os.path.exists(runtime_dir): + lit_config.fatal(f'Path reported by clang does not exist: {runtime_dir}') + return os.path.realpath(runtime_dir) + + lit_config.warning('Failed to determine compiler\'s runtime directory') + return None + + # 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") @@ -63,6 +117,35 @@ # Add compiler ID to the list of available features. config.available_features.add(compiler_id) +# Ask the compiler for the path to libraries it is going to use. If this +# doesn't match config.compiler_rt_libdir then it means we might be testing the +# compiler's own runtime libraries rather than the ones we just built. +# Warn about about this and handle appropriately. +compiler_libdir = find_compiler_libdir() +if compiler_libdir: + compiler_rt_libdir_real = os.path.realpath(config.compiler_rt_libdir) + if compiler_libdir != compiler_rt_libdir_real: + lit_config.warning( + 'Compiler lib dir != compiler-rt lib dir\n' + f'Compiler libdir: "{compiler_libdir}"\n' + f'compiler-rt libdir: "{compiler_rt_libdir_real}"') + if config.test_standalone_build_libs: + # Use just built runtime libraries, i.e. the the libraries this built just built. + if not config.test_suite_supports_overriding_runtime_lib_path: + # Test suite doesn't support this configuration. + lit_config.fatal( + 'COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, but this test suite ' + 'does not support testing the just-built runtime libraries ' + 'when the test compiler is configured to use different runtime ' + 'libraries. Either modify this test suite to support this test ' + 'configuration, or set COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF ' + 'to test the runtime libraries included in the compiler instead.' + ) + else: + # Use Compiler's resource library directory instead. + config.compiler_rt_libdir = compiler_libdir + lit_config.note(f'Testing using libraries in "{config.compiler_rt_libdir}"') + # If needed, add cflag for shadow scale. if config.asan_shadow_scale != '': config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in --- a/compiler-rt/test/lit.common.configured.in +++ b/compiler-rt/test/lit.common.configured.in @@ -46,6 +46,11 @@ set_default("have_rpc_xdr_h", @HAVE_RPC_XDR_H@) set_default("gwp_asan", @COMPILER_RT_HAS_GWP_ASAN_PYBOOL@) set_default("expensive_checks", @LLVM_ENABLE_EXPENSIVE_CHECKS_PYBOOL@) +set_default("test_standalone_build_libs", @COMPILER_RT_TEST_STANDALONE_BUILD_LIBS_PYBOOL@) +# True iff the test suite supports ignoring the test compiler's runtime library path +# and using `config.compiler_rt_libdir` instead. This only matters when the runtime +# library paths differ. +set_default("test_suite_supports_overriding_runtime_lib_path", False) config.available_features.add('target-is-%s' % config.target_arch) if config.enable_per_target_runtime_dir: