Рубрики
Uncategorized

Отрешите Native, как ускорить iOS наращивает 4X, используя кеш -стручки

Оптимизация времени настройки приложений RACE Native IOS. Tagged с реагированием, DevOps, CI, iOS.

Я тот человек, который ненавидит ждать ⌛, и, кажется, мне повезло, что решил работать с приложениями iOS 🙃 (сарказм)

Но в любом случае я думаю, что вы должны знать эту боль 😞 При создании приложения iOS на CI

🖥 Давайте посмотрим на нашу настройку (Действия GitHub) :

  OS: macOS 10.15.7
  CPU: (4) x64 Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz
  Memory: 8.11 GB / 12.00 GB

🗄 Размеры кэша:

node_modules: ~852 MB
pods: ~115 MB
pods derived data: ~1258 MB

⏲ Время строительства:

Так Как можно увидеть, я сохраняю 33M 08S 😲🎉💃!

Я надеюсь, что результаты произвели на вас впечатление, и вы хотите, чтобы получить эти результаты? 😉

Я прочитал 📖 много статей, которые описывают разные подходы:

1) ccache 2) Римский инструмент 3) Cocoapods-Binary-Cache — Работайте странно для меня, построил только 4 зависимости, которые не влияют на скорость сборки. 4) Кокопод-бинар — Требуется использовать use_frameworks!

Я заметил, что это обычно изменяются на стороне JS, но нативно изменяется редко. И большая часть времени сборки требует строительства местного кода.

Таким образом, основной идеей было кэшировать результат кэширования стручков до тех пор, пока ios/podfile.lock изменения

Если вы используете действия GitHub, ваш трубопровод будет выглядеть так:

jobs:
  build_ios:
    runs-on: macos-latest
    steps:

    # Checkout repo, Install deps (node.js, cocacpods, ruby gems) ...

    - uses: actions/cache@master
      with:
        # Path to Derived Data
        path: .local_derived_data
        # Restore cache by Podfile.lock hashsum  
        key: ${{ runner.os }}-pods-derived-data-${{ hashFiles('**/Podfile.lock') }}

    # Run build

Также я использую Fastlane Инструмент для запуска сценариев сборки. Так что код без оптимизации выглядит так:

# Fastfile
platform :ios do
  desc "Build iOS"
  lane :build do
      # Code sign ...

      gym(
        scheme: "MyApp",
        workspace: "./ios/MyApp.xcworkspace",
        export_method: "ad-hoc",
        configuration: "Release",
        clean: true
      )

      # Publish to firebase...
  end
end

Ничего особенного, верно? А теперь версия с оптимизацией:

