Visitar URL original
[flutter_tools] Add flutter assemble support for tool extension build targets by bkonyi · Pull Request #193984 · flutter/flutter · GitHub
Skip to content

[flutter_tools] Add flutter assemble support for tool extension build targets - #193984

Draft
bkonyi wants to merge 4 commits into
flutter:masterfrom
bkonyi:ft-ext-step07b-build-remaining-slice
Draft

bkonyi wants to merge 4 commits into
flutter:masterfrom
bkonyi:ft-ext-step07b-build-remaining-slice

Conversation

@bkonyi

@bkonyi bkonyi commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Extends BuildService and package:flutter_tools_core so tool extensions can define Target nodes (ExtensionTarget) with Source, Artifact, and HostArtifact inputs/outputs and dependencies on built-in or custom targets. Integrates ExtensionAssembleTarget into flutter assemble and flutter build so extension-provided targets can execute within the Flutter build graph and receive resolved environment paths and engine artifacts over RPC via ExtensionBuildContext.

Part of #180258

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • 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].
  • All existing and new tests are passing.

… targets

Extends `BuildService` and `package:flutter_tools_core` to support `flutter assemble` targets contributed by tool extensions (`ExtensionAssembleTarget`, `ExtensionTarget`, `ExtensionBuildContext`, `Source`, `Artifact`, `HostArtifact`, and `Target`), allowing extension targets to participate in the build graph alongside built-in targets.
@bkonyi bkonyi added the CICD Run CI/CD label Oct 8, 2026
@bkonyi
bkonyi requested review from a team as code owners October 8, 2026 02:50
@bkonyi
bkonyi requested review from mboetger and removed request for a team October 8, 2026 02:50
@github-actions github-actions Bot added tool Affects the "flutter" command-line tool. See also t: labels. team-android Owned by Android platform team team-ios Owned by iOS platform team team-macos Owned by the macOS platform team team-linux Owned by the Linux platform team labels Oct 8, 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 integrates custom build targets defined by tool extensions into the Flutter build system, updating AssembleCommand and BuildCommand to discover and execute these targets, and expanding the prototype Linux extension with several concrete build targets. The review feedback highlights potential crashes from unhandled ArgumentErrors when parsing invalid platform strings with TargetPlatform.fromName in ExtensionAssembleTarget, ArtifactResolver, and ExtensionBuildSubCommand, recommending wrapping these in try-catch blocks to throw user-friendly ToolExits. Additionally, a more robust path extraction method is suggested in the Linux prototype's directory copying logic to avoid potential truncation bugs when trailing separators are present.

