[flutter_tools] opt iOS/macOS apps out of Metal API validation via migrator, update templates in repo. (#159228)

Setting "enableGPUValidationMode = "1"" disables Metal API validation. I
know, I know.

Fixes https://github.com/flutter/flutter/issues/159227
This commit is contained in:
Jonah Williams 2024-11-20 17:36:55 -08:00 committed by GitHub
parent b473698019
commit f7869a4799
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 219 additions and 0 deletions

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
enableGPUFrameCaptureMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -59,6 +59,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -59,6 +59,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -58,6 +58,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -52,6 +52,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -50,6 +50,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -59,6 +59,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -36,6 +36,7 @@ import 'application_package.dart';
import 'code_signing.dart';
import 'migrations/host_app_info_plist_migration.dart';
import 'migrations/ios_deployment_target_migration.dart';
import 'migrations/metal_api_validation_migration.dart';
import 'migrations/project_base_configuration_migration.dart';
import 'migrations/project_build_location_migration.dart';
import 'migrations/remove_bitcode_migration.dart';
@ -178,6 +179,7 @@ Future<XcodeBuildResult> buildXcodeProject({
features: featureFlags,
),
SwiftPackageManagerGitignoreMigration(project, globals.logger),
MetalAPIValidationMigrator.ios(app.project, globals.logger),
];
final ProjectMigration migration = ProjectMigration(migrators);

View File

@ -0,0 +1,50 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../../base/file_system.dart';
import '../../base/project_migrator.dart';
import '../../xcode_project.dart';
/// Remove Metal API validation setting that slows down applications.
class MetalAPIValidationMigrator extends ProjectMigrator {
MetalAPIValidationMigrator.ios(
IosProject project,
super.logger,
) : _xcodeProjectScheme = project.xcodeProjectSchemeFile();
MetalAPIValidationMigrator.macos(
MacOSProject project,
super.logger,
) : _xcodeProjectScheme = project.xcodeProjectSchemeFile();
final File _xcodeProjectScheme;
@override
Future<void> migrate() async {
if (_xcodeProjectScheme.existsSync()) {
processFileLines(_xcodeProjectScheme);
} else {
logger.printTrace('default xcscheme file not found. Skipping Metal API validation migration.');
}
}
@override
String migrateFileContents(String fileContents) {
// If this string is anywhere in the file, assume that either we already
// migrated it or the developer made an intentional choice to opt in or out.
if (fileContents.contains('enableGPUValidationMode')) {
return fileContents;
}
// Look for a setting that is included in LaunchAction by default and
// insert the opt out after it.
final RegExp kDebugServiceExtension = RegExp('(\\s)*debugServiceExtension = "internal"\n');
const String kValidationString = 'enableGPUValidationMode = "1"';
return fileContents.replaceFirstMapped(kDebugServiceExtension, (Match match) {
final String group = match.group(0)!;
final int leadingCount = group.split('debugServiceExtension')[0].codeUnits.where((int codeUnit) => codeUnit == 32).length;
return '$group${' ' * leadingCount}$kValidationString\n';
});
}
}

View File

@ -15,6 +15,7 @@ import '../build_info.dart';
import '../convert.dart';
import '../features.dart';
import '../globals.dart' as globals;
import '../ios/migrations/metal_api_validation_migration.dart';
import '../ios/xcode_build_settings.dart';
import '../ios/xcodeproj.dart';
import '../migrations/swift_package_manager_gitignore_migration.dart';
@ -103,6 +104,7 @@ Future<void> buildMacOS({
features: featureFlags,
),
SwiftPackageManagerGitignoreMigration(flutterProject, globals.logger),
MetalAPIValidationMigrator.macos(flutterProject.macos, globals.logger),
];
final ProjectMigration migration = ProjectMigration(migrators);

View File

@ -79,6 +79,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -79,6 +79,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -79,6 +79,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -37,6 +37,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<PathRunnable
runnableDebuggingMode = "0"

View File

@ -0,0 +1,132 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/ios/migrations/metal_api_validation_migration.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
void main() {
testWithoutContext('Adds Metal API setting to matching file', () {
final FileSystem fs = MemoryFileSystem.test();
final File file = fs.file('test_file')
..createSync()
..writeAsStringSync('''
<?xml version="1.0" encoding="UTF-8"?>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
''');
final FakeIosProject project = FakeIosProject(file);
final MetalAPIValidationMigrator validator = MetalAPIValidationMigrator.ios(project, BufferLogger.test());
expect(() async => validator.migrate(), returnsNormally);
expect(file.readAsStringSync(), contains(
'debugServiceExtension = "internal"'
'\n enableGPUValidationMode = "1"'));
});
testWithoutContext('Adds Metal API setting to matching file and crazy indentation', () {
final FileSystem fs = MemoryFileSystem.test();
final File file = fs.file('test_file')
..createSync()
..writeAsStringSync('''
<?xml version="1.0" encoding="UTF-8"?>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
''');
final FakeIosProject project = FakeIosProject(file);
final MetalAPIValidationMigrator validator = MetalAPIValidationMigrator.ios(project, BufferLogger.test());
expect(() async => validator.migrate(), returnsNormally);
expect(file.readAsStringSync(), contains(
'debugServiceExtension = "internal"'
'\n enableGPUValidationMode = "1"'));
});
testWithoutContext('Skips modifying file that already references Metal API setting', () {
final FileSystem fs = MemoryFileSystem.test();
final File file = fs.file('test_file')
..createSync()
..writeAsStringSync('''
<?xml version="1.0" encoding="UTF-8"?>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
''');
final FakeIosProject project = FakeIosProject(file);
final MetalAPIValidationMigrator validator = MetalAPIValidationMigrator.ios(project, BufferLogger.test());
final String initialContents = file.readAsStringSync();
expect(() async => validator.migrate(), returnsNormally);
expect(file.readAsStringSync(), initialContents);
});
testWithoutContext('No-op on file with no match', () {
final FileSystem fs = MemoryFileSystem.test();
final File file = fs.file('does_not_exist')
..createSync()
..writeAsStringSync('NO_OP');
final FakeIosProject project = FakeIosProject(file);
final MetalAPIValidationMigrator validator = MetalAPIValidationMigrator.ios(project, BufferLogger.test());
expect(() async => validator.migrate(), returnsNormally);
expect(file.readAsStringSync(), 'NO_OP');
});
testWithoutContext('No-op on missing file', () async {
final FileSystem fs = MemoryFileSystem.test();
final FakeIosProject project = FakeIosProject(fs.file('does_not_exist'));
final MetalAPIValidationMigrator validator = MetalAPIValidationMigrator.ios(project, BufferLogger.test());
expect(() async => validator.migrate(), returnsNormally);
});
}
class FakeIosProject extends Fake implements IosProject {
FakeIosProject(this._file);
final File _file;
@override
File xcodeProjectSchemeFile({String? scheme}) {
return _file;
}
}