blob: 4339996d4157ca6d2b962a1b31d6c9f18275c6a6 [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001# Copyright 2015 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# Generates a header with preprocessor defines specified by the build file.
6# The GYP version of this (with instructions) is build/buildflag_header.gypi.
7#
8# The flags are converted to function-style defines with mangled names and
9# code uses an accessor macro to access the values. This is to try to
10# minimize bugs where code checks whether something is defined or not, and
11# the proper header isn't included, meaning the answer will always be silently
12# false or might vary across the code base.
13#
14# In the GN template, specify build flags in the template as a list
15# of strings that encode key/value pairs like this:
16#
17# flags = [ "ENABLE_FOO=1", "ENABLE_BAR=$enable_bar" ]
18#
19# The GN values "true" and "false" will be mapped to 0 and 1 for boolean
20# #if flags to be expressed naturally. This means you can't directly make a
21# define that generates C++ value of true or false for use in code. If you
22# REALLY need this, you can also use the string "(true)" and "(false)" to
23# prevent the rewriting.
24
25# To check the value of the flag in C code:
26#
27# #include "path/to/here/header_file.h"
28#
29# #if BUILDFLAG(ENABLE_FOO)
30# ...
31# #endif
32#
33# const char kSpamServerUrl[] = BUILDFLAG(SPAM_SERVER_URL);
34#
35# There will no #define called ENABLE_FOO so if you accidentally test for that
36# in an ifdef it will always be negative.
37#
38#
39# Template parameters
40#
41# flags [required, list of strings]
42# Flag values as described above.
43#
44# header [required, string]
45# File name for generated header. By default, this will go in the
46# generated file directory for this target, and you would include it
47# with:
48# #include "<path_to_this_BUILD_file>/<header>"
49#
50# header_dir [optional, string]
51# Override the default location of the generated header. The string will
52# be treated as a subdirectory of the root_gen_dir. For example:
53# header_dir = "foo/bar"
54# Then you can include the header as:
55# #include "foo/bar/baz.h"
56#
57# deps, public_deps, testonly, visibility
58# Normal meaning.
59#
60#
61# Grit defines
62#
63# If one .grd file uses a flag, just add to the grit target:
64#
65# defines = [
66# "enable_doom_melon=$enable_doom_melon",
67# ]
68#
69# If multiple .grd files use it, you'll want to put the defines in a .gni file
70# so it can be shared. Generally this .gni file should include all grit defines
71# for a given module (for some definition of "module"). Then do:
72#
73# defines = ui_grit_defines
74#
75# If you forget to do this, the flag will be implicitly false in the .grd file
76# and those resources won't be compiled. You'll know because the resource
77# #define won't be generated and any code that uses it won't compile. If you
78# see a missing IDS_* string, this is probably the reason.
79#
80#
81# Example
82#
83# buildflag_header("foo_features") {
84# header = "foo_features.h"
85#
86# flags = [
87# # This uses the GN build flag enable_doom_melon as the definition.
88# "ENABLE_DOOM_MELON=$enable_doom_melon",
89#
90# # This force-enables the flag.
91# "ENABLE_SPACE_LASER=true",
92#
93# # This will expand to the quoted C string when used in source code.
94# "SPAM_SERVER_URL=\"http://www.example.com/\"",
95# ]
96# }
97template("buildflag_header") {
98 action(target_name) {
99 script = "//build/write_buildflag_header.py"
100
101 if (defined(invoker.header_dir)) {
102 header_file = "${invoker.header_dir}/${invoker.header}"
103 } else {
104 # Compute the path from the root to this file.
105 header_file = rebase_path(".", "//") + "/${invoker.header}"
106 }
107
108 outputs = [
109 "$root_gen_dir/$header_file",
110 ]
111
112 # Always write --flags to the file so it's not empty. Empty will confuse GN
113 # into thinking the response file isn't used.
114 response_file_contents = [ "--flags" ]
115 if (defined(invoker.flags)) {
116 response_file_contents += invoker.flags
117 }
118
119 args = [
120 "--output",
121 header_file, # Not rebased, Python script puts it inside gen-dir.
122 "--rulename",
123 get_label_info(":$target_name", "label_no_toolchain"),
124 "--gen-dir",
125 rebase_path(root_gen_dir, root_build_dir),
126 "--definitions",
127 "{{response_file_name}}",
128 ]
129
130 forward_variables_from(invoker,
131 [
132 "deps",
133 "public_deps",
134 "testonly",
135 "visibility",
136 ])
137 }
138}