"Fossies" - the Fresh Open Source Software Archive

Member "flutter-1.22.4/packages/flutter_tools/bin/xcode_backend.sh" (13 Nov 2020, 15080 Bytes) of package /linux/misc/flutter-1.22.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/usr/bin/env bash
    2 # Copyright 2014 The Flutter Authors. All rights reserved.
    3 # Use of this source code is governed by a BSD-style license that can be
    4 # found in the LICENSE file.
    5 
    6 # Exit on error
    7 set -e
    8 
    9 RunCommand() {
   10   if [[ -n "$VERBOSE_SCRIPT_LOGGING" ]]; then
   11     echo "♦ $*"
   12   fi
   13   "$@"
   14   return $?
   15 }
   16 
   17 # When provided with a pipe by the host Flutter build process, output to the
   18 # pipe goes to stdout of the Flutter build process directly.
   19 StreamOutput() {
   20   if [[ -n "$SCRIPT_OUTPUT_STREAM_FILE" ]]; then
   21     echo "$1" > $SCRIPT_OUTPUT_STREAM_FILE
   22   fi
   23 }
   24 
   25 EchoError() {
   26   echo "$@" 1>&2
   27 }
   28 
   29 AssertExists() {
   30   if [[ ! -e "$1" ]]; then
   31     if [[ -h "$1" ]]; then
   32       EchoError "The path $1 is a symlink to a path that does not exist"
   33     else
   34       EchoError "The path $1 does not exist"
   35     fi
   36     exit -1
   37   fi
   38   return 0
   39 }
   40 
   41 ParseFlutterBuildMode() {
   42   # Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
   43   # This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
   44   # they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
   45   local build_mode="$(echo "${FLUTTER_BUILD_MODE:-${CONFIGURATION}}" | tr "[:upper:]" "[:lower:]")"
   46 
   47   case "$build_mode" in
   48     *release*) build_mode="release";;
   49     *profile*) build_mode="profile";;
   50     *debug*) build_mode="debug";;
   51     *)
   52       EchoError "========================================================================"
   53       EchoError "ERROR: Unknown FLUTTER_BUILD_MODE: ${build_mode}."
   54       EchoError "Valid values are 'Debug', 'Profile', or 'Release' (case insensitive)."
   55       EchoError "This is controlled by the FLUTTER_BUILD_MODE environment variable."
   56       EchoError "If that is not set, the CONFIGURATION environment variable is used."
   57       EchoError ""
   58       EchoError "You can fix this by either adding an appropriately named build"
   59       EchoError "configuration, or adding an appropriate value for FLUTTER_BUILD_MODE to the"
   60       EchoError ".xcconfig file for the current build configuration (${CONFIGURATION})."
   61       EchoError "========================================================================"
   62       exit -1;;
   63   esac
   64   echo "${build_mode}"
   65 }
   66 
   67 BuildApp() {
   68   local project_path="${SOURCE_ROOT}/.."
   69   if [[ -n "$FLUTTER_APPLICATION_PATH" ]]; then
   70     project_path="${FLUTTER_APPLICATION_PATH}"
   71   fi
   72 
   73   local target_path="lib/main.dart"
   74   if [[ -n "$FLUTTER_TARGET" ]]; then
   75     target_path="${FLUTTER_TARGET}"
   76   fi
   77 
   78   local derived_dir="${SOURCE_ROOT}/Flutter"
   79   if [[ -e "${project_path}/.ios" ]]; then
   80     derived_dir="${project_path}/.ios/Flutter"
   81   fi
   82 
   83   local bundle_sksl_path=""
   84   if [[ -n "$BUNDLE_SKSL_PATH" ]]; then
   85     bundle_sksl_path="-iBundleSkSLPath=${BUNDLE_SKSL_PATH}"
   86   fi
   87 
   88   # Default value of assets_path is flutter_assets
   89   local assets_path="flutter_assets"
   90   # The value of assets_path can set by add FLTAssetsPath to
   91   # AppFrameworkInfo.plist.
   92   if FLTAssetsPath=$(/usr/libexec/PlistBuddy -c "Print :FLTAssetsPath" "${derived_dir}/AppFrameworkInfo.plist" 2>/dev/null); then
   93     if [[ -n "$FLTAssetsPath" ]]; then
   94       assets_path="${FLTAssetsPath}"
   95     fi
   96   fi
   97 
   98   # Use FLUTTER_BUILD_MODE if it's set, otherwise use the Xcode build configuration name
   99   # This means that if someone wants to use an Xcode build config other than Debug/Profile/Release,
  100   # they _must_ set FLUTTER_BUILD_MODE so we know what type of artifact to build.
  101   local build_mode="$(ParseFlutterBuildMode)"
  102   local artifact_variant="unknown"
  103   case "$build_mode" in
  104     release ) artifact_variant="ios-release";;
  105     profile ) artifact_variant="ios-profile";;
  106     debug ) artifact_variant="ios";;
  107   esac
  108 
  109   # Warn the user if not archiving (ACTION=install) in release mode.
  110   if [[ "$ACTION" == "install" && "$build_mode" != "release" ]]; then
  111     echo "warning: Flutter archive not built in Release mode. Ensure FLUTTER_BUILD_MODE \
  112 is set to release or run \"flutter build ios --release\", then re-run Archive from Xcode."
  113   fi
  114 
  115   local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}"
  116   local flutter_engine_flag=""
  117   local local_engine_flag=""
  118   local flutter_framework="${framework_path}/Flutter.framework"
  119   local flutter_podspec="${framework_path}/Flutter.podspec"
  120 
  121   if [[ -n "$FLUTTER_ENGINE" ]]; then
  122     flutter_engine_flag="--local-engine-src-path=${FLUTTER_ENGINE}"
  123   fi
  124 
  125   if [[ -n "$LOCAL_ENGINE" ]]; then
  126     if [[ $(echo "$LOCAL_ENGINE" | tr "[:upper:]" "[:lower:]") != *"$build_mode"* ]]; then
  127       EchoError "========================================================================"
  128       EchoError "ERROR: Requested build with Flutter local engine at '${LOCAL_ENGINE}'"
  129       EchoError "This engine is not compatible with FLUTTER_BUILD_MODE: '${build_mode}'."
  130       EchoError "You can fix this by updating the LOCAL_ENGINE environment variable, or"
  131       EchoError "by running:"
  132       EchoError "  flutter build ios --local-engine=ios_${build_mode}"
  133       EchoError "or"
  134       EchoError "  flutter build ios --local-engine=ios_${build_mode}_unopt"
  135       EchoError "========================================================================"
  136       exit -1
  137     fi
  138     local_engine_flag="--local-engine=${LOCAL_ENGINE}"
  139     flutter_framework="${FLUTTER_ENGINE}/out/${LOCAL_ENGINE}/Flutter.framework"
  140     flutter_podspec="${FLUTTER_ENGINE}/out/${LOCAL_ENGINE}/Flutter.podspec"
  141   fi
  142 
  143   local bitcode_flag=""
  144   if [[ "$ENABLE_BITCODE" == "YES" ]]; then
  145     bitcode_flag="true"
  146   fi
  147 
  148   # TODO(jonahwilliams): move engine copying to build system.
  149   if [[ -e "${project_path}/.ios" ]]; then
  150     RunCommand rm -rf -- "${derived_dir}/engine"
  151     mkdir "${derived_dir}/engine"
  152     RunCommand cp -r -- "${flutter_podspec}" "${derived_dir}/engine"
  153     RunCommand cp -r -- "${flutter_framework}" "${derived_dir}/engine"
  154   else
  155     RunCommand rm -rf -- "${derived_dir}/Flutter.framework"
  156     RunCommand cp -- "${flutter_podspec}" "${derived_dir}"
  157     RunCommand cp -r -- "${flutter_framework}" "${derived_dir}"
  158   fi
  159 
  160   RunCommand pushd "${project_path}" > /dev/null
  161 
  162   local verbose_flag=""
  163   if [[ -n "$VERBOSE_SCRIPT_LOGGING" ]]; then
  164     verbose_flag="--verbose"
  165   fi
  166 
  167   local performance_measurement_option=""
  168   if [[ -n "$PERFORMANCE_MEASUREMENT_FILE" ]]; then
  169     performance_measurement_option="--performance-measurement-file=${PERFORMANCE_MEASUREMENT_FILE}"
  170   fi
  171 
  172   local code_size_directory=""
  173   if [[ -n "$CODE_SIZE_DIRECTORY" ]]; then
  174     code_size_directory="-dCodeSizeDirectory=${CODE_SIZE_DIRECTORY}"
  175   fi
  176 
  177   RunCommand "${FLUTTER_ROOT}/bin/flutter"                                \
  178     ${verbose_flag}                                                       \
  179     ${flutter_engine_flag}                                                \
  180     ${local_engine_flag}                                                  \
  181     assemble                                                              \
  182     --output="${derived_dir}/"                                            \
  183     ${performance_measurement_option}                                     \
  184     -dTargetPlatform=ios                                                  \
  185     -dTargetFile="${target_path}"                                         \
  186     -dBuildMode=${build_mode}                                             \
  187     -dIosArchs="${ARCHS}"                                                 \
  188     -dSplitDebugInfo="${SPLIT_DEBUG_INFO}"                                \
  189     -dTreeShakeIcons="${TREE_SHAKE_ICONS}"                                \
  190     -dTrackWidgetCreation="${TRACK_WIDGET_CREATION}"                      \
  191     -dDartObfuscation="${DART_OBFUSCATION}"                               \
  192     -dEnableBitcode="${bitcode_flag}"                                     \
  193     ${bundle_sksl_path}                                                   \
  194     ${code_size_directory}                                                \
  195     --ExtraGenSnapshotOptions="${EXTRA_GEN_SNAPSHOT_OPTIONS}"             \
  196     --DartDefines="${DART_DEFINES}"                                       \
  197     --ExtraFrontEndOptions="${EXTRA_FRONT_END_OPTIONS}"                   \
  198     "${build_mode}_ios_bundle_flutter_assets"
  199 
  200   if [[ $? -ne 0 ]]; then
  201     EchoError "Failed to package ${project_path}."
  202     exit -1
  203   fi
  204   StreamOutput "done"
  205   StreamOutput " └─Compiling, linking and signing..."
  206 
  207   RunCommand popd > /dev/null
  208 
  209   echo "Project ${project_path} built and packaged successfully."
  210   return 0
  211 }
  212 
  213 # Returns the CFBundleExecutable for the specified framework directory.
  214 GetFrameworkExecutablePath() {
  215   local framework_dir="$1"
  216 
  217   local plist_path="${framework_dir}/Info.plist"
  218   local executable="$(defaults read "${plist_path}" CFBundleExecutable)"
  219   echo "${framework_dir}/${executable}"
  220 }
  221 
  222 # Destructively thins the specified executable file to include only the
  223 # specified architectures.
  224 LipoExecutable() {
  225   local executable="$1"
  226   shift
  227   # Split $@ into an array.
  228   read -r -a archs <<< "$@"
  229 
  230   # Extract architecture-specific framework executables.
  231   local all_executables=()
  232   for arch in "${archs[@]}"; do
  233     local output="${executable}_${arch}"
  234     local lipo_info="$(lipo -info "${executable}")"
  235     if [[ "${lipo_info}" == "Non-fat file:"* ]]; then
  236       if [[ "${lipo_info}" != *"${arch}" ]]; then
  237         echo "Non-fat binary ${executable} is not ${arch}. Running lipo -info:"
  238         echo "${lipo_info}"
  239         exit 1
  240       fi
  241     else
  242       if lipo -output "${output}" -extract "${arch}" "${executable}"; then
  243         all_executables+=("${output}")
  244       else
  245         echo "Failed to extract ${arch} for ${executable}. Running lipo -info:"
  246         lipo -info "${executable}"
  247         exit 1
  248       fi
  249     fi
  250   done
  251 
  252   # Generate a merged binary from the architecture-specific executables.
  253   # Skip this step for non-fat executables.
  254   if [[ ${#all_executables[@]} > 0 ]]; then
  255     local merged="${executable}_merged"
  256     lipo -output "${merged}" -create "${all_executables[@]}"
  257 
  258     cp -f -- "${merged}" "${executable}" > /dev/null
  259     rm -f -- "${merged}" "${all_executables[@]}"
  260   fi
  261 }
  262 
  263 # Destructively thins the specified framework to include only the specified
  264 # architectures.
  265 ThinFramework() {
  266   local framework_dir="$1"
  267   shift
  268 
  269   local executable="$(GetFrameworkExecutablePath "${framework_dir}")"
  270   LipoExecutable "${executable}" "$@"
  271 }
  272 
  273 ThinAppFrameworks() {
  274   local app_path="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
  275   local frameworks_dir="${app_path}/Frameworks"
  276 
  277   [[ -d "$frameworks_dir" ]] || return 0
  278   find "${app_path}" -type d -name "*.framework" | while read framework_dir; do
  279     ThinFramework "$framework_dir" "$ARCHS"
  280   done
  281 }
  282 
  283 # Adds the App.framework as an embedded binary and the flutter_assets as
  284 # resources.
  285 EmbedFlutterFrameworks() {
  286   local project_path="${SOURCE_ROOT}/.."
  287   if [[ -n "$FLUTTER_APPLICATION_PATH" ]]; then
  288     project_path="${FLUTTER_APPLICATION_PATH}"
  289   fi
  290 
  291   # Prefer the hidden .ios folder, but fallback to a visible ios folder if .ios
  292   # doesn't exist.
  293   local flutter_ios_out_folder="${project_path}/.ios/Flutter"
  294   local flutter_ios_engine_folder="${project_path}/.ios/Flutter/engine"
  295   if [[ ! -d ${flutter_ios_out_folder} ]]; then
  296     flutter_ios_out_folder="${project_path}/ios/Flutter"
  297     flutter_ios_engine_folder="${project_path}/ios/Flutter"
  298   fi
  299 
  300   AssertExists "${flutter_ios_out_folder}"
  301 
  302   # Embed App.framework from Flutter into the app (after creating the Frameworks directory
  303   # if it doesn't already exist).
  304   local xcode_frameworks_dir="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
  305   RunCommand mkdir -p -- "${xcode_frameworks_dir}"
  306   RunCommand rsync -av --delete "${flutter_ios_out_folder}/App.framework" "${xcode_frameworks_dir}"
  307 
  308   # Embed the actual Flutter.framework that the Flutter app expects to run against,
  309   # which could be a local build or an arch/type specific build.
  310 
  311   # Copy Xcode behavior and don't copy over headers or modules.
  312   RunCommand rsync -av --delete --filter "- .DS_Store/" --filter "- Headers/" --filter "- Modules/" "${flutter_ios_engine_folder}/Flutter.framework" "${xcode_frameworks_dir}/"
  313   if [[ "$ACTION" != "install" || "$ENABLE_BITCODE" == "NO" ]]; then
  314     # Strip bitcode from the destination unless archiving, or if bitcode is disabled entirely.
  315     RunCommand "${DT_TOOLCHAIN_DIR}"/usr/bin/bitcode_strip "${flutter_ios_engine_folder}/Flutter.framework/Flutter" -r -o "${xcode_frameworks_dir}/Flutter.framework/Flutter"
  316   fi
  317 
  318   # Sign the binaries we moved.
  319   if [[ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" ]]; then
  320     RunCommand codesign --force --verbose --sign "${EXPANDED_CODE_SIGN_IDENTITY}" -- "${xcode_frameworks_dir}/App.framework/App"
  321     RunCommand codesign --force --verbose --sign "${EXPANDED_CODE_SIGN_IDENTITY}" -- "${xcode_frameworks_dir}/Flutter.framework/Flutter"
  322   fi
  323 
  324   AddObservatoryBonjourService
  325 }
  326 
  327 # Add the observatory publisher Bonjour service to the produced app bundle Info.plist.
  328 AddObservatoryBonjourService() {
  329   local build_mode="$(ParseFlutterBuildMode)"
  330   # Debug and profile only.
  331   if [[ "${build_mode}" == "release" ]]; then
  332     return
  333   fi
  334   local built_products_plist="${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}"
  335 
  336   if [[ ! -f "${built_products_plist}" ]]; then
  337     EchoError "error: ${INFOPLIST_PATH} does not exist. The Flutter \"Thin Binary\" build phase must run after \"Copy Bundle Resources\"."
  338     exit -1
  339   fi
  340   # If there are already NSBonjourServices specified by the app (uncommon), insert the observatory service name to the existing list.
  341   if plutil -extract NSBonjourServices xml1 -o - "${built_products_plist}"; then
  342     RunCommand plutil -insert NSBonjourServices.0 -string "_dartobservatory._tcp" "${built_products_plist}"
  343   else
  344     # Otherwise, add the NSBonjourServices key and observatory service name.
  345     RunCommand plutil -insert NSBonjourServices -json "[\"_dartobservatory._tcp\"]" "${built_products_plist}"
  346   fi
  347 
  348   # Don't override the local network description the Flutter app developer specified (uncommon).
  349   # This text will appear below the "Your app would like to find and connect to devices on your local network" permissions popup.
  350   if ! plutil -extract NSLocalNetworkUsageDescription xml1 -o - "${built_products_plist}"; then
  351     RunCommand plutil -insert NSLocalNetworkUsageDescription -string "Allow Flutter tools on your computer to connect and debug your application. This prompt will not appear on release builds." "${built_products_plist}"
  352   fi
  353 }
  354 
  355 EmbedAndThinFrameworks() {
  356   EmbedFlutterFrameworks
  357   ThinAppFrameworks
  358 }
  359 
  360 # Main entry point.
  361 if [[ $# == 0 ]]; then
  362   # Named entry points were introduced in Flutter v0.0.7.
  363   EchoError "error: Your Xcode project is incompatible with this version of Flutter. Run \"rm -rf ios/Runner.xcodeproj\" and \"flutter create .\" to regenerate."
  364   exit -1
  365 else
  366   case $1 in
  367     "build")
  368       BuildApp ;;
  369     "thin")
  370       ThinAppFrameworks ;;
  371     "embed")
  372       EmbedFlutterFrameworks ;;
  373     "embed_and_thin")
  374       EmbedAndThinFrameworks ;;
  375     "test_observatory_bonjour_service")
  376       # Exposed for integration testing only.
  377       AddObservatoryBonjourService ;;
  378   esac
  379 fi