xcframework_converter 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc55b13f203a5434a0844c4e3e2bdab78de4cf7e9c518a4e504eb4513aaa65d6
4
- data.tar.gz: 2867a3113f62112a2b324ec4822613edaa8168fbc75a2dc6ac398a074b481028
3
+ metadata.gz: 77324350e0b69d68739d71e4e2bd510b2c46e82076d82c066eb1af2ab7019ff0
4
+ data.tar.gz: dd8c817ba142772da87f18c46fffe50f32e2bad22d4bb8a9e3101650b38818a0
5
5
  SHA512:
6
- metadata.gz: 6664a2115bd38a245669ac19a3504359641c790e613a472fe38f755c8f20c23bd38caa57333b6c5817e3d14c7185df8521ecb7394f28a431529d7f8ca5bcdfbe
7
- data.tar.gz: 2cef2f4dc73b1e9091bd5f3580ec1c307ec40e5248c9732e0de781aa5d8a0b33f9e27e3befda29c5d924c9a6fccc9ef3aa1f9f6d11588297b796cedb66abf69a
6
+ metadata.gz: e7a7693803108e192822db1f4ab0de16bed32d4dc134dd3a69b1b6e54eab4e185e4d466d0626ecd46adc4c0bee677de8a9b8ca28d99485a0f5975147133cd94b
7
+ data.tar.gz: 59a9cac8d54309ddd9efea3901425ad5499cccac741cd6d35cb4a493794a8cf35d083ad63ba6e0528065cd717ee1521c7a8794cd445d2093813f65336af9209e
@@ -104,7 +104,7 @@ public enum Transmogrifier {
104
104
  return datas.merge()
105
105
  }
106
106
 
