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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 ''' | 91 ''' |
| 92 | 92 |
| 93 def ShortDescription(self): | 93 def ShortDescription(self): |
| 94 return 'A tool that builds RC files for compilation.' | 94 return 'A tool that builds RC files for compilation.' |
| 95 | 95 |
| 96 def Run(self, opts, args): | 96 def Run(self, opts, args): |
| 97 self.output_directory = '.' | 97 self.output_directory = '.' |
| 98 first_ids_file = None | 98 first_ids_file = None |
| 99 whitelist_filenames = [] | 99 whitelist_filenames = [] |
| 100 target_platform = None | 100 target_platform = None |
| 101 (own_opts, args) = getopt.getopt(args, 'o:D:E:f:w:t:') | 101 dep_dir = None |
| 102 (own_opts, args) = getopt.getopt(args, 'o:D:E:f:w:t:', ('dep-dir=',)) | |
| 102 for (key, val) in own_opts: | 103 for (key, val) in own_opts: |
| 103 if key == '-o': | 104 if key == '-o': |
| 104 self.output_directory = val | 105 self.output_directory = val |
| 105 elif key == '-D': | 106 elif key == '-D': |
| 106 name, val = util.ParseDefine(val) | 107 name, val = util.ParseDefine(val) |
| 107 self.defines[name] = val | 108 self.defines[name] = val |
| 108 elif key == '-E': | 109 elif key == '-E': |
| 109 (env_name, env_value) = val.split('=', 1) | 110 (env_name, env_value) = val.split('=', 1) |
| 110 os.environ[env_name] = env_value | 111 os.environ[env_name] = env_value |
| 111 elif key == '-f': | 112 elif key == '-f': |
| 112 # TODO(joi@chromium.org): Remove this override once change | 113 # TODO(joi@chromium.org): Remove this override once change |
| 113 # lands in WebKit.grd to specify the first_ids_file in the | 114 # lands in WebKit.grd to specify the first_ids_file in the |
| 114 # .grd itself. | 115 # .grd itself. |
| 115 first_ids_file = val | 116 first_ids_file = val |
| 116 elif key == '-w': | 117 elif key == '-w': |
| 117 whitelist_filenames.append(val) | 118 whitelist_filenames.append(val) |
| 118 elif key == '-t': | 119 elif key == '-t': |
| 119 target_platform = val | 120 target_platform = val |
| 121 elif key == '--dep-dir': | |
| 122 dep_dir = val | |
| 120 | 123 |
| 121 if len(args): | 124 if len(args): |
| 122 print 'This tool takes no tool-specific arguments.' | 125 print 'This tool takes no tool-specific arguments.' |
| 123 return 2 | 126 return 2 |
| 124 self.SetOptions(opts) | 127 self.SetOptions(opts) |
| 125 if self.scons_targets: | 128 if self.scons_targets: |
| 126 self.VerboseOut('Using SCons targets to identify files to output.\n') | 129 self.VerboseOut('Using SCons targets to identify files to output.\n') |
| 127 else: | 130 else: |
| 128 self.VerboseOut('Output directory: %s (absolute path: %s)\n' % | 131 self.VerboseOut('Output directory: %s (absolute path: %s)\n' % |
| 129 (self.output_directory, | 132 (self.output_directory, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 140 debug=opts.extra_verbose, | 143 debug=opts.extra_verbose, |
| 141 first_ids_file=first_ids_file, | 144 first_ids_file=first_ids_file, |
| 142 defines=self.defines, | 145 defines=self.defines, |
| 143 target_platform=target_platform) | 146 target_platform=target_platform) |
| 144 # Set an output context so that conditionals can use defines during the | 147 # Set an output context so that conditionals can use defines during the |
| 145 # gathering stage; we use a dummy language here since we are not outputting | 148 # gathering stage; we use a dummy language here since we are not outputting |
| 146 # a specific language. | 149 # a specific language. |
| 147 self.res.SetOutputLanguage('en') | 150 self.res.SetOutputLanguage('en') |
| 148 self.res.RunGatherers() | 151 self.res.RunGatherers() |
| 149 self.Process() | 152 self.Process() |
| 153 | |
| 154 if dep_dir: | |
| 155 self.GenerateDepfile(opts.input, dep_dir) | |
| 156 | |
| 150 return 0 | 157 return 0 |
| 151 | 158 |
| 152 def __init__(self, defines=None): | 159 def __init__(self, defines=None): |
| 153 # Default file-creation function is built-in open(). Only done to allow | 160 # Default file-creation function is built-in open(). Only done to allow |
| 154 # overriding by unit test. | 161 # overriding by unit test. |
| 155 self.fo_create = open | 162 self.fo_create = open |
| 156 | 163 |
| 157 # key/value pairs of C-preprocessor like defines that are used for | 164 # key/value pairs of C-preprocessor like defines that are used for |
| 158 # conditional output of resources | 165 # conditional output of resources |
| 159 self.defines = defines or {} | 166 self.defines = defines or {} |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 else: | 251 else: |
| 245 # TODO(gfeher) modify here to set utf-8 encoding for admx/adml | 252 # TODO(gfeher) modify here to set utf-8 encoding for admx/adml |
| 246 encoding = 'utf_16' | 253 encoding = 'utf_16' |
| 247 | 254 |
| 248 # Set the context, for conditional inclusion of resources | 255 # Set the context, for conditional inclusion of resources |
| 249 self.res.SetOutputLanguage(output.GetLanguage()) | 256 self.res.SetOutputLanguage(output.GetLanguage()) |
| 250 self.res.SetOutputContext(output.GetContext()) | 257 self.res.SetOutputContext(output.GetContext()) |
| 251 self.res.SetDefines(self.defines) | 258 self.res.SetDefines(self.defines) |
| 252 | 259 |
| 253 # Make the output directory if it doesn't exist. | 260 # Make the output directory if it doesn't exist. |
| 254 outdir = os.path.split(output.GetOutputFilename())[0] | 261 self.MakeDirectoriesTo(output.GetOutputFilename()) |
| 255 if not os.path.exists(outdir): | |
| 256 os.makedirs(outdir) | |
| 257 | 262 |
| 258 # Write the results to a temporary file and only overwrite the original | 263 # Write the results to a temporary file and only overwrite the original |
| 259 # if the file changed. This avoids unnecessary rebuilds. | 264 # if the file changed. This avoids unnecessary rebuilds. |
| 260 outfile = self.fo_create(output.GetOutputFilename() + '.tmp', 'wb') | 265 outfile = self.fo_create(output.GetOutputFilename() + '.tmp', 'wb') |
| 261 | 266 |
| 262 if output.GetType() != 'data_package': | 267 if output.GetType() != 'data_package': |
| 263 outfile = util.WrapOutputStream(outfile, encoding) | 268 outfile = util.WrapOutputStream(outfile, encoding) |
| 264 | 269 |
| 265 # Iterate in-order through entire resource tree, calling formatters on | 270 # Iterate in-order through entire resource tree, calling formatters on |
| 266 # the entry into a node and on exit out of it. | 271 # the entry into a node and on exit out of it. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 297 # Print out any fallback warnings, and missing translation errors, and | 302 # Print out any fallback warnings, and missing translation errors, and |
| 298 # exit with an error code if there are missing translations in a non-pseudo | 303 # exit with an error code if there are missing translations in a non-pseudo |
| 299 # and non-official build. | 304 # and non-official build. |
| 300 warnings = (self.res.UberClique().MissingTranslationsReport(). | 305 warnings = (self.res.UberClique().MissingTranslationsReport(). |
| 301 encode('ascii', 'replace')) | 306 encode('ascii', 'replace')) |
| 302 if warnings: | 307 if warnings: |
| 303 self.VerboseOut(warnings) | 308 self.VerboseOut(warnings) |
| 304 if self.res.UberClique().HasMissingTranslations(): | 309 if self.res.UberClique().HasMissingTranslations(): |
| 305 print self.res.UberClique().missing_translations_ | 310 print self.res.UberClique().missing_translations_ |
| 306 sys.exit(-1) | 311 sys.exit(-1) |
| 312 | |
| 313 def GenerateDepfile(self, input_filename, dep_dir): | |
| 314 '''Generate a depfile that contains the imlicit dependencies of the input | |
| 315 grd. The depfile will be in the same format as a makefile, and will contain | |
| 316 references to files relative to |dep_dir|. It will be put in the same | |
| 317 directory as the generated outputs. | |
| 318 | |
| 319 For example, supposing we have three files in a directory src/ | |
| 320 | |
| 321 src/ | |
| 322 blah.grd <- depends on input{1,2}.xtb | |
| 323 input1.xtb | |
| 324 input2.xtb | |
| 325 | |
| 326 and we run | |
| 327 | |
| 328 grit -i blah.grd -o ../out/gen --dep-dir ../out | |
| 329 | |
| 330 from the directory src/ we will generate a depfile ../out/gen/blah.grd.d | |
| 331 that has the contents | |
| 332 | |
| 333 gen/blah.grd.d: ../src/input1.xtb ../src/input2.xtb | |
| 334 | |
| 335 Note that all paths in the depfile are relative to ../out, the dep-dir. | |
| 336 ''' | |
| 337 depsfile_basename = os.path.basename(input_filename + '.d') | |
| 338 depfile = os.path.abspath( | |
| 339 os.path.join(self.output_directory, depsfile_basename)) | |
| 340 dep_dir = os.path.abspath(dep_dir) | |
| 341 # The path prefix to prepend to dependencies in the depfile. | |
| 342 prefix = os.path.relpath(os.getcwd(), dep_dir) | |
| 343 # The path that the depfile refers to itself by. | |
| 344 self_ref_depfile = os.path.relpath(depfile, dep_dir) | |
| 345 infiles = self.res.GetInputFiles() | |
| 346 deps_text = ' '.join([os.path.join(prefix, i) for i in infiles]) | |
| 347 depfile_contents = self_ref_depfile + ': ' + deps_text | |
| 348 self.MakeDirectoriesTo(depfile) | |
| 349 outfile = self.fo_create(depfile, 'wb') | |
| 350 outfile.writelines(depfile_contents) | |
|
Nico
2013/12/31 01:07:42
I'm currently looking at using this in gyp, and I'
| |
| 351 | |
| 352 @staticmethod | |
| 353 def MakeDirectoriesTo(file): | |
| 354 '''Creates directories necessary to contain |file|.''' | |
| 355 dir = os.path.split(file)[0] | |
| 356 if not os.path.exists(dir): | |
| 357 os.makedirs(dir) | |
| OLD | NEW |