Disable CocoaPods input and output paths in Xcode build phase and adopt new Xcode build system (#34167)

Updates the Podfile template to use the CocoaPod disable_input_output_paths installation option which prevents the [CP] Embed Pods Frameworks build phase from outputting the Flutter.framework files.
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 8aec528..bc03cbe 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -94,7 +94,6 @@
       Logger: () => platform.isWindows ? WindowsStdoutLogger() : StdoutLogger(),
       MacOSWorkflow: () => const MacOSWorkflow(),
       OperatingSystemUtils: () => OperatingSystemUtils(),
-      PlistBuddy: () => const PlistBuddy(),
       SimControl: () => SimControl(),
       Stdio: () => const Stdio(),
       SystemClock: () => const SystemClock(),
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index a5cf7c0..cfe4ad4 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -29,55 +29,6 @@
 import 'xcodeproj.dart';
 
 IMobileDevice get iMobileDevice => context.get<IMobileDevice>();
-PlistBuddy get plistBuddy => context.get<PlistBuddy>();
-
-class PlistBuddy {
-  const PlistBuddy();
-
-  static const String path = '/usr/libexec/PlistBuddy';
-
-  Future<ProcessResult> run(List<String> args) => processManager.run(<String>[path]..addAll(args));
-}
-
-/// A property list is a key-value representation commonly used for
-/// configuration on macOS/iOS systems.
-class PropertyList {
-  const PropertyList(this.plistPath);
-
-  final String plistPath;
-
-  /// Prints the specified key, or returns null if not present.
-  Future<String> read(String key) async {
-    final ProcessResult result = await _runCommand('Print $key');
-    if (result.exitCode == 0)
-      return result.stdout.trim();
-    return null;
-  }
-
-  /// Adds [key]. Has no effect if the key already exists.
-  Future<void> addString(String key, String value) async {
-    await _runCommand('Add $key string $value');
-  }
-
-  /// Updates [key] with the new [value]. Has no effect if the key does not exist.
-  Future<void> update(String key, String value) async {
-    await _runCommand('Set $key $value');
-  }
-
-  /// Deletes [key].
-  Future<void> delete(String key) async {
-    await _runCommand('Delete $key');
-  }
-
-  /// Deletes the content of the property list and creates a new root of the specified type.
-  Future<void> clearToDict() async {
-    await _runCommand('Clear dict');
-  }
-
-  Future<ProcessResult> _runCommand(String command) async {
-    return await plistBuddy.run(<String>['-c', command, plistPath]);
-  }
-}
 
 /// Specialized exception for expected situations where the ideviceinfo
 /// tool responds with exit code 255 / 'No device found' message
@@ -150,47 +101,6 @@
   }
 }
 