Comment on lines +65 to +71
final resolver = ArtifactResolver(
artifacts: artifacts,
buildMode: mode,
targetPlatform: buildTarget.targetPlatform.isNotEmpty
? TargetPlatform.fromName(buildTarget.targetPlatform)
: 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

TargetPlatform.fromName throws an ArgumentError if the platform name string is invalid or unrecognized. Since tool extensions are external and can define arbitrary platform strings (or have typos), calling TargetPlatform.fromName directly without a try-catch block will cause the Flutter tool to crash with an unhandled exception and a raw stack trace.

Wrapping this call in a try-catch block and throwing a user-friendly ToolExit instead ensures a much better user experience, in line with our style guide principle that error messages should be useful.

Suggested change
final resolver = ArtifactResolver(
artifacts: artifacts,
buildMode: mode,
targetPlatform: buildTarget.targetPlatform.isNotEmpty
? TargetPlatform.fromName(buildTarget.targetPlatform)
: null,
);
TargetPlatform? targetPlatform;
if (buildTarget.targetPlatform.isNotEmpty) {
try {
targetPlatform = TargetPlatform.fromName(buildTarget.targetPlatform);
} on ArgumentError {
throwToolExit('Invalid target platform "${buildTarget.targetPlatform}" for extension build target "${buildTarget.name}".');
}
}
final resolver = ArtifactResolver(
artifacts: artifacts,
buildMode: mode,
targetPlatform: targetPlatform,
);
References
  1. Error messages should be useful: Every error message is an opportunity to make someone love our product. (link)

Comment on lines +114 to +116
final TargetPlatform? platform = platformName != null
? TargetPlatform.fromName(platformName)
: 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

Similarly, if platformName is invalid here, TargetPlatform.fromName will throw an ArgumentError and crash the build process with a raw stack trace. We should handle this gracefully by catching the error and throwing a ToolExit.

Suggested change
final TargetPlatform? platform = platformName != null
? TargetPlatform.fromName(platformName)
: null;
TargetPlatform? platform;
if (platformName != null) {
try {
platform = TargetPlatform.fromName(platformName);
} on ArgumentError {
throwToolExit('Invalid platform name "$platformName" for artifact "${artifact.name}".');
}
}
References
  1. Error messages should be useful: Every error message is an opportunity to make someone love our product. (link)

Comment on lines +332 to +338
final resolver = ArtifactResolver(
artifacts: artifacts,
buildMode: buildInfo.mode,
targetPlatform: target.targetPlatform.isNotEmpty
? TargetPlatform.fromName(target.targetPlatform)
: 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

TargetPlatform.fromName throws an ArgumentError if the platform name string is invalid or unrecognized. We should wrap this call in a try-catch block and throw a user-friendly ToolExit to prevent raw crashes when processing invalid platform strings from tool extensions.

Suggested change
final resolver = ArtifactResolver(
artifacts: artifacts,
buildMode: buildInfo.mode,
targetPlatform: target.targetPlatform.isNotEmpty
? TargetPlatform.fromName(target.targetPlatform)
: null,
);
TargetPlatform? targetPlatform;
if (target.targetPlatform.isNotEmpty) {
try {
targetPlatform = TargetPlatform.fromName(target.targetPlatform);
} on ArgumentError {
throwToolExit('Invalid target platform "${target.targetPlatform}" for extension build target "${target.name}".');
}
}
final resolver = ArtifactResolver(
artifacts: artifacts,
buildMode: buildInfo.mode,
targetPlatform: targetPlatform,
);
References
  1. Error messages should be useful: Every error message is an opportunity to make someone love our product. (link)

Comment on lines +398 to 405
for (final FileSystemEntity entity in source.listSync()) {
final String name = entity.path.substring(source.path.length + 1);
if (entity is Directory) {
_copyDirectory(entity, Directory('${destination.path}/$name'));
} else if (entity is File) {
entity.copySync('${destination.path}/$name');
}
return ExtensionBuildResult(success: false, errorMessage: 'Unknown build target: $targetName');
}

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

Using entity.path.substring(source.path.length + 1) to extract the relative name of the file or directory assumes that source.path does not end with a separator (like /). If source.path ends with a separator, source.path.length + 1 will slice too far and truncate the first character of the child's name, causing a bug/file copy failure.

A much more robust and standard way is to use entity.uri.pathSegments.lastWhere((e) => e.isNotEmpty) to get the base name of the entity, which works perfectly regardless of trailing slashes.

Suggested change
for (final FileSystemEntity entity in source.listSync()) {
final String name = entity.path.substring(source.path.length + 1);
if (entity is Directory) {
_copyDirectory(entity, Directory('${destination.path}/$name'));
} else if (entity is File) {
entity.copySync('${destination.path}/$name');
}
return ExtensionBuildResult(success: false, errorMessage: 'Unknown build target: $targetName');
}
for (final FileSystemEntity entity in source.listSync()) {
final String name = entity.uri.pathSegments.lastWhere((e) => e.isNotEmpty);
if (entity is Directory) {
_copyDirectory(entity, Directory('${destination.path}/$name'));
} else if (entity is File) {
entity.copySync('${destination.path}/$name');
}
}

@bkonyi
bkonyi removed request for a team and mboetger October 8, 2026 16:50
@LouiseHsu

Copy link
Copy Markdown
Contributor

from triage: is this ready for review? :)

@bkonyi
bkonyi marked this pull request as draft October 8, 2026 22:57
Keep host Source and Target untouched in flutter_tools and convert extension Sources inside ExtensionAssembleTarget, reverting changes to built-in targets and Source.fromProject.
@github-actions github-actions Bot removed team-android Owned by Android platform team team-ios Owned by iOS platform team team-macos Owned by the macOS platform team labels Oct 8, 2026
@bkonyi

bkonyi commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

from triage: is this ready for review? :)

Not yet! I'll mark it as Draft :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

2 participants