SE-0273: Configuration conditionals for target dependencies: time to finish the job?

Hey everyone,

Recently I was trying to add a debug-only dependency to a package target, which is something that comes up in practically every project, something I'd expect to be straightforward, only to discover that while target dependencies do support conditions, those conditions can only be platform- or trait-based, not configuration-based. That sent me digging into SE-0273 (Package Manager Conditional Target Dependencies), where I noticed something interesting: the proposal was accepted and implemented back in 2020, but configuration conditionals never made it in, as reflected in its current status: Partially implemented (Swift 5.3 supports platform conditionals, but not configuration conditionals). From what I can tell, the original blocker no longer exists (more on that below), and 2026 seems like a great time to finally close the gap.

Why it was blocked

PR #2428 actually implemented configuration-based conditionals at the build plan level, but got stuck on one specific problem: Xcode projects and generate-xcodeproj along with it, had no way to conditionalize target dependencies by configuration. So it was decided to shelve the feature for better times.

Why that blocker is gone

Well, better times are here. generate-xcodeproj was removed 2 years later in August 2022 alongside Swift 5.7 (PR #5748) since Xcode now integrates SPM packages natively, so the original reason for not shipping configuration conditionals no longer exists.

Why it matters

The original proposal actually spelled this out explicitly:

"packages may want to link against libraries only in certain configurations, for example when importing debug libraries, which do not make sense to build and link in release builds, or when importing instrumentation logic, which only make sense in release builds"

So the use case was always there: hot-reload tools, inspection libraries, debug helpers: none of these have any business being built and linked into release binaries, yet there's no clean SPM-native way to express this.

Next steps

The groundwork from PR #2428 is already there, so hopefully it's mostly a matter of picking it back up and adapting it to the current codebase. I'd love to make this happen and happy to contribute if needed, but before diving in: are there any known blockers or complications I might have missed?

12 Likes

This would need to be implemented for the new SwiftBuild build system. Mind you it may be easier there since a lot of things in the PIF interchange format between SwiftPM and SwiftBuild model the configuration explicitly.

2 Likes

Thanks for the quick response, Doug. Would some PRs be welcome here? If so, I'm thinking it would make sense to start by extending PIF on the SwiftBuild side first. A sensible name for the new property in the dependencies object might be buildConfigurationFilters (plural, since at the PIF level other clients may support more than two configurations, even though SwiftPM would always provide a single value for now), to stay consistent with the existing platformFilters. The change would be purely additive, so SwiftPM (and Xcode someday, maybe?) could adopt the new dependency configuration filter as an independent next step.

Would the new filter simply be ignored when the native build system is used? I assume it's slowly becoming legacy now that SwiftBuild has become the default.

I just had a closer look and noticed that each PIF target object already contains an array of associated buildConfigurations with two hardcoded DEBUG and RELEASE configurations. I'm wondering if making this array dynamic by filtering it based on the dependency's configuration condition would be enough to avoid any changes to the existing PIF schema, of course assuming there's no requirement that all targets within a project/workspace must have the same number of build configurations. If there's no such requirement (or other constraints), that could be quite an elegant solution. Otherwise, it would indeed require some changes at the SwiftBuild level, as you pointed out.

I’ll defer to @owenv on the SwiftBuild side.

I think something analogous to platformFilters is probably the way to go here, it's likely to scale better if SwiftPM introduces custom build configurations at some point in the future.

1 Like

Thanks, Owen! I also noticed that a third hypothetical approach would be to use the EXCLUDED_EXPLICIT_TARGET_DEPENDENCIES build setting. However, the fact that SwiftPM already went with the more structural and explicit platformFilters approach over that build setting's sdk condition (e.g. [sdk=iphoneos*]) only reinforces that an explicit buildConfigurationFilters would be the way to go, as you said. This is also probably what @dschaefer2 meant by "explicit configuration modeling between SwiftPM and SwiftBuild".

I think I now have everything I need to propose a solution draft, starting at the SwiftBuild level and then finishing from the SwiftPM side.

I’m not sure the history of EXCLUDED_EXPLICIT_TARGET_DEPENDENCIES but having played with it trying to get swift-syntax prebuilts for the HOST_PLATFORM working it feels like a workaround for something.

The dependencies have platformFilters today directly attached to them. I would think you would want build config filters there too. Or maybe we need to generalize these filters for more complicated expressions. They at least need to match any expansion of TargetDependencyCondition such as SDK and Arch/Triple conditions that people have been asking for (and that I think I need for prebuilts)

Yes, generalizing platformFilters into something like a destinationFilters enum where the user could pick a level of specificity (platform/SDK, arch, or full triple) could be a natural future API. That said, I'd argue that build configuration filtering is a fundamentally different axis from destination filtering and should remain separate from this generalization.

Agreed, but I believe that’s what Owen was implying:

1 Like

Right, I just wanted to explore your filtering generalization idea a bit to see if it might affect the upcoming PR. It doesn't look like it does, so we're on the same page.