Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 28 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,32 +28,45 @@ toolchain_gcc_dependencies()
## Configuring the toolchain to a project needs
The `score_toolchains_gcc` module currently supports only GNU GCC version **12.2.0**. Support for multiple GCC versions is planned, with future versions expected to be selectable via an extended toolchain interface. As of now, version 12.2.0 is the sole supported target.

The module exposes an API that allows consumers to enable or disable specific toolchain behaviors related to compilation diagnostics. The following features can be individually configured:
The module exposes an API that allows consumers to enable or disable specific toolchain behaviors related to compilation diagnostics.
By default, the toolchain activates the following features using predefined compiler flags:

1. Minimal warning flags — enables a basic set of compiler warnings
2. Strict warning flags — enables a more aggressive set of warnings (e.g., `-Wall, -Wextra`)
3. A `treat warnings as errors` flags — promotes all warnings to errors (e.g., `-Werror`)
1. Minimal warning flags — Enables a basic set of compiler warnings (e.g., `-Wall`) which cannot be disabled by consumers.
2. Strict warning flags — Enables a more aggressive set of warnings (e.g., `-Wextra`, `-Wpedantic`) which may be disabled by consumers if desired.
3. A `treat warnings as errors` flags — Promotes all warnings to errors using -Werror and exceptions like -Wno-error=deprecated-declarations.

These features provide fine-grained control over the compiler's warning policy. If no features are explicitly selected, the toolchain will apply no additional warning-related flags by default.
Consumers can modify features by adding or removing them in the module configuration.
To disable a feature, prefix its name with a dash (e.g., `-strict_warnings`).
However, the following features are protected and cannot be disabled:
- `minimal_warnings`
- `treat_warnings_as_errors`

When a feature is disabled, neither the default nor any user-defined flags associated with it will be applied.

Consumers can provide custom compiler warning flags through the additional_warnings feature.
This feature accepts a list of flags following any of these patterns: `-W<warning-name>`, `-Wno-<warning-name>`, and `-Wno-error=<warning-name>`.

Important restrictions:
- Warnings enabled by minimal_warnings cannot be disabled.
- Warnings enabled by -Wall cannot be disabled or converted back to non-errors.
- Attempts to use `-Wno-error` for any protected warning will fail.

To set wanted flags, the following API needs to be used:
```python
gcc = use_extension("@score_toolchains_gcc//extentions:gcc.bzl", "gcc")
gcc.extra_features(
features = [
"minimal_warnings",
"treat_warnings_as_errors",
"-strict_warnings",
"additional_warnings"
],
)
gcc.warning_flags(
minimal_warnings = ["-Wall", "-Wno-error=deprecated-declarations"],
strict_warnings = ["-Wextra", "-Wpedantic"],
treat_warnings_as_errors = ["-Werror"],
additional_warnings = ["-Wno-bool-compare"],
)
use_repo(gcc, "gcc_toolchain", "gcc_toolchain_gcc")
```
* `extra_features` - This will enable all features which are set in the list.
* `warning_flags` - This will set flags for selected features.
* `extra_features` - Enables or disables features listed by the consumer.
* `warning_flags` - Sets additional compiler flags for the feature `additional_warnings` when it is enabled.

