Photo by John Matychuk on Unsplash

Treat Warnings as Errors in a Swift Package

Let the Swift compiler help you keep your code clean at the package level

Michael Kiley
3 min readNov 13, 2021

--

It can be tempting to let one or two warnings slip into your codebase — after all, if they don’t actually break the code, what’s the harm, right?

Wrong!

If you allow yourself to get to the point where any new warnings are hidden among a never-ending list of existing warnings, they will no longer be providing any value to you.

And, while it is easy enough to turn on Treat Warnings as Errors from the Xcode UI for Swift apps, it would be nice to be able to apply this same safeguard to your Swift package as well, to ensure that all developers who work on it are kept in the habit of writing clean, up-to-date code.

Fortunately, the Package Description API used to define Swift packages allows us to do just that.

The API allows you to provide a swiftSettings parameter to each target that you define in the package initializer inside your Package.swift file:

static func target(
name: String,
dependencies: [Target.Dependency] = [],
path: String? = nil,
exclude: [String] = [],
sources: [String]? = nil,
resources: [Resource]? = nil,
publicHeadersPath: String? = nil,
cSettings: [CSetting]? = nil,
cxxSettings: [CXXSetting]? = nil,
swiftSettings: [SwiftSetting]? = nil,
linkerSettings: [LinkerSetting]? = nil
) -> Target

Here, swiftSettings is an array of type SwiftSetting, which is an struct with two static methods: one that lets you define your own compilation condition….

…and one that allows you to pass in any build flag as a string:

This is the one we will need to provide the necessary build flag to make the compiler treat warnings as errors. Both kinds of swiftSettings allow you to also provide a BuildSettingCondition which allows you to limit the application of your flag to specific platforms and configurations. Since we want to treat warnings as errors for all platforms and configurations, all we need to do is provide -warnings-as-errors as our flag, as shown on line 21:

Providing this configuration passes the -warnings-as-errors flag to your CompileSwiftSources command. If you want to check what is actually happening, you can access the build command log by clicking on the Report Navigator icon in the tab bar on the far left of Xcode, and then selecting your most recent build.

This will open the below view of your latest build, and clicking the stacked horizontal bars on the right of the Compile Swift source files step for your build will show you the log, including where you passed in the -warnings-as-errors flag.

But wait, unsafeFlags() seems…unsafe

The drawback of this approach is its use of unsafeFlags. Since unsafeFlags allows developers to pass in any arbitrary flag for the build, Apple limits packages that use targets with unsafeFlags so that they can’t be used as dependencies in any other Swift packages, as described in the Apple docs here.

Thanks for reading. Please comment with any questions or feedback. I love participating in the tech community — follow me on Medium above or on Twitter @11ninesofgreat if you do too!

--

--

Michael Kiley

Software developer. Mobile, serverless, voice. Knows some things, curious about all things.