Skip to content

Commit

Permalink
pw_toolchain: Add Bazel mechansim for clang/gcc-specific flags
Browse files Browse the repository at this point in the history
Adds sentinel features for compiler flavor and a rule that can extract
properties from the current toolchain for use in `select()` statements
across build files.

Bug: b/361229275
Change-Id: Ibc4645a082d75ddda6650dbe75123ed2ed11ce0e
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/238429
Presubmit-Verified: CQ Bot Account <[email protected]>
Lint: Lint 🤖 <[email protected]>
Commit-Queue: Auto-Submit <[email protected]>
Pigweed-Auto-Submit: Armando Montanez <[email protected]>
Reviewed-by: Ted Pudlik <[email protected]>
  • Loading branch information
armandomontanez authored and CQ Bot Account committed Oct 9, 2024
1 parent 9fe59f4 commit 0125f4a
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 12 deletions.
9 changes: 5 additions & 4 deletions pw_libcxx/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations under
# the License.

load("//pw_toolchain/cc/current_toolchain:conditions.bzl", "if_compiler_is_clang")
load("//pw_unit_test:pw_cc_test.bzl", "pw_cc_test")

package(default_visibility = ["//visibility:public"])
Expand All @@ -25,10 +26,10 @@ cc_library(
"operator_new.cc",
"verbose_abort.cc",
],
target_compatible_with = select({
"@rules_cc//cc/compiler:clang": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
target_compatible_with = if_compiler_is_clang(
[],
otherwise = ["@platforms//:incompatible"],
),
alwayslink = True,
)

Expand Down
15 changes: 15 additions & 0 deletions pw_toolchain/arm_clang/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
load(
"@pw_toolchain//cc_toolchain:defs.bzl",
"pw_cc_action_files",
"pw_cc_feature",
"pw_cc_flag_set",
"pw_cc_toolchain",
)
Expand Down Expand Up @@ -192,6 +193,18 @@ pw_cc_flag_set(
],
)

pw_cc_feature(
name = "compiler_is_clang",
enabled = True,
feature_name = "compiler_is_clang",
)

pw_cc_feature(
name = "linker_is_clang",
enabled = True,
feature_name = "linker_is_clang",
)

