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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/devtools/devtools.gypi ('k') | Source/devtools/scripts/generate_devtools_html.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/devtools/scripts/concatenate_application_code.py
diff --git a/Source/devtools/scripts/concatenate_application_code.py b/Source/devtools/scripts/concatenate_application_code.py
index 978dd061fd3f7d896e93082abc71f4cdcbcb0fe2..242f9a4b12bf7b746629c538a5bace4c9aa9324e 100755
--- a/Source/devtools/scripts/concatenate_application_code.py
+++ b/Source/devtools/scripts/concatenate_application_code.py
@@ -5,18 +5,25 @@
# found in the LICENSE file.
"""
-Concatenates autostart modules, application modules' module.json descriptors,
-and the application loader into a single script.
-Also concatenates all workers' dependencies into individual worker loader scripts.
+Release:
+ - Concatenates autostart modules, application modules' module.json descriptors,
+ and the application loader into a single script.
+ - Concatenates all workers' dependencies into individual worker loader scripts.
+ - Builds app.html referencing the application script.
+Debug:
+ - Copies the module directories into their destinations.
+ - Copies app.html as-is.
"""
from cStringIO import StringIO
from os import path
+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
from modular_build import read_file, write_file, bail_error
import copy
import modular_build
import os
import re
+import shutil
import sys
try:
@@ -24,8 +31,8 @@ try:
except ImportError:
import json
-rjsmin_path = os.path.abspath(os.path.join(
- os.path.dirname(__file__),
+rjsmin_path = path.abspath(join(
+ path.dirname(__file__),
"..",
"..",
"build",
@@ -34,103 +41,190 @@ sys.path.append(rjsmin_path)
import rjsmin
-def minify_if_needed(javascript, minify):
- return rjsmin.jsmin(javascript) if minify else javascript
+def minify_js(javascript):
+ return rjsmin.jsmin(javascript)
def concatenated_module_filename(module_name, output_dir):
- return path.join(output_dir, module_name + '_module.js')
-
-
-def concatenate_autostart_modules(descriptors, application_dir, output_dir, output):
- non_autostart = set()
- sorted_module_names = descriptors.sorted_modules()
- for name in sorted_module_names:
- desc = descriptors.modules[name]
- name = desc['name']
- type = descriptors.application[name].get('type')
- if type == 'autostart':
- deps = set(desc.get('dependencies', []))
- non_autostart_deps = deps & non_autostart
- if len(non_autostart_deps):
- bail_error('Non-autostart dependencies specified for the autostarted module "%s": %s' % (name, non_autostart_deps))
- output.write('\n/* Module %s */\n' % name)
- modular_build.concatenate_scripts(desc.get('scripts'), path.join(application_dir, name), output_dir, output)
- elif type != 'worker':
- non_autostart.add(name)
-
-
-def concatenate_application_script(application_name, descriptors, application_dir, output_dir, minify):
- application_loader_name = application_name + '.js'
- output = StringIO()
- runtime_contents = read_file(path.join(application_dir, 'Runtime.js'))
- runtime_contents = re.sub('var allDescriptors = \[\];', 'var allDescriptors = %s;' % release_module_descriptors(descriptors.modules).replace("\\", "\\\\"), runtime_contents, 1)
- output.write('/* Runtime.js */\n')
- output.write(runtime_contents)
- output.write('\n/* Autostart modules */\n')
- concatenate_autostart_modules(descriptors, application_dir, output_dir, output)
- output.write('/* Application descriptor %s */\n' % (application_name + '.json'))
- output.write('applicationDescriptor = ')
- output.write(descriptors.application_json)
- output.write(';\n/* Application loader */\n')
- output.write(read_file(path.join(application_dir, application_loader_name)))
-
- write_file(path.join(output_dir, application_loader_name), minify_if_needed(output.getvalue(), minify))
- output.close()
-
-
-def concatenate_dynamic_module(module_name, descriptors, application_dir, output_dir, minify):
- scripts = descriptors.modules[module_name].get('scripts')
- if not scripts:
- return
- module_dir = path.join(application_dir, module_name)
- output = StringIO()
- modular_build.concatenate_scripts(scripts, module_dir, output_dir, output)
- output_file_path = concatenated_module_filename(module_name, output_dir)
- write_file(output_file_path, minify_if_needed(output.getvalue(), minify))
- output.close()
-
-
-def concatenate_worker(module_name, descriptors, application_dir, output_dir, minify):
- descriptor = descriptors.modules[module_name]
- scripts = descriptor.get('scripts')
- if not scripts:
- return
- worker_dir = path.join(application_dir, module_name)
- output_file_path = concatenated_module_filename(module_name, output_dir)
-
- output = StringIO()
- output.write('/* Worker %s */\n' % module_name)
- dependencies = descriptors.sorted_dependencies_closure(module_name)
- dep_descriptors = []
- for dep_name in dependencies:
- dep_descriptor = descriptors.modules[dep_name]
- dep_descriptors.append(dep_descriptor)
- scripts = dep_descriptor.get('scripts')
- if scripts:
- output.write('\n/* Module %s */\n' % dep_name)
- modular_build.concatenate_scripts(scripts, path.join(application_dir, dep_name), output_dir, output)
-
- write_file(output_file_path, minify_if_needed(output.getvalue(), minify))
- output.close()
-
-
-def release_module_descriptors(module_descriptors):
- result = []
- for name in module_descriptors:
- module = copy.copy(module_descriptors[name])
- # Clear scripts, as they are not used at runtime
- # (only the fact of their presence is important).
- if module.get('scripts'):
- module['scripts'] = []
- result.append(module)
- return json.dumps(result)
-
-
-def build_application(application_name, loader, application_dir, output_dir, minify):
+ return join(output_dir, module_name + '_module.js')
+
+
+def hardlink_or_copy_dir(src, dest):
+ if path.exists(dest):
+ shutil.rmtree(dest)
+ for root, dirs, files in os.walk(src):
+ subpath = path.relpath(root, src)
+ dest_dir = path.normpath(join(dest, subpath))
+ os.mkdir(dest_dir)
+ for name in files:
+ 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!
+ dest_name = join(dest_dir, name)
+ if hasattr(os, 'link'):
+ os.link(src_name, dest_name)
+ else:
+ shutil.copy(src_name, dest_name)
+
+
+class AppBuilder:
+ def __init__(self, application_name, descriptors, application_dir, output_dir):
+ self.application_name = application_name
+ self.descriptors = descriptors
+ self.application_dir = application_dir
+ self.output_dir = output_dir
+
+ def app_file(self, extension):
+ return self.application_name + '.' + extension
+
+
+# Outputs:
+# <app_name>.html
+# <app_name>.js
+# <module_name>_module.js
+class ReleaseBuilder(AppBuilder):
+ def __init__(self, application_name, descriptors, application_dir, output_dir):
+ AppBuilder.__init__(self, application_name, descriptors, application_dir, output_dir)
+
+ def build_app(self):
+ self._build_html()
+ self._build_app_script()
+ for module in filter(lambda desc: not desc.get('type'), self.descriptors.application.values()):
+ self._concatenate_dynamic_module(module['name'])
+ for module in filter(lambda desc: desc.get('type') == 'worker', self.descriptors.application.values()):
+ self._concatenate_worker(module['name'])
+
+ def _build_html(self):
+ html_name = self.app_file('html')
+ output = StringIO()
+ with open(join(self.application_dir, html_name), 'r') as app_input_html:
+ for line in app_input_html:
+ if '<script ' in line or '<link ' in line:
+ continue
+ if '</head>' in line:
+ output.write(self._generate_include_tag("%s.css" % self.application_name))
+ output.write(self._generate_include_tag("%s.js" % self.application_name))
+ output.write(line)
+
+ write_file(join(self.output_dir, html_name), output.getvalue())
+ output.close()
+
+ def _build_app_script(self):
+ script_name = self.app_file('js')
+ output = StringIO()
+ self._concatenate_application_script(output)
+ write_file(join(self.output_dir, script_name), minify_js(output.getvalue()))
+ output.close()
+
+ def _generate_include_tag(self, resource_path):
+ if (resource_path.endswith('.js')):
+ return ' <script type="text/javascript" src="%s"></script>\n' % resource_path
+ elif (resource_path.endswith('.css')):
+ return ' <link rel="stylesheet" type="text/css" href="%s">\n' % resource_path
+ else:
+ assert resource_path
+
+ def _release_module_descriptors(self):
+ module_descriptors = self.descriptors.modules
+ result = []
+ for name in module_descriptors:
+ module = copy.copy(module_descriptors[name])
+ # Clear scripts, as they are not used at runtime
+ # (only the fact of their presence is important).
+ if module.get('scripts'):
+ module['scripts'] = []
+ result.append(module)
+ return json.dumps(result)
+
+ def _concatenate_autostart_modules(self, output):
+ non_autostart = set()
+ sorted_module_names = self.descriptors.sorted_modules()
+ for name in sorted_module_names:
+ desc = self.descriptors.modules[name]
+ name = desc['name']
+ type = self.descriptors.application[name].get('type')
+ if type == 'autostart':
+ deps = set(desc.get('dependencies', []))
+ non_autostart_deps = deps & non_autostart
+ if len(non_autostart_deps):
+ bail_error('Non-autostart dependencies specified for the autostarted module "%s": %s' % (name, non_autostart_deps))
+ output.write('\n/* Module %s */\n' % name)
+ modular_build.concatenate_scripts(desc.get('scripts'), join(self.application_dir, name), self.output_dir, output)
+ elif type != 'worker':
+ non_autostart.add(name)
+
+ def _concatenate_application_script(self, output):
+ application_loader_name = self.app_file('js')
+ runtime_contents = read_file(join(self.application_dir, 'Runtime.js'))
+ runtime_contents = re.sub('var allDescriptors = \[\];', 'var allDescriptors = %s;' % self._release_module_descriptors().replace("\\", "\\\\"), runtime_contents, 1)
+ output.write('/* Runtime.js */\n')
+ output.write(runtime_contents)
+ output.write('\n/* Autostart modules */\n')
+ self._concatenate_autostart_modules(output)
+ output.write('/* Application descriptor %s */\n' % self.app_file('json'))
+ output.write('applicationDescriptor = ')
+ output.write(self.descriptors.application_json)
+ output.write('\n/* Application loader */\n')
+ output.write(read_file(join(self.application_dir, application_loader_name)))
+
+ def _concatenate_dynamic_module(self, module_name):
+ module = self.descriptors.modules[module_name]
+ scripts = module.get('scripts')
+ if not scripts:
+ return
+ module_dir = join(self.application_dir, module_name)
+ output = StringIO()
+ modular_build.concatenate_scripts(scripts, module_dir, self.output_dir, output)
+ output_file_path = concatenated_module_filename(module_name, self.output_dir)
+ write_file(output_file_path, minify_js(output.getvalue()))
+ output.close()
+
+ def _concatenate_worker(self, module_name):
+ descriptor = self.descriptors.modules[module_name]
+ scripts = descriptor.get('scripts')
+ if not scripts:
+ return
+
+ output = StringIO()
+ output.write('/* Worker %s */\n' % module_name)
+ dep_descriptors = []
+ for dep_name in self.descriptors.sorted_dependencies_closure(module_name):
+ dep_descriptor = self.descriptors.modules[dep_name]
+ dep_descriptors.append(dep_descriptor)
+ scripts = dep_descriptor.get('scripts')
+ if scripts:
+ output.write('\n/* Module %s */\n' % dep_name)
+ modular_build.concatenate_scripts(scripts, join(self.application_dir, dep_name), self.output_dir, output)
+
+ output_file_path = concatenated_module_filename(module_name, self.output_dir)
+ write_file(output_file_path, minify_js(output.getvalue()))
+ output.close()
+
+
+# Outputs:
+# <app_name>.html as-is
+# <app_name>.js as-is
+# <module_name>/<all_files>
+class DebugBuilder(AppBuilder):
+ def __init__(self, application_name, descriptors, application_dir, output_dir):
+ AppBuilder.__init__(self, application_name, descriptors, application_dir, output_dir)
+
+ def build_app(self):
+ self._build_html()
+ shutil.copy(join(self.application_dir, self.app_file('js')), self.output_dir)
+ for module_name in self.descriptors.modules:
+ module = self.descriptors.modules[module_name]
+ input_module_dir = join(self.application_dir, module_name)
+ output_module_dir = join(self.output_dir, module_name)
+ hardlink_or_copy_dir(input_module_dir, output_module_dir)
+
+ def _build_html(self):
+ html_name = self.app_file('html')
+ shutil.copy(join(self.application_dir, html_name), join(self.output_dir, html_name))
+
+
+def build_application(application_name, loader, application_dir, output_dir, release_mode):
descriptors = loader.load_application(application_name + '.json')
- concatenate_application_script(application_name, descriptors, application_dir, output_dir, minify)
- for module in filter(lambda desc: not desc.get('type'), descriptors.application.values()):
- concatenate_dynamic_module(module['name'], descriptors, application_dir, output_dir, minify)
- for module in filter(lambda desc: desc.get('type') == 'worker', descriptors.application.values()):
- concatenate_worker(module['name'], descriptors, application_dir, output_dir, minify)
+ if release_mode:
+ builder = ReleaseBuilder(application_name, descriptors, application_dir, output_dir)
+ else:
+ builder = DebugBuilder(application_name, descriptors, application_dir, output_dir)
+ builder.build_app()
« 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