Chromium Code Reviews| 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 |