Skip to content

[flutter_tools] Fix native assets crash on Linux custom devices#188384

Merged
auto-submit[bot] merged 3 commits into
flutter:masterfrom
bkonyi:fix-native-assets-custom-device
Jun 25, 2026
Merged

[flutter_tools] Fix native assets crash on Linux custom devices#188384
auto-submit[bot] merged 3 commits into
flutter:masterfrom
bkonyi:fix-native-assets-custom-device

Conversation

@bkonyi

@bkonyi bkonyi commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

When native assets are enabled, the Flutter tool attempts to resolve the C compiler configuration. On Linux, this is done by reading CMakeCache.txt from the native build directory to align toolchains.

However, for custom devices or flutter build bundle commands, no native app build is performed, meaning CMakeCache.txt does not exist. This previously caused the tool to crash unconditionally.

This PR:

  1. Adds a throwIfNotFound parameter to cCompilerConfigLinux (defaulting to true) to allow graceful failures (returning null) when the CMake cache or toolchain is missing.
  2. Updates LinuxAssetTarget.setCCompilerConfig to only require the compiler configuration (passing throwIfNotFound: true) if a native app build directory actually exists. Otherwise, it allows it to be optional and return null.
  3. Fixes and adds unit tests, and introduces a new integration test verifying that flutter build bundle succeeds on Linux with native assets.

Fixes #187980

When native assets are enabled, the Flutter tool attempts to resolve the
C compiler configuration. On Linux, this is done by reading `CMakeCache.txt`
from the native build directory to align toolchains.

However, for custom devices or `flutter build bundle` commands, no native
app build is performed, meaning `CMakeCache.txt` does not exist. This
previously caused the tool to crash unconditionally.

This change:
1. Adds a `throwIfNotFound` parameter to `cCompilerConfigLinux` (defaulting
   to `true`) to allow graceful failures (returning `null`) when the CMake
   cache or toolchain is missing.
2. Updates `LinuxAssetTarget.setCCompilerConfig` to only require the
   compiler configuration (passing `throwIfNotFound: true`) if a native app
   build directory actually exists. Otherwise, it allows it to be optional
   and return `null`.
3. Fixes and adds unit tests, and introduces a new integration test
   verifying that `flutter build bundle` succeeds on Linux with native assets.

Fixes flutter#187980
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 23, 2026
@github-actions github-actions Bot added tool Affects the "flutter" command-line tool. See also t: labels. a: desktop Running on desktop team-linux Owned by the Linux platform team labels Jun 23, 2026
@bkonyi
bkonyi requested a review from dcharkes June 23, 2026 16:15
@bkonyi bkonyi added CICD Run CI/CD and removed CICD Run CI/CD labels Jun 23, 2026
@fluttergithubbot

Copy link
Copy Markdown
Contributor

An existing Git SHA, c4b00d5dfa907154e3baf5dcc09bb4c1dfe8831d, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@bkonyi
bkonyi marked this pull request as ready for review June 23, 2026 16:44
@bkonyi
bkonyi requested a review from a team as a code owner June 23, 2026 16:44

@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 a throwIfNotFound parameter to cCompilerConfigLinux to allow graceful handling of missing compiler configurations by returning null instead of throwing a ToolExit. It also updates setCCompilerConfig and adds corresponding unit and integration tests. The review feedback suggests catching FileSystemException alongside ToolExit to prevent unhandled crashes during symbolic link resolution, and simplifying the configuration logic in setCCompilerConfig to avoid potential regressions where missing directories silently bypass error throwing.

Comment on lines +99 to +104
} on ToolExit {
if (throwIfNotFound) {
rethrow;
}
return null;
}

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

The resolveSymbolicLinks() call on line 88 can throw a FileSystemException if the compiler path specified in CMakeCache.txt does not exist on the host system (for example, due to a stale cache or an invalid toolchain path). Since only ToolExit is caught here, any FileSystemException will propagate and cause the tool to crash, even when throwIfNotFound is set to false. Catching FileSystemException as well ensures graceful failure and robustness.

  } on ToolExit {
    if (throwIfNotFound) {
      rethrow;
    }
    return null;
  } on FileSystemException {
    if (throwIfNotFound) {
      rethrow;
    }
    return null;
  }

Comment thread packages/flutter_tools/lib/src/isolated/native_assets/targets.dart

@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 @bkonyi! 🙏 (Sorry for the slow reply on the bug, I was traveling.)

When native assets are enabled, the Flutter tool attempts to resolve the C compiler configuration. On Linux, this is done by reading CMakeCache.txt from the native build directory to align toolchains.

However, for custom devices or flutter build bundle commands, no native app build is performed, meaning CMakeCache.txt does not exist. This previously caused the tool to crash unconditionally.

Right, that's a bug.

  1. Adds a throwIfNotFound parameter to cCompilerConfigLinux (defaulting to true) to allow graceful failures (returning null) when the CMake cache or toolchain is missing.

Alternatively, we could avoid passing cmakeDirectory? Do we know the contexts where we wont have a cmake build for sure?

@bkonyi

bkonyi commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Alternatively, we could avoid passing cmakeDirectory? Do we know the contexts where we wont have a cmake build for sure?

That would be cleaner, but distinguishing the build context at the target level is surprisingly brittle. Both native and bundle-only builds share the same BuildHooks/LinkHooks targets and pass environment.outputDir as the appBuildDirectory, leaving us without a clean way to tell them apart there.

Checking cmakeBuildDirectory.existsSync() in targets.dart is much more robust as it directly verifies if a CMake environment is physically available. As far as I can tell, since CMake always runs before flutter assemble in native builds, this is a safe proxy. If it's missing, we safely return null instead of crashing.

…links

Stale or invalid compiler paths in CMakeCache.txt can cause resolveSymbolicLinks() to throw a FileSystemException. This change ensures we catch FileSystemException alongside ToolExit in cCompilerConfigLinux, returning null if throwIfNotFound is false, preventing unhandled crashes.

Also adds unit tests using a mock throwing file system.
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 25, 2026
dcharkes
dcharkes previously approved these changes Jun 25, 2026
cCompilerConfigSync = await cCompilerConfigLinux(
cmakeDirectory: mustMatchAppBuild ? cmakeBuildDirectory! : null,
cmakeDirectory: isNativeAppBuild ? cmakeBuildDirectory : null,
throwIfNotFound: mustMatchAppBuild && isNativeAppBuild,

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.

isNativeAppBuild is on both lines, that feels a bit weird. E.g. if the directory is not found we don't pass it. If we don't pass it then we early return null if the directory is null so we will never throw.

throwIfNotFound: mustMatchAppBuild,

If isNativeAppBuild is false, cmakeDirectory is passed as null, which already triggers an early return of null inside cCompilerConfigLinux. Therefore, we do not need to check isNativeAppBuild again in throwIfNotFound, and can simplify it to just mustMatchAppBuild.

Addresses Daco's review feedback.

@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 @bkonyi! 🙏

@auto-submit
auto-submit Bot added this pull request to the merge queue Jun 25, 2026
Merged via the queue into flutter:master with commit 65c759d Jun 25, 2026
168 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 25, 2026
@bkonyi
bkonyi deleted the fix-native-assets-custom-device branch June 25, 2026 20:11
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-linux Owned by the Linux 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.

Native Assets Custom Device

3 participants