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())
|