# frozen_string_literal: true require 'cocoapods' require 'xcodeproj' require 'active_support/core_ext/string/inflections' module GoNative module Plugins module IOS class BuildFramework autoload :FileUtils, 'fileutils' extend DSL::Serviceable BUILD_TEMPLATE_DIRECTORY_PATH = File.expand_path(File.join(__dir__, '../../../..', 'templates', 'build', 'ios')) attr_reader :plugin_name, :archs, :persist_build_dir def initialize(archs, persist_build_dir) podspec_file = Dir["./*.podspec"].first raise Error, "No podspec exists." unless podspec_file @plugin_name = File.basename(podspec_file, '.podspec') @archs = archs.gsub(',', ' ') @persist_build_dir = persist_build_dir end def call setup_dirs create_framework_proj move_template_files! run_pod_install chmod_frameworks_script! build_framework! move_framework_file ensure FileUtils.cd('..') FileUtils.rm_rf('build') unless persist_build_dir end def setup_dirs build_dir = File.join(FileUtils.pwd, 'build') FileUtils.mkdir(build_dir) FileUtils.cd(build_dir) end def create_framework_proj proj = Xcodeproj::Project.new(FileUtils.pwd) target = proj.new_target(:framework, "#{plugin_name}", :ios, deployment_target) main_group = proj.new_group(plugin_name, plugin_name) add_classes(target, main_group) add_frameworks(target, main_group) add_headers(target, main_group) target.build_configurations.each do |config| config.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES' config.build_settings['MODULEMAP_FILE'] = "#{plugin_name}.modulemap" config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = "org.cocoapods.#{plugin_name}" end proj.save("#{plugin_name}.xcodeproj") end def add_classes(target, group) classes_group = group.new_group('Classes', 'Classes') references = Dir.glob("../#{plugin_name}/Classes/**/*.{m,swift}").map do |file| classes_group.new_file("../../#{file}") end target.add_file_references(references) end def add_frameworks(target, group) frameworks_group = group.new_group('Frameworks', 'Frameworks') references = Dir.glob("../#{plugin_name}/Frameworks/*.{framework,xcframework}").map do |file| frameworks_group.new_file("../../#{file}") end target.frameworks_build_phase.add_file_references(references) if references.length end def add_headers(target, group) headers_group = group.new_group('Headers', 'Headers') references = Dir.glob("../#{plugin_name}/Classes/**/*.h").map { |file| headers_group.new_file("../../#{file}") } header_files = target.add_file_references(references) header_files << target.headers_build_phase.add_file_reference(main_group.new_file("../#{plugin_name}-umbrella.h")) header_files.each do |header| header.settings = { 'ATTRIBUTES' => ['Public'] } end end def move_template_files! plugin_dependencies = spec.dependencies.map{|d| ["pod '#{d.name}'", "'#{d.requirement}'"].compact.join(', ') } * "\n\t" FileUtils.cp_r("#{BUILD_TEMPLATE_DIRECTORY_PATH}/.", '.') headers = Dir.glob("../#{plugin_name}/Classes/**/*.h").map{ |f| "#import \"#{File.basename(f)}\"" } * "\n" Utils::TemplateInflator.new(plugin_name: plugin_name, plugin_dependencies: plugin_dependencies, plugin_headers: headers, archs: archs, deployment_target: deployment_target ).call end def run_pod_install system 'pod install' end def chmod_frameworks_script! FileUtils.chmod 0755, 'create-framework.sh' end def build_framework! Utils::UI.info 'Building framework' return if system('sh create-framework.sh >/dev/null 2>/dev/null') raise Error, "Error building framework. Please run the create-framework file manually to fix any errors" end def move_framework_file FileUtils.rm_rf('../XCFramework') FileUtils.mv("XCFramework", '..', force: true) end def deployment_target spec.deployment_target('ios') || '11.0' end def spec @spec ||= Pod::Specification.from_file("../#{plugin_name}.podspec") end end end end end