Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: third_party/WebKit/Source/devtools/scripts/concatenate_application_code.py

Issue 2336943002: DevTools: Simplify debug and release mode builds (Closed)
Patch Set: fix copyright year Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/devtools/scripts/build_release_applications.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 """
8 Release:
9 - Concatenates autostart modules, application modules' module.json descriptors ,
10 and the application loader into a single script.
11 - Builds app.html referencing the application script.
12 Debug:
13 - Copies the module directories into their destinations.
14 - Copies app.html as-is.
15 """
16
17 from cStringIO import StringIO
18 from os import path
19 from os.path import join
20 from modular_build import read_file, write_file, bail_error
21 import copy
22 import modular_build
23 import os
24 import re
25 import shutil
26 import sys
27
28 try:
29 import simplejson as json
30 except ImportError:
31 import json
32
33 import rjsmin
34
35
36 def resource_source_url(url):
37 return '\n/*# sourceURL=' + url + ' */'
38
39
40 def minify_js(javascript):
41 return rjsmin.jsmin(javascript)
42
43
44 def concatenated_module_filename(module_name, output_dir):
45 return join(output_dir, module_name + '/' + module_name + '_module.js')
46
47
48 def symlink_or_copy_file(src, dest, safe=False):
49 if safe and path.exists(dest):
50 os.remove(dest)
51 if hasattr(os, 'symlink'):
52 os.symlink(src, dest)
53 else:
54 shutil.copy(src, dest)
55
56
57 def symlink_or_copy_dir(src, dest):
58 if path.exists(dest):
59 shutil.rmtree(dest)
60 for src_dir, dirs, files in os.walk(src):
61 subpath = path.relpath(src_dir, src)
62 dest_dir = path.normpath(join(dest, subpath))
63 os.mkdir(dest_dir)
64 for name in files:
65 src_name = join(os.getcwd(), src_dir, name)
66 dest_name = join(dest_dir, name)
67 symlink_or_copy_file(src_name, dest_name)
68
69
70 class AppBuilder:
71 def __init__(self, application_name, descriptors, application_dir, output_di r):
72 self.application_name = application_name
73 self.descriptors = descriptors
74 self.application_dir = application_dir
75 self.output_dir = output_dir
76
77 def app_file(self, extension):
78 return self.application_name + '.' + extension
79
80 def core_resource_names(self):
81 result = []
82 for module in self.descriptors.sorted_modules():
83 if self.descriptors.application[module].get('type') != 'autostart':
84 continue
85
86 resources = self.descriptors.modules[module].get('resources')
87 if not resources:
88 continue
89 for resource_name in resources:
90 result.append(path.join(module, resource_name))
91 return result
92
93
94 # Outputs:
95 # <app_name>.html
96 # <app_name>.js
97 # <module_name>_module.js
98 class ReleaseBuilder(AppBuilder):
99 def __init__(self, application_name, descriptors, application_dir, output_di r):
100 AppBuilder.__init__(self, application_name, descriptors, application_dir , output_dir)
101
102 def build_app(self):
103 if self.descriptors.has_html:
104 self._build_html()
105 self._build_app_script()
106 for module in filter(lambda desc: (not desc.get('type') or desc.get('typ e') == 'remote'), self.descriptors.application.values()):
107 self._concatenate_dynamic_module(module['name'])
108
109 def _build_html(self):
110 html_name = self.app_file('html')
111 output = StringIO()
112 with open(join(self.application_dir, html_name), 'r') as app_input_html:
113 for line in app_input_html:
114 if '<script ' in line or '<link ' in line:
115 continue
116 if '</head>' in line:
117 output.write(self._generate_include_tag(self.app_file('js')) )
118 output.write(line)
119
120 write_file(join(self.output_dir, html_name), output.getvalue())
121 output.close()
122
123 def _build_app_script(self):
124 script_name = self.app_file('js')
125 output = StringIO()
126 self._concatenate_application_script(output)
127 write_file(join(self.output_dir, script_name), minify_js(output.getvalue ()))
128 output.close()
129
130 def _generate_include_tag(self, resource_path):
131 if (resource_path.endswith('.js')):
132 return ' <script type="text/javascript" src="%s"></script>\n' % r esource_path
133 else:
134 assert resource_path
135
136 def _release_module_descriptors(self):
137 module_descriptors = self.descriptors.modules
138 result = []
139 for name in module_descriptors:
140 module = copy.copy(module_descriptors[name])
141 module_type = self.descriptors.application[name].get('type')
142 # Clear scripts, as they are not used at runtime
143 # (only the fact of their presence is important).
144 resources = module.get('resources', None)
145 if module.get('scripts') or resources:
146 if module_type == 'autostart':
147 # Autostart modules are already baked in.
148 del module['scripts']
149 else:
150 # Non-autostart modules are vulcanized.
151 module['scripts'] = [name + '_module.js']
152 # Resources are already baked into scripts.
153 if resources is not None:
154 del module['resources']
155 result.append(module)
156 return json.dumps(result)
157
158 def _write_module_resources(self, resource_names, output):
159 for resource_name in resource_names:
160 resource_name = path.normpath(resource_name).replace('\\', '/')
161 output.write('Runtime.cachedResources["%s"] = "' % resource_name)
162 resource_content = read_file(path.join(self.application_dir, resourc e_name)) + resource_source_url(resource_name)
163 resource_content = resource_content.replace('\\', '\\\\')
164 resource_content = resource_content.replace('\n', '\\n')
165 resource_content = resource_content.replace('"', '\\"')
166 output.write(resource_content)
167 output.write('";\n')
168
169 def _concatenate_autostart_modules(self, output):
170 non_autostart = set()
171 sorted_module_names = self.descriptors.sorted_modules()
172 for name in sorted_module_names:
173 desc = self.descriptors.modules[name]
174 name = desc['name']
175 type = self.descriptors.application[name].get('type')
176 if type == 'autostart':
177 deps = set(desc.get('dependencies', []))
178 non_autostart_deps = deps & non_autostart
179 if len(non_autostart_deps):
180 bail_error('Non-autostart dependencies specified for the aut ostarted module "%s": %s' % (name, non_autostart_deps))
181 output.write('\n/* Module %s */\n' % name)
182 modular_build.concatenate_scripts(desc.get('scripts'), join(self .application_dir, name), self.output_dir, output)
183 else:
184 non_autostart.add(name)
185
186 def _concatenate_application_script(self, output):
187 runtime_contents = read_file(join(self.application_dir, 'Runtime.js'))
188 runtime_contents = re.sub('var allDescriptors = \[\];', 'var allDescript ors = %s;' % self._release_module_descriptors().replace('\\', '\\\\'), runtime_c ontents, 1)
189 output.write('/* Runtime.js */\n')
190 output.write(runtime_contents)
191 output.write('\n/* Autostart modules */\n')
192 self._concatenate_autostart_modules(output)
193 output.write('/* Application descriptor %s */\n' % self.app_file('json') )
194 output.write('applicationDescriptor = ')
195 output.write(self.descriptors.application_json())
196 output.write(';\n/* Core resources */\n')
197 self._write_module_resources(self.core_resource_names(), output)
198 output.write('\n/* Application loader */\n')
199 output.write(read_file(join(self.application_dir, self.app_file('js'))))
200
201 def _concatenate_dynamic_module(self, module_name):
202 module = self.descriptors.modules[module_name]
203 scripts = module.get('scripts')
204 resources = self.descriptors.module_resources(module_name)
205 module_dir = join(self.application_dir, module_name)
206 output = StringIO()
207 if scripts:
208 modular_build.concatenate_scripts(scripts, module_dir, self.output_d ir, output)
209 if resources:
210 self._write_module_resources(resources, output)
211 output_file_path = concatenated_module_filename(module_name, self.output _dir)
212 write_file(output_file_path, minify_js(output.getvalue()))
213 output.close()
214
215
216 # Outputs:
217 # <app_name>.html as-is
218 # <app_name>.js as-is
219 # <module_name>/<all_files>
220 class DebugBuilder(AppBuilder):
221 def __init__(self, application_name, descriptors, application_dir, output_di r):
222 AppBuilder.__init__(self, application_name, descriptors, application_dir , output_dir)
223
224 def build_app(self):
225 if self.descriptors.has_html:
226 self._build_html()
227 js_name = self.app_file('js')
228 src_name = join(os.getcwd(), self.application_dir, js_name)
229 symlink_or_copy_file(src_name, join(self.output_dir, js_name), True)
230 for module_name in self.descriptors.modules:
231 module = self.descriptors.modules[module_name]
232 input_module_dir = join(self.application_dir, module_name)
233 output_module_dir = join(self.output_dir, module_name)
234 symlink_or_copy_dir(input_module_dir, output_module_dir)
235
236 def _build_html(self):
237 html_name = self.app_file('html')
238 symlink_or_copy_file(join(os.getcwd(), self.application_dir, html_name), join(self.output_dir, html_name), True)
239
240
241 def build_application(application_name, loader, application_dir, output_dir, rel ease_mode):
242 descriptors = loader.load_application(application_name + '.json')
243 if release_mode:
244 builder = ReleaseBuilder(application_name, descriptors, application_dir, output_dir)
245 else:
246 builder = DebugBuilder(application_name, descriptors, application_dir, o utput_dir)
247 builder.build_app()
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/scripts/build_release_applications.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698