OLD | NEW |
---|---|
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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 output_all_resource_defines attribute of the root <grit> | 109 output_all_resource_defines attribute of the root <grit> |
110 element of the input .grd file. | 110 element of the input .grd file. |
111 | 111 |
112 --write-only-new flag | 112 --write-only-new flag |
113 If flag is non-0, write output files to a temporary file | 113 If flag is non-0, write output files to a temporary file |
114 first, and copy it to the real output only if the new file | 114 first, and copy it to the real output only if the new file |
115 is different from the old file. This allows some build | 115 is different from the old file. This allows some build |
116 systems to realize that dependent build steps might be | 116 systems to realize that dependent build steps might be |
117 unnecessary, at the cost of comparing the output data at | 117 unnecessary, at the cost of comparing the output data at |
118 grit time. | 118 grit time. |
119 | 119 |
120 --depend-on-stamp | |
121 If specified along with --depfile and --depdir, the depfile | |
122 generated will depend on the depfile itself instead of the | |
Nico
2015/03/12 21:34:24
this is kinda weird
cjhopman
2015/03/12 21:38:35
Yeah, and it'll need to be changed if we change gn
| |
123 first output in the input .grd file. Thus the depfile also | |
124 plays the role of an implicit stamp file. | |
120 | 125 |
121 Conditional inclusion of resources only affects the output of files which | 126 Conditional inclusion of resources only affects the output of files which |
122 control which resources get linked into a binary, e.g. it affects .rc files | 127 control which resources get linked into a binary, e.g. it affects .rc files |
123 meant for compilation but it does not affect resource header files (that define | 128 meant for compilation but it does not affect resource header files (that define |
124 IDs). This helps ensure that values of IDs stay the same, that all messages | 129 IDs). This helps ensure that values of IDs stay the same, that all messages |
125 are exported to translation interchange files (e.g. XMB files), etc. | 130 are exported to translation interchange files (e.g. XMB files), etc. |
126 ''' | 131 ''' |
127 | 132 |
128 def ShortDescription(self): | 133 def ShortDescription(self): |
129 return 'A tool that builds RC files for compilation.' | 134 return 'A tool that builds RC files for compilation.' |
130 | 135 |
131 def Run(self, opts, args): | 136 def Run(self, opts, args): |
132 self.output_directory = '.' | 137 self.output_directory = '.' |
133 first_ids_file = None | 138 first_ids_file = None |
134 whitelist_filenames = [] | 139 whitelist_filenames = [] |
135 assert_output_files = [] | 140 assert_output_files = [] |
136 target_platform = None | 141 target_platform = None |
137 depfile = None | 142 depfile = None |
138 depdir = None | 143 depdir = None |
139 rc_header_format = None | 144 rc_header_format = None |
140 output_all_resource_defines = None | 145 output_all_resource_defines = None |
141 write_only_new = False | 146 write_only_new = False |
147 depend_on_stamp = False | |
142 (own_opts, args) = getopt.getopt(args, 'a:o:D:E:f:w:t:h:', | 148 (own_opts, args) = getopt.getopt(args, 'a:o:D:E:f:w:t:h:', |
143 ('depdir=','depfile=','assert-file-list=', | 149 ('depdir=','depfile=','assert-file-list=', |
144 'output-all-resource-defines', | 150 'output-all-resource-defines', |
145 'no-output-all-resource-defines', | 151 'no-output-all-resource-defines', |
152 'depend-on-stamp', | |
146 'write-only-new=')) | 153 'write-only-new=')) |
147 for (key, val) in own_opts: | 154 for (key, val) in own_opts: |
148 if key == '-a': | 155 if key == '-a': |
149 assert_output_files.append(val) | 156 assert_output_files.append(val) |
150 elif key == '--assert-file-list': | 157 elif key == '--assert-file-list': |
151 with open(val) as f: | 158 with open(val) as f: |
152 assert_output_files += f.read().splitlines() | 159 assert_output_files += f.read().splitlines() |
153 elif key == '-o': | 160 elif key == '-o': |
154 self.output_directory = val | 161 self.output_directory = val |
155 elif key == '-D': | 162 elif key == '-D': |
(...skipping 16 matching lines...) Expand all Loading... | |
172 elif key == '-t': | 179 elif key == '-t': |
173 target_platform = val | 180 target_platform = val |
174 elif key == '-h': | 181 elif key == '-h': |
175 rc_header_format = val | 182 rc_header_format = val |
176 elif key == '--depdir': | 183 elif key == '--depdir': |
177 depdir = val | 184 depdir = val |
178 elif key == '--depfile': | 185 elif key == '--depfile': |
179 depfile = val | 186 depfile = val |
180 elif key == '--write-only-new': | 187 elif key == '--write-only-new': |
181 write_only_new = val != '0' | 188 write_only_new = val != '0' |
189 elif key == '--depend-on-stamp': | |
190 depend_on_stamp = True | |
182 | 191 |
183 if len(args): | 192 if len(args): |
184 print 'This tool takes no tool-specific arguments.' | 193 print 'This tool takes no tool-specific arguments.' |
185 return 2 | 194 return 2 |
186 self.SetOptions(opts) | 195 self.SetOptions(opts) |
187 if self.scons_targets: | 196 if self.scons_targets: |
188 self.VerboseOut('Using SCons targets to identify files to output.\n') | 197 self.VerboseOut('Using SCons targets to identify files to output.\n') |
189 else: | 198 else: |
190 self.VerboseOut('Output directory: %s (absolute path: %s)\n' % | 199 self.VerboseOut('Output directory: %s (absolute path: %s)\n' % |
191 (self.output_directory, | 200 (self.output_directory, |
(...skipping 26 matching lines...) Expand all Loading... | |
218 if rc_header_format: | 227 if rc_header_format: |
219 self.res.AssignRcHeaderFormat(rc_header_format) | 228 self.res.AssignRcHeaderFormat(rc_header_format) |
220 self.res.RunGatherers() | 229 self.res.RunGatherers() |
221 self.Process() | 230 self.Process() |
222 | 231 |
223 if assert_output_files: | 232 if assert_output_files: |
224 if not self.CheckAssertedOutputFiles(assert_output_files): | 233 if not self.CheckAssertedOutputFiles(assert_output_files): |
225 return 2 | 234 return 2 |
226 | 235 |
227 if depfile and depdir: | 236 if depfile and depdir: |
228 self.GenerateDepfile(depfile, depdir, first_ids_file) | 237 self.GenerateDepfile(depfile, depdir, first_ids_file, depend_on_stamp) |
229 | 238 |
230 return 0 | 239 return 0 |
231 | 240 |
232 def __init__(self, defines=None): | 241 def __init__(self, defines=None): |
233 # Default file-creation function is built-in open(). Only done to allow | 242 # Default file-creation function is built-in open(). Only done to allow |
234 # overriding by unit test. | 243 # overriding by unit test. |
235 self.fo_create = open | 244 self.fo_create = open |
236 | 245 |
237 # key/value pairs of C-preprocessor like defines that are used for | 246 # key/value pairs of C-preprocessor like defines that are used for |
238 # conditional output of resources | 247 # conditional output of resources |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
417 %s | 426 %s |
418 Extra output files: | 427 Extra output files: |
419 %s | 428 %s |
420 ''' | 429 ''' |
421 print error % ('\n'.join(asserted), '\n'.join(actual), '\n'.join(missing), | 430 print error % ('\n'.join(asserted), '\n'.join(actual), '\n'.join(missing), |
422 '\n'.join(extra)) | 431 '\n'.join(extra)) |
423 return False | 432 return False |
424 return True | 433 return True |
425 | 434 |
426 | 435 |
427 def GenerateDepfile(self, depfile, depdir, first_ids_file): | 436 def GenerateDepfile(self, depfile, depdir, first_ids_file, depend_on_stamp): |
428 '''Generate a depfile that contains the imlicit dependencies of the input | 437 '''Generate a depfile that contains the imlicit dependencies of the input |
429 grd. The depfile will be in the same format as a makefile, and will contain | 438 grd. The depfile will be in the same format as a makefile, and will contain |
430 references to files relative to |depdir|. It will be put in |depfile|. | 439 references to files relative to |depdir|. It will be put in |depfile|. |
431 | 440 |
432 For example, supposing we have three files in a directory src/ | 441 For example, supposing we have three files in a directory src/ |
433 | 442 |
434 src/ | 443 src/ |
435 blah.grd <- depends on input{1,2}.xtb | 444 blah.grd <- depends on input{1,2}.xtb |
436 input1.xtb | 445 input1.xtb |
437 input2.xtb | 446 input2.xtb |
438 | 447 |
439 and we run | 448 and we run |
440 | 449 |
441 grit -i blah.grd -o ../out/gen --depdir ../out --depfile ../out/gen/blah.r d.d | 450 grit -i blah.grd -o ../out/gen --depdir ../out --depfile ../out/gen/blah.r d.d |
442 | 451 |
443 from the directory src/ we will generate a depfile ../out/gen/blah.grd.d | 452 from the directory src/ we will generate a depfile ../out/gen/blah.grd.d |
444 that has the contents | 453 that has the contents |
445 | 454 |
446 gen/blah.h: ../src/input1.xtb ../src/input2.xtb | 455 gen/blah.h: ../src/input1.xtb ../src/input2.xtb |
447 | 456 |
448 Where "gen/blah.h" is the first output (Ninja expects the .d file to list | 457 Where "gen/blah.h" is the first output (Ninja expects the .d file to list |
449 the first output in cases where there is more than one). | 458 the first output in cases where there is more than one). If the flag |
459 --depend-on-stamp is specified, it is "gen/blah.rd.d" instead which is also | |
460 playing the role of a dummy stamp output now. | |
450 | 461 |
451 Note that all paths in the depfile are relative to ../out, the depdir. | 462 Note that all paths in the depfile are relative to ../out, the depdir. |
452 ''' | 463 ''' |
453 depfile = os.path.abspath(depfile) | 464 depfile = os.path.abspath(depfile) |
454 depdir = os.path.abspath(depdir) | 465 depdir = os.path.abspath(depdir) |
455 infiles = self.res.GetInputFiles() | 466 infiles = self.res.GetInputFiles() |
456 | 467 |
457 # We want to trigger a rebuild if the first ids change. | 468 # We want to trigger a rebuild if the first ids change. |
458 if first_ids_file is not None: | 469 if first_ids_file is not None: |
459 infiles.append(first_ids_file) | 470 infiles.append(first_ids_file) |
460 | 471 |
461 # Get the first output file relative to the depdir. | 472 if (depend_on_stamp): |
462 outputs = self.res.GetOutputFiles() | 473 output_file = depfile |
463 output_file = os.path.relpath(os.path.join( | 474 else: |
464 self.output_directory, outputs[0].GetFilename()), depdir) | 475 # Get the first output file relative to the depdir. |
476 outputs = self.res.GetOutputFiles() | |
477 output_file = os.path.join(self.output_directory, | |
478 outputs[0].GetFilename()) | |
465 | 479 |
480 output_file = os.path.relpath(output_file, depdir) | |
466 # The path prefix to prepend to dependencies in the depfile. | 481 # The path prefix to prepend to dependencies in the depfile. |
467 prefix = os.path.relpath(os.getcwd(), depdir) | 482 prefix = os.path.relpath(os.getcwd(), depdir) |
468 deps_text = ' '.join([os.path.join(prefix, i) for i in infiles]) | 483 deps_text = ' '.join([os.path.join(prefix, i) for i in infiles]) |
469 | 484 |
470 depfile_contents = output_file + ': ' + deps_text | 485 depfile_contents = output_file + ': ' + deps_text |
471 self.MakeDirectoriesTo(depfile) | 486 self.MakeDirectoriesTo(depfile) |
472 outfile = self.fo_create(depfile, 'wb') | 487 outfile = self.fo_create(depfile, 'wb') |
473 outfile.writelines(depfile_contents) | 488 outfile.writelines(depfile_contents) |
474 | 489 |
475 @staticmethod | 490 @staticmethod |
476 def MakeDirectoriesTo(file): | 491 def MakeDirectoriesTo(file): |
477 '''Creates directories necessary to contain |file|.''' | 492 '''Creates directories necessary to contain |file|.''' |
478 dir = os.path.split(file)[0] | 493 dir = os.path.split(file)[0] |
479 if not os.path.exists(dir): | 494 if not os.path.exists(dir): |
480 os.makedirs(dir) | 495 os.makedirs(dir) |
OLD | NEW |