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

Side by Side Diff: src/shared/ppapi/update-scons.py

Issue 6715019: Switching ppapi on nacl side to import chrome side .gyp[i] directly. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 9 years, 9 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
OLDNEW
(Empty)
1 #! /usr/bin/python
2 # Copyright 2010 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can
4 # be found in the LICENSE file.
5
6 """Script to update .scons rules from the ppapi.gyp file.
7
8 This script reads the .scons files in this directory. It replaces all of the
9 lines between the starting marker and the ending marker with the corresponding
10 list of files from the given gyp file.
11
12 The starting marker format is:
13 # From GYP_FILE_NAME:TARGET:REGEXP
14 The ending marker format is:
15 # End GYP_FILE_NAME
16
17 For example, if this exists in the .scons file:
18 # From ppapi.gyp:ppapi_c:.*\.h
19 ...
20 # End ppapi.gyp
21
22 then this script will remove all of the lines between the starting marker and
23 the ending marker. It will then find the 'ppapi_c' target in the ppapi.gyp
24 file. It will find all 'sources' for that target that match the regular
25 expression '.*\.h' and will insert each of those source files in between the
26 two markers.
27
28 This script performs a similar action for the ppapi include tests. The files
29 ../../../tests/ppapi/cpp_header_test.cc and
30 ../../../tests/ppapi/cpp_dev_header_test.cc have their include statements
31 replaced based on an include marker with format:
32 // From ppapi.gyp:TARGET:REGEXP
33 """
34
35 from optparse import OptionParser
36 import os
37 import re
38 import sys
39
40 # Constants.
41 PROG = os.path.basename(sys.argv[0])
42 NATIVE_CLIENT_SRC_SHARED_PPAPI = os.path.abspath(os.path.dirname(sys.argv[0]))
43 NATIVE_CLIENT_SRC_SHARED = os.path.dirname(NATIVE_CLIENT_SRC_SHARED_PPAPI)
44 NATIVE_CLIENT_SRC = os.path.dirname(NATIVE_CLIENT_SRC_SHARED)
45 NATIVE_CLIENT = os.path.dirname(NATIVE_CLIENT_SRC)
46 CLIENTDIR = os.path.dirname(NATIVE_CLIENT)
47
48 # Known files names.
49 PPAPI_GYP_DIR = os.path.join(CLIENTDIR, 'ppapi')
50 BUILD_SCONS = os.path.join(NATIVE_CLIENT_SRC_SHARED_PPAPI, 'build.scons')
51 NACL_SCONS = os.path.join(NATIVE_CLIENT_SRC_SHARED_PPAPI, 'nacl.scons')
52 PPAPI_GYP = os.path.join(NATIVE_CLIENT_SRC_SHARED_PPAPI, 'ppapi.gyp')
53 CPP_HEADER_TEST = os.path.join(
54 NATIVE_CLIENT, 'tests', 'ppapi', 'cpp_header_test.cc')
55 CPP_DEV_HEADER_TEST = os.path.join(
56 NATIVE_CLIENT, 'tests', 'ppapi', 'cpp_dev_header_test.cc')
57
58 # Regular expressions for the .scons files.
59 START_PATTERN = re.compile(
60 '^([ \t]*)#[ \t]*From ([^:]*):([^:]*):(.*) *\n',
61 re.IGNORECASE)
62 END_PATTERN = re.compile('^[ \t]*#[ \t]*End ([^:]*) *\n', re.IGNORECASE)
63
64 # Regular expressions for the .cc files.
65 INCLUDE_PATTERN = re.compile(
66 '^[ \t]*//[ \t]*From ([^:]*):([^:]*):(.*) *\n',
67 re.IGNORECASE)
68
69 # Regular expressions for the ppapi.gyp file.
70 TARGET_PATTERN = re.compile(
71 '^[ \t]*\'target_name\'[ \t]*:[ \t]*\'([^\']*)\'[ \t]*,')
72 SOURCES_PATTERN = re.compile('^[ \t]*\'sources\'[ \t]*:[ \t]*[[]')
73 END_SOURCES_PATTERN = re.compile('^[ \t]*[]]')
74
75
76 def ParseCommandLine():
77 """Parses options from the command line.
78
79 Parses options from the command line and returns the options and the
80 arguments to the caller.
81
82 Returns:
83 options: the options settings from the command line.
84 args: the arguments (things that were not options).
85 """
86 usage = '%prog [options]'
87 description = ('Update the .scons files in the "%s" directory with the'
88 ' current definitions from ppapi.gyp. Also update the #include'
89 ' test files in the "%s/../../../tests/ppapi" directory'
90 % (NATIVE_CLIENT_SRC_SHARED_PPAPI,
91 NATIVE_CLIENT_SRC_SHARED_PPAPI))
92 parser = OptionParser(usage=usage, description=description)
93 (options, args) = parser.parse_args()
94 return (options, args)
95
96
97 def CheckFileIsReadable(filename):
98 """Check the read accessibility of filename.
99
100 Args:
101 filename: the file to check.
102
103 Returns:
104 Exits to the system if the file is not readable.
105 """
106 if not os.access(filename, os.F_OK):
107 print >> sys.stderr, '%s does not exist.' % (filename)
108 sys.exit(1)
109 if not os.access(filename, os.R_OK):
110 print >> sys.stderr, 'Cannot read from %s' % (filename)
111 sys.exit(1)
112
113
114 def CheckFileIsWritable(filename):
115 """Check the write accessibility of filename.
116
117 Args:
118 filename: the file to check.
119
120 Returns:
121 Exits to the system if the file is not writable.
122 """
123 if os.access(filename, os.F_OK):
124 # The file already exists. Check if it is writable.
125 if not os.access(filename, os.W_OK):
126 print >> sys.stderr, 'Cannot write to %s' % (filename)
127 sys.exit(1)
128 else:
129 # The file does not yet exist. Check the directory.
130 dirname = os.path.dirname(filename)
131 if not dirname:
132 dirname = '.'
133 if not os.access(dirname, os.W_OK):
134 print >> sys.stderr, 'Cannot write to directory %s' % (dirname)
135 sys.exit(1)
136
137
138 def BuildTmpFilename(filename):
139 """Returns the name of a temporary file for filename.
140
141 Args:
142 filename: the name of a file.
143
144 Returns:
145 The name of a temporary file.
146 """
147 return filename + '.tmp'
148
149
150 def RenameTmpToFile(filename):
151 """Renames filename.tmp to filename.
152
153 Args:
154 filename: the final name of the file.
155 """
156 tmp_filename = BuildTmpFilename(filename)
157 print '%s: Renaming %s back to %s' % (PROG, tmp_filename, filename)
158 os.remove(filename)
159 os.rename(tmp_filename, filename)
160
161
162 def TransferLinesFromPpapiGyp(marker, write_fp, is_cc_file):
163 """Copies matching file lines from ppapi.gyp.
164
165 Opens and reads ppapi.gyp to find the 'target' section that matches the
166 target listed on the marker line. Copies all of the files that match the
167 marker's regular expression into the output file.
168
169 Note that this function reads and parses the contents of ppapi.gyp each
170 time it is called. This entire script should take less than 1 second to
171 run, so the increased complexity involved in pre-caching the contents of
172 the file and passing it around is unnecessary.
173
174 Args:
175 marker: The marker line from the file; matches START_PATTERN.
176 write_fp: The file to write to.
177 is_cc_file: False if this is a .scons file, True if .cc.
178 """
179 # Pluck off the interesting parts of the marker.
180 if not is_cc_file:
181 match = re.match(START_PATTERN, marker)
182 scons_indentation = match.group(1)
183 gyp_file_name = match.group(2)
184 target = match.group(3)
185 file_regexp = match.group(4)
186 else:
187 match = re.match(INCLUDE_PATTERN, marker)
188 gyp_file_name = match.group(1)
189 target = match.group(2)
190 file_regexp = match.group(3)
191
192 # Convert the input file_regexp into a pattern that will match the syntax
193 # of a source file in the ppapi.gyp file. The .gyp file looks like:
194 # 'path/some-file.cc',
195 # Put everything except the leading spaces into match.group(1).
196 # So if the marker line in the .scons file contains the regexp:
197 # .*\.cc
198 # the file_pattern regular expression (for .scons) will look like:
199 # ^ *('.*\.cc',)
200 # and the file_pattern regular expression (for .cc) will look like:
201 # ^ *'(.*\.cc)',
202 if not is_cc_file:
203 file_pattern = re.compile('^[ \t]*(\'' + file_regexp + '\',)')
204 else:
205 file_pattern = re.compile('^[ \t]*\'(' + file_regexp + ')\',')
206
207 gyp_file = open(os.path.join(PPAPI_GYP_DIR, gyp_file_name), 'r')
208 found_target = False
209 found_sources = False
210 for line in gyp_file:
211 if not found_target:
212 # Still looking for:
213 # 'target_name': 'TARGET'
214 match = re.match(TARGET_PATTERN, line)
215 if match:
216 if match.group(1) == target:
217 found_target = True
218 elif not found_sources:
219 # Looking for the start of the sources section for this target:
220 # 'sources': [
221 if re.match(SOURCES_PATTERN, line):
222 found_sources = True
223 elif re.match(END_SOURCES_PATTERN, line):
224 # Found the ']' at the end of the 'sources': section.
225 break
226 else:
227 # This is a line from the 'sources' section. Does it match the filespec?
228 match = re.match(file_pattern, line)
229 if match:
230 # Change the line's indentation to match the .scons file then write
231 # the line to the .scons file.
232 if not is_cc_file:
233 out_line = scons_indentation + match.group(1) + '\n'
234 else:
235 out_line = '#include "ppapi/' + match.group(1) + '"\n'
236 write_fp.write(out_line)
237
238 gyp_file.close()
239
240
241 def UpdateSconsToTmp(filename):
242 """Updates the input .scons file, writing to filename.tmp.
243
244 Updates all filename lines between the start and end header markers with
245 the current values from gyp_file. Writes all output to a temporary file.
246
247 Args:
248 filename: the file to update.
249 """
250 tmp_filename = BuildTmpFilename(filename)
251 print '%s: Updating %s to %s' % (PROG, filename, tmp_filename)
252
253 read_fp = open(filename, 'r')
254 write_fp = open(tmp_filename, 'w')
255
256 skipping_lines = False
257 for line in read_fp:
258 if not skipping_lines:
259 # Currently copying all lines until a START_PATTERN line is found.
260 write_fp.write(line)
261 if re.match(START_PATTERN, line):
262 TransferLinesFromPpapiGyp(line, write_fp, False)
263 skipping_lines = True
264 else:
265 # All of the most recent source files have been copied from the
266 # ppapi.gyp file into the output file. We are now skipping all lines
267 # until an END_PATTERN line is found.
268 if re.match(END_PATTERN, line):
269 write_fp.write(line)
270 skipping_lines = False
271
272 read_fp.close()
273 write_fp.close()
274
275
276 def UpdateCcToTmp(filename):
277 """Updates the input .cc file, writing to filename.tmp.
278
279 Updates all #include lines after the inclusion marker with the
280 current values from gyp_file. Writes all output to a temporary file.
281
282 Args:
283 filename: the file to update.
284 """
285 tmp_filename = BuildTmpFilename(filename)
286 print '%s: Updating %s to %s' % (PROG, filename, tmp_filename)
287
288 read_fp = open(filename, 'r')
289 write_fp = open(tmp_filename, 'w')
290
291 for line in read_fp:
292 # Currently copying all lines until a INCLUDE_PATTERN line is found.
293 write_fp.write(line)
294 if re.match(INCLUDE_PATTERN, line):
295 TransferLinesFromPpapiGyp(line, write_fp, True)
296 break
297
298 read_fp.close()
299 write_fp.close()
300
301
302 def main():
303 ParseCommandLine()
304
305 # Make sure all of the files are accessible.
306 CheckFileIsReadable(BUILD_SCONS)
307 CheckFileIsReadable(NACL_SCONS)
308 CheckFileIsReadable(PPAPI_GYP)
309 CheckFileIsReadable(CPP_HEADER_TEST)
310 CheckFileIsReadable(CPP_DEV_HEADER_TEST)
311 CheckFileIsWritable(BuildTmpFilename(BUILD_SCONS))
312 CheckFileIsWritable(BuildTmpFilename(NACL_SCONS))
313 CheckFileIsWritable(BuildTmpFilename(PPAPI_GYP))
314 CheckFileIsWritable(BuildTmpFilename(CPP_HEADER_TEST))
315 CheckFileIsWritable(BuildTmpFilename(CPP_DEV_HEADER_TEST))
316
317 # Update each of the .scons files into temporary files.
318 UpdateSconsToTmp(BUILD_SCONS)
319 UpdateSconsToTmp(NACL_SCONS)
320
321 # Update the .gyp file into temporary file.
322 UpdateSconsToTmp(PPAPI_GYP)
323
324 # Update each of the .cc files into temporary files.
325 UpdateCcToTmp(CPP_HEADER_TEST)
326 UpdateCcToTmp(CPP_DEV_HEADER_TEST)
327
328 # Copy the temporary files back to the real files.
329 RenameTmpToFile(BUILD_SCONS)
330 RenameTmpToFile(NACL_SCONS)
331 RenameTmpToFile(PPAPI_GYP)
332 RenameTmpToFile(CPP_HEADER_TEST)
333 RenameTmpToFile(CPP_DEV_HEADER_TEST)
334
335 return 0
336
337
338 if __name__ == '__main__':
339 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698