siger-young updated this revision to Diff 375081.
siger-young added a comment.

This update mainly fixed problematic typemaps and adding necessary comments.

Together, it forced Lua installation path as "PREFIX/lib/lua/5.3" and removed 
"lit.util" in tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D108090

Files:
  lldb/CMakeLists.txt
  lldb/bindings/lua/CMakeLists.txt
  lldb/bindings/lua/lua-typemaps.swig
  lldb/test/API/lua_api/TestComprehensive.lua
  lldb/test/API/lua_api/TestLuaAPI.py

Index: lldb/test/API/lua_api/TestLuaAPI.py
===================================================================
--- lldb/test/API/lua_api/TestLuaAPI.py
+++ lldb/test/API/lua_api/TestLuaAPI.py
@@ -5,8 +5,129 @@
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
-import lit.util
+import subprocess
 
+def to_string(b):
+    """Return the parameter as type 'str', possibly encoding it.
+
+    In Python2, the 'str' type is the same as 'bytes'. In Python3, the
+    'str' type is (essentially) Python2's 'unicode' type, and 'bytes' is
+    distinct.
+
+    """
+    if isinstance(b, str):
+        # In Python2, this branch is taken for types 'str' and 'bytes'.
+        # In Python3, this branch is taken only for 'str'.
+        return b
+    if isinstance(b, bytes):
+        # In Python2, this branch is never taken ('bytes' is handled as 'str').
+        # In Python3, this is true only for 'bytes'.
+        try:
+            return b.decode('utf-8')
+        except UnicodeDecodeError:
+            # If the value is not valid Unicode, return the default
+            # repr-line encoding.
+            return str(b)
+
+    # By this point, here's what we *don't* have:
+    #
+    #  - In Python2:
+    #    - 'str' or 'bytes' (1st branch above)
+    #  - In Python3:
+    #    - 'str' (1st branch above)
+    #    - 'bytes' (2nd branch above)
+    #
+    # The last type we might expect is the Python2 'unicode' type. There is no
+    # 'unicode' type in Python3 (all the Python3 cases were already handled). In
+    # order to get a 'str' object, we need to encode the 'unicode' object.
+    try:
+        return b.encode('utf-8')
+    except AttributeError:
+        raise TypeError('not sure how to convert %s to %s' % (type(b), str))
+
+class ExecuteCommandTimeoutException(Exception):
+    def __init__(self, msg, out, err, exitCode):
+        assert isinstance(msg, str)
+        assert isinstance(out, str)
+        assert isinstance(err, str)
+        assert isinstance(exitCode, int)
+        self.msg = msg
+        self.out = out
+        self.err = err
+        self.exitCode = exitCode
+
+
+# Close extra file handles on UNIX (on Windows this cannot be done while
+# also redirecting input).
+kUseCloseFDs = not (platform.system() == 'Windows')
+
+
+def executeCommand(command, cwd=None, env=None, input=None, timeout=0):
+    """Execute command ``command`` (list of arguments or string) with.
+
+    * working directory ``cwd`` (str), use None to use the current
+    working directory
+    * environment ``env`` (dict), use None for none
+    * Input to the command ``input`` (str), use string to pass
+    no input.
+    * Max execution time ``timeout`` (int) seconds. Use 0 for no timeout.
+
+    Returns a tuple (out, err, exitCode) where
+    * ``out`` (str) is the standard output of running the command
+    * ``err`` (str) is the standard error of running the command
+    * ``exitCode`` (int) is the exitCode of running the command
+
+    If the timeout is hit an ``ExecuteCommandTimeoutException``
+    is raised.
+
+    """
+    if input is not None:
+        input = to_bytes(input)
+    p = subprocess.Popen(command, cwd=cwd,
+                        stdin=subprocess.PIPE,
+                        stdout=subprocess.PIPE,
+                        stderr=subprocess.PIPE,
+                        env=env, close_fds=kUseCloseFDs)
+    timerObject = None
+    # FIXME: Because of the way nested function scopes work in Python 2.x we
+    # need to use a reference to a mutable object rather than a plain
+    # bool. In Python 3 we could use the "nonlocal" keyword but we need
+    # to support Python 2 as well.
+    hitTimeOut = [False]
+    try:
+        if timeout > 0:
+            def killProcess():
+                # We may be invoking a shell so we need to kill the
+                # process and all its children.
+                hitTimeOut[0] = True
+                killProcessAndChildren(p.pid)
+
+            timerObject = threading.Timer(timeout, killProcess)
+            timerObject.start()
+
+        out, err = p.communicate(input=input)
+        exitCode = p.wait()
+    finally:
+        if timerObject != None:
+            timerObject.cancel()
+
+    # Ensure the resulting output is always of string type.
+    out = to_string(out)
+    err = to_string(err)
+
+    if hitTimeOut[0]:
+        raise ExecuteCommandTimeoutException(
+            msg='Reached timeout of {} seconds'.format(timeout),
+            out=out,
+            err=err,
+            exitCode=exitCode
+        )
+
+    # Detect Ctrl-C in subprocess.
+    if exitCode == -signal.SIGINT:
+        raise KeyboardInterrupt
+
+    return out, err, exitCode
 
 class TestLuaAPI(TestBase):
 
