Fly-by clean-up: My understanding from the
[changelog](https://pub.dev/packages/dds/changelog) is that the change
causing the bug in 5.0.4 has been reverted in 5.0.5. Therefore, the pin
should be no longer necessary? Unpinning to find out...
> 5.0.5
[DAP] The change in DDS 5.0.4 to individually add/remove breakpoints has
been reverted and may be restored in a future version.
>
>5.0.4
[DAP] Breakpoints are now added/removed individually instead of all
being cleared and re-added during a setBreakpoints request. This
improves performance and can avoid breakpoints flickering between
unresolved/resolved when adding new breakpoints in the same file.
Adds logic to pass `--include-unsupported-platform-library-stubs` to the
CFE when launched via `flutter widget-preview start`, as well as logic
to ensure the flag can't be passed as an extra frontend option to bypass
compile time errors due to imports of unsupported libraries.
Fixes https://github.com/flutter/flutter/issues/166431
<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->
## Add --web-define option for runtime variable injection in Flutter web
templates
This PR adds support for injecting environment-specific variables into
Flutter web templates during development and build processes through a
new `--web-define` command-line option.
### What this changes
**Before**: Developers had to manually edit HTML templates or use
build-time workarounds to inject environment-specific values (API URLs,
feature flags, etc.) into Flutter web applications.
**After**: Developers can now use `--web-define KEY=VALUE` to inject
variables directly into web templates using `{{VARIABLE_NAME}}`
placeholders.
### Key features
- **Template variable substitution**: Support for `{{VARIABLE_NAME}}`
placeholders in `index.html` and `flutter_bootstrap.js`
- **Runtime validation**: Throws clear errors when required variables
are missing with helpful suggestions
- **Command-line integration**: Works with both `flutter run` and
`flutter build web` commands
- **Multiple variable support**: Can define multiple variables in a
single command
- **Built-in variable protection**: Ignores Flutter's built-in template
variables during validation
### Usage examples
```bash
# Development with API configuration
flutter run -d chrome --web-define=API_URL=https://dev-api.example.com --web-define=DEBUG_MODE=true
# Production build with environment variables
flutter build web --web-define=API_URL=https://api.example.com --web-define=ANALYTICS_ID=GA-123456 --web-define=DEBUG_MODE=false
# Multiple environments
flutter run -d chrome --web-define=ENV=staging --web-define=FEATURE_X=enabled
```
### Template usage
In your `web/index.html`:
```html
<script>
window.config = {
apiUrl: '{{API_URL}}',
environment: '{{ENV}}',
debugMode: {{DEBUG_MODE}}
};
</script>
```
### Error handling
If a variable is missing, the tool provides clear feedback:
```
Missing web-define variable: API_URL
Please provide the missing variable using:
flutter run --web-define=API_URL=VALUE
or
flutter build web --web-define=API_URL=VALUE
```
## Issues fixed
Fixes https://github.com/flutter/flutter/issues/127853
## Additional Usage Examples
### Environment-Specific Configurations (Flavors)
```bash
# Development
flutter run -d chrome --web-define=ENV=dev --web-define=API_URL=http://localhost:3000 --web-define=DEBUG=true
# Production
flutter build web --web-define=ENV=prod --web-define=API_URL=https://api.example.com --web-define=DEBUG=false
```
**Template:**
```html
<script>
window.config = {
environment: '{{ENV}}',
apiUrl: '{{API_URL}}',
debugMode: {{DEBUG}}
};
</script>
```
### Dynamic Asset Loading
```bash
flutter build web --web-define=CDN_URL=https://cdn.example.com --web-define=LOGO_PATH=/assets/logo.png
```
**Template:**
```html
<link rel="icon" href="{{CDN_URL}}{{LOGO_PATH}}">
<link rel="stylesheet" href="{{CDN_URL}}/styles/theme.css">
```
### Analytics Integration
```bash
flutter build web --web-define=GA_ID=G-XXXXXXXXXX --web-define=SENTRY_DSN=https://xxx@sentry.io/123
```
**Template:**
```html
<script async src="https://www.googletagmanager.com/gtag/js?id={{GA_ID}}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{GA_ID}}');
</script>
```
### Feature Flags
```bash
flutter run -d chrome --web-define=FEATURE_X=true --web-define=FEATURE_Y=false
```
**Template:**
```html
<script>
window.features = { featureX: {{FEATURE_X}}, featureY: {{FEATURE_Y}} };
</script>
```
### Multi-Tenant/White-Label Apps
```bash
flutter build web --web-define=TENANT=acme --web-define=PRIMARY_COLOR=#FF5733 --web-define=LOGO_URL=https://cdn.acme.com/logo.png
```
**Template:**
```html
<head>
<title>{{TENANT}} Portal</title>
<link rel="icon" href="{{LOGO_URL}}">
<style>:root { --primary: {{PRIMARY_COLOR}}; }</style>
</head>
```
### Backend Service URLs
```bash
flutter build web \
--web-define=API_URL=https://api.example.com \
--web-define=WS_URL=wss://ws.example.com \
--web-define=AUTH_DOMAIN=auth.example.com
```
**Template:**
```html
<script>
window.services = {
api: '{{API_URL}}',
websocket: '{{WS_URL}}',
auth: '{{AUTH_DOMAIN}}'
};
</script>
```
### SEO & Meta Tags
```bash
flutter build web --web-define=APP_TITLE="My App" --web-define=APP_DESC="Description" --web-define=OG_IMAGE=https://example.com/og.png
```
**Template:**
```html
<head>
<title>{{APP_TITLE}}</title>
<meta name="description" content="{{APP_DESC}}">
<meta property="og:title" content="{{APP_TITLE}}">
<meta property="og:image" content="{{OG_IMAGE}}">
</head>
```
### Build Automation
```json
{
"scripts": {
"dev": "flutter run -d chrome --web-define=ENV=dev --web-define=API_URL=http://localhost:3000",
"prod": "flutter build web --web-define=ENV=prod --web-define=API_URL=https://api.example.com"
}
}
```
### Important Notes
- **Security**: Never expose secrets via `--web-define` (client-side
only)
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [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].
**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
[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
---------
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Ben Konyi <bkonyi@google.com>
Co-authored-by: Mouad Debbar <mdebbar@google.com>
This PR restores the correct precedence behavior for web development
server configuration. Since Flutter 3.38, CLI arguments were being
ignored when `web_dev_config.yaml` was present — specifically for HTTPS
and headers.
According to the design and documentation, the precedence should be:
1. Command-line arguments (highest priority)
2. `web_dev_config.yaml`
3. Built-in defaults (lowest priority)
## Root Cause
The regression affected:
* **HTTP headers** — merge order was reversed, causing file config to
override CLI
* **HTTPS config** — CLI TLS arguments were ignored under certain
conditions
Note:
`--web-port` and `--web-hostname` were already working correctly due to
the `host ?? this.host` and `port ?? this.port` pattern.
The observed issue was due to headers + HTTPS only.
## Changes Made
* Fixed header merge order so CLI takes precedence
* Corrected HTTPS config resolution and precedence logic
* Unified logic across `run` and `drive` commands
* Simplified HTTPS handling using `HttpsConfig.parse()`
* Added tests for CLI precedence behavior
## Before (broken)
```
flutter run -d chrome --web-tls-cert-path cert.pem
```
❌ CLI TLS args ignored when config file existed
❌ headers overridden by file config
## After (fixed)
```
flutter run -d chrome --web-tls-cert-path cert.pem
```
✅ CLI TLS args respected
✅ headers override config as expected
## Tests
* Added tests verifying CLI takes precedence
* All existing and new tests pass
* No breaking changes introduced
## Fixes
Fixes: #179014
---------
Co-authored-by: Kevin Moore <kevmoo@google.com>
Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com>
Co-authored-by: Ben Konyi <bkonyi@google.com>
When targeting Android, don't fail in Flutter tools if the NDK is not
installed. Instead, pass a `null` c compiler config to the hooks. The
hooks can then decide to fail if they need the NDK. If no hook happened
to require the NDK, Flutter for Android apps can be built without the
NDK installed.
Bug: https://github.com/flutter/flutter/issues/180163
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [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.
DTD only supports a single instance of a registered service with a given
name. For widget preview development, we sometimes want to use a DTD
instance that's attached to an IDE to test IDE integration. However,
IDEs frequently spawn their own widget preview instances which register
services with DTD. In the case where `flutter widget-preview start
--dtd-url=<dtd-url>` is run and `dtd-url` points to a DTD instance with
another widget preview service running, the process simply crashes.
This change adds a unique identifier to the widget preview DTD service
and stream names that allows for each `flutter widget-preview start`
instance to register its own unique widget preview DTD services, even if
other widget preview instances are using the same DTD instance.
Fixes https://github.com/flutter/flutter/issues/179883
Previously, this made little difference as DWDS used this only in one
case with expression evaluation but now that the load strategies have
diverged based on this flag, we should correctly always pipe this flag.
This fixes an issue with a future DWDS version.
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [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].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [ ] 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.
Fixes https://github.com/flutter/flutter/issues/163479
This adds a flag,
`--cross-origin-isolation`/`--no-cross-origin-isolation` that allows the
user to explicitly control whether `flutter run`/`drive`/`test` serves
files with COOP/COEP headers. If the user doesn't specify, it uses cross
origin isolation when wasm is enabled and no cross origin isolation when
wasm is disabled.
Uses new event structure to capture package info from wasm dry run
errors.
Uses the `package_info.json` to gather the set of public packages and
only includes package names when the package is in that set of publicly
available packages.
Prepends "-p" for when an error type is found in a private package (i.e.
a `package:*` that isn't in the set of public packages), a "-h" for
non-public packages (i.e. any non-"package" packages or otherwise
unrecognized uris), or a "-ph" for both.
Adds a special "error" entry when the package_config can't be loaded and
instead includes the findings in the same format as today
(comma-separated codes).
Also adds tests for dry runs.
See https://github.com/flutter/flutter/issues/178894 for more context.
---------
Co-authored-by: Nate Biggs <natebiggs@google.com>
Each project's `pubspec.yaml` is copied into a temporary directory
before trying to determine which packages can be updated, but this
`pubspec.yaml` is currently deleted immediately after the dependencies
have been determined for the single package. This means that projects
that have path dependencies on other projects in the repository don't
have their dependencies updated properly as the path dependencies fail
to resolve.
This change updates the `update-packages` logic to copy each project's
`pubspec.yaml` to a temporary directory with a consistent relative
directory structure. The `_upgrade` function has been updated to support
processing multiple projects before deleting the temporary directory,
allowing for projects with path dependencies on each other to have their
pubspecs placed in the correct relative directories for them to resolve
correctly.
Fixes https://github.com/flutter/flutter/issues/179941
## Description
This PR adds support for Cyrillic (Russian ЙЦУКЕН) keyboard layout in
the flutter_tools terminal handler, allowing users to use hot reload,
hot restart, and other terminal commands without switching keyboard
layouts.
## Motivation
Developers working with Cyrillic keyboard layouts currently must switch
to a Latin layout every time they want to use terminal commands like hot
reload (r/R) or help (h). This disrupts the development workflow and
reduces productivity.
## Changes
The implementation maps Cyrillic characters to their corresponding Latin
equivalents based on physical key positions on QWERTY/ЙЦУКЕН layouts:
- **к/К** → r/R (hot reload/restart)
- **й/Й** → q/Q (exit)
- **ц/Ц** → w/W (dump widget tree)
- **в/В** → d/D (detach)
- **р/Р** → h/H (help)
- **ш/Ш** → i/I (widget inspector/invert images)
- **ы/Ы** → s/S (screenshot/semantics)
- **е/Е** → t/T (render tree)
- **м/М** → v/V (DevTools)
- **а** → f (focus tree)
- **п** → g (source generators)
- **Д** → L (layer tree)
- **щ/Щ** → o/O (platform toggle)
- **з/З** → p/P (debug paint/performance overlay)
- **Г** → U (semantics inverse order)
- **ф** → a (profile widgets)
- **и** → b (brightness)
- **с** → c (clear)
## Testing
- Added comprehensive test coverage for Cyrillic keyboard commands
- All existing terminal_handler tests pass
- Verified that Cyrillic characters trigger the same actions as their
Latin equivalents
## Impact
This change improves the developer experience for users working with
Cyrillic keyboard layouts by eliminating the need for constant layout
switching during development. The implementation follows Flutter code
style guidelines and does not affect existing functionality.
---------
Co-authored-by: Ben Konyi <bkonyi@google.com>
Passing the DTD URI via a Dart define results in a new
`<hash>.cache.dill.track.dill` being created on each run as the DTD URI
is never the same and the `cache.dill.track.dill` hash is partly based
on the set of Dart defines. These files are not cleaned up
automatically, so they could take up a significant amount of memory over
time.
This change adds an additional code generation step to the widget
previewer which populates
`widget_preview_scaffold/lib/src/dtd/dtd_connection_info.dart` with a
constant containing the DTD URI provided by the tool.
Fixes https://github.com/flutter/flutter/issues/179139
* Set the character set on the response for the index.html
when running the app with flutter tool.
* Add expectation to existing test that verifies the character
set on the requested index.html reponse.
Fixes: https://github.com/dart-lang/sdk/issues/62090
---------
Co-authored-by: Ben Konyi <bkonyi@google.com>
Resolves#5797
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [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.
- [ ] 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].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
A whole bunch of tool tests failed locally even before the change, so
I'll have to see CI results to know if something actually broke due to
the change.
addressing a regression from #172510 that caused the assemble command to
fail in the validation phase when a dart-define was passed as a
base64-encoded value.
Example command:
```
flutter --verbose assemble --no-version-check \
--output=<build_output_path>/ \
-dTargetPlatform=ios \
-dTargetFile=lib/main.dart \
-dBuildMode=release \
-dConfiguration=Debug \
-dIosArchs=arm64 \
-dSdkRoot=<xcode_sdk_path>/iPhoneOS.sdk \
-dSplitDebugInfo= \
-dTreeShakeIcons=false \
-dTrackWidgetCreation=true \
-dDartObfuscation=false \
-dAction=install \
-dFrontendServerStarterPath= \
--ExtraGenSnapshotOptions= \
--DartDefines=ZW52PXFh \
--ExtraFrontEndOptions= \
-dSrcRoot=<project_root> \
-dTargetDeviceOSVersion= \
-dCodesignIdentity=<codesign_identity> \
release_ios_bundle_flutter_assets
```
Partially addressing: https://github.com/flutter/flutter/issues/178452
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
- [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.
- [ ] 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.
---------
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Ben Konyi <bkonyi@google.com>
<!-- start_original_pr_link -->
Reverts: flutter/flutter#175679
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: jtmcdole
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: Linux linux_unopt is now timing out in postsubmit
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: bkonyi
<!-- end_original_pr_author -->
<!-- start_reviewers -->
Reviewed By: {srawlins}
<!-- end_reviewers -->
<!-- start_revert_body -->
This change reverts the following previous change:
The `flutter_analyzer_plugin` implements rules previously enforced by
the `dev/bots/analyze.dart` check run on the CI, allowing for earlier
detection of custom lint violations before a change is uploaded for
review.
Currently, the plugin implements the following rules:
- avoid_future_catch_error
- no_double_clamp
- no_stopwatches
- protect_public_state_subtypes
- render_box_intrinsics
Towards https://github.com/flutter/flutter/issues/175276
<!-- end_revert_body -->
Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
The `flutter_analyzer_plugin` implements rules previously enforced by
the `dev/bots/analyze.dart` check run on the CI, allowing for earlier
detection of custom lint violations before a change is uploaded for
review.
Currently, the plugin implements the following rules:
- avoid_future_catch_error
- no_double_clamp
- no_stopwatches
- protect_public_state_subtypes
- render_box_intrinsics
Towards https://github.com/flutter/flutter/issues/175276
This change allows for users to open an instance of the DevTools Widget
Inspector within a web view embedded in the widget previewer. This will
allow for developers to inspect their previews without requiring IDEs to
create a special debug session for the widget previewer application.
DWDS is also rolled as part of this change to add DDS and DevTools
support for the `web-server` device.
Fixes https://github.com/flutter/flutter/issues/166423
**Demo:**
https://github.com/user-attachments/assets/3e3a1098-0526-4c7f-8087-38fb84f28335
Refactoring of code in `package:dwds` `26.2.1` changed execution
ordering enough for a race condition in the web benchmark harness to be
hit. This change updates the web benchmark harness to not rely on
waiting for console output from the spawned browser which can be missed.
Fixes https://github.com/flutter/flutter/issues/178326
---------
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Instead of generating assembly code that is then compiled to a Mach-O
dynamic library, use the new app-aot-macho-dylib output option for
gen_snapshot to generate the Mach-O dynamic library without the assembly
step.
This is a reland of https://github.com/flutter/flutter/pull/171626, with
the necessary changes to avoid the issue found in
https://github.com/flutter/flutter/issues/174393 where DWARF information
was being retained in the final snapshot. The initial PR state are the
original commits landed in the previous PR, with a followup commit
containing the fix for that issue: the DWARF information is moved into
an associated relocatable object, so the information is still accessible
by dsymutil before the snapshot is stripped.
Related issues:
* https://github.com/dart-lang/sdk/issues/43299
* https://github.com/dart-lang/sdk/issues/60307
## Pre-launch Checklist
- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [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.
Before this change, there was logic in `flutter attach` that would try
and listen for a new application to attach to in the scenario the
current target application disappeared. This behavior isn't documented,
and has resulted in a `StateError` being thrown due to the VM service
URIs stream being listened to multiple times.
This change removes this behavior, which also prevents the `StateError`
from being thrown.
Fixes https://github.com/flutter/flutter/issues/156692, which is a
top-10 crasher for the tool.
This change fixes an issue where the preview command would crash if a
`pubspec.yaml` was added / deleted somewhere under the previewed
directory. It also improves testing for `PreviewManifest` in the context
of pub workspaces and ensures that `FlutterProject` instances are
refreshed based on the latest `pubspec.yaml` contents.
Fixes https://github.com/flutter/flutter/issues/179155
---------
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
To ensure build hooks emit code assets that are compatible with the main
app, Flutter tools pass a `CCompilerConfig` toolchain configuration
object to hooks. This is generally what we want, hooks on macOS should
use the same `clang` from XCode as the one used to compile the app and
native Flutter plugins for instance.
In some cases however, we need to run hooks without necessarily
compiling a full Flutter app with native sources. A good example for
this is `flutter test`, which runs unit / widget tests in a regular Dart
VM without embedding it in a Flutter application. So since `flutter
test` wouldn't invoke a native compiler, running build hooks shouldn't
fail if the expected toolchain is missing.
Currently however, `flutter test` tries to resolve a compiler toolchain
for the host platform. Doing that on Windows already allows not passing
a `CCompilerConfig` if VSCode wasn't found, but on macOS and Linux, this
crashes. This fixes the issue by allowing those methods to return `null`
instead of throwing. They still throw by default, but for the test
target they are configured to not pass a toolchain to hooks if none
could be resolved. This means that hooks not invoking the provided
toolchain (say because they're only downloading native artifacts
instead) would now work, whereas previously `flutter test` would crash
if no toolchian was found.
This closes https://github.com/flutter/flutter/issues/178715 (but only
the part shared in the original issue description, @dcharkes suggested
fixing a similar issue in the same PR but that is _not_ done here).