Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / build / android / gyp / write_build_config.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2014 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 """Writes a build_config file.
8
9 The build_config file for a target is a json file containing information about
10 how to build that target based on the target's dependencies. This includes
11 things like: the javac classpath, the list of android resources dependencies,
12 etc. It also includes the information needed to create the build_config for
13 other targets that depend on that one.
14
15 There are several different types of build_configs:
16   android_library: An android library containing java code.
17   android_resources: A target containing android resources.
18
19 Android build scripts should not refer to the build_config directly, and the
20 build specification should instead pass information in using the special
21 file-arg syntax (see build_utils.py:ExpandFileArgs). That syntax allows passing
22 of values in a json dict in a file and looks like this:
23   --python-arg=@FileArg(build_config_path:javac:classpath)
24
25 Note: If paths to input files are passed in this way, it is important that:
26   1. inputs/deps of the action ensure that the files are available the first
27   time the action runs.
28   2. Either (a) or (b)
29     a. inputs/deps ensure that the action runs whenever one of the files changes
30     b. the files are added to the action's depfile
31 """
32
33 import optparse
34 import os
35 import sys
36
37 from util import build_utils
38
39 dep_config_cache = {}
40 def GetDepConfig(path):
41   if not path in dep_config_cache:
42     dep_config_cache[path] = build_utils.ReadJson(path)['deps_info']
43   return dep_config_cache[path]
44
45
46 def DepsOfType(wanted_type, configs):
47   return [c for c in configs if c['type'] == wanted_type]
48
49
50 def GetAllDepsConfigsInOrder(deps_config_paths):
51   def Deps(path):
52     return set(GetDepConfig(path)['deps_configs'])
53   return build_utils.GetSortedTransitiveDependencies(deps_config_paths, Deps)
54
55
56 def main(argv):
57   parser = optparse.OptionParser()
58   build_utils.AddDepfileOption(parser)
59   parser.add_option('--build-config', help='Path to build_config output.')
60   parser.add_option(
61       '--type',
62       help='Type of this target (e.g. android_library).')
63   parser.add_option(
64       '--possible-deps-configs',
65       help='List of paths for dependency\'s build_config files. Some '
66       'dependencies may not write build_config files. Missing build_config '
67       'files are handled differently based on the type of this target.')
68
69   # android_resources/apk options
70   parser.add_option('--srcjar', help='Path to target\'s resources srcjar.')
71   parser.add_option('--resources-zip', help='Path to target\'s resources zip.')
72
73   # android_library/apk options
74   parser.add_option('--jar-path', help='Path to target\'s jar output.')
75   parser.add_option('--dex-path', help='Path to target\'s dex output.')
76
77   options, args = parser.parse_args(argv)
78
79   if args:
80     parser.error('No positional arguments should be given.')
81
82
83   if not options.type in [
84       'android_library', 'android_resources', 'android_apk']:
85     raise Exception('Unknown type: <%s>' % options.type)
86
87
88   required_options = ['build_config'] + {
89       'android_library': ['jar_path', 'dex_path'],
90       'android_resources': ['resources_zip'],
91       'android_apk': ['jar_path', 'dex_path', 'resources_zip']
92     }[options.type]
93
94   build_utils.CheckOptions(options, parser, required_options)
95
96   possible_deps_config_paths = build_utils.ParseGypList(
97       options.possible_deps_configs)
98
99
100
101
102   allow_unknown_deps = options.type == 'android_apk'
103   unknown_deps = [
104       c for c in possible_deps_config_paths if not os.path.exists(c)]
105   if unknown_deps and not allow_unknown_deps:
106     raise Exception('Unknown deps: ' + unknown_deps)
107
108   direct_deps_config_paths = [
109       c for c in possible_deps_config_paths if not c in unknown_deps]
110   all_deps_config_paths = GetAllDepsConfigsInOrder(direct_deps_config_paths)
111
112   direct_deps_configs = [GetDepConfig(p) for p in direct_deps_config_paths]
113   all_deps_configs = [GetDepConfig(p) for p in all_deps_config_paths]
114
115   direct_library_deps = DepsOfType('android_library', direct_deps_configs)
116   all_resources_deps = DepsOfType('android_resources', all_deps_configs)
117   all_library_deps = DepsOfType('android_library', all_deps_configs)
118
119   # Initialize some common config.
120   config = {
121     'deps_info': {
122       'path': options.build_config,
123       'type': options.type,
124       'deps_configs': direct_deps_config_paths,
125     }
126   }
127   deps_info = config['deps_info']
128
129   if options.type in ['android_library', 'android_apk']:
130     javac_classpath = [c['jar_path'] for c in direct_library_deps]
131     deps_info['resources_deps'] = [c['path'] for c in all_resources_deps]
132     deps_info['jar_path'] = options.jar_path
133     deps_info['dex_path'] = options.dex_path
134     config['javac'] = {
135       'classpath': javac_classpath,
136     }
137     # Only resources might have srcjars (normal srcjar targets are listed in
138     # srcjar_deps). A resource's srcjar contains the R.java file for those
139     # resources, and (like Android's default build system) we allow a library to
140     # refer to the resources in any of its dependents.
141     config['javac']['srcjars'] = [
142         c['srcjar'] for c in all_resources_deps if 'srcjar' in c]
143
144   if options.type == 'android_resources' or options.type == 'android_apk':
145     deps_info['resources_zip'] = options.resources_zip
146     if options.srcjar:
147       deps_info['srcjar'] = options.srcjar
148
149     config['resources'] = {}
150     config['resources']['dependency_zips'] = [
151         c['resources_zip'] for c in all_resources_deps]
152
153   if options.type == 'android_apk':
154     config['apk_dex'] = {}
155     dex_config = config['apk_dex']
156     # TODO(cjhopman): proguard version
157     dex_deps_files = [c['dex_path'] for c in all_library_deps]
158     dex_config['dependency_dex_files'] = dex_deps_files
159
160   build_utils.WriteJson(config, options.build_config, only_if_changed=True)
161
162   if options.depfile:
163     build_utils.WriteDepfile(
164         options.depfile,
165         all_deps_config_paths + build_utils.GetPythonDependencies())
166
167
168 if __name__ == '__main__':
169   sys.exit(main(sys.argv[1:]))