@@ -41,7 +162,7 @@
         test_output = self.getBuildArtifact("output")
         test_input = self.getBuildArtifact("input")
             
-        lua_lldb_cpath = "%s/lua/?.so" % configuration.lldb_libs_dir
+        lua_lldb_cpath = "%s/lua/5.3/?.so" % configuration.lldb_libs_dir
 
         lua_prelude = "package.cpath = '%s;' .. package.cpath" % lua_lldb_cpath
 
@@ -53,7 +174,7 @@
 
         for lua_test in self.get_tests():
             cmd = [lua_executable] + ["-e", lua_prelude] + [lua_test]
-            out, err, exitCode = lit.util.executeCommand(cmd, env=lua_env)
+            out, err, exitCode = executeCommand(cmd, env=lua_env)
             
             # Redirect Lua output
             print(out)
Index: lldb/test/API/lua_api/TestComprehensive.lua
===================================================================
--- lldb/test/API/lua_api/TestComprehensive.lua
+++ lldb/test/API/lua_api/TestComprehensive.lua
@@ -69,6 +69,9 @@
     local size = self.var_inited:GetByteSize()
     local raw_data = self.process:ReadMemory(address:GetOffset(), size, error)
     assertTrue(error:Success())
+    local data_le = lldb.SBData.CreateDataFromUInt32Array(lldb.eByteOrderLittle, 1, {0xDEADBEEF})
+    local data_be = lldb.SBData.CreateDataFromUInt32Array(lldb.eByteOrderBig, 1, {0xDEADBEEF})
+    assertTrue(data_le:GetUnsignedInt32(error, 0) == 0xDCADBEEF or data_be:GetUnsignedInt32(error, 0) == 0xDCADBEEF)
     assertTrue(raw_data == "\xEF\xBE\xAD\xDE" or raw_data == "\xDE\xAD\xBE\xEF")
 end
 
Index: lldb/bindings/lua/lua-typemaps.swig
===================================================================
--- lldb/bindings/lua/lua-typemaps.swig
+++ lldb/bindings/lua/lua-typemaps.swig
@@ -192,6 +192,8 @@
 
 // Typemap for handling char ** in SBTarget::LaunchSimple, SBTarget::Launch...
 
+// It should accept a Lua table of strings, for stuff like "argv" and "envp".
+
 %typemap(in) char ** {
    if (lua_istable(L, $input)) {
       size_t size = lua_rawlen(L, $input);
@@ -200,15 +202,19 @@
       while (i++ < size) {
          lua_rawgeti(L, $input, i);
          if (!lua_isstring(L, -1)) {
+            // if current element cannot be converted to string, raise an error
             lua_pop(L, 1);
-            return luaL_error(L, "List should contains only strings");
+            return luaL_error(L, "List should only contain strings");
          }
          $1[j++] = (char *)lua_tostring(L, -1);
          lua_pop(L, 1);
       }
       $1[j] = 0;
    } else if (lua_isnil(L, $input)) {
+      // "nil" is also acceptable, equivalent as an empty table
       $1 = NULL;
+   } else {
+      return luaL_error(L, "A list of strings expected");
    }
 }
 
@@ -261,21 +267,31 @@
              (int32_t* array, size_t array_len),
              (double* array, size_t array_len) {
    if (lua_istable(L, $input)) {
+      // It should accept a table of numbers.
       $2 = lua_rawlen(L, $input);
       $1 = ($1_ltype)malloc(($2) * sizeof($*1_type));
       int i = 0, j = 0;
       while (i++ < $2) {
          lua_rawgeti(L, $input, i);
+         if (!lua_isnumber(L, -1)) {
+            // if current element cannot be converted to number, raise an error
+            lua_pop(L, 1);
+            return luaL_error(L, "List should only contain numbers");
+         }
          $1[j++] = ($*1_ltype)lua_tonumber(L, -1);
          lua_pop(L, 1);
       }
    } else if (lua_isnil(L, $input)) {
+      // "nil" is also acceptable, equivalent as an empty table
       $1 = NULL;
       $2 = 0;
+   } else {
+      // else raise an error
+      return luaL_error(L, "A list of numbers expected.");
    }
 }
 
-%typemap(in) (uint64_t* array, size_t array_len),
+%typemap(freearg) (uint64_t* array, size_t array_len),
              (uint32_t* array, size_t array_len),
              (int64_t* array, size_t array_len),
              (int32_t* array, size_t array_len),
