Unverified Commit 67b2ca89 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Update minimum required version to Xcode 12 (#77025)

parent 679b8c29
......@@ -72,9 +72,7 @@ const String fixWithDevelopmentTeamInstruction = '''
open ios/Runner.xcworkspace
2- Select the 'Runner' project in the navigator then the 'Runner' target
in the project settings
3- Make sure a 'Development Team' is selected.\u0020
- For Xcode 10, look under General > Signing > Team.
- For Xcode 11 and newer, look under Signing & Capabilities > Team.
3- Make sure a 'Development Team' is selected under Signing & Capabilities > Team.\u0020
You may need to:
- Log in with your Apple ID in Xcode first
- Ensure you have a valid unique Bundle ID
......
......@@ -106,7 +106,7 @@ Future<XcodeBuildResult> buildXcodeProject({
}
final List<ProjectMigrator> migrators = <ProjectMigrator>[
RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.xcode, globals.flutterUsage),
RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.flutterUsage),
XcodeBuildSystemMigration(app.project, globals.logger),
ProjectBaseConfigurationMigration(app.project, globals.logger),
ProjectBuildLocationMigration(app.project, globals.logger),
......
......@@ -8,8 +8,6 @@ import '../../base/common.dart';
import '../../base/file_system.dart';
import '../../base/logger.dart';
import '../../base/project_migrator.dart';
import '../../base/version.dart';
import '../../macos/xcode.dart';
import '../../project.dart';
import '../../reporting/reporting.dart';
......@@ -20,15 +18,12 @@ class RemoveFrameworkLinkAndEmbeddingMigration extends ProjectMigrator {
RemoveFrameworkLinkAndEmbeddingMigration(
IosProject project,
Logger logger,
Xcode xcode,
Usage usage,
) : _xcodeProjectInfoFile = project.xcodeProjectInfoFile,
_xcode = xcode,
_usage = usage,
super(logger);
final File _xcodeProjectInfoFile;
final Xcode _xcode;
final Usage _usage;
@override
......@@ -100,13 +95,10 @@ class RemoveFrameworkLinkAndEmbeddingMigration extends ProjectMigrator {
}
if (line.contains('/* App.framework ') || line.contains('/* Flutter.framework ')) {
// Print scary message if the user is on Xcode 11.4 or greater, or if Xcode isn't installed.
final bool xcodeIsInstalled = _xcode.isInstalled;
if(!xcodeIsInstalled || _xcode.currentVersion >= Version(11, 4, 0)) {
// Print scary message.
UsageEvent('ios-migration', 'remove-frameworks', label: 'failure', flutterUsage: _usage).send();
throwToolExit('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.');
}
}
return line;
}
......
......@@ -29,8 +29,11 @@ import '../ios/mac.dart';
import '../ios/xcodeproj.dart';
import '../reporting/reporting.dart';
Version get xcodeRequiredVersion => Version(11, 0, 0, text: '11.0');
Version get xcodeRecommendedVersion => Version(12, 0, 1, text: '12.0.1');
Version get xcodeRequiredVersion => Version(12, 0, 1, text: '12.0.1');
/// Diverging this number from the minimum required version will provide a doctor
/// warning, not error, that users should upgrade Xcode.
Version get xcodeRecommendedVersion => xcodeRequiredVersion;
/// SDK name passed to `xcrun --sdk`. Corresponds to undocumented Xcode
/// SUPPORTED_PLATFORMS values.
......
......@@ -8,12 +8,10 @@ import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/project_migrator.dart';
import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/ios/migrations/project_base_configuration_migration.dart';
import 'package:flutter_tools/src/ios/migrations/project_build_location_migration.dart';
import 'package:flutter_tools/src/ios/migrations/remove_framework_link_and_embedding_migration.dart';
import 'package:flutter_tools/src/ios/migrations/xcode_build_system_migration.dart';
import 'package:flutter_tools/src/macos/xcode.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:meta/meta.dart';
......@@ -45,11 +43,9 @@ void main () {
BufferLogger testLogger;
MockIosProject mockIosProject;
File xcodeProjectInfoFile;
MockXcode mockXcode;
setUp(() {
memoryFileSystem = MemoryFileSystem.test();
mockXcode = MockXcode();
xcodeProjectInfoFile = memoryFileSystem.file('project.pbxproj');
testLogger = BufferLogger.test();
mockIosProject = MockIosProject();
......@@ -60,7 +56,6 @@ void main () {
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage
);
expect(iosProjectMigration.migrate(), isTrue);
......@@ -80,7 +75,6 @@ void main () {
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate(), isTrue);
......@@ -101,7 +95,6 @@ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate(), isTrue);
......@@ -129,7 +122,6 @@ keep this 2
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate(), isTrue);
......@@ -147,13 +139,10 @@ keep this 2
xcodeProjectInfoFile.writeAsStringSync('''
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
''');
when(mockXcode.isInstalled).thenReturn(true);
when(mockXcode.currentVersion).thenReturn(Version(11, 4, 0));
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
......@@ -167,13 +156,10 @@ keep this 2
xcodeProjectInfoFile.writeAsStringSync('''
9705A1C71CF904A300538480 /* Flutter.framework in Embed Frameworks */,
''');
when(mockXcode.isInstalled).thenReturn(true);
when(mockXcode.currentVersion).thenReturn(Version(11, 4, 0));
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration'));
......@@ -186,68 +172,10 @@ keep this 2
xcodeProjectInfoFile.writeAsStringSync('''
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
''');
when(mockXcode.isInstalled).thenReturn(false);
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration'));
expect(testUsage.events, contains(
const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'),
));
});
testWithoutContext('migration fails on Xcode < 11.4', () {
xcodeProjectInfoFile.writeAsStringSync('''
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
''');
when(mockXcode.isInstalled).thenReturn(true);
when(mockXcode.currentVersion).thenReturn(Version(11, 3, 0));
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate(), isTrue);
expect(testUsage.events, isEmpty);
expect(testLogger.errorText, isEmpty);
});
testWithoutContext('migration fails on Xcode 11.4', () {
xcodeProjectInfoFile.writeAsStringSync('''
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
''');
when(mockXcode.isInstalled).thenReturn(true);
when(mockXcode.currentVersion).thenReturn(Version(11, 4, 0));
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration'));
expect(testUsage.events, contains(
const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'),
));
});
testWithoutContext('migration fails on Xcode 12,0', () {
xcodeProjectInfoFile.writeAsStringSync('''
746232531E83B71900CC1A5E /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 746232521E83B71900CC1A5E /* App.framework */; };
''');
when(mockXcode.isInstalled).thenReturn(true);
when(mockXcode.currentVersion).thenReturn(Version(12, 0, 0));
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
mockIosProject,
testLogger,
mockXcode,
testUsage,
);
expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration'));
......@@ -565,7 +493,6 @@ keep this 3
}
class MockIosProject extends Mock implements IosProject {}
class MockXcode extends Mock implements Xcode {}
class FakeIOSMigrator extends ProjectMigrator {
FakeIOSMigrator({@required this.succeeds})
......
......@@ -151,16 +151,16 @@ void main() {
testWithoutContext('xcodeVersionSatisfactory is true when version meets minimum', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(1);
expect(xcode.isRequiredVersionSatisfactory, isTrue);
});
testWithoutContext('xcodeVersionSatisfactory is true when major version exceeds minimum', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(13);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
......@@ -169,7 +169,7 @@ void main() {
testWithoutContext('xcodeVersionSatisfactory is true when minor version exceeds minimum', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(3);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
......@@ -178,16 +178,16 @@ void main() {
testWithoutContext('xcodeVersionSatisfactory is true when patch version exceeds minimum', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(1);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(2);
expect(xcode.isRequiredVersionSatisfactory, isTrue);
});
testWithoutContext('isRecommendedVersionSatisfactory is false when version is less than minimum', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
......@@ -255,9 +255,9 @@ void main() {
testWithoutContext('isInstalledAndMeetsVersionCheck is true when macOS and installed and version is satisfied', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(1);
expect(xcode.isInstalledAndMeetsVersionCheck, isTrue);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
......
......@@ -69,7 +69,7 @@ void main() {
expect(result.type, ValidationType.partial);
expect(result.messages.last.type, ValidationMessageType.hint);
expect(result.messages.last.message, contains('Xcode 11.0.0 out of date (12.0.1 is recommended)'));
});
}, skip: true); // Unskip and update when minimum and required check versions diverge.
testWithoutContext('Emits partial status when Xcode EULA not signed', () async {
when(xcode.isInstalled).thenReturn(true);
......
......@@ -338,16 +338,16 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
bool get isInstalled => true;
@override
String get versionText => 'Xcode 11.0';
String get versionText => 'Xcode 12.0.1';
@override
int get majorVersion => 11;
int get majorVersion => 12;
@override
int get minorVersion => 0;
@override
int get patchVersion => 0;
int get patchVersion => 1;
@override
Future<Map<String, String>> getBuildSettings(
......
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