<div dir="ltr">Is there any way to have the step that runs the swig executable not be part of this script? Seems like running swig should be a build step, and running these scripts on the output of swig should be a step that follows</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Nov 16, 2015 at 11:20 PM Todd Fiala via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: tfiala<br>
Date: Tue Nov 17 01:17:38 2015<br>
New Revision: 253317<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=253317&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=253317&view=rev</a><br>
Log:<br>
Add Pythonic language binding wrapper generation script.<br>
<br>
This is only used by Xcode at the moment. It replaces the<br>
buildSwigWrapperClasses.py and related per-script-language<br>
scripts. It also fixes a couple bugs in those w/r/t Xcode<br>
usage:<br>
<br>
* the presence of the GCC_PREPROCESSOR_DEFINITIONS env var<br>
should not be short-circuiting generation of the language<br>
binding; rather, only if LLDB_DISABLE_PYTHON is present<br>
within that environment variable.<br>
<br>
* some logic around what to do when building in "non-Makefile"<br>
mode. I've switched the handling of that to be on a<br>
"--framework" flag - if specified, we build an OS X-style<br>
framework; otherwise, we go with non.<br>
<br>
Putting this up now only attached to the Xcode build so<br>
others can look at it but not be affected by it yet.<br>
After this, I'll tackle the finalizer, along with trying<br>
it locally on Linux.<br>
<br>
Added:<br>
lldb/trunk/scripts/Python/prepare_binding_Python.py<br>
lldb/trunk/scripts/prepare_bindings.py (with props)<br>
Modified:<br>
lldb/trunk/lldb.xcodeproj/project.pbxproj<br>
<br>
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=253317&r1=253316&r2=253317&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=253317&r1=253316&r2=253317&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)<br>
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Nov 17 01:17:38 2015<br>
@@ -5984,7 +5984,7 @@<br>
isa = PBXNativeTarget;<br>
buildConfigurationList = 2668020B115FD0EE008E1FE4 /* Build configuration list for PBXNativeTarget "LLDB" */;<br>
buildPhases = (<br>
- 26DC6A5813380D4300FF7998 /* Build swig wrapper classes */,<br>
+ 26DC6A5813380D4300FF7998 /* Prepare Swig Bindings */,<br>
26680202115FD0ED008E1FE4 /* Headers */,<br>
26680203115FD0ED008E1FE4 /* Resources */,<br>
26680204115FD0ED008E1FE4 /* Sources */,<br>
@@ -6214,19 +6214,19 @@<br>
shellPath = /bin/sh;<br>
shellScript = "perl $SRCROOT/scripts/<a href="http://build-llvm.pl" rel="noreferrer" target="_blank">build-llvm.pl</a>";<br>
};<br>
- 26DC6A5813380D4300FF7998 /* Build swig wrapper classes */ = {<br>
+ 26DC6A5813380D4300FF7998 /* Prepare Swig Bindings */ = {<br>
isa = PBXShellScriptBuildPhase;<br>
buildActionMask = 2147483647;<br>
files = (<br>
);<br>
inputPaths = (<br>
);<br>
- name = "Build swig wrapper classes";<br>
+ name = "Prepare Swig Bindings";<br>
outputPaths = (<br>
);<br>
runOnlyForDeploymentPostprocessing = 0;<br>
- shellPath = /bin/sh;<br>
- shellScript = "$SRCROOT/scripts/build-swig-wrapper-classes.sh $SRCROOT $TARGET_BUILD_DIR $CONFIGURATION_BUILD_DIR \"\"\n";<br>
+ shellPath = /bin/bash;<br>
+ shellScript = "/usr/bin/python $SRCROOT/scripts/prepare_bindings.py --framework --src-root $SRCROOT --target-dir $TARGET_BUILD_DIR --config-build-dir $CONFIGURATION_BUILD_DIR --swig-executable `which swig`";<br>
};<br>
4959511A1A1ACE9500F6F8FC /* Install Clang compiler headers */ = {<br>
isa = PBXShellScriptBuildPhase;<br>
<br>
Added: lldb/trunk/scripts/Python/prepare_binding_Python.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/prepare_binding_Python.py?rev=253317&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/prepare_binding_Python.py?rev=253317&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/scripts/Python/prepare_binding_Python.py (added)<br>
+++ lldb/trunk/scripts/Python/prepare_binding_Python.py Tue Nov 17 01:17:38 2015<br>
@@ -0,0 +1,435 @@<br>
+"""<br>
+ The LLVM Compiler Infrastructure<br>
+<br>
+This file is distributed under the University of Illinois Open Source<br>
+License. See LICENSE.TXT for details.<br>
+<br>
+Python binding preparation script.<br>
+"""<br>
+<br>
+# Python modules:<br>
+from __future__ import print_function<br>
+<br>
+import logging<br>
+import os<br>
+import re<br>
+import shutil<br>
+import subprocess<br>
+import sys<br>
+<br>
+<br>
+class SwigSettings(object):<br>
+ """Provides a single object to represent swig files and settings."""<br>
+ def __init__(self):<br>
+ self.extensions_file = None<br>
+ self.header_files = None<br>
+ self.input_file = None<br>
+ self.interface_files = None<br>
+ self.output_file = None<br>
+ self.safecast_file = None<br>
+ self.typemaps_file = None<br>
+ self.wrapper_file = None<br>
+<br>
+ @classmethod<br>
+ def _any_files_newer(cls, files, check_mtime):<br>
+ """Returns if any of the given files has a newer modified time.<br>
+<br>
+ @param cls the class<br>
+ @param files a list of zero or more file paths to check<br>
+ @param check_mtime the modification time to use as a reference.<br>
+<br>
+ @return True if any file's modified time is newer than check_mtime.<br>
+ """<br>
+ for path in files:<br>
+ path_mtime = os.path.getmtime(path)<br>
+ if path_mtime > check_mtime:<br>
+ # This path was modified more recently than the<br>
+ # check_mtime.<br>
+ return True<br>
+ # If we made it here, nothing was newer than the check_mtime<br>
+ return False<br>
+<br>
+ @classmethod<br>
+ def _file_newer(cls, path, check_mtime):<br>
+ """Tests how recently a file has been modified.<br>
+<br>
+ @param cls the class<br>
+ @param path a file path to check<br>
+ @param check_mtime the modification time to use as a reference.<br>
+<br>
+ @return True if the file's modified time is newer than check_mtime.<br>
+ """<br>
+ path_mtime = os.path.getmtime(path)<br>
+ return path_mtime > check_mtime<br>
+<br>
+ def output_out_of_date(self):<br>
+ """Returns whether the output file is out of date.<br>
+<br>
+ Compares output file time to all the input files.<br>
+<br>
+ @return True if any of the input files are newer than<br>
+ the output file, or if the output file doesn't exist;<br>
+ False otherwise.<br>
+ """<br>
+ if not os.path.exists(self.output_file):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, missing binding output file")<br>
+ return True<br>
+ output_mtime = os.path.getmtime(self.output_file)<br>
+ if self._any_files_newer(self.header_files, output_mtime):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, header files newer")<br>
+ return True<br>
+ if self._any_files_newer(self.interface_files, output_mtime):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, interface files newer")<br>
+ return True<br>
+ if self._file_newer(self.input_file, output_mtime):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, swig input file newer")<br>
+ return True<br>
+ if self._file_newer(self.extensions_file, output_mtime):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, swig extensions file newer")<br>
+ return True<br>
+ if self._file_newer(self.wrapper_file, output_mtime):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, swig wrapper file newer")<br>
+ return True<br>
+ if self._file_newer(self.typemaps_file, output_mtime):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, swig typemaps file newer")<br>
+ return True<br>
+ if self._file_newer(self.safecast_file, output_mtime):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("will generate, swig safecast file newer")<br>
+ return True<br>
+<br>
+ # If we made it here, nothing is newer than the output file.<br>
+ # Thus, the output file is not out of date.<br>
+ return False<br>
+<br>
+<br>
+def get_header_files(options):<br>
+ """Returns a list of paths to C++ header files for the LLDB API.<br>
+<br>
+ These are the files that define the C++ API that will be wrapped by Python.<br>
+<br>
+ @param options the dictionary of options parsed from the command line.<br>
+<br>
+ @return a list of full paths to the include files used to define the public<br>
+ LLDB C++ API.<br>
+ """<br>
+<br>
+ header_file_paths = []<br>
+ header_base_dir = os.path.join(options.src_root, "include", "lldb")<br>
+<br>
+ # Specify the include files in include/lldb that are not easy to<br>
+ # grab programatically.<br>
+ for header in [<br>
+ "lldb-defines.h",<br>
+ "lldb-enumerations.h",<br>
+ "lldb-forward.h",<br>
+ "lldb-types.h"]:<br>
+ header_file_paths.append(os.path.normcase(<br>
+ os.path.join(header_base_dir, header)))<br>
+<br>
+ # Include the main LLDB.h file.<br>
+ api_dir = os.path.join(header_base_dir, "API")<br>
+ header_file_paths.append(os.path.normcase(<br>
+ os.path.join(api_dir, "LLDB.h")))<br>
+<br>
+ filename_regex = re.compile(r"^SB.+\.h$")<br>
+<br>
+ # Include all the SB*.h files in the API dir.<br>
+ for filename in os.listdir(api_dir):<br>
+ if filename_regex.match(filename):<br>
+ header_file_paths.append(<br>
+ os.path.normcase(os.path.join(api_dir, filename)))<br>
+<br>
+ logging.debug("found public API header file paths: %s", header_file_paths)<br>
+ return header_file_paths<br>
+<br>
+<br>
+def get_interface_files(options):<br>
+ """Returns a list of interface files used as input to swig.<br>
+<br>
+ @param options the options dictionary parsed from the command line args.<br>
+<br>
+ @return a list of full paths to the interface (.i) files used to describe<br>
+ the public API language binding.<br>
+ """<br>
+ interface_file_paths = []<br>
+ interface_dir = os.path.join(options.src_root, "scripts", "interface")<br>
+<br>
+ for filepath in [f for f in os.listdir(interface_dir)<br>
+ if os.path.splitext(f)[1] == ".i"]:<br>
+ interface_file_paths.append(<br>
+ os.path.normcase(os.path.join(interface_dir, filepath)))<br>
+<br>
+ logging.debug("found swig interface files: %s", interface_file_paths)<br>
+ return interface_file_paths<br>
+<br>
+<br>
+def remove_ignore_enoent(filename):<br>
+ """Removes given file, ignoring error if it doesn't exist.<br>
+<br>
+ @param filename the path of the file to remove.<br>
+ """<br>
+ try:<br>
+ os.remove(filename)<br>
+ except OSError as error:<br>
+ import errno<br>
+ if error.errno != errno.ENOENT:<br>
+ raise<br>
+<br>
+<br>
+def do_swig_rebuild(options, dependency_file, config_build_dir, settings):<br>
+ """Generates Python bindings file from swig.<br>
+<br>
+ This method will do a sys.exit() if something fails. If it returns to<br>
+ the caller, it succeeded.<br>
+<br>
+ @param options the parsed command line options structure.<br>
+ @param dependency_file path to the bindings dependency file<br>
+ to be generated; otherwise, None if a dependency file is not<br>
+ to be generated.<br>
+ @param config_build_dir used as the output directory used by swig<br>
+ @param settings the SwigSettings that specify a number of aspects used<br>
+ to configure building the Python binding with swig (mostly paths)<br>
+ """<br>
+ if options.generate_dependency_file:<br>
+ temp_dep_file_path = dependency_file + ".tmp"<br>
+<br>
+ # Build the SWIG args list<br>
+ command = [<br>
+ options.swig_executable,<br>
+ "-c++",<br>
+ "-shadow",<br>
+ "-python",<br>
+ "-threads",<br>
+ "-I\"%s\"" % os.path.normcase(<br>
+ os.path.join(options.src_root, "include")),<br>
+ "-I\"%s\"" % os.path.normcase("./."),<br>
+ "-D__STDC_LIMIT_MACROS",<br>
+ "-D__STDC_CONSTANT_MACROS"]<br>
+ if options.generate_dependency_file:<br>
+ command.append("-MMD -MF \"%s\"" % temp_dep_file_path)<br>
+ command.extend([<br>
+ "-outdir", "\"%s\"" % config_build_dir,<br>
+ "-o", "\"%s\"" % settings.output_file,<br>
+ "\"%s\"" % settings.input_file<br>
+ ])<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("running swig with: %s", command)<br>
+<br>
+ # Execute swig<br>
+ process = subprocess.Popen(<br>
+ ' '.join(command),<br>
+ stdout=subprocess.PIPE,<br>
+ stderr=subprocess.PIPE,<br>
+ shell=True)<br>
+ # Wait for SWIG process to terminate<br>
+ swig_stdout, swig_stderr = process.communicate()<br>
+ return_code = process.returncode<br>
+ if return_code != 0:<br>
+ logging.error(<br>
+ "swig failed with error code %d: stdout=%s, stderr=%s",<br>
+ return_code,<br>
+ swig_stdout,<br>
+ swig_stderr)<br>
+ logging.error(<br>
+ "command line:\n%s", ' '.join(command))<br>
+ sys.exit(return_code)<br>
+<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("swig generation succeeded")<br>
+ if swig_stdout is not None and len(swig_stdout) > 0:<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("swig output: %s", swig_stdout)<br>
+<br>
+ # Move the depedency file we just generated to the proper location.<br>
+ if options.generate_dependency_file:<br>
+ if os.path.exists(temp_dep_file_path):<br>
+ shutil.move(temp_dep_file_path, dependency_file)<br>
+ else:<br>
+ logging.error(<br>
+ "failed to generate Python binding depedency file '%s'",<br>
+ temp_dep_file_path)<br>
+ if os.path.exists(dependency_file):<br>
+ # Delete the old one.<br>
+ os.remove(dependency_file)<br>
+ sys.exit(-10)<br>
+<br>
+<br>
+def run_python_script(script_and_args):<br>
+ """Runs a python script, logging appropriately.<br>
+<br>
+ If the command returns anything non-zero, it is registered as<br>
+ an error and exits the program.<br>
+<br>
+ @param script_and_args the python script to execute, along with<br>
+ the command line arguments to pass to it.<br>
+ """<br>
+ command_line = "%s %s" % (sys.executable, script_and_args)<br>
+ process = subprocess.Popen(command_line, shell=True)<br>
+ script_stdout, script_stderr = process.communicate()<br>
+ return_code = process.returncode<br>
+ if return_code != 0:<br>
+ logging.error("failed to run '%s': %s", command_line, script_stderr)<br>
+ sys.exit(return_code)<br>
+ else:<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("ran script '%s'", command_line)<br>
+ if script_stdout is not None:<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("output: %s", script_stdout)<br>
+<br>
+<br>
+def do_modify_python_lldb(options, config_build_dir):<br>
+ """Executes the modify-python-lldb.py script.<br>
+<br>
+ @param options the parsed command line arguments<br>
+ @param config_build_dir the directory where the Python output was created.<br>
+ """<br>
+ script_path = os.path.normcase(<br>
+ os.path.join(<br>
+ options.src_root,<br>
+ "scripts",<br>
+ "Python",<br>
+ "modify-python-lldb.py"))<br>
+<br>
+ if not os.path.exists(script_path):<br>
+ logging.error("failed to find python script: '%s'", script_path)<br>
+ sys.exit(-11)<br>
+<br>
+ script_invocation = "%s %s" % (script_path, config_build_dir)<br>
+ run_python_script(script_invocation)<br>
+<br>
+<br>
+def get_python_module_path(options):<br>
+ """Returns the location where the lldb Python module should be placed.<br>
+<br>
+ @param options dictionary of options parsed from the command line.<br>
+<br>
+ @return the directory where the lldb module should be placed.<br>
+ """<br>
+ if options.framework:<br>
+ # Caller wants to use the OS X framework packaging.<br>
+<br>
+ # We are packaging in an OS X-style framework bundle. The<br>
+ # module dir will be within the<br>
+ # LLDB.framework/Resources/Python subdirectory.<br>
+ return os.path.join(<br>
+ options.target_dir,<br>
+ "LLDB.framework",<br>
+ "Resources",<br>
+ "Python",<br>
+ "lldb")<br>
+ else:<br>
+ from distutils.sysconfig import get_python_lib<br>
+<br>
+ if options.prefix is not None:<br>
+ module_path = get_python_lib(True, False, options.prefix)<br>
+ else:<br>
+ module_path = get_python_lib(True, False)<br>
+ return os.path.normcase(<br>
+ os.path.join(module_path, "lldb"))<br>
+<br>
+<br>
+def main(options):<br>
+ """Pepares the Python language binding to LLDB.<br>
+<br>
+ @param options the parsed command line argument dictionary<br>
+ """<br>
+ # Setup generated dependency file options.<br>
+ if options.generate_dependency_file:<br>
+ dependency_file = os.path.normcase(os.path.join(<br>
+ options.target_dir, "LLDBWrapPython.cpp.d"))<br>
+ else:<br>
+ dependency_file = None<br>
+<br>
+ # Keep track of all the swig-related settings.<br>
+ settings = SwigSettings()<br>
+<br>
+ # Determine the final binding file path.<br>
+ settings.output_file = os.path.normcase(<br>
+ os.path.join(options.target_dir, "LLDBWrapPython.cpp"))<br>
+<br>
+ # Touch the output file (but don't really generate it) if python<br>
+ # is disabled.<br>
+ disable_python = os.getenv("LLDB_DISABLE_PYTHON", None)<br>
+ if disable_python is not None and disable_python == "1":<br>
+ remove_ignore_enoent(settings.output_file)<br>
+ # Touch the file.<br>
+ open(settings.output_file, 'w').close()<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>(<br>
+ "Created empty python binding file due to LLDB_DISABLE_PYTHON "<br>
+ "being set")<br>
+ return<br>
+<br>
+ # We also check the GCC_PREPROCESSOR_DEFINITIONS to see if it<br>
+ # contains LLDB_DISABLE_PYTHON. If so, we skip generating<br>
+ # the binding.<br>
+ gcc_preprocessor_defs = os.getenv("GCC_PREPROCESSOR_DEFINITIONS", None)<br>
+ if gcc_preprocessor_defs is not None:<br>
+ if re.search(r"LLDB_DISABLE_PYTHON", gcc_preprocessor_defs):<br>
+ remove_ignore_enoent(settings.output_file)<br>
+ # Touch the file<br>
+ open(settings.output_file, 'w').close()<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>(<br>
+ "Created empty python binding file due to "<br>
+ "finding LLDB_DISABLE_PYTHON in GCC_PREPROCESSOR_DEFINITIONS")<br>
+ return<br>
+<br>
+ # Setup paths used during swig invocation.<br>
+ settings.input_file = os.path.normcase(<br>
+ os.path.join(options.src_root, "scripts", "lldb.swig"))<br>
+ scripts_python_dir = os.path.dirname(os.path.realpath(__file__))<br>
+ settings.extensions_file = os.path.normcase(<br>
+ os.path.join(scripts_python_dir, "python-extensions.swig"))<br>
+ settings.wrapper_file = os.path.normcase(<br>
+ os.path.join(scripts_python_dir, "python-wrapper.swig"))<br>
+ settings.typemaps_file = os.path.normcase(<br>
+ os.path.join(scripts_python_dir, "python-typemaps.swig"))<br>
+ settings.safecast_file = os.path.normcase(<br>
+ os.path.join(scripts_python_dir, "python-swigsafecast.swig"))<br>
+<br>
+ settings.header_files = get_header_files(options)<br>
+ settings.interface_files = get_interface_files(options)<br>
+<br>
+ generate_output = settings.output_out_of_date()<br>
+<br>
+ # Determine where to put the module.<br>
+ python_module_path = get_python_module_path(options)<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("python module path: %s", python_module_path)<br>
+<br>
+ # Handle the configuration build dir.<br>
+ if options.config_build_dir is not None:<br>
+ config_build_dir = options.config_build_dir<br>
+ else:<br>
+ config_build_dir = python_module_path<br>
+<br>
+ # Allow missing/non-link _lldb.so to force regeneration.<br>
+ if not generate_output:<br>
+ # Ensure the _lldb.so file exists.<br>
+ so_path = os.path.join(python_module_path, "_lldb.so")<br>
+ if not os.path.exists(so_path) or not os.path.islink(so_path):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("_lldb.so doesn't exist or isn't a symlink")<br>
+ generate_output = True<br>
+<br>
+ # Allow missing __init__.py to force regeneration.<br>
+ if not generate_output:<br>
+ # Ensure the __init__.py for the lldb module can be found.<br>
+ init_path = os.path.join(python_module_path, "__init__.py")<br>
+ if not os.path.exists(init_path):<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("__init__.py doesn't exist")<br>
+ generate_output = True<br>
+<br>
+ if not generate_output:<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>(<br>
+ "Skipping Python binding generation: everything is up to date")<br>
+ return<br>
+<br>
+ # Generate the Python binding with swig.<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("Python binding is out of date, regenerating")<br>
+ do_swig_rebuild(options, dependency_file, config_build_dir, settings)<br>
+ if options.generate_dependency_file:<br>
+ return<br>
+<br>
+ # Post process the swig-generated file.<br>
+ do_modify_python_lldb(options, config_build_dir)<br>
+<br>
+<br>
+# This script can be called by another Python script by calling the main()<br>
+# function directly<br>
+if __name__ == "__main__":<br>
+ print("Script cannot be called directly.")<br>
+ sys.exit(-1)<br>
<br>
Added: lldb/trunk/scripts/prepare_bindings.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/prepare_bindings.py?rev=253317&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/prepare_bindings.py?rev=253317&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/scripts/prepare_bindings.py (added)<br>
+++ lldb/trunk/scripts/prepare_bindings.py Tue Nov 17 01:17:38 2015<br>
@@ -0,0 +1,196 @@<br>
+#!/usr/bin/env python<br>
+"""<br>
+ The LLVM Compiler Infrastructure<br>
+<br>
+This file is distributed under the University of Illinois Open Source<br>
+License. See LICENSE.TXT for details.<br>
+<br>
+Prepares language bindings for LLDB build process. Run with --help<br>
+to see a description of the supported command line arguments.<br>
+"""<br>
+<br>
+# Python modules:<br>
+import argparse<br>
+import logging<br>
+import os<br>
+import sys<br>
+<br>
+<br>
+def prepare_binding_for_language(scripts_dir, script_lang, options):<br>
+ """Prepares the binding for a specific language.<br>
+<br>
+ @param scripts_dir the full path to the scripts source directory.<br>
+ @param script_lang the name of the script language. Should be a child<br>
+ directory within the scripts dir, and should contain a<br>
+ prepare_scripts_{script_lang}.py script file in it.<br>
+ @param options the dictionary of parsed command line options.<br>
+<br>
+ There is no return value. If it returns, the process succeeded; otherwise,<br>
+ the process will exit where it fails.<br>
+ """<br>
+ # Ensure the language-specific prepare module exists.<br>
+ script_name = "prepare_binding_{}.py".format(script_lang)<br>
+ lang_path = os.path.join(scripts_dir, script_lang)<br>
+ script_path = os.path.join(lang_path, script_name)<br>
+ if not os.path.exists(script_path):<br>
+ logging.error(<br>
+ "failed to find prepare script for language '%s' at '%s'",<br>
+ script_lang,<br>
+ script_path)<br>
+ sys.exit(-9)<br>
+<br>
+ # Include this language-specific directory in the Python search<br>
+ # path.<br>
+ sys.path.append(os.path.normcase(lang_path))<br>
+<br>
+ # Execute the specific language script<br>
+ module_name = os.path.splitext(script_name)[0]<br>
+ module = __import__(module_name)<br>
+ module.main(options)<br>
+<br>
+ # Remove the language-specific directory from the Python search path.<br>
+ sys.path.remove(os.path.normcase(lang_path))<br>
+<br>
+<br>
+def prepare_all_bindings(options):<br>
+ """Prepares bindings for each of the languages supported.<br>
+<br>
+ @param options the parsed arguments from the command line<br>
+<br>
+ @return the exit value for the program. 0 is success, all othes<br>
+ indicate some kind of failure.<br>
+ """<br>
+ # Check for the existence of the SWIG scripts folder<br>
+ scripts_dir = os.path.join(options.src_root, "scripts")<br>
+ if not os.path.exists(scripts_dir):<br>
+ logging.error("failed to find scripts dir: '%s'", scripts_dir)<br>
+ sys.exit(-8)<br>
+<br>
+ # Collect list of child directories. We expect there to be one<br>
+ # for each supported script language.<br>
+ child_dirs = [f for f in os.listdir(scripts_dir)<br>
+ if os.path.isdir(os.path.join(scripts_dir, f))]<br>
+<br>
+ # Remove directories that do not represent script languages.<br>
+ for removal_dir in [".svn", "interface", "__pycache__", "sphinx"]:<br>
+ if removal_dir in child_dirs:<br>
+ child_dirs.remove(removal_dir)<br>
+<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("found script directories: %s", child_dirs)<br>
+<br>
+ # Iterate script directory find any script language directories<br>
+ for script_lang in child_dirs:<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("executing language script for: '%s'", script_lang)<br>
+ prepare_binding_for_language(scripts_dir, script_lang, options)<br>
+<br>
+<br>
+def process_args(args):<br>
+ """Returns options processed from the provided command line.<br>
+<br>
+ @param args the command line to process.<br>
+ """<br>
+<br>
+ # Setup the parser arguments that are accepted.<br>
+ parser = argparse.ArgumentParser(<br>
+ description="Prepare language bindings for LLDB build.")<br>
+<br>
+ # Arguments to control logging verbosity.<br>
+ parser.add_argument(<br>
+ "--debug", "-d",<br>
+ action="store_true",<br>
+ help="Set program logging level to DEBUG.")<br>
+ parser.add_argument(<br>
+ "--verbose", "-v",<br>
+ action="count",<br>
+ default=0,<br>
+ help=(<br>
+ "Increase logging verbosity level. Default: only error and "<br>
+ "higher are displayed. Each -v increases level of verbosity."))<br>
+<br>
+ # Arguments to control whether we're building an OS X-style<br>
+ # framework. This is the opposite of the older "-m" (makefile)<br>
+ # option.<br>
+ parser.add_argument(<br>
+ "--config-build-dir",<br>
+ "--cfgBldDir",<br>
+ help=(<br>
+ "Configuration build dir, will use python module path "<br>
+ "if unspecified."))<br>
+ parser.add_argument(<br>
+ "--framework",<br>
+ action="store_true",<br>
+ help="Prepare as OS X-style framework.")<br>
+ parser.add_argument(<br>
+ "--generate-dependency-file",<br>
+ "-M",<br>
+ action="store_true",<br>
+ help="Make the dependency (.d) file for the wrappers.")<br>
+ parser.add_argument(<br>
+ "--prefix",<br>
+ help="Override path where the LLDB module is placed.")<br>
+ parser.add_argument(<br>
+ "--src-root",<br>
+ "--srcRoot",<br>
+ "-s",<br>
+ # Default to the parent directory of this script's directory.<br>
+ default=os.path.abspath(<br>
+ os.path.join(<br>
+ os.path.dirname(os.path.realpath(__file__)),<br>
+ os.path.pardir)),<br>
+ help="Specifies the LLDB source root directory.")<br>
+ parser.add_argument(<br>
+ "--swig-executable",<br>
+ "--swigExecutable",<br>
+ help="Path to the swig executable.")<br>
+ parser.add_argument(<br>
+ "--target-dir",<br>
+ "--targetDir",<br>
+ required=True,<br>
+ help=(<br>
+ "Specifies the build dir where the language binding "<br>
+ "should be placed"))<br>
+<br>
+ # Process args.<br>
+ options = parser.parse_args(args)<br>
+<br>
+ # Set logging level based on verbosity count.<br>
+ if options.debug:<br>
+ log_level = logging.DEBUG<br>
+ else:<br>
+ # See logging documentation for error levels. We'll default<br>
+ # to showing ERROR or higher error messages. For each -v<br>
+ # specified, we'll shift to the next lower-priority log level.<br>
+ log_level = logging.ERROR - 10 * options.verbose<br>
+ if log_level < logging.NOTSET:<br>
+ # Displays all logged messages.<br>
+ log_level = logging.NOTSET<br>
+ logging.basicConfig(level=log_level)<br>
+ <a href="http://logging.info" rel="noreferrer" target="_blank">logging.info</a>("logging is using level: %d", log_level)<br>
+<br>
+ return options<br>
+<br>
+<br>
+def main(args):<br>
+ """Drives the main script preparation steps.<br>
+<br>
+ @param args list of command line arguments.<br>
+ """<br>
+ # Process command line arguments.<br>
+ options = process_args(args)<br>
+ logging.debug("Processed args: options=%s", options)<br>
+<br>
+ # Check if the swig file exists.<br>
+ swig_path = os.path.normcase(<br>
+ os.path.join(options.src_root, "scripts", "lldb.swig"))<br>
+ if not os.path.isfile(swig_path):<br>
+ logging.error("swig file not found at '%s'", swig_path)<br>
+ sys.exit(-3)<br>
+<br>
+ # Prepare bindings for each supported language binding.<br>
+ # This will error out if it doesn't succeed.<br>
+ prepare_all_bindings(options)<br>
+ sys.exit(0)<br>
+<br>
+if __name__ == "__main__":<br>
+ # Run the main driver loop.<br>
+ main(sys.argv[1:])<br>
<br>
Propchange: lldb/trunk/scripts/prepare_bindings.py<br>
------------------------------------------------------------------------------<br>
svn:executable = *<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits</a><br>
</blockquote></div>