Skip to content

[SwiftPM] When Swift Package Manager migration fails, link to documentation instructions to set it up manually #160214

@bc-lee

Description

@bc-lee

The Xcode project format has a notoriously bad reputation among iOS/macOS software engineers. It is fragile, hard to read, and difficult to maintain. This is why iOS engineers often reinvent alternatives or generators for Xcode project files, such as XcodeGen and Tuist. Personally, I no longer use plain Xcode project files, except for Flutter-related projects. Flutter performs a lot of "magic" during the build process and relies on Xcode project files for iOS/macOS targets.

Additionally, with the decline of CocoaPods, most dependencies are now available through Swift Package Manager (SPM). Flutter has embraced this shift by introducing an option to use SPM for iOS/macOS projects in Flutter 3.27, which I find very exciting.

However, I encountered an issue when migrating to Swift Package Manager. The migration script failed with the following error:

Adding Swift Package Manager integration...                         22ms
An error occurred when adding Swift Package Manager integration:
  Exception: Unable to find PBXFrameworksBuildPhase for Runner target.

Swift Package Manager is currently an experimental feature. Please file a bug at:
  https://github.com/flutter/flutter/issues/new?template=1_activation.yml
Consider including a copy of the following files in your bug report:
  ios/Runner.xcodeproj/project.pbxproj
  ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (or the scheme for the flavor used)

To avoid this failure, disable Flutter Swift Package Manager integration for the project
by adding the following to the project's `pubspec.yaml` under the "flutter" section:
  `disable-swift-package-manager: true`
Alternatively, disable Flutter Swift Package Manager integration globally with:
  `flutter config --no-enable-swift-package-manager`

Upon investigation, I reviewed the migration script code in swift_package_manager_integration_migration.dart and discovered that it relies on hard-coded identifiers for various Xcode project sections. For example:

static const String _iosRunnerNativeTargetIdentifier = '97C146ED1CF9000F007C117D';

This is problematic because tools like xUnique, which normalize Xcode project files, can change these identifiers. Here's an example of how identifiers change after normalization:

Before Normalization

/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
    isa = PBXNativeTarget;
    buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
    buildPhases = (
        EF5FC0595FAA045E778ABA64 /* [CP] Check Pods Manifest.lock */,
        9740EEB61CF901F6004384FC /* Run Script */,
        97C146EA1CF9000F007C117D /* Sources */,
        97C146EB1CF9000F007C117D /* Frameworks */,
        97C146EC1CF9000F007C117D /* Resources */,
        9705A1C41CF9048500538489 /* Embed Frameworks */,
        3B06AD1E1E4923F5004D2608 /* Thin Binary */,
    );
    productName = Runner;
    ...
};
/* End PBXNativeTarget section */

After Normalization

/* Begin PBXNativeTarget section */
E30F7D64842177B99FDDF63DCA10BCDE /* Runner */ = {
    isa = PBXNativeTarget;
    buildConfigurationList = 92578F7B9E3F6AC8F17192C290223DCF /* Build configuration list for PBXNativeTarget "Runner" */;
    buildPhases = (
        AC0061BF939EE938EA540EE9D04BF3B3 /* [CP] Check Pods Manifest.lock */,
        7E9D2C9174A80CAA4BFDFDCB4F72C7A8 /* Run Script */,
        FBC56BB6E87C12DAFB6BB5C3C53DF533 /* Sources */,
        00C27919A6B50DC1DE2CD3F64D33BCCA /* Frameworks */,
        8CF819BBBFB9AE05A1821B127DF85DF8 /* Resources */,
        E55F38183CFB6C120953C92EF0C091F4 /* Embed Frameworks */,
        3CBF9DA705FA99067B6DD4D7F9246CC9 /* Thin Binary */,
    );
    productName = Runner;
    ...
};
/* End PBXNativeTarget section */

The hard-coded identifier for the Runner target (97C146ED1CF9000F007C117D) was replaced with a new identifier (E30F7D64842177B99FDDF63DCA10BCDE). As a result, the migration script failed.

Suggested Solution

To avoid these issues, the migration script should not rely on hard-coded identifiers. Instead, it should dynamically locate the required objects in the Xcode project file, possibly by matching the name property of targets or using other stable metadata. While implementing such a solution might be more complex, it would make the migration process more robust and compatible with various Xcode project configurations.

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listc: proposalA detailed proposal for a change to Flutterplatform-iosiOS applications specificallyplatform-macBuilding on or for macOS specificallyr: fixedIssue is closed as already fixed in a newer versionteam-iosOwned by iOS platform teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-iosTriaged by iOS platform team

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions