dillon - branch off of chromium-67.0.3396.87 and apply 67.bad-dfly
[chromium-dfly.git] / tools / grit / grit_rule.gni
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 # Instantiate grit. This will produce a script target to run grit, and a
6 # static library that compiles the .cc files.
7 #
8 # Parameters
9 #
10 #   source (required)
11 #       Path to .grd file.
12 #
13 #   source_is_generated (optional, defaults to false)
14 #       Declares that the input (or one of its dependencies) is generated so
15 #       that grit_info is not run on the file when
16 #       compute_grit_inputs_for_analyze is set (because the file will not
17 #       exist at analyze time). For "analyze" to be correct in this case, the
18 #       inputs to the grit file must either be listed in the inputs variable
19 #       or are listed as inputs to dependencies of this target.
20 #
21 #   inputs  (optional)
22 #       List of additional files, required for grit to process source file.
23 #
24 #   outputs (required)
25 #       List of outputs from grit, relative to the target_gen_dir. Grit will
26 #       verify at build time that this list is correct and will fail if there
27 #       is a mismatch between the outputs specified by the .grd file and the
28 #       outputs list here.
29 #
30 #       To get this list, you can look in the .grd file for
31 #       <output filename="..." and put those filename here. The base directory
32 #       of the list in Grit and the output list specified in the GN grit target
33 #       are the same (the target_gen_dir) so you can generally copy the names
34 #       exactly.
35 #
36 #       To get the list of outputs programatically, run:
37 #           python tools/grit/grit_info.py --outputs . path/to/your.grd
38 #       And strip the leading "./" from the output files.
39 #
40 #   defines (optional)
41 #       Extra defines to pass to grit (on top of the global grit_defines list).
42 #
43 #   grit_flags (optional)
44 #       List of strings containing extra command-line flags to pass to Grit.
45 #
46 #   resource_ids (optional)
47 #       Path to a grit "firstidsfile". Default is
48 #       //tools/gritsettings/resource_ids. Set to "" to use the value specified
49 #       in the <grit> nodes of the processed files.
50 #
51 #   output_dir (optional)
52 #       Directory for generated files. If you specify this, you will often
53 #       want to specify output_name if the target name is not particularly
54 #       unique, since this can cause files from multiple grit targets to
55 #       overwrite each other.
56 #
57 #   output_name (optional)
58 #       Provide an alternate base name for the generated files, like the .d
59 #       files. Normally these are based on the target name and go in the
60 #       output_dir, but if multiple targets with the same name end up in
61 #       the same output_dir, they can collide.
62 #
63 #   depfile_dir (optional)
64 #       If set, used to store the depfile and corresponding stamp file.
65 #       Defaults to output_dir
66 #
67 #   configs (optional)
68 #       List of additional configs to be applied to the generated target.
69 #   deps  (optional)
70 #   visibility  (optional)
71 #       Normal meaning.
72 #
73 # Example
74 #
75 #   grit("my_resources") {
76 #     # Source and outputs are required.
77 #     source = "myfile.grd"
78 #     outputs = [
79 #       "foo_strings.h",
80 #       "foo_strings.pak",
81 #     ]
82 #
83 #     grit_flags = [ "-E", "foo=bar" ]  # Optional extra flags.
84 #     # You can also put deps here if the grit source depends on generated
85 #     # files.
86 #   }
87 import("//build/config/android/config.gni")
88 import("//build/config/chrome_build.gni")
89 import("//build/config/crypto.gni")
90 import("//build/config/features.gni")
91 import("//build/config/ui.gni")
92 import("//third_party/closure_compiler/closure_args.gni")
93
94 assert(!enable_resource_whitelist_generation || is_android,
95        "resource whitelist generation only works on android")
96
97 declare_args() {
98   # When set, this will fork out to grit at GN-time to get all inputs
99   # referenced by the .grd file.
100   #
101   # Normal builds don't need this since proper incremental builds are handled
102   # by grit writing out the inputs in .d files at build-time. But for analyze
103   # to work on the bots, it needs to know about all input files at GN-time so
104   # it knows which tests to trigger when something changes. This option will
105   # slow down the GN run.
106   compute_grit_inputs_for_analyze = false
107 }
108
109 grit_defines = []
110
111 # Mac and iOS want Title Case strings.
112 use_titlecase_in_grd_files = is_mac || is_ios
113 if (use_titlecase_in_grd_files) {
114   grit_defines += [
115     "-D",
116     "use_titlecase",
117   ]
118 }
119
120 if (is_chrome_branded) {
121   grit_defines += [
122     "-D",
123     "_google_chrome",
124     "-E",
125     "CHROMIUM_BUILD=google_chrome",
126   ]
127 } else {
128   grit_defines += [
129     "-D",
130     "_chromium",
131     "-E",
132     "CHROMIUM_BUILD=chromium",
133   ]
134 }
135
136 if (is_chromeos) {
137   grit_defines += [
138     "-D",
139     "chromeos",
140     "-D",
141     "scale_factors=2x",
142   ]
143 }
144
145 if (is_desktop_linux) {
146   grit_defines += [
147     "-D",
148     "desktop_linux",
149   ]
150 }
151
152 if (toolkit_views) {
153   grit_defines += [
154     "-D",
155     "toolkit_views",
156   ]
157 }
158
159 if (use_aura) {
160   grit_defines += [
161     "-D",
162     "use_aura",
163   ]
164 }
165
166 if (use_nss_certs) {
167   grit_defines += [
168     "-D",
169     "use_nss_certs",
170   ]
171 }
172
173 if (use_ozone) {
174   grit_defines += [
175     "-D",
176     "use_ozone",
177   ]
178 }
179
180 if (is_android) {
181   grit_defines += [
182     "-E",
183     "ANDROID_JAVA_TAGGED_ONLY=true",
184   ]
185 }
186
187 if (is_mac || is_ios) {
188   grit_defines += [
189     "-D",
190     "scale_factors=2x",
191   ]
192 }
193
194 # When cross-compiling, explicitly pass the target system to grit.
195 if (current_toolchain != host_toolchain) {
196   if (is_android) {
197     grit_defines += [
198       "-t",
199       "android",
200     ]
201   }
202   if (is_ios) {
203     grit_defines += [
204       "-t",
205       "ios",
206     ]
207   }
208   if (is_linux || is_bsd) {
209     grit_defines += [
210       "-t",
211       "linux2",
212     ]
213   }
214   if (is_mac) {
215     grit_defines += [
216       "-t",
217       "darwin",
218     ]
219   }
220   if (is_win) {
221     grit_defines += [
222       "-t",
223       "win32",
224     ]
225   }
226 }
227
228 # TODO(aberent): Enable for other platforms once the build machines have
229 #                Java on them (and hence can run the closure compiler).
230 _strip_resource_files = is_android
231 _js_minifier = "//third_party/closure_compiler/js_minify.py"
232
233 grit_resource_id_file = "//tools/gritsettings/resource_ids"
234 grit_info_script = "//tools/grit/grit_info.py"
235
236 # TODO(asvitkine): Add predetermined ids files for other platforms.
237 grit_predetermined_resource_ids_file = ""
238 if (is_mac) {
239   grit_predetermined_resource_ids_file =
240       "//tools/gritsettings/startup_resources_mac.txt"
241 }
242 if (is_win) {
243   grit_predetermined_resource_ids_file =
244       "//tools/gritsettings/startup_resources_win.txt"
245 }
246
247 template("grit") {
248   assert(defined(invoker.source),
249          "\"source\" must be defined for the grit template $target_name")
250
251   if (defined(invoker.resource_ids)) {
252     resource_ids = invoker.resource_ids
253   } else {
254     resource_ids = grit_resource_id_file
255   }
256
257   if (defined(invoker.output_dir)) {
258     output_dir = invoker.output_dir
259   } else {
260     output_dir = target_gen_dir
261   }
262
263   if (defined(invoker.output_name)) {
264     grit_output_name = invoker.output_name
265   } else {
266     grit_output_name = target_name
267   }
268
269   if (defined(invoker.depfile_dir)) {
270     depfile_dir = invoker.depfile_dir
271   } else {
272     depfile_dir = output_dir
273   }
274
275   # These are all passed as arguments to the script so have to be relative to
276   # the build directory.
277   rebased_output_dir = rebase_path(output_dir, root_build_dir)
278   source_path = rebase_path(invoker.source, root_build_dir)
279
280   # Compute flags.
281   grit_flags = []
282   if (enable_resource_whitelist_generation) {
283     grit_flags += [ "-h" ]
284     if (is_win) {
285       grit_flags += [ "#define {textual_id} __pragma(message(\"whitelisted_resource_{numeric_id}\")) {numeric_id}" ]
286     } else {
287       grit_flags += [ "#define {textual_id} _Pragma(\"whitelisted_resource_{numeric_id}\") {numeric_id}" ]
288     }
289   }
290   if (defined(invoker.grit_flags)) {
291     grit_flags += invoker.grit_flags
292   }
293   if (resource_ids != "") {
294     grit_flags += [
295       "-f",
296       rebase_path(resource_ids, root_build_dir),
297     ]
298   }
299   if (grit_predetermined_resource_ids_file != "") {
300     grit_flags += [
301       "-p",
302       rebase_path(grit_predetermined_resource_ids_file, root_build_dir),
303     ]
304   }
305
306   if (defined(invoker.source_is_generated)) {
307     source_is_generated = invoker.source_is_generated
308   } else {
309     source_is_generated = false
310   }
311
312   assert_files_flags = []
313
314   # We want to make sure the declared outputs actually match what Grit is
315   # writing. We write the list to a file (some of the output lists are long
316   # enough to not fit on a Windows command line) and ask Grit to verify those
317   # are the actual outputs at runtime.
318   asserted_list_file =
319       "$target_out_dir/${grit_output_name}_expected_outputs.txt"
320   write_file(asserted_list_file,
321              rebase_path(invoker.outputs, root_build_dir, output_dir))
322   assert_files_flags += [ "--assert-file-list=" +
323                           rebase_path(asserted_list_file, root_build_dir) ]
324   grit_outputs =
325       get_path_info(rebase_path(invoker.outputs, ".", output_dir), "abspath")
326
327   # Add .info output for all pak files
328   set_sources_assignment_filter([ "*.pak" ])
329   sources = grit_outputs
330   pak_grit_outputs = grit_outputs - sources
331   sources = []
332   pak_info_outputs = []
333   foreach(output, pak_grit_outputs) {
334     pak_info_outputs += [ "${output}.info" ]
335   }
336
337   # The config and the action below get this visibility son only the generated
338   # source set can depend on them. The variable "target_name" will get
339   # overwritten inside the inner classes so we need to compute it here.
340   target_visibility = [ ":$target_name" ]
341
342   # This config sets up flags needed for enable_resource_whitelist_generation.
343   grit_config = target_name + "_grit_config"
344   config(grit_config) {
345     if ((is_linux || is_android || is_bsd) &&
346     enable_resource_whitelist_generation) {
347       cflags = [
348         "-Wunknown-pragmas",
349         "-Wno-error=unknown-pragmas",
350       ]
351     }
352     visibility = target_visibility
353   }
354
355   grit_custom_target = target_name + "_grit"
356   action(grit_custom_target) {
357     script = "//tools/grit/grit.py"
358
359     inputs = [
360       invoker.source,
361     ]
362     if (resource_ids != "") {
363       # The script depends on the ID file. Only add this dependency if the ID
364       # file is specified.
365       inputs += [ resource_ids ]
366     }
367
368     depfile = "$depfile_dir/${grit_output_name}_stamp.d"
369     outputs = [ "${depfile}.stamp" ] + grit_outputs + pak_info_outputs
370
371     args = [
372              "-i",
373              source_path,
374              "build",
375              "-o",
376              rebased_output_dir,
377              "--depdir",
378              ".",
379              "--depfile",
380              rebase_path(depfile, root_build_dir),
381              "--write-only-new=1",
382              "--depend-on-stamp",
383            ] + grit_defines
384
385     # Add extra defines with -D flags.
386     define_args = []
387     if (defined(invoker.defines)) {
388       foreach(i, invoker.defines) {
389         define_args += [
390           "-D",
391           i,
392         ]
393       }
394     }
395
396     args += define_args + grit_flags + assert_files_flags
397
398     if (_strip_resource_files) {
399       js_minifier_command = rebase_path(_js_minifier)
400       js_minifier_command = "$js_minifier_command --closure_args"
401       foreach(closure_arg,
402               common_closure_args + minifying_closure_args +
403                   default_disabled_closure_args) {
404         js_minifier_command = "$js_minifier_command $closure_arg"
405       }
406       args += [
407         "--js-minifier",
408         js_minifier_command,
409       ]
410       inputs += [
411         _js_minifier,
412         "//third_party/closure_compiler/compiler/compiler.jar",
413       ]
414     }
415
416     # Must be after the args are computed since they are re-used.
417     # See the comments for the two variables used in this condition for
418     # why this works this way.
419     if (compute_grit_inputs_for_analyze && !source_is_generated) {
420       grit_info_script = "//tools/grit/grit_info.py"
421       grit_info_args = [
422                          "--inputs",
423                          source_path,
424                        ] + grit_flags + grit_defines
425
426       # Only call exec_script when the user has explicitly opted into greater
427       # precision at the expense of performance.
428       rel_inputs = exec_script(grit_info_script,
429                                grit_info_args,
430                                "list lines",
431                                [ grit_info_script ])
432       inputs += rebase_path(rel_inputs, ".", root_build_dir)
433     } else {
434       assert(source_is_generated || !source_is_generated)  # Prevent error.
435     }
436
437     if (defined(invoker.visibility)) {
438       # This needs to include both what the invoker specified (since they
439       # probably include generated headers from this target), as well as the
440       # generated source set (since there's no guarantee that the visibility
441       # specified by the invoker includes our target).
442       #
443       # Only define visibility at all if the invoker specified it. Otherwise,
444       # we want to keep the public "no visibility specified" default.
445       visibility = target_visibility + invoker.visibility
446     }
447
448     deps = [
449       "//tools/grit:grit_sources",
450     ]
451     if (defined(invoker.deps)) {
452       deps += invoker.deps
453     }
454     if (defined(invoker.inputs)) {
455       inputs += invoker.inputs
456     }
457   }
458
459   # This is the thing that people actually link with, it must be named the
460   # same as the argument the template was invoked with.
461   source_set(target_name) {
462     # Since we generate a file, we need to be run before the targets that
463     # depend on us.
464     sources = grit_outputs
465
466     # Deps set on the template invocation will go on the action that runs
467     # grit above rather than this library. This target needs to depend on the
468     # action publicly so other scripts can take the outputs from the grit
469     # script as inputs.
470     public_deps = [
471       ":$grit_custom_target",
472     ]
473     public_configs = [ ":$grit_config" ]
474
475     if (defined(invoker.public_configs)) {
476       public_configs += invoker.public_configs
477     }
478
479     if (defined(invoker.configs)) {
480       configs += invoker.configs
481     }
482
483     if (defined(invoker.visibility)) {
484       visibility = invoker.visibility
485     }
486     output_name = grit_output_name
487   }
488 }