Skip to content

Filter out SwiftPM schemes when fetching schemes#186006

Merged
auto-submit[bot] merged 11 commits into
flutter:masterfrom
lukemmtt:fix-watch-companion-swiftpm-scheme-scan
May 22, 2026
Merged

Filter out SwiftPM schemes when fetching schemes#186006
auto-submit[bot] merged 11 commits into
flutter:masterfrom
lukemmtt:fix-watch-companion-swiftpm-scheme-scan

Conversation

@lukemmtt

@lukemmtt lukemmtt commented May 4, 2026

Copy link
Copy Markdown
Contributor

Summary

In iOS projects with a watchOS companion target and Swift Package Manager enabled, IosProject.containsWatchCompanion() has a fallback path for modern Xcode projects where the companion relationship is declared through INFOPLIST_KEY_WKCompanionAppBundleIdentifier in project.pbxproj, rather than as a literal WKCompanionAppBundleIdentifier key in the watch target Info.plist.

That fallback iterates projectInfo.schemes and runs:

xcodebuild -showBuildSettings -destination generic/platform=watchOS

for each non-default scheme until it finds the watch companion scheme.

With SwiftPM enabled, xcodebuild -list can include schemes for direct Flutter plugin packages and transitive Swift packages, such as advertising-id, amplitude-flutter, Amplitude-Swift, RevenueCatUI, and SuperwallKit. Those schemes cannot be the host project's watch companion, but each failed watchOS build-settings probe can take multiple seconds.

This PR filters those non-host schemes earlier, in XcodeProjectInterpreter.getInfo(), before they become part of XcodeProjectInfo.schemes.

