wumu
2024-10-09 d93a5a61f94ac4cf795ba4a8970d9eeba037f4c3
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import sys, ast, os, argparse
 
class Gyp(object):
    def __init__(self, fileName, gypVariables):
        self.fileName = fileName
        self.gypVariables = gypVariables
        with open(fileName, "r") as f:
            self.variables = ast.literal_eval(f.read())
 
    def target(self, name):
        for t in self.variables["targets"]:
            if t["target_name"] == name:
                return t;
 
        for condition in self.variables["conditions"] or []:
            check = condition[0]
            vars = condition[1]
            try:
                if eval(check, None, self.gypVariables):
                    for t in vars["targets"] or []:
                        if t["target_name"] == name:
                            return t;
            except: pass
        return None
 
    def target_defaults(self):
        return self.variables["target_defaults"]
 
class ProFileSection(object):
    sourceExtensions = [ ".cpp", ".cc", ".c" ]
    headerExtensions = [ ".h", ".hh" ]
    skippingExtensions = [ ".rc" ]
    skippingFiles = [ "makefile" ]
 
    def __init__(self, scope):
        self.sources = []
        self.headers = []
        self.defines = []
        self.includes = []
        self.config = []
        self.scope = scope
 
    def addSource(self, fileName):
        extension = os.path.splitext(fileName)[1]
        baseName = os.path.basename(fileName)
        if extension in ProFile.headerExtensions:
            self.headers.append(fileName)
        elif extension in ProFile.sourceExtensions:
            self.sources.append(fileName)
        elif baseName in ProFile.skippingFiles:
            return
        elif extension in ProFile.skippingExtensions:
            return
        else:
            raise Exception("Unknown source %s" % fileName)
 
    def addSources(self, sources, baseDirectory = None):
        for source in sources:
            path = source
            if baseDirectory:
                path = baseDirectory + "/" + path
            self.addSource(path)
 
    def addDefine(self, define):
        self.defines.append(define)
 
    def addDefines(self, defines):
        for macro in defines:
            self.addDefine(macro)
 
    def addConfig(self, cfg):
        self.config.append(cfg)
 
    def addInclude(self, path):
        path = path.replace("<(DEPTH)", "")
        self.includes.append("$$PWD/" + path)
 
    def generate(self):
        result = ""
        if self.defines:
            result += "DEFINES += \\\n    "
            result += " \\\n    ".join(self.defines)
            result += "\n\n"
        if self.config:
            result += "CONFIG += \\\n    "
            result += " \\\n    ".join(self.config)
            result += "\n\n"
        if self.includes:
            result += "INCLUDEPATH += \\\n    "
            result += " \\\n    ".join(self.includes)
            result += "\n\n"
        result += "SOURCES += \\\n    "
        result += " \\\n    ".join(self.sources)
        result += "\n\n"
        result += "HEADERS += \\\n    "
        result += " \\\n    ".join(self.headers)
        result += "\n\n"
        return result
 
class ProFile(ProFileSection):
    def __init__(self):
        ProFileSection.__init__(self, "")
        self.scopes = []
 
    def addScope(self, section):
        self.scopes.append(section)
 
    def generate(self):
        result = "# This is a generated file, do not edit!\n"
        result += ProFileSection.generate(self)
        for section in self.scopes:
            result += section.scope + " {\n"
            result += section.generate()
            result += "\n}\n"
        return result
 
def addDependencies(gyp, proFile, gypTarget, variables):
    for dep in gypTarget.get("dependencies") or []:
        target = None
        baseDir = None
        for key, value in variables.items():
            name = "<(" + key + ")"
            replacement = value
            dep = dep.replace(name, replacement)
        if ".gyp:" in dep:
            targetFileName = dep[:dep.index(":")]
            fileName = os.path.dirname(gyp.fileName) + "/" + targetFileName
            subDep = dep[dep.index(":") + 1:]
            target = Gyp(fileName, variables).target(subDep)
            baseDir = os.path.relpath(os.path.dirname(fileName), os.path.dirname(gyp.fileName))
        else:
            target = gyp.target(dep)
        if not target:
            return
        if target["target_name"] == "javascript":
            continue
        if target["target_name"] == "jsapi":
            continue
        pro.addSources(target["sources"], baseDir)
 
        if "conditions" in target:
            for condition in target["conditions"]:
                if condition[0] == "OS==\"win\"":
                    scope = ProFileSection("win32")
                    scope.addSources(condition[1]["sources"])
                    pro.addScope(scope)
 
        addDependencies(gyp, proFile, target, variables)
 
optionParser = argparse.ArgumentParser()
optionParser.add_argument("--gyp-var", action="append")
optionParser.add_argument("input")
optionParser.add_argument("mainTarget")
optionParser.add_argument("output")
config = optionParser.parse_args()
 
variables = {}
for var in config.gyp_var or []:
    key, value = var.split("=")
    variables[key] = value
 
gyp = Gyp(config.input, variables)
 
mainTarget = gyp.target(config.mainTarget)
 
pro = ProFile()
 
pro.addSources(mainTarget["sources"])
 
addDependencies(gyp, pro, mainTarget, variables)
 
target_defaults = gyp.target_defaults()
pro.addDefines(target_defaults["defines"])
if "include_dirs" in target_defaults:
    for path in target_defaults["include_dirs"]:
        pro.addInclude(os.path.relpath(os.path.dirname(gyp.fileName) + "/" + path, os.path.dirname(config.output)))
 
with open(config.output, "w") as f:
    f.write(pro.generate())