From fdd023fa5943baa772e3f8cd7bf0813dacd5622e Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Tue, 10 Mar 2020 10:11:16 -0700 Subject: [PATCH] Migrate older Xcode projects off the legacy build system (#52288) --- packages/flutter_tools/lib/src/ios/mac.dart | 4 +- .../lib/src/ios/migrations/ios_migrator.dart | 5 +- ...ramework_link_and_embedding_migration.dart | 11 +-- .../xcode_build_system_migration.dart | 48 +++++++++++ .../ios/ios_project_migration_test.dart | 79 +++++++++++++++++++ 5 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 packages/flutter_tools/lib/src/ios/migrations/xcode_build_system_migration.dart diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart index 6d6bb4df6ab..82e09df39c1 100644 --- a/packages/flutter_tools/lib/src/ios/mac.dart +++ b/packages/flutter_tools/lib/src/ios/mac.dart @@ -24,6 +24,7 @@ import '../reporting/reporting.dart'; import 'code_signing.dart'; import 'migrations/ios_migrator.dart'; import 'migrations/remove_framework_link_and_embedding_migration.dart'; +import 'migrations/xcode_build_system_migration.dart'; import 'xcodeproj.dart'; class IMobileDevice { @@ -90,7 +91,8 @@ Future buildXcodeProject({ } final List migrators = [ - RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.xcode, globals.flutterUsage) + RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.xcode, globals.flutterUsage), + XcodeBuildSystemMigration(app.project, globals.logger), ]; final IOSMigration migration = IOSMigration(migrators); diff --git a/packages/flutter_tools/lib/src/ios/migrations/ios_migrator.dart b/packages/flutter_tools/lib/src/ios/migrations/ios_migrator.dart index 2353b7dd5a8..7965e6699c8 100644 --- a/packages/flutter_tools/lib/src/ios/migrations/ios_migrator.dart +++ b/packages/flutter_tools/lib/src/ios/migrations/ios_migrator.dart @@ -20,7 +20,10 @@ abstract class IOSMigrator { bool migrate(); /// Return null if the line should be deleted. - String migrateLine(String line); + @protected + String migrateLine(String line) { + return line; + } @protected void processFileLines(File file) { diff --git a/packages/flutter_tools/lib/src/ios/migrations/remove_framework_link_and_embedding_migration.dart b/packages/flutter_tools/lib/src/ios/migrations/remove_framework_link_and_embedding_migration.dart index 755163465ff..462701bd48e 100644 --- a/packages/flutter_tools/lib/src/ios/migrations/remove_framework_link_and_embedding_migration.dart +++ b/packages/flutter_tools/lib/src/ios/migrations/remove_framework_link_and_embedding_migration.dart @@ -10,9 +10,9 @@ import '../../project.dart'; import '../../reporting/reporting.dart'; import 'ios_migrator.dart'; -/// Xcode 11.4 requires linked and embedded frameworks to contain all targeted architectures before build phases are run. -/// This caused issues switching between a real device and simulator due to architecture mismatch. -/// Remove the linking and embedding logic from the Xcode project to give the tool more control over these. +// Xcode 11.4 requires linked and embedded frameworks to contain all targeted architectures before build phases are run. +// This caused issues switching between a real device and simulator due to architecture mismatch. +// Remove the linking and embedding logic from the Xcode project to give the tool more control over these. class RemoveFrameworkLinkAndEmbeddingMigration extends IOSMigrator { RemoveFrameworkLinkAndEmbeddingMigration( IosProject project, @@ -28,13 +28,8 @@ class RemoveFrameworkLinkAndEmbeddingMigration extends IOSMigrator { final Xcode _xcode; final Usage _usage; - /// Inspect [project] for necessary migrations and rewrite files as needed. @override bool migrate() { - return _migrateXcodeProjectInfoFile(); - } - - bool _migrateXcodeProjectInfoFile() { if (!_xcodeProjectInfoFile.existsSync()) { logger.printTrace('Xcode project not found, skipping migration'); return true; diff --git a/packages/flutter_tools/lib/src/ios/migrations/xcode_build_system_migration.dart b/packages/flutter_tools/lib/src/ios/migrations/xcode_build_system_migration.dart new file mode 100644 index 00000000000..0faf22ba542 --- /dev/null +++ b/packages/flutter_tools/lib/src/ios/migrations/xcode_build_system_migration.dart @@ -0,0 +1,48 @@ +// 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/logger.dart'; +import '../../project.dart'; +import 'ios_migrator.dart'; + +// Xcode legacy build system no longer supported by Xcode. +// Set in https://github.com/flutter/flutter/pull/21901/. +// Removed in https://github.com/flutter/flutter/pull/33684. +class XcodeBuildSystemMigration extends IOSMigrator { + XcodeBuildSystemMigration( + IosProject project, + Logger logger, + ) : _xcodeWorkspaceSharedSettings = project.xcodeWorkspaceSharedSettings, + super(logger); + + final File _xcodeWorkspaceSharedSettings; + + @override + bool migrate() { + if (!_xcodeWorkspaceSharedSettings.existsSync()) { + logger.printTrace('Xcode workspace settings not found, skipping migration'); + return true; + } + + final String contents = _xcodeWorkspaceSharedSettings.readAsStringSync(); + + // Only delete this file when it matches the original Flutter template. + const String legacyBuildSettingsWorkspace = ''' + + + BuildSystemType + Original + +'''; + + // contains instead of equals to ignore newline file ending variance. + if (contents.contains(legacyBuildSettingsWorkspace)) { + logger.printStatus('Legacy build system detected, removing ${_xcodeWorkspaceSharedSettings.path}'); + _xcodeWorkspaceSharedSettings.deleteSync(); + } + + return true; + } +} diff --git a/packages/flutter_tools/test/general.shard/ios/ios_project_migration_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_project_migration_test.dart index 04f926701f1..7e9c7a25865 100644 --- a/packages/flutter_tools/test/general.shard/ios/ios_project_migration_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/ios_project_migration_test.dart @@ -12,6 +12,7 @@ import 'package:platform/platform.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/terminal.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'; @@ -257,6 +258,84 @@ keep this 2 verify(mockUsage.sendEvent('ios-migration', 'remove-frameworks', label: 'failure', value: null)); }); }); + + group('new Xcode build system', () { + MemoryFileSystem memoryFileSystem; + BufferLogger testLogger; + MockIosProject mockIosProject; + File xcodeWorkspaceSharedSettings; + + setUp(() { + memoryFileSystem = MemoryFileSystem(); + xcodeWorkspaceSharedSettings = memoryFileSystem.file('WorkspaceSettings.xcsettings'); + + testLogger = BufferLogger( + terminal: AnsiTerminal( + stdio: null, + platform: const LocalPlatform(), + ), + outputPreferences: OutputPreferences.test(), + ); + + mockIosProject = MockIosProject(); + when(mockIosProject.xcodeWorkspaceSharedSettings).thenReturn(xcodeWorkspaceSharedSettings); + }); + + testWithoutContext('skipped if files are missing', () { + final XcodeBuildSystemMigration iosProjectMigration = XcodeBuildSystemMigration( + mockIosProject, + testLogger, + ); + expect(iosProjectMigration.migrate(), isTrue); + expect(xcodeWorkspaceSharedSettings.existsSync(), isFalse); + + expect(testLogger.traceText, contains('Xcode workspace settings not found, skipping migration')); + expect(testLogger.statusText, isEmpty); + }); + + testWithoutContext('skipped if nothing to upgrade', () { + const String contents = ''' + + + + + BuildSystemType + + +'''; + xcodeWorkspaceSharedSettings.writeAsStringSync(contents); + + final XcodeBuildSystemMigration iosProjectMigration = XcodeBuildSystemMigration( + mockIosProject, + testLogger, + ); + expect(iosProjectMigration.migrate(), isTrue); + expect(xcodeWorkspaceSharedSettings.existsSync(), isTrue); + expect(testLogger.statusText, isEmpty); + }); + + testWithoutContext('Xcode project is migrated', () { + const String contents = ''' + + + + + BuildSystemType + Original + +'''; + xcodeWorkspaceSharedSettings.writeAsStringSync(contents); + + final XcodeBuildSystemMigration iosProjectMigration = XcodeBuildSystemMigration( + mockIosProject, + testLogger, + ); + expect(iosProjectMigration.migrate(), isTrue); + expect(xcodeWorkspaceSharedSettings.existsSync(), isFalse); + + expect(testLogger.statusText, contains('Legacy build system detected, removing')); + }); + }); }); }