JDevlieghere updated this revision to Diff 270262.
JDevlieghere added a comment.

Move work out of `LLDBTest` so we only have to compute it once.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D81696/new/

https://reviews.llvm.org/D81696

Files:
  lldb/test/API/lit.cfg.py
  lldb/test/API/lit.site.cfg.py.in
  lldb/test/API/lldbtest.py

Index: lldb/test/API/lldbtest.py
===================================================================
--- lldb/test/API/lldbtest.py
+++ lldb/test/API/lldbtest.py
@@ -10,24 +10,6 @@
 import lit.util
 from lit.formats.base import TestFormat
 
-def getBuildDir(cmd):
-    found = False
-    for arg in cmd:
-        if found:
-            return arg
-        if arg == '--build-dir':
-            found = True
-    return None
-
-def mkdir_p(path):
-    import errno
-    try:
-        os.makedirs(path)
-    except OSError as e:
-        if e.errno != errno.EEXIST:
-            raise
-    if not os.path.isdir(path):
-        raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
 
 class LLDBTest(TestFormat):
     def __init__(self, dotest_cmd):
@@ -73,33 +55,10 @@
         # python exe as the first parameter of the command.
         cmd = [executable] + self.dotest_cmd + [testPath, '-p', testFile]
 
-        builddir = getBuildDir(cmd)
-        mkdir_p(builddir)
-
-        # On macOS, we can't do the DYLD_INSERT_LIBRARIES trick with a shim
-        # python binary as the ASan interceptors get loaded too late. Also,
-        # when SIP is enabled, we can't inject libraries into system binaries
-        # at all, so we need a copy of the "real" python to work with.
-        #
-        # Find the "real" python binary, copy it, and invoke it.
-        if 'DYLD_INSERT_LIBRARIES' in test.config.environment and \
-                platform.system() == 'Darwin':
-            copied_python = os.path.join(builddir, 'copied-system-python')
-            if not os.path.isfile(copied_python):
-                import shutil, subprocess
-                python = subprocess.check_output([
-                    executable,
-                    os.path.join(os.path.dirname(os.path.realpath(__file__)),
-                        'get_darwin_real_python.py')
-                ]).decode('utf-8').strip()
-                shutil.copy(python, copied_python)
-            cmd[0] = copied_python
-
         if 'lldb-repro-capture' in test.config.available_features or \
            'lldb-repro-replay' in test.config.available_features:
-            reproducer_root = os.path.join(builddir, 'reproducers')
-            mkdir_p(reproducer_root)
-            reproducer_path = os.path.join(reproducer_root, testFile)
+            reproducer_path = os.path.join(
+                test.config.lldb_reproducer_directory, testFile)
             if 'lldb-repro-capture' in test.config.available_features:
                 cmd.extend(['--capture-path', reproducer_path])
             else:
Index: lldb/test/API/lit.site.cfg.py.in
===================================================================
--- lldb/test/API/lit.site.cfg.py.in
+++ lldb/test/API/lit.site.cfg.py.in
@@ -18,6 +18,7 @@
 config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
 config.target_triple = "@TARGET_TRIPLE@"
 config.lldb_build_directory = "@LLDB_TEST_BUILD_DIRECTORY@"
+config.lldb_reproducer_directory = os.path.join("@LLDB_TEST_BUILD_DIRECTORY@", "reproducers")
 config.python_executable = "@PYTHON_EXECUTABLE@"
 config.dotest_path = "@LLDB_SOURCE_DIR@/test/API/dotest.py"
 config.dotest_args_str = "@LLDB_DOTEST_ARGS@"
@@ -29,6 +30,7 @@
 config.test_compiler = '@LLDB_TEST_COMPILER@'
 config.dsymutil = '@LLDB_TEST_DSYMUTIL@'
 config.filecheck = '@LLDB_TEST_FILECHECK@'
+
 # The API tests use their own module caches.
 config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-api")
 config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-api")
@@ -61,5 +63,6 @@
     key, = e.args
     lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
 
+
 # Let the main config do the real work.
 lit_config.load_config(config, "@LLDB_SOURCE_DIR@/test/API/lit.cfg.py")
Index: lldb/test/API/lit.cfg.py
===================================================================
--- lldb/test/API/lit.cfg.py
+++ lldb/test/API/lit.cfg.py
@@ -21,6 +21,17 @@
 config.test_exec_root = config.test_source_root
 
 
+def mkdir_p(path):
+    import errno
+    try:
+        os.makedirs(path)
+    except OSError as e:
+        if e.errno != errno.EEXIST:
+            raise
+    if not os.path.isdir(path):
+        raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
+
+
 def find_sanitizer_runtime(name):
   import subprocess
   resource_dir = subprocess.check_output(
@@ -38,6 +49,44 @@
     yield 'PATH'
 
 
+# On macOS, we can't do the DYLD_INSERT_LIBRARIES trick with a shim python
+# binary as the ASan interceptors get loaded too late. Also, when SIP is
+# enabled, we can't inject libraries into system binaries at all, so we need a
+# copy of the "real" python to work with.
+def find_python_interpreter():
+  # Avoid doing any work if we already copied the binary. This serves as
+  # synchronization between multiple API tests.
+  copied_python = os.path.join(config.lldb_build_directory, 'copied-python')
+  if os.path.isfile(copied_python):
+    return copied_python
+
+  # Find the "real" python binary.
+  import shutil, subprocess
+  real_python = subprocess.check_output([
+      config.python_executable,
+      os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                   'get_darwin_real_python.py')
+  ]).decode('utf-8').strip()
+
+  shutil.copy(real_python, copied_python)
+
+  # Now make sure the copied Python works. The Python in Xcode has a relative
+  # RPATH and cannot be copied.
+  try:
+    # We don't care about the output, just make sure it runs.
+    subprocess.check_output([copied_python, '-V'], stderr=subprocess.STDOUT)
+  except subprocess.CalledProcessError:
+    # The copied Python didn't work. Assume we're dealing with the Python
+    # interpreter in Xcode. Given that this is not a system binary SIP
+    # won't prevent us form injecting the interceptors so we get away with
+    # not copying the executable.
+    os.remove(copied_python)
+    return real_python
+
+  # The copied Python works.
+  return copied_python
+
+
 if 'Address' in config.llvm_use_sanitizer:
   config.environment['ASAN_OPTIONS'] = 'detect_stack_use_after_return=1'
   if 'Darwin' in config.host_os and 'x86' in config.host_triple:
@@ -49,6 +98,9 @@
     config.environment['DYLD_INSERT_LIBRARIES'] = find_sanitizer_runtime(
         'libclang_rt.tsan_osx_dynamic.dylib')
 
+if 'DYLD_INSERT_LIBRARIES' in config.environment and platform.system() == 'Darwin':
+  config.python_executable = find_python_interpreter()
+
 # Shared library build of LLVM may require LD_LIBRARY_PATH or equivalent.
 if config.shared_libs:
   for shlibpath_var in find_shlibpath_var():
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to