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
diff --git a/packages/flutter_tools/lib/src/commands/inject_plugins.dart b/packages/flutter_tools/lib/src/commands/inject_plugins.dart index bf53cb5..f1df432 100644 --- a/packages/flutter_tools/lib/src/commands/inject_plugins.dart +++ b/packages/flutter_tools/lib/src/commands/inject_plugins.dart
@@ -24,7 +24,7 @@ @override Future<Null> runCommand() async { - final bool result = injectPlugins(); + final bool result = injectPlugins().hasPlugin; if (result) { printStatus('GeneratedPluginRegistrants successfully written.'); } else {
diff --git a/packages/flutter_tools/lib/src/ios/cocoapods.dart b/packages/flutter_tools/lib/src/ios/cocoapods.dart index 78fd425..9ebe95a 100644 --- a/packages/flutter_tools/lib/src/ios/cocoapods.dart +++ b/packages/flutter_tools/lib/src/ios/cocoapods.dart
@@ -57,18 +57,21 @@ 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 @@ 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.
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart index e3ead3b..2ca8109 100644 --- a/packages/flutter_tools/lib/src/ios/mac.dart +++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -254,14 +254,9 @@ // 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 @@ 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<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 @@ // 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; }
diff --git a/packages/flutter_tools/lib/src/plugins.dart b/packages/flutter_tools/lib/src/plugins.dart index 19d7bc0..60f7c5c 100644 --- a/packages/flutter_tools/lib/src/plugins.dart +++ b/packages/flutter_tools/lib/src/plugins.dart
@@ -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 @@ 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 @@ pluginsProperties.deleteSync(); } } + final String currentFlutterPlugins = + (pluginsProperties.existsSync() ? pluginsProperties.readAsStringSync() : null); + return currentFlutterPlugins != previousFlutterPlugins; } const String _androidPluginRegistryTemplate = '''package io.flutter.plugins; @@ -206,17 +213,28 @@ } +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); }