Skip to content

Commit

Permalink
[lldb] Creates _liblldb symlink from cmake
Browse files Browse the repository at this point in the history
Summary:
This is another attempt of D67993.

This change removed hard coded relative paths. This way we can generate correct result when get_python_lib() returns a different path, or LLDB_PYTHON_RELATIVE_PATH is specified directly.

By moving things out of python, we are also able to correctly process more cross compile situations. E.g. .pyd vs .so for Windows.

Subscribers: lldb-commits, mgorny

Tags: #lldb

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

llvm-svn: 374953
  • Loading branch information
hhb committed Oct 15, 2019
1 parent 666f977 commit 208e9c0
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 283 deletions.
38 changes: 37 additions & 1 deletion lldb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ if (NOT LLDB_DISABLE_PYTHON)
else()
set(lldb_python_build_path "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${LLDB_PYTHON_RELATIVE_PATH}/lldb")
endif()
get_filename_component(lldb_python_build_path ${lldb_python_build_path} ABSOLUTE)

# Add a Post-Build Event to copy over Python files and create the symlink
# to liblldb.so for the Python API(hardlink on Windows).
Expand All @@ -225,6 +224,43 @@ if (NOT LLDB_DISABLE_PYTHON)
DEPENDS ${lldb_scripts_dir}/lldb.py
COMMENT "Python script sym-linking LLDB Python API")

function(create_relative_symlink target dest_file output_dir output_name)
get_filename_component(dest_file ${dest_file} ABSOLUTE)
get_filename_component(output_dir ${output_dir} ABSOLUTE)
file(RELATIVE_PATH rel_dest_file ${output_dir} ${dest_file})
if(CMAKE_HOST_UNIX)
set(LLVM_LINK_OR_COPY create_symlink)
else()
set(LLVM_LINK_OR_COPY copy)
endif()
add_custom_command(TARGET ${target} POST_BUILD VERBATIM
COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} ${rel_dest_file} ${output_name}
WORKING_DIRECTORY ${output_dir})
endfunction()

if(LLDB_BUILD_FRAMEWORK)
set(LIBLLDB_SYMLINK_DEST "${liblldb_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(finish_swig ${LIBLLDB_SYMLINK_DEST}
${lldb_python_build_path} ${LIBLLDB_SYMLINK_OUTPUT_FILE})

if(NOT LLDB_BUILD_FRAMEWORK)
set(LLDB_ARGDUMPER_FILENAME "lldb-argdumper${CMAKE_EXECUTABLE_SUFFIX}")
create_relative_symlink(finish_swig "${LLVM_RUNTIME_OUTPUT_INTDIR}/${LLDB_ARGDUMPER_FILENAME}"
${lldb_python_build_path} ${LLDB_ARGDUMPER_FILENAME})
endif()

add_dependencies(finish_swig swig_wrapper liblldb lldb-argdumper)
set_target_properties(finish_swig swig_wrapper PROPERTIES FOLDER "lldb misc")

