| 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 -h HEADERFORMAT Custom format string to use for generating rc header files. | 102 -h HEADERFORMAT Custom format string to use for generating rc header files. |
| 103 The string should have two placeholders: {textual_id} | 103 The string should have two placeholders: {textual_id} |
| 104 and {numeric_id}. E.g. "#define {textual_id} {numeric_id}" | 104 and {numeric_id}. E.g. "#define {textual_id} {numeric_id}" |
| 105 Otherwise it will use the default "#define SYMBOL 1234" | 105 Otherwise it will use the default "#define SYMBOL 1234" |
| 106 | 106 |
| 107 --output-all-resource-defines | 107 --output-all-resource-defines |
| 108 --no-output-all-resource-defines If specified, overrides the value of the | 108 --no-output-all-resource-defines If specified, overrides the value of the |
| 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 |
| 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 |
| 115 is different from the old file. This allows some build |
| 116 systems to realize that dependent build steps might be |
| 117 unnecessary, at the cost of comparing the output data at |
| 118 grit time. |
| 119 |
| 120 |
| 112 Conditional inclusion of resources only affects the output of files which | 121 Conditional inclusion of resources only affects the output of files which |
| 113 control which resources get linked into a binary, e.g. it affects .rc files | 122 control which resources get linked into a binary, e.g. it affects .rc files |
| 114 meant for compilation but it does not affect resource header files (that define | 123 meant for compilation but it does not affect resource header files (that define |
| 115 IDs). This helps ensure that values of IDs stay the same, that all messages | 124 IDs). This helps ensure that values of IDs stay the same, that all messages |
| 116 are exported to translation interchange files (e.g. XMB files), etc. | 125 are exported to translation interchange files (e.g. XMB files), etc. |
| 117 ''' | 126 ''' |
| 118 | 127 |
| 119 def ShortDescription(self): | 128 def ShortDescription(self): |
| 120 return 'A tool that builds RC files for compilation.' | 129 return 'A tool that builds RC files for compilation.' |
| 121 | 130 |
| 122 def Run(self, opts, args): | 131 def Run(self, opts, args): |
| 123 self.output_directory = '.' | 132 self.output_directory = '.' |
| 124 first_ids_file = None | 133 first_ids_file = None |
| 125 whitelist_filenames = [] | 134 whitelist_filenames = [] |
| 126 assert_output_files = [] | 135 assert_output_files = [] |
| 127 target_platform = None | 136 target_platform = None |
| 128 depfile = None | 137 depfile = None |
| 129 depdir = None | 138 depdir = None |
| 130 rc_header_format = None | 139 rc_header_format = None |
| 131 output_all_resource_defines = None | 140 output_all_resource_defines = None |
| 141 write_only_new = False |
| 132 (own_opts, args) = getopt.getopt(args, 'a:o:D:E:f:w:t:h:', | 142 (own_opts, args) = getopt.getopt(args, 'a:o:D:E:f:w:t:h:', |
| 133 ('depdir=','depfile=','assert-file-list=', | 143 ('depdir=','depfile=','assert-file-list=', |
| 134 'output-all-resource-defines', | 144 'output-all-resource-defines', |
| 135 'no-output-all-resource-defines',)) | 145 'no-output-all-resource-defines', |
| 146 'write-only-new=')) |
| 136 for (key, val) in own_opts: | 147 for (key, val) in own_opts: |
| 137 if key == '-a': | 148 if key == '-a': |
| 138 assert_output_files.append(val) | 149 assert_output_files.append(val) |
| 139 elif key == '--assert-file-list': | 150 elif key == '--assert-file-list': |
| 140 with open(val) as f: | 151 with open(val) as f: |
| 141 assert_output_files += f.read().splitlines() | 152 assert_output_files += f.read().splitlines() |
| 142 elif key == '-o': | 153 elif key == '-o': |
| 143 self.output_directory = val | 154 self.output_directory = val |
| 144 elif key == '-D': | 155 elif key == '-D': |
| 145 name, val = util.ParseDefine(val) | 156 name, val = util.ParseDefine(val) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 159 elif key == '--no-output-all-resource-defines': | 170 elif key == '--no-output-all-resource-defines': |
| 160 output_all_resource_defines = False | 171 output_all_resource_defines = False |
| 161 elif key == '-t': | 172 elif key == '-t': |
| 162 target_platform = val | 173 target_platform = val |
| 163 elif key == '-h': | 174 elif key == '-h': |
| 164 rc_header_format = val | 175 rc_header_format = val |
| 165 elif key == '--depdir': | 176 elif key == '--depdir': |
| 166 depdir = val | 177 depdir = val |
| 167 elif key == '--depfile': | 178 elif key == '--depfile': |
| 168 depfile = val | 179 depfile = val |
| 180 elif key == '--write-only-new': |
| 181 write_only_new = val != '0' |
| 169 | 182 |
| 170 if len(args): | 183 if len(args): |
| 171 print 'This tool takes no tool-specific arguments.' | 184 print 'This tool takes no tool-specific arguments.' |
| 172 return 2 | 185 return 2 |
| 173 self.SetOptions(opts) | 186 self.SetOptions(opts) |
| 174 if self.scons_targets: | 187 if self.scons_targets: |
| 175 self.VerboseOut('Using SCons targets to identify files to output.\n') | 188 self.VerboseOut('Using SCons targets to identify files to output.\n') |
| 176 else: | 189 else: |
| 177 self.VerboseOut('Output directory: %s (absolute path: %s)\n' % | 190 self.VerboseOut('Output directory: %s (absolute path: %s)\n' % |
| 178 (self.output_directory, | 191 (self.output_directory, |
| 179 os.path.abspath(self.output_directory))) | 192 os.path.abspath(self.output_directory))) |
| 180 | 193 |
| 181 if whitelist_filenames: | 194 if whitelist_filenames: |
| 182 self.whitelist_names = set() | 195 self.whitelist_names = set() |
| 183 for whitelist_filename in whitelist_filenames: | 196 for whitelist_filename in whitelist_filenames: |
| 184 self.VerboseOut('Using whitelist: %s\n' % whitelist_filename); | 197 self.VerboseOut('Using whitelist: %s\n' % whitelist_filename); |
| 185 whitelist_contents = util.ReadFile(whitelist_filename, util.RAW_TEXT) | 198 whitelist_contents = util.ReadFile(whitelist_filename, util.RAW_TEXT) |
| 186 self.whitelist_names.update(whitelist_contents.strip().split('\n')) | 199 self.whitelist_names.update(whitelist_contents.strip().split('\n')) |
| 187 | 200 |
| 201 self.write_only_new = write_only_new |
| 202 |
| 188 self.res = grd_reader.Parse(opts.input, | 203 self.res = grd_reader.Parse(opts.input, |
| 189 debug=opts.extra_verbose, | 204 debug=opts.extra_verbose, |
| 190 first_ids_file=first_ids_file, | 205 first_ids_file=first_ids_file, |
| 191 defines=self.defines, | 206 defines=self.defines, |
| 192 target_platform=target_platform) | 207 target_platform=target_platform) |
| 193 | 208 |
| 194 # If the output_all_resource_defines option is specified, override the value | 209 # If the output_all_resource_defines option is specified, override the value |
| 195 # found in the grd file. | 210 # found in the grd file. |
| 196 if output_all_resource_defines is not None: | 211 if output_all_resource_defines is not None: |
| 197 self.res.SetShouldOutputAllResourceDefines(output_all_resource_defines) | 212 self.res.SetShouldOutputAllResourceDefines(output_all_resource_defines) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 | 244 |
| 230 # Set to a list of filenames for the output nodes that are relative | 245 # Set to a list of filenames for the output nodes that are relative |
| 231 # to the current working directory. They are in the same order as the | 246 # to the current working directory. They are in the same order as the |
| 232 # output nodes in the file. | 247 # output nodes in the file. |
| 233 self.scons_targets = None | 248 self.scons_targets = None |
| 234 | 249 |
| 235 # The set of names that are whitelisted to actually be included in the | 250 # The set of names that are whitelisted to actually be included in the |
| 236 # output. | 251 # output. |
| 237 self.whitelist_names = None | 252 self.whitelist_names = None |
| 238 | 253 |
| 254 # Whether to compare outputs to their old contents before writing. |
| 255 self.write_only_new = False |
| 256 |
| 239 @staticmethod | 257 @staticmethod |
| 240 def AddWhitelistTags(start_node, whitelist_names): | 258 def AddWhitelistTags(start_node, whitelist_names): |
| 241 # Walk the tree of nodes added attributes for the nodes that shouldn't | 259 # Walk the tree of nodes added attributes for the nodes that shouldn't |
| 242 # be written into the target files (skip markers). | 260 # be written into the target files (skip markers). |
| 243 from grit.node import include | 261 from grit.node import include |
| 244 from grit.node import message | 262 from grit.node import message |
| 245 from grit.node import structure | 263 from grit.node import structure |
| 246 for node in start_node: | 264 for node in start_node: |
| 247 # Same trick data_pack.py uses to see what nodes actually result in | 265 # Same trick data_pack.py uses to see what nodes actually result in |
| 248 # real items. | 266 # real items. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 # Now copy from the temp file back to the real output, but on Windows, | 352 # Now copy from the temp file back to the real output, but on Windows, |
| 335 # only if the real output doesn't exist or the contents of the file | 353 # only if the real output doesn't exist or the contents of the file |
| 336 # changed. This prevents identical headers from being written and .cc | 354 # changed. This prevents identical headers from being written and .cc |
| 337 # files from recompiling (which is painful on Windows). | 355 # files from recompiling (which is painful on Windows). |
| 338 if not os.path.exists(output.GetOutputFilename()): | 356 if not os.path.exists(output.GetOutputFilename()): |
| 339 os.rename(output.GetOutputFilename() + '.tmp', | 357 os.rename(output.GetOutputFilename() + '.tmp', |
| 340 output.GetOutputFilename()) | 358 output.GetOutputFilename()) |
| 341 else: | 359 else: |
| 342 # CHROMIUM SPECIFIC CHANGE. | 360 # CHROMIUM SPECIFIC CHANGE. |
| 343 # This clashes with gyp + vstudio, which expect the output timestamp | 361 # This clashes with gyp + vstudio, which expect the output timestamp |
| 344 # to change on a rebuild, even if nothing has changed. | 362 # to change on a rebuild, even if nothing has changed, so only do |
| 345 #files_match = filecmp.cmp(output.GetOutputFilename(), | 363 # it when opted in. |
| 346 # output.GetOutputFilename() + '.tmp') | 364 if not self.write_only_new: |
| 347 #if (output.GetType() != 'rc_header' or not files_match | 365 write_file = True |
| 348 # or sys.platform != 'win32'): | 366 else: |
| 349 shutil.copy2(output.GetOutputFilename() + '.tmp', | 367 files_match = filecmp.cmp(output.GetOutputFilename(), |
| 350 output.GetOutputFilename()) | 368 output.GetOutputFilename() + '.tmp') |
| 369 write_file = not files_match |
| 370 if write_file: |
| 371 shutil.copy2(output.GetOutputFilename() + '.tmp', |
| 372 output.GetOutputFilename()) |
| 351 os.remove(output.GetOutputFilename() + '.tmp') | 373 os.remove(output.GetOutputFilename() + '.tmp') |
| 352 | 374 |
| 353 self.VerboseOut(' done.\n') | 375 self.VerboseOut(' done.\n') |
| 354 | 376 |
| 355 # Print warnings if there are any duplicate shortcuts. | 377 # Print warnings if there are any duplicate shortcuts. |
| 356 warnings = shortcuts.GenerateDuplicateShortcutsWarnings( | 378 warnings = shortcuts.GenerateDuplicateShortcutsWarnings( |
| 357 self.res.UberClique(), self.res.GetTcProject()) | 379 self.res.UberClique(), self.res.GetTcProject()) |
| 358 if warnings: | 380 if warnings: |
| 359 print '\n'.join(warnings) | 381 print '\n'.join(warnings) |
| 360 | 382 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 self.MakeDirectoriesTo(depfile) | 467 self.MakeDirectoriesTo(depfile) |
| 446 outfile = self.fo_create(depfile, 'wb') | 468 outfile = self.fo_create(depfile, 'wb') |
| 447 outfile.writelines(depfile_contents) | 469 outfile.writelines(depfile_contents) |
| 448 | 470 |
| 449 @staticmethod | 471 @staticmethod |
| 450 def MakeDirectoriesTo(file): | 472 def MakeDirectoriesTo(file): |
| 451 '''Creates directories necessary to contain |file|.''' | 473 '''Creates directories necessary to contain |file|.''' |
| 452 dir = os.path.split(file)[0] | 474 dir = os.path.split(file)[0] |
| 453 if not os.path.exists(dir): | 475 if not os.path.exists(dir): |
| 454 os.makedirs(dir) | 476 os.makedirs(dir) |
| OLD | NEW |