Repository: flutter
Issue: [SwiftPM] When Swift Package Manager migration fails, link to documentation instructions to set it up manually
Labels: platform-ios,tool,platform-mac,c: proposal,P2,team-ios,triaged-ios

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](https://github.com/yonaskolb/XcodeGen) and [Tuist](https://tuist.io/). 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:

```plaintext
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`](https://github.com/flutter/flutter/blob/97426566104215127a44666fe2b75c18208d1701/packages/flutter_tools/lib/src/migrations/swift_package_manager_integration_migration.dart) and discovered that it relies on hard-coded identifiers for various Xcode project sections. For example:

```dart
static const String _iosRunnerNativeTargetIdentifier = '97C146ED1CF9000F007C117D';
```

This is problematic because tools like [xUnique](https://github.com/truebit/xUnique), which normalize Xcode project files, can change these identifiers. Here's an example of how identifiers change after normalization:

#### Before Normalization
```plaintext
/* 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
```plaintext
/* 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.