The current filter excludes:

  • FlutterGeneratedPluginSwiftPackage
  • FlutterFramework
  • plugin names from xcodeProject.getPlugins()
  • dashed and capitalized plugin-name variants, e.g. cloud_firestore, cloud-firestore, Cloud-firestore
  • transitive SwiftPM package schemes found under build/ios/SourcePackages/checkouts/*/.swiftpm/xcode/xcshareddata/xcschemes/*.xcscheme

I also removed the earlier shared-scheme-location filter from containsWatchCompanion(). That earlier approach was present in 0cfdd3a67c2, but it could skip valid non-shared host schemes. The current approach keeps the fallback behavior scheme-based while removing known SwiftPM package schemes from the candidate list.

Fixes #186004.

Measurements

Test project: TimeFinder app.

Command:

flutter build ios --debug --simulator --no-pub -v

Benchmark condition for fallback rows: the literal WKCompanionAppBundleIdentifier key was removed from the watch target Info.plist, while the modern INFOPLIST_KEY_WKCompanionAppBundleIdentifier entries remained in project.pbxproj.

Scenario Unique watchOS probes before detection Time to detection, 3 trials Median Fallback scan only, 3 trials Median
Literal plist key present, no fallback 0 92.8s, 70.0s, 70.9s 70.9s n/a n/a
Unpatched baseline, no plist key 60 244.2s, 235.4s, 238.9s 238.9s 174.1s, 170.8s, 165.6s 170.8s
Earlier shared-scheme approach, no plist key 5 90.2s, 89.8s, 87.7s 89.8s 16.9s, 21.0s, 17.6s 17.6s
Current PR, no plist key 3 85.3s, 80.7s, 83.3s 83.3s 12.5s, 11.5s, 11.8s 11.8s

In this project, Xcode listed 67 schemes. The current filter reduced that to 6 retained schemes, and the fallback reached TimeFinderWatchApp after probing only:

  • LiveActivityWidgetExtension
  • ScheduleWidgetExtension
  • TimeFinderWatchApp

It did not probe direct plugin schemes or transitive SwiftPM package schemes, including Patrol, Amplitude-Swift, RevenueCatUI, RevenueCatUITests, or SuperwallKit.

Worth noting: TimeFinder is a worst-case-ish benchmark project for this issue: it has many SwiftPM package schemes, and xcodebuild -list returns schemes alphabetically here, so TimeFinderWatchApp is near the end of the candidate sequence. A project with a watch scheme that sorts early, such as AAAWatchApp, would see far less baseline overhead and therefore less benefit from this PR.

Test Plan

  • flutter test test/general.shard/ios/xcodeproj_test.dart
  • flutter test test/general.shard/project_test.dart --plain-name 'watch companion'
  • flutter analyze in packages/flutter_tools
  • git diff --check

@lukemmtt lukemmtt requested review from a team as code owners May 4, 2026 19:01
@github-actions github-actions Bot added tool Affects the "flutter" command-line tool. See also t: labels. team-ios Owned by iOS platform team team-macos Owned by the macOS platform team labels May 4, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request implements a filtering mechanism for Xcode schemes to skip Swift Package Manager schemes, reducing the time spent probing for watchOS companion targets. It verifies the existence of an .xcscheme file in the host project's shared schemes directory. Tests were updated to reflect this requirement and a new test case was added. Feedback indicates that the current implementation may skip valid schemes in workspaces or those not marked as shared.

Comment thread packages/flutter_tools/lib/src/xcode_project.dart Outdated
@lukemmtt lukemmtt changed the title Skip non-host schemes in watch companion fallback to avoid SwiftPM scan Skip schemes outside Runner.xcodeproj when detecting watch companion May 4, 2026
@LouiseHsu LouiseHsu added the CICD Run CI/CD label May 5, 2026
@vashworth vashworth self-requested a review May 5, 2026 17:36
Comment thread packages/flutter_tools/lib/src/xcode_project.dart Outdated
@vashworth vashworth added the waiting for response The Flutter team cannot make further progress on this issue until the original reporter responds label May 12, 2026
@vashworth

Copy link
Copy Markdown
Contributor

@lukemmtt Do you think this is something you have bandwidth for sometime this week or next? If not, I'll have my team take over so we can get this fixed ASAP. Let me know :)

@lukemmtt

Copy link
Copy Markdown
Contributor Author

Thanks for the note! Yes, I'll take a stab at it today and let you know :)

@github-actions github-actions Bot removed the waiting for response The Flutter team cannot make further progress on this issue until the original reporter responds label May 13, 2026
@okorohelijah okorohelijah self-requested a review May 13, 2026 20:52
lukemmtt added 3 commits May 13, 2026 16:54
In iOS projects with a watchOS companion target and Swift Package Manager enabled, IosProject.containsWatchCompanion()'s fallback path iterates every entry in projectInfo.schemes and runs xcodebuild -showBuildSettings -destination generic/platform=watchOS for each one. With SwiftPM, that list contains a scheme per resolved package and plugin, none of which can be a watch companion. Each probe takes ~2-3 seconds, so on a real project this added ~160s (60 probes) before the actual build started.

This change restricts the fallback to schemes that have an .xcscheme file under the host Xcode project's xcshareddata/xcschemes/ directory, so SwiftPM package schemes are skipped without an xcodebuild call.

Fixes flutter#186004
Addresses review feedback: the previous filter only checked
Runner.xcodeproj/xcshareddata/xcschemes, which would falsely skip
projects whose watch scheme is shared at the workspace level
(Runner.xcworkspace/xcshareddata/xcschemes) instead.

The host-shared check now passes when an .xcscheme file exists in
either the project's or the workspace's xcshareddata/xcschemes
directory. SwiftPM package schemes still appear in neither, so they
continue to be skipped.

Adds a test that places the scheme only at the workspace level and
asserts that containsWatchCompanion finds it.
Moves SwiftPM scheme filtering into XcodeProjectInterpreter.getInfo so callers receive an XcodeProjectInfo that excludes Flutter-generated Swift package schemes, direct plugin scheme names, plugin dash variants, and transitive Swift package schemes discovered under SourcePackages checkouts.

This keeps watch companion detection from probing SwiftPM package schemes while avoiding a host .xcscheme file requirement for valid non-shared project schemes.

Adds getInfo coverage for direct plugin schemes and transitive .swiftpm schemes, and restores watch companion tests to exercise generic non-default scheme probing.
@lukemmtt lukemmtt force-pushed the fix-watch-companion-swiftpm-scheme-scan branch from 28d6b49 to f9975fc Compare May 13, 2026 20:54
@github-actions github-actions Bot added platform-ios iOS applications specifically and removed CICD Run CI/CD labels May 13, 2026
@lukemmtt

Copy link
Copy Markdown
Contributor Author

Thanks again for the heads-up about #186378 landing; I’ve now rebased onto the latest main, force-pushed, and revisited this approach as follows:

The filtering logic has been moved earlier, into XcodeProjectInterpreter.getInfo(). It now excludes:

  • Default Flutter schemes (FlutterGeneratedPluginSwiftPackage, FlutterFramework)
  • Plugin schemes from xcodeProject.getPlugins() (as well as dashed and capitalized variants)
  • Transitive SwiftPM package schemes under SourcePackages/checkouts/*/.swiftpm/*

I’ve also removed the earlier shared-scheme filter from containsWatchCompanion(), so valid non-shared host schemes won’t be accidentally skipped.

Local testing against my TimeFinder app showed the scheme count reduced significantly as expected (67 → 6), and correctly detecting the watch companion (TimeFinderWatchApp) without probing unrelated plugin schemes (Patrol, Amplitude-Swift, etc).

Happy to address any needed revisions as quickly as I can. Thanks for the attention to this Victoria!

@lukemmtt lukemmtt changed the title Skip schemes outside Runner.xcodeproj when detecting watch companion Filter SwiftPM schemes when detecting watch companion May 14, 2026

@vashworth vashworth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks really great! Thanks for working on it! I think it just needs some doc comments and then should be good to go

Comment thread packages/flutter_tools/lib/src/ios/xcodeproj.dart
Comment thread packages/flutter_tools/lib/src/ios/xcodeproj.dart Outdated
Comment thread packages/flutter_tools/lib/src/ios/xcodeproj.dart Outdated
Comment thread packages/flutter_tools/lib/src/ios/xcodeproj.dart
@vashworth vashworth added the CICD Run CI/CD label May 15, 2026
lukemmtt added 3 commits May 18, 2026 16:32
Compare schemes parsed from `xcodebuild -list` against ignored scheme candidates case-insensitively instead of generating sentence-cased plugin variants. The ignored set still enumerates known plugin spellings (`snake_case` and dashed), while casing is handled at lookup time.

Add comments explaining why the watch companion fallback excludes generated Flutter SwiftPM package schemes, plugin scheme-name candidates, and schemes contributed by transitive SwiftPM checkouts. Addresses review feedback on flutter#186006.
@github-actions github-actions Bot removed the CICD Run CI/CD label May 18, 2026
@lukemmtt

Copy link
Copy Markdown
Contributor Author

Thanks for the thoughtful review @vashworth; I believe I've addressed all the comments. Let me know if you have any other suggestions. Thank you!

@hellohuanlin hellohuanlin added the autosubmit Merge PR when tree becomes green via auto submit App label May 21, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label May 22, 2026
@okorohelijah okorohelijah added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App and removed autosubmit Merge PR when tree becomes green via auto submit App labels May 22, 2026
@auto-submit auto-submit Bot added this pull request to the merge queue May 22, 2026
Merged via the queue into flutter:master with commit cc7a86d May 22, 2026
167 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label May 22, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request May 26, 2026
Roll Flutter from e03b91f1fe34 to f3a4b9897834 (63 revisions)

flutter/flutter@e03b91f...f3a4b98

2026-05-26 47866232+chunhtai@users.noreply.github.com Update batch release doc to reflect latest workflow (flutter/flutter#186979)
2026-05-26 engine-flutter-autoroll@skia.org Roll Skia from 0442274cc696 to 27a819894f7c (5 revisions) (flutter/flutter#187094)
2026-05-26 bkonyi@google.com [Tool Robustness] Gracefully handle asynchronous subprocess crashes and connection timeouts (flutter/flutter#186964)
2026-05-26 bkonyi@google.com [pubspec] Bump Dart SDK constraint to ^3.13.0 (flutter/flutter#186957)
2026-05-26 engine-flutter-autoroll@skia.org Roll Dart SDK from 7eb54169841d to 00e625453c43 (1 revision) (flutter/flutter#187086)
2026-05-26 bdero@google.com [Impeller] Retire Y-coord-scale plumbing by flipping GLES at the vertex stage (flutter/flutter#186556)
2026-05-26 engine-flutter-autoroll@skia.org Roll Skia from f4f294bdf98d to 0442274cc696 (2 revisions) (flutter/flutter#187079)
2026-05-26 kevmoo@users.noreply.github.com [flutter_tools] Fix version cache poisoning from git environment variables (flutter/flutter#186595)
2026-05-26 bkonyi@google.com [Tool] Handle DTD connection failures gracefully in widget-preview (flutter/flutter#186952)
2026-05-25 engine-flutter-autoroll@skia.org Roll Skia from 9d1adb5f2427 to f4f294bdf98d (1 revision) (flutter/flutter#187056)
2026-05-25 engine-flutter-autoroll@skia.org Roll Skia from 4dd78179e6ec to 9d1adb5f2427 (1 revision) (flutter/flutter#187048)
2026-05-25 engine-flutter-autoroll@skia.org Roll Skia from 1f26101197bf to 4dd78179e6ec (4 revisions) (flutter/flutter#187044)
2026-05-24 engine-flutter-autoroll@skia.org Roll Skia from bbe9ccc2bdbf to 1f26101197bf (1 revision) (flutter/flutter#187016)
2026-05-24 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from nsgcNDlZOuweOvy3Q... to Itd2Jq_ZIABH2rW7B... (flutter/flutter#187032)
2026-05-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 7e0f28eb5315 to 7eb54169841d (1 revision) (flutter/flutter#187005)
2026-05-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 90e55fa88456 to 7e0f28eb5315 (1 revision) (flutter/flutter#186990)
2026-05-23 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from 6T6BY9PTftoG3vP_1... to nsgcNDlZOuweOvy3Q... (flutter/flutter#186984)
2026-05-23 chris@bracken.jp iOS] Migrate VSyncClient to a pure Obj-C implementation (#186166) (flutter/flutter#186935)
2026-05-23 30870216+gaaclarke@users.noreply.github.com Disables embedder_tests.cm for fuchsia (flutter/flutter#186969)
2026-05-23 engine-flutter-autoroll@skia.org Roll Dart SDK from b8414c46f6c7 to 90e55fa88456 (2 revisions) (flutter/flutter#186977)
2026-05-22 engine-flutter-autoroll@skia.org Roll Skia from 6fdb013d1953 to bbe9ccc2bdbf (1 revision) (flutter/flutter#186980)
2026-05-22 mdebbar@google.com [web] Fix cutoff text in WebParagraph (flutter/flutter#186819)
2026-05-22 1961493+harryterkelsen@users.noreply.github.com fix(web): Removes the iterative downscaling hack (flutter/flutter#186914)
2026-05-22 30870216+gaaclarke@users.noreply.github.com opts the linux embedder into sdf rendering (flutter/flutter#186909)
2026-05-22 engine-flutter-autoroll@skia.org Roll Skia from dae8778ca40d to 6fdb013d1953 (5 revisions) (flutter/flutter#186970)
2026-05-22 dacoharkes@google.com Fix hooks inputs outputs rebuilt (flutter/flutter#186701)
2026-05-22 30870216+gaaclarke@users.noreply.github.com adds linux impeller integration test for external textures (flutter/flutter#186759)
2026-05-22 kevmoo@users.noreply.github.com fix(flutter_tools): defensively catch DWDS unregistered service extension errors (flutter/flutter#186896)
2026-05-22 bdero@google.com [Impeller] Add golden harness support to the renderer test layer (flutter/flutter#186735)
2026-05-22 mdebbar@google.com [web] Remove image codecs from canvaskit_chromium (flutter/flutter#178133)
2026-05-22 30870216+gaaclarke@users.noreply.github.com opts all macos into wide gamut (flutter/flutter#186277)
2026-05-22 engine-flutter-autoroll@skia.org Roll Skia from 356185490a75 to dae8778ca40d (9 revisions) (flutter/flutter#186949)
2026-05-22 1598289+lukemmtt@users.noreply.github.com Filter out SwiftPM schemes when fetching schemes (flutter/flutter#186006)
2026-05-22 engine-flutter-autoroll@skia.org Roll Packages from 3754d04 to 69cf959 (1 revision) (flutter/flutter#186950)
2026-05-22 engine-flutter-autoroll@skia.org Roll Dart SDK from eca46bec956d to b8414c46f6c7 (2 revisions) (flutter/flutter#186944)
2026-05-22 30870216+gaaclarke@users.noreply.github.com Saves a DeviceHolderVK with the CommandPoolVK (flutter/flutter#186749)
2026-05-22 engine-flutter-autoroll@skia.org Roll Dart SDK from e0d509fd676e to eca46bec956d (1 revision) (flutter/flutter#186922)
2026-05-22 bkonyi@google.com [ Tool ] Stop generating widget preview scaffold under $TMP (flutter/flutter#186476)
2026-05-21 737941+loic-sharma@users.noreply.github.com Fix typo in StretchingOverscrollIndicator docs (flutter/flutter#186897)
2026-05-21 engine-flutter-autoroll@skia.org Roll Dart SDK from 28c7cb5a8e8d to e0d509fd676e (1 revision) (flutter/flutter#186903)
2026-05-21 jason-simmons@users.noreply.github.com Fix some issues in the integration between EmbedderExternalViewEmbedder and Impeller (flutter/flutter#184905)
2026-05-21 jason-simmons@users.noreply.github.com Fix a potential buffer overflow in the animated PNG decoder when parsing malformed fdAT chunks (flutter/flutter#186700)
2026-05-21 engine-flutter-autoroll@skia.org Roll Skia from 2ff20950975d to 356185490a75 (5 revisions) (flutter/flutter#186892)
2026-05-21 flar@google.com Add primitive shadows to rendering benchmark (flutter/flutter#186779)
2026-05-21 15619084+vashworth@users.noreply.github.com Move prefetchSwiftPackages to be per platform (flutter/flutter#186468)
2026-05-21 okorohelijah@google.com Upgrade iOS version (flutter/flutter#186889)
...
creatorpiyush pushed a commit to creatorpiyush/packages that referenced this pull request Jun 10, 2026
…r#11789)

Roll Flutter from e03b91f1fe34 to f3a4b9897834 (63 revisions)

flutter/flutter@e03b91f...f3a4b98

2026-05-26 47866232+chunhtai@users.noreply.github.com Update batch release doc to reflect latest workflow (flutter/flutter#186979)
2026-05-26 engine-flutter-autoroll@skia.org Roll Skia from 0442274cc696 to 27a819894f7c (5 revisions) (flutter/flutter#187094)
2026-05-26 bkonyi@google.com [Tool Robustness] Gracefully handle asynchronous subprocess crashes and connection timeouts (flutter/flutter#186964)
2026-05-26 bkonyi@google.com [pubspec] Bump Dart SDK constraint to ^3.13.0 (flutter/flutter#186957)
2026-05-26 engine-flutter-autoroll@skia.org Roll Dart SDK from 7eb54169841d to 00e625453c43 (1 revision) (flutter/flutter#187086)
2026-05-26 bdero@google.com [Impeller] Retire Y-coord-scale plumbing by flipping GLES at the vertex stage (flutter/flutter#186556)
2026-05-26 engine-flutter-autoroll@skia.org Roll Skia from f4f294bdf98d to 0442274cc696 (2 revisions) (flutter/flutter#187079)
2026-05-26 kevmoo@users.noreply.github.com [flutter_tools] Fix version cache poisoning from git environment variables (flutter/flutter#186595)
2026-05-26 bkonyi@google.com [Tool] Handle DTD connection failures gracefully in widget-preview (flutter/flutter#186952)
2026-05-25 engine-flutter-autoroll@skia.org Roll Skia from 9d1adb5f2427 to f4f294bdf98d (1 revision) (flutter/flutter#187056)
2026-05-25 engine-flutter-autoroll@skia.org Roll Skia from 4dd78179e6ec to 9d1adb5f2427 (1 revision) (flutter/flutter#187048)
2026-05-25 engine-flutter-autoroll@skia.org Roll Skia from 1f26101197bf to 4dd78179e6ec (4 revisions) (flutter/flutter#187044)
2026-05-24 engine-flutter-autoroll@skia.org Roll Skia from bbe9ccc2bdbf to 1f26101197bf (1 revision) (flutter/flutter#187016)
2026-05-24 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from nsgcNDlZOuweOvy3Q... to Itd2Jq_ZIABH2rW7B... (flutter/flutter#187032)
2026-05-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 7e0f28eb5315 to 7eb54169841d (1 revision) (flutter/flutter#187005)
2026-05-23 engine-flutter-autoroll@skia.org Roll Dart SDK from 90e55fa88456 to 7e0f28eb5315 (1 revision) (flutter/flutter#186990)
2026-05-23 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from 6T6BY9PTftoG3vP_1... to nsgcNDlZOuweOvy3Q... (flutter/flutter#186984)
2026-05-23 chris@bracken.jp iOS] Migrate VSyncClient to a pure Obj-C implementation (#186166) (flutter/flutter#186935)
2026-05-23 30870216+gaaclarke@users.noreply.github.com Disables embedder_tests.cm for fuchsia (flutter/flutter#186969)
2026-05-23 engine-flutter-autoroll@skia.org Roll Dart SDK from b8414c46f6c7 to 90e55fa88456 (2 revisions) (flutter/flutter#186977)
2026-05-22 engine-flutter-autoroll@skia.org Roll Skia from 6fdb013d1953 to bbe9ccc2bdbf (1 revision) (flutter/flutter#186980)
2026-05-22 mdebbar@google.com [web] Fix cutoff text in WebParagraph (flutter/flutter#186819)
2026-05-22 1961493+harryterkelsen@users.noreply.github.com fix(web): Removes the iterative downscaling hack (flutter/flutter#186914)
2026-05-22 30870216+gaaclarke@users.noreply.github.com opts the linux embedder into sdf rendering (flutter/flutter#186909)
2026-05-22 engine-flutter-autoroll@skia.org Roll Skia from dae8778ca40d to 6fdb013d1953 (5 revisions) (flutter/flutter#186970)
2026-05-22 dacoharkes@google.com Fix hooks inputs outputs rebuilt (flutter/flutter#186701)
2026-05-22 30870216+gaaclarke@users.noreply.github.com adds linux impeller integration test for external textures (flutter/flutter#186759)
2026-05-22 kevmoo@users.noreply.github.com fix(flutter_tools): defensively catch DWDS unregistered service extension errors (flutter/flutter#186896)
2026-05-22 bdero@google.com [Impeller] Add golden harness support to the renderer test layer (flutter/flutter#186735)
2026-05-22 mdebbar@google.com [web] Remove image codecs from canvaskit_chromium (flutter/flutter#178133)
2026-05-22 30870216+gaaclarke@users.noreply.github.com opts all macos into wide gamut (flutter/flutter#186277)
2026-05-22 engine-flutter-autoroll@skia.org Roll Skia from 356185490a75 to dae8778ca40d (9 revisions) (flutter/flutter#186949)
2026-05-22 1598289+lukemmtt@users.noreply.github.com Filter out SwiftPM schemes when fetching schemes (flutter/flutter#186006)
2026-05-22 engine-flutter-autoroll@skia.org Roll Packages from 3754d04 to 69cf959 (1 revision) (flutter/flutter#186950)
2026-05-22 engine-flutter-autoroll@skia.org Roll Dart SDK from eca46bec956d to b8414c46f6c7 (2 revisions) (flutter/flutter#186944)
2026-05-22 30870216+gaaclarke@users.noreply.github.com Saves a DeviceHolderVK with the CommandPoolVK (flutter/flutter#186749)
2026-05-22 engine-flutter-autoroll@skia.org Roll Dart SDK from e0d509fd676e to eca46bec956d (1 revision) (flutter/flutter#186922)
2026-05-22 bkonyi@google.com [ Tool ] Stop generating widget preview scaffold under $TMP (flutter/flutter#186476)
2026-05-21 737941+loic-sharma@users.noreply.github.com Fix typo in StretchingOverscrollIndicator docs (flutter/flutter#186897)
2026-05-21 engine-flutter-autoroll@skia.org Roll Dart SDK from 28c7cb5a8e8d to e0d509fd676e (1 revision) (flutter/flutter#186903)
2026-05-21 jason-simmons@users.noreply.github.com Fix some issues in the integration between EmbedderExternalViewEmbedder and Impeller (flutter/flutter#184905)
2026-05-21 jason-simmons@users.noreply.github.com Fix a potential buffer overflow in the animated PNG decoder when parsing malformed fdAT chunks (flutter/flutter#186700)
2026-05-21 engine-flutter-autoroll@skia.org Roll Skia from 2ff20950975d to 356185490a75 (5 revisions) (flutter/flutter#186892)
2026-05-21 flar@google.com Add primitive shadows to rendering benchmark (flutter/flutter#186779)
2026-05-21 15619084+vashworth@users.noreply.github.com Move prefetchSwiftPackages to be per platform (flutter/flutter#186468)
2026-05-21 okorohelijah@google.com Upgrade iOS version (flutter/flutter#186889)
...
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
## Summary

In iOS projects with a watchOS companion target and Swift Package
Manager enabled, `IosProject.containsWatchCompanion()` has a fallback
path for modern Xcode projects where the companion relationship is
declared through `INFOPLIST_KEY_WKCompanionAppBundleIdentifier` in
`project.pbxproj`, rather than as a literal
`WKCompanionAppBundleIdentifier` key in the watch target `Info.plist`.

That fallback iterates `projectInfo.schemes` and runs:

```bash
xcodebuild -showBuildSettings -destination generic/platform=watchOS
```

for each non-default scheme until it finds the watch companion scheme.

With SwiftPM enabled, `xcodebuild -list` can include schemes for direct
Flutter plugin packages and transitive Swift packages, such as
`advertising-id`, `amplitude-flutter`, `Amplitude-Swift`,
`RevenueCatUI`, and `SuperwallKit`. Those schemes cannot be the host
project's watch companion, but each failed watchOS build-settings probe
can take multiple seconds.

This PR filters those non-host schemes earlier, in
`XcodeProjectInterpreter.getInfo()`, before they become part of
`XcodeProjectInfo.schemes`.

The current filter excludes:

- `FlutterGeneratedPluginSwiftPackage`
- `FlutterFramework`
- plugin names from `xcodeProject.getPlugins()`
- dashed and capitalized plugin-name variants, e.g. `cloud_firestore`,
`cloud-firestore`, `Cloud-firestore`
- transitive SwiftPM package schemes found under
`build/ios/SourcePackages/checkouts/*/.swiftpm/xcode/xcshareddata/xcschemes/*.xcscheme`

I also removed the earlier shared-scheme-location filter from
`containsWatchCompanion()`. That earlier approach was present in
[0cfdd3a](flutter@0cfdd3a),
but it could skip valid non-shared host schemes. The current approach
keeps the fallback behavior scheme-based while removing known SwiftPM
package schemes from the candidate list.

Fixes flutter#186004.

## Measurements

Test project: TimeFinder app.

Command:

```bash
flutter build ios --debug --simulator --no-pub -v
```

Benchmark condition for fallback rows: the literal
`WKCompanionAppBundleIdentifier` key was removed from the watch target
`Info.plist`, while the modern
`INFOPLIST_KEY_WKCompanionAppBundleIdentifier` entries remained in
`project.pbxproj`.

| Scenario | Unique watchOS probes before detection | Time to detection,
3 trials | Median | Fallback scan only, 3 trials | Median |
|---|---:|---:|---:|---:|---:|
| Literal plist key present, no fallback | 0 | 92.8s, 70.0s, 70.9s |
70.9s | n/a | n/a |
| Unpatched baseline, no plist key | 60 | 244.2s, 235.4s, 238.9s |
238.9s | 174.1s, 170.8s, 165.6s | 170.8s |
| Earlier shared-scheme approach, no plist key | 5 | 90.2s, 89.8s, 87.7s
| 89.8s | 16.9s, 21.0s, 17.6s | 17.6s |
| Current PR, no plist key | 3 | 85.3s, 80.7s, 83.3s | 83.3s | 12.5s,
11.5s, 11.8s | 11.8s |

In this project, Xcode listed 67 schemes. The current filter reduced
that to 6 retained schemes, and the fallback reached
`TimeFinderWatchApp` after probing only:

- `LiveActivityWidgetExtension`
- `ScheduleWidgetExtension`
- `TimeFinderWatchApp`

It did not probe direct plugin schemes or transitive SwiftPM package
schemes, including `Patrol`, `Amplitude-Swift`, `RevenueCatUI`,
`RevenueCatUITests`, or `SuperwallKit`.

Worth noting: TimeFinder is a worst-case-ish benchmark project for this
issue: it has many SwiftPM package schemes, and `xcodebuild -list`
returns schemes alphabetically here, so `TimeFinderWatchApp` is near the
end of the candidate sequence. A project with a watch scheme that sorts
early, such as `AAAWatchApp`, would see far less baseline overhead and
therefore less benefit from this PR.

## Test Plan

- `flutter test test/general.shard/ios/xcodeproj_test.dart`
- `flutter test test/general.shard/project_test.dart --plain-name 'watch
companion'`
- `flutter analyze` in `packages/flutter_tools`
- `git diff --check`

---------

Co-authored-by: Victoria Ashworth <15619084+vashworth@users.noreply.github.com>
Co-authored-by: Elijah Okoroh <okorohelijah@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD platform-ios iOS applications specifically team-ios Owned by iOS platform team team-macos Owned by the macOS platform team tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[tool][iOS] Slow Apple Watch companion detection: scans every SwiftPM scheme

6 participants