blob: e490fd9e30757818b1a64c693d846da29082d8b3 [file] [log] [blame]
damargulis5c5337d2017-04-21 22:36:081# Copyright 2017 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4"""Used by a js_binary action to compile javascript files.
5
6This script takes in a list of sources and dependencies and compiles them all
7together into a single compiled .js file. The dependencies are ordered in a
8post-order, left-to-right traversal order. If multiple instances of the same
9source file are read, only the first is kept. The script can also take in
10optional --flags argument which will add custom flags to the compiler. Any
11extern files can also be passed in using the --extern flag.
12"""
13
Luciano Pachecoaab13d412021-01-06 08:58:1814from __future__ import print_function
15
Mike Bjorge61bf88e2017-05-14 07:34:0616import argparse
damargulis5c5337d2017-04-21 22:36:0817import os
Mike Bjorge61bf88e2017-05-14 07:34:0618import sys
19
Dan Beam0135f0c2019-01-23 02:18:3720import compiler
damargulis5c5337d2017-04-21 22:36:0821
22
23def ParseDepList(dep):
Christopher Lam997fd812017-11-03 03:42:4024 """Parses a dependency list, returns |sources, deps, externs|."""
25 assert os.path.isfile(dep), (dep +
damargulis5c5337d2017-04-21 22:36:0826 ' is not a js_library target')
27 with open(dep, 'r') as dep_list:
28 lines = dep_list.read().splitlines()
29 assert 'deps:' in lines, dep + ' is not formated correctly, missing "deps:"'
Christopher Lam997fd812017-11-03 03:42:4030 deps_start = lines.index('deps:')
31 assert 'externs:' in lines, dep + ' is not formated correctly, missing "externs:"'
32 externs_start = lines.index('externs:')
33
34 return (lines[1:deps_start],
35 lines[deps_start+1:externs_start],
36 lines[externs_start+1:])
damargulis5c5337d2017-04-21 22:36:0837
38
Trent Apted131641f02018-08-09 23:46:4539# Cache, to avoid reading the same file twice in the dependency tree and
40# processing its dependencies again.
41depcache = {}
42
43def AppendUnique(items, new_items):
44 """Append items in |new_items| to |items|, avoiding duplicates."""
45 # Note this is O(n*n), and assumes |new_items| is already unique, but this is
46 # not a bottleneck overall.
47 items += [i for i in new_items if i not in items]
48
49def CrawlDepsTree(deps):
damargulis5c5337d2017-04-21 22:36:0850 """Parses the dependency tree creating a post-order listing of sources."""
Trent Apted131641f02018-08-09 23:46:4551 global depcache
52
53 if len(deps) == 0:
54 return ([], [])
55
56 new_sources = []
57 new_externs = []
damargulis5c5337d2017-04-21 22:36:0858 for dep in deps:
Trent Apted131641f02018-08-09 23:46:4559 if dep in depcache:
60 cur_sources, cur_externs = depcache[dep]
61 else:
62 dep_sources, dep_deps, dep_externs = ParseDepList(dep)
63 cur_sources, cur_externs = CrawlDepsTree(dep_deps)
64 # Add child dependencies of this node before the current node, then cache.
65 AppendUnique(cur_sources, dep_sources)
66 AppendUnique(cur_externs, dep_externs)
67 depcache[dep] = (cur_sources, cur_externs)
Christopher Lam997fd812017-11-03 03:42:4068
69 # Add the current node's sources and dedupe.
Trent Apted131641f02018-08-09 23:46:4570 AppendUnique(new_sources, cur_sources)
71 AppendUnique(new_externs, cur_externs)
Christopher Lam997fd812017-11-03 03:42:4072
Trent Apted131641f02018-08-09 23:46:4573 return new_sources, new_externs
Christopher Lam997fd812017-11-03 03:42:4074
Trent Apted131641f02018-08-09 23:46:4575
76def CrawlRootDepsTree(deps, target_sources, target_externs):
77 """Parses the dependency tree and adds target sources."""
78 sources, externs = CrawlDepsTree(deps)
79 AppendUnique(sources, target_sources)
80 AppendUnique(externs, target_externs)
Christopher Lam997fd812017-11-03 03:42:4081 return sources, externs
damargulis5c5337d2017-04-21 22:36:0882
83
84def main():
Mike Bjorge61bf88e2017-05-14 07:34:0685 parser = argparse.ArgumentParser()
damargulis5c5337d2017-04-21 22:36:0886 parser.add_argument('-c', '--compiler', required=True,
87 help='Path to compiler')
88 parser.add_argument('-s', '--sources', nargs='*', default=[],
89 help='List of js source files')
90 parser.add_argument('-o', '--output', required=True,
91 help='Compile to output')
92 parser.add_argument('-d', '--deps', nargs='*', default=[],
93 help='List of js_libarary dependencies')
94 parser.add_argument('-b', '--bootstrap',
95 help='A file to include before all others')
96 parser.add_argument('-cf', '--config', nargs='*', default=[],
97 help='A list of files to include after bootstrap and '
98 'before all others')
99 parser.add_argument('-f', '--flags', nargs='*', default=[],
100 help='A list of custom flags to pass to the compiler. '
101 'Do not include leading dashes')
102 parser.add_argument('-e', '--externs', nargs='*', default=[],
103 help='A list of extern files to pass to the compiler')
Christopher Lamc7566742018-07-18 03:02:06104 parser.add_argument('-co', '--checks-only', action='store_true',
105 help='Only performs checks and writes an empty output')
damargulis5c5337d2017-04-21 22:36:08106
107 args = parser.parse_args()
Trent Apted131641f02018-08-09 23:46:45108 sources, externs = CrawlRootDepsTree(args.deps, args.sources, args.externs)
damargulis5c5337d2017-04-21 22:36:08109
110 compiler_args = ['--%s' % flag for flag in args.flags]
Trent Apted131641f02018-08-09 23:46:45111 compiler_args += ['--externs=%s' % e for e in externs]
damargulis5c5337d2017-04-21 22:36:08112 compiler_args += [
113 '--js_output_file',
114 args.output,
115 '--js',
116 ]
117 if args.bootstrap:
118 compiler_args += [args.bootstrap]
119 compiler_args += args.config
120 compiler_args += sources
121
Christopher Lamc7566742018-07-18 03:02:06122 if args.checks_only:
123 compiler_args += ['--checks-only']
124 open(args.output, 'w').close()
125
Dan Beam0135f0c2019-01-23 02:18:37126 returncode, errors = compiler.Compiler().run_jar(args.compiler, compiler_args)
Mike Bjorge61bf88e2017-05-14 07:34:06127 if returncode != 0:
Luciano Pachecoaab13d412021-01-06 08:58:18128 print(args.compiler, ' '.join(compiler_args))
129 print(errors)
Mike Bjorge61bf88e2017-05-14 07:34:06130
131 return returncode
damargulis5c5337d2017-04-21 22:36:08132
133
134if __name__ == '__main__':
Mike Bjorge61bf88e2017-05-14 07:34:06135 sys.exit(main())