0

a project I'm working on -- Envoy proxy -- uses Bazel and tcmalloc. I'd like to configure it to use the debug version of tcmalloc when compiling for debug and fastbuild, and use the optimized one for optimized builds.

There are other conditions as well, e.g. a command-line flag passed to bazel to turn off tcmalloc completely, using this logic:

https://github.com/envoyproxy/envoy/blob/7d2e84d3d0f8a4ffbf4257c450b3e5a6d93d4697/bazel/envoy_build_system.bzl#L166

def tcmalloc_external_dep(repository):
    return select({
        repository + "//bazel:disable_tcmalloc": None,
        "//conditions:default": envoy_external_dep_path("tcmalloc_and_profiler"),
    })

I have PR out (https://github.com/envoyproxy/envoy/pull/5424) failing continuous integration which changes the logic (https://github.com/envoyproxy/envoy/blob/1ed5aba5894ce519181edbdaee3f52c2971befaf/bazel/envoy_build_system.bzl#L156) to:

def tcmalloc_external_dep(repository):
    return select({
        repository + "//bazel:disable_tcmalloc": None,
        repository + "//bazel:dbg_build": envoy_external_dep_path("tcmalloc_debug"),
        "//conditions:default": envoy_external_dep_path("tcmalloc_and_profiler"),
    })

However this does not work as we allow disabling tcmalloc on debug builds (which we do in continuous-integration scripts when running tsan). This runs afoul of bazel which evidently expects the conditions to be mutually exclusive, when I want "first matching rule wins" in this case. I get this error:

ERROR: /home/jmarantz/git4/envoy/test/common/network/BUILD:58:1: Illegal ambiguous match on configurable attribute "malloc" in //test/common/network:dns_impl_test:
//bazel:disable_tcmalloc
//bazel:dbg_build
Multiple matches are not allowed unless one is unambiguously more specialized.
ERROR: Analysis of target '//test/common/network:dns_impl_test' failed; build aborted: 

/home/jmarantz/git4/envoy/test/common/network/BUILD:58:1: Illegal ambiguous match on configurable attribute "malloc" in //test/common/network:dns_impl_test:
//bazel:disable_tcmalloc
//bazel:dbg_build

What's the best way to solve this? Can I use a Python conditional on the bazel command-line settings? Can I use AND or OR operators in the conditional expressions to make them mutually exclusive? Or is there another approach I could use?

2 Answers2

1

Not an answer, but perhaps I can give you some ideas:

As of now, you can simulate and and or by nesting selects or refactoring your config_settings.

There is a proposal for some changes to add flexibility here: https://github.com/bazelbuild/proposals/blob/master/designs/2018-11-09-config-setting-chaining.md

You might also find some useful ideas in Skylib. https://github.com/bazelbuild/bazel-skylib

0

Yup you can chain select using https://github.com/bazelbuild/bazel-skylib/blob/master/lib/selects.bzl#L80. You can also write your own feature flag rule that can be used in the select and that has artibrary logic in it, see https://source.bazel.build/bazel/+/0faef9148362a5234df3507441dadb0f32ade59a:tools/cpp/compiler_flag.bzl for example, it's a rule that can be used in selects and that gets the current C++ toolchain and inspects its state and returns its compiler value. You'll have to follow the thread a bit to see all the pieces. I'll ask for better docs for this.

hlopko
  • 3,100
  • 22
  • 27
  • Cool. Better doc would be pretty great. Are you saying that if I simply replace `select({` with `selects.with_or({` then my example will work -- it will not give me the 'ambiguous match' complaint? It's not entirely obvious to me that the OR functionality gives me that, or that I could build that device with OR-gates. I think I need AND-gates and NOT-gates :) E.g. the select() would be OK if I could do: select({condA:a-result, AND(NOT(condA),condB):b-result...}) – Joshua Marantz Jan 11 '19 at 14:59