Expand Down
282 changes: 0 additions & 282 deletions lldb/scripts/Python/finishSwigPythonLLDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,284 +245,6 @@ def copy_lldbpy_file_to_lldb_pkg_dir(

return (bOk, strMsg)

#++---------------------------------------------------------------------------
# Details: Make the symbolic link on a Windows platform.
# Args: vstrSrcFile - (R) Source file name.
# vstrTargetFile - (R) Destination file name.
# Returns: Bool - True = function success, False = failure.
# Str - Error description on task failure.
# Throws: None.
#--


def make_symlink_windows(vstrSrcPath, vstrTargetPath):
print(("Making symlink from %s to %s" % (vstrSrcPath, vstrTargetPath)))
dbg = utilsDebug.CDebugFnVerbose("Python script make_symlink_windows()")
bOk = True
strErrMsg = ""
# If the src file doesn't exist, this is an error and we should throw.
src_stat = os.stat(vstrSrcPath)

try:
target_stat = os.stat(vstrTargetPath)
# If the target file exists but refers to a different file, delete it so that we can
# re-create the link. This can happen if you run this script once (creating a link)
# and then delete the source file (so that a brand new file gets created the next time
# you compile and link), and then re-run this script, so that both the target hardlink
# and the source file exist, but the target refers to an old copy of
# the source.
if (target_stat.st_ino == src_stat.st_ino) and (
target_stat.st_dev == src_stat.st_dev):
return (bOk, strErrMsg)

os.remove(vstrTargetPath)
except:
# If the target file don't exist, ignore this exception, we will link
# it shortly.
pass

try:
csl = ctypes.windll.kernel32.CreateHardLinkW
csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
csl.restype = ctypes.c_ubyte
if csl(vstrTargetPath, vstrSrcPath, 0) == 0:
raise ctypes.WinError()
except Exception as e:
if e.errno != 17:
bOk = False
strErrMsg = "WinError(%d): %s %s" % (
e.errno, e.strerror, strErrMsgMakeSymlink)
strErrMsg += " Src:'%s' Target:'%s'" % (
vstrSrcPath, vstrTargetPath)

return (bOk, strErrMsg)

#++---------------------------------------------------------------------------
# Details: Make the symbolic link on a UNIX style platform.
# Args: vstrSrcFile - (R) Source file name.
# vstrTargetFile - (R) Destination file name.
# Returns: Bool - True = function success, False = failure.
# Str - Error description on task failure.
# Throws: None.
#--


def make_symlink_other_platforms(vstrSrcPath, vstrTargetPath):
dbg = utilsDebug.CDebugFnVerbose(
"Python script make_symlink_other_platforms()")
bOk = True
strErrMsg = ""

try:
os.symlink(vstrSrcPath, vstrTargetPath)
except OSError as e:
bOk = False
strErrMsg = "OSError(%d): %s %s" % (
e.errno, e.strerror, strErrMsgMakeSymlink)
strErrMsg += " Src:'%s' Target:'%s'" % (vstrSrcPath, vstrTargetPath)
except:
bOk = False
strErrMsg = strErrMsgUnexpected % sys.exec_info()[0]

return (bOk, strErrMsg)


def make_symlink_native(vDictArgs, strSrc, strTarget):
eOSType = utilsOsType.determine_os_type()
bDbg = "-d" in vDictArgs
bOk = True
strErrMsg = ""

target_filename = os.path.basename(strTarget)
if eOSType == utilsOsType.EnumOsType.Unknown:
bOk = False
strErrMsg = strErrMsgOsTypeUnknown
elif eOSType == utilsOsType.EnumOsType.Windows:
if bDbg:
print((strMsgSymlinkMk % (target_filename, strSrc, strTarget)))
bOk, strErrMsg = make_symlink_windows(strSrc,
strTarget)
else:
if os.path.islink(strTarget):
if bDbg:
print((strMsgSymlinkExists % target_filename))
return (bOk, strErrMsg)
if bDbg:
print((strMsgSymlinkMk % (target_filename, strSrc, strTarget)))
bOk, strErrMsg = make_symlink_other_platforms(strSrc,
strTarget)

return (bOk, strErrMsg)

#++---------------------------------------------------------------------------
# Details: Make the symbolic link.
# Args: vDictArgs - (R) Program input parameters.
# vstrFrameworkPythonDir - (R) Python framework directory.
# vstrSrcFile - (R) Source file name.
# vstrTargetFile - (R) Destination file name.
# Returns: Bool - True = function success, False = failure.
# Str - Error description on task failure.
# Throws: None.
#--


def make_symlink(
vDictArgs,
vstrFrameworkPythonDir,
vstrSrcFile,
vstrTargetFile):
dbg = utilsDebug.CDebugFnVerbose("Python script make_symlink()")
strTarget = os.path.join(vstrFrameworkPythonDir, vstrTargetFile)
strTarget = os.path.normcase(strTarget)
strSrc = ""

os.chdir(vstrFrameworkPythonDir)
bMakeFileCalled = "-m" in vDictArgs
eOSType = utilsOsType.determine_os_type()
if not bMakeFileCalled:
strBuildDir = os.path.join("..", "..", "..")
else:
# Resolve vstrSrcFile path relatively the build directory
if eOSType == utilsOsType.EnumOsType.Windows:
# On a Windows platform the vstrFrameworkPythonDir looks like:
# llvm\\build\\Lib\\site-packages\\lldb
strBuildDir = os.path.join("..", "..", "..")
else:
# On a UNIX style platform the vstrFrameworkPythonDir looks like:
# llvm/build/lib/python2.7/site-packages/lldb
strBuildDir = os.path.join("..", "..", "..", "..")
strSrc = os.path.normcase(os.path.join(strBuildDir, vstrSrcFile))

return make_symlink_native(vDictArgs, strSrc, strTarget)


#++---------------------------------------------------------------------------
# Details: Make the symbolic that the script bridge for Python will need in
# the Python framework directory.
# Args: vDictArgs - (R) Program input parameters.
# vstrFrameworkPythonDir - (R) Python framework directory.
# vstrLiblldbName - (R) File name for _lldb library.
# vstrLiblldbDir - (R) liblldb directory.
# Returns: Bool - True = function success, False = failure.
# Str - Error description on task failure.
# Throws: None.
#--
def make_symlink_liblldb(
vDictArgs,
vstrFrameworkPythonDir,
vstrLiblldbFileName,
vstrLldbLibDir):
dbg = utilsDebug.CDebugFnVerbose("Python script make_symlink_liblldb()")
bOk = True
strErrMsg = ""
strTarget = vstrLiblldbFileName
strSrc = ""

eOSType = utilsOsType.determine_os_type()
if eOSType == utilsOsType.EnumOsType.Windows:
# When importing an extension module using a debug version of python, you
# write, for example, "import foo", but the interpreter searches for
# "foo_d.pyd"
if is_debug_interpreter():
strTarget += "_d"
strTarget += ".pyd"
else:
strTarget += ".so"

bMakeFileCalled = "-m" in vDictArgs
if not bMakeFileCalled:
strSrc = "LLDB"
else:
strLibFileExtn = ""
if eOSType == utilsOsType.EnumOsType.Windows:
strSrc = os.path.join("bin", "liblldb.dll")
else:
if eOSType == utilsOsType.EnumOsType.Darwin:
strLibFileExtn = ".dylib"
else:
strLibFileExtn = ".so"
strSrc = os.path.join(vstrLldbLibDir, "liblldb" + strLibFileExtn)

bOk, strErrMsg = make_symlink(
vDictArgs, vstrFrameworkPythonDir, strSrc, strTarget)

return (bOk, strErrMsg)

#++---------------------------------------------------------------------------
# Details: Make the symbolic link to the lldb-argdumper.
# Args: vDictArgs - (R) Program input parameters.
# vstrFrameworkPythonDir - (R) Python framework directory.
# vstrArgdumperFileName - (R) File name for lldb-argdumper.
# Returns: Bool - True = function success, False = failure.
# Str - Error description on task failure.
# Throws: None.
#--


def make_symlink_lldb_argdumper(
vDictArgs,
vstrFrameworkPythonDir,
vstrArgdumperFileName):
dbg = utilsDebug.CDebugFnVerbose(
"Python script make_symlink_lldb_argdumper()")
bOk = True
strErrMsg = ""
strTarget = vstrArgdumperFileName
strSrc = ""

eOSType = utilsOsType.determine_os_type()
if eOSType == utilsOsType.EnumOsType.Windows:
strTarget += ".exe"

bMakeFileCalled = "-m" in vDictArgs
if not bMakeFileCalled:
return (bOk, strErrMsg)
else:
strExeFileExtn = ""
if eOSType == utilsOsType.EnumOsType.Windows:
strExeFileExtn = ".exe"
strSrc = os.path.join("bin", "lldb-argdumper" + strExeFileExtn)

bOk, strErrMsg = make_symlink(
vDictArgs, vstrFrameworkPythonDir, strSrc, strTarget)

return (bOk, strErrMsg)

#++---------------------------------------------------------------------------
# Details: Make the symlink that the script bridge for Python will need in
# the Python framework directory.
# Args: vDictArgs - (R) Program input parameters.
# vstrFrameworkPythonDir - (R) Python framework directory.
# vstrLldbLibDir - (R) liblldb directory.
# Returns: Bool - True = function success, False = failure.
# strErrMsg - Error description on task failure.
# Throws: None.
#--


def create_symlinks(vDictArgs, vstrFrameworkPythonDir, vstrLldbLibDir):
dbg = utilsDebug.CDebugFnVerbose("Python script create_symlinks()")
bOk = True
strErrMsg = ""
eOSType = utilsOsType.determine_os_type()

# Make symlink for _lldb
strLibLldbFileName = "_lldb"
if bOk:
bOk, strErrMsg = make_symlink_liblldb(vDictArgs,
vstrFrameworkPythonDir,
strLibLldbFileName,
vstrLldbLibDir)

# Make symlink for lldb-argdumper
strArgdumperFileName = "lldb-argdumper"
if bOk:
bOk, strErrMsg = make_symlink_lldb_argdumper(vDictArgs,
vstrFrameworkPythonDir,
strArgdumperFileName)

return (bOk, strErrMsg)


def copy_six(vDictArgs, vstrFrameworkPythonDir):
dbg = utilsDebug.CDebugFnVerbose("Python script copy_six()")
Expand Down Expand Up @@ -723,10 +445,6 @@ def main(vDictArgs):
bOk, strMsg = find_or_create_python_dir(
vDictArgs, strFrameworkPythonDir)

if bOk:
bOk, strMsg = create_symlinks(
vDictArgs, strFrameworkPythonDir, strLldbLibDir)

bUseSystemSix = "--useSystemSix" in vDictArgs

if not bUseSystemSix and bOk:
Expand Down

0 comments on commit 208e9c0

Please sign in to comment.