107
- private static func updateVersionMin(_ data: Data, _ offset: UInt32, minos: UInt32, sdk: UInt32) -> Data {
107
+ private static func createLcBuildVersion(minos: UInt32, sdk: UInt32) -> Data {
108
108
  var command = build_version_command(cmd: UInt32(LC_BUILD_VERSION),
109
109
  cmdsize: UInt32(MemoryLayout<build_version_command>.stride),
110
110
  platform: UInt32(PLATFORM_IOSSIMULATOR),
@@ -115,6 +115,15 @@ public enum Transmogrifier {
115
115
  return Data(bytes: &command, count: MemoryLayout<build_version_command>.stride)
116
116
  }
117
117
 
118
+ private static func updateLcBuildVersion(_ data: Data, minos: UInt32, sdk: UInt32) -> Data {
119
+ var command: build_version_command = data.asStruct()
120
+ command.platform = UInt32(PLATFORM_IOSSIMULATOR)
121
+ command.minos = minos << 16 | 0 << 8 | 0
122
+ command.sdk = sdk << 16 | 0 << 8 | 0
123
+
124
+ return Data(bytes: &command, count: data.count)
125
+ }
126
+
118
127
  private static func updateDataInCode(_ data: Data, _ offset: UInt32) -> Data {
119
128
  var command: linkedit_data_command = data.asStruct()
120
129
  command.dataoff += offset
@@ -154,8 +163,6 @@ public enum Transmogrifier {
154
163
  }
155
164
 
156
165
  if contains_LC_VERSION_MIN_IPHONEOS {
157
- // `offset` is kind of a magic number here, since we know that's the only meaningful change to binary size
158
- // having a dynamic `offset` requires two passes over the load commands and is left as an exercise to the reader
159
166
  return updatePreiOS12ObjectFile
160
167
  } else {
161
168
  return updatePostiOS12ObjectFile
@@ -167,7 +174,7 @@ public enum Transmogrifier {
167
174
  let cmd = Int32(bitPattern: lc.loadCommand)
168
175
  switch cmd {
169
176
  case LC_BUILD_VERSION:
170
- return updateVersionMin(lc, 0, minos: minos, sdk: sdk)
177
+ return updateLcBuildVersion(lc, minos: minos, sdk: sdk)
171
178
  default:
172
179
  return lc
173
180
  }
@@ -182,28 +189,25 @@ public enum Transmogrifier {
182
189
  case LC_SEGMENT_64:
183
190
  return updateSegment64(lc, offset)
184
191
  case LC_VERSION_MIN_IPHONEOS:
185
- return updateVersionMin(lc, offset, minos: minos, sdk: sdk)
192
+ return createLcBuildVersion(minos: minos, sdk: sdk)
186
193
  case LC_DATA_IN_CODE, LC_LINKER_OPTIMIZATION_HINT:
187
194
  return updateDataInCode(lc, offset)
188
195
  case LC_SYMTAB:
189
196
  return updateSymTab(lc, offset)
190
197
  case LC_BUILD_VERSION:
191
- return updateVersionMin(lc, offset, minos: minos, sdk: sdk)
198
+ fatalError("pre-12 object file shold not contain LC_BUILD_VERSION!")
192
199
  default:
193
200
  return lc
194
201
  }
195
202
  }
196
203
 
197
204
  static func updateDylibFile(lc: Data, minos: UInt32, sdk: UInt32) -> Data {
198
- // `offset` is kind of a magic number here, since we know that's the only meaningful change to binary size
199
- // having a dynamic `offset` requires two passes over the load commands and is left as an exercise to the reader
200
- let offset = UInt32(abs(MemoryLayout<build_version_command>.stride - MemoryLayout<version_min_command>.stride))
201
205
  let cmd = Int32(bitPattern: lc.loadCommand)
202
206
  guard cmd != LC_BUILD_VERSION else {
203
207
  fatalError("This arm64 binary already contains an LC_BUILD_VERSION load command!")
204
208
  }
205
209
  if cmd == LC_VERSION_MIN_IPHONEOS {
206
- return updateVersionMin(lc, offset, minos: minos, sdk: sdk)
210
+ return createLcBuildVersion(minos: minos, sdk: sdk)
207
211
  }
208
212
  return lc
209
213
  }
@@ -37,9 +37,8 @@ module XCFrameworkConverter
37
37
  extracted_path = slice.path.join('arm64.dylib')
38
38
  `xcrun lipo \"#{slice.binary_path}\" -thin arm64 -output \"#{extracted_path}\"`
39
39
 
40
- file = MachO::MachOFile.new(extracted_path)
41
- sdk_version = file[:LC_VERSION_MIN_IPHONEOS].first.version_string
42
- `xcrun vtool -arch arm64 -set-build-version 7 #{sdk_version} #{sdk_version} -replace -output \"#{extracted_path}\" \"#{extracted_path}\"`
40
+ minos_version, sdk_version = version_strings(extracted_path).map(&:to_i)
41
+ `xcrun vtool -arch arm64 -set-build-version 7 #{minos_version} #{sdk_version} -replace -output \"#{extracted_path}\" \"#{extracted_path}\"`
43
42
  `xcrun lipo \"#{slice.binary_path}\" -replace arm64 \"#{extracted_path}\" -output \"#{slice.binary_path}\"`
44
43
  extracted_path.rmtree
45
44
  end
@@ -63,36 +62,61 @@ module XCFrameworkConverter
63
62
  `xcrun lipo \"#{slice.binary_path}\" -thin arm64 -output \"#{extracted_path}\"`
64
63
  extracted_path_dir = slice.path.join('arm64-objects')
65
64
  extracted_path_dir.mkdir
66
- object_files = `ar t \"#{extracted_path}\"`.split("\n").map(&:chomp).sort
67
- .select { |o| o.end_with?('.o') }
68
- .group_by(&:itself).transform_values(&:count)
69
- processed_files = []
70
- index = 0
71
- while object_files.any?
72
- object_files.keys.each do |object_file|
73
- file_shard = Digest::MD5.hexdigest(object_file).to_s[0..2]
74
- file_dir = extracted_path_dir.join("#{index}-#{file_shard}")
75
- file_path = file_dir.join(object_file)
76
- file_dir.mkdir unless file_dir.exist?
77
- `ar p \"#{extracted_path}\" \"#{object_file}\" > \"#{file_path}\"`
78
- macho_file = MachO::MachOFile.new(file_path)
79
- sdk_version = macho_file[:LC_VERSION_MIN_IPHONEOS].first.version_string.to_i
80
- `\"#{arm2sim_path}\" \"#{file_path}\" \"#{sdk_version}\" \"#{sdk_version}\"`
81
- $stderr.printf '.'
82
- processed_files << file_path
65
+ if macho_file_type(extracted_path) == :object
66
+ patch_object_file(extracted_path)
67
+ else
68
+ object_files = `ar t \"#{extracted_path}\"`.split("\n").map(&:chomp).sort
69
+ .select { |o| o.end_with?('.o') }
70
+ .group_by(&:itself).transform_values(&:count)
71
+ processed_files = []
72
+ index = 0
73
+ while object_files.any?
74
+ object_files.keys.each do |object_file|
75
+ file_shard = Digest::MD5.hexdigest(object_file).to_s[0..2]
76
+ file_dir = extracted_path_dir.join("#{index}-#{file_shard}")
77
+ file_path = file_dir.join(object_file)
78
+ file_dir.mkdir unless file_dir.exist?
79
+ `ar p \"#{extracted_path}\" \"#{object_file}\" > \"#{file_path}\"`
80
+ patch_object_file(file_path)
81
+ $stderr.printf '.'
82
+ processed_files << file_path
83
+ end
84
+ `ar d \"#{extracted_path}\" #{object_files.keys.map(&:shellescape).join(' ')}`
85
+ $stderr.printf '#'
86
+ object_files.reject! { |_, count| count <= index + 1 }
87
+ index += 1
83
88
  end
84
- `ar d \"#{extracted_path}\" #{object_files.keys.map(&:shellescape).join(' ')}`
85
- $stderr.printf '#'
86
- object_files.reject! { |_, count| count <= index + 1 }
87
- index += 1
89
+ $stderr.puts
90
+ `cd \"#{extracted_path_dir}\" ; ar cqv \"#{extracted_path}\" #{processed_files.map(&:shellescape).join(' ')}`
88
91
  end
89
- $stderr.puts
90
- `cd \"#{extracted_path_dir}\" ; ar cqv \"#{extracted_path}\" #{processed_files.map(&:shellescape).join(' ')}`
91
92
  `xcrun lipo \"#{slice.binary_path}\" -replace arm64 \"#{extracted_path}\" -output \"#{slice.binary_path}\"`
92
93
  extracted_path_dir.rmtree
93
94
  extracted_path.rmtree
94
95
  end
95
96
 
97
+ def macho_file_type(file_path)
98
+ MachO.open(file_path).filetype
99
+ rescue MachO::MagicError
100
+ nil
101
+ end
102
+
103
+ def patch_object_file(file_path)
104
+ minos_version, sdk_version = version_strings(file_path).map(&:to_i)
105
+ `\"#{arm2sim_path}\" \"#{file_path}\" \"#{minos_version}\" \"#{sdk_version}\"`
106
+ end
107
+
108
+ def version_strings(file_path)
109
+ macho_file = MachO::MachOFile.new(file_path)
110
+ if (version_min_command = macho_file.load_commands.find { |c| c.is_a?(MachO::LoadCommands::VersionMinCommand) })
111
+ return [version_min_command.version_string, version_min_command.sdk_string]
112
+ end
113
+ if (build_version_command = macho_file.load_commands.find { |c| c.is_a?(MachO::LoadCommands::BuildVersionCommand) })
114
+ return [build_version_command.minos_string, build_version_command.sdk_string]
115
+ end
116
+
117
+ raise "Could not find version strings in #{file_path}"
118
+ end
119
+
96
120
  public
97
121
 
98
122
  def cleanup_unused_archs(slice)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module XCFrameworkConverter
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xcframework_converter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Makarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-09 00:00:00.000000000 Z
11
+ date: 2022-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocoapods