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

Side by Side Diff: grit/tool/build.py

Issue 407693002: Fix .d file outputs, add support for asserting outputs. (Closed) Base URL: https://chromium.googlesource.com/external/grit-i18n.git@master
Patch Set: now with tests Created 6 years, 5 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
« no previous file with comments | « no previous file | grit/tool/build_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 '''The 'grit build' tool along with integration for this tool with the 6 '''The 'grit build' tool along with integration for this tool with the
7 SCons build system. 7 SCons build system.
8 ''' 8 '''
9 9
10 import filecmp 10 import filecmp
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 '''A tool that builds RC files and resource header files for compilation. 56 '''A tool that builds RC files and resource header files for compilation.
57 57
58 Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]* 58 Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]*
59 59
60 All output options for this tool are specified in the input file (see 60 All output options for this tool are specified in the input file (see
61 'grit help' for details on how to specify the input file - it is a global 61 'grit help' for details on how to specify the input file - it is a global
62 option). 62 option).
63 63
64 Options: 64 Options:
65 65
66 -a FILE Assert that the given file is an output. There can be
67 multiple "-a" flags listed for multiple outputs. If a "-a"
68 or "--assert-file-list" argument is present, then the list
69 of asserted files must match the output files or the tool
70 will fail. The use-case is for the build system to maintain
71 separate lists of output files and to catch errors if the
72 build system's list and the grit list are out-of-sync.
73
74 --assert-file-list Provide a file listing multiple asserted output files.
75 There is one file name per line. This acts like specifying
76 each file with "-a" on the command line, but without the
77 possibility of running into OS line-length limits for very
78 long lists.
79
66 -o OUTPUTDIR Specify what directory output paths are relative to. 80 -o OUTPUTDIR Specify what directory output paths are relative to.
67 Defaults to the current directory. 81 Defaults to the current directory.
68 82
69 -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional 83 -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
70 value VAL (defaults to 1) which will be used to control 84 value VAL (defaults to 1) which will be used to control
71 conditional inclusion of resources. 85 conditional inclusion of resources.
72 86
73 -E NAME=VALUE Set environment variable NAME to VALUE (within grit). 87 -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
74 88
75 -f FIRSTIDSFILE Path to a python file that specifies the first id of 89 -f FIRSTIDSFILE Path to a python file that specifies the first id of
(...skipping 21 matching lines...) Expand all
97 are exported to translation interchange files (e.g. XMB files), etc. 111 are exported to translation interchange files (e.g. XMB files), etc.
98 ''' 112 '''
99 113
100 def ShortDescription(self): 114 def ShortDescription(self):
101 return 'A tool that builds RC files for compilation.' 115 return 'A tool that builds RC files for compilation.'
102 116
103 def Run(self, opts, args): 117 def Run(self, opts, args):
104 self.output_directory = '.' 118 self.output_directory = '.'
105 first_ids_file = None 119 first_ids_file = None
106 whitelist_filenames = [] 120 whitelist_filenames = []
121 assert_output_files = []
107 target_platform = None 122 target_platform = None
108 depfile = None 123 depfile = None
109 depdir = None 124 depdir = None
110 rc_header_format = None 125 rc_header_format = None
111 (own_opts, args) = getopt.getopt(args, 'o:D:E:f:w:t:h:', ('depdir=','depfile =')) 126 (own_opts, args) = getopt.getopt(args, 'a:o:D:E:f:w:t:h:',
127 ('depdir=','depfile=','assert-file-list='))
112 for (key, val) in own_opts: 128 for (key, val) in own_opts:
113 if key == '-o': 129 if key == '-a':
130 assert_output_files.append(val)
131 elif key == '--assert-file-list':
132 with open(val) as f:
133 assert_output_files += f.read().splitlines()
134 elif key == '-o':
114 self.output_directory = val 135 self.output_directory = val
115 elif key == '-D': 136 elif key == '-D':
116 name, val = util.ParseDefine(val) 137 name, val = util.ParseDefine(val)
117 self.defines[name] = val 138 self.defines[name] = val
118 elif key == '-E': 139 elif key == '-E':
119 (env_name, env_value) = val.split('=', 1) 140 (env_name, env_value) = val.split('=', 1)
120 os.environ[env_name] = env_value 141 os.environ[env_name] = env_value
121 elif key == '-f': 142 elif key == '-f':
122 # TODO(joi@chromium.org): Remove this override once change 143 # TODO(joi@chromium.org): Remove this override once change
123 # lands in WebKit.grd to specify the first_ids_file in the 144 # lands in WebKit.grd to specify the first_ids_file in the
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 target_platform=target_platform) 180 target_platform=target_platform)
160 # Set an output context so that conditionals can use defines during the 181 # Set an output context so that conditionals can use defines during the
161 # gathering stage; we use a dummy language here since we are not outputting 182 # gathering stage; we use a dummy language here since we are not outputting
162 # a specific language. 183 # a specific language.
163 self.res.SetOutputLanguage('en') 184 self.res.SetOutputLanguage('en')
164 if rc_header_format: 185 if rc_header_format:
165 self.res.AssignRcHeaderFormat(rc_header_format) 186 self.res.AssignRcHeaderFormat(rc_header_format)
166 self.res.RunGatherers() 187 self.res.RunGatherers()
167 self.Process() 188 self.Process()
168 189
190 if assert_output_files:
191 if not self.CheckAssertedOutputFiles(assert_output_files):
192 return 2
193
169 if depfile and depdir: 194 if depfile and depdir:
170 self.GenerateDepfile(opts.input, depfile, depdir) 195 self.GenerateDepfile(depfile, depdir)
171 196
172 return 0 197 return 0
173 198
174 def __init__(self, defines=None): 199 def __init__(self, defines=None):
175 # Default file-creation function is built-in open(). Only done to allow 200 # Default file-creation function is built-in open(). Only done to allow
176 # overriding by unit test. 201 # overriding by unit test.
177 self.fo_create = open 202 self.fo_create = open
178 203
179 # key/value pairs of C-preprocessor like defines that are used for 204 # key/value pairs of C-preprocessor like defines that are used for
180 # conditional output of resources 205 # conditional output of resources
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 # exit with an error code if there are missing translations in a non-pseudo 342 # exit with an error code if there are missing translations in a non-pseudo
318 # and non-official build. 343 # and non-official build.
319 warnings = (self.res.UberClique().MissingTranslationsReport(). 344 warnings = (self.res.UberClique().MissingTranslationsReport().
320 encode('ascii', 'replace')) 345 encode('ascii', 'replace'))
321 if warnings: 346 if warnings:
322 self.VerboseOut(warnings) 347 self.VerboseOut(warnings)
323 if self.res.UberClique().HasMissingTranslations(): 348 if self.res.UberClique().HasMissingTranslations():
324 print self.res.UberClique().missing_translations_ 349 print self.res.UberClique().missing_translations_
325 sys.exit(-1) 350 sys.exit(-1)
326 351
327 def GenerateDepfile(self, input_filename, depfile, depdir): 352
353 def CheckAssertedOutputFiles(self, assert_output_files):
354 '''Checks that the asserted output files are specified in the given list.
355
356 Returns true if the asserted files are present. If they are not, returns
357 False and prints the failure.
358 '''
359 # Compare the absolute path names, sorted.
360 asserted = sorted([os.path.abspath(i) for i in assert_output_files])
Nico 2014/07/21 18:09:25 so asserted_output_files is relative to the cwd, b
brettw 2014/07/21 19:51:53 Yes, like all other inputs, they're relative to th
361 actual = sorted([
362 os.path.abspath(os.path.join(self.output_directory, i.GetFilename()))
363 for i in self.res.GetOutputFiles()])
364
365 if asserted != actual:
366 print '''Asserted file list does not match.
367
368 Expected output files: %s
369
370 Actual output files: %s
371 ''' % (asserted, actual)
372 return False
373 return True
374
375
376 def GenerateDepfile(self, depfile, depdir):
328 '''Generate a depfile that contains the imlicit dependencies of the input 377 '''Generate a depfile that contains the imlicit dependencies of the input
329 grd. The depfile will be in the same format as a makefile, and will contain 378 grd. The depfile will be in the same format as a makefile, and will contain
330 references to files relative to |depdir|. It will be put in |depfile|. 379 references to files relative to |depdir|. It will be put in |depfile|.
331 380
332 For example, supposing we have three files in a directory src/ 381 For example, supposing we have three files in a directory src/
333 382
334 src/ 383 src/
335 blah.grd <- depends on input{1,2}.xtb 384 blah.grd <- depends on input{1,2}.xtb
336 input1.xtb 385 input1.xtb
337 input2.xtb 386 input2.xtb
338 387
339 and we run 388 and we run
340 389
341 grit -i blah.grd -o ../out/gen --depdir ../out --depfile ../out/gen/blah.r d.d 390 grit -i blah.grd -o ../out/gen --depdir ../out --depfile ../out/gen/blah.r d.d
342 391
343 from the directory src/ we will generate a depfile ../out/gen/blah.grd.d 392 from the directory src/ we will generate a depfile ../out/gen/blah.grd.d
344 that has the contents 393 that has the contents
345 394
346 gen/blah.grd.d: ../src/input1.xtb ../src/input2.xtb 395 gen/blah.h: ../src/input1.xtb ../src/input2.xtb
396
397 Where "gen/blah.h" is the first output (Ninja expects the .d file to list
398 the first output in cases where there is more than one).
347 399
348 Note that all paths in the depfile are relative to ../out, the depdir. 400 Note that all paths in the depfile are relative to ../out, the depdir.
349 ''' 401 '''
350 depfile = os.path.abspath(depfile) 402 depfile = os.path.abspath(depfile)
351 depdir = os.path.abspath(depdir) 403 depdir = os.path.abspath(depdir)
404 infiles = self.res.GetInputFiles()
405
406 # Get the first output file relative to the depdir.
407 outputs = self.res.GetOutputFiles()
408 output_file = os.path.relpath(os.path.join(
409 self.output_directory, outputs[0].GetFilename()), depdir)
410
352 # The path prefix to prepend to dependencies in the depfile. 411 # The path prefix to prepend to dependencies in the depfile.
353 prefix = os.path.relpath(os.getcwd(), depdir) 412 prefix = os.path.relpath(os.getcwd(), depdir)
354 # The path that the depfile refers to itself by.
355 self_ref_depfile = os.path.relpath(depfile, depdir)
356 infiles = self.res.GetInputFiles()
357 deps_text = ' '.join([os.path.join(prefix, i) for i in infiles]) 413 deps_text = ' '.join([os.path.join(prefix, i) for i in infiles])
358 depfile_contents = self_ref_depfile + ': ' + deps_text 414
415 depfile_contents = output_file + ': ' + deps_text
359 self.MakeDirectoriesTo(depfile) 416 self.MakeDirectoriesTo(depfile)
360 outfile = self.fo_create(depfile, 'wb') 417 outfile = self.fo_create(depfile, 'wb')
361 outfile.writelines(depfile_contents) 418 outfile.writelines(depfile_contents)
362 419
363 @staticmethod 420 @staticmethod
364 def MakeDirectoriesTo(file): 421 def MakeDirectoriesTo(file):
365 '''Creates directories necessary to contain |file|.''' 422 '''Creates directories necessary to contain |file|.'''
366 dir = os.path.split(file)[0] 423 dir = os.path.split(file)[0]
367 if not os.path.exists(dir): 424 if not os.path.exists(dir):
368 os.makedirs(dir) 425 os.makedirs(dir)
OLDNEW
« no previous file with comments | « no previous file | grit/tool/build_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698