summaryrefslogtreecommitdiffstats
path: root/build/buildflag_header.gni
blob: 4339996d4157ca6d2b962a1b31d6c9f18275c6a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Generates a header with preprocessor defines specified by the build file.
# The GYP version of this (with instructions) is build/buildflag_header.gypi.
#
# The flags are converted to function-style defines with mangled names and
# code uses an accessor macro to access the values. This is to try to
# minimize bugs where code checks whether something is defined or not, and
# the proper header isn't included, meaning the answer will always be silently
# false or might vary across the code base.
#
# In the GN template, specify build flags in the template as a list
# of strings that encode key/value pairs like this:
#
#   flags = [ "ENABLE_FOO=1", "ENABLE_BAR=$enable_bar" ]
#
# The GN values "true" and "false" will be mapped to 0 and 1 for boolean
# #if flags to be expressed naturally. This means you can't directly make a
# define that generates C++ value of true or false for use in code. If you
# REALLY need this, you can also use the string "(true)" and "(false)" to
# prevent the rewriting.

# To check the value of the flag in C code:
#
#   #include "path/to/here/header_file.h"
#
#   #if BUILDFLAG(ENABLE_FOO)
#   ...
#   #endif
#
#   const char kSpamServerUrl[] = BUILDFLAG(SPAM_SERVER_URL);
#
# There will no #define called ENABLE_FOO so if you accidentally test for that
# in an ifdef it will always be negative.
#
#
# Template parameters
#
#   flags [required, list of strings]
#       Flag values as described above.
#
#   header [required, string]
#       File name for generated header. By default, this will go in the
#       generated file directory for this target, and you would include it
#       with:
#         #include "<path_to_this_BUILD_file>/<header>"
#
#   header_dir [optional, string]
#       Override the default location of the generated header. The string will
#       be treated as a subdirectory of the root_gen_dir. For example:
#         header_dir = "foo/bar"
#       Then you can include the header as:
#         #include "foo/bar/baz.h"
#
#   deps, public_deps, testonly, visibility
#       Normal meaning.
#
#
# Grit defines
#
# If one .grd file uses a flag, just add to the grit target:
#
#   defines = [
#     "enable_doom_melon=$enable_doom_melon",
#   ]
#
# If multiple .grd files use it, you'll want to put the defines in a .gni file
# so it can be shared. Generally this .gni file should include all grit defines
# for a given module (for some definition of "module"). Then do:
#
#   defines = ui_grit_defines
#
# If you forget to do this, the flag will be implicitly false in the .grd file
# and those resources won't be compiled. You'll know because the resource
# #define won't be generated and any code that uses it won't compile. If you
# see a missing IDS_* string, this is probably the reason.
#
#
# Example
#
#   buildflag_header("foo_features") {
#     header = "foo_features.h"
#
#     flags = [
#       # This uses the GN build flag enable_doom_melon as the definition.
#       "ENABLE_DOOM_MELON=$enable_doom_melon",
#
#       # This force-enables the flag.
#       "ENABLE_SPACE_LASER=true",
#
#       # This will expand to the quoted C string when used in source code.
#       "SPAM_SERVER_URL=\"http://www.example.com/\"",
#     ]
#   }
template("buildflag_header") {
  action(target_name) {
    script = "//build/write_buildflag_header.py"

    if (defined(invoker.header_dir)) {
      header_file = "${invoker.header_dir}/${invoker.header}"
    } else {
      # Compute the path from the root to this file.
      header_file = rebase_path(".", "//") + "/${invoker.header}"
    }

    outputs = [
      "$root_gen_dir/$header_file",
    ]

    # Always write --flags to the file so it's not empty. Empty will confuse GN
    # into thinking the response file isn't used.
    response_file_contents = [ "--flags" ]
    if (defined(invoker.flags)) {
      response_file_contents += invoker.flags
    }

    args = [
      "--output",
      header_file,  # Not rebased, Python script puts it inside gen-dir.
      "--rulename",
      get_label_info(":$target_name", "label_no_toolchain"),
      "--gen-dir",
      rebase_path(root_gen_dir, root_build_dir),
      "--definitions",
      "{{response_file_name}}",
    ]

    forward_variables_from(invoker,
                           [
                             "deps",
                             "public_deps",
                             "testonly",
                             "visibility",
                           ])
  }
}