Skip to content

[native_assets] Record bundled code assets under their install name - #190819

Merged
dcharkes merged 2 commits into
flutter:masterfrom
wilyan09007:fix/issue-190799
Aug 18, 2026
Merged

dcharkes merged 2 commits into
flutter:masterfrom
wilyan09007:fix/issue-190799

Conversation

@wilyan09007

Copy link
Copy Markdown
Contributor

On macOS and iOS, flutter_tools stamps a bundled code asset's framework with the install name
@rpath/<name>.framework/<name>, but records that asset in NativeAssetsManifest.json as
<name>.framework/<name>. The manifest entry is the string the Dart VM hands to dlopen, so the two
never match. dyld cannot recognize the library under a name it has no install name for, so it falls
back on identifying the file on disk, and that identity only holds until the file is replaced.
Rebuilding an app while a debug instance is still running replaces it, so the next lazily resolved
@Native binding maps a second copy of the asset into the process. Two copies of a C library do not
share its global state, and a handle produced by the first copy is not valid in the second. For
package:sqlite3 that is a segfault on the first write after a rebuild, and the operation is lost.

Both strings now come from one frameworkInstallName helper, so the name stamped into the framework
and the name recorded in the manifest cannot drift apart again. The framework is still bundled at the
unprefixed path, and DarwinAddToAppNativeAssets.parseNativeAssetsManifest drops the prefix for the
add-to-app and Swift Package callers that use the manifest to find the framework on disk.

The flutter test path is unchanged. The tester loads the dylib from where it was built and its
install name is already the absolute path that the manifest records, which is why dart run and
flutter test never showed this.

Fixes #190799

The reporter of that issue measured the dyld behaviour on macOS, including that a manifest entry of
@rpath/<name>.framework/<name> resolves through dlopen and leaves a single mapping across a
rebuild. iOS goes through the same helper and had the same mismatch, so it is fixed here too. I do
not have a Mac, so beyond the unit tests added here I am relying on the existing macOS native assets
integration tests (flutter run with a bundled code asset, in all three build modes) on CI.

Pre-launch Checklist

@wilyan09007
wilyan09007 requested review from a team as code owners August 10, 2026 02:10
@github-actions github-actions Bot added tool Affects the "flutter" command-line tool. See also t: labels. a: desktop Running on desktop team-ios Owned by iOS platform team team-macos Owned by the macOS platform team labels Aug 10, 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 updates the macOS and iOS native assets compilation to record bundled framework assets under their @rpath-relative install name in the native assets manifest, while maintaining their correct location within the bundle. It introduces a helper function frameworkInstallName to generate this install name and updates the corresponding asset target location logic and tests to verify this behavior. I have no feedback to provide as there are no review comments.

@wilyan09007

Copy link
Copy Markdown
Contributor Author

Could someone add the CICD label? Presubmits have not started on this PR, so there is no test signal for a reviewer to work from. The branch is still clean against master.

@dcharkes dcharkes 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.

Thanks for the detailed explanation in #190799 🙏

Would it be possible to make the integration test that runs the app on MacOS/iOS add some C code so that it would crash without the fix. So that we also verify it end-to-end on CI.

@knopp knopp added the CICD Run CI/CD label Aug 13, 2026
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Aug 14, 2026
@wilyan09007

Copy link
Copy Markdown
Contributor Author

Done in the flutter run -dmacos integration test. The generated test project now gets a pair of native functions over state the library keeps on the heap: the app stores a value, the test replaces the bundled framework with a byte for byte copy of itself, and a hot reload then reads the state back through a binding that has not resolved yet. Mapped twice, the second copy has nothing stored in it and the app dies on the read. It runs on presubmit, so it will run on this PR.

I left the devicelab tasks alone. Replacing the framework under a running app needs a writable bundle, which rules out the on-device task, and there is no macOS native assets task there today.

@dcharkes dcharkes added the CICD Run CI/CD label Aug 14, 2026
@dcharkes

Copy link
Copy Markdown
Contributor

Done in the flutter run -dmacos integration test. The generated test project now gets a pair of native functions over state the library keeps on the heap: the app stores a value, the test replaces the bundled framework with a byte for byte copy of itself, and a hot reload then reads the state back through a binding that has not resolved yet. Mapped twice, the second copy has nothing stored in it and the app dies on the read. It runs on presubmit, so it will run on this PR.

I left the devicelab tasks alone. Replacing the framework under a running app needs a writable bundle, which rules out the on-device task, and there is no macOS native assets task there today.

Perfect. Yes, running it on one OS is enough. 👍

@dcharkes

Copy link
Copy Markdown
Contributor

ci.yaml validationFailing after 1s — ci.yaml validation

This error makes no sense, this PR is not changing the yaml file. I'll ping infra.

@dcharkes

Copy link
Copy Markdown
Contributor

ci.yaml validationFailing after 1s — ci.yaml validation

This error makes no sense, this PR is not changing the yaml file. I'll ping infra.

@wilyan09007 rebasing on master should fix this.

On macOS and iOS a bundled code asset is stamped with the install name
`@rpath/<name>.framework/<name>`, but NativeAssetsManifest.json recorded it as
`<name>.framework/<name>`. The manifest entry is the string the Dart VM passes
to `dlopen`, so the two never matched and dyld had to fall back on identifying
the library by the file it came from. Rebuilding an app replaces that file
underneath a debug instance that is still running, so the next lazily resolved
`@Native` binding maps a second copy of the asset into the process. Two copies
of a C library do not share its global state, and a handle produced by the
first one is not valid in the second.

Both strings now come from `frameworkInstallName`, so they cannot drift apart
again. The framework is still bundled at the unprefixed path, and
`parseNativeAssetsManifest` drops the prefix for the callers that use the
manifest to locate the framework on disk.

Fixes flutter#190799
Adds a pair of native functions over state the library keeps on the heap.
One stores a value, the other reads it back through a binding of its own,
so it resolves the asset again on first use rather than reusing whatever
the first call resolved.

The test stores state, replaces the bundled framework with a byte for byte
copy of itself, which is what a rebuild does to a bundle a debug instance
is still running, and then hot reloads a build that reads the state back.
Mapped twice, the second copy has nothing stored in it and the app dies on
the read.
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Aug 15, 2026
@dcharkes dcharkes added the CICD Run CI/CD label Aug 17, 2026
@dcharkes

Copy link
Copy Markdown
Contributor

@vashworth @jmagman Would the iOS team like to review this before merging?

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 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.

# [macOS] Native asset framework is mapped twice after a rebuild, because the manifest path does not match the install name

3 participants