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