Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import argparse | 6 import argparse |
| 7 import itertools | 7 import itertools |
| 8 import os | 8 import os |
| 9 import platform | 9 import platform |
| 10 import re | 10 import re |
| 11 import subprocess | 11 import subprocess |
| 12 import sys | 12 import sys |
| 13 import tempfile | 13 import tempfile |
| 14 | 14 |
| 15 | 15 |
| 16 _HERE_PATH = os.path.dirname(__file__) | 16 _HERE_PATH = os.path.dirname(__file__) |
| 17 _SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..')) | 17 _SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..')) |
| 18 _CWD = os.getcwd() | 18 _CWD = os.getcwd() # NOTE(dbeam): this is typically out/<gn_name>/. |
| 19 | 19 |
| 20 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node')) | 20 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node')) |
| 21 import node | 21 import node |
| 22 import node_modules | 22 import node_modules |
| 23 | 23 |
| 24 | 24 |
| 25 _RESOURCES_PATH = os.path.join(_SRC_PATH, 'ui', 'webui', 'resources') | 25 _RESOURCES_PATH = os.path.join(_SRC_PATH, 'ui', 'webui', 'resources') |
| 26 | 26 |
| 27 | 27 |
| 28 _CR_ELEMENTS_PATH = os.path.join(_RESOURCES_PATH, 'cr_elements') | 28 _CR_ELEMENTS_PATH = os.path.join(_RESOURCES_PATH, 'cr_elements') |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 print >> sys.stderr, '%s failed: %s' % (cmd, stderr) | 89 print >> sys.stderr, '%s failed: %s' % (cmd, stderr) |
| 90 raise | 90 raise |
| 91 | 91 |
| 92 return stdout | 92 return stdout |
| 93 | 93 |
| 94 | 94 |
| 95 def _undo_mapping(mappings, url): | 95 def _undo_mapping(mappings, url): |
| 96 for (redirect_url, file_path) in mappings: | 96 for (redirect_url, file_path) in mappings: |
| 97 if url.startswith(redirect_url): | 97 if url.startswith(redirect_url): |
| 98 return url.replace(redirect_url, file_path + os.sep) | 98 return url.replace(redirect_url, file_path + os.sep) |
| 99 # TODO(dbeam): can we make this stricter? | |
| 99 return url | 100 return url |
| 100 | 101 |
| 101 | 102 |
| 102 # Get a list of all files that were bundled with Vulcanize and update the | 103 # Get a list of all files that were bundled with Vulcanize and update the |
| 103 # depfile accordingly such that Ninja knows when to trigger re-vulcanization. | 104 # depfile accordingly such that Ninja knows when to trigger re-vulcanization. |
| 104 def _update_dep_file(in_folder, args): | 105 def _update_dep_file(in_folder, args): |
| 105 in_path = os.path.join(_CWD, in_folder) | 106 in_path = os.path.join(_CWD, in_folder) |
| 106 out_path = os.path.join(_CWD, args.out_folder) | 107 out_path = os.path.join(_CWD, args.out_folder) |
| 107 | 108 |
| 108 # Prior call to vulcanize already generated the deps list, grab it from there. | 109 # Prior call to vulcanize already generated the deps list, grab it from there. |
| 109 request_list = open(os.path.join( | 110 request_list_path = os.path.join(out_path, _REQUEST_LIST_FILE) |
| 110 out_path, _REQUEST_LIST_FILE), 'r').read().splitlines() | 111 request_list = open(request_list_path, 'r').read().splitlines() |
| 112 | |
| 113 if platform.system() == 'Windows': | |
| 114 # TODO(dbeam): UGH. For some reason Vulcanize is interpreting the target | |
| 115 # file path as a URL and using the drive letter (e.g. D:\) as a protocol. | |
| 116 # This is a little insane, but we're fixing here by normalizing case (which | |
| 117 # really shouldn't matter, these are all file paths and generally are all | |
| 118 # lower case) and writing from / to \ (file path) and then back again. This | |
| 119 # is compounded by NodeJS having a bug in url.resolve() that handles | |
| 120 # chrome:// protocol URLs poorly as well as us using startswith() to strip | |
| 121 # file paths (which isn't crazy awesome either). Don't remove unless you | |
| 122 # really really know what you're doing. | |
| 123 norm = lambda u: u.lower().replace('/', '\\') | |
| 124 request_list = [norm(u).replace(norm(in_path), '').replace('\\', '/') | |
| 125 for u in request_list] | |
| 111 | 126 |
| 112 # Undo the URL mappings applied by vulcanize to get file paths relative to | 127 # Undo the URL mappings applied by vulcanize to get file paths relative to |
| 113 # current working directory. | 128 # current working directory. |
| 114 url_mappings = _URL_MAPPINGS + [ | 129 url_mappings = _URL_MAPPINGS + [ |
| 115 ('/', os.path.relpath(in_path, _CWD)), | 130 ('/', os.path.relpath(in_path, _CWD)), |
| 116 ('chrome://%s/' % args.host, os.path.relpath(in_path, _CWD)), | 131 ('chrome://%s/' % args.host, os.path.relpath(in_path, _CWD)), |
| 117 ] | 132 ] |
| 118 | 133 |
| 119 dependencies = map( | 134 deps = [_undo_mapping(url_mappings, u) for u in request_list] |
| 120 lambda url: _undo_mapping(url_mappings, url), request_list) | 135 deps = map(os.path.normpath, deps) |
| 121 | 136 |
| 122 # If the input was a .pak file, the generated depfile should not list files | 137 # If the input was a .pak file, the generated depfile should not list files |
| 123 # already in the .pak file. | 138 # already in the .pak file. |
| 124 filtered_dependencies = dependencies | 139 if args.input.endswith('.pak'): |
| 125 if (args.input_type == 'PAK_FILE'): | |
| 126 filter_url = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER) | 140 filter_url = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER) |
| 127 filtered_dependencies = filter( | 141 deps = [d for d in deps if not d.startswith(filter_url)] |
| 128 lambda url: not url.startswith(filter_url), dependencies) | |
| 129 | 142 |
| 130 with open(os.path.join(_CWD, args.depfile), 'w') as f: | 143 with open(os.path.join(_CWD, args.depfile), 'w') as f: |
| 131 f.write(os.path.join( | 144 deps_file_header = os.path.join(args.out_folder, args.html_out_file) |
| 132 args.out_folder, args.html_out_file) + ': ' + ' '.join( | 145 f.write(deps_file_header + ': ' + ' '.join(deps)) |
| 133 filtered_dependencies)) | |
| 134 | 146 |
| 135 | 147 |
| 136 def _vulcanize(in_folder, args): | 148 def _vulcanize(in_folder, args): |
| 137 in_path = os.path.normpath(os.path.join(_CWD, in_folder)) | 149 in_path = os.path.normpath(os.path.join(_CWD, in_folder)) |
| 138 out_path = os.path.join(_CWD, args.out_folder) | 150 out_path = os.path.join(_CWD, args.out_folder) |
| 139 | 151 |
| 140 html_out_path = os.path.join(out_path, args.html_out_file) | 152 html_out_path = os.path.join(out_path, args.html_out_file) |
| 141 js_out_path = os.path.join(out_path, args.js_out_file) | 153 js_out_path = os.path.join(out_path, args.js_out_file) |
| 142 | 154 |
| 143 output = _run_node( | 155 output = _run_node( |
| 144 [node_modules.PathToVulcanize()] + | 156 [node_modules.PathToVulcanize()] + |
| 145 _VULCANIZE_BASE_ARGS + _VULCANIZE_REDIRECT_ARGS + | 157 _VULCANIZE_BASE_ARGS + _VULCANIZE_REDIRECT_ARGS + |
| 146 ['--out-request-list', os.path.join(out_path, _REQUEST_LIST_FILE), | 158 ['--out-request-list', os.path.join(out_path, _REQUEST_LIST_FILE), |
| 147 '--redirect', '"/|%s"' % in_path, | 159 '--redirect', '"/|%s"' % in_path, |
| 148 '--redirect', '"chrome://%s/|%s"' % (args.host, in_path), | 160 '--redirect', '"chrome://%s/|%s"' % (args.host, in_path), |
| 149 # TODO(dpapad): Figure out why vulcanize treats the input path | 161 # TODO(dpapad): Figure out why vulcanize treats the input path |
| 150 # differently on Windows VS Linux/Mac. | 162 # differently on Windows VS Linux/Mac. |
| 151 os.path.join( | 163 os.path.join( |
| 152 in_path if platform.system() == 'Windows' else os.sep, | 164 in_path if platform.system() == 'Windows' else os.sep, |
| 153 args.html_in_file)]) | 165 args.html_in_file)]) |
| 154 | 166 |
| 155 # Grit includes are not supported, use HTML imports instead. | 167 # Grit includes are not supported, use HTML imports instead. |
| 156 output = output.replace('<include src="', '<include src-disabled="') | 168 output = output.replace('<include src="', '<include src-disabled="') |
| 157 | 169 |
| 158 if args.insert_in_head: | 170 if args.insert_in_head: |
| 159 assert '<head>' in output | 171 assert '<head>' in output |
| 172 # NOTE(dbeam): Vulcanize eats <base> tags after processing. This undoes | |
| 173 # that by adding a <base> tag to the (post-processed) generated output. | |
| 160 output = output.replace('<head>', '<head>' + args.insert_in_head) | 174 output = output.replace('<head>', '<head>' + args.insert_in_head) |
| 161 | 175 |
| 162 with tempfile.NamedTemporaryFile(mode='wt+', delete=False) as tmp: | 176 with tempfile.NamedTemporaryFile(mode='wt+', delete=False) as tmp: |
| 163 tmp.write(output) | 177 tmp.write(output) |
| 164 | 178 |
| 165 try: | 179 try: |
| 166 _run_node([node_modules.PathToCrisper(), | 180 _run_node([node_modules.PathToCrisper(), |
| 167 '--source', tmp.name, | 181 '--source', tmp.name, |
| 168 '--script-in-head', 'false', | 182 '--script-in-head', 'false', |
| 169 '--html', html_out_path, | 183 '--html', html_out_path, |
| 170 '--js', js_out_path]) | 184 '--js', js_out_path]) |
| 171 | 185 |
| 172 # TODO(tsergeant): Remove when JS resources are minified by default: | 186 # TODO(tsergeant): Remove when JS resources are minified by default: |
| 173 # crbug.com/619091. | 187 # crbug.com/619091. |
| 174 _run_node([node_modules.PathToUglifyJs(), js_out_path, | 188 _run_node([node_modules.PathToUglifyJs(), js_out_path, |
| 175 '--comments', '"/Copyright|license|LICENSE|\<\/?if/"', | 189 '--comments', '"/Copyright|license|LICENSE|\<\/?if/"', |
| 176 '--output', js_out_path]) | 190 '--output', js_out_path]) |
| 177 finally: | 191 finally: |
| 178 os.remove(tmp.name) | 192 os.remove(tmp.name) |
| 179 | 193 |
| 180 | 194 |
| 181 def _css_build(out_folder, files): | 195 def _css_build(out_folder, files): |
| 182 out_path = os.path.join(_CWD, out_folder) | 196 out_path = os.path.join(_CWD, out_folder) |
| 183 paths = map(lambda f: os.path.join(out_path, f), files) | 197 paths = [os.path.join(out_path, f) for f in files] |
| 184 | 198 |
| 185 _run_node([node_modules.PathToPolymerCssBuild()] + paths) | 199 _run_node([node_modules.PathToPolymerCssBuild()] + paths) |
| 186 | 200 |
| 187 | 201 |
| 188 def main(): | 202 def main(argv): |
| 189 parser = argparse.ArgumentParser() | 203 parser = argparse.ArgumentParser() |
| 190 parser.add_argument('--depfile') | 204 parser.add_argument('--depfile') |
|
dpapad
2017/02/07 03:00:32
This is required too. If it needs to be optional t
Dan Beam
2017/02/07 03:02:39
made required
| |
| 191 parser.add_argument('--host') | 205 parser.add_argument('--host', required=True) |
| 192 parser.add_argument('--html_in_file') | 206 parser.add_argument('--html_in_file', required=True) |
| 193 parser.add_argument('--html_out_file') | 207 parser.add_argument('--html_out_file', required=True) |
| 194 parser.add_argument('--input') | 208 parser.add_argument('--input', required=True) |
| 195 parser.add_argument('--input_type') | |
| 196 parser.add_argument('--insert_in_head') | 209 parser.add_argument('--insert_in_head') |
| 197 parser.add_argument('--js_out_file') | 210 parser.add_argument('--js_out_file', required=True) |
| 198 parser.add_argument('--out_folder') | 211 parser.add_argument('--out_folder', required=True) |
| 199 args = parser.parse_args() | 212 args = parser.parse_args(argv) |
| 213 | |
| 214 # NOTE(dbeam): on Windows, GN can send dirs/like/this. When joined, you might | |
| 215 # get dirs/like/this\file.txt. This looks odd to windows. Normalize to right | |
| 216 # the slashes. | |
| 217 if args.depfile: | |
| 218 args.depfile = os.path.normpath(args.depfile) | |
| 200 args.input = os.path.normpath(args.input) | 219 args.input = os.path.normpath(args.input) |
| 220 args.out_folder = os.path.normpath(args.out_folder) | |
| 201 | 221 |
| 202 vulcanize_input_folder = args.input | 222 vulcanize_input_folder = args.input |
| 203 | 223 |
| 204 # If a .pak file was specified, unpack that file first and pass the output to | 224 # If a .pak file was specified, unpack that file first and pass the output to |
| 205 # vulcanize. | 225 # vulcanize. |
| 206 if (args.input_type == 'PAK_FILE'): | 226 if args.input.endswith('.pak'): |
| 207 import unpack_pak | 227 import unpack_pak |
| 208 input_folder = os.path.join(_CWD, args.input) | 228 input_folder = os.path.join(_CWD, args.input) |
| 209 output_folder = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER) | 229 output_folder = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER) |
| 210 unpack_pak.unpack(args.input, output_folder) | 230 unpack_pak.unpack(args.input, output_folder) |
| 211 vulcanize_input_folder = output_folder | 231 vulcanize_input_folder = output_folder |
| 212 | 232 |
| 213 _vulcanize(vulcanize_input_folder, args) | 233 _vulcanize(vulcanize_input_folder, args) |
| 214 _css_build(args.out_folder, files=[args.html_out_file]) | 234 _css_build(args.out_folder, files=[args.html_out_file]) |
| 215 | 235 |
| 216 _update_dep_file(vulcanize_input_folder, args) | 236 if args.depfile: |
| 237 _update_dep_file(vulcanize_input_folder, args) | |
| 217 | 238 |
| 218 | 239 |
| 219 if __name__ == '__main__': | 240 if __name__ == '__main__': |
| 220 main() | 241 main(sys.argv[1:]) |
| OLD | NEW |