OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
3 # for details. All rights reserved. Use of this source code is governed by a | |
4 # BSD-style license that can be found in the LICENSE file. | |
5 """Used to merge and copy dart source files for deployment to AppEngine""" | |
6 | |
7 import fileinput | |
8 import sys | |
9 import shutil | |
10 import os | |
11 import re | |
12 from os.path import abspath, basename, dirname, exists, isabs, join | |
13 from glob import glob | |
14 | |
15 re_directive = re.compile( | |
16 r'^#(library|import|source|native|resource)\([\'"]([^\'"]*)[\'"](.*)\);$') | |
17 | |
18 class Library(object): | |
19 def __init__(self, name, imports, sources, natives, code): | |
20 self.name = name | |
21 self.imports = imports | |
22 self.sources = sources | |
23 self.natives = natives | |
24 self.code = code | |
25 | |
26 def parseLibrary(library): | |
27 """ Parses a .dart source file that is the root of a library, and returns | |
28 information about it: the name, the imports, included sources, and any | |
29 code in the file. | |
30 """ | |
31 libraryname = None | |
32 imports = [] | |
33 sources = [] | |
34 natives = [] | |
35 inlinecode = [] | |
36 if exists(library): | |
37 # TODO(sigmund): stop parsing when import/source | |
38 for line in fileinput.input(library): | |
39 match = re_directive.match(line) | |
40 if match: | |
41 directive = match.group(1) | |
42 if directive == 'library': | |
43 assert libraryname is None | |
44 libraryname = match.group(2) | |
45 elif directive == 'source': | |
46 sources.append(match.group(2)) | |
47 elif directive == 'import': | |
48 imports.append((match.group(2), match.group(3))) | |
49 elif directive == 'native': | |
50 natives.append(match.group(2)) | |
51 elif directive == 'resource': | |
52 # currently ignored | |
53 pass | |
54 else: | |
55 raise 'unknown directive %s' % directive | |
56 else: | |
57 inlinecode.append(line) | |
58 fileinput.close() | |
59 return Library(libraryname, imports, sources, natives, inlinecode) | |
60 | |
61 def normjoin(*args): | |
62 return os.path.normpath(os.path.join(*args)) | |
63 | |
64 def mergefiles(srcs, dstfile): | |
65 for src in srcs: | |
66 with open(src, 'r') as s: | |
67 dstfile.write(s.read()) | |
68 | |
69 def copyfile(src, dst): | |
70 if not exists(dirname(dst)): | |
71 os.makedirs(dirname(dst)) | |
72 with open(src, 'r') as s: | |
73 with open(dst, 'w') as d: | |
74 d.write(s.read()) | |
75 | |
76 def main(outdir = None, *inputs): | |
77 if not outdir or not inputs: | |
78 print "Usage: %s OUTDIR INPUTS" % args[0] | |
79 print " OUTDIR is the war directory to copy to" | |
80 print " INPUTS is a list of files or patterns used to specify the input" | |
81 print " .dart files" | |
82 print "This script should be run from the client root directory." | |
83 print "Files will be merged and copied to: OUTDIR/relative-path-of-file," | |
84 print "except for dart files with absolute paths, which will be copied to" | |
85 print " OUTDIR/absolute-path-as-directories" | |
86 return 1 | |
87 | |
88 entry_libraries = [] | |
89 for i in inputs: | |
90 entry_libraries.extend(glob(i)) | |
91 | |
92 for entrypoint in entry_libraries: | |
93 # Get the transitive set of dart files this entrypoint depends on, merging | |
94 # each library along the way. | |
95 worklist = [os.path.normpath(entrypoint)] | |
96 seen = set() | |
97 while len(worklist) > 0: | |
98 lib = worklist.pop() | |
99 if lib in seen: | |
100 continue | |
101 | |
102 seen.add(lib) | |
103 | |
104 if lib.startswith('dart:'): | |
105 continue | |
106 | |
107 if (dirname(dirname(lib)).endswith('dom/generated/src') | |
108 or dirname(lib).endswith('dom/src')): | |
109 continue | |
110 | |
111 if lib.endswith('json/json.dart'): | |
112 # TODO(jmesserly): Dartium interprets "json.dart" as "dart_json.dart", | |
113 # so we need that add dart_json.dart here. This is hacky. | |
114 lib = lib.replace('json.dart', 'dart_json.dart') | |
115 | |
116 library = parseLibrary(lib) | |
117 | |
118 # Ensure output directory exists | |
119 outpath = join(outdir, lib[1:] if isabs(lib) else lib) | |
120 dstpath = dirname(outpath) | |
121 if not exists(dstpath): | |
122 os.makedirs(dstpath) | |
123 | |
124 | |
125 # Create file containing all imports, and inlining all sources | |
126 with open(outpath, 'w') as f: | |
127 if library.name: | |
128 f.write("#library('%s');\n\n" % library.name) | |
129 else: | |
130 f.write("#library('%s');\n\n" % basename(lib)) | |
131 for (importfile, optional_prefix) in library.imports: | |
132 f.write("#import('%s'%s);\n" % (importfile, optional_prefix)) | |
133 for native in library.natives: | |
134 if isabs(native): | |
135 npath = native[1:] | |
136 else: | |
137 npath = native | |
138 f.write("#native('%s');\n" % npath) | |
139 copyfile(normjoin(dirname(lib), native), | |
140 join(dirname(outpath), npath)) | |
141 f.write('%s' % (''.join(library.code))) | |
142 mergefiles([normjoin(dirname(lib), s) for s in library.sources], f) | |
143 | |
144 for (i, prefix) in library.imports: | |
145 if not i.startswith('dart:'): | |
146 worklist.append(normjoin(dirname(lib), i)); | |
147 | |
148 return 0 | |
149 | |
150 if __name__ == '__main__': | |
151 sys.exit(main(*sys.argv[1:])) | |
OLD | NEW |