Skip to content

Conversation

@jmagman
Copy link
Member

@jmagman jmagman commented Oct 5, 2019

Description

There were two links/copies of Flutter.framework inside my_flutter_app/ios/. One was symlinked from the cache during pod install and embedded by CocoaPods:

if [[ "$CONFIGURATION" == "Debug" ]]; then
  install_framework "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework"
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
  install_framework "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework"
fi
if [[ "$CONFIGURATION" == "Profile" ]]; then
  install_framework "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework"
fi

The location of the framework was pulled from FLUTTER_FRAMEWORK_DIR which was only updated from a command line flutter build. This caused issues when a user runs flutter build --debug but then immediately tries to archive their app from Xcode. The FLUTTER_FRAMEWORK_DIR would still point to the Debug version even though the Xcode build config was Release.

The second version is copied during xcode_backend.sh. This used the Xcode build configuration to decide which version of Flutter.framework to use. The script runs on every Xcode build from the command line or from Xcode itself, and correctly (assuming schemes are well-named) chooses the right build mode version of the framework.

The CocoaPods version always gets the last word since it is embedded last after xcode_backend runs. Users experience various production blank screens/crashes/app submission rejections due to accidentally submitting the debug version of their engine.

This change removes the symlinked version and points to the xcode_backend location. It pulls a similar trick as podhelper.rb and copies the FLUTTER_FRAMEWORK_DIR version of the engine to the correct place if xcode_backend has not yet run. This fall-back lets pod install succeed, and the correct version of the framework is always copied over by xcode_backend on every Xcode build/test/archive.

This has the side effect of no longer changing the Podfile.lock (which should be checked into source control) every time the build mode changes.

 EXTERNAL SOURCES:
   Flutter:
    :path: ".symlinks/flutter/ios-release"

becomes

 
 EXTERNAL SOURCES:
   Flutter:
    :path: Flutter

Additionally, the Ruby code was updated to make it more idiomatic.

Related Issues

Fixes #24641
Fixes #25167
Fixes #25370
Fixes #28802

Some of these issues have become muddied so it will fix some people chiming in but not others:
#22765
#24887
#37850

Related:
#36247

Tests

Added a few file location checks to deploy_gallery. It will also be exercised by other integration tests that build or run on iOS.

Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I signed the [CLA].
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

  • Yes, this is a breaking change (Please read [Handling breaking changes]). Replace this with a link to the e-mail where you asked for input on this proposed change.
  • No, this is not a breaking change.

@jmagman jmagman added platform-ios iOS applications specifically tool Affects the "flutter" command-line tool. See also t: labels. t: xcode "xcodebuild" on iOS and general Xcode project management labels Oct 5, 2019
@jmagman jmagman self-assigned this Oct 5, 2019
@fluttergithubbot fluttergithubbot added d: examples Sample code and demos c: contributor-productivity Team-specific productivity, code health, technical debt. customer: gallery Relating to flutter/gallery repository. Please transfer non-framework issues there. labels Oct 5, 2019
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Flutter.podspec is now getting copied in. People will have to add it to their .gitignore or check it in... ☹️

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same file as Podfile-ios-obj except for use_frameworks!.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be the only Podfile.lock in the entire repo. You can see how it changes.
I don't know why MaterialControls was in there, but it doesn't seem to be a real dependency and was automatically removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a copy of the template.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy of the template.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these mean this will break for consumers?

Copy link
Member Author

@jmagman jmagman Oct 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the original format of the Generated.xcconfig is the same, and this method isn't accessible outside this file (unless someone was doing some really weird hackery). The method return type is different now, but I changed the two places we call it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I mean the fact that you had to update all of these - will it not be automatic for people running Flutter on existing projects?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only place this method is called is within this Podfile. So if they regenerate the Podfile they will get the updated method and the updated usage.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P.S. The stale framework issue this is fixing happens when developers fail to follow the deployment instructions and do not run flutter build ios in release before archiving. So if the Podfile isn't updated, but they follow instructions, they will be fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could read the podfile an dlook for the the offending line?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more detailed message, or a link to some docs on the website, could help folks do the necessary update manually if they have local edits they want to keep. Like, "Your Podfile is out of date. Regenerate it with .... If you have local edits that you'd like to keep, see ... for instructions."

Copy link
Member Author

@jmagman jmagman Oct 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's easy to see if their Podfile is out of date without parsing (either .symlinks/flutter exists or it doesn't since that directory gets removed and recreated each pod install run).
The minimum Podfile change (without the mapping refactor) is pretty large, so it's not just a one-line swap:

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 pub get is executed first."
end
generated_xcode_build_settings.map { |p|
  if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
    symlink = File.join('.symlinks', 'flutter')
    File.symlink(File.dirname(p[:path]), symlink)
    pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
  end
}

becomes:

