summaryrefslogtreecommitdiff
path: root/lldb
diff options
context:
space:
mode:
authorStefan Gränitz <stefan.graenitz@gmail.com>2023-05-16 15:22:49 +0200
committerStefan Gränitz <stefan.graenitz@gmail.com>2023-05-17 10:37:38 +0200
commit4241ac542d691289f08c3229cfc58641f5659ec7 (patch)
tree9fc37fa64d2666860e679835e5e06ea75864a13e /lldb
parent704eb9938387d38c4289890872247121f5a9382d (diff)
downloadllvm-4241ac542d691289f08c3229cfc58641f5659ec7.tar.gz
[lldb][gnustep] Add basic test and infrastructure for GNUstep ObjC runtime
This patch adds test infrastructure to utilize the GNUstep runtime in the LLDB test suite and adds coverage for features that already work on Linux. These seem accidental in parts, but it's a good early baseline. On Windows nothing works yet. Please find the repository for the GNUstep ObjC runtime here: https://github.com/gnustep/libobjc2 GNUstep support is disabled by default. CMake configuration involves two variables: * `LLDB_TEST_OBJC_GNUSTEP=On` enables GNUstep support in the test suite. It requires the libobjc2 shared library and headers to be found. * `LLDB_TEST_OBJC_GNUSTEP=Off` disables GNUstep support in the test suite and resets associated cache values if necessary (default). * `LLDB_TEST_OBJC_GNUSTEP_DIR` allows to pass a custom installation root. Differential Revision: https://reviews.llvm.org/D146058
Diffstat (limited to 'lldb')
-rw-r--r--lldb/cmake/modules/FindGNUstepObjC.cmake41
-rw-r--r--lldb/test/CMakeLists.txt24
-rw-r--r--lldb/test/Shell/Expr/objc-gnustep-print.m62
-rwxr-xr-xlldb/test/Shell/helper/build.py33
-rw-r--r--lldb/test/Shell/helper/toolchain.py2
-rw-r--r--lldb/test/Shell/lit.cfg.py10
-rw-r--r--lldb/test/Shell/lit.site.cfg.py.in1
7 files changed, 169 insertions, 4 deletions
diff --git a/lldb/cmake/modules/FindGNUstepObjC.cmake b/lldb/cmake/modules/FindGNUstepObjC.cmake
new file mode 100644
index 000000000000..e53a89e50a48
--- /dev/null
+++ b/lldb/cmake/modules/FindGNUstepObjC.cmake
@@ -0,0 +1,41 @@
+#.rst:
+# FindGNUstepObjC
+# ---------------
+#
+# Find the GNUstep libobjc2 shared library.
+
+set(gnustep_install_dir "")
+
+if (UNIX)
+ set(gnustep_lib lib/libobjc.so)
+ set(gnustep_header include/objc/runtime.h)
+ if (GNUstepObjC_DIR)
+ if (EXISTS "${GNUstepObjC_DIR}/${gnustep_lib}" AND
+ EXISTS "${GNUstepObjC_DIR}/${gnustep_header}")
+ set(gnustep_install_dir ${GNUstepObjC_DIR})
+ endif()
+ else()
+ set(gnustep_install_dir)
+ find_path(gnustep_install_dir NAMES lib/libobjc.so include/objc/runtime.h)
+ endif()
+ if (gnustep_install_dir)
+ set(GNUstepObjC_FOUND TRUE)
+ endif()
+elseif (WIN32)
+ set(gnustep_lib lib/objc.dll)
+ set(gnustep_header include/objc/runtime.h)
+ if (GNUstepObjC_DIR)
+ set(gnustep_install_dir ${GNUstepObjC_DIR})
+ else()
+ set(gnustep_install_dir "C:/Program Files (x86)/libobjc")
+ endif()
+ if (EXISTS "${gnustep_install_dir}/${gnustep_lib}" AND
+ EXISTS "${gnustep_install_dir}/${gnustep_header}")
+ set(GNUstepObjC_FOUND TRUE)
+ endif()
+endif()
+
+if (GNUstepObjC_FOUND)
+ set(GNUstepObjC_DIR ${gnustep_install_dir})
+ message(STATUS "Found GNUstep ObjC runtime: ${GNUstepObjC_DIR}/${gnustep_lib}")
+endif()
diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt
index ca15b96586ca..38013e1df618 100644
--- a/lldb/test/CMakeLists.txt
+++ b/lldb/test/CMakeLists.txt
@@ -50,6 +50,30 @@ set(LLDB_TEST_MODULE_CACHE_CLANG "${LLDB_TEST_BUILD_DIRECTORY}/module-cache-clan
file(MAKE_DIRECTORY ${LLDB_TEST_MODULE_CACHE_LLDB})
file(MAKE_DIRECTORY ${LLDB_TEST_MODULE_CACHE_CLANG})
+# Windows and Linux have no built-in ObjC runtime. Turn this on in order to run tests with GNUstep.
+option(LLDB_TEST_OBJC_GNUSTEP "Enable ObjC tests with GNUstep libobjc2 on non-Apple platforms" Off)
+set(LLDB_TEST_OBJC_GNUSTEP_DIR "" CACHE PATH "Custom path to the GNUstep shared library")
+
+if (LLDB_TEST_OBJC_GNUSTEP)
+ if (LLDB_TEST_OBJC_GNUSTEP_DIR)
+ set(GNUstepObjC_DIR ${LLDB_TEST_OBJC_GNUSTEP_DIR})
+ endif()
+ find_package(GNUstepObjC)
+ if (NOT GNUstepObjC_FOUND)
+ if (LLDB_TEST_OBJC_GNUSTEP_DIR)
+ message(FATAL_ERROR "Failed to find GNUstep libobjc2 in ${LLDB_TEST_OBJC_GNUSTEP_DIR}. "
+ "Please check LLDB_TEST_OBJC_GNUSTEP_DIR or turn off LLDB_TEST_OBJC_GNUSTEP.")
+ else()
+ message(FATAL_ERROR "Failed to find GNUstep libobjc2. "
+ "Please set LLDB_TEST_OBJC_GNUSTEP_DIR or turn off LLDB_TEST_OBJC_GNUSTEP.")
+ endif()
+ endif()
+ set(LLDB_TEST_OBJC_GNUSTEP_DIR ${GNUstepObjC_DIR})
+elseif (LLDB_TEST_OBJC_GNUSTEP_DIR)
+ message(STATUS "Reset LLDB_TEST_OBJC_GNUSTEP_DIR since LLDB_TEST_OBJC_GNUSTEP is off")
+ set(LLDB_TEST_OBJC_GNUSTEP_DIR "" CACHE PATH "Custom path to the GNUstep shared library" FORCE)
+endif()
+
# LLVM_BUILD_MODE is used in lit.site.cfg
if (CMAKE_CFG_INTDIR STREQUAL ".")
set(LLVM_BUILD_MODE ".")
diff --git a/lldb/test/Shell/Expr/objc-gnustep-print.m b/lldb/test/Shell/Expr/objc-gnustep-print.m
new file mode 100644
index 000000000000..565a96f15a3f
--- /dev/null
+++ b/lldb/test/Shell/Expr/objc-gnustep-print.m
@@ -0,0 +1,62 @@
+// REQUIRES: objc-gnustep
+// XFAIL: system-windows
+//
+// RUN: %build %s --compiler=clang --objc-gnustep --output=%t
+
+#import "objc/runtime.h"
+
+@protocol NSCoding
+@end
+
+#ifdef __has_attribute
+#if __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
+#endif
+@interface NSObject <NSCoding> {
+ id isa;
+ int refcount;
+}
+@end
+@implementation NSObject
+- (id)class {
+ return object_getClass(self);
+}
++ (id)new {
+ return class_createInstance(self, 0);
+}
+@end
+
+@interface TestObj : NSObject {}
+- (int)ok;
+@end
+@implementation TestObj
+- (int)ok {
+ return self ? 0 : 1;
+}
+@end
+
+// RUN: %lldb -b -o "b objc-gnustep-print.m:35" -o "run" -o "p self" -o "p *self" -- %t | FileCheck %s --check-prefix=SELF
+//
+// SELF: (lldb) b objc-gnustep-print.m:35
+// SELF: Breakpoint {{.*}} at objc-gnustep-print.m
+//
+// SELF: (lldb) run
+// SELF: Process {{[0-9]+}} stopped
+// SELF: -[TestObj ok](self=[[SELF_PTR:0x[0-9a-f]+]]{{.*}}) at objc-gnustep-print.m:35
+//
+// SELF: (lldb) p self
+// SELF: (TestObj *) [[SELF_PTR]]
+//
+// SELF: (lldb) p *self
+// SELF: (TestObj) {
+// SELF: NSObject = {
+// SELF: isa
+// SELF: refcount
+// SELF: }
+// SELF: }
+
+int main() {
+ TestObj *t = [TestObj new];
+ return [t ok];
+}
diff --git a/lldb/test/Shell/helper/build.py b/lldb/test/Shell/helper/build.py
index 55d871f2a040..2c15d6df5149 100755
--- a/lldb/test/Shell/helper/build.py
+++ b/lldb/test/Shell/helper/build.py
@@ -49,6 +49,18 @@ parser.add_argument('--tools-dir',
action='append',
help='If specified, a path to search in addition to PATH when --compiler is not an exact path')
+parser.add_argument('--objc-gnustep-dir',
+ metavar='directory',
+ dest='objc_gnustep_dir',
+ required=False,
+ help='If specified, a path to GNUstep libobjc2 runtime for use on Windows and Linux')
+
+parser.add_argument('--objc-gnustep',
+ dest='objc_gnustep',
+ action='store_true',
+ default=False,
+ help='Include and link GNUstep libobjc2 (Windows and Linux only)')
+
if sys.platform == 'darwin':
parser.add_argument('--apple-sdk',
metavar='apple_sdk',
@@ -238,6 +250,10 @@ class Builder(object):
self.obj_ext = obj_ext
self.lib_paths = args.libs_dir
self.std = args.std
+ assert not args.objc_gnustep or args.objc_gnustep_dir, \
+ "--objc-gnustep specified without path to libobjc2"
+ self.objc_gnustep_inc = os.path.join(args.objc_gnustep_dir, 'include') if args.objc_gnustep_dir else None
+ self.objc_gnustep_lib = os.path.join(args.objc_gnustep_dir, 'lib') if args.objc_gnustep_dir else None
def _exe_file_name(self):
assert self.mode != 'compile'
@@ -656,15 +672,20 @@ class GccBuilder(Builder):
args.append('-static')
args.append('-c')
- args.extend(['-o', obj])
- args.append(source)
-
if sys.platform == 'darwin':
args.extend(['-isysroot', self.apple_sdk])
+ elif self.objc_gnustep_inc:
+ if source.endswith('.m') or source.endswith('.mm'):
+ args.extend(['-fobjc-runtime=gnustep-2.0', '-I', self.objc_gnustep_inc])
+ if sys.platform == "win32":
+ args.extend(['-Xclang', '-gcodeview', '-Xclang', '--dependent-lib=msvcrtd'])
if self.std:
args.append('-std={0}'.format(self.std))
+ args.extend(['-o', obj])
+ args.append(source)
+
return ('compiling', [source], obj, None, args)
def _get_link_command(self):
@@ -686,6 +707,12 @@ class GccBuilder(Builder):
if sys.platform == 'darwin':
args.extend(['-isysroot', self.apple_sdk])
+ elif self.objc_gnustep_lib:
+ args.extend(['-L', self.objc_gnustep_lib, '-lobjc'])
+ if sys.platform == 'linux':
+ args.extend(['-Wl,-rpath,' + self.objc_gnustep_lib])
+ elif sys.platform == 'win32':
+ args.extend(['-fuse-ld=lld-link', '-g', '-Xclang', '--dependent-lib=msvcrtd'])
return ('linking', self._obj_file_names(), self._exe_file_name(), None, args)
diff --git a/lldb/test/Shell/helper/toolchain.py b/lldb/test/Shell/helper/toolchain.py
index 69b55b90751a..c882223fb5d2 100644
--- a/lldb/test/Shell/helper/toolchain.py
+++ b/lldb/test/Shell/helper/toolchain.py
@@ -42,6 +42,8 @@ def use_lldb_substitutions(config):
build_script_args.append('--tools-dir={0}'.format(config.lldb_tools_dir))
if config.llvm_libs_dir:
build_script_args.append('--libs-dir={0}'.format(config.llvm_libs_dir))
+ if config.objc_gnustep_dir:
+ build_script_args.append('--objc-gnustep-dir="{0}"'.format(config.objc_gnustep_dir))
lldb_init = _get_lldb_init_path(config)
diff --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py
index 7717400f0de1..20dd8fcc2276 100644
--- a/lldb/test/Shell/lit.cfg.py
+++ b/lldb/test/Shell/lit.cfg.py
@@ -24,7 +24,7 @@ config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
# suffixes: A list of file extensions to treat as test files. This is overriden
# by individual lit.local.cfg files in the test subdirectories.
-config.suffixes = ['.test', '.cpp', '.s']
+config.suffixes = ['.test', '.cpp', '.s', '.m']
# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
@@ -135,6 +135,14 @@ if config.lldb_system_debugserver:
if config.have_lldb_server:
config.available_features.add('lldb-server')
+if config.objc_gnustep_dir:
+ config.available_features.add('objc-gnustep')
+ if platform.system() == 'Windows':
+ # objc.dll must be in PATH since Windows has no rpath
+ config.environment['PATH'] = os.path.pathsep.join((
+ os.path.join(config.objc_gnustep_dir, 'lib'),
+ config.environment.get('PATH','')))
+
# NetBSD permits setting dbregs either if one is root
# or if user_set_dbregs is enabled
can_set_dbregs = True
diff --git a/lldb/test/Shell/lit.site.cfg.py.in b/lldb/test/Shell/lit.site.cfg.py.in
index d58918c87315..f84cb60ff940 100644
--- a/lldb/test/Shell/lit.site.cfg.py.in
+++ b/lldb/test/Shell/lit.site.cfg.py.in
@@ -16,6 +16,7 @@ config.lldb_lit_tools_dir = lit_config.substitute(r"@LLDB_LIT_TOOLS_DIR@")
config.target_triple = "@LLVM_TARGET_TRIPLE@"
config.python_executable = "@Python3_EXECUTABLE@"
config.have_zlib = @LLVM_ENABLE_ZLIB@
+config.objc_gnustep_dir = "@LLDB_TEST_OBJC_GNUSTEP_DIR@"
config.lldb_enable_lzma = @LLDB_ENABLE_LZMA@
config.host_triple = "@LLVM_HOST_TRIPLE@"
config.lldb_bitness = 64 if @LLDB_IS_64_BITS@ else 32