Ever since Swift gained the ability to control warnings via diagnostic groups in SE-0443, we’ve been able to promote specific diagnostic groups to errors.

However, passing these flags via copts on swift_library targets isn’t always convenient. To apply them globally, we’d either need to modify every swift_library target, pass them via the command line, configure them in .bazelrc, or use Bazel macros to apply them automatically. All of these approaches have their downsides, such as accidentally applying the flags to external repositories, introducing additional complexity through macros, or making it difficult to opt out for specific targets.

In the past, I’ve written about Bazel’s features mechanism, as well as how to suppress warnings in external repositories.

Bazel feature-based approach

In rules_swift 4.2.0, we added a way to control these warnings using Bazel’s features mechanism in #1960.

Simply build a target while passing --features, like so:

bazel build //... --features=swift.werror.DeprecatedDeclaration

And all warnings belonging to the DeprecatedDeclaration diagnostic group will be reported as compiler errors.

This approach is extremely flexible, as it allows per-target control via the features attribute, repository-wide configuration via REPO.bazel, which only applies to the current Bazel repository, and, of course, configuration via the command line or .bazelrc.

Furthermore, we can take advantage of Bazel’s feature negation mechanism by prefixing feature names with -, allowing us to opt out of specific features when needed.

For example, if we’ve enabled swift.werror.DeprecatedDeclaration globally but want to opt out for a specific target, we can simply negate the feature in its features attribute:

swift_library(
    name = "legacy_library",
    srcs = ["Legacy.swift"],
    features = ["-swift.werror.DeprecatedDeclaration"],
)

This way, deprecated declaration warnings will remain warnings for legacy_library, while still being treated as errors for the rest of the project.

Conclusion

There we have it: a simple and clean way to control Swift warnings with Bazel.

P.S. I wish Swift would give us a way to suppress warnings per diagnostic group. If that ever comes to fruition, I’ll be the first to add a feature-based approach to rules_swift.