Index: lldb/bindings/lua/CMakeLists.txt
===================================================================
--- lldb/bindings/lua/CMakeLists.txt
+++ lldb/bindings/lua/CMakeLists.txt
@@ -29,22 +29,43 @@
   add_custom_target(${swig_target} ALL VERBATIM
     COMMAND ${CMAKE_COMMAND} -E make_directory ${lldb_lua_target_dir}
     DEPENDS swig_wrapper_lua
-    COMMENT "Lua LLDB Python API")
-  create_relative_symlink(${swig_target}
-                         "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/liblldb${CMAKE_SHARED_LIBRARY_SUFFIX}"
-                         ${lldb_lua_target_dir}
-                         "lldb.so")
+    COMMENT "LLDB Lua API")
+  if(LLDB_BUILD_FRAMEWORK)
+    set(LIBLLDB_SYMLINK_DEST "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/LLDB")
+  else()
+    set(LIBLLDB_SYMLINK_DEST "${LLVM_SHLIB_OUTPUT_INTDIR}/liblldb${CMAKE_SHARED_LIBRARY_SUFFIX}")
+  endif()
+  if(WIN32)
+    if(CMAKE_BUILD_TYPE STREQUAL Debug)
+      set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb_d.pyd")
+    else()
+      set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb.pyd")
+    endif()
+  else()
+    set(LIBLLDB_SYMLINK_OUTPUT_FILE "lldb.so")
+  endif()
+  create_relative_symlink(${swig_target} ${LIBLLDB_SYMLINK_DEST}
+                          ${lldb_lua_target_dir} ${LIBLLDB_SYMLINK_OUTPUT_FILE})
   set(lldb_lua_library_target "${swig_target}-library")
   add_custom_target(${lldb_lua_library_target})
   add_dependencies(${lldb_lua_library_target} ${swig_target})
+
+  # Ensure we do the Lua post-build step when building lldb.
+  add_dependencies(lldb ${swig_target})
+
+  if(LLDB_BUILD_FRAMEWORK)
+    set(LLDB_LUA_INSTALL_PATH ${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Resources/Python)
+  else()
+    set(LLDB_LUA_INSTALL_PATH ${LLDB_LUA_RELATIVE_PATH})
+  endif()
   install(DIRECTORY ${lldb_lua_target_dir}/
           DESTINATION ${LLDB_LUA_INSTALL_PATH}
           COMPONENT ${lldb_lua_library_target})
-  # Ensure we do the Lua post-build step when building lldb.
-  add_dependencies(lldb ${swig_target})
 
   set(lldb_lua_library_install_target "install-${lldb_lua_library_target}")
-  add_llvm_install_targets(${lldb_lua_library_install_target}
-                           COMPONENT ${lldb_lua_library_target}
-                           DEPENDS ${lldb_lua_library_target})
+  if (NOT LLVM_ENABLE_IDE)
+    add_llvm_install_targets(${lldb_lua_library_install_target}
+                            COMPONENT ${lldb_lua_library_target}
+                            DEPENDS ${lldb_lua_library_target})
+  endif()
 endfunction()
Index: lldb/CMakeLists.txt
===================================================================
--- lldb/CMakeLists.txt
+++ lldb/CMakeLists.txt
@@ -52,21 +52,10 @@
 endif ()
 
 if (LLDB_ENABLE_LUA)
-   # FIXME: Lua 5.3 is hardcoded but it should support 5.3+!
-   find_program(Lua_EXECUTABLE lua5.3)
-   if (NOT Lua_EXECUTABLE)
-      message(FATAL_ERROR "Lua executable not found")
-   else ()
-      execute_process(
-         COMMAND ${Lua_EXECUTABLE}
-         -e "for w in string.gmatch(package.cpath, ';?([^;]+);?') do \
-         if string.match(w, '%?%.so') then print(string.sub(w, 1, #w - 4)) break end end"
-         OUTPUT_VARIABLE LLDB_LUA_DEFAULT_INSTALL_PATH
-         OUTPUT_STRIP_TRAILING_WHITESPACE)
-      file(TO_CMAKE_PATH ${LLDB_LUA_DEFAULT_INSTALL_PATH} LLDB_LUA_DEFAULT_INSTALL_PATH)
-      set(LLDB_LUA_INSTALL_PATH ${LLDB_LUA_DEFAULT_INSTALL_PATH}
-         CACHE STRING "Path where Lua modules are installed")
-   endif ()
+  find_program(Lua_EXECUTABLE lua5.3)
+  set(LLDB_LUA_DEFAULT_RELATIVE_PATH "lib/lua/5.3")
+  set(LLDB_LUA_RELATIVE_PATH ${LLDB_LUA_DEFAULT_RELATIVE_PATH}
+    CACHE STRING "Path where Lua modules are installed, relative to install prefix")
 endif ()
 
 if (LLDB_ENABLE_PYTHON OR LLDB_ENABLE_LUA)
@@ -113,7 +102,11 @@
 endif()
 
 if (LLDB_ENABLE_LUA)
-  set(lldb_lua_target_dir "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_INSTALL_LIBDIR}/lua")
+  if(LLDB_BUILD_FRAMEWORK)
+    set(lldb_lua_target_dir "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/Resources/Lua")
+  else()
+    set(lldb_lua_target_dir "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${LLDB_LUA_RELATIVE_PATH}")
+  endif()
   get_target_property(lldb_lua_bindings_dir swig_wrapper_lua BINARY_DIR)
   finish_swig_lua("lldb-lua" "${lldb_lua_bindings_dir}" "${lldb_lua_target_dir}")
 endif()
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to