copied_flutter_dir = File.join(__dir__, 'Flutter')
copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
  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 pub get is executed first."
  end
  generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
  generated_xcode_build_settings.map { |p|
    if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
      cached_framework_dir = p[:path]
      unless File.exist?(copied_framework_path)
        FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
      end
      unless File.exist?(copied_podspec_path)
        FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
      end
    end
  }
end

pod 'Flutter', :path => 'Flutter'

Copy link
Member Author

@jmagman jmagman Oct 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's what it looks like when I have an old version, build, get the migration instructions, remove the Podfile, then build again:
podfile_migration
Note I need to actually add instructions to that issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy of the template.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy of the template.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return a map of keys => values instead of an array of single key => value maps.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually stops the script now instead of just printing, and it's in red (ignore the double period at the end, I fixed that but I was too lazy to generate another screen shot)!
raise

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is essentially a migration step since people may already have ios/Flutter/Flutter.framework but will definitely not have ios/Flutter/Flutter.podspec.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more idiomatic Ruby.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take your word for it :)

@codecov
Copy link

codecov bot commented Oct 5, 2019

Codecov Report

Merging #42029 into master will decrease coverage by 0.5%.
The diff coverage is 81.81%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #42029      +/-   ##
==========================================
- Coverage   60.63%   60.13%   -0.51%     
==========================================
  Files         194      194              
  Lines       18886    18897      +11     
==========================================
- Hits        11452    11364      -88     
- Misses       7434     7533      +99
Flag Coverage Δ
#flutter_tool 60.13% <81.81%> (-0.51%) ⬇️
Impacted Files Coverage Δ
...ackages/flutter_tools/lib/src/macos/cocoapods.dart 91.15% <100%> (+0.58%) ⬆️
packages/flutter_tools/lib/src/project.dart 87.5% <50%> (-0.47%) ⬇️
...ges/flutter_tools/lib/src/commands/ide_config.dart 30.39% <0%> (-53.93%) ⬇️
...tter_tools/lib/src/build_system/targets/linux.dart 38.29% <0%> (-46.81%) ⬇️
...tools/lib/src/windows/visual_studio_validator.dart 61.29% <0%> (-32.26%) ⬇️
...utter_tools/lib/src/build_system/build_system.dart 82.72% <0%> (-6.37%) ⬇️
...ages/flutter_tools/lib/src/base/user_messages.dart 47.74% <0%> (-3.61%) ⬇️
packages/flutter_tools/lib/src/base/os.dart 24.6% <0%> (-2.39%) ⬇️
packages/flutter_tools/lib/src/version.dart 93.23% <0%> (-1.94%) ⬇️
packages/flutter_tools/lib/src/cache.dart 48.47% <0%> (-0.71%) ⬇️
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dda74a1...f3d5013. Read the comment docs.

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What test are we missing that would have caught this? I suppose since the devicelab is building through flutter it wouldn't have tickled this bug at all?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flutter packages get or are we rebranding to flutter pub get? Both probably work, not sure if we're consistent with one or the other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷‍♀ I didn't change the text of this line, I made it a raise instead of a puts. I feel like I've seen flutter packages get in more places, so I'll change it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, flutter packages get is only used in the Podfile-macos (which I didn't change in this PR because I want to test that thoroughly and separately). flutter pub get is used in 26 places in the repo.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take your word for it :)

@jmagman
Copy link
Member Author

jmagman commented Oct 5, 2019

What test are we missing that would have caught this? I suppose since the devicelab is building through flutter it wouldn't have tickled this bug at all?

Something like:

flutter build ios --release --no-codesign -t lib/main_publish.dart

but builds with --debug that deploys (uses Release) and then does a smoke test of the archived app.

I'll think more about how to test this...

@dnfield
Copy link
Contributor

dnfield commented Oct 5, 2019

For a test, couldn't we take one of the integration tests we have and assert that the .symlinks folder doesn't have Flutter in it?

@genert
Copy link

genert commented Oct 14, 2019

What is the status of this PR?

@jmagman
Copy link
Member Author

jmagman commented Oct 14, 2019

For a test, couldn't we take one of the integration tests we have and assert that the .symlinks folder doesn't have Flutter in it?

I added a few location checks to deploy_gallery.

@genert
Copy link

genert commented Oct 15, 2019

@jonahwilliams @zanderso

@jmagman jmagman merged commit 357d02c into flutter:master Oct 15, 2019
@jmagman jmagman deleted the pod-path branch October 15, 2019 22:34
Inconnu08 pushed a commit to Inconnu08/flutter that referenced this pull request Nov 26, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

c: contributor-productivity Team-specific productivity, code health, technical debt. customer: gallery Relating to flutter/gallery repository. Please transfer non-framework issues there. d: examples Sample code and demos platform-ios iOS applications specifically t: xcode "xcodebuild" on iOS and general Xcode project management tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

7 participants