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