[CP-stable] Prepare and warn when missing iOS Device Support Symbols by vashworth · Pull Request #192301 · flutter/flutter · GitHub
Skip to content

[CP-stable] Prepare and warn when missing iOS Device Support Symbols - #192301

Open
vashworth wants to merge 2 commits into
flutter:flutter-3.47-candidate.0from
vashworth:cp_3.47_pr_189993
Open

[CP-stable] Prepare and warn when missing iOS Device Support Symbols#192301
vashworth wants to merge 2 commits into
flutter:flutter-3.47-candidate.0from
vashworth:cp_3.47_pr_189993

Conversation

@vashworth

Copy link
Copy Markdown
Contributor

Issue Link:

#189284

Impact Description:

When debugging on iOS 27 devices, the app may launch and hang for multiple minutes.

Changelog Description:

[flutter/189284] When debugging with an iOS 27 device, the app may launch to a white screen and hang for multiple minutes.

Workaround:

Run xcrun xcodebuild -prepareDeviceSupport -destination id=[insert device id]

Risk:

What is the risk level of this cherry-pick?

  • Low
  • Medium
  • High

Test Coverage:

Are you confident that your fix is well-tested by automated tests?

  • Yes
  • No

Validation Steps:

See repro steps in #189284.

When debugging for iOS devices, Device Support symbols are required to
be copied from the iOS device to the host. Previously the only way to
trigger this was to open Xcode. We recently discovered there's now a
command that automates this.

This PR adds a command that calls `xcodebuild -prepareDeviceSupport`
before installing/launching the app so that Device Support symbols are
verified to be installed.

Toward flutter#189284.

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This PR explicitly sets the iOS Device Support symbols in LLDB if we're
able to identify them. If LLDB takes too long or receives a `warning:
libobjc.A.dylib is being read from process memory.` log, we print out a
message indicating that symbols may be missing and that you need to open
Xcode to trigger it to copy them.

Fixes flutter#189284.

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
@vashworth
vashworth requested review from a team as code owners September 4, 2026 16:59
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Sep 4, 2026
@flutter-dashboard

Copy link
Copy Markdown

@github-actions github-actions Bot added platform-ios iOS applications specifically tool Affects the "flutter" command-line tool. See also t: labels. platform-macos Building on or for macOS specifically a: desktop Running on desktop team-ios Owned by iOS platform team team-macos Owned by the macOS platform team labels Sep 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 introduces the IOSDeviceSupport class to manage and prepare iOS device support symbols using xcodebuild -prepareDeviceSupport for Xcode 16.3+, integrating it into the IOSDevice and LLDB launch and debugging flows. Feedback on the changes suggests several robustness improvements, including catching all exceptions during symbol preparation to prevent tool crashes, using a LineSplitter to robustly parse stream output, ensuring the entire device directory is cleared when removing cached symbols, correcting a version typo in the comments, and adding a timeout to the LLDB platform status check to prevent potential hangs.

Comment on lines +155 to +160
} on ProcessException catch (exception, stackTrace) {
_logger.printError(
'Process exception running "xcodebuild -prepareDeviceSupport": $exception',
);
_logger.printTrace('$stackTrace');
}

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.

high

Since prepareDeviceSupport() is called during the critical application startup path (startApp), any uncaught exception will crash the entire flutter run command. Catching only ProcessException is risky because other types of exceptions (such as ArgumentError, FileSystemException, or StateError) could be thrown during process startup or stream processing. Catching all exceptions (catch (exception, stackTrace)) ensures that any unexpected error is gracefully logged to trace/error without blocking the user from running their app.

Suggested change
} on ProcessException catch (exception, stackTrace) {
_logger.printError(
'Process exception running "xcodebuild -prepareDeviceSupport": $exception',
);
_logger.printTrace('$stackTrace');
}
} catch (exception, stackTrace) {
_logger.printError(
'Error running "xcodebuild -prepareDeviceSupport": $exception',
);
_logger.printTrace('$stackTrace');
}

Comment on lines +107 to +123
final StreamSubscription<String> stdoutSubscription = process.stdout
.transform(utf8.decoder)
.listen((String text) {
if (text.contains('Copying')) {
printToTrace = false;
_logger.printStatus(
'Copying Device Support symbols. This may take several minutes to complete...\n'
'Please do not connect or disconnect your device or open Xcode until finished.',
);
timer.cancel();
}
if (printToTrace) {
_logger.printTrace(text);
} else {
_logger.printStatus(text, newline: false);
}
});

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.

