Unverified Commit 4c045e79 authored by Chris Bracken's avatar Chris Bracken Committed by GitHub

Revert "Use Xcode legacy build system for iOS builds (#21901)" (#21966)

This caused issues for projects without an Xcode workspace. Almost all
Flutter projects in the wild will have a workspace, but this patch needs
to add a check to catch any that lack one.

This reverts commit 021f472e.
parent 021f472e
......@@ -71,7 +71,6 @@ Future<T> runInContext<T>(
KernelCompiler: () => const KernelCompiler(),
Logger: () => platform.isWindows ? WindowsStdoutLogger() : StdoutLogger(),
OperatingSystemUtils: () => OperatingSystemUtils(),
PlistBuddy: () => const PlistBuddy(),
SimControl: () => SimControl(),
Stdio: () => const Stdio(),
Usage: () => Usage(),
......
......@@ -32,56 +32,8 @@ const int kXcodeRequiredVersionMajor = 9;
const int kXcodeRequiredVersionMinor = 0;
IMobileDevice get iMobileDevice => context[IMobileDevice];
PlistBuddy get plistBuddy => context[PlistBuddy];
Xcode get xcode => context[Xcode];
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]);
}
}
Xcode get xcode => context[Xcode];
class IMobileDevice {
const IMobileDevice();
......@@ -229,41 +181,6 @@ class Xcode {
}
}
/// 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 File workspaceSettings,
@required bool modern,
}) async {
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,
......@@ -278,12 +195,6 @@ Future<XcodeBuildResult> buildXcodeProject({
if (!_checkXcodeVersion())
return XcodeBuildResult(success: false);
// TODO(cbracken) remove when https://github.com/flutter/flutter/issues/20685 is fixed.
await setXcodeWorkspaceBuildSystem(
workspaceSettings: app.project.xcodeWorkspaceSharedSettings,
modern: false,
);
final XcodeProjectInfo projectInfo = xcodeProjectInterpreter.getInfo(app.project.directory.path);
if (!projectInfo.targets.contains('Runner')) {
printError('The Xcode project does not define target "Runner" which is needed by Flutter tooling.');
......
......@@ -186,15 +186,6 @@ class IosProject {
/// The '.pbxproj' file of the host app.
File get xcodeProjectInfoFile => xcodeProject.childFile('project.pbxproj');
/// Xcode workspace directory of the host app.
Directory get xcodeWorkspace => directory.childDirectory('$_hostAppBundleName.xcworkspace');
/// Xcode workspace shared data directory for the host app.
Directory get xcodeWorkspaceSharedData => xcodeWorkspace.childDirectory('xcshareddata');
/// Xcode workspace shared workspace settings file for the host app.
File get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData.childFile('WorkspaceSettings.xcsettings');
/// The product bundle identifier of the host app, or null if not set or if
/// iOS tooling needed to read it is not installed.
String get productBundleIdentifier {
......
......@@ -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';
......@@ -22,63 +21,6 @@ class MockFile extends Mock implements File {}
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
void main() {
group('PropertyList', () {
MockProcessManager mockProcessManager;
MemoryFileSystem fs;
File workspaceSettingsFile;
setUp(() {
mockProcessManager = MockProcessManager();
fs = MemoryFileSystem();
workspaceSettingsFile = fs.file('WorkspaceSettings.xcsettings');
});
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(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();
when(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]))
.thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 1, '', '')));
await setXcodeWorkspaceBuildSystem(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();
when(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]))
.thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 0, 'FancyNewOne', '')));
await setXcodeWorkspaceBuildSystem(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();
when(mockProcessManager.run(<String>[PlistBuddy.path, '-c', 'Print BuildSystemType', workspaceSettingsFile.path]))
.thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 0, 'Original', '')));
await setXcodeWorkspaceBuildSystem(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';
......
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