blob: 4fca9611fc423abd9ddd5ca148f099c6311620d4 [file] [log] [blame]
Derek Sollenberger5d3f7702018-02-01 09:22:53 -05001#!/usr/bin/env python
2#
3# Copyright 2018 Google Inc.
4#
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8# Generate Android.bp for Skia from GN configuration.
9
Martin Vejdarskibeaaf472020-03-03 13:53:20 +070010from __future__ import print_function
11
Derek Sollenberger5d3f7702018-02-01 09:22:53 -050012import argparse
13import json
14import os
15import pprint
16import string
17import subprocess
18import tempfile
19
20parser = argparse.ArgumentParser(description='Process some cmdline flags.')
21parser.add_argument('--gn', dest='gn_cmd', default='gn')
22args = parser.parse_args()
23
24def GenerateJSONFromGN(gn_args):
Leon Scroggins III86b2c952021-08-03 11:49:44 -040025 gn_args = ' '.join(sorted('%s=%s' % (k,v) for (k,v) in iter(gn_args.items())))
Derek Sollenberger5d3f7702018-02-01 09:22:53 -050026 tmp = tempfile.mkdtemp()
27 subprocess.check_call([args.gn_cmd, 'gen', tmp, '--args=%s' % gn_args,
28 '--ide=json'])
29 return json.load(open(os.path.join(tmp, 'project.json')))
30
31def _strip_slash(lst):
32 return {str(p.lstrip('/')) for p in lst}
33
34def GrabDependentValues(js, name, value_type, list_to_extend, exclude):
35 # Grab the values from other targets that $name depends on (e.g. optional
36 # Skia components, gms, tests, etc).
37 for dep in js['targets'][name]['deps']:
38 if 'third_party' in dep:
39 continue # We've handled all third-party DEPS as static or shared_libs.
40 if 'none' in dep:
41 continue # We'll handle all cpu-specific sources manually later.
42 if exclude and exclude in dep:
43 continue
44 list_to_extend.update(_strip_slash(js['targets'][dep].get(value_type, [])))
45 GrabDependentValues(js, dep, value_type, list_to_extend, exclude)
46
47def CleanupCFlags(cflags):
48 # Only use the generated flags related to warnings.
49 cflags = {s for s in cflags if s.startswith('-W')}
Ben Wagner72513e72021-03-22 13:51:31 -040050 # Add additional warning suppressions
51 # Some for third_party/vulkanmemoryallocator
52 # Some for Android's '-Wall -Werror'
Greg Daniel18dbfd02018-05-29 10:46:51 -040053 cflags = cflags.union([
Derek Sollenberger1821a5b2018-09-11 14:48:36 -040054 "-Wno-implicit-fallthrough",
Greg Daniel18dbfd02018-05-29 10:46:51 -040055 "-Wno-missing-field-initializers",
Ben Wagner72513e72021-03-22 13:51:31 -040056 "-Wno-sign-conversion",
Derek Sollenberger1821a5b2018-09-11 14:48:36 -040057 "-Wno-thread-safety-analysis",
Brian Osman759802f2021-06-15 13:19:08 -040058 "-Wno-unknown-warning-option",
Ben Wagner72513e72021-03-22 13:51:31 -040059 "-Wno-unused-parameter",
Greg Daniel18dbfd02018-05-29 10:46:51 -040060 "-Wno-unused-variable",
61 ])
Derek Sollenberger5d3f7702018-02-01 09:22:53 -050062 # Add the rest of the flags we want.
63 cflags = cflags.union([
64 "-fvisibility=hidden",
65 "-D_FORTIFY_SOURCE=1",
66 "-DSKIA_DLL",
67 "-DSKIA_IMPLEMENTATION=1",
68 "-DATRACE_TAG=ATRACE_TAG_VIEW",
Derek Sollenberger5d3f7702018-02-01 09:22:53 -050069 ])
70
71 # We need to undefine FORTIFY_SOURCE before we define it. Insert it at the
72 # beginning after sorting.
73 cflags = sorted(cflags)
74 cflags.insert(0, "-U_FORTIFY_SOURCE")
75 return cflags
76
77def CleanupCCFlags(cflags_cc):
78 # Only use the generated flags related to warnings.
Leon Scroggins III6c41bf52021-01-29 15:33:00 -050079 return {s for s in cflags_cc if s.startswith('-W')}
Derek Sollenberger5d3f7702018-02-01 09:22:53 -050080
81def _get_path_info(path, kind):
82 assert path == "../src"
83 assert kind == "abspath"
84 # While we want absolute paths in GN, relative paths work best here.
85 return "src"
86
87def GetArchSources(opts_file):
88 # For architecture specific files, it's easier to just read the same source
89 # that GN does (opts.gni) rather than re-run GN once for each architecture.
90
91 # This .gni file we want to read is close enough to Python syntax
92 # that we can use execfile() if we supply definitions for GN builtins.
93 builtins = { 'get_path_info': _get_path_info }
94 defs = {}
Leon Scroggins III86b2c952021-08-03 11:49:44 -040095 with open(opts_file) as f:
96 code = compile(f.read(), opts_file, 'exec')
97 exec(code, builtins, defs)
Derek Sollenberger5d3f7702018-02-01 09:22:53 -050098
99 # Perform any string substitutions.
100 for arch in defs:
101 defs[arch] = [ p.replace('$_src', 'src') for p in defs[arch]]
102
103 return defs
104
105def WriteUserConfig(userConfigPath, defines):
106 # Most defines go into SkUserConfig.h
107 defines.remove('NDEBUG') # Controlled by the Android build
Mike Kleinf5f4e812019-04-29 15:45:14 +0000108 defines.remove('SKIA_IMPLEMENTATION=1') # don't export this define.
Leon Scroggins IIIee0e5d02019-02-27 10:59:11 -0500109 if 'WIN32_LEAN_AND_MEAN' in defines: # Controlled by the Android build
110 defines.remove('WIN32_LEAN_AND_MEAN')
Leon Scroggins III631dbc82019-03-04 13:54:02 -0500111 if '_HAS_EXCEPTIONS=0' in defines: # Controlled by the Android build
112 defines.remove('_HAS_EXCEPTIONS=0')
Derek Sollenberger5d3f7702018-02-01 09:22:53 -0500113
114 #... and all the #defines we want to put in SkUserConfig.h.
115 with open(userConfigPath, 'w') as f:
Martin Vejdarskibeaaf472020-03-03 13:53:20 +0700116 print('// DO NOT MODIFY! This file is autogenerated by gn_to_bp.py.', file=f)
117 print('// If need to change a define, modify SkUserConfigManual.h', file=f)
118 print('#pragma once', file=f)
119 print('#include "SkUserConfigManual.h"', file=f)
Derek Sollenberger5d3f7702018-02-01 09:22:53 -0500120 for define in sorted(defines):
Martin Vejdarskibeaaf472020-03-03 13:53:20 +0700121 print('', file=f)
122 print('#ifndef', define.split('=')[0], file=f)
123 print('#define', define.replace('=', ' ', 1), file=f)
124 print('#endif', file=f)