[lldb] Unifying lldb python path

Based on mgorny@'s D67890

There are 3 places where python site-package path is calculated
independently:

1. finishSwigPythonLLDB.py where files are written to site-packages.

2. lldb/scripts/CMakeLists.txt where site-packages are installed.

3. ScriptInterpreterPython.cpp where site-packages are added to
PYTHONPATH.

This change creates the path once and use it everywhere. So that they
will not go out of sync.

Also it provides a chance for cross compiling users to specify the right
path for site-packages.

Subscribers: lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D68442

llvm-svn: 373991
This commit is contained in:
Haibo Huang 2019-10-07 23:49:01 +00:00
parent f4c7345b88
commit 61f471a705
8 changed files with 49 additions and 214 deletions

View File

@ -37,6 +37,16 @@ if (WIN32)
endif()
if (NOT LLDB_DISABLE_PYTHON)
execute_process(
COMMAND ${PYTHON_EXECUTABLE}
-c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(False, False, ''))"
OUTPUT_VARIABLE LLDB_PYTHON_DEFAULT_RELATIVE_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE)
file(TO_CMAKE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} LLDB_PYTHON_DEFAULT_RELATIVE_PATH)
set(LLDB_PYTHON_RELATIVE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH}
CACHE STRING "Path where Python modules are installed, relative to install prefix")
add_subdirectory(scripts)
endif ()
@ -195,6 +205,12 @@ if (NOT LLDB_DISABLE_PYTHON)
get_target_property(lldb_scripts_dir swig_wrapper BINARY_DIR)
get_target_property(liblldb_build_dir liblldb LIBRARY_OUTPUT_DIRECTORY)
if(LLDB_BUILD_FRAMEWORK)
set(lldb_python_build_path "${liblldb_build_dir}/LLDB.framework/Resources/Python/lldb")
else()
set(lldb_python_build_path "${CMAKE_BINARY_DIR}/${LLDB_PYTHON_RELATIVE_PATH}/lldb")
endif()
# Add a Post-Build Event to copy over Python files and create the symlink
# to liblldb.so for the Python API(hardlink on Windows).
add_custom_target(finish_swig ALL
@ -206,6 +222,7 @@ if (NOT LLDB_DISABLE_PYTHON)
--prefix=${CMAKE_BINARY_DIR}
--cmakeBuildConfiguration=${CMAKE_CFG_INTDIR}
--lldbLibDir=lib${LLVM_LIBDIR_SUFFIX}
--lldbPythonPath=${lldb_python_build_path}
${use_python_wrapper_from_src_dir}
${use_six_py_from_system}
VERBATIM
@ -219,6 +236,20 @@ if (NOT LLDB_DISABLE_PYTHON)
# Ensure we do the python post-build step when building lldb.
add_dependencies(lldb finish_swig)
if(NOT LLDB_BUILD_FRAMEWORK)
# Install the LLDB python module
add_custom_target(lldb-python-scripts)
add_dependencies(lldb-python-scripts finish_swig)
install(DIRECTORY ${CMAKE_BINARY_DIR}/${LLDB_PYTHON_RELATIVE_PATH}/
DESTINATION ${LLDB_PYTHON_RELATIVE_PATH}
COMPONENT lldb-scripts)
if (NOT LLVM_ENABLE_IDE)
add_llvm_install_targets(install-lldb-python-scripts
COMPONENT lldb-python-scripts
DEPENDS lldb-python-scripts)
endif()
endif()
# Add a Post-Build Event to copy the custom Python DLL to the lldb binaries dir so that Windows can find it when launching
# lldb.exe or any other executables that were linked with liblldb.
if (WIN32 AND NOT "${PYTHON_DLL}" STREQUAL "")

View File

@ -55,28 +55,3 @@ add_custom_target(swig_wrapper ALL DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/lldb.py
)
if(NOT LLDB_BUILD_FRAMEWORK)
execute_process(
COMMAND ${PYTHON_EXECUTABLE}
-c "import distutils.sysconfig, sys; print(distutils.sysconfig.get_python_lib(True, False, sys.argv[1]))"
${CMAKE_BINARY_DIR}
OUTPUT_VARIABLE SWIG_PYTHON_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND ${PYTHON_EXECUTABLE}
-c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(True, False, ''))"
OUTPUT_VARIABLE SWIG_INSTALL_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
# Install the LLDB python module
add_custom_target(lldb-python-scripts)
add_dependencies(lldb-python-scripts finish_swig)
install(DIRECTORY ${SWIG_PYTHON_DIR}/
DESTINATION ${SWIG_INSTALL_DIR}
COMPONENT lldb-scripts)
if (NOT LLVM_ENABLE_IDE)
add_llvm_install_targets(install-lldb-python-scripts
COMPONENT lldb-python-scripts
DEPENDS lldb-python-scripts)
endif()
endif()

View File

@ -597,86 +597,6 @@ def get_config_build_dir(vDictArgs, vstrFrameworkPythonDir):
return (bOk, strConfigBldDir, strErrMsg)
#++---------------------------------------------------------------------------
# Details: Determine where to put the files. Retrieve the directory path for
# Python's dist_packages/ site_package folder on a Windows platform.
# Args: vDictArgs - (R) Program input parameters.
# Returns: Bool - True = function success, False = failure.
# Str - Python Framework directory path.
# strErrMsg - Error description on task failure.
# Throws: None.
#--
def get_framework_python_dir_windows(vDictArgs):
dbg = utilsDebug.CDebugFnVerbose(
"Python script get_framework_python_dir_windows()")
bOk = True
strWkDir = ""
strErrMsg = ""
# We are being built by LLVM, so use the PYTHON_INSTALL_DIR argument,
# and append the python version directory to the end of it. Depending
# on the system other stuff may need to be put here as well.
from distutils.sysconfig import get_python_lib
strPythonInstallDir = ""
bHaveArgPrefix = "--prefix" in vDictArgs
if bHaveArgPrefix:
strPythonInstallDir = os.path.normpath(vDictArgs["--prefix"])
bHaveArgCmakeBuildConfiguration = "--cmakeBuildConfiguration" in vDictArgs
if bHaveArgCmakeBuildConfiguration:
strPythonInstallDir = os.path.join(
strPythonInstallDir,
vDictArgs["--cmakeBuildConfiguration"])
if strPythonInstallDir.__len__() != 0:
strWkDir = get_python_lib(True, False, strPythonInstallDir)
else:
strWkDir = get_python_lib(True, False)
strWkDir = os.path.normcase(os.path.join(strWkDir, "lldb"))
return (bOk, strWkDir, strErrMsg)
#++---------------------------------------------------------------------------
# Details: Retrieve the directory path for Python's dist_packages/
# site_package folder on a UNIX style platform.
# Args: vDictArgs - (R) Program input parameters.
# Returns: Bool - True = function success, False = failure.
# Str - Python Framework directory path.
# strErrMsg - Error description on task failure.
# Throws: None.
#--
def get_framework_python_dir_other_platforms(vDictArgs):
dbg = utilsDebug.CDebugFnVerbose(
"Python script get_framework_python_dir_other_platform()")
bOk = True
strWkDir = ""
strErrMsg = ""
bDbg = "-d" in vDictArgs
bMakeFileCalled = "-m" in vDictArgs
if bMakeFileCalled:
dbg.dump_text("Built by LLVM")
return get_framework_python_dir_windows(vDictArgs)
else:
dbg.dump_text("Built by XCode")
# We are being built by XCode, so all the lldb Python files can go
# into the LLDB.framework/Resources/Python subdirectory.
strWkDir = vDictArgs["--targetDir"]
strWkDir = os.path.join(strWkDir, "LLDB.framework")
if os.path.exists(strWkDir):
if bDbg:
print((strMsgFoundLldbFrameWkDir % strWkDir))
strWkDir = os.path.join(strWkDir, "Resources", "Python", "lldb")
strWkDir = os.path.normcase(strWkDir)
else:
bOk = False
strErrMsg = strErrMsgFrameWkPyDirNotExist % strWkDir
return (bOk, strWkDir, strErrMsg)
#++---------------------------------------------------------------------------
# Details: Retrieve the directory path for Python's dist_packages/
@ -694,19 +614,8 @@ def get_framework_python_dir(vDictArgs):
dbg = utilsDebug.CDebugFnVerbose(
"Python script get_framework_python_dir()")
bOk = True
strWkDir = ""
strErrMsg = ""
eOSType = utilsOsType.determine_os_type()
if eOSType == utilsOsType.EnumOsType.Unknown:
bOk = False
strErrMsg = strErrMsgOsTypeUnknown
elif eOSType == utilsOsType.EnumOsType.Windows:
bOk, strWkDir, strErrMsg = get_framework_python_dir_windows(vDictArgs)
else:
bOk, strWkDir, strErrMsg = get_framework_python_dir_other_platforms(
vDictArgs)
strWkDir = os.path.normpath(vDictArgs["--lldbPythonPath"])
return (bOk, strWkDir, strErrMsg)
#++---------------------------------------------------------------------------

View File

@ -179,6 +179,7 @@ def validate_arguments(vArgv):
"prefix=",
"cmakeBuildConfiguration=",
"lldbLibDir=",
"lldbPythonPath=",
"argsFile",
"useSystemSix"]
dictArgReq = {"-h": "o", # o = optional, m = mandatory
@ -191,7 +192,8 @@ def validate_arguments(vArgv):
"--cmakeBuildConfiguration": "o",
"--lldbLibDir": "o",
"--argsFile": "o",
"--useSystemSix": "o"}
"--useSystemSix": "o",
"--lldbPythonPath": "m"}
# Check for mandatory parameters
nResult, dictArgs, strMsg = utilsArgsParse.parse(vArgv, strListArgs,
@ -293,11 +295,9 @@ def run_post_process_for_each_script_supported(vDictArgs):
# Iterate script directory find any script language directories
for scriptLang in listDirs:
# __pycache__ is a magic directory in Python 3 that holds .pyc files
if scriptLang != "__pycache__" and scriptLang != "swig_bot_lib":
dbg.dump_text("Executing language script for \'%s\'" % scriptLang)
nResult, strStatusMsg = run_post_process(
scriptLang, strFinishFileName, vDictArgs)
dbg.dump_text("Executing language script for \'%s\'" % scriptLang)
nResult, strStatusMsg = run_post_process(
scriptLang, strFinishFileName, vDictArgs)
if nResult < 0:
break
@ -337,13 +337,6 @@ def main(vArgv):
if gbDbgFlag:
print_out_input_parameters(dictArgs)
# Check to see if we were called from the Makefile system. If we were, check
# if the caller wants SWIG to generate a dependency file.
# Not used in this program, but passed through to the language script file
# called by this program
global gbMakeFileFlag
gbMakeFileFlag = "-m" in dictArgs
nResult, strMsg = run_post_process_for_each_script_supported(dictArgs)
program_exit(nResult, strMsg)

View File

@ -1,44 +0,0 @@
import distutils.sysconfig
import os
import platform
import re
import sys
def get_python_relative_libdir():
"""Returns the appropropriate python libdir relative to the build directory.
@param exe_path the path to the lldb executable
@return the python path that needs to be added to sys.path (PYTHONPATH)
in order to find the lldb python module.
"""
if platform.system() != 'Linux':
return None
# We currently have a bug in lldb -P that does not account for
# architecture variants in python paths for
# architecture-specific modules. Handle the lookup here.
# When that bug is fixed, we should just ask lldb for the
# right answer always.
arch_specific_libdir = distutils.sysconfig.get_python_lib(True, False)
split_libdir = arch_specific_libdir.split(os.sep)
lib_re = re.compile(r"^lib.*$")
for i in range(len(split_libdir)):
match = lib_re.match(split_libdir[i])
if match is not None:
# We'll call this the relative root of the lib dir.
# Things like RHEL will have an arch-specific python
# lib dir, which isn't 'lib' on x86_64.
return os.sep.join(split_libdir[i:])
# Didn't resolve it.
return None
if __name__ == '__main__':
lib_dir = get_python_relative_libdir()
if lib_dir is not None:
sys.stdout.write(lib_dir)
sys.exit(0)
else:
sys.exit(1)

View File

@ -1,15 +1,7 @@
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
# Call a python script to gather the arch-specific libdir for
# modules like the lldb module.
execute_process(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../../../scripts/get_relative_lib_dir.py
RESULT_VARIABLE get_libdir_status
OUTPUT_VARIABLE relative_libdir
)
if (get_libdir_status EQUAL 0)
add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${relative_libdir}")
endif()
if(NOT LLDB_PYTHON_RELATIVE_PATH)
message(FATAL_ERROR "LLDB_PYTHON_RELATIVE_PATH is not set.")
endif()
add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${LLDB_PYTHON_RELATIVE_PATH}")
add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
PythonDataObjects.cpp

View File

@ -305,39 +305,20 @@ void ScriptInterpreterPython::ComputePythonDirForApple(
auto rend = llvm::sys::path::rend(path_ref);
auto framework = std::find(rbegin, rend, "LLDB.framework");
if (framework == rend) {
ComputePythonDirForPosix(path);
ComputePythonDir(path);
return;
}
path.resize(framework - rend);
llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");
}
void ScriptInterpreterPython::ComputePythonDirForPosix(
void ScriptInterpreterPython::ComputePythonDir(
llvm::SmallVectorImpl<char> &path) {
auto style = llvm::sys::path::Style::posix;
#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
// Build the path by backing out of the lib dir, then building with whatever
// the real python interpreter uses. (e.g. lib for most, lib64 on RHEL
// x86_64).
llvm::sys::path::remove_filename(path, style);
llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR);
#else
llvm::sys::path::append(path, style,
"python" + llvm::Twine(PY_MAJOR_VERSION) + "." +
llvm::Twine(PY_MINOR_VERSION),
"site-packages");
#endif
}
void ScriptInterpreterPython::ComputePythonDirForWindows(
llvm::SmallVectorImpl<char> &path) {
auto style = llvm::sys::path::Style::windows;
llvm::sys::path::remove_filename(path, style);
llvm::sys::path::append(path, style, "lib", "site-packages");
// This will be injected directly through FileSpec.GetDirectory().SetString(),
// so we need to normalize manually.
std::replace(path.begin(), path.end(), '\\', '/');
// x86_64, or bin on Windows).
llvm::sys::path::remove_filename(path);
llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR);
}
FileSpec ScriptInterpreterPython::GetPythonDir() {
@ -350,11 +331,10 @@ FileSpec ScriptInterpreterPython::GetPythonDir() {
#if defined(__APPLE__)
ComputePythonDirForApple(path);
#elif defined(_WIN32)
ComputePythonDirForWindows(path);
#else
ComputePythonDirForPosix(path);
ComputePythonDir(path);
#endif
llvm::sys::path::native(path);
spec.GetDirectory().SetString(path);
return spec;
}();

View File

@ -48,8 +48,7 @@ public:
protected:
static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path);
static void ComputePythonDirForPosix(llvm::SmallVectorImpl<char> &path);
static void ComputePythonDirForWindows(llvm::SmallVectorImpl<char> &path);
static void ComputePythonDir(llvm::SmallVectorImpl<char> &path);
};
} // namespace lldb_private