pw_cc_toolchain(
name = "arm_clang_toolchain_cortex-m",
action_configs = [
Expand Down Expand Up @@ -251,6 +264,8 @@ pw_cc_toolchain(
toolchain_features = [
"//pw_toolchain/cc:c++17_feature",
"//pw_toolchain/cc:c++20_feature",
":compiler_is_clang",
":linker_is_clang",
],
toolchain_identifier = "arm-clang-toolchain",
visibility = ["//pw_toolchain:__pkg__"],
Expand Down
15 changes: 15 additions & 0 deletions pw_toolchain/arm_gcc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

load(
"@pw_toolchain//cc_toolchain:defs.bzl",
"pw_cc_feature",
"pw_cc_flag_set",
"pw_cc_toolchain",
)
Expand Down Expand Up @@ -256,6 +257,18 @@ pw_cc_flag_set(
],
)

pw_cc_feature(
name = "compiler_is_gcc",
enabled = True,
feature_name = "compiler_is_gcc",
)

pw_cc_feature(
name = "linker_is_gcc",
enabled = True,
feature_name = "linker_is_gcc",
)

pw_cc_toolchain(
name = "arm_gcc_toolchain_cortex-m",
action_configs = [
Expand Down Expand Up @@ -322,6 +335,8 @@ pw_cc_toolchain(
toolchain_features = [
"//pw_toolchain/cc:c++17_feature",
"//pw_toolchain/cc:c++20_feature",
":compiler_is_gcc",
":linker_is_gcc",
],
toolchain_identifier = "arm-gcc-toolchain",
visibility = ["//pw_toolchain:__pkg__"],
Expand Down
59 changes: 59 additions & 0 deletions pw_toolchain/bazel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,62 @@ upstream toolchains by calling ``register_pigweed_cxx_toolchains()``:
Pigweed's upstream toolchains are subject to change without notice. If you
would prefer more stability in toolchain configurations, consider declaring
custom toolchains in your project.

-----------------------------
Compiler-specific build logic
-----------------------------
Whenever possible, avoid introducing compiler-specific behaviors in Bazel
``BUILD`` files. Instead, prefer to design build logic against
more intentional :ref:`docs-bazel-compatibility`. For compiler-specific
behavior, this means defining and/or using compiler capabilities like
`@rules_cc//cc/toolchains/capabilities:supports_interface_shared_libraries <https://github.com/bazelbuild/rules_cc/blob/main/cc/toolchains/capabilities/BUILD>`__

If you need to expose a toolchain capability as a choice in a select, you
can use ``pw_cc_toolchain_feature_is_enabled``.

Example:

.. code-block:: py
load(
"@pigweed//pw_toolchain/cc/current_toolchain:pw_cc_toolchain_feature_is_enabled.bzl",
"pw_cc_toolchain_feature_is_enabled",
)
pw_cc_toolchain_feature_is_enabled(
name = "llvm_libc_enabled",
feature_name = "llvm_libc",
)
cc_library(
name = "libfoo",
deps = select({
":llvm_libc_enabled": ["//foo:llvm_libc_extras"],
"//conditions:default": [],
}),
)
If you absolutely must introduce a ``select`` statement that checks the current
compiler, use Pigweed's helper macros.

Example:

.. code-block:: py
load(
"@pigweed//pw_toolchain/cc/current_toolchain:conditions.bzl",
"if_compiler_is_clang",
"if_linker_is_gcc",
)
cc_library(
copts = if_compiler_is_clang(
["-fno-codegen"],
default = [],
),
linkopts = if_linker_is_gcc(
["-Wl,--delete-main"],
default = [],
),
srcs = ["lib.cc"],
)
41 changes: 41 additions & 0 deletions pw_toolchain/cc/capability/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

load("@rules_cc//cc/toolchains:feature.bzl", "cc_feature")

package(default_visibility = ["//visibility:public"])

# All of the toolchain features enumerated in this build file are sentinel
# features. By nature, they do not provide any flags. Instead, these features
# are used to guide other behaviors throughout a toolchain.

cc_feature(
name = "compiler_is_clang",
feature_name = "compiler_is_clang",
)

cc_feature(
name = "compiler_is_gcc",
feature_name = "compiler_is_gcc",
)

cc_feature(
name = "linker_is_clang",
feature_name = "linker_is_clang",
)

cc_feature(
name = "linker_is_gcc",
feature_name = "linker_is_gcc",
)
65 changes: 65 additions & 0 deletions pw_toolchain/cc/current_toolchain/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

load(":pw_cc_toolchain_feature_is_enabled.bzl", "pw_cc_toolchain_feature_is_enabled")

pw_cc_toolchain_feature_is_enabled(
name = "compiler_is_clang",
feature_name = "compiler_is_clang",
)

pw_cc_toolchain_feature_is_enabled(
name = "compiler_is_clang-cl",
feature_name = "compiler_is_clang-cl",
)

pw_cc_toolchain_feature_is_enabled(
name = "compiler_is_gcc",
feature_name = "compiler_is_gcc",
)

pw_cc_toolchain_feature_is_enabled(
name = "compiler_is_mingw-gcc",
feature_name = "compiler_is_mingw-gcc",
)

pw_cc_toolchain_feature_is_enabled(
name = "compiler_is_msvc-cl",
feature_name = "compiler_is_msvc-cl",
)

pw_cc_toolchain_feature_is_enabled(
name = "linker_is_clang",
feature_name = "linker_is_clang",
)

pw_cc_toolchain_feature_is_enabled(
name = "linker_is_clang-cl",
feature_name = "linker_is_clang-cl",
)

pw_cc_toolchain_feature_is_enabled(
name = "linker_is_gcc",
feature_name = "linker_is_gcc",
)

pw_cc_toolchain_feature_is_enabled(
name = "linker_is_mingw-gcc",
feature_name = "linker_is_mingw-gcc",
)

pw_cc_toolchain_feature_is_enabled(
name = "linker_is_msvc-cl",
feature_name = "linker_is_msvc-cl",
)
42 changes: 42 additions & 0 deletions pw_toolchain/cc/current_toolchain/conditions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Helpers for expressing compiler-specific build file logic."""

def if_compiler_is_clang(then, *, otherwise):
return select({
"//pw_toolchain/cc/current_toolchain:compiler_is_clang": then,
"@rules_cc//cc/compiler:clang": then,
"//conditions:default": otherwise,
})

def if_compiler_is_gcc(then, *, otherwise):
return select({
"//pw_toolchain/cc/current_toolchain:compiler_is_gcc": then,
"@rules_cc//cc/compiler:gcc": then,
"//conditions:default": otherwise,
})

def if_linker_is_clang(then, *, otherwise):
return select({
"//pw_toolchain/cc/current_toolchain:linker_is_clang": then,
"@rules_cc//cc/compiler:clang": then,
"//conditions:default": otherwise,
})

def if_linker_is_gcc(then, *, otherwise):
return select({
"//pw_toolchain/cc/current_toolchain:linker_is_gcc": then,
"@rules_cc//cc/compiler:gcc": then,
"//conditions:default": otherwise,
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""A rule for letting enabled toolchain features drive build configuration."""

load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")

def _cc_toolchain_feature_is_enabled_impl(ctx):
toolchain = find_cpp_toolchain(ctx)
feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = toolchain,
)
val = cc_common.is_enabled(
feature_configuration = feature_configuration,
feature_name = ctx.attr.feature_name,
)
return [
config_common.FeatureFlagInfo(value = str(val)),
BuildSettingInfo(value = val),
]

_cc_toolchain_feature_is_enabled = rule(
implementation = _cc_toolchain_feature_is_enabled_impl,
attrs = {
"feature_name": attr.string(
mandatory = True,
doc = "The feature name to match against",
),
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
},
doc = """Extracts a matching, enabled feature from the current C/C++ toolchain.
This rule is a bridge that allows feature presence/absence to be communicated
from a toolchain configuration as if it was just a `bool_flag`.
This allows toolchain features to become branches in `select()` statements:
```py
_cc_toolchain_feature_is_enabled(
name = "toolchain_flavor_chocolate",
feature_name = "toolchain_flavor_chocolate",
)
config_setting(
name = "chocolate",
flag_values = {":toolchain_flavor_chocolate": "True"},
)
cc_library(
name = "libfoo",
copts = select({
":chocolate": ["-fno-dog-food"],
"//conditions:default": [],
}),
srcs = ["foo.cc"],
)
```
""",
toolchains = use_cpp_toolchain(),
fragments = ["cpp"],
)

def pw_cc_toolchain_feature_is_enabled(*, name, feature_name, **kwargs):
_cc_toolchain_query_name = name + ".value"
_cc_toolchain_feature_is_enabled(
name = _cc_toolchain_query_name,
feature_name = feature_name,
**kwargs
)

native.config_setting(
name = name,
flag_values = {":{}".format(_cc_toolchain_query_name): "True"},
)
Loading

0 comments on commit 0125f4a

Please sign in to comment.