225 lines
6.4 KiB
Python
225 lines
6.4 KiB
Python
#!/bin/python3
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
|
|
def cleanup_json(data):
|
|
"""Cleans up the json structure by removing empty "", and empty key value
|
|
pairs."""
|
|
if isinstance(data, str):
|
|
copy = data.strip()
|
|
return None if len(copy) == 0 else copy
|
|
|
|
if isinstance(data, dict):
|
|
copy = {}
|
|
for key, value in data.items():
|
|
rem = cleanup_json(value)
|
|
if rem is not None:
|
|
copy[key] = rem
|
|
return None if len(copy) == 0 else copy
|
|
|
|
if isinstance(data, list):
|
|
copy = []
|
|
for elem in data:
|
|
rem = cleanup_json(elem)
|
|
if rem is not None:
|
|
if rem not in copy:
|
|
copy.append(rem)
|
|
|
|
if len(copy) == 0:
|
|
return None
|
|
return copy
|
|
|
|
|
|
class AttrDict(dict):
|
|
def __init__(self, *args, **kwargs):
|
|
super(AttrDict, self).__init__(*args, **kwargs)
|
|
self.__dict__ = self
|
|
|
|
def as_list(self, name):
|
|
v = self.get(name, [])
|
|
if isinstance(v, list):
|
|
return v
|
|
|
|
return [v]
|
|
|
|
|
|
def remove_lib_prefix(module):
|
|
"""Removes the lib prefix, as we are not using them in CMake."""
|
|
if module.startswith("lib"):
|
|
return module[3:]
|
|
else:
|
|
return module
|
|
|
|
|
|
def escape(msg):
|
|
"""Escapes the "."""
|
|
return '"' + msg.replace('"', '\\"') + '"'
|
|
|
|
|
|
def header():
|
|
"""The auto generate header."""
|
|
return [
|
|
"# This is an autogenerated file! Do not edit!",
|
|
"# instead run make from .../device/generic/goldfish-opengl",
|
|
"# which will re-generate this file.",
|
|
]
|
|
|
|
|
|
def checksum(fname):
|
|
"""Calculates a SHA256 digest of the given file name."""
|
|
m = hashlib.sha256()
|
|
with open(fname, "r", encoding="utf-8") as mk:
|
|
m.update(mk.read().encode("utf-8"))
|
|
return m.hexdigest()
|
|
|
|
|
|
def generate_module(module):
|
|
"""Generates a cmake module."""
|
|
name = remove_lib_prefix(module["module"])
|
|
make = header()
|
|
mkfile = os.path.join(module["path"], "Android.mk")
|
|
sha256 = checksum(mkfile)
|
|
make.append(
|
|
'android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/%s" "%s")' % (mkfile, sha256)
|
|
)
|
|
make.append("set(%s_src %s)" % (name, " ".join(module["src"])))
|
|
if module["type"] == "SHARED_LIBRARY":
|
|
make.append(
|
|
"android_add_library(TARGET {} SHARED LICENSE Apache-2.0 SRC {})".format(
|
|
name, " ".join(module["src"])
|
|
)
|
|
)
|
|
elif module["type"] == "STATIC_LIBRARY":
|
|
make.append(
|
|
"android_add_library(TARGET {} LICENSE Apache-2.0 SRC {})".format(
|
|
name, " ".join(module["src"])
|
|
)
|
|
)
|
|
else:
|
|
raise ValueError("Unexpected module type: %s" % module["type"])
|
|
|
|
# Fix up the includes.
|
|
includes = ["${GOLDFISH_DEVICE_ROOT}/" + s for s in module["includes"]]
|
|
make.append(
|
|
"target_include_directories(%s PRIVATE %s)" % (name, " ".join(includes))
|
|
)
|
|
|
|
# filter out definitions
|
|
defs = [escape(d) for d in module["cflags"] if d.startswith("-D")]
|
|
|
|
# And the remaining flags.
|
|
flags = [escape(d) for d in module["cflags"] if not d.startswith("-D")]
|
|
|
|
# Make sure we remove the lib prefix from all our dependencies.
|
|
libs = [remove_lib_prefix(l) for l in module.get("libs", [])]
|
|
staticlibs = [
|
|
remove_lib_prefix(l)
|
|
for l in module.get("staticlibs", [])
|
|
if l != "libandroidemu"
|
|
]
|
|
|
|
# Configure the target.
|
|
make.append("target_compile_definitions(%s PRIVATE %s)" % (name, " ".join(defs)))
|
|
make.append("target_compile_options(%s PRIVATE %s)" % (name, " ".join(flags)))
|
|
|
|
if len(staticlibs) > 0:
|
|
make.append(
|
|
"target_link_libraries(%s PRIVATE %s PRIVATE %s)"
|
|
% (name, " ".join(libs), " ".join(staticlibs))
|
|
)
|
|
else:
|
|
make.append("target_link_libraries(%s PRIVATE %s)" % (name, " ".join(libs)))
|
|
return make
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(
|
|
description="Generates a set of cmake files"
|
|
"based up the js representation."
|
|
"Use this to generate cmake files that can be consumed by the emulator build"
|
|
)
|
|
parser.add_argument(
|
|
"-i",
|
|
"--input",
|
|
dest="input",
|
|
type=str,
|
|
required=True,
|
|
help="json file containing the build tree",
|
|
)
|
|
parser.add_argument(
|
|
"-v",
|
|
"--verbose",
|
|
action="store_const",
|
|
dest="loglevel",
|
|
const=logging.INFO,
|
|
default=logging.ERROR,
|
|
help="Log what is happening",
|
|
)
|
|
parser.add_argument(
|
|
"-o",
|
|
"--output",
|
|
dest="outdir",
|
|
type=str,
|
|
default=None,
|
|
help="Output directory for create CMakefile.txt",
|
|
)
|
|
parser.add_argument(
|
|
"-c",
|
|
"--clean",
|
|
dest="output",
|
|
type=str,
|
|
default=None,
|
|
help="Write out the cleaned up js",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
logging.basicConfig(level=args.loglevel)
|
|
|
|
with open(args.input) as data_file:
|
|
data = json.load(data_file)
|
|
|
|
modules = cleanup_json(data)
|
|
|
|
# Write out cleaned up json, mainly useful for debugging etc.
|
|
if args.output is not None:
|
|
with open(args.output, "w") as out_file:
|
|
out_file.write(json.dumps(modules, indent=2))
|
|
|
|
# Location --> CMakeLists.txt
|
|
cmake = {}
|
|
|
|
# The root, it will basically just include all the generated files.
|
|
root = os.path.join(args.outdir, "CMakeLists.txt")
|
|
mkfile = os.path.join(args.outdir, "Android.mk")
|
|
sha256 = checksum(mkfile)
|
|
cmake[root] = header()
|
|
cmake[root].append("set(GOLDFISH_DEVICE_ROOT ${CMAKE_CURRENT_SOURCE_DIR})")
|
|
cmake[root].append(
|
|
'android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/%s" "%s")' % (mkfile, sha256)
|
|
)
|
|
|
|
# Generate the modules.
|
|
for module in modules:
|
|
location = os.path.join(args.outdir, module["path"], "CMakeLists.txt")
|
|
|
|
# Make sure we handle the case where we have >2 modules in the same dir.
|
|
if location not in cmake:
|
|
cmake[root].append("add_subdirectory(%s)" % module["path"])
|
|
cmake[location] = []
|
|
cmake[location].extend(generate_module(module))
|
|
|
|
# Write them to disk.
|
|
for (loc, cmklist) in cmake.items():
|
|
logging.info("Writing to %s", loc)
|
|
with open(loc, "w") as fn:
|
|
fn.write("\n".join(cmklist))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|