diff options
Diffstat (limited to 'scripts/Python/prepare_binding_Python.py')
| -rw-r--r-- | scripts/Python/prepare_binding_Python.py | 441 | 
1 files changed, 0 insertions, 441 deletions
| diff --git a/scripts/Python/prepare_binding_Python.py b/scripts/Python/prepare_binding_Python.py deleted file mode 100644 index cf64d49504f3d..0000000000000 --- a/scripts/Python/prepare_binding_Python.py +++ /dev/null @@ -1,441 +0,0 @@ -""" -                     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 -import platform - - -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 -    is_darwin = options.target_platform == "Darwin" -    gen_deps = options.generate_dependency_file -    darwin_extras = ["-D__APPLE__"] if is_darwin else [] -    deps_args = ["-MMD", "-MF", temp_dep_file_path] if gen_deps else [] -    command = ([ -            options.swig_executable, -            "-c++", -            "-shadow", -            "-python", -            "-threads", -            "-I" + os.path.normpath(os.path.join(options.src_root, "include")), -            "-I" + os.path.curdir, -            "-D__STDC_LIMIT_MACROS", -            "-D__STDC_CONSTANT_MACROS" -        ] -        + darwin_extras -        + deps_args -        + [ -            "-outdir", config_build_dir, -            "-o", settings.output_file, -            settings.input_file -        ] -    ) -    logging.info("running swig with: %r", command) - -    # Execute swig -    process = subprocess.Popen( -        command, -        stdout=subprocess.PIPE, -        stderr=subprocess.PIPE, -    ) -    # 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 = [sys.executable] + script_and_args -    process = subprocess.Popen(command) -    script_stdout, script_stderr = process.communicate() -    return_code = process.returncode -    if return_code != 0: -        logging.error("failed to run %r: %r", command, script_stderr) -        sys.exit(return_code) -    else: -        logging.info("ran script %r'", command) -        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) - -    run_python_script([script_path, config_build_dir]) - - -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) | 
