From f52eaaea082470a7ed1b04db9fd91cbaf4adfae1 Mon Sep 17 00:00:00 2001 From: Lau Ching Jun Date: Tue, 23 Jan 2024 11:49:10 -0800 Subject: [PATCH] Allow overriding the native assets yaml file in the resident runner. (#142016) This is used when the native assets are built by a separate build system. Context: b/286799303 --- .../lib/src/commands/attach.dart | 4 ++ .../flutter_tools/lib/src/commands/run.dart | 2 + packages/flutter_tools/lib/src/run_hot.dart | 34 +++++---- .../lib/src/runner/flutter_command.dart | 9 +++ .../commands.shard/hermetic/attach_test.dart | 1 + .../general.shard/resident_runner_test.dart | 69 ++++++++++++++++++- 6 files changed, 105 insertions(+), 14 deletions(-) diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart index 615e7e392e7..2589a2aaff8 100644 --- a/packages/flutter_tools/lib/src/commands/attach.dart +++ b/packages/flutter_tools/lib/src/commands/attach.dart @@ -90,6 +90,7 @@ class AttachCommand extends FlutterCommand { addEnableExperimentation(hide: !verboseHelp); addNullSafetyModeOptions(hide: !verboseHelp); usesInitializeFromDillOption(hide: !verboseHelp); + usesNativeAssetsOption(hide: !verboseHelp); argParser ..addOption( 'debug-port', @@ -539,6 +540,7 @@ known, it can be explicitly provided to attach via the command-line, e.g. dillOutputPath: stringArg('output-dill'), ipv6: usesIpv6, flutterProject: flutterProject, + nativeAssetsYamlFile: stringArg(FlutterOptions.kNativeAssetsYamlFile), analytics: analytics, ) : ColdRunner( @@ -572,6 +574,7 @@ class HotRunnerFactory { bool stayResident = true, bool ipv6 = false, FlutterProject? flutterProject, + String? nativeAssetsYamlFile, required Analytics analytics, }) => HotRunner( devices, @@ -584,6 +587,7 @@ class HotRunnerFactory { dillOutputPath: dillOutputPath, stayResident: stayResident, ipv6: ipv6, + nativeAssetsYamlFile: nativeAssetsYamlFile, analytics: analytics, ); } diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 45cca988773..73bd2893bdb 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -331,6 +331,7 @@ class RunCommand extends RunCommandBase { usesFrontendServerStarterPathOption(verboseHelp: verboseHelp); addEnableExperimentation(hide: !verboseHelp); usesInitializeFromDillOption(hide: !verboseHelp); + usesNativeAssetsOption(hide: !verboseHelp); // By default, the app should to publish the VM service port over mDNS. // This will allow subsequent "flutter attach" commands to connect to the VM @@ -641,6 +642,7 @@ class RunCommand extends RunCommandBase { ipv6: ipv6 ?? false, multidexEnabled: boolArg('multidex'), analytics: globals.analytics, + nativeAssetsYamlFile: stringArg(FlutterOptions.kNativeAssetsYamlFile), ); } else if (webMode) { return webRunnerFactory!.createWebRunner( diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index 740b18961e7..91252605e94 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -95,11 +95,13 @@ class HotRunner extends ResidentRunner { ReloadSourcesHelper reloadSourcesHelper = defaultReloadSourcesHelper, ReassembleHelper reassembleHelper = _defaultReassembleHelper, NativeAssetsBuildRunner? buildRunner, + String? nativeAssetsYamlFile, required Analytics analytics, }) : _stopwatchFactory = stopwatchFactory, _reloadSourcesHelper = reloadSourcesHelper, _reassembleHelper = reassembleHelper, _buildRunner = buildRunner, + _nativeAssetsYamlFile = nativeAssetsYamlFile, _analytics = analytics, super( hotMode: true, @@ -140,6 +142,7 @@ class HotRunner extends ResidentRunner { bool? _emulator; NativeAssetsBuildRunner? _buildRunner; + final String? _nativeAssetsYamlFile; String? flavor; @@ -371,19 +374,24 @@ class HotRunner extends ResidentRunner { }) async { await _calculateTargetPlatform(); - final Uri projectUri = Uri.directory(projectRootPath); - _buildRunner ??= NativeAssetsBuildRunnerImpl( - projectUri, - debuggingOptions.buildInfo.packageConfig, - fileSystem, - globals.logger, - ); - final Uri? nativeAssetsYaml = await dryRunNativeAssets( - projectUri: projectUri, - fileSystem: fileSystem, - buildRunner: _buildRunner!, - flutterDevices: flutterDevices, - ); + final Uri? nativeAssetsYaml; + if (_nativeAssetsYamlFile != null) { + nativeAssetsYaml = globals.fs.path.toUri(_nativeAssetsYamlFile); + } else { + final Uri projectUri = Uri.directory(projectRootPath); + _buildRunner ??= NativeAssetsBuildRunnerImpl( + projectUri, + debuggingOptions.buildInfo.packageConfig, + fileSystem, + globals.logger, + ); + nativeAssetsYaml = await dryRunNativeAssets( + projectUri: projectUri, + fileSystem: fileSystem, + buildRunner: _buildRunner!, + flutterDevices: flutterDevices, + ); + } final Stopwatch appStartedTimer = Stopwatch()..start(); final File mainFile = globals.fs.file(mainPath); diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 906c9aba7f2..355ed345b49 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -150,6 +150,7 @@ abstract final class FlutterOptions { static const String kAndroidProjectArgs = 'android-project-arg'; static const String kInitializeFromDill = 'initialize-from-dill'; static const String kAssumeInitializeFromDillUpToDate = 'assume-initialize-from-dill-up-to-date'; + static const String kNativeAssetsYamlFile = 'native-assets-yaml-file'; static const String kFatalWarnings = 'fatal-warnings'; static const String kUseApplicationBinary = 'use-application-binary'; static const String kWebBrowserFlag = 'web-browser-flag'; @@ -1007,6 +1008,14 @@ abstract class FlutterCommand extends Command { ); } + void usesNativeAssetsOption({ required bool hide }) { + argParser.addOption(FlutterOptions.kNativeAssetsYamlFile, + help: 'Initializes the resident compiler with a custom native assets ' + 'yaml file instead of the default cached location.', + hide: hide, + ); + } + void addMultidexOption({ bool hide = false }) { argParser.addFlag('multidex', defaultsTo: true, diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart index ceda608b3e5..775632d1c40 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart @@ -1208,6 +1208,7 @@ class FakeHotRunnerFactory extends Fake implements HotRunnerFactory { bool ipv6 = false, FlutterProject? flutterProject, Analytics? analytics, + String? nativeAssetsYamlFile, }) { if (_artifactTester != null) { for (final FlutterDevice device in devices) { diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart index 1ddc051075f..ae000ea0a6e 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart @@ -2455,12 +2455,14 @@ flutter: targetPlatform: TargetPlatform.darwin, sdkNameAndVersion: 'Macos', ); + final FakeResidentCompiler residentCompiler = FakeResidentCompiler(); final FakeFlutterDevice flutterDevice = FakeFlutterDevice() ..testUri = testUri ..vmServiceHost = (() => fakeVmServiceHost) ..device = device .._devFS = devFS - ..targetPlatform = TargetPlatform.darwin; + ..targetPlatform = TargetPlatform.darwin + ..generator = residentCompiler; fakeVmServiceHost = FakeVmServiceHost(requests: [ listViews, @@ -2508,6 +2510,67 @@ flutter: expect(buildRunner.dryRunInvocations, 1); expect(buildRunner.hasPackageConfigInvocations, 1); expect(buildRunner.packagesWithNativeAssetsInvocations, 1); + + expect(residentCompiler.recompileCalled, true); + expect(residentCompiler.receivedNativeAssetsYaml.toString(), endsWith('native_assets/macos/native_assets.yaml')); + }), + overrides: { + ProcessManager: () => FakeProcessManager.any(), + FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true, isMacOSEnabled: true), + }); + + testUsingContext( + 'use the nativeAssetsYamlFile when provided', + () => testbed.run(() async { + final FakeDevice device = FakeDevice( + targetPlatform: TargetPlatform.darwin, + sdkNameAndVersion: 'Macos', + ); + final FakeResidentCompiler residentCompiler = FakeResidentCompiler(); + final FakeFlutterDevice flutterDevice = FakeFlutterDevice() + ..testUri = testUri + ..vmServiceHost = (() => fakeVmServiceHost) + ..device = device + .._devFS = devFS + ..targetPlatform = TargetPlatform.darwin + ..generator = residentCompiler; + + fakeVmServiceHost = FakeVmServiceHost(requests: [ + listViews, + listViews, + ]); + globals.fs + .file(globals.fs.path.join('lib', 'main.dart')) + .createSync(recursive: true); + final FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(); + residentRunner = HotRunner( + [ + flutterDevice, + ], + stayResident: false, + debuggingOptions: DebuggingOptions.enabled(const BuildInfo( + BuildMode.debug, + '', + treeShakeIcons: false, + trackWidgetCreation: true, + )), + target: 'main.dart', + devtoolsHandler: createNoOpHandler, + buildRunner: buildRunner, + analytics: fakeAnalytics, + nativeAssetsYamlFile: 'foo.yaml', + ); + + final int? result = await residentRunner.run(); + expect(result, 0); + + expect(buildRunner.buildInvocations, 0); + expect(buildRunner.dryRunInvocations, 0); + expect(buildRunner.hasPackageConfigInvocations, 0); + expect(buildRunner.packagesWithNativeAssetsInvocations, 0); + + expect(residentCompiler.recompileCalled, true); + expect(residentCompiler.receivedNativeAssetsYaml, globals.fs.path.toUri('foo.yaml')); }), overrides: { ProcessManager: () => FakeProcessManager.any(), @@ -2700,6 +2763,8 @@ class FakeDelegateFlutterDevice extends FlutterDevice { class FakeResidentCompiler extends Fake implements ResidentCompiler { CompilerOutput? nextOutput; bool didSuppressErrors = false; + Uri? receivedNativeAssetsYaml; + bool recompileCalled = false; @override Future recompile( @@ -2714,6 +2779,8 @@ class FakeResidentCompiler extends Fake implements ResidentCompiler { File? dartPluginRegistrant, Uri? nativeAssetsYaml, }) async { + recompileCalled = true; + receivedNativeAssetsYaml = nativeAssetsYaml; didSuppressErrors = suppressErrors; return nextOutput ?? const CompilerOutput('foo.dill', 0, []); }