-
Notifications
You must be signed in to change notification settings - Fork 30.5k
Fix hooks inputs outputs rebuilt #186701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix hooks inputs outputs rebuilt #186701
Changes from all commits
fc54789
9d5de55
91bfdc5
b3c1566
de55565
28dff0e
21e0207
67c7fc6
2f51a43
6c5d0e9
22fd24d
077878f
08cd19a
d822048
b5309dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,3 +29,6 @@ migrate_working_dir/ | |
| .flutter-plugins-dependencies | ||
| /build/ | ||
| /coverage/ | ||
|
|
||
| # Generated test file. | ||
| data/generated.txt | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,8 +57,8 @@ class BuildHooks extends Target { | |
| final FlutterNativeAssetsBuildRunner buildRunner = | ||
| _buildRunner ?? await createFlutterNativeAssetsBuildRunner(environment); | ||
| final ( | ||
| results: SerializedBuildResults results, | ||
| dependencies: List<Uri> dependencies, | ||
| :SerializedBuildResults results, | ||
| :DartHooksResult buildResult, | ||
| ) = await runFlutterSpecificBuildHooks( | ||
| environmentDefines: environment.defines, | ||
| buildRunner: buildRunner, | ||
|
|
@@ -74,11 +74,20 @@ class BuildHooks extends Target { | |
| dartBuildOutputJsonFile.parent.createSync(recursive: true); | ||
| } | ||
|
|
||
| dartBuildOutputJsonFile.writeAsStringSync(json.encode(results)); | ||
| final String encodedResults = json.encode(results); | ||
| if (!dartBuildOutputJsonFile.existsSync() || | ||
| dartBuildOutputJsonFile.readAsStringSync() != encodedResults) { | ||
| dartBuildOutputJsonFile.writeAsStringSync(encodedResults); | ||
| } | ||
|
|
||
| final Set<Uri> buildDependencies = buildResult.dependencies.toSet(); | ||
| final depfile = Depfile( | ||
| <File>[for (final Uri dependency in dependencies) fileSystem.file(dependency)], | ||
| <File>[fileSystem.file(dartBuildOutputJsonFile)], | ||
| <File>[for (final Uri dependency in buildResult.dependencies) fileSystem.file(dependency)], | ||
| <File>[ | ||
| fileSystem.file(dartBuildOutputJsonFile), | ||
| for (final Uri uri in buildResult.filesToBeBundled) | ||
| if (!buildDependencies.contains(uri)) fileSystem.file(uri), | ||
| ], | ||
| ); | ||
|
Comment on lines
84
to
91
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The final Set<Uri> buildDependencies = buildResult.dependencies.toSet();
final depfile = Depfile(
<File>[for (final Uri dependency in buildResult.dependencies) fileSystem.file(dependency)],
<File>[
fileSystem.file(dartBuildOutputJsonFile),
for (final Uri uri in buildResult.filesToBeBundled)
if (!buildDependencies.contains(uri)) fileSystem.file(uri),
],
);
dcharkes marked this conversation as resolved.
|
||
| final File outputDepfile = environment.buildDir.childFile(depFilename); | ||
| if (!outputDepfile.parent.existsSync()) { | ||
|
|
@@ -98,7 +107,6 @@ class BuildHooks extends Target { | |
| // If different packages are resolved, different native assets might need to | ||
| // be built. | ||
| Source.pattern('{WORKSPACE_DIR}/.dart_tool/package_config.json'), | ||
| // TODO(mosuem): Should consume resources.json. https://github.com/flutter/flutter/issues/146263 | ||
| ]; | ||
|
|
||
| @override | ||
|
|
@@ -197,6 +205,8 @@ class LinkHooks extends Target { | |
| final buildMode = BuildMode.fromCliName(buildModeEnvironment); | ||
| final File? recordedUsesFileToPass = getRecordedUsesFile(environment, buildMode); | ||
|
|
||
| final linkingEnabled = buildMode != BuildMode.debug; | ||
|
|
||
| // Read the result of BuildHooks. | ||
| final File dartBuildOutputJsonFile = environment.buildDir.childFile(BuildHooks.resultFilename); | ||
| if (!dartBuildOutputJsonFile.existsSync()) { | ||
|
|
@@ -207,29 +217,52 @@ class LinkHooks extends Target { | |
| final Map<String, Map<String, Object?>> buildResults = serializedBuildResults | ||
| .cast<String, Map<String, Object?>>(); | ||
|
|
||
| final DartHooksResult result = await runFlutterSpecificLinkHooks( | ||
| final DartHooksResult linkResult; | ||
| if (linkingEnabled) { | ||
| linkResult = await runFlutterSpecificLinkHooks( | ||
| environmentDefines: environment.defines, | ||
| buildRunner: buildRunner, | ||
| targetPlatform: targetPlatform, | ||
| projectUri: projectUri, | ||
| fileSystem: fileSystem, | ||
| buildCodeAssets: BuildCodeAssetsOptions(appBuildDirectory: environment.outputDir), | ||
| buildDataAssets: true, | ||
| buildResults: buildResults, | ||
| recordedUsesFile: recordedUsesFileToPass, | ||
| ); | ||
| } else { | ||
| linkResult = DartHooksResult.empty(); | ||
| } | ||
|
|
||
| final DartHooksResult combinedResult = combineBuildAndLinkResults( | ||
| environmentDefines: environment.defines, | ||
| buildRunner: buildRunner, | ||
| targetPlatform: targetPlatform, | ||
| projectUri: projectUri, | ||
| fileSystem: fileSystem, | ||
| buildCodeAssets: BuildCodeAssetsOptions(appBuildDirectory: environment.outputDir), | ||
| buildDataAssets: true, | ||
| buildResults: buildResults, | ||
| recordedUsesFile: recordedUsesFileToPass, | ||
| linkResult: linkResult, | ||
| ); | ||
|
|
||
| final File dartHookResultJsonFile = environment.buildDir.childFile(resultFilename); | ||
| if (!dartHookResultJsonFile.parent.existsSync()) { | ||
| dartHookResultJsonFile.parent.createSync(recursive: true); | ||
| } | ||
| dartHookResultJsonFile.writeAsStringSync(json.encode(result.toJson())); | ||
|
|
||
| // TODO(dcharkes): The build system uses file hashing to determine if | ||
| // targets need to be rerun. Because combinedResult.toJson() includes | ||
| // transient build_start and build_end times, this file is rewritten on | ||
| // every build causing downstream targets to rerun. We should remove | ||
| // build_start and build_end from the JSON representation entirely in a | ||
| // future PR. | ||
| dartHookResultJsonFile.writeAsStringSync(json.encode(combinedResult.toJson())); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To optimize incremental builds, the output JSON file should only be written if its content has changed. This prevents updating the file's modification timestamp unnecessarily, which avoids triggering downstream targets (like final String encodedResult = json.encode(combinedResult.toJson());
if (!dartHookResultJsonFile.existsSync() ||
dartHookResultJsonFile.readAsStringSync() != encodedResult) {
dartHookResultJsonFile.writeAsStringSync(encodedResult);
}
dcharkes marked this conversation as resolved.
|
||
| final Set<Uri> linkDependencies = linkResult.dependencies.toSet(); | ||
| final depfile = Depfile( | ||
| <File>[for (final Uri dependency in result.dependencies) fileSystem.file(dependency)], | ||
| <File>[for (final Uri dependency in linkResult.dependencies) fileSystem.file(dependency)], | ||
| <File>[ | ||
| fileSystem.file(dartHookResultJsonFile), | ||
| for (final Uri uri in result.filesToBeBundled) fileSystem.file(uri), | ||
| if (linkingEnabled) | ||
| for (final Uri uri in linkResult.filesToBeBundled) | ||
| if (!linkDependencies.contains(uri)) fileSystem.file(uri), | ||
| ], | ||
| ); | ||
|
Comment on lines
259
to
267
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same O(N*M) complexity issue as in final Set<Uri> linkDependencies = linkResult.dependencies.toSet();
final depfile = Depfile(
<File>[for (final Uri dependency in linkResult.dependencies) fileSystem.file(dependency)],
<File>[
fileSystem.file(dartHookResultJsonFile),
if (linkingEnabled)
for (final Uri uri in linkResult.filesToBeBundled)
if (!linkDependencies.contains(uri)) fileSystem.file(uri),
],
);
dcharkes marked this conversation as resolved.
|
||
| final File outputDepfile = environment.buildDir.childFile(depFilename); | ||
|
|
@@ -278,8 +311,8 @@ class InstallCodeAssets extends Target { | |
| final FileSystem fileSystem = environment.fileSystem; | ||
| final TargetPlatform targetPlatform = _getTargetPlatformFromEnvironment(environment, name); | ||
|
|
||
| // We fetch the result from the [LinkHooks]. | ||
| final DartHooksResult dartHookResult = await LinkHooks.loadHookResult(environment); | ||
| // We fetch the combined result from the [LinkHooks]. | ||
| final DartHooksResult combinedResult = await LinkHooks.loadHookResult(environment); | ||
|
|
||
| // And install/copy the code assets to the right place and create a | ||
| // native_asset.yaml that can be used by the final AOT compilation. | ||
|
|
@@ -293,7 +326,7 @@ class InstallCodeAssets extends Target { | |
| } | ||
|
|
||
| final List<File> installedFiles = await installCodeAssets( | ||
| dartHookResult: dartHookResult, | ||
| dartHookResult: combinedResult, | ||
| environmentDefines: environment.defines, | ||
| targetPlatform: targetPlatform, | ||
| projectUri: projectUri, | ||
|
|
@@ -304,7 +337,7 @@ class InstallCodeAssets extends Target { | |
| assert(fileSystem.file(nativeAssetsFileUri).existsSync()); | ||
|
|
||
| final depfile = Depfile(<File>[ | ||
| for (final Uri file in dartHookResult.filesToBeBundled) fileSystem.file(file), | ||
| for (final Uri file in combinedResult.filesToBeBundled) fileSystem.file(file), | ||
| ], installedFiles); | ||
| final File outputDepfile = environment.buildDir.childFile(depFilename); | ||
| environment.depFileService.writeToFile(depfile, outputDepfile); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need to bind
resultsat all here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think records destructuring has a ... rest syntax. I tried a bunch of different syntaxes but the analyzer stays unhappy. Would you enlighten me what the right syntax is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, disregard. Gemini lied to me when I asked if
final (:DartHooksResult buildResult) = await runFlutterSpecificBuildHooks(...)was valid 🤦