Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: grit/tool/build.py

Issue 9965022: Allow substitution of messages as variables in other messages. (Closed) Base URL: https://grit-i18n.googlecode.com/svn/trunk
Patch Set: Fix unit tests for policy writers. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « grit/testdata/transl.rc ('k') | grit/tool/resize.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 import getopt 11 import getopt
12 import os 12 import os
13 import shutil 13 import shutil
14 import sys 14 import sys
15 import types 15 import types
16 16
17 from grit import grd_reader 17 from grit import grd_reader
18 from grit import util 18 from grit import util
19 from grit.tool import interface 19 from grit.tool import interface
20 from grit import shortcuts 20 from grit import shortcuts
21 21
22 22
23 def ParseDefine(define):
24 '''Parses a define that is either like "NAME" or "NAME=VAL" and
25 returns its components, using True as the default value. Values of
26 "1" and "0" are transformed to True and False respectively.
27 '''
28 parts = [part.strip() for part in define.split('=')]
29 assert len(parts) >= 1
30 name = parts[0]
31 val = True
32 if len(parts) > 1:
33 val = parts[1]
34 if val == "1": val = True
35 elif val == "0": val = False
36 return (name, val)
37
38
39 class RcBuilder(interface.Tool): 23 class RcBuilder(interface.Tool):
40 '''A tool that builds RC files and resource header files for compilation. 24 '''A tool that builds RC files and resource header files for compilation.
41 25
42 Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]* 26 Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]*
43 27
44 All output options for this tool are specified in the input file (see 28 All output options for this tool are specified in the input file (see
45 'grit help' for details on how to specify the input file - it is a global 29 'grit help' for details on how to specify the input file - it is a global
46 option). 30 option).
47 31
48 Options: 32 Options:
(...skipping 28 matching lines...) Expand all
77 61
78 def Run(self, opts, args): 62 def Run(self, opts, args):
79 self.output_directory = '.' 63 self.output_directory = '.'
80 first_ids_file = None 64 first_ids_file = None
81 whitelist_filenames = [] 65 whitelist_filenames = []
82 (own_opts, args) = getopt.getopt(args, 'o:D:E:f:w:') 66 (own_opts, args) = getopt.getopt(args, 'o:D:E:f:w:')
83 for (key, val) in own_opts: 67 for (key, val) in own_opts:
84 if key == '-o': 68 if key == '-o':
85 self.output_directory = val 69 self.output_directory = val
86 elif key == '-D': 70 elif key == '-D':
87 name, val = ParseDefine(val) 71 name, val = util.ParseDefine(val)
88 self.defines[name] = val 72 self.defines[name] = val
89 elif key == '-E': 73 elif key == '-E':
90 (env_name, env_value) = val.split('=') 74 (env_name, env_value) = val.split('=')
91 os.environ[env_name] = env_value 75 os.environ[env_name] = env_value
92 elif key == '-f': 76 elif key == '-f':
93 # TODO(joi@chromium.org): Remove this override once change 77 # TODO(joi@chromium.org): Remove this override once change
94 # lands in WebKit.grd to specify the first_ids_file in the 78 # lands in WebKit.grd to specify the first_ids_file in the
95 # .grd itself. 79 # .grd itself.
96 first_ids_file = val 80 first_ids_file = val
97 elif key == '-w': 81 elif key == '-w':
98 whitelist_filenames.append(val) 82 whitelist_filenames.append(val)
99 83
100 if len(args): 84 if len(args):
101 print "This tool takes no tool-specific arguments." 85 print 'This tool takes no tool-specific arguments.'
102 return 2 86 return 2
103 self.SetOptions(opts) 87 self.SetOptions(opts)
104 if self.scons_targets: 88 if self.scons_targets:
105 self.VerboseOut('Using SCons targets to identify files to output.\n') 89 self.VerboseOut('Using SCons targets to identify files to output.\n')
106 else: 90 else:
107 self.VerboseOut('Output directory: %s (absolute path: %s)\n' % 91 self.VerboseOut('Output directory: %s (absolute path: %s)\n' %
108 (self.output_directory, 92 (self.output_directory,
109 os.path.abspath(self.output_directory))) 93 os.path.abspath(self.output_directory)))
110 94
111 if whitelist_filenames: 95 if whitelist_filenames:
112 self.whitelist_names = set() 96 self.whitelist_names = set()
113 for whitelist_filename in whitelist_filenames: 97 for whitelist_filename in whitelist_filenames:
114 self.VerboseOut('Using whitelist: %s\n' % whitelist_filename); 98 self.VerboseOut('Using whitelist: %s\n' % whitelist_filename);
115 whitelist_file = open(whitelist_filename) 99 whitelist_file = open(whitelist_filename)
116 self.whitelist_names |= set(whitelist_file.read().strip().split('\n')) 100 self.whitelist_names |= set(whitelist_file.read().strip().split('\n'))
117 whitelist_file.close() 101 whitelist_file.close()
118 102
119 self.res = grd_reader.Parse(opts.input, 103 self.res = grd_reader.Parse(opts.input,
120 debug=opts.extra_verbose, 104 debug=opts.extra_verbose,
121 first_ids_file=first_ids_file, 105 first_ids_file=first_ids_file,
122 defines=self.defines) 106 defines=self.defines)
123 # Set an output context so that conditionals can use defines during the 107 # Set an output context so that conditionals can use defines during the
124 # gathering stage; we use a dummy language here since we are not outputting 108 # gathering stage; we use a dummy language here since we are not outputting
125 # a specific language. 109 # a specific language.
126 self.res.SetOutputContext('no-specific-language', self.defines) 110 self.res.SetOutputContext('en', self.defines)
127 self.res.RunGatherers(recursive = True) 111 self.res.RunGatherers(recursive = True)
128 self.Process() 112 self.Process()
129 return 0 113 return 0
130 114
131 def __init__(self, defines=None): 115 def __init__(self, defines=None):
132 # Default file-creation function is built-in file(). Only done to allow 116 # Default file-creation function is built-in file(). Only done to allow
133 # overriding by unit test. 117 # overriding by unit test.
134 self.fo_create = file 118 self.fo_create = file
135 119
136 # key/value pairs of C-preprocessor like defines that are used for 120 # key/value pairs of C-preprocessor like defines that are used for
137 # conditional output of resources 121 # conditional output of resources
138 if defines: 122 self.defines = defines or {}
139 self.defines = defines
140 else:
141 self.defines = {}
142 123
143 # self.res is a fully-populated resource tree if Run() 124 # self.res is a fully-populated resource tree if Run()
144 # has been called, otherwise None. 125 # has been called, otherwise None.
145 self.res = None 126 self.res = None
146 127
147 # Set to a list of filenames for the output nodes that are relative 128 # Set to a list of filenames for the output nodes that are relative
148 # to the current working directory. They are in the same order as the 129 # to the current working directory. They are in the same order as the
149 # output nodes in the file. 130 # output nodes in the file.
150 self.scons_targets = None 131 self.scons_targets = None
151 132
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 # Note: Some Format calls have side effects, so Format is always called 166 # Note: Some Format calls have side effects, so Format is always called
186 # and the whitelist is used to only avoid the output. 167 # and the whitelist is used to only avoid the output.
187 should_write = not node.WhitelistMarkedAsSkip() 168 should_write = not node.WhitelistMarkedAsSkip()
188 169
189 base_dir = util.dirname(output_node.GetOutputFilename()) 170 base_dir = util.dirname(output_node.GetOutputFilename())
190 171
191 try: 172 try:
192 formatter = node.ItemFormatter(output_node.GetType()) 173 formatter = node.ItemFormatter(output_node.GetType())
193 if formatter: 174 if formatter:
194 formatted = formatter.Format(node, output_node.GetLanguage(), 175 formatted = formatter.Format(node, output_node.GetLanguage(),
195 begin_item=True, output_dir=base_dir) 176 output_dir=base_dir)
196 if should_write: 177 if should_write:
197 outfile.write(formatted) 178 outfile.write(formatted)
198 except: 179 except:
199 print u"Error processing node %s" % unicode(node) 180 print u'Error processing node %s' % unicode(node)
200 raise 181 raise
201 182
202 for child in node.children: 183 for child in node.children:
203 RcBuilder.ProcessNode(child, output_node, outfile) 184 RcBuilder.ProcessNode(child, output_node, outfile)
204 185
205 try: 186 try:
206 if formatter: 187 if formatter:
207 formatted = formatter.Format(node, output_node.GetLanguage(), 188 formatted = formatter.FormatEnd(node, output_node.GetLanguage(),
208 begin_item=False, output_dir=base_dir) 189 output_dir=base_dir)
209 if should_write: 190 if should_write:
210 outfile.write(formatted) 191 outfile.write(formatted)
211 except: 192 except:
212 print u"Error processing node %s" % unicode(node) 193 print u'Error processing node %s' % unicode(node)
213 raise 194 raise
214 ProcessNode = staticmethod(ProcessNode) 195 ProcessNode = staticmethod(ProcessNode)
215 196
216 197
217 def Process(self): 198 def Process(self):
218 # Update filenames with those provided by SCons if we're being invoked 199 # Update filenames with those provided by SCons if we're being invoked
219 # from SCons. The list of SCons targets also includes all <structure> 200 # from SCons. The list of SCons targets also includes all <structure>
220 # node outputs, but it starts with our output files, in the order they 201 # node outputs, but it starts with our output files, in the order they
221 # occur in the .grd 202 # occur in the .grd
222 if self.scons_targets: 203 if self.scons_targets:
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 284
304 # Print out any fallback warnings, and missing translation errors, and 285 # Print out any fallback warnings, and missing translation errors, and
305 # exit with an error code if there are missing translations in a non-pseudo 286 # exit with an error code if there are missing translations in a non-pseudo
306 # and non-official build. 287 # and non-official build.
307 warnings = (self.res.UberClique().MissingTranslationsReport(). 288 warnings = (self.res.UberClique().MissingTranslationsReport().
308 encode('ascii', 'replace')) 289 encode('ascii', 'replace'))
309 if warnings and self.defines.get('_google_chrome', False): 290 if warnings and self.defines.get('_google_chrome', False):
310 print warnings 291 print warnings
311 if self.res.UberClique().HasMissingTranslations(): 292 if self.res.UberClique().HasMissingTranslations():
312 sys.exit(-1) 293 sys.exit(-1)
OLDNEW
« no previous file with comments | « grit/testdata/transl.rc ('k') | grit/tool/resize.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698