xref: /aosp_15_r20/external/pigweed/docs/blog/02-bazel-feature-flags.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _docs-blog-02-bazel-feature-flags:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker==================================================
4*61c4878aSAndroid Build Coastguard WorkerPigweed Eng Blog #2: Feature flags in Bazel builds
5*61c4878aSAndroid Build Coastguard Worker==================================================
6*61c4878aSAndroid Build Coastguard WorkerBy Ted Pudlik
7*61c4878aSAndroid Build Coastguard Worker
8*61c4878aSAndroid Build Coastguard WorkerPublished 2024-05-31
9*61c4878aSAndroid Build Coastguard Worker
10*61c4878aSAndroid Build Coastguard WorkerLet's say you're migrating your build system to Bazel. Your project heavily
11*61c4878aSAndroid Build Coastguard Workerrelies on preprocessor defines to configure its code.
12*61c4878aSAndroid Build Coastguard Worker
13*61c4878aSAndroid Build Coastguard Worker.. code-block::
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker   -DBUILD_FEATURE_CPU_PROFILE
16*61c4878aSAndroid Build Coastguard Worker   -DBUILD_FEATURE_HEAP_PROFILE
17*61c4878aSAndroid Build Coastguard Worker   -DBUILD_FEATURE_HW_SHA256
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard WorkerIn your source files, you use these preprocessor variables to conditionally
20*61c4878aSAndroid Build Coastguard Workercompile some sections, via ``#ifdef``. When building the same code for
21*61c4878aSAndroid Build Coastguard Workerdifferent final product configurations, you want to set different defines.
22*61c4878aSAndroid Build Coastguard Worker
23*61c4878aSAndroid Build Coastguard WorkerHow do you model this in Bazel?
24*61c4878aSAndroid Build Coastguard Worker
25*61c4878aSAndroid Build Coastguard WorkerThis post discusses three possible approaches:
26*61c4878aSAndroid Build Coastguard Worker
27*61c4878aSAndroid Build Coastguard Worker#. :ref:`docs-blog-02-config-with-copts`
28*61c4878aSAndroid Build Coastguard Worker#. :ref:`docs-blog-02-platform-based-skylib-flags`
29*61c4878aSAndroid Build Coastguard Worker#. :ref:`docs-blog-02-chromium-pattern`
30*61c4878aSAndroid Build Coastguard Worker
31*61c4878aSAndroid Build Coastguard WorkerWhich one to choose? If you have the freedom to refactor your code to use the
32*61c4878aSAndroid Build Coastguard WorkerChromium pattern, give it a try! It is not difficult to maintain once
33*61c4878aSAndroid Build Coastguard Workerimplemented, and can prevent real production issues by detecting typos.
34*61c4878aSAndroid Build Coastguard Worker
35*61c4878aSAndroid Build Coastguard Worker.. _docs-blog-02-config-with-copts:
36*61c4878aSAndroid Build Coastguard Worker
37*61c4878aSAndroid Build Coastguard Worker-------------------------------------------
38*61c4878aSAndroid Build Coastguard WorkerEasy but limited: bazelrc config with copts
39*61c4878aSAndroid Build Coastguard Worker-------------------------------------------
40*61c4878aSAndroid Build Coastguard WorkerLet's start with the simplest approach: you can put the compiler options into
41*61c4878aSAndroid Build Coastguard Workeryour `bazelrc configuration file <https://bazel.build/run/bazelrc>`_.
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker.. code-block::
44*61c4878aSAndroid Build Coastguard Worker
45*61c4878aSAndroid Build Coastguard Worker   # .bazelrc
46*61c4878aSAndroid Build Coastguard Worker
47*61c4878aSAndroid Build Coastguard Worker   common:mydevice_evt1 --copts=-DBUILD_FEATURE_CPU_PROFILE
48*61c4878aSAndroid Build Coastguard Worker   common:mydevice_evt1 --copts=-DBUILD_FEATURE_HEAP_PROFILE
49*61c4878aSAndroid Build Coastguard Worker   common:mydevice_evt1 --copts=-DBUILD_FEATURE_HW_SHA256
50*61c4878aSAndroid Build Coastguard Worker   # and so on
51*61c4878aSAndroid Build Coastguard Worker
52*61c4878aSAndroid Build Coastguard WorkerThen, when you build your application, the defines will all be applied:
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard Worker
55*61c4878aSAndroid Build Coastguard Worker.. code-block:: sh
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker   bazel build --config=mydevice_evt1 //src:application
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard Worker
60*61c4878aSAndroid Build Coastguard WorkerConfigs are expanded recursively, allowing you to group options together and
61*61c4878aSAndroid Build Coastguard Workerreuse them:
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker.. code-block::
64*61c4878aSAndroid Build Coastguard Worker
65*61c4878aSAndroid Build Coastguard Worker   # .bazelrc
66*61c4878aSAndroid Build Coastguard Worker
67*61c4878aSAndroid Build Coastguard Worker   common:full_profile --copts=-DBUILD_FEATURE_CPU_PROFILE
68*61c4878aSAndroid Build Coastguard Worker   common:full_profile --copts=-DBUILD_FEATURE_HEAP_PROFILE
69*61c4878aSAndroid Build Coastguard Worker
70*61c4878aSAndroid Build Coastguard Worker   # When building for mydevice_evt1, use full_profile.
71*61c4878aSAndroid Build Coastguard Worker   common:mydevice_evt1 --config=full_profile
72*61c4878aSAndroid Build Coastguard Worker
73*61c4878aSAndroid Build Coastguard Worker   # When building for mydevice_evt2, additionally enable HW_SHA256.
74*61c4878aSAndroid Build Coastguard Worker   common:mydevice_evt2 --config=full_profile
75*61c4878aSAndroid Build Coastguard Worker   common:mydevice_evt1 --copts=-DBUILD_FEATURE_HW_SHA256
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard WorkerDownsides
78*61c4878aSAndroid Build Coastguard Worker=========
79*61c4878aSAndroid Build Coastguard WorkerWhile it *is* simple, the config-with-copts approach has a few downsides.
80*61c4878aSAndroid Build Coastguard Worker
81*61c4878aSAndroid Build Coastguard Worker.. _docs-blog-02-config-dangeous-typos:
82*61c4878aSAndroid Build Coastguard Worker
83*61c4878aSAndroid Build Coastguard WorkerDangerous typos
84*61c4878aSAndroid Build Coastguard Worker---------------
85*61c4878aSAndroid Build Coastguard WorkerIf you misspell ``BUILDDD_FEATURE_CPU_PROFILE`` [sic!] in your ``.bazelrc``,
86*61c4878aSAndroid Build Coastguard Workerthe actual ``BUILD_FEATURE_CPU_PROFILE`` variable will `take the default value
87*61c4878aSAndroid Build Coastguard Workerof 0 <https://stackoverflow.com/q/5085392/24291280>`__. So, although you
88*61c4878aSAndroid Build Coastguard Workerintended to enable this feature, it will just remain disabled!
89*61c4878aSAndroid Build Coastguard Worker
90*61c4878aSAndroid Build Coastguard WorkerThis isn't just a Bazel problem, but a general issue with the simple
91*61c4878aSAndroid Build Coastguard Worker``BUILD_FEATURE`` macro pattern. If you misspell ``BUILD_FEATUER_CPU_PROFILE``
92*61c4878aSAndroid Build Coastguard Worker[sic!] in your C++ file, you'll get it to evaluate to 0 in any build system!
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard WorkerOne way to avoid this issue is to use the :ref:`"Chromium-style" build flag
95*61c4878aSAndroid Build Coastguard Workerpattern <docs-blog-02-chromium-pattern>`, ``BUILDFLAG(CPU_PROFILE)``. If you
96*61c4878aSAndroid Build Coastguard Workerdo, a misspelled or missing define becomes a compiler error. However, the
97*61c4878aSAndroid Build Coastguard Workerconfig-with-copts approach is a little *too* simple to express this pattern,
98*61c4878aSAndroid Build Coastguard Workerwhich requires code generation of the build flag headers.
99*61c4878aSAndroid Build Coastguard Worker
100*61c4878aSAndroid Build Coastguard WorkerNo multi-platform build support
101*61c4878aSAndroid Build Coastguard Worker-------------------------------
102*61c4878aSAndroid Build Coastguard WorkerBazel allows you to perform multi-platform builds. For example, in a single
103*61c4878aSAndroid Build Coastguard WorkerBazel invocation you can build a Python flasher program (that will run on your
104*61c4878aSAndroid Build Coastguard Workerlaptop) which embeds as a data dependency the microcontroller firmware to flash
105*61c4878aSAndroid Build Coastguard Worker(that will run on the microcontroller). `We do this in Pigweed's own
106*61c4878aSAndroid Build Coastguard Workerexamples
107*61c4878aSAndroid Build Coastguard Worker<https://cs.opensource.google/pigweed/examples/+/main:examples/01_blinky/BUILD.bazel>`__.
108*61c4878aSAndroid Build Coastguard Worker
109*61c4878aSAndroid Build Coastguard WorkerUnfortunately, the config-with-copts pattern doesn't work nicely with
110*61c4878aSAndroid Build Coastguard Workermulti-platform build primitives. (Technically, the problem is that Bazel
111*61c4878aSAndroid Build Coastguard Worker`doesn't support transitioning on --config
112*61c4878aSAndroid Build Coastguard Worker<https://bazel.build/extending/config#unsupported-native-options>`__.) If you
113*61c4878aSAndroid Build Coastguard Workerwant a multi-platform build, you need some more sophisticated idiom.
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard WorkerNo build system variables
116*61c4878aSAndroid Build Coastguard Worker-------------------------
117*61c4878aSAndroid Build Coastguard WorkerThis approach doesn't introduce any variable that can be used within the build
118*61c4878aSAndroid Build Coastguard Workersystem to e.g. conditionally select different source files for a library,
119*61c4878aSAndroid Build Coastguard Workerchoose a different library as a dependency, or remove some targets from the
120*61c4878aSAndroid Build Coastguard Workerbuild altogether. We're really just setting preprocessor defines here.
121*61c4878aSAndroid Build Coastguard Worker
122*61c4878aSAndroid Build Coastguard Worker
123*61c4878aSAndroid Build Coastguard WorkerLimited multirepo support
124*61c4878aSAndroid Build Coastguard Worker-------------------------
125*61c4878aSAndroid Build Coastguard WorkerThe ``.bazelrc`` files are not automatically inherited when another repo
126*61c4878aSAndroid Build Coastguard Workerdepends on yours. They can be `imported
127*61c4878aSAndroid Build Coastguard Worker<https://bazel.build/run/bazelrc#imports>`__, but it's an all-or-nothing
128*61c4878aSAndroid Build Coastguard Workeraffair.
129*61c4878aSAndroid Build Coastguard Worker
130*61c4878aSAndroid Build Coastguard Worker.. _docs-blog-02-platform-based-skylib-flags:
131*61c4878aSAndroid Build Coastguard Worker
132*61c4878aSAndroid Build Coastguard Worker------------------------------------------------------------
133*61c4878aSAndroid Build Coastguard WorkerMore power with no code changes: Platform-based Skylib flags
134*61c4878aSAndroid Build Coastguard Worker------------------------------------------------------------
135*61c4878aSAndroid Build Coastguard WorkerLet's address some shortcomings of the approach above by representing the build
136*61c4878aSAndroid Build Coastguard Workerfeatures as `Skylib flags
137*61c4878aSAndroid Build Coastguard Worker<https://github.com/bazelbuild/bazel-skylib/blob/main/docs/common_settings_doc.md>`__
138*61c4878aSAndroid Build Coastguard Workerand grouping them through `platform-based flags
139*61c4878aSAndroid Build Coastguard Worker<https://github.com/bazelbuild/proposals/blob/main/designs/2023-06-08-platform-based-flags.md>`__.
140*61c4878aSAndroid Build Coastguard Worker(Important note: this feature is `still under development
141*61c4878aSAndroid Build Coastguard Worker<https://github.com/bazelbuild/bazel/issues/19409>`__! See :ref:`the Appendix
142*61c4878aSAndroid Build Coastguard Worker<docs-blog-02-old-bazel>` for workarounds for older Bazel versions.)
143*61c4878aSAndroid Build Coastguard Worker
144*61c4878aSAndroid Build Coastguard WorkerThe platform sets a bunch of flags:
145*61c4878aSAndroid Build Coastguard Worker
146*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
147*61c4878aSAndroid Build Coastguard Worker
148*61c4878aSAndroid Build Coastguard Worker   # //platform/BUILD.bazel
149*61c4878aSAndroid Build Coastguard Worker
150*61c4878aSAndroid Build Coastguard Worker   # The platform definition
151*61c4878aSAndroid Build Coastguard Worker   platform(
152*61c4878aSAndroid Build Coastguard Worker     name = "mydevice_evt1",
153*61c4878aSAndroid Build Coastguard Worker     flags = [
154*61c4878aSAndroid Build Coastguard Worker       "--//build/feature:cpu_profile=true",
155*61c4878aSAndroid Build Coastguard Worker       "--//build/feature:heap_profile=true",
156*61c4878aSAndroid Build Coastguard Worker       "--//build/feature:hw_sha256=true",
157*61c4878aSAndroid Build Coastguard Worker     ],
158*61c4878aSAndroid Build Coastguard Worker   )
159*61c4878aSAndroid Build Coastguard Worker
160*61c4878aSAndroid Build Coastguard WorkerThe flags have corresponding code-generated C++ libraries:
161*61c4878aSAndroid Build Coastguard Worker
162*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
163*61c4878aSAndroid Build Coastguard Worker
164*61c4878aSAndroid Build Coastguard Worker   # //build/feature/BUILD.bazel
165*61c4878aSAndroid Build Coastguard Worker   load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
166*61c4878aSAndroid Build Coastguard Worker   # I'll show one possible implementation of feature_cc_library later.
167*61c4878aSAndroid Build Coastguard Worker   load("//:feature_cc_library.bzl", "feature_cc_library")
168*61c4878aSAndroid Build Coastguard Worker
169*61c4878aSAndroid Build Coastguard Worker   # This is a boolean flag, but there's support for int- and string-valued
170*61c4878aSAndroid Build Coastguard Worker   # flags, too.
171*61c4878aSAndroid Build Coastguard Worker   bool_flag(
172*61c4878aSAndroid Build Coastguard Worker       name = "cpu_profile",
173*61c4878aSAndroid Build Coastguard Worker       build_setting_default = False,
174*61c4878aSAndroid Build Coastguard Worker   )
175*61c4878aSAndroid Build Coastguard Worker
176*61c4878aSAndroid Build Coastguard Worker   # This is a custom rule that generates a cc_library target that exposes
177*61c4878aSAndroid Build Coastguard Worker   # a header "cpu_profile.h", the contents of which are either,
178*61c4878aSAndroid Build Coastguard Worker   #
179*61c4878aSAndroid Build Coastguard Worker   # BUILD_FEATURE_CPU_PROFILE=1
180*61c4878aSAndroid Build Coastguard Worker   #
181*61c4878aSAndroid Build Coastguard Worker   # or,
182*61c4878aSAndroid Build Coastguard Worker   #
183*61c4878aSAndroid Build Coastguard Worker   # BUILD_FEATURE_CPU_PROFILE=0
184*61c4878aSAndroid Build Coastguard Worker   #
185*61c4878aSAndroid Build Coastguard Worker   # depending on the value of the cpu_profile bool_flag. This "code
186*61c4878aSAndroid Build Coastguard Worker   # generation" is so simple that it can actually be done in pure Starlark;
187*61c4878aSAndroid Build Coastguard Worker   # see below.
188*61c4878aSAndroid Build Coastguard Worker   feature_cc_library(
189*61c4878aSAndroid Build Coastguard Worker       name = "cpu_profile_cc",
190*61c4878aSAndroid Build Coastguard Worker       flag = ":cpu_profile",
191*61c4878aSAndroid Build Coastguard Worker   )
192*61c4878aSAndroid Build Coastguard Worker
193*61c4878aSAndroid Build Coastguard Worker   # Analogous library that exposes the constant in Python.
194*61c4878aSAndroid Build Coastguard Worker   feature_py_library(
195*61c4878aSAndroid Build Coastguard Worker       name = "cpu_profile_py",
196*61c4878aSAndroid Build Coastguard Worker       flag = ":cpu_profile",
197*61c4878aSAndroid Build Coastguard Worker   )
198*61c4878aSAndroid Build Coastguard Worker
199*61c4878aSAndroid Build Coastguard Worker   # And in Rust, why not?
200*61c4878aSAndroid Build Coastguard Worker   feature_rs_library(
201*61c4878aSAndroid Build Coastguard Worker       name = "cpu_profile_rs",
202*61c4878aSAndroid Build Coastguard Worker       flag = ":cpu_profile",
203*61c4878aSAndroid Build Coastguard Worker   )
204*61c4878aSAndroid Build Coastguard Worker
205*61c4878aSAndroid Build Coastguard Worker   bool_flag(
206*61c4878aSAndroid Build Coastguard Worker       name = "heap_profile",
207*61c4878aSAndroid Build Coastguard Worker       build_setting_default = False,
208*61c4878aSAndroid Build Coastguard Worker   )
209*61c4878aSAndroid Build Coastguard Worker
210*61c4878aSAndroid Build Coastguard Worker   feature_cc_library(
211*61c4878aSAndroid Build Coastguard Worker       name = "heap_profile_cc",
212*61c4878aSAndroid Build Coastguard Worker       flag = ":heap_profile",
213*61c4878aSAndroid Build Coastguard Worker   )
214*61c4878aSAndroid Build Coastguard Worker
215*61c4878aSAndroid Build Coastguard Worker   bool_flag(
216*61c4878aSAndroid Build Coastguard Worker       name = "hw_sha256",
217*61c4878aSAndroid Build Coastguard Worker       build_setting_default = False,
218*61c4878aSAndroid Build Coastguard Worker   )
219*61c4878aSAndroid Build Coastguard Worker
220*61c4878aSAndroid Build Coastguard Worker   feature_cc_library(
221*61c4878aSAndroid Build Coastguard Worker       name = "hw_sha256_cc",
222*61c4878aSAndroid Build Coastguard Worker       flag = ":hw_sha256",
223*61c4878aSAndroid Build Coastguard Worker   )
224*61c4878aSAndroid Build Coastguard Worker
225*61c4878aSAndroid Build Coastguard WorkerC++ libraries that want to access the variable needs to depend on the
226*61c4878aSAndroid Build Coastguard Worker``cpu_profile_cc`` (or ``heap_profile_cc``, ``hw_sha256_cc``) library.
227*61c4878aSAndroid Build Coastguard Worker
228*61c4878aSAndroid Build Coastguard WorkerHere's one possible implementation of ``feature_cc_library``:
229*61c4878aSAndroid Build Coastguard Worker
230*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
231*61c4878aSAndroid Build Coastguard Worker
232*61c4878aSAndroid Build Coastguard Worker   # feature_cc_library.bzl
233*61c4878aSAndroid Build Coastguard Worker   load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
234*61c4878aSAndroid Build Coastguard Worker
235*61c4878aSAndroid Build Coastguard Worker   def feature_cc_library(name, build_setting):
236*61c4878aSAndroid Build Coastguard Worker       hdrs_name = name + ".hdr"
237*61c4878aSAndroid Build Coastguard Worker
238*61c4878aSAndroid Build Coastguard Worker       flag_header_file(
239*61c4878aSAndroid Build Coastguard Worker           name = hdrs_name,
240*61c4878aSAndroid Build Coastguard Worker           build_setting = build_setting,
241*61c4878aSAndroid Build Coastguard Worker       )
242*61c4878aSAndroid Build Coastguard Worker
243*61c4878aSAndroid Build Coastguard Worker       native.cc_library(
244*61c4878aSAndroid Build Coastguard Worker           name = name,
245*61c4878aSAndroid Build Coastguard Worker           hdrs = [":" + hdrs_name],
246*61c4878aSAndroid Build Coastguard Worker       )
247*61c4878aSAndroid Build Coastguard Worker
248*61c4878aSAndroid Build Coastguard Worker   def _impl(ctx):
249*61c4878aSAndroid Build Coastguard Worker       out = ctx.actions.declare_file(ctx.attr.build_setting.label.name + ".h")
250*61c4878aSAndroid Build Coastguard Worker
251*61c4878aSAndroid Build Coastguard Worker       # Convert boolean flags to canonical integer values.
252*61c4878aSAndroid Build Coastguard Worker       value = ctx.attr.build_setting[BuildSettingInfo].value
253*61c4878aSAndroid Build Coastguard Worker       if type(value) == type(True):
254*61c4878aSAndroid Build Coastguard Worker           if value:
255*61c4878aSAndroid Build Coastguard Worker               value = 1
256*61c4878aSAndroid Build Coastguard Worker           else:
257*61c4878aSAndroid Build Coastguard Worker               value = 0
258*61c4878aSAndroid Build Coastguard Worker
259*61c4878aSAndroid Build Coastguard Worker       ctx.actions.write(
260*61c4878aSAndroid Build Coastguard Worker           output = out,
261*61c4878aSAndroid Build Coastguard Worker           content = r"""
262*61c4878aSAndroid Build Coastguard Worker   #pragma once
263*61c4878aSAndroid Build Coastguard Worker   #define {}={}
264*61c4878aSAndroid Build Coastguard Worker   """.format(ctx.attr.build_setting.label.name.upper(), value),
265*61c4878aSAndroid Build Coastguard Worker       )
266*61c4878aSAndroid Build Coastguard Worker       return [DefaultInfo(files = depset([out]))]
267*61c4878aSAndroid Build Coastguard Worker
268*61c4878aSAndroid Build Coastguard Worker   flag_header_file = rule(
269*61c4878aSAndroid Build Coastguard Worker       implementation = _impl,
270*61c4878aSAndroid Build Coastguard Worker       attrs = {
271*61c4878aSAndroid Build Coastguard Worker           "build_setting": attr.label(
272*61c4878aSAndroid Build Coastguard Worker               doc = "Build setting (flag) to construct the header from.",
273*61c4878aSAndroid Build Coastguard Worker               mandatory = True,
274*61c4878aSAndroid Build Coastguard Worker           ),
275*61c4878aSAndroid Build Coastguard Worker       },
276*61c4878aSAndroid Build Coastguard Worker   )
277*61c4878aSAndroid Build Coastguard Worker
278*61c4878aSAndroid Build Coastguard WorkerAdvantages
279*61c4878aSAndroid Build Coastguard Worker==========
280*61c4878aSAndroid Build Coastguard Worker
281*61c4878aSAndroid Build Coastguard WorkerComposability of platforms
282*61c4878aSAndroid Build Coastguard Worker--------------------------
283*61c4878aSAndroid Build Coastguard WorkerA neat feature of the simple config-based approach was that configs could be
284*61c4878aSAndroid Build Coastguard Workercomposed through recursive expansion. Fortunately, platforms can be composed,
285*61c4878aSAndroid Build Coastguard Workertoo! There are two mechanisms for doing so:
286*61c4878aSAndroid Build Coastguard Worker
287*61c4878aSAndroid Build Coastguard Worker#. Use platforms' `support for inheritance
288*61c4878aSAndroid Build Coastguard Worker   <https://bazel.build/reference/be/platforms-and-toolchains#platform_inheritance>`__.
289*61c4878aSAndroid Build Coastguard Worker   This allows "subplatforms" to override entries from "superplatforms". But,
290*61c4878aSAndroid Build Coastguard Worker   only single inheritance is supported (each platform has at most one parent).
291*61c4878aSAndroid Build Coastguard Worker
292*61c4878aSAndroid Build Coastguard Worker#. The other approach is to compose lists of flags directly, through concatenation:
293*61c4878aSAndroid Build Coastguard Worker
294*61c4878aSAndroid Build Coastguard Worker   .. code-block:: python
295*61c4878aSAndroid Build Coastguard Worker
296*61c4878aSAndroid Build Coastguard Worker      FEATURES_CORTEX_M7 = [
297*61c4878aSAndroid Build Coastguard Worker        "--//build/feature:some_feature",
298*61c4878aSAndroid Build Coastguard Worker      ]
299*61c4878aSAndroid Build Coastguard Worker
300*61c4878aSAndroid Build Coastguard Worker      FEATURES_MYDEVICE_EVT1 = FEATURES_CORTEX_M7 + [
301*61c4878aSAndroid Build Coastguard Worker        "--//build/feature:some_other_feature",
302*61c4878aSAndroid Build Coastguard Worker      ]
303*61c4878aSAndroid Build Coastguard Worker
304*61c4878aSAndroid Build Coastguard Worker      platform(
305*61c4878aSAndroid Build Coastguard Worker        name = "mydevice_evt1",
306*61c4878aSAndroid Build Coastguard Worker        flags = FEATURES_MYDEVICE_EVT1,
307*61c4878aSAndroid Build Coastguard Worker      )
308*61c4878aSAndroid Build Coastguard Worker
309*61c4878aSAndroid Build Coastguard Worker   Concatenation doesn't allow overriding entries, but frees you from the
310*61c4878aSAndroid Build Coastguard Worker   single-parent limitation of inheritance.
311*61c4878aSAndroid Build Coastguard Worker
312*61c4878aSAndroid Build Coastguard Worker   .. tip::
313*61c4878aSAndroid Build Coastguard Worker
314*61c4878aSAndroid Build Coastguard Worker      This approach can also be used to define custom host platforms:
315*61c4878aSAndroid Build Coastguard Worker      ``HOST_CONSTRAINTS`` in ``@local_config_platform//:constraints.bzl``
316*61c4878aSAndroid Build Coastguard Worker      contains the autodetected ``@platform//os`` and ``@platforms//cpu``
317*61c4878aSAndroid Build Coastguard Worker      constraints set by Bazel's default host platform.
318*61c4878aSAndroid Build Coastguard Worker
319*61c4878aSAndroid Build Coastguard WorkerMulti-platform build support
320*61c4878aSAndroid Build Coastguard Worker----------------------------
321*61c4878aSAndroid Build Coastguard WorkerHow do you actually associate the platform with a binary you want to build? One
322*61c4878aSAndroid Build Coastguard Workerapproach is to just specify the platform on the command-line when building a
323*61c4878aSAndroid Build Coastguard Worker``cc_binary``:
324*61c4878aSAndroid Build Coastguard Worker
325*61c4878aSAndroid Build Coastguard Worker.. code-block:: sh
326*61c4878aSAndroid Build Coastguard Worker
327*61c4878aSAndroid Build Coastguard Worker   bazel build --platforms=//platform:mydevice_evt1 //src:main
328*61c4878aSAndroid Build Coastguard Worker
329*61c4878aSAndroid Build Coastguard WorkerBut another approach is to leverage multi-platform build, through
330*61c4878aSAndroid Build Coastguard Worker`platform_data <https://github.com/bazelbuild/rules_platform/blob/main/platform_data/defs.bzl>`__:
331*61c4878aSAndroid Build Coastguard Worker
332*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
333*61c4878aSAndroid Build Coastguard Worker
334*61c4878aSAndroid Build Coastguard Worker   # //src/BUILD.bazel
335*61c4878aSAndroid Build Coastguard Worker   load("@rules_platform//platform_data:defs.bzl", "platform_data")
336*61c4878aSAndroid Build Coastguard Worker
337*61c4878aSAndroid Build Coastguard Worker   cc_binary(name = "main")
338*61c4878aSAndroid Build Coastguard Worker
339*61c4878aSAndroid Build Coastguard Worker   platform_data(
340*61c4878aSAndroid Build Coastguard Worker       name = "main_mydevice_evt1",
341*61c4878aSAndroid Build Coastguard Worker       target = ":main",
342*61c4878aSAndroid Build Coastguard Worker       platform = "//platform:mydevice_evt1",
343*61c4878aSAndroid Build Coastguard Worker   )
344*61c4878aSAndroid Build Coastguard Worker
345*61c4878aSAndroid Build Coastguard WorkerThen you can keep your command-line simple:
346*61c4878aSAndroid Build Coastguard Worker
347*61c4878aSAndroid Build Coastguard Worker.. code-block:: sh
348*61c4878aSAndroid Build Coastguard Worker
349*61c4878aSAndroid Build Coastguard Worker   bazel build //src:main_mydevice_evt1
350*61c4878aSAndroid Build Coastguard Worker
351*61c4878aSAndroid Build Coastguard Worker
352*61c4878aSAndroid Build Coastguard Worker
353*61c4878aSAndroid Build Coastguard WorkerFlags correspond to build variables
354*61c4878aSAndroid Build Coastguard Worker-----------------------------------
355*61c4878aSAndroid Build Coastguard WorkerYou can make various features of the build conditional on the value of the
356*61c4878aSAndroid Build Coastguard Workerflag. For example, you can select different dependencies:
357*61c4878aSAndroid Build Coastguard Worker
358*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
359*61c4878aSAndroid Build Coastguard Worker
360*61c4878aSAndroid Build Coastguard Worker   # //build/feature/BUILD.bazel
361*61c4878aSAndroid Build Coastguard Worker   config_setting(
362*61c4878aSAndroid Build Coastguard Worker     name = "hw_sha256=true",
363*61c4878aSAndroid Build Coastguard Worker     flag_values = {
364*61c4878aSAndroid Build Coastguard Worker       ":hw_sha256": "true",
365*61c4878aSAndroid Build Coastguard Worker     },
366*61c4878aSAndroid Build Coastguard Worker   )
367*61c4878aSAndroid Build Coastguard Worker
368*61c4878aSAndroid Build Coastguard Worker   # //src/BUILD.bazel
369*61c4878aSAndroid Build Coastguard Worker   cc_library(
370*61c4878aSAndroid Build Coastguard Worker     name = "my_library",
371*61c4878aSAndroid Build Coastguard Worker     deps = [
372*61c4878aSAndroid Build Coastguard Worker       "//some/unconditional:dep",
373*61c4878aSAndroid Build Coastguard Worker     ] + select({
374*61c4878aSAndroid Build Coastguard Worker       "//build/feature:hw_sha256=true": ["//extra/dep/for/hw_sha256:only"],
375*61c4878aSAndroid Build Coastguard Worker       "//conditions:default": [],
376*61c4878aSAndroid Build Coastguard Worker   })
377*61c4878aSAndroid Build Coastguard Worker
378*61c4878aSAndroid Build Coastguard WorkerAny Bazel rule attribute described as `"configurable"
379*61c4878aSAndroid Build Coastguard Worker<https://bazel.build/docs/configurable-attributes>`__ can take a value that
380*61c4878aSAndroid Build Coastguard Workerdepends on the flag in this way. Library header lists and source lists are
381*61c4878aSAndroid Build Coastguard Workercommon examples, but the vast majority of attributes in Bazel are configurable.
382*61c4878aSAndroid Build Coastguard Worker
383*61c4878aSAndroid Build Coastguard WorkerDownsides
384*61c4878aSAndroid Build Coastguard Worker=========
385*61c4878aSAndroid Build Coastguard Worker
386*61c4878aSAndroid Build Coastguard WorkerTypos remain dangerous
387*61c4878aSAndroid Build Coastguard Worker----------------------
388*61c4878aSAndroid Build Coastguard WorkerIf you used :ref:`"Chromium-style" build flags <docs-blog-02-chromium-pattern>`
389*61c4878aSAndroid Build Coastguard Workeryou *would* be immune to dangerous typos when using this Bazel pattern. But
390*61c4878aSAndroid Build Coastguard Workeruntil then, you still have this problem, and actually it got worse!
391*61c4878aSAndroid Build Coastguard Worker
392*61c4878aSAndroid Build Coastguard WorkerIf you forget to ``#include "build/features/hw_sha256.h"`` in the C++ file that
393*61c4878aSAndroid Build Coastguard Workerreferences the preprocessor variable, the build system or compiler will still
394*61c4878aSAndroid Build Coastguard Workernot yell at you. Instead, the ``BUILD_FEATURE_HA_SHA256`` variable will take
395*61c4878aSAndroid Build Coastguard Workerthe default value of 0.
396*61c4878aSAndroid Build Coastguard Worker
397*61c4878aSAndroid Build Coastguard WorkerThis is similar to the :ref:`typo problem with the config approach
398*61c4878aSAndroid Build Coastguard Worker<docs-blog-02-config-dangeous-typos>`, but worse, because it's easier to miss
399*61c4878aSAndroid Build Coastguard Workeran ``#include`` than to misspell a name, and you'll need to add these
400*61c4878aSAndroid Build Coastguard Worker``#include`` statements in many places.
401*61c4878aSAndroid Build Coastguard Worker
402*61c4878aSAndroid Build Coastguard WorkerOne way to mitigate this problem is to make the individual
403*61c4878aSAndroid Build Coastguard Worker``feature_cc_library`` targets private, and gather them into one big library
404*61c4878aSAndroid Build Coastguard Workerthat all targets will depend on:
405*61c4878aSAndroid Build Coastguard Worker
406*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
407*61c4878aSAndroid Build Coastguard Worker
408*61c4878aSAndroid Build Coastguard Worker   feature_cc_library(
409*61c4878aSAndroid Build Coastguard Worker       name = "cpu_profile_cc",
410*61c4878aSAndroid Build Coastguard Worker       flag = ":cpu_profile",
411*61c4878aSAndroid Build Coastguard Worker       visibility = ["//visibility:private"],
412*61c4878aSAndroid Build Coastguard Worker   )
413*61c4878aSAndroid Build Coastguard Worker
414*61c4878aSAndroid Build Coastguard Worker   feature_cc_library(
415*61c4878aSAndroid Build Coastguard Worker       name = "heap_profile_cc",
416*61c4878aSAndroid Build Coastguard Worker       flag = ":heap_profile",
417*61c4878aSAndroid Build Coastguard Worker       visibility = ["//visibility:private"],
418*61c4878aSAndroid Build Coastguard Worker   )
419*61c4878aSAndroid Build Coastguard Worker
420*61c4878aSAndroid Build Coastguard Worker   feature_cc_library(
421*61c4878aSAndroid Build Coastguard Worker       name = "hw_sha256_cc",
422*61c4878aSAndroid Build Coastguard Worker       flag = ":hw_sha256",
423*61c4878aSAndroid Build Coastguard Worker       visibility = ["//visibility:private"],
424*61c4878aSAndroid Build Coastguard Worker   )
425*61c4878aSAndroid Build Coastguard Worker
426*61c4878aSAndroid Build Coastguard Worker   # Code-generated cc_library that #includes all the individual
427*61c4878aSAndroid Build Coastguard Worker   # feature_cc_library headers.
428*61c4878aSAndroid Build Coastguard Worker   all_features_cc_library(
429*61c4878aSAndroid Build Coastguard Worker       name = "all_features",
430*61c4878aSAndroid Build Coastguard Worker       deps = [
431*61c4878aSAndroid Build Coastguard Worker           ":cpu_profile_cc",
432*61c4878aSAndroid Build Coastguard Worker           ":heap_profile_cc",
433*61c4878aSAndroid Build Coastguard Worker           ":hw_sha256_cc",
434*61c4878aSAndroid Build Coastguard Worker           # ... and many more.
435*61c4878aSAndroid Build Coastguard Worker       ],
436*61c4878aSAndroid Build Coastguard Worker       visibility = ["//visibility:public"],
437*61c4878aSAndroid Build Coastguard Worker   )
438*61c4878aSAndroid Build Coastguard Worker
439*61c4878aSAndroid Build Coastguard WorkerHowever, a more satisfactory solution is to adopt :ref:`Chromium-style build
440*61c4878aSAndroid Build Coastguard Workerflags <docs-blog-02-chromium-pattern>`, which we discuss next.
441*61c4878aSAndroid Build Coastguard Worker
442*61c4878aSAndroid Build Coastguard WorkerBuild settings have mandatory default values
443*61c4878aSAndroid Build Coastguard Worker--------------------------------------------
444*61c4878aSAndroid Build Coastguard WorkerThe Skylib ``bool_flag`` that represents the build flag within Bazel has a
445*61c4878aSAndroid Build Coastguard Worker``build_setting_default`` attribute. This attribute is mandatory.
446*61c4878aSAndroid Build Coastguard Worker
447*61c4878aSAndroid Build Coastguard WorkerThis may be a disappointment if you were hoping to provide no default, and have
448*61c4878aSAndroid Build Coastguard WorkerBazel return errors if no value is explicitly set for a flag (either via a
449*61c4878aSAndroid Build Coastguard Workerplatform, through ``.bazelrc``, or on the command line). The Skylib build flags
450*61c4878aSAndroid Build Coastguard Workerdon't support this.
451*61c4878aSAndroid Build Coastguard Worker
452*61c4878aSAndroid Build Coastguard WorkerThe danger here is that the default value may be unsafe, and you forget to
453*61c4878aSAndroid Build Coastguard Workeroverride it when adding a new platform (or for some existing platform, when
454*61c4878aSAndroid Build Coastguard Workeradding a new flag).
455*61c4878aSAndroid Build Coastguard Worker
456*61c4878aSAndroid Build Coastguard WorkerThere is an alternative pattern that allows you to define default-less build
457*61c4878aSAndroid Build Coastguard Workerflags: instead of representing build flags as Skylib flags, you can represent
458*61c4878aSAndroid Build Coastguard Workerthem as ``constraint_setting`` objects. I won't spell this pattern out in
459*61c4878aSAndroid Build Coastguard Workerthis blog post, but it comes with its own drawbacks:
460*61c4878aSAndroid Build Coastguard Worker
461*61c4878aSAndroid Build Coastguard Worker*  The custom code-generation rules are more complex, and need to parse the
462*61c4878aSAndroid Build Coastguard Worker   ``constraint_value`` names to infer the build flag values.
463*61c4878aSAndroid Build Coastguard Worker*  All supported flag values must be explicitly enumerated in the ``BUILD``
464*61c4878aSAndroid Build Coastguard Worker   files, and the code-generation rules need explicit dependencies on them.
465*61c4878aSAndroid Build Coastguard Worker   This leads to substantially more verbose ``BUILD`` files.
466*61c4878aSAndroid Build Coastguard Worker
467*61c4878aSAndroid Build Coastguard WorkerOn the whole, I'd recommend sticking with the Skylib flags!
468*61c4878aSAndroid Build Coastguard Worker
469*61c4878aSAndroid Build Coastguard Worker
470*61c4878aSAndroid Build Coastguard Worker.. _docs-blog-02-chromium-pattern:
471*61c4878aSAndroid Build Coastguard Worker
472*61c4878aSAndroid Build Coastguard Worker------------------------------------------------------------
473*61c4878aSAndroid Build Coastguard WorkerError-preventing approach: Chromium-style build flag pattern
474*61c4878aSAndroid Build Coastguard Worker------------------------------------------------------------
475*61c4878aSAndroid Build Coastguard WorkerThis pattern builds on :ref:`docs-blog-02-platform-based-skylib-flags` by
476*61c4878aSAndroid Build Coastguard Workeradding a macro helper for retrieving flag values that guards against typos. The
477*61c4878aSAndroid Build Coastguard Worker``BUILD.bazel`` files look exactly the same as in the :ref:`previous section
478*61c4878aSAndroid Build Coastguard Worker<docs-blog-02-platform-based-skylib-flags>`, but:
479*61c4878aSAndroid Build Coastguard Worker
480*61c4878aSAndroid Build Coastguard Worker#. Users of flags access them in C++ files via ``BUILDFLAG(SOME_NAME)``.
481*61c4878aSAndroid Build Coastguard Worker#. The code generated by ``feature_cc_library`` is a little more elaborate than
482*61c4878aSAndroid Build Coastguard Worker   a plain ``SOME_NAME=1`` or ``SOME_NAME=0``, and it includes a dependency on
483*61c4878aSAndroid Build Coastguard Worker   the `Chromium build flag header
484*61c4878aSAndroid Build Coastguard Worker   <https://chromium.googlesource.com/chromium/src/build/+/refs/heads/main/buildflag.h>`__.
485*61c4878aSAndroid Build Coastguard Worker
486*61c4878aSAndroid Build Coastguard WorkerHere's the ``feature_cc_library`` implementation:
487*61c4878aSAndroid Build Coastguard Worker
488*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
489*61c4878aSAndroid Build Coastguard Worker
490*61c4878aSAndroid Build Coastguard Worker   load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
491*61c4878aSAndroid Build Coastguard Worker
492*61c4878aSAndroid Build Coastguard Worker   def feature_cc_library(name, build_setting):
493*61c4878aSAndroid Build Coastguard Worker       """Generates a cc_library from a common build setting.
494*61c4878aSAndroid Build Coastguard Worker
495*61c4878aSAndroid Build Coastguard Worker       The generated cc_library exposes a header [build_setting.name].h that
496*61c4878aSAndroid Build Coastguard Worker       defines a corresponding build flag.
497*61c4878aSAndroid Build Coastguard Worker
498*61c4878aSAndroid Build Coastguard Worker       Example:
499*61c4878aSAndroid Build Coastguard Worker
500*61c4878aSAndroid Build Coastguard Worker           feature_cc_library(
501*61c4878aSAndroid Build Coastguard Worker               name = "evt1_cc",
502*61c4878aSAndroid Build Coastguard Worker               build_setting = ":evt1",
503*61c4878aSAndroid Build Coastguard Worker           )
504*61c4878aSAndroid Build Coastguard Worker
505*61c4878aSAndroid Build Coastguard Worker       *  This target is a cc_library that exposes a header you can include via
506*61c4878aSAndroid Build Coastguard Worker          #include "build/flags/evt1.h".
507*61c4878aSAndroid Build Coastguard Worker       *  That header defines a build flag you can access in your code through
508*61c4878aSAndroid Build Coastguard Worker          BUILDFLAGS(EVT1).
509*61c4878aSAndroid Build Coastguard Worker       *  If you wish to use the build flag from a cc_library, add the target
510*61c4878aSAndroid Build Coastguard Worker          evt1_cc to your cc_library's deps.
511*61c4878aSAndroid Build Coastguard Worker
512*61c4878aSAndroid Build Coastguard Worker       Args:
513*61c4878aSAndroid Build Coastguard Worker         name: Name for the generated cc_library.
514*61c4878aSAndroid Build Coastguard Worker         build_setting: One of the Skylib "common settings": bool_flag, int_flag,
515*61c4878aSAndroid Build Coastguard Worker           string_flag, etc. See
516*61c4878aSAndroid Build Coastguard Worker           https://github.com/bazelbuild/bazel-skylib/blob/main/docs/common_settings_doc.md
517*61c4878aSAndroid Build Coastguard Worker       """
518*61c4878aSAndroid Build Coastguard Worker       hdrs_name = name + ".hdr"
519*61c4878aSAndroid Build Coastguard Worker
520*61c4878aSAndroid Build Coastguard Worker       flag_header_file(
521*61c4878aSAndroid Build Coastguard Worker           name = hdrs_name,
522*61c4878aSAndroid Build Coastguard Worker           build_setting = build_setting,
523*61c4878aSAndroid Build Coastguard Worker       )
524*61c4878aSAndroid Build Coastguard Worker
525*61c4878aSAndroid Build Coastguard Worker       native.cc_library(
526*61c4878aSAndroid Build Coastguard Worker           name = name,
527*61c4878aSAndroid Build Coastguard Worker           hdrs = [":" + hdrs_name],
528*61c4878aSAndroid Build Coastguard Worker           # //:buildflag is a cc_library containing the
529*61c4878aSAndroid Build Coastguard Worker           # Chromium build flag header.
530*61c4878aSAndroid Build Coastguard Worker           deps = ["//:buildflag"],
531*61c4878aSAndroid Build Coastguard Worker       )
532*61c4878aSAndroid Build Coastguard Worker
533*61c4878aSAndroid Build Coastguard Worker   def _impl(ctx):
534*61c4878aSAndroid Build Coastguard Worker       out = ctx.actions.declare_file(ctx.attr.build_setting.label.name + ".h")
535*61c4878aSAndroid Build Coastguard Worker
536*61c4878aSAndroid Build Coastguard Worker       # Convert boolean flags to canonical integer values.
537*61c4878aSAndroid Build Coastguard Worker       value = ctx.attr.build_setting[BuildSettingInfo].value
538*61c4878aSAndroid Build Coastguard Worker       if type(value) == type(True):
539*61c4878aSAndroid Build Coastguard Worker           if value:
540*61c4878aSAndroid Build Coastguard Worker               value = 1
541*61c4878aSAndroid Build Coastguard Worker           else:
542*61c4878aSAndroid Build Coastguard Worker               value = 0
543*61c4878aSAndroid Build Coastguard Worker
544*61c4878aSAndroid Build Coastguard Worker       ctx.actions.write(
545*61c4878aSAndroid Build Coastguard Worker           output = out,
546*61c4878aSAndroid Build Coastguard Worker           content = r"""
547*61c4878aSAndroid Build Coastguard Worker   #pragma once
548*61c4878aSAndroid Build Coastguard Worker
549*61c4878aSAndroid Build Coastguard Worker   #include "buildflag.h"
550*61c4878aSAndroid Build Coastguard Worker
551*61c4878aSAndroid Build Coastguard Worker   #define BUILDFLAG_INTERNAL_{}() ({})
552*61c4878aSAndroid Build Coastguard Worker   """.format(ctx.attr.build_setting.label.name.upper(), value),
553*61c4878aSAndroid Build Coastguard Worker       )
554*61c4878aSAndroid Build Coastguard Worker       return [DefaultInfo(files = depset([out]))]
555*61c4878aSAndroid Build Coastguard Worker
556*61c4878aSAndroid Build Coastguard Worker   flag_header_file = rule(
557*61c4878aSAndroid Build Coastguard Worker       implementation = _impl,
558*61c4878aSAndroid Build Coastguard Worker       attrs = {
559*61c4878aSAndroid Build Coastguard Worker           "build_setting": attr.label(
560*61c4878aSAndroid Build Coastguard Worker               doc = "Build setting (flag) to construct the header from.",
561*61c4878aSAndroid Build Coastguard Worker               mandatory = True,
562*61c4878aSAndroid Build Coastguard Worker           ),
563*61c4878aSAndroid Build Coastguard Worker       },
564*61c4878aSAndroid Build Coastguard Worker   )
565*61c4878aSAndroid Build Coastguard Worker
566*61c4878aSAndroid Build Coastguard Worker-----------
567*61c4878aSAndroid Build Coastguard WorkerBottom line
568*61c4878aSAndroid Build Coastguard Worker-----------
569*61c4878aSAndroid Build Coastguard WorkerIf you have the freedom to refactor your code to use the Chromium pattern,
570*61c4878aSAndroid Build Coastguard WorkerBazel provides safe and convenient idioms for expressing configuration through
571*61c4878aSAndroid Build Coastguard Workerbuild flags. Give it a try!
572*61c4878aSAndroid Build Coastguard Worker
573*61c4878aSAndroid Build Coastguard WorkerOtherwise, you can still use platform-based Skylib flags, but beware typos and
574*61c4878aSAndroid Build Coastguard Workermissing ``#include`` statements!
575*61c4878aSAndroid Build Coastguard Worker
576*61c4878aSAndroid Build Coastguard Worker--------
577*61c4878aSAndroid Build Coastguard WorkerAppendix
578*61c4878aSAndroid Build Coastguard Worker--------
579*61c4878aSAndroid Build Coastguard WorkerA couple "deep in the weeds" questions came up while this blog post was being
580*61c4878aSAndroid Build Coastguard Workerreviewed. I thought they were interesting enough to discuss here, for the
581*61c4878aSAndroid Build Coastguard Workerinterested reader!
582*61c4878aSAndroid Build Coastguard Worker
583*61c4878aSAndroid Build Coastguard WorkerWhy isn't the reference code a library?
584*61c4878aSAndroid Build Coastguard Worker=======================================
585*61c4878aSAndroid Build Coastguard WorkerIf you made it this far you might be wondering, why is the code listing for
586*61c4878aSAndroid Build Coastguard Worker``feature_cc_library`` even here? Why isn't it just part of Pigweed, and used
587*61c4878aSAndroid Build Coastguard Workerin our own codebase?
588*61c4878aSAndroid Build Coastguard Worker
589*61c4878aSAndroid Build Coastguard WorkerThe short answer is that Pigweed is middleware supporting multiple build
590*61c4878aSAndroid Build Coastguard Workersystems, so we don't want to rely on the build system to generate configuration
591*61c4878aSAndroid Build Coastguard Workerheaders.
592*61c4878aSAndroid Build Coastguard Worker
593*61c4878aSAndroid Build Coastguard WorkerBut the longer answer has to do with how this blog post came about. Some time
594*61c4878aSAndroid Build Coastguard Workerago, I was migrating team A's build from CMake to Bazel. They used Chromium
595*61c4878aSAndroid Build Coastguard Workerbuild flags, but in CMake, so to do a build migration they needed Bazel support
596*61c4878aSAndroid Build Coastguard Workerfor this pattern. So I put an implementation together. I wrote a design
597*61c4878aSAndroid Build Coastguard Workerdocument, but it had confidential details and was not widely shared.
598*61c4878aSAndroid Build Coastguard Worker
599*61c4878aSAndroid Build Coastguard WorkerThen team B comes along and says, "we tried migrating to Bazel but couldn't
600*61c4878aSAndroid Build Coastguard Workerfigure out how to support build flags" (not the Chromium flags, but the "naive"
601*61c4878aSAndroid Build Coastguard Workerkind; i.e. their problem statement was exactly the one the blog opens with). So
602*61c4878aSAndroid Build Coastguard WorkerI wrote a less-confidential but still internal doc for them saying "here's how
603*61c4878aSAndroid Build Coastguard Workeryou could do it"; basically, :ref:`docs-blog-02-platform-based-skylib-flags`.
604*61c4878aSAndroid Build Coastguard Worker
605*61c4878aSAndroid Build Coastguard WorkerThen Pigweed's TL comes along and says "Ted, don't you feel like spending a day
606*61c4878aSAndroid Build Coastguard Workerfighting with RST [the markup we use for pigweed.dev]?" Sorry, actually they
607*61c4878aSAndroid Build Coastguard Workersaid something more like, "Why is this doc internal, can't we share this more
608*61c4878aSAndroid Build Coastguard Workerwidely"? Well we can. So that's the doc you're reading now!
609*61c4878aSAndroid Build Coastguard Worker
610*61c4878aSAndroid Build Coastguard WorkerBut arguably the story shouldn't end here: Pigweed should probably provide a
611*61c4878aSAndroid Build Coastguard Workerready-made implementation of Chromium build flags for downstream projects. See
612*61c4878aSAndroid Build Coastguard Worker:bug:`342454993` to check out how that's going!
613*61c4878aSAndroid Build Coastguard Worker
614*61c4878aSAndroid Build Coastguard WorkerDo you need to generate actual files?
615*61c4878aSAndroid Build Coastguard Worker=====================================
616*61c4878aSAndroid Build Coastguard WorkerIf you are a Bazel expert, you may ask: do we need to have Bazel write out the
617*61c4878aSAndroid Build Coastguard Workeractual header files, and wrap those in a ``cc_library``? If we're already
618*61c4878aSAndroid Build Coastguard Workerwriting a custom rule for ``feature_cc_library``, can we just set ``-D``
619*61c4878aSAndroid Build Coastguard Workerdefines by providing `CcInfo
620*61c4878aSAndroid Build Coastguard Worker<https://bazel.build/rules/lib/providers/CcInfo>`__? That is, do something like
621*61c4878aSAndroid Build Coastguard Workerthis:
622*61c4878aSAndroid Build Coastguard Worker
623*61c4878aSAndroid Build Coastguard Worker.. code-block:: python
624*61c4878aSAndroid Build Coastguard Worker
625*61c4878aSAndroid Build Coastguard Worker   define = "{}={}"..format(
626*61c4878aSAndroid Build Coastguard Worker     ctx.attr.build_setting.label.name.upper(),
627*61c4878aSAndroid Build Coastguard Worker     value)
628*61c4878aSAndroid Build Coastguard Worker   return [CcInfo(
629*61c4878aSAndroid Build Coastguard Worker     compilation_context=cc_common.create_compilation_context(
630*61c4878aSAndroid Build Coastguard Worker       defines=depset([define])))]
631*61c4878aSAndroid Build Coastguard Worker
632*61c4878aSAndroid Build Coastguard WorkerThe honest answer is that this didn't occur to me! But one reason to prefer
633*61c4878aSAndroid Build Coastguard Workerwriting out the header files is that this approach generalizes in an obvious
634*61c4878aSAndroid Build Coastguard Workerway to other programming languages: if you want to generate Python or Golang
635*61c4878aSAndroid Build Coastguard Workerconstants, you can use the same pattern, just change the contents of the file.
636*61c4878aSAndroid Build Coastguard WorkerGeneralizing the ``CcInfo`` approach is trickier!
637*61c4878aSAndroid Build Coastguard Worker
638*61c4878aSAndroid Build Coastguard Worker.. _docs-blog-02-old-bazel:
639*61c4878aSAndroid Build Coastguard Worker
640*61c4878aSAndroid Build Coastguard WorkerWhat can I do on older Bazel versions?
641*61c4878aSAndroid Build Coastguard Worker======================================
642*61c4878aSAndroid Build Coastguard WorkerThis blog focused on describing approaches that rely on `platform-based
643*61c4878aSAndroid Build Coastguard Workerflags
644*61c4878aSAndroid Build Coastguard Worker<https://github.com/bazelbuild/proposals/blob/main/designs/2023-06-08-platform-based-flags.md>`__.
645*61c4878aSAndroid Build Coastguard WorkerBut this feature is very new: in fact, as of this writing, it is `still under
646*61c4878aSAndroid Build Coastguard Workerdevelopment <https://github.com/bazelbuild/bazel/issues/19409>`__, so it's not
647*61c4878aSAndroid Build Coastguard Workeravailable in *any* Bazel version! So what can you do?
648*61c4878aSAndroid Build Coastguard Worker
649*61c4878aSAndroid Build Coastguard WorkerOne approach is to define custom wrapper rules for your ``cc_binary`` targets
650*61c4878aSAndroid Build Coastguard Workerthat use a `transition
651*61c4878aSAndroid Build Coastguard Worker<https://bazel.build/extending/config#user-defined-transitions>`__ to set the
652*61c4878aSAndroid Build Coastguard Workerflags. You can see examples of such transitions in the `Pigweed examples
653*61c4878aSAndroid Build Coastguard Workerproject
654*61c4878aSAndroid Build Coastguard Worker<https://cs.opensource.google/pigweed/examples/+/main:targets/transition.bzl>`__.
655