From 942559c7dcdfa72d53343fcf048cade00d4accb8 Mon Sep 17 00:00:00 2001 From: Nikola Radakovic Date: Wed, 15 Apr 2026 14:58:25 +0100 Subject: [PATCH] Add feature injection Add feature injection to toolchain gcc extension. This option will allow users to add external defined features. --- MODULE.bazel | 2 +- MODULE.bazel.lock | 8 +- docs/examples_and_validation.md | 13 +- docs/extension_api.md | 6 + examples/BUILD | 54 ----- examples/MODULE.bazel | 2 +- examples/MODULE.bazel.lock | 26 +- examples/README.md | 11 + examples/asan_test.cpp | 36 --- examples/lsan_test.cpp | 31 --- examples/tsan_test.cpp | 40 ---- extensions/gcc.bzl | 24 ++ rules/common.bzl | 11 + rules/gcc.bzl | 12 +- .../linux/cc_toolchain_config.bzl.template | 222 ++---------------- .../qnx/cc_toolchain_config.bzl.template | 22 ++ 16 files changed, 145 insertions(+), 375 deletions(-) delete mode 100644 examples/asan_test.cpp delete mode 100644 examples/lsan_test.cpp delete mode 100644 examples/tsan_test.cpp diff --git a/MODULE.bazel b/MODULE.bazel index 2e5d9ae..341eea2 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -27,7 +27,7 @@ bazel_dep(name = "score_bazel_platforms", version = "0.1.2") # ******************************************************************************* # C++ Rules for Bazel # ******************************************************************************* -bazel_dep(name = "rules_cc", version = "0.2.14") +bazel_dep(name = "rules_cc", version = "0.2.17") # ******************************************************************************* # Needed by S-CORE CI Automatic checks diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index f3d7244..4dc17a4 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -156,8 +156,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", "https://bcr.bazel.build/modules/rules_diff/1.0.0/MODULE.bazel": "1739509d8db9a6cd7d3584822340d3dfe1f9f27e62462fbca60aa061d88741b2", @@ -403,7 +403,7 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.0.8/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.0.9/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.1.1/MODULE.bazel": "not found", - "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.14/MODULE.bazel": "not found", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.17/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.4/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.8/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_diff/1.0.0/MODULE.bazel": "not found", @@ -1884,7 +1884,7 @@ }, "@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": { "general": { - "bzlTransitiveDigest": "gVtgT7glGR1T+ubbYuYNuRDSxAQJ4d86ZafxsQchHhQ=", + "bzlTransitiveDigest": "pkKYmGmCmLXmfoskyn8tfyQRAqAIKifHQs9cZyYY5QE=", "usagesDigest": "dQ7SQZ7uSSL3vVKSMBKRxKJUm9OVrZZA+S1/QQfT570=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, diff --git a/docs/examples_and_validation.md b/docs/examples_and_validation.md index 4baca2f..077783b 100644 --- a/docs/examples_and_validation.md +++ b/docs/examples_and_validation.md @@ -45,7 +45,8 @@ platforms. `examples/BUILD` Contains small C++ targets used to verify compilation, linking, pthread -support, and sanitizer integration. +support, and optional sanitizer integration when sanitizer features are +registered explicitly. `examples/test.sh` @@ -85,4 +86,12 @@ In practice this means checking among other things: - correct toolchain registration and platform matching, - basic linking behavior, - feature coverage such as pthread-enabled builds, -- optional sanitizer feature wiring for the local Linux toolchain path. \ No newline at end of file +- optional sanitizer feature wiring for the local Linux toolchain path. + +## Sanitizer Note + +Sanitizer features are not included by default by the generated toolchains. +If a workspace wants to use targets such as `asan_test`, it must first +register the sanitizer `cc_feature` definitions explicitly, for example via +`extra_known_features` or `extra_enabled_features` when declaring the +toolchain and by providing the feature definitions from `score_cpp_policies`. \ No newline at end of file diff --git a/docs/extension_api.md b/docs/extension_api.md index 1c2b6d1..91d21a1 100644 --- a/docs/extension_api.md +++ b/docs/extension_api.md @@ -72,6 +72,8 @@ Flag and runtime attributes: - `extra_c_compile_flags` - `extra_cxx_compile_flags` - `extra_link_flags` +- `extra_known_features` +- `extra_enabled_features` - `ld_library_paths` - `runtime_ecosystem` - `use_base_constraints_only` @@ -112,5 +114,9 @@ configurations for this activation step. - The extension is intended for the root module. - When `use_default_package` is enabled, the version matrix can inject extra include and link flags required by non-standard sysroot layouts. +- Sanitizer features are not registered automatically. Workspaces that want + sanitizer support must provide the relevant rule-based `cc_feature` + definitions explicitly, typically from `score_cpp_policies`, through + `extra_known_features` or `extra_enabled_features`. - QNX toolchains use additional licensing and include-path parameters that do not apply to Linux toolchains. \ No newline at end of file diff --git a/examples/BUILD b/examples/BUILD index 41fc5ad..c0d526a 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -51,57 +51,3 @@ cc_test( linkstatic = False, deps = [":math_lib"], ) - -cc_test( - name = "asan_test", - srcs = ["asan_test.cpp"], - features = ["asan"], - deps = [ - "@googletest//:gtest", - "@googletest//:gtest_main", - ], -) - -# for some reason this test is very flaky. -# cc_test( -# name = "tsan_test", -# srcs = ["tsan_test.cpp"], -# features = ["tsan"], -# env = { -# "TSAN_OPTIONS": "halt_on_error=1", -# }, -# deps = [ -# "@googletest//:gtest", -# "@googletest//:gtest_main", -# ], -# ) - -cc_test( - name = "ubsan_test", - srcs = ["ubsan_test.cpp"], - env = { - "UBSAN_OPTIONS": "halt_on_error=1", - }, - features = ["ubsan"], - deps = [ - "@googletest//:gtest", - "@googletest//:gtest_main", - ], -) - -cc_test( - name = "lsan_test", - srcs = ["lsan_test.cpp"], - env = { - "ASAN_OPTIONS": "detect_leaks=1", - "LSAN_OPTIONS": "exitcode=23", - }, - features = [ - "lsan", - "asan", - ], - deps = [ - "@googletest//:gtest", - "@googletest//:gtest_main", - ], -) diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel index 05bfc17..c2ead01 100644 --- a/examples/MODULE.bazel +++ b/examples/MODULE.bazel @@ -30,7 +30,7 @@ bazel_dep(name = "score_bazel_platforms", version = "0.1.2") # ******************************************************************************* # C++ Rules for Bazel # ******************************************************************************* -bazel_dep(name = "rules_cc", version = "0.2.14") +bazel_dep(name = "rules_cc", version = "0.2.17") bazel_dep(name = "googletest", version = "1.17.0") # ******************************************************************************* diff --git a/examples/MODULE.bazel.lock b/examples/MODULE.bazel.lock index 0c28807..9d3e63c 100644 --- a/examples/MODULE.bazel.lock +++ b/examples/MODULE.bazel.lock @@ -165,8 +165,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", "https://bcr.bazel.build/modules/rules_diff/1.0.0/MODULE.bazel": "1739509d8db9a6cd7d3584822340d3dfe1f9f27e62462fbca60aa061d88741b2", @@ -423,7 +423,7 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.0.8/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.0.9/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.1.1/MODULE.bazel": "not found", - "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.14/MODULE.bazel": "not found", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.17/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.4/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_cc/0.2.8/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/rules_diff/1.0.0/MODULE.bazel": "not found", @@ -1902,7 +1902,7 @@ }, "@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": { "general": { - "bzlTransitiveDigest": "gVtgT7glGR1T+ubbYuYNuRDSxAQJ4d86ZafxsQchHhQ=", + "bzlTransitiveDigest": "pkKYmGmCmLXmfoskyn8tfyQRAqAIKifHQs9cZyYY5QE=", "usagesDigest": "dQ7SQZ7uSSL3vVKSMBKRxKJUm9OVrZZA+S1/QQfT570=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -2054,7 +2054,7 @@ }, "@@score_bazel_cpp_toolchains+//extensions:gcc.bzl%gcc": { "general": { - "bzlTransitiveDigest": "ffZnV0q7fvKZoTuHJha11Vgfd22yTEYU3paXbuFBu2M=", + "bzlTransitiveDigest": "bwOGkDfv3sSgJrEeLpjFYKtqAM/UCo4+wNAf+KhqurE=", "usagesDigest": "UGWjRneAyNFej8g6SWlPfmeiX8/dwQzCLxr5gub4nN4=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -2154,6 +2154,8 @@ "extra_compile_flags": [], "extra_c_compile_flags": [], "extra_cxx_compile_flags": [], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [], "license_info_variable": "", "license_info_value": "", @@ -2179,6 +2181,8 @@ "extra_compile_flags": [], "extra_c_compile_flags": [], "extra_cxx_compile_flags": [], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [], "license_info_variable": "", "license_info_value": "", @@ -2204,6 +2208,8 @@ "extra_compile_flags": [], "extra_c_compile_flags": [], "extra_cxx_compile_flags": [], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [], "license_info_variable": "", "license_info_value": "", @@ -2229,6 +2235,8 @@ "extra_compile_flags": [], "extra_c_compile_flags": [], "extra_cxx_compile_flags": [], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [ "-lpthread" ], @@ -2256,6 +2264,8 @@ "extra_compile_flags": [], "extra_c_compile_flags": [], "extra_cxx_compile_flags": [], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [], "license_info_variable": "", "license_info_value": "", @@ -2281,6 +2291,8 @@ "extra_compile_flags": [], "extra_c_compile_flags": [], "extra_cxx_compile_flags": [], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [], "license_info_variable": "", "license_info_value": "", @@ -2325,6 +2337,8 @@ "-isystem", "external/%{toolchain_pkg}%/usr/include" ], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [ "-B", "external/%{toolchain_pkg}%/usr/bin", @@ -2400,6 +2414,8 @@ "external/%{toolchain_pkg}%/usr/lib/x86_64-linux-gnu", "--no-canonical-prefixes" ], + "extra_known_features": [], + "extra_enabled_features": [], "extra_link_flags": [ "-B", "external/%{toolchain_pkg}%/usr/aarch64-linux-gnu/bin", diff --git a/examples/README.md b/examples/README.md index 2f1fd1f..58ee531 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,6 +10,17 @@ The toolchain configurations are defined in: ## Building Targets +## Sanitizer Feature Registration + +Sanitizer features are no longer included by default by the example toolchain +declarations. Targets that request features such as `score_asan` require the +workspace to register those feature definitions explicitly, for example from +`score_cpp_policies` via `extra_known_features` or `extra_enabled_features` on +the corresponding `gcc.toolchain(...)` declaration. + +Without that explicit registration, sanitizer-specific example targets are not +expected to build. + ### Default Toolchain Build a specific target with the default toolchain: diff --git a/examples/asan_test.cpp b/examples/asan_test.cpp deleted file mode 100644 index 5f8fb94..0000000 --- a/examples/asan_test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include - -// Reproduce the buggy logic as a callable function (rather than a real main()). -static int buggy(int argc) { - int *array = new int[100]; - delete[] array; - - // Prevent compiler from optimizing away the UB access. - volatile int idx = argc; - - // Use-after-free (+ potential OOB if argc >= 100). - return array[idx]; -} - -TEST(BugReproTest, UseAfterFree_ShouldCrashUnderSanitizers) { - // Under ASan/UBSan this should reliably abort. - // Regex ".*" accepts any sanitizer death message. - ASSERT_DEATH({ (void)buggy(0); }, ".*"); -} - -TEST(BugReproTest, OutOfBoundsPlusUaf_ShouldCrashUnderSanitizers) { - // argc=200 also implies out-of-bounds in addition to use-after-free. - ASSERT_DEATH({ (void)buggy(200); }, ".*"); -} \ No newline at end of file diff --git a/examples/lsan_test.cpp b/examples/lsan_test.cpp deleted file mode 100644 index 084d044..0000000 --- a/examples/lsan_test.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include -#include - -static void lsan_buggy() { - int* leaked = new int[100]; - leaked[0] = 42; - - // Drop the last visible reference so LSan can't find it on the stack. - leaked = nullptr; - - std::exit(0); -} - -TEST(LsanBugReproTest, MemoryLeak_ShouldBeReportedByLeakSanitizer) { - EXPECT_EXIT( - { lsan_buggy(); }, - ::testing::ExitedWithCode(23), - ".*"); -} \ No newline at end of file diff --git a/examples/tsan_test.cpp b/examples/tsan_test.cpp deleted file mode 100644 index 782aeeb..0000000 --- a/examples/tsan_test.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include -#include -#include - -static int shared_value = 0; - -static void tsan_buggy() { - std::thread writer([]() { - for (int i = 0; i < 100000; ++i) { - shared_value = i; // unsynchronized write - } - }); - - std::thread reader([]() { - int tmp = 0; - for (int i = 0; i < 100000; ++i) { - tmp = shared_value; // unsynchronized read - } - (void)tmp; - }); - - writer.join(); - reader.join(); -} - -TEST(TsanBugReproTest, ReadWriteRace_ShouldCrashUnderThreadSanitizer) { - ASSERT_DEATH({ tsan_buggy(); }, ".*"); -} \ No newline at end of file diff --git a/extensions/gcc.bzl b/extensions/gcc.bzl index 5b00c28..d09856a 100644 --- a/extensions/gcc.bzl +++ b/extensions/gcc.bzl @@ -68,6 +68,26 @@ _attrs_tc = { default = [], doc = "List of additional flags to be passed to linker.", ), + "extra_enabled_features": attr.label_list( + mandatory = False, + default = [], + doc = ("Extra `cc_feature` features to add to this toolchain in an initially " + + "enabled state. This attribute has limited integration with `cc_feature`, " + + "and does not run additional correctness checks or handle things like `data` " + + "files. This is only offered as a migration bridge for projects transitioning " + + "to rule-based toolchain configurations, or sharing of simple argument sets " + + "with older toolchains."), + ), + "extra_known_features": attr.label_list( + mandatory = False, + default = [], + doc = ("Extra `cc_feature` features to add to this toolchain in an initially " + + "disabled state. This attribute has limited integration with `cc_feature`, " + + "and does not run additional correctness checks or handle things like `data` " + + "files. This is only offered as a migration bridge for projects transitioning " + + "to rule-based toolchain configurations, or sharing of simple argument sets " + + "with older toolchains."), + ), "license_info_url": attr.string( default = "", mandatory = False, @@ -193,6 +213,8 @@ def _get_toolchains(tags): "tc_extra_compile_flags": tag.extra_compile_flags, "tc_extra_cxx_compile_flags": tag.extra_cxx_compile_flags, "tc_extra_link_flags": tag.extra_link_flags, + "tc_extra_known_features": tag.extra_known_features, + "tc_extra_enabled_features": tag.extra_enabled_features, "tc_license_info_url": tag.license_info_url, "tc_license_info_variable": tag.license_info_variable, "tc_license_path": tag.license_path, @@ -333,6 +355,8 @@ def _impl(mctx): extra_compile_flags = toolchain_info["tc_extra_compile_flags"], extra_c_compile_flags = toolchain_info["tc_extra_c_compile_flags"], extra_cxx_compile_flags = toolchain_info["tc_extra_cxx_compile_flags"], + extra_known_features = toolchain_info["tc_extra_known_features"], + extra_enabled_features = toolchain_info["tc_extra_enabled_features"], extra_link_flags = toolchain_info["tc_extra_link_flags"], license_info_variable = toolchain_info["tc_license_info_variable"], license_info_value = toolchain_info["tc_license_info_url"], diff --git a/rules/common.bzl b/rules/common.bzl index 03b5396..10dd657 100644 --- a/rules/common.bzl +++ b/rules/common.bzl @@ -45,3 +45,14 @@ def get_flag_group(flags): ), ] return [] + +def label_list_to_string(input_list): + """ Small helper function to transform label list into string list + + Args: + input_list (list[labels]): A list of Bazel labels. + + Return: + str: Formated string + """ + return "[{}]".format(", ".join(["\"{}\"".format(item) for item in input_list])) diff --git a/rules/gcc.bzl b/rules/gcc.bzl index 20ba43b..ba3a2dd 100644 --- a/rules/gcc.bzl +++ b/rules/gcc.bzl @@ -14,7 +14,7 @@ """ Module rule for defining GCC toolchains in Bazel. """ -load("@score_bazel_cpp_toolchains//rules:common.bzl", "get_flag_groups") +load("@score_bazel_cpp_toolchains//rules:common.bzl", "get_flag_groups", "label_list_to_string") def dict_union(x, y): """ Helper function to merge 2 dict @@ -53,12 +53,16 @@ cc_toolchain_config( sysroot = "@{tc_pkg_repo}//:sysroot_dir", target_cpu = "{tc_cpu}", target_os = "{tc_os}", + extra_known_features = {tc_extra_known_features}, + extra_enabled_features = {tc_extra_enabled_features}, visibility = ["//visibility:public"], ) """.format( tc_pkg_repo = rctx.attr.tc_pkg_repo, tc_cpu = rctx.attr.tc_cpu, tc_os = rctx.attr.tc_os, + tc_extra_known_features = label_list_to_string(rctx.attr.extra_known_features), + tc_extra_enabled_features = label_list_to_string(rctx.attr.extra_enabled_features), ) def _get_cc_config_qnx(rctx): @@ -85,12 +89,16 @@ cc_toolchain_config( cxx_builtin_include_directories = "@{tc_pkg_repo}//:cxx_builtin_include_directories", target_cpu = "{tc_cpu}", target_os = "{tc_os}", + extra_known_features = {tc_extra_known_features}, + extra_enabled_features = {tc_extra_enabled_features}, visibility = ["//visibility:public"], ) """.format( tc_pkg_repo = rctx.attr.tc_pkg_repo, tc_cpu = rctx.attr.tc_cpu, tc_os = rctx.attr.tc_os, + tc_extra_known_features = label_list_to_string(rctx.attr.extra_known_features), + tc_extra_enabled_features = label_list_to_string(rctx.attr.extra_enabled_features), ) def _impl(rctx): @@ -244,6 +252,8 @@ gcc_toolchain = repository_rule( "extra_c_compile_flags": attr.string_list(doc = "Extra/Additional C-specific compile flags."), "extra_compile_flags": attr.string_list(doc = "Extra/Additional compile flags."), "extra_cxx_compile_flags": attr.string_list(doc = "Extra/Additional C++-specific compile flags."), + "extra_known_features": attr.label_list(doc = "Extra/Additional C++ FeatureInfo provider list"), + "extra_enabled_features": attr.label_list(doc = "Extra/Additional C++ FeatureInfo provider list enabled by default"), "extra_link_flags": attr.string_list(doc = "Extra/Additional link flags."), "gcc_version": attr.string(doc = "GCC version string"), "use_base_constraints_only": attr.bool(doc = "Boolean flag to state only base constraints should be used for toolchain compatibility definition"), diff --git a/templates/linux/cc_toolchain_config.bzl.template b/templates/linux/cc_toolchain_config.bzl.template index 8ee5a75..a22af9f 100644 --- a/templates/linux/cc_toolchain_config.bzl.template +++ b/templates/linux/cc_toolchain_config.bzl.template @@ -27,6 +27,7 @@ load("@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", "with_feature_set", ) load("@rules_cc//cc:defs.bzl", "cc_common", "CcToolchainConfigInfo") +load("@rules_cc//cc/toolchains:feature_injection.bzl", "convert_feature", "FeatureInfo") load(":flags.bzl", "UNFILTERED_COMPILE_FLAGS", "DEFAULT_COMPILE_FLAGS", @@ -85,9 +86,6 @@ def _impl(ctx): dbg_feature = feature(name = "dbg") opt_feature = feature(name = "opt") - # Temp solution until we do not add feature injection - gnu11_feature = feature(name = "gnu11") - supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) supports_fission_feature = feature(name = "supports_fission", enabled = True) @@ -207,16 +205,6 @@ def _impl(ctx): actions = all_compile_actions, flag_groups = target_cpu_flags, ), - flag_set( - actions = all_c_compile_actions, - flag_groups = [flag_group(flags = ["-std=c11"])], - with_features = [with_feature_set(not_features = ["gnu11"])], - ), - flag_set( - actions = all_c_compile_actions, - flag_groups = [flag_group(flags = ["-std=gnu11"])], - with_features = [with_feature_set(features = ["gnu11"])], - ), flag_set( actions = all_cpp_compile_actions, flag_groups = DEFAULT_CXX_COMPILE_FLAGS, @@ -288,187 +276,6 @@ def _impl(ctx): ], ) - sanitizer_feature = feature( - name = "sanitizer", - flag_sets = [ - flag_set( - actions = all_compile_actions, - flag_groups = [ - flag_group( - flags = [ - "-fno-omit-frame-pointer", - "-fno-sanitize-recover=all", # TODO: Check if this is needed. - "-g", - ], - ), - ], - with_features = [ - with_feature_set( - features = [ - "asan", - "lsan", - "tsan", - "ubsan", - ], - not_features = ["opt"], - ) - ], - ), - ], - ) - - asan_feature = feature( - name = "asan", - implies = ["sanitizer"], - flag_sets = [ - flag_set( - actions = all_compile_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=address", - "-DADDRESS_SANITIZER", - "-O0", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - flag_set( - actions = all_link_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=address", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - ], - ) - - lsan_feature = feature( - name = "lsan", - implies = ["sanitizer"], - flag_sets = [ - flag_set( - actions = all_compile_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=leak", - "-O0", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - flag_set( - actions = all_link_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=leak", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - ], - ) - - tsan_feature = feature( - name = "tsan", - implies = ["sanitizer"], - flag_sets = [ - flag_set( - actions = all_compile_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=thread", - "-O1", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - flag_set( - actions = all_link_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=thread", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - ], - ) - - ubsan_feature = feature( - name = "ubsan", - implies = ["sanitizer"], - flag_sets = [ - flag_set( - actions = all_compile_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=undefined", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - flag_set( - actions = all_link_actions, - flag_groups = [ - flag_group( - flags = [ - "-fsanitize=undefined", - ], - ), - ], - with_features = [ - with_feature_set( - not_features = ["opt"], - ) - ], - ), - ], - ) - minimal_warnings_feature = feature( name = "minimal_warnings", enabled = False, @@ -642,14 +449,8 @@ def _impl(ctx): features = [ compiler_library_search_paths_feature, - sanitizer_feature, - asan_feature, - lsan_feature, - tsan_feature, - ubsan_feature, dbg_feature, unfiltered_compile_flags_feature, - gnu11_feature, default_compile_flags_feature, default_link_flags_feature, sysroot_link_flags_feature, @@ -671,6 +472,9 @@ def _impl(ctx): gcc_coverage_map_format_feature, ] + extra_rules_based_features = depset(ctx.attr.extra_enabled_features + ctx.attr.extra_known_features) + features.extend([convert_feature(extra_feature[FeatureInfo], enabled = extra_feature in ctx.attr.extra_enabled_features) for extra_feature in extra_rules_based_features.to_list()]) + # Get builtin include directories from attribute if provided cxx_builtin_include_directories = [] if hasattr(ctx.attr, "builtin_include_directories") and ctx.attr.builtin_include_directories: @@ -715,5 +519,23 @@ cc_toolchain_config = rule( "host_dir": attr.label(default = None), "target_dir": attr.label(default = None), "cxx_builtin_include_directories": attr.label(allow_files = True, default = None), + "extra_enabled_features": attr.label_list( + providers = [FeatureInfo], + default = [], + doc = """ +Extra `cc_feature` features to add to this toolchain in an initially enabled state. +This attribute has limited integration with `cc_feature`, and does not run additional correctness checks or handle things like `data` files. +This is only offered as a migration bridge for projects transitioning to rule-based toolchain configurations, or sharing of simple argument sets with older toolchains. +""", + ), + "extra_known_features": attr.label_list( + providers = [FeatureInfo], + default = [], + doc = """ +Extra `cc_feature` features to add to this toolchain in an initially disabled state. +This attribute has limited integration with `cc_feature`, and does not run additional correctness checks or handle things like `data` files. +This is only offered as a migration bridge for projects transitioning to rule-based toolchain configurations, or sharing of simple argument sets with older toolchains. +""", + ), }, ) \ No newline at end of file diff --git a/templates/qnx/cc_toolchain_config.bzl.template b/templates/qnx/cc_toolchain_config.bzl.template index 97b6d8b..7b355a4 100644 --- a/templates/qnx/cc_toolchain_config.bzl.template +++ b/templates/qnx/cc_toolchain_config.bzl.template @@ -27,6 +27,7 @@ load("@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", "with_feature_set", ) load("@rules_cc//cc:defs.bzl", "cc_common", "CcToolchainConfigInfo") +load("@rules_cc//cc/toolchains:feature_injection.bzl", "convert_feature", "FeatureInfo") load(":flags.bzl", "UNFILTERED_COMPILE_FLAGS", "DEFAULT_COMPILE_FLAGS", @@ -477,6 +478,9 @@ def _impl(ctx): gcc_coverage_map_format_feature, ] + extra_rules_based_features = depset(ctx.attr.extra_enabled_features + ctx.attr.extra_known_features) + features.extend([convert_feature(extra_feature[FeatureInfo], enabled = extra_feature in ctx.attr.extra_enabled_features) for extra_feature in extra_rules_based_features.to_list()]) + cxx_builtin_include_directories = [ "/proc/self/cwd/{}".format(include_directory.path) for include_directory in ctx.files.cxx_builtin_include_directories @@ -515,5 +519,23 @@ cc_toolchain_config = rule( "target_cpu": attr.string(mandatory = True), "target_os": attr.string(mandatory = True), "cxx_builtin_include_directories": attr.label(allow_files = True, mandatory = True), + "extra_enabled_features": attr.label_list( + providers = [FeatureInfo], + default = [], + doc = """ +Extra `cc_feature` features to add to this toolchain in an initially enabled state. +This attribute has limited integration with `cc_feature`, and does not run additional correctness checks or handle things like `data` files. +This is only offered as a migration bridge for projects transitioning to rule-based toolchain configurations, or sharing of simple argument sets with older toolchains. +""", + ), + "extra_known_features": attr.label_list( + providers = [FeatureInfo], + default = [], + doc = """ +Extra `cc_feature` features to add to this toolchain in an initially disabled state. +This attribute has limited integration with `cc_feature`, and does not run additional correctness checks or handle things like `data` files. +This is only offered as a migration bridge for projects transitioning to rule-based toolchain configurations, or sharing of simple argument sets with older toolchains. +""", + ), }, )