From ffa8a1ebe8af7cf85b9eea4d58db47d2f52b3560 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 16 Oct 2018 13:50:20 -0700 Subject: [PATCH] Make it easier to use CocoaPods to Add2App for iOS (#23021) * Make it easier to Add2App for iOS * Use local engine if xcconfig says so * newline --- packages/flutter_tools/bin/xcode_backend.sh | 59 ++++++++++++++++--- .../ios/library/Flutter.tmpl/podhelper.rb | 17 ++++++ 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/packages/flutter_tools/bin/xcode_backend.sh b/packages/flutter_tools/bin/xcode_backend.sh index 0df51198a73..7348c0e289a 100755 --- a/packages/flutter_tools/bin/xcode_backend.sh +++ b/packages/flutter_tools/bin/xcode_backend.sh @@ -88,15 +88,24 @@ BuildApp() { RunCommand rm -rf -- "${derived_dir}/App.framework" + local local_engine_flag="" + local flutter_framework="${framework_path}/Flutter.framework" + local flutter_podspec="${framework_path}/Flutter.podspec" + if [[ -n "$LOCAL_ENGINE" ]]; then + local_engine_flag="--local-engine=${LOCAL_ENGINE}" + flutter_framework="${LOCAL_ENGINE}/Flutter.framework" + flutter_podspec="${LOCAL_ENGINE}/Flutter.podspec" + fi + if [[ -e "${project_path}/.ios" ]]; then RunCommand rm -rf -- "${derived_dir}/engine" mkdir "${derived_dir}/engine" - RunCommand cp -r -- "${framework_path}/Flutter.podspec" "${derived_dir}/engine" - RunCommand cp -r -- "${framework_path}/Flutter.framework" "${derived_dir}/engine" + RunCommand cp -r -- ${flutter_podspec} "${derived_dir}/engine" + RunCommand cp -r -- ${flutter_framework} "${derived_dir}/engine" RunCommand find "${derived_dir}/engine/Flutter.framework" -type f -exec chmod a-w "{}" \; else RunCommand rm -rf -- "${derived_dir}/Flutter.framework" - RunCommand cp -r -- "${framework_path}/Flutter.framework" "${derived_dir}" + RunCommand cp -r -- ${flutter_framework} "${derived_dir}" RunCommand find "${derived_dir}/Flutter.framework" -type f -exec chmod a-w "{}" \; fi @@ -110,10 +119,6 @@ BuildApp() { fi local build_dir="${FLUTTER_BUILD_DIR:-build}" - local local_engine_flag="" - if [[ -n "$LOCAL_ENGINE" ]]; then - local_engine_flag="--local-engine=$LOCAL_ENGINE" - fi local track_widget_creation_flag="" if [[ -n "$TRACK_WIDGET_CREATION" ]]; then @@ -296,6 +301,44 @@ ThinAppFrameworks() { done } +# Adds the App.framework as an embedded binary and the flutter_assets as +# resources. +EmbedFlutterFrameworks() { + AssertExists "${FLUTTER_APPLICATION_PATH}" + + # Prefer the hidden .ios folder, but fallback to a visible ios folder if .ios + # doesn't exist. + local flutter_ios_out_folder="${FLUTTER_APPLICATION_PATH}/.ios/Flutter" + if [[ ! -d ${flutter_ios_out_folder} ]]; then + flutter_ios_out_folder="${FLUTTER_APPLICATION_PATH}/ios/Flutter" + fi + + AssertExists "${flutter_ios_out_folder}" + + # Copy the flutter_assets to the Application's resources. + AssertExists "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/" + RunCommand cp -r -- "${flutter_ios_out_folder}/flutter_assets" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/" + + # Embed App.framework from Flutter into the app (after creating the Frameworks directory + # if it doesn't already exist). + local xcode_frameworks_dir=${BUILT_PRODUCTS_DIR}"/"${PRODUCT_NAME}".app/Frameworks" + RunCommand mkdir -p -- "${xcode_frameworks_dir}" + RunCommand cp -Rv -- "${flutter_ios_out_folder}/App.framework" "${xcode_frameworks_dir}" + + # Embed the actual Flutter.framework that the Flutter app expects to run against, + # which could be a local build or an arch/type specific build. + # Remove it first since Xcode might be trying to hold some of these files - this way we're + # sure to get a clean copy. + RunCommand rm -rf -- "${xcode_frameworks_dir}/Flutter.framework" + RunCommand cp -Rv -- "${flutter_ios_out_folder}/engine/Flutter.framework" "${xcode_frameworks_dir}/" + + # Sign the binaries we moved. + local identity="${EXPANDED_CODE_SIGN_IDENTITY_NAME:-$CODE_SIGN_IDENTITY}" + + RunCommand codesign --force --verbose --sign "${identity}" -- "${xcode_frameworks_dir}/App.framework/App" + RunCommand codesign --force --verbose --sign "${identity}" -- "${xcode_frameworks_dir}/Flutter.framework/Flutter" +} + # Main entry point. # TODO(cbracken): improve error handling, then enable set -e @@ -309,5 +352,7 @@ else BuildApp ;; "thin") ThinAppFrameworks ;; + "embed") + EmbedFlutterFrameworks ;; esac fi diff --git a/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb index 0ac9d7c9fc4..f98153a08ae 100644 --- a/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb +++ b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb @@ -33,6 +33,8 @@ def flutter_root(f) } end +# If this wasn't specified, assume it's two levels up from the directory of this script. +flutter_application_path ||= File.join(__dir__, '..', '..') framework_dir = File.join(flutter_application_path, '.ios', 'Flutter') engine_dir = File.join(framework_dir, 'engine') @@ -56,3 +58,18 @@ plugin_pods.map { |r| File.symlink(r[:path], symlink) pod r[:name], :path => File.join(symlink, 'ios') } + +# Ensure that ENABLE_BITCODE is set to NO, add a #include to Generated.xcconfig, and +# add a run script to the Build Phases. +# TODO(dnfield): Figure out a way to deliver the Build Phase scripts without manual user intervention. +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + xcconfig_path = config.base_configuration_reference.real_path + File.open(xcconfig_path, 'a+') do |file| + file.puts "#include \"#{File.join(framework_dir, 'Generated.xcconfig')}\"" + end + end + end +end