### Using WORKSPACE file
The same approuch needs to be done when configuring toolchain over WORKSPACE file:
Expand All @@ -63,13 +76,11 @@ gcc_toolchain(
name = "gcc_toolchain",
gcc_repo = "gcc_toolchain_gcc",
extra_features = [
"minimal_warnings",
"treat_warnings_as_errors",
"-strict_warnings",
"additional_warnings",
],
warning_flags = {
"minimal_warnings": ["-Wall", "-Wno-error=deprecated-declarations"],
"strict_warnings": ["-Wextra", "-Wpedantic"],
"treat_warnings_as_errors": ["-Werror"],
"additional_warnings": ["-Wno-bool-compare"],
},
)
```
Expand Down
File renamed without changes.
153 changes: 153 additions & 0 deletions extensions/gcc.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# *******************************************************************************
# Copyright (c) 2025 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
# *******************************************************************************

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@score_toolchains_gcc//rules:gcc.bzl", "gcc_toolchain")
load("@score_toolchains_gcc//extensions:gcc_defs.bzl",
"DEFAULT_MINIMAL_WARNINGS",
"DEFAULT_STRICT_WARNINGS",
"DEFAULT_WARNINGS_AS_ERRORS",
"DEFAULT_FEATURES",
"ALL_WALL_WARNINGS",
)

def _validate_warning_flag(flag):
if not flag.startswith("-W"):
fail("Invalid warning flag: '%s'. Must start with '-W'" % flag)

if flag.startswith("-Wno-"):
warning_name = flag[5:]

for minimal_flag in DEFAULT_MINIMAL_WARNINGS:
minimal_name = minimal_flag[2:]
if minimal_name == warning_name or minimal_flag == flag:
fail("Cannot disable minimal warning '%s' using '%s'" % (minimal_flag, flag))

for wall_flag in ALL_WALL_WARNINGS:
wall_name = wall_flag[2:]
if wall_name == warning_name or wall_flag == flag:
fail("Cannot disable -Wall warning '%s' using '%s'" % (wall_flag, flag))

if flag.startswith("-Wno-error"):
if "=" in flag:
warning_name = flag.split("=", 1)[1]
for minimal_flag in DEFAULT_MINIMAL_WARNINGS:
if minimal_flag[2:] == warning_name:
fail("Cannot convert minimal warning '%s' back to non-error using '%s'" % (minimal_flag, flag))
for wall_flag in ALL_WALL_WARNINGS:
if wall_flag[2:] == warning_name:
fail("Cannot convert -Wall warning '%s' back to non-error using '%s'" % (wall_flag, flag))
else:
fail("Cannot disable all errors using '%s' because minimal and -Wall warnings must remain errors" % flag)

return True


def _gcc_impl(mctx):
"""Implementation of the module extension."""

for mod in mctx.modules:
if not mod.is_root:
fail("Only the root module can use the 'gcc' extension")

toolchain_info = None
features = list(DEFAULT_FEATURES)
warning_flags = {
"minimal_warnings": list(DEFAULT_MINIMAL_WARNINGS),
"strict_warnings": list(DEFAULT_STRICT_WARNINGS),
"treat_warnings_as_errors": list(DEFAULT_WARNINGS_AS_ERRORS),
"additional_warnings": [],
}

for mod in mctx.modules:
for tag in mod.tags.toolchain:
toolchain_info = {
"name": tag.name,
"url": tag.url,
"strip_prefix": tag.strip_prefix,
"sha256": tag.sha256,
}

for tag in mod.tags.extra_features:
for feature in tag.features:
f = feature.strip()
if not f:
continue
if f.startswith("-"):
remove_feature = f[1:].strip()
if remove_feature == "minimal_warnings":
fail("'minimal_warnings' feature is protected and cannot be disabled")

if remove_feature == "treat_warnings_as_errors":
fail("'treat_warnings_as_errors' feature is protected and cannot be disabled")

if remove_feature in features:
features.remove(remove_feature)
else:
if f not in features:
features.append(f)

for tag in mod.tags.warning_flags:
for flag in tag.additional_warnings:
_validate_warning_flag(flag)
if flag not in warning_flags["additional_warnings"]:
warning_flags["additional_warnings"].append(flag)

if toolchain_info:
http_archive(
name = "%s_gcc" % toolchain_info["name"],
urls = [toolchain_info["url"]],
build_file = "@score_toolchains_gcc//toolchain/third_party:gcc.BUILD",
sha256 = toolchain_info["sha256"],
strip_prefix = toolchain_info["strip_prefix"],
)

gcc_toolchain(
name = toolchain_info["name"],
gcc_repo = "%s_gcc" % toolchain_info["name"],
extra_features = features,
warning_flags = warning_flags,
)

else:
fail("Cannot create gcc toolchain repository, some info is missing!")

gcc = module_extension(
implementation = _gcc_impl,
tag_classes = {
"toolchain": tag_class(
attrs = {
"name": attr.string(doc = "Same name as the toolchain tag.", default="gcc_toolchain"),
"url": attr.string(doc = "Url to the toolchain package."),
"strip_prefix": attr.string(doc = "Strip prefix from toolchain package.", default=""),
"sha256": attr.string(doc = "Checksum of the package"),
},
),
"warning_flags": tag_class(
attrs = {
"additional_warnings": attr.string_list(
doc = "List of additional warning flags. Patterns: '-W<warning-name>', '-Wno-error=<warning-name>'. Cannot use '-Wno-' to disable warnings from DEFAULT_MINIMAL_WARNINGS.",
default = [],
),
},
),
"extra_features": tag_class(
attrs = {
"features": attr.string_list(
doc = "List of extra compiler and linker features. Use '-strict_warnings' to disable strict warnings (minimal_warnings and treat_warnings_as_errors cannot be disabled).",
default = [],
),
},
),
}
)
152 changes: 152 additions & 0 deletions extensions/gcc_defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# *******************************************************************************
# Copyright (c) 2025 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
# *******************************************************************************
DEFAULT_MINIMAL_WARNINGS = [
"-Wall",
"-Wundef",
"-Wwrite-strings",
"-Wpointer-arith",
"-Wcast-align",
"-Wredundant-decls",
"-Wreturn-local-addr",
"-Wcast-qual",
"-Wbad-function-cast",
"-Wodr",
"-Wsizeof-array-argument",
"-Wformat=2",
"-Wmissing-format-attribute",
"-Wformat-nonliteral",
"-Wformat-signedness",
"-Wmissing-prototypes",
"-Wreorder"
]


# According to https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html,
# the `-Wall` option in GCC enables a set of warnings by default.
# The following list represents all warnings enabled by `-Wall`,
# This list is used ONLY for validation (to prevent disabling important warnings), not for direct compilation.
# For compilation, we use a smaller curated MINIMAL_WARNINGS list.

ALL_WALL_WARNINGS = [
"-Waddress",
"-Waligned-new",
"-Warray-bounds=1",
"-Warray-compare",
"-Warray-parameter=2",
"-Wbool-compare",
"-Wbool-operation",
"-Wc++11-compat",
"-Wc++14-compat",
"-Wc++17-compat",
"-Wc++20-compat",
"-Wcatch-value",
"-Wchar-subscripts",
"-Wclass-memaccess",
"-Wcomment",
"-Wdangling-else",
"-Wdangling-pointer=2",
"-Wdelete-non-virtual-dtor",
"-Wduplicate-decl-specifier",
"-Wenum-compare",
"-Wenum-int-mismatch",
"-Wformat=1",
"-Wformat-contains-nul",
"-Wformat-diag",
"-Wformat-extra-args",
"-Wformat-overflow=1",
"-Wformat-truncation=1",
"-Wformat-zero-length",
"-Wframe-address",
"-Wimplicit",
"-Wimplicit-function-declaration",
"-Wimplicit-int",
"-Winfinite-recursion",
"-Winit-self",
"-Wint-in-bool-context",
"-Wlogical-not-parentheses",
"-Wmain",
"-Wmaybe-uninitialized",
"-Wmemset-elt-size",
"-Wmemset-transposed-args",
"-Wmisleading-indentation",
"-Wmismatched-dealloc",
"-Wmismatched-new-delete",
"-Wmissing-attributes",
"-Wmissing-braces",
"-Wmultistatement-macros",
"-Wnarrowing",
"-Wnonnull",
"-Wnonnull-compare",
"-Wopenmp-simd",
"-Woverloaded-virtual=1",
"-Wpacked-not-aligned",
"-Wparentheses",
"-Wpessimizing-move",
"-Wpointer-sign",
"-Wrange-loop-construct",
"-Wreorder",
"-Wrestrict",
"-Wreturn-type",
"-Wself-move",
"-Wsequence-point",
"-Wsign-compare",
"-Wsizeof-array-div",
"-Wsizeof-pointer-div",
"-Wsizeof-pointer-memaccess",
"-Wstrict-aliasing",
"-Wstrict-overflow=1",
"-Wswitch",
"-Wtautological-compare",
"-Wtrigraphs",
"-Wuninitialized",
"-Wunknown-pragmas",
"-Wunused",
"-Wunused-but-set-variable",
"-Wunused-const-variable=1",
"-Wunused-function",
"-Wunused-label",
"-Wunused-local-typedefs",
"-Wunused-value",
"-Wunused-variable",
"-Wuse-after-free=2",
"-Wvla-parameter",
"-Wvolatile-register-var",
"-Wzero-length-bounds",
]

DEFAULT_STRICT_WARNINGS = [
"-Wextra",
"-Wpedantic",
"-Wswitch-bool",
"-Wconversion",
"-Wlogical-op",
"-Wunused-but-set-parameter",
"-Wlogical-not-parentheses",
"-Wbool-compare",
"-Winvalid-pch",
"-Wvla",
"-Wuseless-cast",
"-Wdouble-promotion",
"-Wnarrowing"
]

DEFAULT_WARNINGS_AS_ERRORS = [
"-Werror",
"-Wno-error=deprecated-declarations",
]

DEFAULT_FEATURES = [
"minimal_warnings",
"strict_warnings",
"treat_warnings_as_errors",
]
Loading