platform :ios do
  desc "Build iOS"
  lane :build do
    scheme = "MyApp"
    build_configuration = "Release"
    # !!! Path to the folder that you will cache on CI !!!
    ios_derived_data_path = File.expand_path("../.local_derived_data")
    cache_folder = File.expand_path("#{ios_derived_data_path}/Build/Intermediates.noindex/ArchiveIntermediates/#{scheme}/BuildProductsPath/#{build_configuration}-iphoneos")

    # Code sign ...

    # Step 0) Check if cache exists 

    if(File.exist?(cache_folder))
      # Step 1) Apply a fix of "Copy Pods Resources" Build Phase

      # Before:
      # "${PODS_ROOT}/Target Support Files/Pods-MyApp/Pods-MyApp-resources.sh"
      #
      # After:
      # BUILT_PRODUCTS_DIR=/a/b/c "${PODS_ROOT}/Target Support Files/Pods-MyApp/Pods-MyApp-resources.sh"

      fastlane_require 'xcodeproj'
      project = Xcodeproj::Project.open("../ios/MyApp.xcodeproj")
      target = project.targets.select { |target| target.name == 'MyApp' }.first
      phase = target.shell_script_build_phases.select { |phase| phase.name && phase.name.include?('Copy Pods Resources') }.first
      if (!phase.shell_script.start_with?('BUILT_PRODUCTS_DIR'))
        phase.shell_script = "BUILT_PRODUCTS_DIR=#{cache_folder} #{phase.shell_script}"
        project.save()
      end

      # Step 2) Build only .xcodeproj 
      gym(
        clean: false,
        project: './ios/MyApp.xcodeproj',
        scheme: scheme,
        configuration: build_configuration,
        export_method: "ad-hoc",
        destination: 'generic/platform=iOS',
        export_options: {
          compileBitcode: false,
          uploadBitcode: false,
          uploadSymbols: false 
        },
        xcargs: [
            # Step 3) Provide paths where xcode can't find pods binaries
            "PODS_CONFIGURATION_BUILD_DIR=#{cache_folder}",
            "FRAMEWORK_SEARCH_PATHS='#{cache_folder} $(inherited)'",
            "LIBRARY_SEARCH_PATHS='#{cache_folder} $(inherited)'",
            "SWIFT_INCLUDE_PATHS=#{cache_folder}"
        ].join(" ")
      )
    else

      # Step 4) Build full app .xcworkspace
      gym(
        scheme: "MyApp",
        workspace: "./ios/MyApp.xcworkspace",
        derived_data_path: ios_derived_data_path,
        export_method: "ad-hoc",
        configuration: build_configuration,
        clean: true
      )


      # Step 5) Remove not a Pods binaries to reduce cache size
      require 'fileutils';
      dirs = [
        File.expand_path("#{ios_derived_data_path}/info.plist"),
        File.expand_path("#{ios_derived_data_path}/Logs"),
        File.expand_path("#{ios_derived_data_path}/SourcePackages"),
        File.expand_path("#{ios_derived_data_path}/ModuleCache.noindex"),
        File.expand_path("#{ios_derived_data_path}/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/IntermediateBuildFilesPath/MyApp.build"),
        File.expand_path("#{ios_derived_data_path}/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/IntermediateBuildFilesPath/XCBuildData"),
        File.expand_path("#{ios_derived_data_path}/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/BuildProductsPath/SwiftSupport"),
        File.expand_path("#{ios_derived_data_path}/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/PrecompiledHeaders")
      ]
      dirs.each { |dir| FileUtils.rm_rf(dir) }
    end

    # Publish to firebase...
  end
end

Некоторые заметки, чтобы понять, что происходит:

  • Прежде всего, я проверяю, что кеш существует? (См. Шаг 0 )

  • Если это не существует, я буду призывать тренажерный зал () С параметрами по умолчанию (см. Шаг 4 ), но добавьте новые параметры defived_data_path: ... . Затем немного очистите эту папку, удаляя не PODS -файлы. (См. Шаг 5 )

  • Если кэш успешно восстановлен необходим для обновления фазы сборки [CP] Копировать Pods Resources Анкет (См. Шаг 1 )

[CP] Копировать Pods Resources Запуск скрипта, который Cocoapods автоматически добавляет к вашему проекту. Он заботится о копировании ресурсов POD в правильный каталог, чтобы они стали частью последнего архива.

  • Тогда я могу вызвать тренажерный зал () Но он имеет другую конфигурацию (см. Шаг 2 ). В настоящее время я буду строить не целый a Workspace, просто проект. По мере того, как я создаю проект приложения, мне также нужно предоставить некоторые важные xcargs Чтобы помочь линкеру, искать капсулы во время ссылки. (См. Шаг 3 )
      gym(
-        workspace: "./ios/MyApp.xcworkspace",
+        project: './ios/MyApp.xcodeproj',
+        xcargs: [
+            "PODS_CONFIGURATION_BUILD_DIR=#{cache_folder}",
+            "FRAMEWORK_SEARCH_PATHS='#{cache_folder} $(inherited)'",
+            "LIBRARY_SEARCH_PATHS='#{cache_folder} $(inherited)'",
+            "SWIFT_INCLUDE_PATHS=#{cache_folder}"
+        ].join(" ")
-        clean: true,
+        clean: false,
         # ... 
      )

Если у вас есть какие -либо вопросы, я рад обсудить их в комментариях!

© Мурамур

Оригинал: «https://dev.to/retyui/react-native-how-speed-up-ios-build-4x-using-cache-pods-597c»