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