Index: lldb/trunk/packages/Python/lldbsuite/support/gmodules.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/support/gmodules.py +++ lldb/trunk/packages/Python/lldbsuite/support/gmodules.py @@ -0,0 +1,30 @@ +from __future__ import absolute_import +from __future__ import print_function + +# System modules +import os +import re + + +GMODULES_SUPPORT_MAP = {} +GMODULES_HELP_REGEX = re.compile(r"\s-gmodules\s") + + +def is_compiler_clang_with_gmodules(compiler_path): + # Before computing the result, check if we already have it cached. + if compiler_path in GMODULES_SUPPORT_MAP: + return GMODULES_SUPPORT_MAP[compiler_path] + + def _gmodules_supported_internal(): + compiler = os.path.basename(compiler_path) + if "clang" not in compiler: + return False + else: + # Check the compiler help for the -gmodules option. + clang_help = os.popen("%s --help" % compiler_path).read() + return GMODULES_HELP_REGEX.search(clang_help, re.DOTALL) is not None + + GMODULES_SUPPORT_MAP[compiler_path] = _gmodules_supported_internal() + return GMODULES_SUPPORT_MAP[compiler_path] + + Index: lldb/trunk/packages/Python/lldbsuite/test/decorators.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/decorators.py +++ lldb/trunk/packages/Python/lldbsuite/test/decorators.py @@ -522,15 +522,3 @@ return "Compiler cannot compile with -fsanitize=thread" return None return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func) - -def skipUnlessClangModules(): - """Decorate the item to skip test unless Clang -gmodules flag is supported.""" - def is_compiler_clang_with_gmodules(self): - compiler_path = self.getCompiler() - compiler = os.path.basename(compiler_path) - if compiler != "clang": - return "Test requires clang as compiler" - clang_help = os.popen("%s --help" % (compiler_path)).read() - match = re.match(".* -gmodules ", clang_help, re.DOTALL) - return "Clang version doesn't support -gmodules flag" if not match else None - return skipTestIfFn(is_compiler_clang_with_gmodules) Index: lldb/trunk/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py +++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py @@ -52,6 +52,7 @@ @add_test_categories(['pyapi']) @expectedFailureAndroid(api_levels=[21, 22], bugnumber="llvm.org/pr27787") @expectedFailureAll(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr27787") + @expectedFailureAll(oslist=["macosx"], debug_info="gmodules", bugnumber="llvm.org/pr27864") @skipIf(oslist=["windows"]) # Error in record layout on Windows def test_top_level_expressions(self): self.build_and_run() Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py @@ -18,6 +18,7 @@ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @expectedFailureAll(debug_info="dwo", bugnumber="llvm.org/pr25087") + @expectedFailureAll(oslist=["linux"], debug_info="gmodules", bugnumber="llvm.org/pr27865") @skipIfFreeBSD # The -dead_strip linker option isn't supported on FreeBSD versions of ld. def test(self): """Test breakpoint works correctly with dead-code stripping.""" Index: lldb/trunk/packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py @@ -20,7 +20,7 @@ self.shlib_names = ["a"] @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") - @expectedFailureAll("llvm.org/pr25872", oslist=["macosx"], debug_info="dwarf") + @expectedFailureAll("llvm.org/pr25872", oslist=["macosx"], debug_info=["dwarf", "gmodules"]) def test_c_global_variables(self): """Test 'frame variable --scope --no-args' which omits args and shows scopes.""" self.build() Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py @@ -7,15 +7,9 @@ mydir = TestBase.compute_mydir(__file__) + @add_test_categories(["gmodules"]) @expectedFailureAll(bugnumber="llvm.org/pr27412") - @skipUnlessClangModules() def test_specialized_typedef_from_pch(self): - clang_help = os.popen("clang --help").read() - match = re.match(".* -gmodules ", clang_help, re.DOTALL) - if not match: - self.skipTest("Clang version doesn't support -gmodules flag") - return - self.build() cwd = os.getcwd() Index: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py @@ -90,6 +90,7 @@ patterns = ["\(int\) \$.* = 3"]) self.runCmd("process continue") + @expectedFailureAll(oslist=["macosx"], debug_info="gmodules", bugnumber="llvm.org/pr27861") def test_NSString_expr_commands(self): """Test expression commands for NSString.""" self.build() Index: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py @@ -17,6 +17,7 @@ mydir = TestBase.compute_mydir(__file__) + @expectedFailureAll(oslist=["macosx"], debug_info="gmodules", bugnumber="llvm.org/pr27862") def test_break(self): """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" if self.getArchitecture() != 'x86_64': Index: lldb/trunk/packages/Python/lldbsuite/test/lldbinline.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lldbinline.py +++ lldb/trunk/packages/Python/lldbsuite/test/lldbinline.py @@ -9,6 +9,7 @@ # LLDB modules import lldb from .lldbtest import * +from . import configuration from . import lldbutil from .decorators import * @@ -141,6 +142,12 @@ self.buildDwo() self.do_test() + def __test_with_gmodules(self): + self.using_dsym = False + self.BuildMakefile() + self.buildGModules() + self.do_test() + def execute_user_command(self, __command): exec(__command, globals(), locals()) @@ -205,12 +212,14 @@ test.name = test_name target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] - if test_categories.is_supported_on_platform("dsym", target_platform): + if test_categories.is_supported_on_platform("dsym", target_platform, configuration.compilers): test.test_with_dsym = ApplyDecoratorsToFunction(test._InlineTest__test_with_dsym, decorators) - if test_categories.is_supported_on_platform("dwarf", target_platform): + if test_categories.is_supported_on_platform("dwarf", target_platform, configuration.compilers): test.test_with_dwarf = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwarf, decorators) - if test_categories.is_supported_on_platform("dwo", target_platform): + if test_categories.is_supported_on_platform("dwo", target_platform, configuration.compilers): test.test_with_dwo = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwo, decorators) + if test_categories.is_supported_on_platform("gmodules", target_platform, configuration.compilers): + test.test_with_gmodules = ApplyDecoratorsToFunction(test._InlineTest__test_with_gmodules, decorators) # Add the test case to the globals, and hide InlineTest __globals.update({test_name : test}) Index: lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py +++ lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py @@ -1329,6 +1329,12 @@ if not module.buildDwo(self, architecture, compiler, dictionary, clean): raise Exception("Don't know how to build binary with dwo") + def buildGModules(self, architecture=None, compiler=None, dictionary=None, clean=True): + """Platform specific way to build binaries with gmodules info.""" + module = builder_module() + if not module.buildGModules(self, architecture, compiler, dictionary, clean): + raise Exception("Don't know how to build binary with gmodules") + def buildGo(self): """Build the default go binary. """ @@ -1447,8 +1453,9 @@ if not categories: categories = all_dbginfo_categories - supported_categories = [x for x in categories - if test_categories.is_supported_on_platform(x, target_platform)] + supported_categories = [x for x in categories + if test_categories.is_supported_on_platform( + x, target_platform, configuration.compilers)] if "dsym" in supported_categories: @decorators.add_test_categories(["dsym"]) @wraps(attrvalue) @@ -1478,6 +1485,17 @@ dwo_method_name = attrname + "_dwo" dwo_test_method.__name__ = dwo_method_name newattrs[dwo_method_name] = dwo_test_method + + if "gmodules" in supported_categories: + @decorators.add_test_categories(["gmodules"]) + @wraps(attrvalue) + def gmodules_test_method(self, attrvalue=attrvalue): + self.debug_info = "gmodules" + return attrvalue(self) + gmodules_method_name = attrname + "_gmodules" + gmodules_test_method.__name__ = gmodules_method_name + newattrs[gmodules_method_name] = gmodules_test_method + else: newattrs[attrname] = attrvalue return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs) @@ -1947,6 +1965,8 @@ return self.buildDwarf(architecture, compiler, dictionary, clean) elif self.debug_info == "dwo": return self.buildDwo(architecture, compiler, dictionary, clean) + elif self.debug_info == "gmodules": + return self.buildGModules(architecture, compiler, dictionary, clean) else: self.fail("Can't build for debug info: %s" % self.debug_info) Index: lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules +++ lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules @@ -212,8 +212,13 @@ CFLAGS += -gsplit-dwarf endif +ifeq "$(MAKE_GMODULES)" "YES" + CFLAGS += -fmodules -gmodules +endif + CXXFLAGS += -std=c++11 -CXXFLAGS += $(CFLAGS) +# FIXME: C++ modules aren't supported on all platforms. +CXXFLAGS += $(subst -fmodules,, $(CFLAGS)) LD = $(CC) LDFLAGS ?= $(CFLAGS) LDFLAGS += $(LD_EXTRAS) @@ -519,7 +524,7 @@ $(PCH_OUTPUT) : $(PCH_CXX_SOURCE) $(CXX) $(CXXFLAGS) -x c++-header -o $(PCH_OUTPUT) $(PCH_CXX_SOURCE) %.o : %.cpp $(PCH_OUTPUT) - $(CXX) $(PCHFLAGS) $(CXXFLAGS) $(CFLAGS) -c -o $@ $< + $(CXX) $(PCHFLAGS) $(CXXFLAGS) -c -o $@ $< #endif #---------------------------------------------------------------------- Index: lldb/trunk/packages/Python/lldbsuite/test/plugins/builder_base.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/plugins/builder_base.py +++ lldb/trunk/packages/Python/lldbsuite/test/plugins/builder_base.py @@ -143,6 +143,17 @@ # True signifies that we can handle building dwo. return True +def buildGModules(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): + """Build the binaries with dwarf debug info.""" + commands = [] + if clean: + commands.append([getMake(), "clean", getCmdLine(dictionary)]) + commands.append([getMake(), "MAKE_DSYM=NO", "MAKE_GMODULES=YES", getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)]) + + lldbtest.system(commands, sender=sender) + # True signifies that we can handle building with gmodules. + return True + def cleanup(sender=None, dictionary=None): """Perform a platform-specific cleanup after the test.""" #import traceback Index: lldb/trunk/packages/Python/lldbsuite/test/test_categories.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/test_categories.py +++ lldb/trunk/packages/Python/lldbsuite/test/test_categories.py @@ -11,9 +11,11 @@ # Third-party modules # LLDB modules +from lldbsuite.support import gmodules + debug_info_categories = [ - 'dwarf', 'dwo', 'dsym' + 'dwarf', 'dwo', 'dsym', 'gmodules' ] all_categories = { @@ -21,6 +23,7 @@ 'dwarf' : 'Tests that can be run with DWARF debug information', 'dwo' : 'Tests that can be run with DWO debug information', 'dsym' : 'Tests that can be run with DSYM debug information', + 'gmodules' : 'Tests that can be run with -gmodules debug information', 'expression' : 'Tests related to the expression parser', 'objc' : 'Tests related to the Objective-C programming language support', 'pyapi' : 'Tests related to the Python API', @@ -42,12 +45,27 @@ candidate = item return candidate -def is_supported_on_platform(category, platform): + +def is_supported_on_platform(category, platform, compiler_paths): if category == "dwo": # -gsplit-dwarf is not implemented by clang on Windows. return platform in ["linux", "freebsd"] elif category == "dsym": return platform in ["darwin", "macosx", "ios"] + elif category == "gmodules": + # First, check to see if the platform can even support gmodules. + if platform not in ["linux", "freebsd", "darwin", "macosx", "ios"]: + return False + # If all compilers specified support gmodules, we'll enable it. + for compiler_path in compiler_paths: + if not gmodules.is_compiler_clang_with_gmodules(compiler_path): + # Ideally in a multi-compiler scenario during a single test run, this would + # allow gmodules on compilers that support it and not on ones that don't. + # However, I didn't see an easy way for all the callers of this to know + # the compiler being used for a test invocation. As we tend to run with + # a single compiler per test run, this shouldn't be a major issue. + return False + return True return True def validate(categories, exact_match):