require_relative "xcodebuild_raw" module PodPrebuild class XcodebuildCommand # rubocop:disable Metrics/ClassLength def initialize(options) @options = options case options[:targets][0].platform.name when :ios @options[:device] = "iphoneos" @options[:simulator] = "iphonesimulator" when :tvos @options[:device] = "appletvos" @options[:simulator] = "appletvsimulator" when :watchos @options[:device] = "watchos" @options[:simulator] = "watchsimulator" end @build_args = make_up_build_args(options[:args] || {}) end def run sdks.each { |sdk| build_for_sdk(sdk) } targets.each do |target| if PodPrebuild.config.xcframework? create_xcframework(target) elsif sdks.count > 1 create_fat_framework(target) else collect_output(target, Dir[target_products_dir_of(target, sdks[0]) + "/*"]) end end fix_swiftinterface_files(targets) end private def sdks @sdks ||= begin sdks_ = [] sdks_ << simulator if build_types.include?(:simulator) sdks_ << device if build_types.include?(:device) sdks_ end end def preferred_sdk @preferred_sdk ||= sdks.include?(device) ? device : sdks[0] end def build_types @build_types ||= begin # TODO (thuyen): Add DSL options `build_for_types` to specify build types types = [:simulator] types << :device if device_build_enabled? types end end def make_up_build_args(args) # Note: The build arguments explicitly passed from config_cocoapods_binary_cache # should be preceded by the default arguments so that they could take higher priority # when there are argument collisions in the xcodebuild command. # For ex. `xcodebuild AN_ARG=1 AN_ARG=2` should use `AN_ARG=2` instead. args_ = args.clone args_[:default] ||= [] args_[:simulator] ||= [] args_[:device] ||= [] args_[:default].prepend("BITCODE_GENERATION_MODE=bitcode") if bitcode_enabled? args_[:default].prepend("DEBUG_INFORMATION_FORMAT=dwarf-with-dsym") unless disable_dsym? args_[:default].prepend("DEBUG_INFORMATION_FORMAT=dwarf") if disable_dsym? args_[:default].prepend("BUILD_LIBRARY_FOR_DISTRIBUTION=YES") #args_[:default].prepend("OTHER_SWIFT_FLAGS=\"-Xfrontend -module-interface-preserve-types-as-written\"") args_[:simulator].prepend("ARCHS=\"x86_64 arm64\"", "ONLY_ACTIVE_ARCH=NO") if simulator == "iphonesimulator" args_[:simulator] += args_[:default] args_[:device].prepend("ONLY_ACTIVE_ARCH=NO") args_[:device] += args_[:default] args_ end def build_for_sdk(sdk) PodPrebuild::XcodebuildCommand.xcodebuild( sandbox: sandbox, scheme: scheme, targets: targets.map(&:label), configuration: configuration, sdk: sdk, deployment_target: targets.map { |t| t.platform.deployment_target }.max.to_s, log_path: log_path(sdk), args: sdk == simulator ? @build_args[:simulator] : @build_args[:device] ) end def create_xcframework(target) non_framework_paths = Dir[target_products_dir_of(target, preferred_sdk) + "/*"] \ - [framework_path_of(target, preferred_sdk)] \ - dsym_paths_of(target, preferred_sdk) \ - bcsymbolmap_paths_of(target, preferred_sdk) collect_output(target, non_framework_paths) output = "#{output_path(target)}/#{target.product_module_name}.xcframework" FileUtils.rm_rf(output) cmd = ["xcodebuild", "-create-xcframework" " -allow-internal-distribution"] # -allow-internal-distribution # # for each sdk, the order of params must be -framework then -debug-symbols # to prevent duplicated file error when copying dSYMs sdks.each do |sdk| cmd << "-framework" << framework_path_of(target, sdk).shellescape unless disable_dsym? dsyms = dsym_paths_of(target, sdk) cmd += dsyms.map { |dsym| "-debug-symbols #{dsym.shellescape}" } end if bitcode_enabled? bcsymbolmaps = bcsymbolmap_paths_of(target, sdk) cmd += bcsymbolmaps.map { |bcsymbolmap| "-debug-symbols #{bcsymbolmap.shellescape}" } end end cmd << "-output" << output Pod::UI.puts "- Create xcframework: #{target}".magenta Pod::UI.puts_indented "$ #{cmd.join(' ')}" unless PodPrebuild.config.silent_build? `#{cmd.join(" ")}` end def fix_swiftinterface_files(targets) targets.each do |target| escapedPod = target.product_module_name.gsub('/', '\/') # replace when framework and class in framework with the same name replaceString1 = "-e '/^import/! s/ #{escapedPod}\\./ /g'" #remove framework name in swiftinterface of it frameworkd replaceString2 = "-e 's/\(#{escapedPod}\\./(/g'" replaceString3 = "-e 's/\\[#{escapedPod}\\./[/g'" replaceString4 = "-e 's/<#{escapedPod}\\./