From e34a56458d55f472296971425049a12ea525c6e3 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 9 Dec 2020 11:16:47 -0800 Subject: [PATCH 1/3] Move macOS Podfile logic into the tool --- dev/benchmarks/macrobenchmarks/macos/Podfile | 73 ++++---------- dev/devicelab/bin/tasks/plugin_lint_mac.dart | 27 ++++- .../flutter_gallery/macos/Podfile | 73 ++++---------- packages/flutter_tools/bin/podhelper.rb | 98 +++++++++++++++---- .../flutter_tools/lib/src/context_runner.dart | 1 - .../flutter_tools/lib/src/ios/xcodeproj.dart | 11 --- .../lib/src/macos/cocoapods.dart | 76 +++++++------- .../templates/cocoapods/Podfile-macos | 73 ++++---------- .../hermetic/build_macos_test.dart | 1 - .../general.shard/macos/cocoapods_test.dart | 23 ++++- .../build_ios_config_only_test.dart | 5 +- 11 files changed, 211 insertions(+), 250 deletions(-) diff --git a/dev/benchmarks/macrobenchmarks/macos/Podfile b/dev/benchmarks/macrobenchmarks/macos/Podfile index b8e51657ae78d..c3dfe98231abc 100644 --- a/dev/benchmarks/macrobenchmarks/macos/Podfile +++ b/dev/benchmarks/macrobenchmarks/macos/Podfile @@ -9,71 +9,32 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end - pods_ary = [] - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - 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 -def pubspec_supports_macos(file) - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return false; + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches end - File.foreach(file_abs_path) { |line| - return true if line =~ /^\s*macos:/ - } - return false + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run flutter pub get" end +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + target 'Runner' do use_frameworks! use_modular_headers! - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - ephemeral_dir = File.join('Flutter', 'ephemeral') - symlink_dir = File.join(ephemeral_dir, '.symlinks') - symlink_plugins_dir = File.join(symlink_dir, 'plugins') - system("rm -rf #{symlink_dir}") - system("mkdir -p #{symlink_plugins_dir}") + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end - # Flutter Pods - generated_xcconfig = parse_KV_file(File.join(ephemeral_dir, 'Flutter-Generated.xcconfig')) - if generated_xcconfig.empty? - puts "Flutter-Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) end - generated_xcconfig.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join(symlink_dir, 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'FlutterMacOS', :path => File.join(symlink, File.basename(p[:path])) - end - } - - # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join(symlink_plugins_dir, p[:name]) - File.symlink(p[:path], symlink) - if pubspec_supports_macos(File.join(symlink, 'pubspec.yaml')) - pod p[:name], :path => File.join(symlink, 'macos') - end - } end diff --git a/dev/devicelab/bin/tasks/plugin_lint_mac.dart b/dev/devicelab/bin/tasks/plugin_lint_mac.dart index 272a8cd16deda..45c8429dba9bf 100644 --- a/dev/devicelab/bin/tasks/plugin_lint_mac.dart +++ b/dev/devicelab/bin/tasks/plugin_lint_mac.dart @@ -415,7 +415,7 @@ void _validateIosPodfile(String appPath) { || !podfileLockOutput.contains(':path: ".symlinks/plugins/test_plugin_objc/ios"') || !podfileLockOutput.contains(':path: ".symlinks/plugins/test_plugin_swift/ios"') || podfileLockOutput.contains('url_launcher_macos')) { - throw TaskResult.failure('Podfile.lock does not contain expected pods'); + throw TaskResult.failure('iOS Podfile.lock does not contain expected pods'); } checkDirectoryNotExists(path.join( @@ -445,6 +445,11 @@ void _validateIosPodfile(String appPath) { 'ios', )); + checkDirectoryNotExists(path.join( + pluginSymlinks, + 'url_launcher_macos', + )); + checkDirectoryExists(path.join( pluginSymlinks, 'test_plugin_objc', @@ -463,12 +468,21 @@ void _validateMacOSPodfile(String appPath) { final File podfileLockFile = File(path.join(appPath, 'macos', 'Podfile.lock')); final String podfileLockOutput = podfileLockFile.readAsStringSync(); - if (!podfileLockOutput.contains(':path: Flutter/ephemeral/.symlinks/flutter/darwin-x64-release') + if (!podfileLockOutput.contains(':path: Flutter/ephemeral\n') || !podfileLockOutput.contains(':path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos') - || !podfileLockOutput.contains(':path: Flutter/ephemeral/.symlinks/plugins/test_plugin_swift/macos')) { - throw TaskResult.failure('Podfile.lock does not contain expected pods'); + || !podfileLockOutput.contains(':path: Flutter/ephemeral/.symlinks/plugins/test_plugin_swift/macos') + || podfileLockOutput.contains('url_launcher/')) { + throw TaskResult.failure('macOS Podfile.lock does not contain expected pods'); } + checkFileExists(path.join( + appPath, + 'macos', + 'Flutter', + 'ephemeral', + 'FlutterMacOS.podspec', + )); + final String pluginSymlinks = path.join( appPath, 'macos', @@ -484,6 +498,11 @@ void _validateMacOSPodfile(String appPath) { 'macos', )); + checkDirectoryNotExists(path.join( + pluginSymlinks, + 'url_launcher', + )); + checkDirectoryExists(path.join( pluginSymlinks, 'test_plugin_swift', diff --git a/dev/integration_tests/flutter_gallery/macos/Podfile b/dev/integration_tests/flutter_gallery/macos/Podfile index b8e51657ae78d..c3dfe98231abc 100644 --- a/dev/integration_tests/flutter_gallery/macos/Podfile +++ b/dev/integration_tests/flutter_gallery/macos/Podfile @@ -9,71 +9,32 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end - pods_ary = [] - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - 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 -def pubspec_supports_macos(file) - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return false; + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches end - File.foreach(file_abs_path) { |line| - return true if line =~ /^\s*macos:/ - } - return false + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run flutter pub get" end +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + target 'Runner' do use_frameworks! use_modular_headers! - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - ephemeral_dir = File.join('Flutter', 'ephemeral') - symlink_dir = File.join(ephemeral_dir, '.symlinks') - symlink_plugins_dir = File.join(symlink_dir, 'plugins') - system("rm -rf #{symlink_dir}") - system("mkdir -p #{symlink_plugins_dir}") + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end - # Flutter Pods - generated_xcconfig = parse_KV_file(File.join(ephemeral_dir, 'Flutter-Generated.xcconfig')) - if generated_xcconfig.empty? - puts "Flutter-Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) end - generated_xcconfig.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join(symlink_dir, 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'FlutterMacOS', :path => File.join(symlink, File.basename(p[:path])) - end - } - - # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join(symlink_plugins_dir, p[:name]) - File.symlink(p[:path], symlink) - if pubspec_supports_macos(File.join(symlink, 'pubspec.yaml')) - pod p[:name], :path => File.join(symlink, 'macos') - end - } end diff --git a/packages/flutter_tools/bin/podhelper.rb b/packages/flutter_tools/bin/podhelper.rb index 806c4c278f009..277daac61fa99 100644 --- a/packages/flutter_tools/bin/podhelper.rb +++ b/packages/flutter_tools/bin/podhelper.rb @@ -17,6 +17,12 @@ def flutter_ios_podfile_setup end +# Same as flutter_ios_podfile_setup for macOS. +def flutter_macos_podfile_setup + # 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 +end + # Add iOS build settings to pod targets. # # @example @@ -67,6 +73,24 @@ def flutter_additional_ios_build_settings(target) end end +# Same as flutter_ios_podfile_setup for macOS. +def flutter_additional_macos_build_settings(target) + print target.platform_name + return unless target.platform_name == :osx + + # This podhelper script is at $FLUTTER_ROOT/packages/flutter_tools/bin. + # Add search paths from $FLUTTER_ROOT/bin/cache/artifacts/engine. + artifacts_dir = File.join('..', '..', '..', '..', 'bin', 'cache', 'artifacts', 'engine') + debug_framework_dir = File.expand_path(File.join(artifacts_dir, 'darwin-x64'), __FILE__) + release_framework_dir = File.expand_path(File.join(artifacts_dir, 'darwin-x64-release'), __FILE__) + + target.build_configurations.each do |build_configuration| + # Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only). + configuration_engine_dir = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir + build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS'] = "\"#{configuration_engine_dir}\" $(inherited)" + end +end + # Install pods needed to embed Flutter iOS engine and plugins. # # @example @@ -77,7 +101,13 @@ def flutter_additional_ios_build_settings(target) # Optional, defaults to the Podfile directory. def flutter_install_all_ios_pods(ios_application_path = nil) flutter_install_ios_engine_pod(ios_application_path) - flutter_install_ios_plugin_pods(ios_application_path) + flutter_install_plugin_pods(ios_application_path, '.symlinks', 'ios') +end + +# Same as flutter_install_all_ios_pods for macOS. +def flutter_install_all_macos_pods(macos_application_path = nil) + flutter_install_macos_engine_pod(macos_application_path) + flutter_install_plugin_pods(macos_application_path, File.join('Flutter', 'ephemeral', '.symlinks'), 'macos') end # Install iOS Flutter engine pod. @@ -125,30 +155,64 @@ def flutter_install_ios_engine_pod(ios_application_path = nil) pod 'Flutter', :path => 'Flutter' end -# Install iOS Flutter plugin pods. +# Same as flutter_install_ios_engine_pod for macOS. +def flutter_install_macos_engine_pod(mac_application_path = nil) + # defined_in_file is set by CocoaPods and is a Pathname to the Podfile. + mac_application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file) + raise 'Could not find macOS application path' unless mac_application_path + + copied_podspec_path = File.expand_path('FlutterMacOS.podspec', File.join(mac_application_path, 'Flutter', 'ephemeral')) + + # Generate a fake podspec to represent the FlutterMacOS framework. + # This is only necessary because plugin podspecs contain `s.dependency 'FlutterMacOS'`, and if this Podfile + # does not add a `pod 'FlutterMacOS'` CocoaPods will try to download it from the CoocaPods trunk. + File.open(copied_podspec_path, 'w') { |podspec| + podspec.write <<~EOF + # + # NOTE: This podspec is NOT to be published. It is only used as a local source! + # This is a generated file; do not edit or check into version control. + # + + Pod::Spec.new do |s| + s.name = 'FlutterMacOS' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.homepage = 'https://flutter.io' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.osx.deployment_target = '10.11' + # Framework linking is handled by Flutter tooling, not CocoaPods. + # Add a placeholder to satisfy `s.dependency 'FlutterMacOS'` plugin podspecs. + s.vendored_frameworks = 'path/to/nothing' + end + EOF + } + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'FlutterMacOS', :path => File.join('Flutter', 'ephemeral') +end + +# Install Flutter plugin pods. # -# @example -# target 'Runner' do -# flutter_install_ios_plugin_pods -# end -# @param [String] ios_application_path Path of the iOS directory of the Flutter app. -# Optional, defaults to the Podfile directory. -def flutter_install_ios_plugin_pods(ios_application_path = nil) +# @param [String] application_path Path of the directory of the Flutter app. +# Optional, defaults to the Podfile directory. +def flutter_install_plugin_pods(application_path = nil, relative_symlink_dir, platform) # defined_in_file is set by CocoaPods and is a Pathname to the Podfile. - ios_application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file) - raise 'Could not find iOS application path' unless ios_application_path + application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file) + raise 'Could not find application path' unless application_path # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock # referring to absolute paths on developers' machines. - symlink_dir = File.expand_path('.symlinks', ios_application_path) + symlink_dir = File.expand_path(relative_symlink_dir, application_path) system('rm', '-rf', symlink_dir) # Avoid the complication of dependencies like FileUtils. symlink_plugins_dir = File.expand_path('plugins', symlink_dir) system('mkdir', '-p', symlink_plugins_dir) - plugins_file = File.join(ios_application_path, '..', '.flutter-plugins-dependencies') - plugin_pods = flutter_parse_plugins_file(plugins_file) + plugins_file = File.join(application_path, '..', '.flutter-plugins-dependencies') + plugin_pods = flutter_parse_plugins_file(plugins_file, platform) plugin_pods.each do |plugin_hash| plugin_name = plugin_hash['name'] plugin_path = plugin_hash['path'] @@ -157,14 +221,14 @@ def flutter_install_ios_plugin_pods(ios_application_path = nil) File.symlink(plugin_path, symlink) # Keep pod path relative so it can be checked into Podfile.lock. - pod plugin_name, :path => File.join('.symlinks', 'plugins', plugin_name, 'ios') + pod plugin_name, :path => File.join(relative_symlink_dir, 'plugins', plugin_name, platform) end end end # .flutter-plugins-dependencies format documented at # https://flutter.dev/go/plugins-list-migration -def flutter_parse_plugins_file(file) +def flutter_parse_plugins_file(file, platform) file_path = File.expand_path(file) return [] unless File.exists? file_path @@ -174,5 +238,5 @@ def flutter_parse_plugins_file(file) # dependencies_hash.dig('plugins', 'ios') not available until Ruby 2.3 return [] unless dependencies_hash.has_key?('plugins') return [] unless dependencies_hash['plugins'].has_key?('ios') - dependencies_hash['plugins']['ios'] || [] + dependencies_hash['plugins'][platform] || [] end diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart index 24597a1eebaaf..f220d7baa3f3e 100644 --- a/packages/flutter_tools/lib/src/context_runner.dart +++ b/packages/flutter_tools/lib/src/context_runner.dart @@ -136,7 +136,6 @@ Future runInContext( logger: globals.logger, platform: globals.platform, xcodeProjectInterpreter: globals.xcodeProjectInterpreter, - artifacts: globals.artifacts, usage: globals.flutterUsage, ), CocoaPodsValidator: () => CocoaPodsValidator( diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index f47556d89f91e..de863d1d1db67 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart @@ -181,17 +181,6 @@ List _xcodeBuildSettingsLines({ xcodeBuildSettings.add('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}'); } - if (!project.isModule && useMacOSConfig) { - // For module projects we do not want to write the FLUTTER_FRAMEWORK_DIR - // explicitly. Rather we rely on the xcode backend script and the Podfile - // logic to derive it from FLUTTER_ROOT and FLUTTER_BUILD_MODE. - // However, this is necessary for regular macOS projects using Cocoapods. - final String frameworkDir = - flutterMacOSFrameworkDir(buildInfo.mode, globals.fs, globals.artifacts); - xcodeBuildSettings.add('FLUTTER_FRAMEWORK_DIR=$frameworkDir'); - } - - final String buildName = parsedBuildName(manifest: project.manifest, buildInfo: buildInfo) ?? '1.0.0'; xcodeBuildSettings.add('FLUTTER_BUILD_NAME=$buildName'); diff --git a/packages/flutter_tools/lib/src/macos/cocoapods.dart b/packages/flutter_tools/lib/src/macos/cocoapods.dart index ed16fa3453996..ebc682bba9210 100644 --- a/packages/flutter_tools/lib/src/macos/cocoapods.dart +++ b/packages/flutter_tools/lib/src/macos/cocoapods.dart @@ -6,7 +6,6 @@ import 'package:file/file.dart'; import 'package:meta/meta.dart'; import 'package:process/process.dart'; -import '../artifacts.dart'; import '../base/common.dart'; import '../base/error_handling_io.dart'; import '../base/file_system.dart'; @@ -41,15 +40,18 @@ const String outOfDateFrameworksPodfileConsequence = ''' If you have local Podfile edits you would like to keep, see https://github.com/flutter/flutter/issues/24641 for instructions.'''; const String outOfDatePluginsPodfileConsequence = ''' - This can cause issues if your application depends on plugins that do not support iOS. + This can cause issues if your application depends on plugins that do not support iOS or macOS. See https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin-platforms for details. If you have local Podfile edits you would like to keep, see https://github.com/flutter/flutter/issues/45197 for instructions.'''; const String cocoaPodsInstallInstructions = 'see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.'; -const String podfileMigrationInstructions = ''' +const String podfileIosMigrationInstructions = ''' rm ios/Podfile'''; +const String podfileMacOSMigrationInstructions = ''' + rm macos/Podfile'''; + /// Result of evaluating the CocoaPods installation. enum CocoaPodsStatus { /// iOS plugins will not work, installation required. @@ -83,13 +85,11 @@ class CocoaPods { @required XcodeProjectInterpreter xcodeProjectInterpreter, @required Logger logger, @required Platform platform, - @required Artifacts artifacts, @required Usage usage, }) : _fileSystem = fileSystem, _processManager = processManager, _xcodeProjectInterpreter = xcodeProjectInterpreter, _logger = logger, - _artifacts = artifacts, _usage = usage, _processUtils = ProcessUtils(processManager: processManager, logger: logger), _operatingSystemUtils = OperatingSystemUtils( @@ -105,7 +105,6 @@ class CocoaPods { final OperatingSystemUtils _operatingSystemUtils; final XcodeProjectInterpreter _xcodeProjectInterpreter; final Logger _logger; - final Artifacts _artifacts; final Usage _usage; Future _versionText; @@ -314,10 +313,6 @@ class CocoaPods { ['pod', 'install', '--verbose'], workingDirectory: _fileSystem.path.dirname(xcodeProject.podfile.path), environment: { - // For macOS Podfile only. - if (xcodeProject is MacOSProject) - 'FLUTTER_FRAMEWORK_DIR': - flutterMacOSFrameworkDir(buildMode, _fileSystem, _artifacts), // See https://github.com/flutter/flutter/issues/10873. // CocoaPods analytics adds a lot of latency. 'COCOAPODS_DISABLE_STATS': 'true', @@ -374,29 +369,28 @@ class CocoaPods { } void _warnIfPodfileOutOfDate(XcodeBasedProject xcodeProject) { - if (xcodeProject is! IosProject) { - return; - } - - // Previously, the Podfile created a symlink to the cached artifacts engine framework - // and installed the Flutter pod from that path. This could get out of sync with the copy - // of the Flutter engine that was copied to ios/Flutter by the xcode_backend script. - // It was possible for the symlink to point to a Debug version of the engine when the - // Xcode build configuration was Release, which caused App Store submission rejections. - // - // Warn the user if they are still symlinking to the framework. - final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join( - (xcodeProject as IosProject).symlinks.path, - 'flutter', - )); - if (flutterSymlink.existsSync()) { - throwToolExit( - 'Warning: Podfile is out of date\n' - '$outOfDateFrameworksPodfileConsequence\n' - 'To regenerate the Podfile, run:\n' - '$podfileMigrationInstructions\n', - ); - return; + final bool isIos = xcodeProject is IosProject; + if (isIos) { + // Previously, the Podfile created a symlink to the cached artifacts engine framework + // and installed the Flutter pod from that path. This could get out of sync with the copy + // of the Flutter engine that was copied to ios/Flutter by the xcode_backend script. + // It was possible for the symlink to point to a Debug version of the engine when the + // Xcode build configuration was Release, which caused App Store submission rejections. + // + // Warn the user if they are still symlinking to the framework. + final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join( + (xcodeProject as IosProject).symlinks.path, + 'flutter', + )); + if (flutterSymlink.existsSync()) { + throwToolExit( + 'Warning: Podfile is out of date\n' + '$outOfDateFrameworksPodfileConsequence\n' + 'To regenerate the Podfile, run:\n' + '$podfileIosMigrationInstructions\n', + ); + return; + } } // Most of the pod and plugin parsing logic was moved from the Podfile // into the tool's podhelper.rb script. If the Podfile still references @@ -404,12 +398,16 @@ class CocoaPods { // plugin_pods = parse_KV_file('../.flutter-plugins') if (xcodeProject.podfile.existsSync() && xcodeProject.podfile.readAsStringSync().contains('.flutter-plugins\'')) { - throwToolExit( - 'Warning: Podfile is out of date\n' - '$outOfDatePluginsPodfileConsequence\n' - 'To regenerate the Podfile, run:\n' - '$podfileMigrationInstructions\n', - ); + const String error = 'Warning: Podfile is out of date\n' + '$outOfDatePluginsPodfileConsequence\n' + 'To regenerate the Podfile, run:\n'; + if (isIos) { + throwToolExit('$error\n$podfileIosMigrationInstructions\n'); + } else { + // The old macOS Podfile will work until `.flutter-plugins` is removed. + // Warn instead of exit. + _logger.printError('$error\n$podfileMacOSMigrationInstructions\n', emphasis: true); + } } } } diff --git a/packages/flutter_tools/templates/cocoapods/Podfile-macos b/packages/flutter_tools/templates/cocoapods/Podfile-macos index b8e51657ae78d..c3dfe98231abc 100644 --- a/packages/flutter_tools/templates/cocoapods/Podfile-macos +++ b/packages/flutter_tools/templates/cocoapods/Podfile-macos @@ -9,71 +9,32 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end - pods_ary = [] - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - 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 -def pubspec_supports_macos(file) - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return false; + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches end - File.foreach(file_abs_path) { |line| - return true if line =~ /^\s*macos:/ - } - return false + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run flutter pub get" end +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + target 'Runner' do use_frameworks! use_modular_headers! - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - ephemeral_dir = File.join('Flutter', 'ephemeral') - symlink_dir = File.join(ephemeral_dir, '.symlinks') - symlink_plugins_dir = File.join(symlink_dir, 'plugins') - system("rm -rf #{symlink_dir}") - system("mkdir -p #{symlink_plugins_dir}") + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end - # Flutter Pods - generated_xcconfig = parse_KV_file(File.join(ephemeral_dir, 'Flutter-Generated.xcconfig')) - if generated_xcconfig.empty? - puts "Flutter-Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) end - generated_xcconfig.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join(symlink_dir, 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'FlutterMacOS', :path => File.join(symlink, File.basename(p[:path])) - end - } - - # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join(symlink_plugins_dir, p[:name]) - File.symlink(p[:path], symlink) - if pubspec_supports_macos(File.join(symlink, 'pubspec.yaml')) - pod p[:name], :path => File.join(symlink, 'macos') - end - } end diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart index 5d9a6042f7b8f..5c7d06c72e20d 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart @@ -260,7 +260,6 @@ void main() { 'DART_OBFUSCATION=true', 'EXTRA_FRONT_END_OPTIONS=--enable-experiment%3Dnon-nullable', 'EXTRA_GEN_SNAPSHOT_OPTIONS=--enable-experiment%3Dnon-nullable', - 'FLUTTER_FRAMEWORK_DIR=.', 'SPLIT_DEBUG_INFO=foo/', 'TRACK_WIDGET_CREATION=true', 'TREE_SHAKE_ICONS=true', diff --git a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart index 2f499bda6e4dd..29241110e8ac4 100644 --- a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart @@ -4,7 +4,6 @@ import 'package:file/file.dart'; import 'package:file/memory.dart'; -import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; @@ -76,7 +75,6 @@ void main() { processManager: mockProcessManager, logger: logger, platform: FakePlatform(operatingSystem: 'macos'), - artifacts: Artifacts.test(), xcodeProjectInterpreter: mockXcodeProjectInterpreter, usage: usage, ); @@ -109,7 +107,7 @@ void main() { when(mockProcessManager.run( ['pod', 'install', '--verbose'], workingDirectory: 'project/macos', - environment: {'FLUTTER_FRAMEWORK_DIR': '.', 'COCOAPODS_DISABLE_STATS': 'true', 'LANG': 'en_US.UTF-8'}, + environment: {'COCOAPODS_DISABLE_STATS': 'true', 'LANG': 'en_US.UTF-8'}, )).thenAnswer((_) async => exitsHappy()); fileSystem.file('.packages').writeAsStringSync('\n'); }); @@ -373,7 +371,7 @@ void main() { ), throwsToolExit(message: 'Podfile is out of date')); }); - testWithoutContext('exits if Podfile parses .flutter-plugins', () async { + testWithoutContext('exits if iOS Podfile parses .flutter-plugins', () async { pretendPodIsInstalled(); fileSystem.file(fileSystem.path.join('project', 'ios', 'Podfile')) @@ -386,6 +384,22 @@ void main() { ), throwsToolExit(message: 'Podfile is out of date')); }); + testWithoutContext('prints warning if macOS Podfile parses .flutter-plugins', () async { + pretendPodIsInstalled(); + + fileSystem.file(fileSystem.path.join('project', 'macos', 'Podfile')) + ..createSync() + ..writeAsStringSync('plugin_pods = parse_KV_file(\'../.flutter-plugins\')'); + + await cocoaPodsUnderTest.processPods( + xcodeProject: projectUnderTest.macos, + buildMode: BuildMode.debug, + ); + + expect(logger.errorText, contains('Warning: Podfile is out of date')); + expect(logger.errorText, contains('rm macos/Podfile')); + }); + testWithoutContext('throws, if Podfile is missing.', () async { pretendPodIsInstalled(); try { @@ -588,7 +602,6 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ['pod', 'install', '--verbose'], workingDirectory: 'project/macos', environment: { - 'FLUTTER_FRAMEWORK_DIR': '.', 'COCOAPODS_DISABLE_STATS': 'true', 'LANG': 'en_US.UTF-8', }, diff --git a/packages/flutter_tools/test/integration.shard/build_ios_config_only_test.dart b/packages/flutter_tools/test/integration.shard/build_ios_config_only_test.dart index b1fede15c8556..7382a46cedaf0 100644 --- a/packages/flutter_tools/test/integration.shard/build_ios_config_only_test.dart +++ b/packages/flutter_tools/test/integration.shard/build_ios_config_only_test.dart @@ -41,10 +41,7 @@ void main() { // Config is updated if command succeeded. expect(generatedConfig, exists); - expect(generatedConfig.readAsStringSync(), allOf( - contains('DART_OBFUSCATION=true'), - isNot(contains('FLUTTER_FRAMEWORK_DIR')), - )); + expect(generatedConfig.readAsStringSync(), contains('DART_OBFUSCATION=true')); // file that only exists if app was fully built. final File frameworkPlist = fileSystem.file( From f5708e67f60b128d519368bf636afa9037fb0af1 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Tue, 15 Dec 2020 12:21:57 -0800 Subject: [PATCH 2/3] Remove disable_input_output_paths --- packages/flutter_tools/bin/podhelper.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/flutter_tools/bin/podhelper.rb b/packages/flutter_tools/bin/podhelper.rb index 277daac61fa99..6128a47eb9dfc 100644 --- a/packages/flutter_tools/bin/podhelper.rb +++ b/packages/flutter_tools/bin/podhelper.rb @@ -19,8 +19,6 @@ def flutter_ios_podfile_setup # Same as flutter_ios_podfile_setup for macOS. def flutter_macos_podfile_setup - # 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 end # Add iOS build settings to pod targets. From 56dfbd1dc167e8517db400637d7e0305ffad5851 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 17 Dec 2020 10:32:37 -0800 Subject: [PATCH 3/3] Quotes around command --- dev/benchmarks/macrobenchmarks/macos/Podfile | 4 ++-- dev/integration_tests/flutter_gallery/macos/Podfile | 4 ++-- packages/flutter_tools/templates/cocoapods/Podfile-macos | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/benchmarks/macrobenchmarks/macos/Podfile b/dev/benchmarks/macrobenchmarks/macos/Podfile index c3dfe98231abc..dade8dfad0dcf 100644 --- a/dev/benchmarks/macrobenchmarks/macos/Podfile +++ b/dev/benchmarks/macrobenchmarks/macos/Podfile @@ -12,14 +12,14 @@ project 'Runner', { def flutter_root generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" end File.foreach(generated_xcode_build_settings_path) do |line| matches = line.match(/FLUTTER_ROOT\=(.*)/) return matches[1].strip if matches end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run flutter pub get" + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" end require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) diff --git a/dev/integration_tests/flutter_gallery/macos/Podfile b/dev/integration_tests/flutter_gallery/macos/Podfile index c3dfe98231abc..dade8dfad0dcf 100644 --- a/dev/integration_tests/flutter_gallery/macos/Podfile +++ b/dev/integration_tests/flutter_gallery/macos/Podfile @@ -12,14 +12,14 @@ project 'Runner', { def flutter_root generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" end File.foreach(generated_xcode_build_settings_path) do |line| matches = line.match(/FLUTTER_ROOT\=(.*)/) return matches[1].strip if matches end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run flutter pub get" + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" end require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) diff --git a/packages/flutter_tools/templates/cocoapods/Podfile-macos b/packages/flutter_tools/templates/cocoapods/Podfile-macos index c3dfe98231abc..dade8dfad0dcf 100644 --- a/packages/flutter_tools/templates/cocoapods/Podfile-macos +++ b/packages/flutter_tools/templates/cocoapods/Podfile-macos @@ -12,14 +12,14 @@ project 'Runner', { def flutter_root generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" end File.foreach(generated_xcode_build_settings_path) do |line| matches = line.match(/FLUTTER_ROOT\=(.*)/) return matches[1].strip if matches end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run flutter pub get" + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" end require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy