2015-09-27 07:00:35 +08:00
|
|
|
"""
|
2019-01-19 16:50:56 +08:00
|
|
|
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2015-09-27 07:00:35 +08:00
|
|
|
|
|
|
|
Sync lldb and related source from a local machine to a remote machine.
|
|
|
|
|
|
|
|
This facilitates working on the lldb sourcecode on multiple machines
|
|
|
|
and multiple OS types, verifying changes across all.
|
|
|
|
|
|
|
|
Provides helper support for adding lldb test paths to the python path.
|
|
|
|
"""
|
2015-10-20 07:45:41 +08:00
|
|
|
|
|
|
|
from __future__ import print_function
|
Python 3 - Turn on absolute imports, and fix existing imports.
Absolute imports were introduced in Python 2.5 as a feature
(e.g. from __future__ import absolute_import), and made default
in Python 3.
When absolute imports are enabled, the import system changes in
a couple of ways:
1) The `import foo` syntax will *only* search sys.path. If `foo`
isn't in sys.path, it won't be found. Period. Without absolute
imports, the import system will also search the same directory
that the importing file resides in, so that you can easily
import from the same folder.
2) From inside a package, you can use a dot syntax to refer to higher
levels of the current package. For example, if you are in the
package lldbsuite.test.utility, then ..foo refers to
lldbsuite.test.foo. You can use this notation with the
`from X import Y` syntax to write intra-package references. For
example, using the previous locationa s a starting point, writing
`from ..support import seven` would import lldbsuite.support.seven
Since this is now the default behavior in Python 3, this means that
importing from the same directory with `import foo` *no longer works*.
As a result, the only way to have portable code is to force absolute
imports for all versions of Python.
See PEP 0328 [https://www.python.org/dev/peps/pep-0328/] for more
information about absolute and relative imports.
Differential Revision: http://reviews.llvm.org/D14342
Reviewed By: Todd Fiala
llvm-svn: 252191
2015-11-06 03:22:28 +08:00
|
|
|
from __future__ import absolute_import
|
2015-10-20 07:45:41 +08:00
|
|
|
|
Python 3 - Turn on absolute imports, and fix existing imports.
Absolute imports were introduced in Python 2.5 as a feature
(e.g. from __future__ import absolute_import), and made default
in Python 3.
When absolute imports are enabled, the import system changes in
a couple of ways:
1) The `import foo` syntax will *only* search sys.path. If `foo`
isn't in sys.path, it won't be found. Period. Without absolute
imports, the import system will also search the same directory
that the importing file resides in, so that you can easily
import from the same folder.
2) From inside a package, you can use a dot syntax to refer to higher
levels of the current package. For example, if you are in the
package lldbsuite.test.utility, then ..foo refers to
lldbsuite.test.foo. You can use this notation with the
`from X import Y` syntax to write intra-package references. For
example, using the previous locationa s a starting point, writing
`from ..support import seven` would import lldbsuite.support.seven
Since this is now the default behavior in Python 3, this means that
importing from the same directory with `import foo` *no longer works*.
As a result, the only way to have portable code is to force absolute
imports for all versions of Python.
See PEP 0328 [https://www.python.org/dev/peps/pep-0328/] for more
information about absolute and relative imports.
Differential Revision: http://reviews.llvm.org/D14342
Reviewed By: Todd Fiala
llvm-svn: 252191
2015-11-06 03:22:28 +08:00
|
|
|
# System modules
|
2015-09-27 07:00:35 +08:00
|
|
|
import os
|
2015-10-16 04:27:23 +08:00
|
|
|
import platform
|
|
|
|
import subprocess
|
2015-09-27 07:00:35 +08:00
|
|
|
import sys
|
|
|
|
|
Python 3 - Turn on absolute imports, and fix existing imports.
Absolute imports were introduced in Python 2.5 as a feature
(e.g. from __future__ import absolute_import), and made default
in Python 3.
When absolute imports are enabled, the import system changes in
a couple of ways:
1) The `import foo` syntax will *only* search sys.path. If `foo`
isn't in sys.path, it won't be found. Period. Without absolute
imports, the import system will also search the same directory
that the importing file resides in, so that you can easily
import from the same folder.
2) From inside a package, you can use a dot syntax to refer to higher
levels of the current package. For example, if you are in the
package lldbsuite.test.utility, then ..foo refers to
lldbsuite.test.foo. You can use this notation with the
`from X import Y` syntax to write intra-package references. For
example, using the previous locationa s a starting point, writing
`from ..support import seven` would import lldbsuite.support.seven
Since this is now the default behavior in Python 3, this means that
importing from the same directory with `import foo` *no longer works*.
As a result, the only way to have portable code is to force absolute
imports for all versions of Python.
See PEP 0328 [https://www.python.org/dev/peps/pep-0328/] for more
information about absolute and relative imports.
Differential Revision: http://reviews.llvm.org/D14342
Reviewed By: Todd Fiala
llvm-svn: 252191
2015-11-06 03:22:28 +08:00
|
|
|
# Third-party modules
|
|
|
|
|
|
|
|
# LLDB modules
|
|
|
|
|
2015-09-27 07:00:35 +08:00
|
|
|
|
|
|
|
def add_lldb_test_paths(check_dir):
|
2015-10-16 04:27:23 +08:00
|
|
|
# pylint: disable=line-too-long
|
2015-09-27 07:00:35 +08:00
|
|
|
"""Adds lldb test-related paths to the python path.
|
|
|
|
|
|
|
|
Starting with the given directory and working upward through
|
|
|
|
each parent directory up to the root, it looks for the lldb
|
|
|
|
test directory. When found, the lldb test directory and its
|
|
|
|
child test_runner/lib directory will be added to the python
|
|
|
|
system path.
|
|
|
|
|
|
|
|
Instructions for use:
|
|
|
|
|
|
|
|
This method supports a simple way of getting pylint to be able
|
|
|
|
to reliably lint lldb python test scripts (including the test
|
|
|
|
infrastructure itself). To do so, add the following to a
|
|
|
|
.pylintrc file in your home directory:
|
|
|
|
|
|
|
|
[Master]
|
2015-11-11 04:01:33 +08:00
|
|
|
init-hook='import os; import sys; sys.path.append(os.path.expanduser("~/path/to/lldb/packages/Python/lldbsuite/test")); import lldb_pylint_helper; lldb_pylint_helper.add_lldb_test_paths(os.getcwd()); print("sys.path={}\n".format(sys.path))'
|
2015-09-27 07:00:35 +08:00
|
|
|
|
2015-11-11 04:01:33 +08:00
|
|
|
Replace ~/path/to/lldb with a valid path to your local lldb source
|
2015-09-27 07:00:35 +08:00
|
|
|
tree. Note you can have multiple lldb source trees on your system, and
|
|
|
|
this will work just fine. The path in your .pylintrc is just needed to
|
|
|
|
find the paths needed for pylint in whatever lldb source tree you're in.
|
|
|
|
pylint will use the python files in whichever tree it is run from.
|
|
|
|
|
|
|
|
Note it is critical that the init-hook line be contained on a single line.
|
|
|
|
You can remove the print line at the end once you know the pythonpath is
|
|
|
|
getting set up the way you expect.
|
|
|
|
|
|
|
|
With these changes, you will be able to run the following, for example.
|
|
|
|
|
|
|
|
cd lldb/sourcetree/1-of-many/test/lang/c/anonymous
|
|
|
|
pylint TestAnonymous.py
|
|
|
|
|
|
|
|
This will work, and include all the lldb/sourcetree/1-of-many lldb-specific
|
|
|
|
python directories to your path.
|
|
|
|
|
|
|
|
You can then run it in another lldb source tree on the same machine like
|
|
|
|
so:
|
|
|
|
|
|
|
|
cd lldb/sourcetree/2-of-many/test/functionalities/inferior-assert
|
|
|
|
pyline TestInferiorAssert.py
|
|
|
|
|
|
|
|
and this will properly lint that file, using the lldb-specific python
|
|
|
|
directories from the 2-of-many source tree.
|
|
|
|
|
|
|
|
Note at the time I'm writing this, our tests are in pretty sad shape
|
|
|
|
as far as a stock pylint setup goes. But we need to start somewhere :-)
|
|
|
|
|
|
|
|
@param check_dir specifies a directory that will be used to start
|
|
|
|
looking for the lldb test infrastructure python library paths.
|
|
|
|
"""
|
2015-10-16 04:27:23 +08:00
|
|
|
# Add the test-related packages themselves.
|
|
|
|
add_lldb_test_package_paths(check_dir)
|
|
|
|
|
|
|
|
# Add the lldb directory itself
|
|
|
|
add_lldb_module_directory()
|
|
|
|
|
|
|
|
|
|
|
|
def add_lldb_module_directory():
|
|
|
|
"""
|
|
|
|
Desired Approach:
|
|
|
|
|
|
|
|
Part A: find an lldb
|
|
|
|
|
|
|
|
1. Walk up the parent chain from the current directory, looking for
|
|
|
|
a directory matching *build*. If we find that, use it as the
|
|
|
|
root of a directory search for an lldb[.exe] executable.
|
|
|
|
|
|
|
|
2. If 1 fails, use the path and look for an lldb[.exe] in there.
|
|
|
|
|
|
|
|
If Part A ends up with an lldb, go to part B. Otherwise, give up
|
|
|
|
on the lldb python module path.
|
|
|
|
|
|
|
|
Part B: use the output from 'lldb[.exe] -P' to find the lldb dir.
|
|
|
|
|
|
|
|
Current approach:
|
|
|
|
If Darwin, use 'xcrun lldb -P'; others: find lldb on path.
|
|
|
|
|
|
|
|
Drawback to current approach:
|
|
|
|
If the tester is changing the SB API (adding new methods), pylint
|
|
|
|
will not know about them as it is using the wrong lldb python module.
|
|
|
|
In practice, this should be minor.
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
lldb_module_path = None
|
|
|
|
|
|
|
|
if platform.system() == 'Darwin':
|
|
|
|
# Use xcrun to find the selected lldb.
|
|
|
|
lldb_module_path = subprocess.check_output(["xcrun", "lldb", "-P"])
|
|
|
|
elif platform.system() == 'Windows':
|
|
|
|
lldb_module_path = subprocess.check_output(
|
|
|
|
["lldb.exe", "-P"], shell=True)
|
|
|
|
else:
|
|
|
|
# Use the shell to run lldb from the path.
|
|
|
|
lldb_module_path = subprocess.check_output(
|
|
|
|
["lldb", "-P"], shell=True)
|
|
|
|
|
|
|
|
# Trim the result.
|
|
|
|
if lldb_module_path is not None:
|
2015-10-16 04:32:25 +08:00
|
|
|
lldb_module_path = lldb_module_path.strip()
|
2015-10-16 04:27:23 +08:00
|
|
|
|
|
|
|
# If we have a result, add it to the path
|
|
|
|
if lldb_module_path is not None and len(lldb_module_path) > 0:
|
|
|
|
sys.path.insert(0, lldb_module_path)
|
|
|
|
# pylint: disable=broad-except
|
|
|
|
except Exception as exception:
|
2015-10-20 07:45:41 +08:00
|
|
|
print("failed to find python path: {}".format(exception))
|
2015-10-16 04:32:25 +08:00
|
|
|
|
2015-10-16 04:27:23 +08:00
|
|
|
|
|
|
|
def add_lldb_test_package_paths(check_dir):
|
|
|
|
"""Adds the lldb test infrastructure modules to the python path.
|
|
|
|
|
|
|
|
See add_lldb_test_paths for more details.
|
|
|
|
|
|
|
|
@param check_dir the directory of the test.
|
|
|
|
"""
|
2015-11-11 04:01:33 +08:00
|
|
|
|
|
|
|
def child_dirs(parent_dir):
|
|
|
|
return [os.path.join(parent_dir, child)
|
|
|
|
for child in os.listdir(parent_dir)
|
|
|
|
if os.path.isdir(os.path.join(parent_dir, child))]
|
|
|
|
|
2015-09-27 07:00:35 +08:00
|
|
|
check_dir = os.path.realpath(check_dir)
|
|
|
|
while check_dir and len(check_dir) > 0:
|
2015-11-11 04:01:33 +08:00
|
|
|
# If the current directory contains a packages/Python
|
|
|
|
# directory, add that directory to the path.
|
|
|
|
packages_python_child_dir = os.path.join(
|
|
|
|
check_dir, "packages", "Python")
|
|
|
|
if os.path.exists(packages_python_child_dir):
|
|
|
|
sys.path.insert(0, packages_python_child_dir)
|
|
|
|
sys.path.insert(0, os.path.join(
|
|
|
|
packages_python_child_dir, "test_runner", "lib"))
|
|
|
|
|
|
|
|
# Handle third_party module/package directory.
|
|
|
|
third_party_module_dir = os.path.join(
|
|
|
|
check_dir, "third_party", "Python", "module")
|
|
|
|
for child_dir in child_dirs(third_party_module_dir):
|
|
|
|
# Yes, we embed the module in the module parent dir
|
|
|
|
sys.path.insert(0, child_dir)
|
|
|
|
|
|
|
|
# We're done.
|
|
|
|
break
|
|
|
|
|
2015-09-27 07:00:35 +08:00
|
|
|
# Continue looking up the parent chain until we have no more
|
|
|
|
# directories to check.
|
|
|
|
new_check_dir = os.path.dirname(check_dir)
|
|
|
|
# We're done when the new check dir is not different
|
|
|
|
# than the current one.
|
|
|
|
if new_check_dir == check_dir:
|
|
|
|
break
|
|
|
|
check_dir = new_check_dir
|