mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Revert pod install skip revert (#13774)
* Revert "Revert "Enable developers to run pod from terminal directly and skip pod install if possible. (#13374)" (#13770)" This reverts commit 0759043e47395b692bff7d6aa045c1ecb06627eb. * some nits on cocoapods code * put back the FLUTTER_FRAMEWORK_DIR env variable
This commit is contained in:
parent
0759043e47
commit
4d2c2aaaa1
@ -24,7 +24,7 @@ class InjectPluginsCommand extends FlutterCommand {
|
||||
|
||||
@override
|
||||
Future<Null> runCommand() async {
|
||||
final bool result = injectPlugins();
|
||||
final bool result = injectPlugins().hasPlugin;
|
||||
if (result) {
|
||||
printStatus('GeneratedPluginRegistrants successfully written.');
|
||||
} else {
|
||||
|
||||
@ -57,18 +57,21 @@ class CocoaPods {
|
||||
|
||||
Future<Null> processPods({
|
||||
@required Directory appIosDir,
|
||||
// For backward compatibility with previously created Podfile only.
|
||||
@required String iosEngineDir,
|
||||
bool isSwift: false,
|
||||
bool pluginOrFlutterPodChanged: true,
|
||||
}) async {
|
||||
if (await _checkPodCondition()) {
|
||||
if (!fs.file(fs.path.join(appIosDir.path, 'Podfile')).existsSync()) {
|
||||
await _createPodfile(appIosDir, isSwift);
|
||||
} // TODO(xster): Add more logic for handling merge conflicts.
|
||||
|
||||
await _runPodInstall(appIosDir, iosEngineDir);
|
||||
if (_shouldRunPodInstall(appIosDir.path, pluginOrFlutterPodChanged))
|
||||
await _runPodInstall(appIosDir, iosEngineDir);
|
||||
}
|
||||
}
|
||||
|
||||
/// Make sure the CocoaPods tools are in the right states.
|
||||
Future<bool> _checkPodCondition() async {
|
||||
if (!await isCocoaPodsInstalledAndMeetsVersionCheck) {
|
||||
final String minimumVersion = cocoaPodsMinimumVersion;
|
||||
@ -108,12 +111,36 @@ class CocoaPods {
|
||||
podfileTemplate.copySync(fs.path.join(bundle.path, 'Podfile'));
|
||||
}
|
||||
|
||||
// Check if you need to run pod install.
|
||||
// The pod install will run if any of below is true.
|
||||
// 1. Any plugins changed (add/update/delete)
|
||||
// 2. The flutter.framework has changed (debug/release/profile)
|
||||
// 3. The podfile.lock doesn't exists
|
||||
// 4. The Pods/manifest.lock doesn't exists
|
||||
// 5. The podfile.lock doesn't match Pods/manifest.lock.
|
||||
bool _shouldRunPodInstall(String appDir, bool pluginOrFlutterPodChanged) {
|
||||
if (pluginOrFlutterPodChanged)
|
||||
return true;
|
||||
// Check if podfile.lock and Pods/Manifest.lock exists and matches.
|
||||
final File podfileLockFile = fs.file(fs.path.join(appDir, 'Podfile.lock'));
|
||||
final File manifestLockFile =
|
||||
fs.file(fs.path.join(appDir, 'Pods', 'Manifest.lock'));
|
||||
if (!podfileLockFile.existsSync()
|
||||
|| !manifestLockFile.existsSync()
|
||||
|| podfileLockFile.readAsStringSync() !=
|
||||
manifestLockFile.readAsStringSync()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<Null> _runPodInstall(Directory bundle, String engineDirectory) async {
|
||||
final Status status = logger.startProgress('Running pod install...', expectSlowOperation: true);
|
||||
final ProcessResult result = await processManager.run(
|
||||
<String>['pod', 'install', '--verbose'],
|
||||
workingDirectory: bundle.path,
|
||||
environment: <String, String>{
|
||||
// For backward compatibility with previously created Podfile only.
|
||||
'FLUTTER_FRAMEWORK_DIR': engineDirectory,
|
||||
// See https://github.com/flutter/flutter/issues/10873.
|
||||
// CocoaPods analytics adds a lot of latency.
|
||||
|
||||
@ -254,14 +254,9 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
// copied over to a location that is suitable for Xcodebuild to find them.
|
||||
final Directory appDirectory = fs.directory(app.appDirectory);
|
||||
await _addServicesToBundle(appDirectory);
|
||||
final bool hasFlutterPlugins = injectPlugins();
|
||||
|
||||
if (hasFlutterPlugins)
|
||||
await cocoaPods.processPods(
|
||||
appIosDir: appDirectory,
|
||||
iosEngineDir: flutterFrameworkDir(buildInfo.mode),
|
||||
isSwift: app.isSwift,
|
||||
);
|
||||
final InjectPluginsResult injectPluginsResult = injectPlugins();
|
||||
final bool hasFlutterPlugins = injectPluginsResult.hasPlugin;
|
||||
final String previousGeneratedXcconfig = readGeneratedXcconfig(app.appDirectory);
|
||||
|
||||
updateXcodeGeneratedProperties(
|
||||
projectPath: fs.currentDirectory.path,
|
||||
@ -271,6 +266,17 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
previewDart2: buildInfo.previewDart2,
|
||||
);
|
||||
|
||||
if (hasFlutterPlugins) {
|
||||
final String currentGeneratedXcconfig = readGeneratedXcconfig(app.appDirectory);
|
||||
await cocoaPods.processPods(
|
||||
appIosDir: appDirectory,
|
||||
iosEngineDir: flutterFrameworkDir(buildInfo.mode),
|
||||
isSwift: app.isSwift,
|
||||
pluginOrFlutterPodChanged: (injectPluginsResult.hasChanged
|
||||
|| previousGeneratedXcconfig != currentGeneratedXcconfig),
|
||||
);
|
||||
}
|
||||
|
||||
final List<String> commands = <String>[
|
||||
'/usr/bin/env',
|
||||
'xcrun',
|
||||
@ -355,7 +361,17 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
}
|
||||
}
|
||||
|
||||
Future<Null> diagnoseXcodeBuildFailure(XcodeBuildResult result, BuildableIOSApp app) async {
|
||||
String readGeneratedXcconfig(String appPath) {
|
||||
final String generatedXcconfigPath =
|
||||
fs.path.join(fs.currentDirectory.path, appPath, 'Flutter','Generated.xcconfig');
|
||||
final File generatedXcconfigFile = fs.file(generatedXcconfigPath);
|
||||
if (!generatedXcconfigFile.existsSync())
|
||||
return null;
|
||||
return generatedXcconfigFile.readAsStringSync();
|
||||
}
|
||||
|
||||
Future<Null> diagnoseXcodeBuildFailure(
|
||||
XcodeBuildResult result, BuildableIOSApp app) async {
|
||||
if (result.xcodeBuildExecution != null &&
|
||||
result.xcodeBuildExecution.buildForPhysicalDevice &&
|
||||
result.stdout?.contains('BCEROR') == true &&
|
||||
@ -369,7 +385,8 @@ Future<Null> diagnoseXcodeBuildFailure(XcodeBuildResult result, BuildableIOSApp
|
||||
// Make sure the user has specified one of:
|
||||
// DEVELOPMENT_TEAM (automatic signing)
|
||||
// PROVISIONING_PROFILE (manual signing)
|
||||
!(app.buildSettings?.containsKey('DEVELOPMENT_TEAM')) == true || app.buildSettings?.containsKey('PROVISIONING_PROFILE') == true) {
|
||||
!(app.buildSettings?.containsKey('DEVELOPMENT_TEAM')) == true
|
||||
|| app.buildSettings?.containsKey('PROVISIONING_PROFILE') == true) {
|
||||
printError(noDevelopmentTeamInstruction, emphasis: true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:mustache/mustache.dart' as mustache;
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
@ -77,10 +78,13 @@ List<Plugin> _findPlugins(String directory) {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
void _writeFlutterPluginsList(String directory, List<Plugin> plugins) {
|
||||
/// Returns true if .flutter-plugins has changed, otherwise returns false.
|
||||
bool _writeFlutterPluginsList(String directory, List<Plugin> plugins) {
|
||||
final File pluginsProperties = fs.file(fs.path.join(directory, '.flutter-plugins'));
|
||||
final String previousFlutterPlugins =
|
||||
(pluginsProperties.existsSync() ? pluginsProperties.readAsStringSync() : null);
|
||||
final String pluginManifest =
|
||||
plugins.map((Plugin p) => '${p.name}=${escapePath(p.path)}').join('\n');
|
||||
plugins.map((Plugin p) => '${p.name}=${escapePath(p.path)}').join('\n');
|
||||
if (pluginManifest.isNotEmpty) {
|
||||
pluginsProperties.writeAsStringSync('$pluginManifest\n');
|
||||
} else {
|
||||
@ -88,6 +92,9 @@ void _writeFlutterPluginsList(String directory, List<Plugin> plugins) {
|
||||
pluginsProperties.deleteSync();
|
||||
}
|
||||
}
|
||||
final String currentFlutterPlugins =
|
||||
(pluginsProperties.existsSync() ? pluginsProperties.readAsStringSync() : null);
|
||||
return currentFlutterPlugins != previousFlutterPlugins;
|
||||
}
|
||||
|
||||
const String _androidPluginRegistryTemplate = '''package io.flutter.plugins;
|
||||
@ -206,17 +213,28 @@ void _writeIOSPluginRegistry(String directory, List<Plugin> plugins) {
|
||||
|
||||
}
|
||||
|
||||
class InjectPluginsResult{
|
||||
InjectPluginsResult({
|
||||
@required this.hasPlugin,
|
||||
@required this.hasChanged,
|
||||
});
|
||||
/// True if any flutter plugin exists, otherwise false.
|
||||
final bool hasPlugin;
|
||||
/// True if plugins have changed since last build.
|
||||
final bool hasChanged;
|
||||
}
|
||||
|
||||
/// Finds Flutter plugins in the pubspec.yaml, creates platform injection
|
||||
/// registries classes and add them to the build dependencies.
|
||||
///
|
||||
/// Returns whether any Flutter plugins are added.
|
||||
bool injectPlugins({String directory}) {
|
||||
/// Returns whether any Flutter plugins are added and whether they changed.
|
||||
InjectPluginsResult injectPlugins({String directory}) {
|
||||
directory ??= fs.currentDirectory.path;
|
||||
final List<Plugin> plugins = _findPlugins(directory);
|
||||
_writeFlutterPluginsList(directory, plugins);
|
||||
final bool hasPluginsChanged = _writeFlutterPluginsList(directory, plugins);
|
||||
if (fs.isDirectorySync(fs.path.join(directory, 'android')))
|
||||
_writeAndroidPluginRegistry(directory, plugins);
|
||||
if (fs.isDirectorySync(fs.path.join(directory, 'ios')))
|
||||
_writeIOSPluginRegistry(directory, plugins);
|
||||
return plugins.isNotEmpty;
|
||||
return new InjectPluginsResult(hasPlugin: plugins.isNotEmpty, hasChanged: hasPluginsChanged);
|
||||
}
|
||||
|
||||
@ -1,30 +1,44 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
|
||||
if ENV['FLUTTER_FRAMEWORK_DIR'] == nil
|
||||
abort('Please set FLUTTER_FRAMEWORK_DIR to the directory containing Flutter.framework')
|
||||
end
|
||||
|
||||
target 'Runner' do
|
||||
# Pods for Runner
|
||||
|
||||
# Flutter Pods
|
||||
pod 'Flutter', :path => ENV['FLUTTER_FRAMEWORK_DIR']
|
||||
|
||||
if File.exists? '../.flutter-plugins'
|
||||
flutter_root = File.expand_path('..')
|
||||
File.foreach('../.flutter-plugins') { |line|
|
||||
plugin = line.split(pattern='=')
|
||||
def parse_KV_file(file,seperator='=')
|
||||
file_abs_path = File.expand_path(file)
|
||||
if !File.exists? file_abs_path
|
||||
return [];
|
||||
end
|
||||
pods_ary = []
|
||||
File.foreach(file_abs_path) { |line|
|
||||
plugin = line.split(pattern=seperator)
|
||||
if plugin.length == 2
|
||||
name = plugin[0].strip()
|
||||
podname = plugin[0].strip()
|
||||
path = plugin[1].strip()
|
||||
resolved_path = File.expand_path("#{path}/ios", flutter_root)
|
||||
pod name, :path => resolved_path
|
||||
podpath = File.expand_path("#{path}", file_abs_path)
|
||||
pods_ary.push({:name => podname,:path=>podpath});
|
||||
else
|
||||
puts "Invalid plugin specification: #{line}"
|
||||
end
|
||||
}
|
||||
}
|
||||
return pods_ary
|
||||
end
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
# Flutter Pods
|
||||
generated_xcode_build_settings = parse_KV_file("./Flutter/Generated.xcconfig")
|
||||
if generated_xcode_build_settings.empty?
|
||||
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter build or flutter run is executed once first."
|
||||
end
|
||||
generated_xcode_build_settings.map{ |p|
|
||||
if p[:name]=='FLUTTER_FRAMEWORK_DIR'
|
||||
pod 'Flutter', :path => p[:path]
|
||||
end
|
||||
}
|
||||
|
||||
# Plugin Pods
|
||||
plugin_pods = parse_KV_file("../.flutter-plugins")
|
||||
plugin_pods.map{ |p|
|
||||
pod p[:name], :path => File.expand_path("ios",p[:path])
|
||||
}
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
@ -33,4 +47,4 @@ post_install do |installer|
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,32 +1,44 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
|
||||
if ENV['FLUTTER_FRAMEWORK_DIR'] == nil
|
||||
abort('Please set FLUTTER_FRAMEWORK_DIR to the directory containing Flutter.framework')
|
||||
def parse_KV_file(file,seperator='=')
|
||||
file_abs_path = File.expand_path(file)
|
||||
if !File.exists? file_abs_path
|
||||
return [];
|
||||
end
|
||||
pods_ary = []
|
||||
File.foreach(file_abs_path) { |line|
|
||||
plugin = line.split(pattern=seperator)
|
||||
if plugin.length == 2
|
||||
podname = plugin[0].strip()
|
||||
path = plugin[1].strip()
|
||||
podpath = File.expand_path("#{path}", file_abs_path)
|
||||
pods_ary.push({:name => podname,:path=>podpath});
|
||||
else
|
||||
puts "Invalid plugin specification: #{line}"
|
||||
end
|
||||
}
|
||||
return pods_ary
|
||||
end
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
|
||||
# Pods for Runner
|
||||
|
||||
# Flutter Pods
|
||||
pod 'Flutter', :path => ENV['FLUTTER_FRAMEWORK_DIR']
|
||||
|
||||
if File.exists? '../.flutter-plugins'
|
||||
flutter_root = File.expand_path('..')
|
||||
File.foreach('../.flutter-plugins') { |line|
|
||||
plugin = line.split(pattern='=')
|
||||
if plugin.length == 2
|
||||
name = plugin[0].strip()
|
||||
path = plugin[1].strip()
|
||||
resolved_path = File.expand_path("#{path}/ios", flutter_root)
|
||||
pod name, :path => resolved_path
|
||||
else
|
||||
puts "Invalid plugin specification: #{line}"
|
||||
end
|
||||
}
|
||||
generated_xcode_build_settings = parse_KV_file("./Flutter/Generated.xcconfig")
|
||||
if generated_xcode_build_settings.empty?
|
||||
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter build or flutter run is executed once first."
|
||||
end
|
||||
generated_xcode_build_settings.map{ |p|
|
||||
if p[:name]=='FLUTTER_FRAMEWORK_DIR'
|
||||
pod 'Flutter', :path => p[:path]
|
||||
end
|
||||
}
|
||||
|
||||
# Plugin Pods
|
||||
plugin_pods = parse_KV_file("../.flutter-plugins")
|
||||
plugin_pods.map{ |p|
|
||||
pod p[:name], :path => File.expand_path("ios",p[:path])
|
||||
}
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
@ -35,4 +47,4 @@ post_install do |installer|
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -95,7 +95,8 @@ void main() {
|
||||
await cocoaPodsUnderTest.processPods(
|
||||
appIosDir: projectUnderTest,
|
||||
iosEngineDir: 'engine/path',
|
||||
); expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
|
||||
);
|
||||
expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
|
||||
verify(mockProcessManager.run(
|
||||
<String>['pod', 'install', '--verbose'],
|
||||
workingDirectory: 'project/ios',
|
||||
@ -177,6 +178,64 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
|
||||
ProcessManager: () => mockProcessManager,
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'Run pod install if plugins or flutter framework have changes.',
|
||||
() async {
|
||||
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
||||
..createSync()
|
||||
..writeAsString('Existing Podfile');
|
||||
fs.file(fs.path.join('project', 'ios', 'Podfile.lock'))
|
||||
..createSync()
|
||||
..writeAsString('Existing lock files.');
|
||||
fs.file(fs.path.join('project', 'ios', 'Pods','Manifest.lock'))
|
||||
..createSync(recursive: true)
|
||||
..writeAsString('Existing lock files.');
|
||||
await cocoaPodsUnderTest.processPods(
|
||||
appIosDir: projectUnderTest,
|
||||
iosEngineDir: 'engine/path',
|
||||
pluginOrFlutterPodChanged: true
|
||||
);
|
||||
verify(mockProcessManager.run(
|
||||
<String>['pod', 'install', '--verbose'],
|
||||
workingDirectory: 'project/ios',
|
||||
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
||||
));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => mockProcessManager,
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'Skip pod install if plugins and flutter framework remain unchanged.',
|
||||
() async {
|
||||
fs.file(fs.path.join('project', 'ios', 'Podfile'))
|
||||
..createSync()
|
||||
..writeAsString('Existing Podfile');
|
||||
fs.file(fs.path.join('project', 'ios', 'Podfile.lock'))
|
||||
..createSync()
|
||||
..writeAsString('Existing lock files.');
|
||||
fs.file(fs.path.join('project', 'ios', 'Pods','Manifest.lock'))
|
||||
..createSync(recursive: true)
|
||||
..writeAsString('Existing lock files.');
|
||||
await cocoaPodsUnderTest.processPods(
|
||||
appIosDir: projectUnderTest,
|
||||
iosEngineDir: 'engine/path',
|
||||
pluginOrFlutterPodChanged: false
|
||||
);
|
||||
verifyNever(mockProcessManager.run(
|
||||
<String>['pod', 'install', '--verbose'],
|
||||
workingDirectory: 'project/ios',
|
||||
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
|
||||
));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => mockProcessManager,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
class MockProcessManager extends Mock implements ProcessManager {}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user