Skip to content

[tools] Pass IMPELLERC and LIBTESSELLATOR env vars to build hooks - #186300

Closed
bdero wants to merge 3 commits into
flutter:masterfrom
bdero:local-engine-impellerc-env
Closed

bdero wants to merge 3 commits into
flutter:masterfrom
bdero:local-engine-impellerc-env

Conversation

@bdero

@bdero bdero commented May 10, 2026 •

Copy link
Copy Markdown
Member

Fixes #186299. When flutter_tools spawns build hooks (the cross-package replacement for native_assets_cli), it now publishes IMPELLERC and LIBTESSELLATOR environment variables resolved through Artifacts.getHostArtifact(...), so build hooks that need host-side tools see the same versions of those tools that flutter_tools' own build targets do.

Build hooks run as separate Dart subprocesses spawned by hooks_runner. They don't have access to flutter_tools' in-process Artifacts API, so packages that need host tools (the canonical case being flutter_gpu_shaders, which compiles .shaderbundle.json via impellerc) re-implement their own artifact resolution by walking up from the dart binary into bin/cache/artifacts/engine/<host>/. That homegrown lookup misses the --local-engine override that CachedLocalEngineArtifacts.getHostArtifact already wires up for flutter_tools' own targets (the FragmentProgram shader compiler at build_system/tools/shader_compiler.dart:167 works correctly under --local-engine for this exact reason). The downstream symptom is silent version skew: a freshly built local engine paired with a hook that picked up the cached SDK's impellerc produces shader bundles in a format the local engine doesn't understand. The user sees an opaque Unsupported shader bundle format version: 1, expected: 2 at runtime with no pointer back to the artifact mismatch.

flutter_tools/lib/src/isolated/native_assets/native_assets.dart adds a buildHookEnvironment(...) helper that takes Artifacts and Platform, replicates the NativeAssetsBuildRunner default filter, and adds IMPELLERC and LIBTESSELLATOR from the HostArtifact resolver. Artifacts and Platform are threaded through FlutterNativeAssetsBuildRunnerImpl's constructor and used to populate NativeAssetsBuildRunner.hookEnvironment. flutter_tools/lib/src/build_system/targets/native_assets.dart updates createFlutterNativeAssetsBuildRunner(environment) to pass environment.artifacts and environment.platform through to the impl. The pattern matches what desktop builds already do for LOCAL_ENGINE and LOCAL_ENGINE_HOST env vars (see lib/src/linux/build_linux.dart:75-76, lib/src/windows/build_windows.dart:292-293).

Hooks that don't read these env vars are unaffected. Hooks that opt in (e.g. by checking Platform.environment['IMPELLERC']) get correct behavior under both --local-engine and the normal cached engine without any per-package logic. The cache hash for build hook inputs already includes the hook environment, so consumers will see a one-time cache miss on the first run after this lands and stable hits thereafter.

packages/flutter_tools/test/general.shard/isolated/build_system/targets/native_assets_test.dart adds three direct tests for buildHookEnvironment: verifying IMPELLERC and LIBTESSELLATOR are present in the produced env; verifying the values match Artifacts.getHostArtifact(...) (the contract that propagates the --local-engine override to hooks); and verifying the parent-process env is filtered through the same allowlist NativeAssetsBuildRunner uses by default. All 14 tests in the file pass, including the original 11.

Pre-launch Checklist

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label May 10, 2026
@github-actions github-actions Bot added the tool Affects the "flutter" command-line tool. See also t: labels. label May 10, 2026
@bdero
bdero requested a review from dcharkes May 10, 2026 02:19
@bdero

bdero commented May 10, 2026

Copy link
Copy Markdown
Member Author

@dcharkes I'm back at it 😛

@bdero
bdero force-pushed the local-engine-impellerc-env branch from b5f49c2 to ea4efbc Compare May 10, 2026 02:21
@github-actions github-actions Bot removed the CICD Run CI/CD label May 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 native assets build system to provide host-tool paths, specifically IMPELLERC and LIBTESSELLATOR, to build hook subprocesses. It adds a buildHookEnvironment utility to filter environment variables and resolve artifact paths, with accompanying unit tests. Feedback includes a suggestion to remove a potentially redundant toUpperCase() call and a recommendation to use absolute paths for host artifacts to ensure reliability across different working directories.

Comment thread packages/flutter_tools/lib/src/isolated/native_assets/native_assets.dart Outdated
Build hooks (the cross-package replacement for native_assets_cli) run
as separate Dart subprocesses spawned by hooks_runner. They don't have
access to flutter_tools' in-process `Artifacts` API, so packages that
need host-side tools (the canonical case being `flutter_gpu_shaders`,
which compiles `.shaderbundle.json` via `impellerc`) re-implement their
own artifact resolution by walking up from the dart binary into
`bin/cache/artifacts/engine/<host>/`.

That homegrown lookup misses the `--local-engine` override that
`CachedLocalEngineArtifacts.getHostArtifact` already wires up for
flutter_tools' own targets. The result is silent version skew between
the local engine and host tools, which surfaces downstream as opaque
failures (e.g. shader bundle format mismatches).

