brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.4 KiB · 04df6fb Raw
174 lines · python
1""" Copies the build output of a custom python interpreter to a directory2    structure that mirrors that of an official Python distribution.3 4    --------------------------------------------------------------------------5    File:           install_custom_python.py6 7    Overview:       Most users build LLDB by linking against the standard8                    Python distribution installed on their system.  Occasionally9                    a user may want to build their own version of Python, and on10                    platforms such as Windows this is a hard requirement.  This11                    script will take the build output of a custom interpreter and12                    install it into a canonical structure that mirrors that of an13                    official Python distribution, thus allowing PYTHONHOME to be14                    set appropriately.15 16    Gotchas:        None.17 18    Copyright:      None.19    --------------------------------------------------------------------------20 21"""22 23import argparse24import itertools25import os26import shutil27import sys28 29 30def copy_one_file(dest_dir, source_dir, filename):31    source_path = os.path.join(source_dir, filename)32    dest_path = os.path.join(dest_dir, filename)33    print("Copying file %s ==> %s..." % (source_path, dest_path))34    shutil.copyfile(source_path, dest_path)35 36 37def copy_named_files(dest_dir, source_dir, files, extensions, copy_debug_suffix_also):38    for file, ext in itertools.product(files, extensions):39        copy_one_file(dest_dir, source_dir, file + "." + ext)40        if copy_debug_suffix_also:41            copy_one_file(dest_dir, source_dir, file + "_d." + ext)42 43 44def copy_subdirectory(dest_dir, source_dir, subdir):45    dest_dir = os.path.join(dest_dir, subdir)46    source_dir = os.path.join(source_dir, subdir)47    print("Copying directory %s ==> %s..." % (source_dir, dest_dir))48    shutil.copytree(source_dir, dest_dir)49 50 51def copy_distro(dest_dir, dest_subdir, source_dir, source_prefix):52    dest_dir = os.path.join(dest_dir, dest_subdir)53 54    print("Copying distribution %s ==> %s" % (source_dir, dest_dir))55 56    os.mkdir(dest_dir)57    PCbuild_dir = os.path.join(source_dir, "PCbuild")58    if source_prefix:59        PCbuild_dir = os.path.join(PCbuild_dir, source_prefix)60    # First copy the files that go into the root of the new distribution. This61    # includes the Python executables, python27(_d).dll, and relevant PDB62    # files.63    print("Copying Python executables...")64    copy_named_files(dest_dir, PCbuild_dir, ["w9xpopen"], ["exe", "pdb"], False)65    copy_named_files(dest_dir, PCbuild_dir, ["python_d", "pythonw_d"], ["exe"], False)66    copy_named_files(67        dest_dir, PCbuild_dir, ["python", "pythonw"], ["exe", "pdb"], False68    )69    copy_named_files(dest_dir, PCbuild_dir, ["python27"], ["dll", "pdb"], True)70 71    # Next copy everything in the Include directory.72    print("Copying Python include directory")73    copy_subdirectory(dest_dir, source_dir, "Include")74 75    # Copy Lib folder (builtin Python modules)76    print("Copying Python Lib directory")77    copy_subdirectory(dest_dir, source_dir, "Lib")78 79    # Copy tools folder.  These are probably not necessary, but we copy them anyway to80    # match an official distribution as closely as possible.  Note that we don't just copy81    # the subdirectory recursively.  The source distribution ships with many more tools82    # than what you get by installing python regularly.  We only copy the tools that appear83    # in an installed distribution.84    tools_dest_dir = os.path.join(dest_dir, "Tools")85    tools_source_dir = os.path.join(source_dir, "Tools")86    os.mkdir(tools_dest_dir)87    copy_subdirectory(tools_dest_dir, tools_source_dir, "i18n")88    copy_subdirectory(tools_dest_dir, tools_source_dir, "pynche")89    copy_subdirectory(tools_dest_dir, tools_source_dir, "scripts")90    copy_subdirectory(tools_dest_dir, tools_source_dir, "versioncheck")91    copy_subdirectory(tools_dest_dir, tools_source_dir, "webchecker")92 93    pyd_names = [94        "_ctypes",95        "_ctypes_test",96        "_elementtree",97        "_multiprocessing",98        "_socket",99        "_testcapi",100        "pyexpat",101        "select",102        "unicodedata",103        "winsound",104    ]105 106    # Copy builtin extension modules (pyd files)107    dlls_dir = os.path.join(dest_dir, "DLLs")108    os.mkdir(dlls_dir)109    print("Copying DLLs directory")110    copy_named_files(dlls_dir, PCbuild_dir, pyd_names, ["pyd", "pdb"], True)111 112    # Copy libs folder (implibs for the pyd files)113    libs_dir = os.path.join(dest_dir, "libs")114    os.mkdir(libs_dir)115    print("Copying libs directory")116    copy_named_files(libs_dir, PCbuild_dir, pyd_names, ["lib"], False)117    copy_named_files(libs_dir, PCbuild_dir, ["python27"], ["lib"], True)118 119 120parser = argparse.ArgumentParser(description="Install a custom Python distribution")121parser.add_argument(122    "--source", required=True, help="The root of the source tree where Python is built."123)124parser.add_argument(125    "--dest", required=True, help="The location to install the Python distributions."126)127parser.add_argument(128    "--overwrite",129    default=False,130    action="store_true",131    help="If the destination directory already exists, destroys its contents first.",132)133parser.add_argument(134    "--silent",135    default=False,136    action="store_true",137    help="If --overwite was specified, suppress confirmation before deleting a directory tree.",138)139 140args = parser.parse_args()141 142args.source = os.path.normpath(args.source)143args.dest = os.path.normpath(args.dest)144 145if not os.path.exists(args.source):146    print("The source directory %s does not exist.  Exiting...")147    sys.exit(1)148 149if os.path.exists(args.dest):150    if not args.overwrite:151        print(152            "The destination directory '%s' already exists and --overwrite was not specified.  Exiting..."153            % args.dest154        )155        sys.exit(1)156    while not args.silent:157        print(158            "Ok to recursively delete '%s' and all contents (Y/N)?  Choosing Y will permanently delete the contents."159            % args.dest160        )161        result = str.upper(sys.stdin.read(1))162        if result == "N":163            print(164                "Unable to copy files to the destination.  The destination already exists."165            )166            sys.exit(1)167        elif result == "Y":168            break169    shutil.rmtree(args.dest)170 171os.mkdir(args.dest)172copy_distro(args.dest, "x86", args.source, None)173copy_distro(args.dest, "x64", args.source, "amd64")174