Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embed Flutter and App frameworks for add-to-app on iOS #102538

Merged
merged 1 commit into from
May 2, 2022

Conversation

jmagman
Copy link
Member

@jmagman jmagman commented Apr 25, 2022

Previously, the iOS Flutter module copied the Flutter.xcframework and created a dummy version of App.framework in the the ephemeral .ios directory, as well as two corresponding podspecs that pointed at these frameworks. On every compilation of the host app, flutter assemble would create the real App.framework and copy the right Flutter.framework variant into the Xcode BUILT_PRODUCTS_DIR. On the first build, CocoaPods would then copy/re-codesign/re-strip the frameworks and embed them into the app.

However, since flutter assemble updates the frameworks in BUILT_PRODUCTS_DIR and not the dummy frameworks in the ephemeral directory, on incremental builds CocoaPods would not run its copy script because the timestamp of the dummy ephemeral frameworks did not change. So the compiled dart code embedded in the app would not be updated, and would be stale until a hot reload.

  1. Stop creating the dummy ephemeral directory frameworks so CocoaPods can find them. Instead, use the existing tool podhelper scripts that embed the frameworks into the app. assemble already codesigns, bitcode strips, and debug symbol strips the frameworks, so all that's left it to rsync them to the right place in the app.
  2. Deduplicate engine/plugins logic in the add-to-app podhelper.rb ruby script to use the Flutter SDK flutter_tools/bin/podhelper.rb version of this file to push as much logic as possible into the SDK instead of the module project.
  3. Update the SDK ruby script to use relative paths in places where it had assumed relative location from the Podfile (since now it's being called from host apps, which are located outside the Flutter module).

Fixes #101979
Probably would have resolved parts of #94481
Follow-up to #101943

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@jmagman jmagman added platform-ios iOS applications specifically tool Affects the "flutter" command-line tool. See also t: labels. a: existing-apps Integration with existing apps via the add-to-app flow labels Apr 25, 2022
@jmagman jmagman self-assigned this Apr 25, 2022
@flutter-dashboard flutter-dashboard bot added the team Infra upgrades, team productivity, code health, technical debt. See also team: labels. label Apr 25, 2022
@jmagman jmagman force-pushed the add-to-app-embed branch 3 times, most recently from 86d0d33 to 2b32a72 Compare April 26, 2022 00:32
@@ -79,32 +80,6 @@ Future<void> main() async {
);
}

section('Build ephemeral host app when SDK is on external disk');

// Pretend the SDK was on an external drive with stray "._" files in the xcframework
Copy link
Member Author

Choose a reason for hiding this comment

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

.ios/Flutter/engine no longer exists

@@ -190,7 +191,7 @@ def flutter_install_ios_engine_pod(ios_application_path = nil)
}

# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
pod 'Flutter', :path => flutter_relative_path_from_podfile(podspec_directory)
Copy link
Member Author

@jmagman jmagman Apr 26, 2022

Choose a reason for hiding this comment

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

This is now called from the host app Podfile script, and the fake podspec is in the Flutter module, so don't assume they are sibling paths.

derivedDir = '$projectPath/.ios/Flutter';
}

// Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
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 comment is already in parseFlutterBuildMode we don't need it twice.


pod 'Flutter', :path => relative.to_s, :inhibit_warnings => true
# flutter_install_ios_engine_pod is in Flutter root podhelper.rb
flutter_install_ios_engine_pod(ios_application_path)
Copy link
Member Author

Choose a reason for hiding this comment

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

Instead of duplicating logic, call the ruby script in the tool

def flutter_install_ios_engine_pod(ios_application_path = nil)

@@ -79,33 +61,13 @@ end
# MyApp/my_flutter/.ios/Flutter/../..
def install_flutter_plugin_pods(flutter_application_path)
flutter_application_path ||= File.join('..', '..')
ios_application_path = File.join(flutter_application_path, '.ios')
# flutter_install_plugin_pods is in Flutter root podhelper.rb
flutter_install_plugin_pods(ios_application_path, '.symlinks', 'ios')
Copy link
Member Author

Choose a reason for hiding this comment

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

Remove duplicated logic, call

def flutter_install_plugin_pods(application_path = nil, relative_symlink_dir, platform)

# Create a dummy dylib.
FileUtils.mkdir_p(app_framework_dir)
sdk_path = `xcrun --sdk iphoneos --show-sdk-path`.strip
`echo "static const int Moo = 88;" | xcrun clang -x c -arch arm64 -dynamiclib -miphoneos-version-min=11.0 -isysroot "#{sdk_path}" -o "#{app_framework_dylib}" -`
Copy link
Member Author

Choose a reason for hiding this comment

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

Stop making the dummy App.framework in the ephemeral module directory.
🐮

current_directory = File.expand_path('..', __FILE__)
engine_dir = File.expand_path('engine', current_directory)
framework_name = 'Flutter.xcframework'
copied_engine = File.expand_path(framework_name, engine_dir)
Copy link
Member Author

Choose a reason for hiding this comment

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

Stop copying the engine into the module ephemeral directory. Let the tool handle copying the right version where it needs to go when assemble is called.


# Embed App.framework AND Flutter.framework.
script_phase :name => 'Embed Flutter Build {{projectName}} Script',
:script => "set -e\nset -u\nsource \"#{flutter_export_environment_path}\"\nexport VERBOSE_SCRIPT_LOGGING=1 && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh embed_and_thin",
Copy link
Member Author

@jmagman jmagman Apr 26, 2022

Choose a reason for hiding this comment

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

Instead of letting CocoaPods copy/re-codesign/strip the frameworks from the ephemeral directory, instead let the tool copy it via embed_and_thin after the rest of the app has compiled. The tool already codesigned/stripped it during assemble.

Note this is the only real added logic to this PR, everything else is deletions or slight refactoring.

@jmagman jmagman marked this pull request as ready for review April 26, 2022 01:09
Copy link
Contributor

@cyanglaz cyanglaz left a comment

Choose a reason for hiding this comment

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

LGTM

@jmagman
Copy link
Member Author

jmagman commented Apr 30, 2022

friendly ping @christopherfujino

Copy link
Member

@christopherfujino christopherfujino left a comment

Choose a reason for hiding this comment

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

Sorry, thought I approved this, LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: existing-apps Integration with existing apps via the add-to-app flow platform-ios iOS applications specifically team Infra upgrades, team productivity, code health, technical debt. See also team: labels. tool Affects the "flutter" command-line tool. See also t: labels.
Projects
None yet
4 participants