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

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

Issue 646413002: DevTools: Refactor build script to copy module files in debug_devtools mode (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address comments Created 6 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « Source/devtools/devtools.gypi ('k') | Source/devtools/scripts/generate_devtools_html.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2014 The Chromium Authors. All rights reserved. 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 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """ 7 """
8 Concatenates autostart modules, application modules' module.json descriptors, 8 Release:
9 and the application loader into a single script. 9 - Concatenates autostart modules, application modules' module.json descriptors ,
10 Also concatenates all workers' dependencies into individual worker loader script s. 10 and the application loader into a single script.
11 - Concatenates all workers' dependencies into individual worker loader scripts .
12 - Builds app.html referencing the application script.
13 Debug:
14 - Copies the module directories into their destinations.
15 - Copies app.html as-is.
11 """ 16 """
12 17
13 from cStringIO import StringIO 18 from cStringIO import StringIO
14 from os import path 19 from os import path
20 from os.path import join
dgozman 2014/10/14 10:17:48 Personally, I think that "join" is a too generic n
apavlov 2014/10/14 10:29:29 I had thought so, too, until I saw https://code.go
15 from modular_build import read_file, write_file, bail_error 21 from modular_build import read_file, write_file, bail_error
16 import copy 22 import copy
17 import modular_build 23 import modular_build
18 import os 24 import os
19 import re 25 import re
26 import shutil
20 import sys 27 import sys
21 28
22 try: 29 try:
23 import simplejson as json 30 import simplejson as json
24 except ImportError: 31 except ImportError:
25 import json 32 import json
26 33
27 rjsmin_path = os.path.abspath(os.path.join( 34 rjsmin_path = path.abspath(join(
28 os.path.dirname(__file__), 35 path.dirname(__file__),
29 "..", 36 "..",
30 "..", 37 "..",
31 "build", 38 "build",
32 "scripts")) 39 "scripts"))
33 sys.path.append(rjsmin_path) 40 sys.path.append(rjsmin_path)
34 import rjsmin 41 import rjsmin
35 42
36 43
37 def minify_if_needed(javascript, minify): 44 def minify_js(javascript):
38 return rjsmin.jsmin(javascript) if minify else javascript 45 return rjsmin.jsmin(javascript)
39 46
40 47
41 def concatenated_module_filename(module_name, output_dir): 48 def concatenated_module_filename(module_name, output_dir):
42 return path.join(output_dir, module_name + '_module.js') 49 return join(output_dir, module_name + '_module.js')
43 50
44 51
45 def concatenate_autostart_modules(descriptors, application_dir, output_dir, outp ut): 52 def hardlink_or_copy_dir(src, dest):
46 non_autostart = set() 53 if path.exists(dest):
47 sorted_module_names = descriptors.sorted_modules() 54 shutil.rmtree(dest)
48 for name in sorted_module_names: 55 for root, dirs, files in os.walk(src):
49 desc = descriptors.modules[name] 56 subpath = path.relpath(root, src)
50 name = desc['name'] 57 dest_dir = path.normpath(join(dest, subpath))
51 type = descriptors.application[name].get('type') 58 os.mkdir(dest_dir)
52 if type == 'autostart': 59 for name in files:
53 deps = set(desc.get('dependencies', [])) 60 src_name = join(root, name)
dgozman 2014/10/14 10:17:48 nit: renaming |root| to |src_dir| will make this c
apavlov 2014/10/14 10:29:28 good point!
54 non_autostart_deps = deps & non_autostart 61 dest_name = join(dest_dir, name)
55 if len(non_autostart_deps): 62 if hasattr(os, 'link'):
56 bail_error('Non-autostart dependencies specified for the autosta rted module "%s": %s' % (name, non_autostart_deps)) 63 os.link(src_name, dest_name)
57 output.write('\n/* Module %s */\n' % name) 64 else:
58 modular_build.concatenate_scripts(desc.get('scripts'), path.join(app lication_dir, name), output_dir, output) 65 shutil.copy(src_name, dest_name)
59 elif type != 'worker':
60 non_autostart.add(name)
61 66
62 67
63 def concatenate_application_script(application_name, descriptors, application_di r, output_dir, minify): 68 class AppBuilder:
64 application_loader_name = application_name + '.js' 69 def __init__(self, application_name, descriptors, application_dir, output_di r):
65 output = StringIO() 70 self.application_name = application_name
66 runtime_contents = read_file(path.join(application_dir, 'Runtime.js')) 71 self.descriptors = descriptors
67 runtime_contents = re.sub('var allDescriptors = \[\];', 'var allDescriptors = %s;' % release_module_descriptors(descriptors.modules).replace("\\", "\\\\"), runtime_contents, 1) 72 self.application_dir = application_dir
68 output.write('/* Runtime.js */\n') 73 self.output_dir = output_dir
69 output.write(runtime_contents)
70 output.write('\n/* Autostart modules */\n')
71 concatenate_autostart_modules(descriptors, application_dir, output_dir, outp ut)
72 output.write('/* Application descriptor %s */\n' % (application_name + '.jso n'))
73 output.write('applicationDescriptor = ')
74 output.write(descriptors.application_json)
75 output.write(';\n/* Application loader */\n')
76 output.write(read_file(path.join(application_dir, application_loader_name)))
77 74
78 write_file(path.join(output_dir, application_loader_name), minify_if_needed( output.getvalue(), minify)) 75 def app_file(self, extension):
79 output.close() 76 return self.application_name + '.' + extension
80 77
81 78
82 def concatenate_dynamic_module(module_name, descriptors, application_dir, output _dir, minify): 79 # Outputs:
83 scripts = descriptors.modules[module_name].get('scripts') 80 # <app_name>.html
84 if not scripts: 81 # <app_name>.js
85 return 82 # <module_name>_module.js
86 module_dir = path.join(application_dir, module_name) 83 class ReleaseBuilder(AppBuilder):
87 output = StringIO() 84 def __init__(self, application_name, descriptors, application_dir, output_di r):
88 modular_build.concatenate_scripts(scripts, module_dir, output_dir, output) 85 AppBuilder.__init__(self, application_name, descriptors, application_dir , output_dir)
89 output_file_path = concatenated_module_filename(module_name, output_dir) 86
90 write_file(output_file_path, minify_if_needed(output.getvalue(), minify)) 87 def build_app(self):
91 output.close() 88 self._build_html()
89 self._build_app_script()
90 for module in filter(lambda desc: not desc.get('type'), self.descriptors .application.values()):
91 self._concatenate_dynamic_module(module['name'])
92 for module in filter(lambda desc: desc.get('type') == 'worker', self.des criptors.application.values()):
93 self._concatenate_worker(module['name'])
94
95 def _build_html(self):
96 html_name = self.app_file('html')
97 output = StringIO()
98 with open(join(self.application_dir, html_name), 'r') as app_input_html:
99 for line in app_input_html:
100 if '<script ' in line or '<link ' in line:
101 continue
102 if '</head>' in line:
103 output.write(self._generate_include_tag("%s.css" % self.appl ication_name))
104 output.write(self._generate_include_tag("%s.js" % self.appli cation_name))
105 output.write(line)
106
107 write_file(join(self.output_dir, html_name), output.getvalue())
108 output.close()
109
110 def _build_app_script(self):
111 script_name = self.app_file('js')
112 output = StringIO()
113 self._concatenate_application_script(output)
114 write_file(join(self.output_dir, script_name), minify_js(output.getvalue ()))
115 output.close()
116
117 def _generate_include_tag(self, resource_path):
118 if (resource_path.endswith('.js')):
119 return ' <script type="text/javascript" src="%s"></script>\n' % r esource_path
120 elif (resource_path.endswith('.css')):
121 return ' <link rel="stylesheet" type="text/css" href="%s">\n' % r esource_path
122 else:
123 assert resource_path
124
125 def _release_module_descriptors(self):
126 module_descriptors = self.descriptors.modules
127 result = []
128 for name in module_descriptors:
129 module = copy.copy(module_descriptors[name])
130 # Clear scripts, as they are not used at runtime
131 # (only the fact of their presence is important).
132 if module.get('scripts'):
133 module['scripts'] = []
134 result.append(module)
135 return json.dumps(result)
136
137 def _concatenate_autostart_modules(self, output):
138 non_autostart = set()
139 sorted_module_names = self.descriptors.sorted_modules()
140 for name in sorted_module_names:
141 desc = self.descriptors.modules[name]
142 name = desc['name']
143 type = self.descriptors.application[name].get('type')
144 if type == 'autostart':
145 deps = set(desc.get('dependencies', []))
146 non_autostart_deps = deps & non_autostart
147 if len(non_autostart_deps):
148 bail_error('Non-autostart dependencies specified for the aut ostarted module "%s": %s' % (name, non_autostart_deps))
149 output.write('\n/* Module %s */\n' % name)
150 modular_build.concatenate_scripts(desc.get('scripts'), join(self .application_dir, name), self.output_dir, output)
151 elif type != 'worker':
152 non_autostart.add(name)
153
154 def _concatenate_application_script(self, output):
155 application_loader_name = self.app_file('js')
156 runtime_contents = read_file(join(self.application_dir, 'Runtime.js'))
157 runtime_contents = re.sub('var allDescriptors = \[\];', 'var allDescript ors = %s;' % self._release_module_descriptors().replace("\\", "\\\\"), runtime_c ontents, 1)
158 output.write('/* Runtime.js */\n')
159 output.write(runtime_contents)
160 output.write('\n/* Autostart modules */\n')
161 self._concatenate_autostart_modules(output)
162 output.write('/* Application descriptor %s */\n' % self.app_file('json') )
163 output.write('applicationDescriptor = ')
164 output.write(self.descriptors.application_json)
165 output.write('\n/* Application loader */\n')
166 output.write(read_file(join(self.application_dir, application_loader_nam e)))
167
168 def _concatenate_dynamic_module(self, module_name):
169 module = self.descriptors.modules[module_name]
170 scripts = module.get('scripts')
171 if not scripts:
172 return
173 module_dir = join(self.application_dir, module_name)
174 output = StringIO()
175 modular_build.concatenate_scripts(scripts, module_dir, self.output_dir, output)
176 output_file_path = concatenated_module_filename(module_name, self.output _dir)
177 write_file(output_file_path, minify_js(output.getvalue()))
178 output.close()
179
180 def _concatenate_worker(self, module_name):
181 descriptor = self.descriptors.modules[module_name]
182 scripts = descriptor.get('scripts')
183 if not scripts:
184 return
185
186 output = StringIO()
187 output.write('/* Worker %s */\n' % module_name)
188 dep_descriptors = []
189 for dep_name in self.descriptors.sorted_dependencies_closure(module_name ):
190 dep_descriptor = self.descriptors.modules[dep_name]
191 dep_descriptors.append(dep_descriptor)
192 scripts = dep_descriptor.get('scripts')
193 if scripts:
194 output.write('\n/* Module %s */\n' % dep_name)
195 modular_build.concatenate_scripts(scripts, join(self.application _dir, dep_name), self.output_dir, output)
196
197 output_file_path = concatenated_module_filename(module_name, self.output _dir)
198 write_file(output_file_path, minify_js(output.getvalue()))
199 output.close()
92 200
93 201
94 def concatenate_worker(module_name, descriptors, application_dir, output_dir, mi nify): 202 # Outputs:
95 descriptor = descriptors.modules[module_name] 203 # <app_name>.html as-is
96 scripts = descriptor.get('scripts') 204 # <app_name>.js as-is
97 if not scripts: 205 # <module_name>/<all_files>
98 return 206 class DebugBuilder(AppBuilder):
99 worker_dir = path.join(application_dir, module_name) 207 def __init__(self, application_name, descriptors, application_dir, output_di r):
100 output_file_path = concatenated_module_filename(module_name, output_dir) 208 AppBuilder.__init__(self, application_name, descriptors, application_dir , output_dir)
101 209
102 output = StringIO() 210 def build_app(self):
103 output.write('/* Worker %s */\n' % module_name) 211 self._build_html()
104 dependencies = descriptors.sorted_dependencies_closure(module_name) 212 shutil.copy(join(self.application_dir, self.app_file('js')), self.output _dir)
105 dep_descriptors = [] 213 for module_name in self.descriptors.modules:
106 for dep_name in dependencies: 214 module = self.descriptors.modules[module_name]
107 dep_descriptor = descriptors.modules[dep_name] 215 input_module_dir = join(self.application_dir, module_name)
108 dep_descriptors.append(dep_descriptor) 216 output_module_dir = join(self.output_dir, module_name)
109 scripts = dep_descriptor.get('scripts') 217 hardlink_or_copy_dir(input_module_dir, output_module_dir)
110 if scripts:
111 output.write('\n/* Module %s */\n' % dep_name)
112 modular_build.concatenate_scripts(scripts, path.join(application_dir , dep_name), output_dir, output)
113 218
114 write_file(output_file_path, minify_if_needed(output.getvalue(), minify)) 219 def _build_html(self):
115 output.close() 220 html_name = self.app_file('html')
221 shutil.copy(join(self.application_dir, html_name), join(self.output_dir, html_name))
116 222
117 223
118 def release_module_descriptors(module_descriptors): 224 def build_application(application_name, loader, application_dir, output_dir, rel ease_mode):
119 result = []
120 for name in module_descriptors:
121 module = copy.copy(module_descriptors[name])
122 # Clear scripts, as they are not used at runtime
123 # (only the fact of their presence is important).
124 if module.get('scripts'):
125 module['scripts'] = []
126 result.append(module)
127 return json.dumps(result)
128
129
130 def build_application(application_name, loader, application_dir, output_dir, min ify):
131 descriptors = loader.load_application(application_name + '.json') 225 descriptors = loader.load_application(application_name + '.json')
132 concatenate_application_script(application_name, descriptors, application_di r, output_dir, minify) 226 if release_mode:
133 for module in filter(lambda desc: not desc.get('type'), descriptors.applicat ion.values()): 227 builder = ReleaseBuilder(application_name, descriptors, application_dir, output_dir)
134 concatenate_dynamic_module(module['name'], descriptors, application_dir, output_dir, minify) 228 else:
135 for module in filter(lambda desc: desc.get('type') == 'worker', descriptors. application.values()): 229 builder = DebugBuilder(application_name, descriptors, application_dir, o utput_dir)
136 concatenate_worker(module['name'], descriptors, application_dir, output_ dir, minify) 230 builder.build_app()
OLDNEW
« no previous file with comments | « Source/devtools/devtools.gypi ('k') | Source/devtools/scripts/generate_devtools_html.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698