medium

Searching for 'Copying' directly on raw stream chunks can fail if the word is split across chunk boundaries (which can happen due to OS block-buffering on pipes). Using LineSplitter ensures that we process complete lines, making the substring search robust and preventing potential false negatives where the status message is missed and the 10-second warning is erroneously triggered.

Suggested change
final StreamSubscription<String> stdoutSubscription = process.stdout
.transform(utf8.decoder)
.listen((String text) {
if (text.contains('Copying')) {
printToTrace = false;
_logger.printStatus(
'Copying Device Support symbols. This may take several minutes to complete...\n'
'Please do not connect or disconnect your device or open Xcode until finished.',
);
timer.cancel();
}
if (printToTrace) {
_logger.printTrace(text);
} else {
_logger.printStatus(text, newline: false);
}
});
final StreamSubscription<String> stdoutSubscription = process.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen((String line) {
if (line.contains('Copying')) {
printToTrace = false;
_logger.printStatus(
'Copying Device Support symbols. This may take several minutes to complete...\n'
'Please do not connect or disconnect your device or open Xcode until finished.',
);
timer.cancel();
}
if (printToTrace) {
_logger.printTrace(line);
} else {
_logger.printStatus(line);
}
});

Comment on lines +184 to +189
return 'Xcode Device Support symbols exist for this device, but are being read from '
'process memory. $reducePerformance\n'
'To re-copy symbols from your device, complete the following steps:\n'
' 1. Remove cached symbols:\n'
' rm -rf "${existingDeviceSupportSymbols!.parent.path}"\n'
' 2. $action';

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.

medium

If existingDeviceSupportSymbols is archSymbolDirectory (e.g., deviceDirectory/arm64e/Symbols), then existingDeviceSupportSymbols!.parent is deviceDirectory/arm64e. Deleting only deviceDirectory/arm64e leaves other parts of the device directory intact, which might prevent Xcode from cleanly re-copying all symbols. To completely clear the cache for this device, we should delete the entire deviceDirectory (which is symbolDirectory.parent).

        final (Directory? symbolDirectory, _) = _findSymbolDirectories();
        final String deletePath = symbolDirectory?.parent.path ?? existingDeviceSupportSymbols!.parent.path;
        return 'Xcode Device Support symbols exist for this device, but are being read from '
            'process memory. $reducePerformance\n'
            'To re-copy symbols from your device, complete the following steps:\n'
            '  1. Remove cached symbols:\n'
            '     rm -rf "$deletePath"\n'
            '  2. $action';

/// Returns a tuple of the symbol directory and the architecture-specific symbol directory.
/// If the paths to the directories cannot be constructed, returns (null, null).
///
/// The architecture-specific symbol directory is only present on newer versions of iOS (27+).

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.

medium

The version number iOS (27+) is a typo for iOS (17+). iOS 17 is the version where Apple introduced the new CoreDevice connectivity and changed the symbol path structure. Please correct this typo here and on line 241 to avoid confusing future maintainers.

Suggested change
/// The architecture-specific symbol directory is only present on newer versions of iOS (27+).
/// The architecture-specific symbol directory is only present on newer versions of iOS (17+).

Comment on lines +274 to +281

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.

medium

If platform status fails or doesn't output the expected Platform: pattern (e.g., due to an unexpected LLDB error or environment difference), await futureLog will hang indefinitely, blocking the entire flutter run startup. Adding a reasonable timeout (e.g., 5 seconds) ensures that the tool remains robust and continues startup even if the status command fails to produce the expected output.

  Future<void> _printDeviceSupportStatus() async {
    final Future<String> futureLog = _startWaitingForLog(
      RegExp(r'\s*Platform:'),
    ).then((value) => value, onError: _handleAsyncError);

    await _lldbProcess?.stdinWriteln('platform status');
    await futureLog.timeout(
      const Duration(seconds: 5),
      onTimeout: () => '',
    );
  }

@vashworth vashworth added the cp: review Cherry-picks in the review queue label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop CICD Run CI/CD cp: review Cherry-picks in the review queue platform-ios iOS applications specifically platform-macos Building on or for macOS 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.

1 participant