Class: KZ::KZFrameworkManager
- Inherits:
-
Object
- Object
- KZ::KZFrameworkManager
- Defined in:
- lib/cocoapods-kz/helpers/kz_framework_manager.rb
Constant Summary collapse
- @@all_resources_cache_info =
{}
Class Method Summary collapse
- .contain_multiple_arch?(file_path) ⇒ Boolean
- .convert_arm64_to_simulator(origin_framework_path, destination_path) ⇒ Object
-
.convert_static_library_to_framework(origin_library_path, framework_basename, destination_path) ⇒ Object
将 xcframework slice 中直接提供的 .a 包装成 create_xcframework 可处理的 .framework。 除了静态库本身,也保留同级目录中的 Headers、Modules 等支持文件。.
- .create_xcframework(origin_framework_path, framework_basename, destination_xcframework_path) ⇒ Object
- .handle_origin_framework(origin_frameworks, kz_pod_target) ⇒ Object
- .handle_origin_library(origin_libraries, kz_pod_target) ⇒ Object
- .is_current_ar_archive?(file_path) ⇒ Boolean
- .is_dynamic_library?(file_path) ⇒ Boolean
- .resources_cache_info ⇒ Object
- .validate_framework_and_get_result(kz_pod_target) ⇒ Object
Class Method Details
.contain_multiple_arch?(file_path) ⇒ Boolean
260 261 262 263 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 260 def self.contain_multiple_arch?(file_path) file_result = `lipo -info #{file_path}` return file_result.include?("Architectures in the fat file") end |
.convert_arm64_to_simulator(origin_framework_path, destination_path) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 94 def self.convert_arm64_to_simulator(origin_framework_path, destination_path) framework_name = origin_framework_path.basename.to_s if framework_name.end_with?(".framework") framework_basename = framework_name.chomp(".framework") xcframework_path = destination_path + "#{framework_basename}.xcframework" return xcframework_path if File.exist?(xcframework_path) && !Dir.empty?(xcframework_path) if self.create_xcframework(origin_framework_path, framework_basename, xcframework_path) return xcframework_path else return origin_framework_path end elsif framework_name.end_with?(".xcframework") framework_basename = framework_name.chomp(".xcframework") xcframework_path = destination_path + "#{framework_basename}.xcframework" return xcframework_path if File.exist?(xcframework_path) info_plist_path = origin_framework_path + "Info.plist" return origin_framework_path unless File.exist?(info_plist_path) info_plist = Xcodeproj::Plist.read_from_path(info_plist_path) available_libraries = info_plist["AvailableLibraries"] available_libraries.each do |available_librarie| if available_librarie["SupportedPlatformVariant"] == "simulator" && available_librarie["SupportedArchitectures"].include?("arm64") FileUtils.mkdir_p(destination_path) unless File.exist?(destination_path) FileUtils.cp_r(origin_framework_path, destination_path) return xcframework_path end end # 找到真机arm64 framework xc_framework_path = "" available_libraries.each do |available_librarie| if available_librarie["SupportedPlatform"] == "ios" if available_librarie["SupportedArchitectures"].include?("arm64") xc_framework_path = origin_framework_path + available_librarie["LibraryIdentifier"] + available_librarie["LibraryPath"] end end end if xc_framework_path == "" || !self.create_xcframework(xc_framework_path, framework_basename, xcframework_path) return origin_framework_path else return xcframework_path end else return origin_framework_path end end |
.convert_static_library_to_framework(origin_library_path, framework_basename, destination_path) ⇒ Object
将 xcframework slice 中直接提供的 .a 包装成 create_xcframework 可处理的 .framework。 除了静态库本身,也保留同级目录中的 Headers、Modules 等支持文件。
146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 146 def self.convert_static_library_to_framework(origin_library_path, framework_basename, destination_path) return origin_library_path unless File.extname(origin_library_path.to_s) == ".a" framework_path = destination_path + "#{framework_basename}.framework" framework_library_path = framework_path + origin_library_path.basename framework_executable_path = framework_path + framework_basename FileUtils.mkdir_p(framework_path) Dir.children(origin_library_path.parent).each do |entry| FileUtils.cp_r(origin_library_path.parent + entry, framework_path) end FileUtils.mv(framework_library_path, framework_executable_path) KZLog.log("'#{origin_library_path.basename}' 已包装为 framework,继续创建 xcframework") framework_path end |
.create_xcframework(origin_framework_path, framework_basename, destination_xcframework_path) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 161 def self.create_xcframework(origin_framework_path, framework_basename, destination_xcframework_path) tempdir = Pathname(Dir.mktmpdir) origin_framework_path = self.convert_static_library_to_framework(origin_framework_path, framework_basename, tempdir + "origin") arm64_path = tempdir + "arm64" FileUtils.mkdir_p(arm64_path) arm64_framework_path = arm64_path + "#{framework_basename}.framework" FileUtils.cp_r(origin_framework_path, arm64_framework_path) arm64_framework_exe_path = arm64_framework_path + framework_basename if self.contain_multiple_arch?(arm64_framework_exe_path) KZLog.run_shell("lipo #{arm64_framework_exe_path} -thin arm64 -output #{arm64_framework_exe_path}") end simulator_path = tempdir + "simulator" FileUtils.mkdir_p(simulator_path) simulator_framework_path = simulator_path + "#{framework_basename}.framework" FileUtils.cp_r(arm64_framework_path, simulator_framework_path) simulator_framework_exe_path = simulator_framework_path + framework_basename temp_framwork_exe_path = tempdir + "#{framework_basename}_arm64_simulator" if self.is_dynamic_library?(arm64_framework_exe_path) KZLog.log("'#{origin_framework_path.basename}' 是一个动态库,开始做Load command转换") xcrun_vtool_show_result = `xcrun vtool -arch arm64 -show #{arm64_framework_exe_path}`.lines.map(&:chomp) framework_sdk_version = "16.0" framework_deployment_version = "12.0" reach_cmd_tag = false xcrun_vtool_show_result.each do |line| reach_cmd_tag = false if line.start_with?("Load command") line_infos = line.lstrip.split next unless line_infos.count == 2 if line_infos.first == "cmd" && line_infos.last == "LC_VERSION_MIN_IPHONEOS" reach_cmd_tag = true end if reach_cmd_tag if line_infos.include?("sdk") framework_sdk_version = line_infos.last elsif line_infos.include?("version") framework_deployment_version = line_infos.last end end end xcrun_vtool_set_result = KZLog.run_shell("xcrun vtool -arch arm64 -set-build-version 7 #{framework_deployment_version} #{framework_sdk_version} -replace -output #{temp_framwork_exe_path} #{arm64_framework_exe_path}") unless xcrun_vtool_set_result KZLog.log("'#{origin_framework_path.basename}' Load command转换转换失败", :warning) FileUtils.rm_r(tempdir) return false end else ar_x_path = tempdir + "ar_x" FileUtils.mkdir_p(ar_x_path) if self.is_current_ar_archive?(arm64_framework_exe_path) KZLog.log("'#{arm64_framework_path.basename}' 是一个ar archive类型静态库,开始拆分.o并重新构建") ar_x_success = KZLog.run_shell("cd #{ar_x_path}; ar x #{arm64_framework_exe_path}") if ar_x_success Dir["#{ar_x_path}/*.o"].each do |file| status = KZLog.run_shell("#{ARM64_TO_SIMULATOR_EXECUTE_PATH} '#{file}'") unless status KZLog.log("'#{file}' 存在.o转换失败", :warning) FileUtils.rm_r(tempdir) return false end end KZLog.run_shell("ar crv #{temp_framwork_exe_path} #{ar_x_path}/*.o") else KZLog.log("'#{origin_framework_path.basename}' ar拆分失败", :warning) FileUtils.rm_r(tempdir) return false end else KZLog.log("'#{origin_framework_path.basename}' 是一个不支持转换的格式,arm64 simulator转换失败", :warning) FileUtils.rm_r(tempdir) return false end end FileUtils.mv("#{temp_framwork_exe_path}", simulator_framework_exe_path) FileUtils.mkdir_p(destination_xcframework_path) unless File.exist?(destination_xcframework_path) KZLog.run_shell("xcodebuild -create-xcframework -framework $(readlink -f '#{arm64_framework_path}') -framework $(readlink -f '#{simulator_framework_path}') -output #{destination_xcframework_path}") FileUtils.rm_r(tempdir) KZLog.log("'#{origin_framework_path.basename}'xcframework创建成功", :success) return true end |
.handle_origin_framework(origin_frameworks, kz_pod_target) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 74 def self.handle_origin_framework(origin_frameworks, kz_pod_target) new_frameworks = [] old_destination_path = kz_pod_target.pod_config_cache_path(false , true) FileUtils.rm_rf(old_destination_path) if File.exist?(old_destination_path) destination_path = kz_pod_target.pod_config_cache_path(true, true) origin_frameworks.each do |origin_framework_path| if kz_pod_target.disable_to_simulator_frameworks.include?(origin_framework_path) new_frameworks.append(origin_framework_path) else new_framework_path = self.convert_arm64_to_simulator(origin_framework_path, destination_path) if new_framework_path == origin_framework_path kz_pod_target.disable_to_simulator_frameworks.append(origin_framework_path) end new_frameworks.append(new_framework_path) end end new_frameworks end |
.handle_origin_library(origin_libraries, kz_pod_target) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 54 def self.handle_origin_library(origin_libraries, kz_pod_target) tempdir = Pathname(Dir.mktmpdir) lib_frameworks_path = tempdir + "lib_frameworks" FileUtils.mkdir_p(lib_frameworks_path) origin_lib_frameworks = [] origin_libraries.each do |origin_library_path| lib_framework_name = origin_library_path.basename(origin_library_path.extname) lib_framework_path = lib_frameworks_path + "#{lib_framework_name}.framework" FileUtils.mkdir_p(lib_framework_path) FileUtils.cp(origin_library_path, lib_framework_path + lib_framework_name) origin_lib_frameworks.append(lib_framework_path) end new_frameworks = handle_origin_framework(origin_lib_frameworks, kz_pod_target) FileUtils.rm_r(tempdir) new_frameworks end |
.is_current_ar_archive?(file_path) ⇒ Boolean
255 256 257 258 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 255 def self.is_current_ar_archive?(file_path) file_result = `file -b #{file_path}` return file_result.include?("current ar archive") end |
.is_dynamic_library?(file_path) ⇒ Boolean
250 251 252 253 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 250 def self.is_dynamic_library?(file_path) file_result = `file -b #{file_path}` return file_result.include?("dynamically linked shared library") end |
.resources_cache_info ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 22 def self.resources_cache_info if @@all_resources_cache_info.count > 0 return @@all_resources_cache_info end Dir.foreach(KZ_POD_CONFIG_POD_TARGETS) do |folder_name| next if folder_name == '.' || folder_name == '..' || folder_name == '.DS_Store' config_folder = KZ_POD_CONFIG_POD_TARGETS + folder_name if File.directory?(config_folder) Dir.foreach(config_folder) do |version| next if version == '.' || version == '..' || version == '.DS_Store' || version == 'Headers' version_folder = config_folder + version if File.directory?(version_folder) have_framework = false Dir.foreach(version_folder) do |file_name| next if file_name == '.' || file_name == '..' || file_name == '.DS_Store' if file_name.end_with?(".xcframework") && File.directory?(version_folder + file_name) have_framework = true break end end @@all_resources_cache_info["#{folder_name}_#{version}"] = version_folder if have_framework end end end end @@all_resources_cache_info end |
.validate_framework_and_get_result(kz_pod_target) ⇒ Object
12 13 14 15 16 17 18 19 20 |
# File 'lib/cocoapods-kz/helpers/kz_framework_manager.rb', line 12 def self.validate_framework_and_get_result(kz_pod_target) resources_cache_info = self.resources_cache_info resource_path = resources_cache_info["#{kz_pod_target.name}_#{kz_pod_target.version}"] return nil unless resource_path result = KZConfigResult.new(kz_pod_target) result.resource_path = resource_path result end |