blob: 3e8d9c5480548f1cf326436d955a5cb44b4c8aad [file] [log] [blame]
Erwin Jansenf96db3c2018-10-25 23:28:54 -07001#!/bin/python
2import argparse
Erwin Jansena7916b12018-10-26 09:44:10 -07003import hashlib
Erwin Jansenf96db3c2018-10-25 23:28:54 -07004import json
5import logging
6import os
7import sys
8
9
10def cleanup_json(data):
11 """Cleans up the json structure by removing empty "", and empty key value
12 pairs."""
13 if (isinstance(data, unicode)):
14 copy = data.strip()
15 return None if len(copy) == 0 else copy
16
17 if (isinstance(data, dict)):
18 copy = {}
19 for key, value in data.iteritems():
20 rem = cleanup_json(value)
21 if (rem is not None):
22 copy[key] = rem
23 return None if len(copy) == 0 else copy
24
25 if (isinstance(data, list)):
26 copy = []
27 for elem in data:
28 rem = cleanup_json(elem)
29 if (rem is not None):
30 if rem not in copy:
31 copy.append(rem)
32
33 if len(copy) == 0:
34 return None
35 return copy
36
37
38class AttrDict(dict):
39 def __init__(self, *args, **kwargs):
40 super(AttrDict, self).__init__(*args, **kwargs)
41 self.__dict__ = self
42
43 def as_list(self, name):
44 v = self.get(name, [])
45 if (isinstance(v, list)):
46 return v
47
48 return [v]
49
50
51def remove_lib_prefix(module):
52 """Removes the lib prefix, as we are not using them in CMake."""
53 if module.startswith('lib'):
54 return module[3:]
55 else:
56 return module
57
58
59def escape(msg):
60 """Escapes the "."""
61 return '"' + msg.replace('"', '\\"') + '"'
62
63
64def header():
65 """The auto generate header."""
66 return [
67 '# This is an autogenerated file! Do not edit!',
68 '# instead run make from .../device/generic/goldfish-opengl',
69 '# which will re-generate this file.'
70 ]
71
72
Erwin Jansena7916b12018-10-26 09:44:10 -070073def checksum(fname):
74 """Calculates a SHA256 digest of the given file name."""
75 m = hashlib.sha256()
76 with open(fname, 'r') as mk:
77 m.update(mk.read())
78 return m.hexdigest()
79
80
Erwin Jansenf96db3c2018-10-25 23:28:54 -070081def generate_module(module):
82 """Generates a cmake module."""
83 name = remove_lib_prefix(module['module'])
84 make = header()
Erwin Jansena7916b12018-10-26 09:44:10 -070085 mkfile = os.path.join(module['path'], 'Android.mk')
86 sha256 = checksum(mkfile)
87 make.append(
88 'android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/%s" "%s")' % (mkfile, sha256))
Erwin Jansenf96db3c2018-10-25 23:28:54 -070089 make.append('set(%s_src %s)' % (name, ' '.join(module['src'])))
90 if module['type'] == 'SHARED_LIBRARY':
91 make.append('android_add_shared_library(%s)' % name)
Lingfeng Yangd7447042018-10-25 11:09:18 -070092 elif module['type'] == 'STATIC_LIBRARY':
93 make.append('android_add_library(%s)' % name)
Erwin Jansenf96db3c2018-10-25 23:28:54 -070094 else:
95 raise ValueError('Unexpected module type: %s' % module['type'])
96
97 # Fix up the includes.
98 includes = ['${GOLDFISH_DEVICE_ROOT}/' + s for s in module['includes']]
99 make.append('target_include_directories(%s PRIVATE %s)' %
100 (name, ' '.join(includes)))
101
102 # filter out definitions
103 defs = [escape(d) for d in module['cflags'] if d.startswith('-D')]
104
105 # And the remaining flags.
106 flags = [escape(d) for d in module['cflags'] if not d.startswith('-D')]
107
108 # Make sure we remove the lib prefix from all our dependencies.
109 libs = [remove_lib_prefix(l) for l in module['libs']]
Lingfeng Yangf4d77ef2018-11-02 23:21:37 -0700110 staticlibs = [remove_lib_prefix(l) for l in
111 module.get('staticlibs', [])
112 if l != "libandroidemu"]
Erwin Jansenf96db3c2018-10-25 23:28:54 -0700113
114 # Configure the target.
115 make.append('target_compile_definitions(%s PRIVATE %s)' %
116 (name, ' '.join(defs)))
117 make.append('target_compile_options(%s PRIVATE %s)' %
118 (name, ' '.join(flags)))
Lingfeng Yangf4d77ef2018-11-02 23:21:37 -0700119
120 if len(staticlibs) > 0:
121 make.append('target_link_libraries(%s PRIVATE %s PRIVATE %s)' %
122 (name, ' '.join(libs), " ".join(staticlibs)))
123 else:
124 make.append('target_link_libraries(%s PRIVATE %s)' %
125 (name, ' '.join(libs)))
Erwin Jansenf96db3c2018-10-25 23:28:54 -0700126 return make
127
128
129def main(argv=None):
130 parser = argparse.ArgumentParser(
131 description='Generates a set of cmake files'
132 'based up the js representation.'
133 'Use this to generate cmake files that can be consumed by the emulator build')
134 parser.add_argument('-i', '--input', dest='input', type=str, required=True,
135 help='json file containing the build tree')
136 parser.add_argument('-v', '--verbose',
137 action='store_const', dest='loglevel',
138 const=logging.INFO, default=logging.ERROR,
139 help='Log what is happening')
140 parser.add_argument('-o', '--output',
141 dest='outdir', type=str, default=None,
142 help='Output directory for create CMakefile.txt')
143 parser.add_argument('-c', '--clean', dest='output', type=str,
144 default=None,
145 help='Write out the cleaned up js')
146 args = parser.parse_args()
147
148 logging.basicConfig(level=args.loglevel)
149
150 with open(args.input) as data_file:
151 data = json.load(data_file)
152
153 modules = cleanup_json(data)
154
155 # Write out cleaned up json, mainly useful for debugging etc.
156 if (args.output is not None):
157 with open(args.output, 'w') as out_file:
158 out_file.write(json.dumps(modules, indent=2))
159
160 # Location --> CMakeLists.txt
161 cmake = {}
162
163 # The root, it will basically just include all the generated files.
164 root = os.path.join(args.outdir, 'CMakeLists.txt')
Erwin Jansena7916b12018-10-26 09:44:10 -0700165 mkfile = os.path.join(args.outdir, 'Android.mk')
166 sha256 = checksum(mkfile)
Erwin Jansenf96db3c2018-10-25 23:28:54 -0700167 cmake[root] = header()
168 cmake[root].append('set(GOLDFISH_DEVICE_ROOT ${CMAKE_CURRENT_SOURCE_DIR})')
Erwin Jansena7916b12018-10-26 09:44:10 -0700169 cmake[root].append(
170 'android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/%s" "%s")' % (mkfile, sha256))
Erwin Jansenf96db3c2018-10-25 23:28:54 -0700171
172 # Generate the modules.
173 for module in modules:
174 location = os.path.join(args.outdir, module['path'], 'CMakeLists.txt')
175
176 # Make sure we handle the case where we have >2 modules in the same dir.
177 if location not in cmake:
178 cmake[root].append('add_subdirectory(%s)' % module['path'])
179 cmake[location] = []
180 cmake[location].extend(generate_module(module))
181
182 # Write them to disk.
183 for (loc, cmklist) in cmake.iteritems():
184 logging.info('Writing to %s', loc)
185 with open(loc, 'w') as fn:
186 fn.write('\n'.join(cmklist))
187
188
189if __name__ == '__main__':
190 sys.exit(main())