-/// Sets the Xcode system.
-///
-/// Xcode 10 added a new (default) build system with better performance and
-/// stricter checks. Flutter apps without plugins build fine under the new
-/// system, but it causes build breakages in projects with CocoaPods enabled.
-/// This affects Flutter apps with plugins.
-///
-/// Once Flutter has been updated to be fully compliant with the new build
-/// system, this can be removed.
-//
-// TODO(cbracken): remove when https://github.com/flutter/flutter/issues/20685 is fixed.
-Future<void> setXcodeWorkspaceBuildSystem({
-  @required Directory workspaceDirectory,
-  @required File workspaceSettings,
-  @required bool modern,
-}) async {
-  // If this isn't a workspace, we're not using CocoaPods and can use the new
-  // build system.
-  if (!workspaceDirectory.existsSync())
-    return;
-
-  final PropertyList plist = PropertyList(workspaceSettings.path);
-  if (!workspaceSettings.existsSync()) {
-    workspaceSettings.parent.createSync(recursive: true);
-    await plist.clearToDict();
-  }
-
-  const String kBuildSystemType = 'BuildSystemType';
-  if (modern) {
-    printTrace('Using new Xcode build system.');
-    await plist.delete(kBuildSystemType);
-  } else {
-    printTrace('Using legacy Xcode build system.');
-    if (await plist.read(kBuildSystemType) == null) {
-      await plist.addString(kBuildSystemType, 'Original');
-    } else {
-      await plist.update(kBuildSystemType, 'Original');
-    }
-  }
-}
-
 Future<XcodeBuildResult> buildXcodeProject({
   BuildableIOSApp app,
   BuildInfo buildInfo,
@@ -206,12 +116,6 @@
   if (!_checkXcodeVersion())
     return XcodeBuildResult(success: false);
 
-  // TODO(cbracken): remove when https://github.com/flutter/flutter/issues/20685 is fixed.
-  await setXcodeWorkspaceBuildSystem(
-    workspaceDirectory: app.project.xcodeWorkspace,
-    workspaceSettings: app.project.xcodeWorkspaceSharedSettings,
-    modern: false,
-  );
 
   final XcodeProjectInfo projectInfo = await xcodeProjectInterpreter.getInfo(app.project.hostAppRoot.path);
   if (!projectInfo.targets.contains('Runner')) {
diff --git a/packages/flutter_tools/lib/src/macos/cocoapods.dart b/packages/flutter_tools/lib/src/macos/cocoapods.dart
index 868b0e9..9462395 100644
--- a/packages/flutter_tools/lib/src/macos/cocoapods.dart
+++ b/packages/flutter_tools/lib/src/macos/cocoapods.dart
@@ -57,8 +57,8 @@
 class CocoaPods {
   Future<String> _versionText;
 
-  String get cocoaPodsMinimumVersion => '1.0.0';
-  String get cocoaPodsRecommendedVersion => '1.5.0';
+  String get cocoaPodsMinimumVersion => '1.6.0';
+  String get cocoaPodsRecommendedVersion => '1.6.0';
 
   Future<String> get cocoaPodsVersionText {
     _versionText ??= runAsync(<String>['pod', '--version']).then<String>((RunResult result) {
diff --git a/packages/flutter_tools/templates/cocoapods/Podfile-ios-objc b/packages/flutter_tools/templates/cocoapods/Podfile-ios-objc
index f1f7194..64ba749 100644
--- a/packages/flutter_tools/templates/cocoapods/Podfile-ios-objc
+++ b/packages/flutter_tools/templates/cocoapods/Podfile-ios-objc
@@ -60,6 +60,9 @@
   }
 end
 
+# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
+install! 'cocoapods', :disable_input_output_paths => true
+
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
diff --git a/packages/flutter_tools/templates/cocoapods/Podfile-ios-swift b/packages/flutter_tools/templates/cocoapods/Podfile-ios-swift
index 3f49388..e9286cb 100644
--- a/packages/flutter_tools/templates/cocoapods/Podfile-ios-swift
+++ b/packages/flutter_tools/templates/cocoapods/Podfile-ios-swift
@@ -62,6 +62,9 @@
   }
 end
 
+# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
+install! 'cocoapods', :disable_input_output_paths => true
+
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
diff --git a/packages/flutter_tools/templates/cocoapods/Podfile-macos b/packages/flutter_tools/templates/cocoapods/Podfile-macos
index ddc00d9..45f3262 100644
--- a/packages/flutter_tools/templates/cocoapods/Podfile-macos
+++ b/packages/flutter_tools/templates/cocoapods/Podfile-macos
@@ -79,3 +79,6 @@
     end
   }
 end
+
+# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
+install! 'cocoapods', :disable_input_output_paths => true
diff --git a/packages/flutter_tools/test/commands/create_test.dart b/packages/flutter_tools/test/commands/create_test.dart
index 3707b62..22fe447 100644
--- a/packages/flutter_tools/test/commands/create_test.dart
+++ b/packages/flutter_tools/test/commands/create_test.dart
@@ -507,8 +507,8 @@
 
     await runner.run(<String>['create', '--template=module', '--no-pub', '--org', 'com.foo.bar', projectDir.path]);
 
-    void expectExists(String relPath) {
-      expect(fs.isFileSync('${projectDir.path}/$relPath'), true);
+    void expectExists(String relPath, [bool expectation = true]) {
+      expect(fs.isFileSync('${projectDir.path}/$relPath'), expectation);
     }
 
     expectExists('lib/main.dart');
@@ -549,6 +549,9 @@
     final File xcodeProjectFile = fs.file(fs.path.join(projectDir.path, xcodeProjectPath));
     final String xcodeProject = xcodeProjectFile.readAsStringSync();
     expect(xcodeProject, contains('PRODUCT_BUNDLE_IDENTIFIER = com.foo.bar.flutterProject'));
+    // Xcode build system
+    final String xcodeWorkspaceSettingsPath = fs.path.join('.ios', 'Runner.xcworkspace', 'xcshareddata', 'WorkspaceSettings.xcsettings');
+    expectExists(xcodeWorkspaceSettingsPath, false);
 
     final String versionPath = fs.path.join('.metadata');
     expectExists(versionPath);
diff --git a/packages/flutter_tools/test/ios/mac_test.dart b/packages/flutter_tools/test/ios/mac_test.dart
index ba50d7e..8124ed8 100644
--- a/packages/flutter_tools/test/ios/mac_test.dart
+++ b/packages/flutter_tools/test/ios/mac_test.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 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/io.dart' show ProcessException, ProcessResult;
 import 'package:flutter_tools/src/ios/mac.dart';
@@ -29,73 +28,6 @@
 class MockIosProject extends Mock implements IosProject {}
 
 void main() {
-  group('PropertyList', () {
-    MockProcessManager mockProcessManager;
-    MemoryFileSystem fs;
-    Directory workspaceDirectory;
-    File workspaceSettingsFile;
-
-    setUp(() {
-      mockProcessManager = MockProcessManager();
-      fs = MemoryFileSystem();
-      workspaceDirectory = fs.directory('Runner.xcworkspace');
-      workspaceSettingsFile = workspaceDirectory.childDirectory('xcshareddata').childFile('WorkspaceSettings.xcsettings');
-    });
-
-    testUsingContext('does nothing if workspace directory does not exist', () async {
-      await setXcodeWorkspaceBuildSystem(workspaceDirectory: workspaceDirectory, workspaceSettings: workspaceSettingsFile, modern: false);
-      verifyNever(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]));
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-      ProcessManager: () => mockProcessManager,
-    });
-
-    testUsingContext('creates dict-based plist if settings file does not exist', () async {
-      workspaceSettingsFile.parent.createSync(recursive: true);
-      when(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]))
-        .thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 1, '', '')));
-      await setXcodeWorkspaceBuildSystem(workspaceDirectory: workspaceDirectory, workspaceSettings: workspaceSettingsFile, modern: false);
-      verify(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Clear dict', workspaceSettingsFile.path]));
-      verify(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Add BuildSystemType string Original', workspaceSettingsFile.path]));
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-      ProcessManager: () => mockProcessManager,
-    });
-
-    testUsingContext('writes legacy build mode settings if requested and not present', () async {
-      workspaceSettingsFile.createSync(recursive: true);
-      when(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]))
-        .thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 1, '', '')));
-      await setXcodeWorkspaceBuildSystem(workspaceDirectory: workspaceDirectory, workspaceSettings: workspaceSettingsFile, modern: false);
-      verify(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Add BuildSystemType string Original', workspaceSettingsFile.path]));
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-      ProcessManager: () => mockProcessManager,
-    });
-
-    testUsingContext('updates legacy build mode setting if requested and existing setting is present', () async {
-      workspaceSettingsFile.createSync(recursive: true);
-      when(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]))
-        .thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 0, 'FancyNewOne', '')));
-      await setXcodeWorkspaceBuildSystem(workspaceDirectory: workspaceDirectory, workspaceSettings: workspaceSettingsFile, modern: false);
-      verify(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Set BuildSystemType Original', workspaceSettingsFile.path]));
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-      ProcessManager: () => mockProcessManager,
-    });
-
-    testUsingContext('deletes legacy build mode setting if modern build mode requested', () async {
-      workspaceSettingsFile.createSync(recursive: true);
-      when(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]))
-        .thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 0, 'Original', '')));
-      await setXcodeWorkspaceBuildSystem(workspaceDirectory: workspaceDirectory, workspaceSettings: workspaceSettingsFile, modern: true);
-      verify(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Delete BuildSystemType', workspaceSettingsFile.path]));
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-      ProcessManager: () => mockProcessManager,
-    });
-  });
-
   group('IMobileDevice', () {
     final FakePlatform osx = FakePlatform.fromPlatform(const LocalPlatform())
       ..operatingSystem = 'macos';
diff --git a/packages/flutter_tools/test/macos/cocoapods_test.dart b/packages/flutter_tools/test/macos/cocoapods_test.dart
index 82b8aa9..bc2afa6 100644
--- a/packages/flutter_tools/test/macos/cocoapods_test.dart
+++ b/packages/flutter_tools/test/macos/cocoapods_test.dart
@@ -60,7 +60,7 @@
     projectUnderTest = FlutterProject.fromDirectory(fs.directory('project'));
     projectUnderTest.ios.xcodeProject.createSync(recursive: true);
     cocoaPodsUnderTest = CocoaPods();
-    pretendPodVersionIs('1.5.0');
+    pretendPodVersionIs('1.6.0');
     fs.file(fs.path.join(
       Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-objc',
     ))
@@ -123,28 +123,21 @@
     });
 
     testUsingContext('detects below minimum version', () async {
-      pretendPodVersionIs('0.39.8');
+      pretendPodVersionIs('1.5.0');
       expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.belowMinimumVersion);
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
     });
 
-    testUsingContext('detects below recommended version', () async {
-      pretendPodVersionIs('1.4.99');
-      expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.belowRecommendedVersion);
-    }, overrides: <Type, Generator>{
-      ProcessManager: () => mockProcessManager,
-    });
-
     testUsingContext('detects at recommended version', () async {
-      pretendPodVersionIs('1.5.0');
+      pretendPodVersionIs('1.6.0');
       expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended);
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
     });
 
     testUsingContext('detects above recommended version', () async {
-      pretendPodVersionIs('1.5.1');
+      pretendPodVersionIs('1.6.1');
       expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended);
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,