Unverified Commit 52a6de25 authored by Matan Lurey's avatar Matan Lurey Committed by GitHub

Add `--local-engine-host`, which if specified, is used instead of being inferred (#132180)

Closes https://github.com/flutter/flutter/issues/132162.

I did a tiny bit of minor cleanup but didn't want to go 🍔 beyond the
scope of this change. After it lands I'll update the Wiki.

## Before

```bash
$ fl run \
  --local-engine-src-path=$ENGINE \
  --local-engine=android_debug_unopt_arm64
```

... would try to use `host_debug_unopt` (i.e. Rosetta).

## After

```bash
$ fl run \
  --local-engine-src-path=$ENGINE \
  --local-engine=android_debug_unopt_arm64 \
  --local-engine-host=host_debug_unopt_arm64
```

... uses `host_debug_unopt_arm64`, as specified.

---

/cc @jonahwilliams @gaaclarke @zanderso
parent bd1bb675
...@@ -28,8 +28,8 @@ SPEC CHECKSUMS: ...@@ -28,8 +28,8 @@ SPEC CHECKSUMS:
connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9 connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
PODFILE CHECKSUM: 2e6060c123c393d6beb3ee5b7beaf789de4d2e47 PODFILE CHECKSUM: 2e6060c123c393d6beb3ee5b7beaf789de4d2e47
COCOAPODS: 1.12.0 COCOAPODS: 1.12.1
...@@ -308,6 +308,12 @@ class UserMessages { ...@@ -308,6 +308,12 @@ class UserMessages {
"you have compiled the engine in that directory, which should produce an 'out' directory"; "you have compiled the engine in that directory, which should produce an 'out' directory";
String get runnerLocalEngineOrWebSdkRequired => String get runnerLocalEngineOrWebSdkRequired =>
'You must specify --local-engine or --local-web-sdk if you are using a locally built engine or web sdk.'; 'You must specify --local-engine or --local-web-sdk if you are using a locally built engine or web sdk.';
// TODO(matanlurey): Make this an error, https://github.com/flutter/flutter/issues/132245.
String get runnerLocalEngineRequiresHostEngine =>
'Warning! You are using a locally built engine (--local-engine) but have not specified --local-host-engine.\n'
'You may be building with a different engine than the one you are running with. '
'See https://github.com/flutter/flutter/issues/132245 for details (in the future this will become '
'an error).';
String runnerNoEngineBuild(String engineBuildPath) => String runnerNoEngineBuild(String engineBuildPath) =>
'No Flutter engine build found at $engineBuildPath.'; 'No Flutter engine build found at $engineBuildPath.';
String runnerNoWebSdk(String webSdkPath) => String runnerNoWebSdk(String webSdkPath) =>
......
...@@ -30,6 +30,7 @@ abstract final class FlutterGlobalOptions { ...@@ -30,6 +30,7 @@ abstract final class FlutterGlobalOptions {
static const String kEnableTelemetryFlag = 'enable-telemetry'; static const String kEnableTelemetryFlag = 'enable-telemetry';
static const String kLocalEngineOption = 'local-engine'; static const String kLocalEngineOption = 'local-engine';
static const String kLocalEngineSrcPathOption = 'local-engine-src-path'; static const String kLocalEngineSrcPathOption = 'local-engine-src-path';
static const String kLocalEngineHostOption = 'local-engine-host';
static const String kLocalWebSDKOption = 'local-web-sdk'; static const String kLocalWebSDKOption = 'local-web-sdk';
static const String kMachineFlag = 'machine'; static const String kMachineFlag = 'machine';
static const String kPackagesOption = 'packages'; static const String kPackagesOption = 'packages';
...@@ -131,6 +132,13 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -131,6 +132,13 @@ class FlutterCommandRunner extends CommandRunner<void> {
'Use this to select a specific version of the engine if you have built multiple engine targets.\n' 'Use this to select a specific version of the engine if you have built multiple engine targets.\n'
'This path is relative to "--local-engine-src-path" (see above).'); 'This path is relative to "--local-engine-src-path" (see above).');
argParser.addOption(FlutterGlobalOptions.kLocalEngineHostOption,
hide: !verboseHelp,
help: 'The host operating system for which engine artifacts should be selected, if you are building Flutter locally.\n'
'This is only used when "--local-engine" is also specified.\n'
'By default, the host is determined automatically, but you may need to specify this if you are building on one '
'platform (e.g. MacOS ARM64) but intend to run Flutter on another (e.g. Android).');
argParser.addOption(FlutterGlobalOptions.kLocalWebSDKOption, argParser.addOption(FlutterGlobalOptions.kLocalWebSDKOption,
hide: !verboseHelp, hide: !verboseHelp,
help: 'Name of a build output within the engine out directory, if you are building Flutter locally.\n' help: 'Name of a build output within the engine out directory, if you are building Flutter locally.\n'
...@@ -273,6 +281,7 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -273,6 +281,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
final EngineBuildPaths? engineBuildPaths = await globals.localEngineLocator?.findEnginePath( final EngineBuildPaths? engineBuildPaths = await globals.localEngineLocator?.findEnginePath(
engineSourcePath: topLevelResults[FlutterGlobalOptions.kLocalEngineSrcPathOption] as String?, engineSourcePath: topLevelResults[FlutterGlobalOptions.kLocalEngineSrcPathOption] as String?,
localEngine: topLevelResults[FlutterGlobalOptions.kLocalEngineOption] as String?, localEngine: topLevelResults[FlutterGlobalOptions.kLocalEngineOption] as String?,
localHostEngine: topLevelResults[FlutterGlobalOptions.kLocalEngineHostOption] as String?,
localWebSdk: topLevelResults[FlutterGlobalOptions.kLocalWebSDKOption] as String?, localWebSdk: topLevelResults[FlutterGlobalOptions.kLocalWebSDKOption] as String?,
packagePath: topLevelResults[FlutterGlobalOptions.kPackagesOption] as String?, packagePath: topLevelResults[FlutterGlobalOptions.kPackagesOption] as String?,
); );
......
...@@ -13,7 +13,7 @@ import '../base/user_messages.dart' hide userMessages; ...@@ -13,7 +13,7 @@ import '../base/user_messages.dart' hide userMessages;
import '../cache.dart'; import '../cache.dart';
import '../dart/package_map.dart'; import '../dart/package_map.dart';
/// A strategy for locating the out/ directory of a local engine build. /// A strategy for locating the `out/` directory of a local engine build.
/// ///
/// The flutter tool can be run with the output files of one or more engine builds /// The flutter tool can be run with the output files of one or more engine builds
/// replacing the cached artifacts. Typically this is done by setting the /// replacing the cached artifacts. Typically this is done by setting the
...@@ -25,7 +25,7 @@ import '../dart/package_map.dart'; ...@@ -25,7 +25,7 @@ import '../dart/package_map.dart';
/// For scenarios where the engine is not adjacent to flutter, the /// For scenarios where the engine is not adjacent to flutter, the
/// `--local-engine-src-path` can be provided to give an exact path. /// `--local-engine-src-path` can be provided to give an exact path.
/// ///
/// For more information on local engines, see CONTRIBUTING.md. /// For more information on local engines, see README.md.
class LocalEngineLocator { class LocalEngineLocator {
LocalEngineLocator({ LocalEngineLocator({
required Platform platform, required Platform platform,
...@@ -46,7 +46,13 @@ class LocalEngineLocator { ...@@ -46,7 +46,13 @@ class LocalEngineLocator {
final UserMessages _userMessages; final UserMessages _userMessages;
/// Returns the engine build path of a local engine if one is located, otherwise `null`. /// Returns the engine build path of a local engine if one is located, otherwise `null`.
Future<EngineBuildPaths?> findEnginePath({String? engineSourcePath, String? localEngine, String? localWebSdk, String? packagePath}) async { Future<EngineBuildPaths?> findEnginePath({
String? engineSourcePath,
String? localEngine,
String? localHostEngine,
String? localWebSdk,
String? packagePath,
}) async {
engineSourcePath ??= _platform.environment[kFlutterEngineEnvironmentVariableName]; engineSourcePath ??= _platform.environment[kFlutterEngineEnvironmentVariableName];
if (engineSourcePath == null && localEngine == null && localWebSdk == null && packagePath == null) { if (engineSourcePath == null && localEngine == null && localWebSdk == null && packagePath == null) {
return null; return null;
...@@ -81,7 +87,12 @@ class LocalEngineLocator { ...@@ -81,7 +87,12 @@ class LocalEngineLocator {
if (engineSourcePath != null) { if (engineSourcePath != null) {
_logger.printTrace('Local engine source at $engineSourcePath'); _logger.printTrace('Local engine source at $engineSourcePath');
return _findEngineBuildPath(localEngine, localWebSdk, engineSourcePath); return _findEngineBuildPath(
engineSourcePath: engineSourcePath,
localEngine: localEngine,
localWebSdk: localWebSdk,
localHostEngine: localHostEngine,
);
} }
if (localEngine != null || localWebSdk != null) { if (localEngine != null || localWebSdk != null) {
throwToolExit( throwToolExit(
...@@ -176,7 +187,12 @@ class LocalEngineLocator { ...@@ -176,7 +187,12 @@ class LocalEngineLocator {
return 'host_$tmpBasename'; return 'host_$tmpBasename';
} }
EngineBuildPaths _findEngineBuildPath(String? localEngine, String? localWebSdk, String enginePath) { EngineBuildPaths _findEngineBuildPath({
required String engineSourcePath,
String? localEngine,
String? localWebSdk,
String? localHostEngine,
}) {
if (localEngine == null && localWebSdk == null) { if (localEngine == null && localWebSdk == null) {
throwToolExit(_userMessages.runnerLocalEngineOrWebSdkRequired, exitCode: 2); throwToolExit(_userMessages.runnerLocalEngineOrWebSdkRequired, exitCode: 2);
} }
...@@ -184,12 +200,16 @@ class LocalEngineLocator { ...@@ -184,12 +200,16 @@ class LocalEngineLocator {
String? engineBuildPath; String? engineBuildPath;
String? engineHostBuildPath; String? engineHostBuildPath;
if (localEngine != null) { if (localEngine != null) {
engineBuildPath = _fileSystem.path.normalize(_fileSystem.path.join(enginePath, 'out', localEngine)); engineBuildPath = _fileSystem.path.normalize(_fileSystem.path.join(engineSourcePath, 'out', localEngine));
if (!_fileSystem.isDirectorySync(engineBuildPath)) { if (!_fileSystem.isDirectorySync(engineBuildPath)) {
throwToolExit(_userMessages.runnerNoEngineBuild(engineBuildPath), exitCode: 2); throwToolExit(_userMessages.runnerNoEngineBuild(engineBuildPath), exitCode: 2);
} }
final String basename = _fileSystem.path.basename(engineBuildPath); if (localHostEngine == null) {
// TODO(matanlurey): https://github.com/flutter/flutter/issues/132245, change to throwToolExit.
_logger.printStatus(_userMessages.runnerLocalEngineRequiresHostEngine);
}
final String basename = localHostEngine ?? _fileSystem.path.basename(engineBuildPath);
final String hostBasename = _getHostEngineBasename(basename); final String hostBasename = _getHostEngineBasename(basename);
engineHostBuildPath = _fileSystem.path.normalize( engineHostBuildPath = _fileSystem.path.normalize(
_fileSystem.path.join(_fileSystem.path.dirname(engineBuildPath), hostBasename), _fileSystem.path.join(_fileSystem.path.dirname(engineBuildPath), hostBasename),
...@@ -201,7 +221,7 @@ class LocalEngineLocator { ...@@ -201,7 +221,7 @@ class LocalEngineLocator {
String? webSdkPath; String? webSdkPath;
if (localWebSdk != null) { if (localWebSdk != null) {
webSdkPath = _fileSystem.path.normalize(_fileSystem.path.join(enginePath, 'out', localWebSdk)); webSdkPath = _fileSystem.path.normalize(_fileSystem.path.join(engineSourcePath, 'out', localWebSdk));
if (!_fileSystem.isDirectorySync(webSdkPath)) { if (!_fileSystem.isDirectorySync(webSdkPath)) {
throwToolExit(_userMessages.runnerNoWebSdk(webSdkPath), exitCode: 2); throwToolExit(_userMessages.runnerNoWebSdk(webSdkPath), exitCode: 2);
} }
......
...@@ -93,6 +93,58 @@ void main() { ...@@ -93,6 +93,58 @@ void main() {
expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src')); expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src'));
}); });
testWithoutContext('works if --local-engine is specified and --local-engine-host is specified', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory localEngine = fileSystem
.directory('$kArbitraryEngineRoot/src/out/android_debug_unopt_arm64/')
..createSync(recursive: true);
fileSystem.directory('$kArbitraryEngineRoot/src/out/host_debug_unopt_arm64/').createSync(recursive: true);
final BufferLogger logger = BufferLogger.test();
final LocalEngineLocator localEngineLocator = LocalEngineLocator(
fileSystem: fileSystem,
flutterRoot: 'flutter/flutter',
logger: logger,
userMessages: UserMessages(),
platform: FakePlatform(environment: <String, String>{}),
);
expect(
await localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: 'host_debug_unopt_arm64'),
matchesEngineBuildPaths(
hostEngine: '/arbitrary/engine/src/out/host_debug_unopt_arm64',
targetEngine: '/arbitrary/engine/src/out/android_debug_unopt_arm64',
),
);
expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src'));
});
testWithoutContext('works but produces a warning if --local-engine is specified but not --local-host-engine', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory localEngine = fileSystem
.directory('$kArbitraryEngineRoot/src/out/android_debug_unopt_arm64/')
..createSync(recursive: true);
fileSystem.directory('$kArbitraryEngineRoot/src/out/host_debug_unopt/').createSync(recursive: true);
final BufferLogger logger = BufferLogger.test();
final LocalEngineLocator localEngineLocator = LocalEngineLocator(
fileSystem: fileSystem,
flutterRoot: 'flutter/flutter',
logger: logger,
userMessages: UserMessages(),
platform: FakePlatform(environment: <String, String>{}),
);
expect(
await localEngineLocator.findEnginePath(localEngine: localEngine.path),
matchesEngineBuildPaths(
hostEngine: '/arbitrary/engine/src/out/host_debug_unopt',
targetEngine: '/arbitrary/engine/src/out/android_debug_unopt_arm64',
),
);
expect(logger.statusText, contains('Warning! You are using a locally built engine (--local-engine) but have not specified --local-host-engine'));
});
testWithoutContext('works if --local-engine is specified and --local-engine-src-path ' testWithoutContext('works if --local-engine is specified and --local-engine-src-path '
'is determined by --local-engine', () async { 'is determined by --local-engine', () async {
final FileSystem fileSystem = MemoryFileSystem.test(); final FileSystem fileSystem = MemoryFileSystem.test();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment