| 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 |