This change extends the same pattern desktop builds already use for
LOCAL_ENGINE / LOCAL_ENGINE_HOST: when flutter_tools constructs its
NativeAssetsBuildRunner, also build a `hookEnvironment` that augments
the default filtered env with `IMPELLERC` and `LIBTESSELLATOR`,
resolved through `Artifacts.getHostArtifact(...)`. Hooks that read
these env vars get the correct host tools whether or not
`--local-engine` is set, and don't have to re-implement artifact
resolution.

Fixes flutter#186299.
@bdero
bdero force-pushed the local-engine-impellerc-env branch from ea4efbc to bad5505 Compare May 10, 2026 02:23
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label May 10, 2026
bdero added a commit to bdero/flutter_gpu_shaders that referenced this pull request May 10, 2026
flutter_tools sets IMPELLERC on build hook subprocesses (see
flutter/flutter#186300) so that the --local-engine override that
CachedLocalEngineArtifacts already wires up for flutter_tools' own
build targets also reaches third-party hooks. Honor the runtime env
var as a second resolution step (after the existing compile-time
String.fromEnvironment define, before walking up to the SDK cache),
so this package picks up the correct impellerc with no per-user
configuration when developing against a locally built engine.
@github-actions github-actions Bot removed the CICD Run CI/CD label May 10, 2026
@bdero

bdero commented May 10, 2026

Copy link
Copy Markdown
Member Author

Just retriggered CI with an empty commit. The previous Linux analyze failure looks unrelated to this PR: I locally reproduced the same two errors on a clean upstream/master detached HEAD with no local changes:

error - Target of URI doesn't exist: 'package:hook_user_defines/hook_user_defines.dart' (dev/integration_tests/hook_user_defines/test/hook_user_defines_test.dart:5:8)
error - The function 'sum' isn't defined (dev/integration_tests/hook_user_defines/test/hook_user_defines_test.dart:11:12)

Running flutter pub get inside dev/integration_tests/hook_user_defines/ clears it (the package is intentionally outside the workspace per the comment in its own pubspec.yaml). This PR doesn't touch that integration test or its deps, so I'm treating the previous failure as a transient CI setup miss.

CI's Linux analyze shard fails on dev/tools/bin/format.dart because
testUsingContext and one expect call were left on multiple lines where
the formatter collapses them onto one. No behavior change.
@github-actions github-actions Bot removed the CICD Run CI/CD label May 11, 2026
@dcharkes

dcharkes commented May 11, 2026 •

Copy link
Copy Markdown
Contributor

Hi @bdero! Welcome back!

I think allowlisting env vars for specific packages is an anti-pattern. So far we've only been allowlisting variables for OS-specific things or build-system specific things.

If you want your end users to configure whether a feature is available or where a native library can be found, this should be done via user-defines.

// pubspec.yaml
hooks:
  user_defines:
    <package-name>:
      <key>: <value>

These are accessible in https://pub.dev/documentation/hooks/latest/hooks/HookInputUserDefines-class.html

If at all possible, I'd encourage to structure your package in a way that doesn't require end-users to configure everything. If your package ends up being used by 100000 devs, all of them would need to configure their system. Is it possible to have good defaults? And to write your hook in a way that would download any necessary files from a CDN (GitHuhb releases/artifacts).

Edit: If you want to expose Flutter-internal artifacts to build hooks, then we should add some kind of flutter-specific extension to the input.config with a Dart API as an extension method that is available in Flutter. Something along the lines of: input.config.flutter.impeller;

@bdero

bdero commented May 11, 2026 •

Copy link
Copy Markdown
Member Author

Yup, just trying to expose a couple of binaries that ship in the Flutter engine artifacts to build hooks. This replaces the fragile code in flutter_gpu_shaders that has to work out where the engine artifacts are located.

Are you suggesting I do something similar to the code_assets package, where we publish a new package (probably placed under flutter/packages) with FlutterExtension implements ProtocolExtension and a HookConfig.flutter typed accessor?
And then flutter_tools would inject the paths via the new extension, and flutter_gpu_shaders (or anything else that needs to find ImpellerC) would read them via the typed accessor?

Happy to try and go for this approach if it sounds right to you.

@dcharkes

Copy link
Copy Markdown
Contributor

Are you suggesting I do something similar to the code_assets package, where we publish a new package (probably placed under flutter/packages) with FlutterExtension implements ProtocolExtension and a HookConfig.flutter typed accessor? And then flutter_tools would inject the paths via the new extension, and flutter_gpu_shaders (or anything else that needs to find ImpellerC) would read them via the typed accessor?

Yes!

@bdero

bdero commented May 13, 2026

Copy link
Copy Markdown
Member Author

Alright, I pushed the package here: flutter/packages#11701

If we're able to land it, I'll repurpose this PR for the integration.

@bkonyi

bkonyi commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Alright, I pushed the package here: flutter/packages#11701

This PR was closed in favor of flutter/core-packages#19.

@bdero, I'm guessing you're still working on figuring out the name for the package before picking this back up?

@bdero

bdero commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

http://github.com/flutter/flutter/pull/189821 replaces the need for this, closing now.

@bdero bdero closed this Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flutter_tools] Expose Flutter engine host-tool paths to build hooks via a typed protocol extension

4 participants