Skip to content

Fix platform filter handling for binary target build files - #1600

Open
yimajo wants to merge 2 commits into
swiftlang:mainfrom
yimajo:aggregate-binary-target-platform-filters
Open

Fix platform filter handling for binary target build files#1600
yimajo wants to merge 2 commits into
swiftlang:mainfrom
yimajo:aggregate-binary-target-platform-filters

Conversation

@yimajo

@yimajo yimajo commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

For binary targets, this change removes the incorrect assert for platform filters and applies the union of the platform filters to the returned BuildFile.

Motivation

When an app uses a Swift package that depends on a binary target, running Swift Build with assertions enabled fails at the following assertion:

The issue can be reproduced with the following Package.swift:

// swift-tools-version: 6.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "MyLibrary",
    platforms: [
        .macOS(.v26),
        .iOS(.v26),
    ],
    products: [
        .library(
            name: "PackageProduct",
            targets: [
                "FeatureMacOS",
            ]
        ),
        .library(
            name: "PackageProductMacOSAndIOS",
            targets: [
                "FeatureIOS",
            ]
        ),
    ],
    targets: [
        // MARK: -
        .target(
            name: "FeatureIOS",
            dependencies: [
                .target(
                    name: "GoogleAppMeasurement",
                    condition: .when(platforms: [.iOS, .macOS])
                ),
            ]
        ),

        .target(
            name: "FeatureMacOS",
            dependencies: [
                .target(
                    name: "GoogleAppMeasurement",
                    condition: .when(platforms: [.macOS])
                ),
            ]
        ),

        .binaryTarget(
            name: "GoogleAppMeasurement",
            url: "https://dl.google.com/firebase/ios/swiftpm/12.17.0/GoogleAppMeasurement.zip",
            checksum: "5bf58d72ecbb6a84e0a64f8557c4488f7812c1742d409eb712033bc7edc95992"
        ),
    ],
    swiftLanguageModes: [.v6]
)

The issue can be reproduced by linking both package products from an app.

A target that depends on a binary target can specify platform conditions using .when(platforms:). SwiftPM carries these conditions as platformFilters on the corresponding BuildFiles.

In this example, the same binary target is reached through two package products with different platform filters. Both dependency paths participate in a macOS build, so aggregatedPlatformFilters is nonempty and the assertion fails.

Changes

Removing assert(aggregatedPlatformFilters.isEmpty) is sufficient to prevent the assertion failure. However, returning firstBuildFile unchanged would preserve only one set of platform filters and discard the aggregated union.

This change:

  • Removes assert(aggregatedPlatformFilters.isEmpty).
  • Applies aggregatedPlatformFilters to the returned BuildFile for binary targets.
  • Preserves assert(aggregatedBuildConfigurationFilters.isEmpty), because SwiftPM does not support conditionalizing a binary-target dependency by build configuration.
  • Rewrites the BuildableItem branching as a switch.
  • Keeps returning firstBuildFile if a .targetProduct cannot be resolved, while using assertionFailure to report the violated invariant when assertions are enabled.

Testing

Added SwiftPackageCopyFilesTaskProducerTests.packageBinaryXCFrameworkPlatformFiltersAreAggregated().

The test verifies that SwiftPackageCopyFilesTaskProducer.buildFilesForPackages(context:frameworksBuildPhase:) returns a BuildFile containing the union of the macOS, iOS, and iOS Simulator platform filters.

@yimajo

yimajo commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@swift-ci test

@owenv owenv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. This looks good to me, but I think we should future proof build configuration filters too to avoid a similar regression in the future

)
case .reference, .namedReference:
// Binary targets do not support build configuration filters.
assert(aggregatedBuildConfigurationFilters.isEmpty)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent is that eventually binary targets could condition on build configuration as well, so I think we should drop this assert at the same time to future proof things.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify, do you mean that I should only remove the assertion for now, or also apply aggregatedBuildConfigurationFilters to the returned BuildFile by extending with(...) as follows?

 case .reference, .namedReference:
-    // Binary targets do not support build configuration filters.
-    assert(aggregatedBuildConfigurationFilters.isEmpty)
     return firstBuildFile.with(
-        platformFilters: aggregatedPlatformFilters
+        platformFilters: aggregatedPlatformFilters,
+        buildConfigurationFilters: aggregatedBuildConfigurationFilters
     )

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should extend with and also use the aggregatedBuildConfigurationFilters, so the two types of filters are handled consistently

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback. I’ve updated the implementation to aggregate build configuration filters as well and updated the test accordingly.

@owenv

owenv commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@swift-ci test

@owenv

owenv commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@yimajo By the way, if you're interested in getting CI access to start tests yourself, there's some information about that in https://www.swift.org/contributing/#contributing-code (the "Member" section) if you're not already aware. I think you probably qualify based on the PRs you've been submitting here.

@yimajo
yimajo force-pushed the aggregate-binary-target-platform-filters branch from 0449e51 to 43bd44c Compare August 7, 2026 05:25
@yimajo
yimajo requested a review from owenv August 7, 2026 06:49
@owenv

owenv commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

@swift-ci test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants