aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python/lib/bootstrap.py
blob: 31d3f69fb692b03822a937eee193f47b7ebf50eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os
import sys


_SOURCE_ROOT = None


def truncate_path(path):
    path = os.path.normpath(path)
    if _SOURCE_ROOT and path.startswith(_SOURCE_ROOT):
        return os.path.relpath(path, _SOURCE_ROOT)
    return os.path.basename(path)


def module_load(name, path = None):
    import imp

    module_name = name
    module_dot = name.find(".")
    if module_dot >= 0:
        module_name = module_name[:module_dot]

    fileobject, pathname, description = imp.find_module(module_name, path and [path])

    if os.path.isdir(pathname):
        pathname = os.path.join(pathname, "")

        if module_dot >= 0:
            return module_load(name[module_dot + 1:], pathname)
        return module_load("__init__", pathname)

    return pathname, fileobject, name == "__init__"


def list_modules():
    import pydoc

    modules = []

    def module_callback(path, name, description):
        modules.append(name)

    module_scanner = pydoc.ModuleScanner()
    module_scanner.run(module_callback)
    return modules


def make_path_directories(path):
    path_directory = os.path.dirname(path)
    if not os.path.exists(path_directory):
        os.makedirs(path_directory)
    return path


def module_blob_compile(module_file, module_path):
    import marshal
    module_code = compile(module_file.read(), truncate_path(module_path), "exec")
    return marshal.dumps(module_code)


def module_blob_write(module_blob, module_blob_name, module_blob_file):
    if EXTERN:
        if _SOURCE_ROOT and _SOURCE_ROOT in module_blob:
            raise Exception('Unable to add module %s because the blob contains the source root %s' % (module_blob_name, _SOURCE_ROOT))
        if os.getcwd() in module_blob:
            raise Exception('Unable to add module %s because the blob contains the build root %s' % (module_blob_name, os.getcwd()))

        module_blob_file.write(module_blob)
        return

    module_blob_file.write(STATIC + "unsigned char %s[] = {" % module_blob_name)
    for module_blob_byte in module_blob:
        module_blob_file.write("%d," % ord(module_blob_byte))
    module_blob_file.write("};\n\n")


def module_table_write(module_blobs, module_table_file):
    if EXTERN:
        off = 0
        module_table_file.write('extern unsigned char %s[];\n\n' % EXTERN)
        for module_name, module_blob_name, module_blob_size in module_blobs:
            if module_blob_size < 0:
                module_blob_size = -module_blob_size
            module_table_file.write("#define %s (%s + %d)\n" % (module_blob_name, EXTERN, off))
            off += module_blob_size

    module_table_file.write("""\n#include "Python.h"\n""")
    module_table_file.write("\nstatic struct _frozen _PyImport_FrozenModules[] = {\n")

    for module_name, module_blob_name, module_blob_size in module_blobs:
        module_table_file.write("""\t{"%s", %s, %d},\n""" % (module_name, module_blob_name, module_blob_size))

    module_table_file.write("\t{0, 0, 0}\n};\n")
    module_table_file.write("\nstruct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules;\n")


def load_module_list(module_list_path):
    return [line.strip() for line in open(module_list_path)]


if len(sys.argv) == 4:
    module_blob_path = make_path_directories(sys.argv[1])
    module_table_path = make_path_directories(sys.argv[2])
    modules_enabled = load_module_list(sys.argv[3])
    mode2 = 'w'
    STATIC = ''
    EXTERN = os.path.basename(module_blob_path)[:-7]
else:
    module_blob_path = make_path_directories(sys.argv[1])
    module_table_path = make_path_directories(sys.argv[1])
    modules_enabled = load_module_list(sys.argv[2])
    mode2 = 'a'
    STATIC = 'static '
    EXTERN = False


#modules = list_modules()

if 'ARCADIA_ROOT_DISTBUILD' in os.environ:
    _SOURCE_ROOT = os.path.normpath(os.environ['ARCADIA_ROOT_DISTBUILD'])

module_blobs = []

with open(module_blob_path, "wb") as module_blob_file:
    for module_name in modules_enabled:
        #if module_name not in modules: continue

        try:
            module_path, module_file, module_is_package = module_load(module_name)
        except ImportError as e:
            print e
            continue

        if module_file and module_path != __file__:
            module_blob_name = "M_" + "__".join(module_name.split("."))

            module_blob = module_blob_compile(module_file, module_path)
            module_blob_write(module_blob, module_blob_name, module_blob_file)
            module_blob_size = len(module_blob)

            if module_is_package:
                module_blob_size = -module_blob_size

            module_blobs.append((module_name, module_blob_name, module_blob_size))


with open(module_table_path, mode2) as module_table_file:
    module_table_write(module_blobs, module_table_file)