xcframework_converter 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/arm64-to-sim/Package.swift +28 -0
- data/lib/{arm2sim.swift → arm64-to-sim/Sources/Arm64ToSimLib/Transmogrifier.swift} +124 -56
- data/lib/arm64-to-sim/Sources/Tests/Arm64ToSimTestCase.swift +73 -0
- data/lib/arm64-to-sim/Sources/arm64-to-sim/main.swift +16 -0
- data/lib/xcframework_converter/arm_patcher.rb +14 -2
- data/lib/xcframework_converter/version.rb +1 -1
- data/lib/xcframework_converter.rb +25 -6
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ed138cd025eb265a64d714f9342520dd10ca44c9d78120a20eb6695623f1e86
|
4
|
+
data.tar.gz: 870d95ae53553761641a9572a6e08f58103435f4312035749794353c2d34979c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5f9e9d85f7385b2a1f7406b5942741c7060c9263e751a9e59bdeb13c234e117c0ba1f58a3f3f2c0f509d797b76c9b51afbb12131fde7bdfefe9940a29e4ac4d
|
7
|
+
data.tar.gz: a2201235913e84433ee593288511da552b23cdf9e0e09ca0efdcc525f82ebd2e884d9d134b71f7323ed07a7b1ea88d70d49406492c51e2834afa3af02c1071e9
|
@@ -0,0 +1,28 @@
|
|
1
|
+
// swift-tools-version:5.3
|
2
|
+
import PackageDescription
|
3
|
+
|
4
|
+
let package = Package(
|
5
|
+
name: "arm64-to-sim",
|
6
|
+
platforms: [
|
7
|
+
.macOS(.v11)
|
8
|
+
],
|
9
|
+
products: [
|
10
|
+
.executable(name: "arm64-to-sim", targets: ["arm64-to-sim"])
|
11
|
+
],
|
12
|
+
dependencies: [
|
13
|
+
],
|
14
|
+
targets: [
|
15
|
+
.target(
|
16
|
+
name: "arm64-to-sim",
|
17
|
+
dependencies: [ "Arm64ToSimLib" ]),
|
18
|
+
.target(
|
19
|
+
name: "Arm64ToSimLib",
|
20
|
+
dependencies: []),
|
21
|
+
.testTarget(
|
22
|
+
name: "Tests",
|
23
|
+
dependencies: ["Arm64ToSimLib"],
|
24
|
+
resources: [
|
25
|
+
.copy("TestResources"),
|
26
|
+
])
|
27
|
+
]
|
28
|
+
)
|
@@ -7,12 +7,12 @@ extension Data {
|
|
7
7
|
let lc: load_command = withUnsafeBytes { $0.load(as: load_command.self) }
|
8
8
|
return lc.cmd
|
9
9
|
}
|
10
|
-
|
10
|
+
|
11
11
|
var commandSize: Int {
|
12
12
|
let lc: load_command = withUnsafeBytes { $0.load(as: load_command.self) }
|
13
13
|
return Int(lc.cmdsize)
|
14
14
|
}
|
15
|
-
|
15
|
+
|
16
16
|
func asStruct<T>(fromByteOffset offset: Int = 0) -> T {
|
17
17
|
return withUnsafeBytes { $0.load(fromByteOffset: offset, as: T.self) }
|
18
18
|
}
|
@@ -35,63 +35,75 @@ extension FileHandle {
|
|
35
35
|
}
|
36
36
|
}
|
37
37
|
|
38
|
-
enum Transmogrifier {
|
39
|
-
private static func readBinary(atPath path: String) -> (Data, [Data], Data) {
|
38
|
+
public enum Transmogrifier {
|
39
|
+
private static func readBinary(atPath path: String, isDynamic: Bool = false) -> (Data, [Data], Data) {
|
40
40
|
guard let handle = FileHandle(forReadingAtPath: path) else {
|
41
41
|
fatalError("Cannot open a handle for the file at \(path). Aborting.")
|
42
42
|
}
|
43
|
-
|
43
|
+
|
44
44
|
// chop up the file into a relevant number of segments
|
45
45
|
let headerData = try! handle.read(upToCount: MemoryLayout<mach_header_64>.stride)!
|
46
|
-
|
46
|
+
|
47
47
|
let header: mach_header_64 = headerData.asStruct()
|
48
48
|
if header.magic != MH_MAGIC_64 || header.cputype != CPU_TYPE_ARM64 {
|
49
49
|
fatalError("The file is not a correct arm64 binary. Try thinning (via lipo) or unarchiving (via ar) first.")
|
50
50
|
}
|
51
|
-
|
51
|
+
|
52
52
|
let loadCommandsData: [Data] = (0..<header.ncmds).map { _ in
|
53
53
|
let loadCommandPeekData = try! handle.peek(upToCount: MemoryLayout<load_command>.stride)
|
54
54
|
return try! handle.read(upToCount: Int(loadCommandPeekData!.commandSize))!
|
55
55
|
}
|
56
|
-
|
56
|
+
|
57
|
+
if isDynamic {
|
58
|
+
let bytesToDiscard = abs(MemoryLayout<build_version_command>.stride - MemoryLayout<version_min_command>.stride)
|
59
|
+
_ = handle.readData(ofLength: bytesToDiscard)
|
60
|
+
}
|
61
|
+
|
57
62
|
let programData = try! handle.readToEnd()!
|
58
|
-
|
63
|
+
|
59
64
|
try! handle.close()
|
60
|
-
|
65
|
+
|
61
66
|
return (headerData, loadCommandsData, programData)
|
62
67
|
}
|
63
|
-
|
68
|
+
|
64
69
|
private static func updateSegment64(_ data: Data, _ offset: UInt32) -> Data {
|
65
70
|
// decode both the segment_command_64 and the subsequent section_64s
|
66
71
|
var segment: segment_command_64 = data.asStruct()
|
67
|
-
|
72
|
+
|
68
73
|
let sections: [section_64] = (0..<Int(segment.nsects)).map { index in
|
69
74
|
let offset = MemoryLayout<segment_command_64>.stride + index * MemoryLayout<section_64>.stride
|
70
75
|
return data.asStruct(fromByteOffset: offset)
|
71
76
|
}
|
72
|
-
|
77
|
+
|
73
78
|
// shift segment information by the offset
|
74
79
|
segment.fileoff += UInt64(offset)
|
75
80
|
segment.filesize += UInt64(offset)
|
76
81
|
segment.vmsize += UInt64(offset)
|
77
|
-
|
82
|
+
|
78
83
|
let offsetSections = sections.map { section -> section_64 in
|
84
|
+
let sectionType = section.flags & UInt32(SECTION_TYPE)
|
85
|
+
switch Int32(sectionType) {
|
86
|
+
case S_ZEROFILL, S_GB_ZEROFILL, S_THREAD_LOCAL_ZEROFILL:
|
87
|
+
return section
|
88
|
+
case _: break
|
89
|
+
}
|
90
|
+
|
79
91
|
var section = section
|
80
92
|
section.offset += UInt32(offset)
|
81
93
|
section.reloff += section.reloff > 0 ? UInt32(offset) : 0
|
82
94
|
return section
|
83
95
|
}
|
84
|
-
|
96
|
+
|
85
97
|
var datas = [Data]()
|
86
98
|
datas.append(Data(bytes: &segment, count: MemoryLayout<segment_command_64>.stride))
|
87
99
|
datas.append(contentsOf: offsetSections.map { section in
|
88
100
|
var section = section
|
89
101
|
return Data(bytes: §ion, count: MemoryLayout<section_64>.stride)
|
90
102
|
})
|
91
|
-
|
103
|
+
|
92
104
|
return datas.merge()
|
93
105
|
}
|
94
|
-
|
106
|
+
|
95
107
|
private static func updateVersionMin(_ data: Data, _ offset: UInt32, minos: UInt32, sdk: UInt32) -> Data {
|
96
108
|
var command = build_version_command(cmd: UInt32(LC_BUILD_VERSION),
|
97
109
|
cmdsize: UInt32(MemoryLayout<build_version_command>.stride),
|
@@ -99,68 +111,124 @@ enum Transmogrifier {
|
|
99
111
|
minos: minos << 16 | 0 << 8 | 0,
|
100
112
|
sdk: sdk << 16 | 0 << 8 | 0,
|
101
113
|
ntools: 0)
|
102
|
-
|
114
|
+
|
103
115
|
return Data(bytes: &command, count: MemoryLayout<build_version_command>.stride)
|
104
116
|
}
|
105
|
-
|
117
|
+
|
106
118
|
private static func updateDataInCode(_ data: Data, _ offset: UInt32) -> Data {
|
107
119
|
var command: linkedit_data_command = data.asStruct()
|
108
120
|
command.dataoff += offset
|
109
121
|
return Data(bytes: &command, count: data.commandSize)
|
110
122
|
}
|
111
|
-
|
123
|
+
|
112
124
|
private static func updateSymTab(_ data: Data, _ offset: UInt32) -> Data {
|
113
125
|
var command: symtab_command = data.asStruct()
|
114
126
|
command.stroff += offset
|
115
127
|
command.symoff += offset
|
116
128
|
return Data(bytes: &command, count: data.commandSize)
|
117
129
|
}
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
130
|
+
|
131
|
+
private static func computeLoadCommandsEditor(_ loadCommandsData: [Data], isDynamic: Bool) -> ((Data, UInt32, UInt32) -> Data) {
|
132
|
+
|
133
|
+
if isDynamic {
|
134
|
+
return updateDylibFile
|
135
|
+
}
|
136
|
+
|
137
|
+
var contains_LC_VERSION_MIN_IPHONEOS = false
|
138
|
+
var contains_LC_BUILD_VERSION = false
|
139
|
+
for lc in loadCommandsData {
|
140
|
+
let loadCommand = UInt32(lc.loadCommand)
|
141
|
+
if loadCommand == LC_VERSION_MIN_IPHONEOS {
|
142
|
+
contains_LC_VERSION_MIN_IPHONEOS = true
|
143
|
+
} else if loadCommand == LC_BUILD_VERSION {
|
144
|
+
contains_LC_BUILD_VERSION = true
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
if contains_LC_VERSION_MIN_IPHONEOS == contains_LC_BUILD_VERSION {
|
149
|
+
if contains_LC_BUILD_VERSION == true {
|
150
|
+
fatalError("Bad Mach-O Object file: Both LC_VERSION_MIN_IPHONEOS and LC_BUILD_VERSION are present.\nEither one of them should be present")
|
151
|
+
} else {
|
152
|
+
fatalError("Bad Mach-O Object file: does not contain LC_VERSION_MIN_IPHONEOS or LC_BUILD_VERSION.\nEither one of them should be present")
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
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
|
+
return updatePreiOS12ObjectFile
|
160
|
+
} else {
|
161
|
+
return updatePostiOS12ObjectFile
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
static func updatePostiOS12ObjectFile(lc: Data, minos: UInt32, sdk: UInt32) -> Data {
|
167
|
+
let cmd = Int32(bitPattern: lc.loadCommand)
|
168
|
+
switch cmd {
|
169
|
+
case LC_BUILD_VERSION:
|
170
|
+
return updateVersionMin(lc, 0, minos: minos, sdk: sdk)
|
171
|
+
default:
|
172
|
+
return lc
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
static func updatePreiOS12ObjectFile(lc: Data, minos: UInt32, sdk: UInt32) -> Data {
|
177
|
+
// `offset` is kind of a magic number here, since we know that's the only meaningful change to binary size
|
178
|
+
// having a dynamic `offset` requires two passes over the load commands and is left as an exercise to the reader
|
179
|
+
let offset = UInt32(abs(MemoryLayout<build_version_command>.stride - MemoryLayout<version_min_command>.stride))
|
180
|
+
let cmd = Int32(bitPattern: lc.loadCommand)
|
181
|
+
switch cmd {
|
182
|
+
case LC_SEGMENT_64:
|
183
|
+
return updateSegment64(lc, offset)
|
184
|
+
case LC_VERSION_MIN_IPHONEOS:
|
185
|
+
return updateVersionMin(lc, offset, minos: minos, sdk: sdk)
|
186
|
+
case LC_DATA_IN_CODE, LC_LINKER_OPTIMIZATION_HINT:
|
187
|
+
return updateDataInCode(lc, offset)
|
188
|
+
case LC_SYMTAB:
|
189
|
+
return updateSymTab(lc, offset)
|
190
|
+
case LC_BUILD_VERSION:
|
191
|
+
return updateVersionMin(lc, offset, minos: minos, sdk: sdk)
|
192
|
+
default:
|
193
|
+
return lc
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
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
|
+
let cmd = Int32(bitPattern: lc.loadCommand)
|
202
|
+
guard cmd != LC_BUILD_VERSION else {
|
203
|
+
fatalError("This arm64 binary already contains an LC_BUILD_VERSION load command!")
|
204
|
+
}
|
205
|
+
if cmd == LC_VERSION_MIN_IPHONEOS {
|
206
|
+
return updateVersionMin(lc, offset, minos: minos, sdk: sdk)
|
207
|
+
}
|
208
|
+
return lc
|
209
|
+
}
|
210
|
+
|
211
|
+
|
212
|
+
public static func processBinary(atPath path: String, minos: UInt32 = 13, sdk: UInt32 = 13, isDynamic: Bool = false) {
|
213
|
+
let (headerData, loadCommandsData, programData) = readBinary(atPath: path, isDynamic: isDynamic)
|
214
|
+
|
215
|
+
let editor = computeLoadCommandsEditor(loadCommandsData, isDynamic: isDynamic)
|
216
|
+
|
129
217
|
let editedCommandsData = loadCommandsData
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
return updateSegment64(lc, offset)
|
134
|
-
case LC_VERSION_MIN_IPHONEOS:
|
135
|
-
return updateVersionMin(lc, offset, minos: minos, sdk: sdk)
|
136
|
-
case LC_DATA_IN_CODE, LC_LINKER_OPTIMIZATION_HINT:
|
137
|
-
return updateDataInCode(lc, offset)
|
138
|
-
case LC_SYMTAB:
|
139
|
-
return updateSymTab(lc, offset)
|
140
|
-
case LC_BUILD_VERSION:
|
141
|
-
fatalError("This arm64 binary already contains an LC_BUILD_VERSION load command!")
|
142
|
-
default:
|
143
|
-
return lc
|
144
|
-
}
|
145
|
-
}
|
146
|
-
.merge()
|
147
|
-
|
218
|
+
.map { return editor($0, minos, sdk) }
|
219
|
+
.merge()
|
220
|
+
|
148
221
|
var header: mach_header_64 = headerData.asStruct()
|
149
222
|
header.sizeofcmds = UInt32(editedCommandsData.count)
|
150
|
-
|
223
|
+
|
151
224
|
// reassemble the binary
|
152
225
|
let reworkedData = [
|
153
226
|
Data(bytes: &header, count: MemoryLayout<mach_header_64>.stride),
|
154
227
|
editedCommandsData,
|
155
228
|
programData
|
156
229
|
].merge()
|
157
|
-
|
230
|
+
|
158
231
|
// save back to disk
|
159
232
|
try! reworkedData.write(to: URL(fileURLWithPath: path))
|
160
233
|
}
|
161
234
|
}
|
162
|
-
|
163
|
-
let binaryPath = CommandLine.arguments[1]
|
164
|
-
let minos = UInt32(CommandLine.arguments[2]) ?? 13
|
165
|
-
let sdk = UInt32(CommandLine.arguments[3]) ?? 13
|
166
|
-
Transmogrifier.processBinary(atPath: binaryPath, minos: minos, sdk: sdk)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import Foundation
|
2
|
+
import XCTest
|
3
|
+
import Arm64ToSimLib
|
4
|
+
|
5
|
+
class Arm64ToSimTestCase: XCTestCase {
|
6
|
+
|
7
|
+
|
8
|
+
var tempDir: URL!
|
9
|
+
override func setUp() {
|
10
|
+
self.tempDir = FileManager.default.temporaryDirectory.appendingPathComponent(UUID.init().uuidString)
|
11
|
+
try! FileManager.default.createDirectory(at: self.tempDir, withIntermediateDirectories: false, attributes: nil)
|
12
|
+
copyFixtures()
|
13
|
+
}
|
14
|
+
|
15
|
+
override func tearDown() {
|
16
|
+
try! FileManager.default.removeItem(at: self.tempDir)
|
17
|
+
}
|
18
|
+
|
19
|
+
private func copyFixtures() {
|
20
|
+
let testResourcesPath = Bundle.module.resourcePath!.appending("/TestResources")
|
21
|
+
if let files = try? FileManager.default.contentsOfDirectory(atPath: testResourcesPath){
|
22
|
+
for file in files {
|
23
|
+
var isDir : ObjCBool = false
|
24
|
+
let fileURL = URL(fileURLWithPath: testResourcesPath).appendingPathComponent(file)
|
25
|
+
if FileManager.default.fileExists(atPath: fileURL.path, isDirectory: &isDir) {
|
26
|
+
if !isDir.boolValue {
|
27
|
+
try! FileManager.default.copyItem(at: fileURL, to: tempDir.appendingPathComponent(fileURL.lastPathComponent.replacingOccurrences(of: ".fixture", with: "")))
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
@discardableResult func runCommand(args: [String]) -> (String, Int32) {
|
35
|
+
let task = Process()
|
36
|
+
task.executableURL = URL(fileURLWithPath: args[0])
|
37
|
+
task.arguments = Array(args.dropFirst())
|
38
|
+
task.currentDirectoryURL = tempDir
|
39
|
+
let pipe = Pipe()
|
40
|
+
task.standardOutput = pipe
|
41
|
+
task.standardError = pipe
|
42
|
+
task.launch()
|
43
|
+
task.waitUntilExit()
|
44
|
+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
45
|
+
let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
|
46
|
+
return (output!, task.terminationStatus)
|
47
|
+
}
|
48
|
+
|
49
|
+
private func testConvert(deviceTarget: String, simulatorTarget:String, file: StaticString = #file, line: UInt = #line) {
|
50
|
+
let (sysroot, _) = runCommand(args: ["/usr/bin/xcrun", "--show-sdk-path", "--sdk", "iphonesimulator"])
|
51
|
+
runCommand(args: ["/usr/bin/clang", "-isysroot", sysroot, "-target", simulatorTarget, "-c", "main.c", "-o", "main.arm64.ios.simulator.o"])
|
52
|
+
runCommand(args: ["/usr/bin/clang", "-isysroot", sysroot, "-target", deviceTarget, "-c", "return2.c", "-o", "return2.ios.device.o"])
|
53
|
+
let (loadCommandsOutput, _) = runCommand(args: ["/usr/bin/otool", "-l", "return2.ios.device.o" ])
|
54
|
+
print("LOAD_COMMANDS:")
|
55
|
+
for lc in loadCommandsOutput.split(separator: "\n").filter({$0.contains("cmd")}) {
|
56
|
+
print(lc)
|
57
|
+
}
|
58
|
+
let (_, link_status_failing) = runCommand(args: ["/usr/bin/clang", "-isysroot", sysroot, "-target", deviceTarget, "main.arm64.ios.simulator.o", "return2.ios.device.o"])
|
59
|
+
XCTAssert(link_status_failing != 0)
|
60
|
+
Transmogrifier.processBinary(atPath: tempDir.appendingPathComponent("return2.ios.device.o").path, minos: 13, sdk: 13, isDynamic: false)
|
61
|
+
let (_, link_status_success) = runCommand(args: ["/usr/bin/clang", "-isysroot", sysroot, "-target", "arm64-apple-ios-simulator", "main.arm64.ios.simulator.o", "return2.ios.device.o"])
|
62
|
+
XCTAssert(link_status_success == 0)
|
63
|
+
}
|
64
|
+
|
65
|
+
func testConvertPreiOS12FileFormatToSim() {
|
66
|
+
testConvert(deviceTarget: "arm64-apple-ios11", simulatorTarget: "arm64-apple-ios12-simulator")
|
67
|
+
}
|
68
|
+
|
69
|
+
func testConvertNewObjectFileFormatToSim() {
|
70
|
+
testConvert(deviceTarget: "arm64-apple-ios12", simulatorTarget: "arm64-apple-ios12-simulator")
|
71
|
+
}
|
72
|
+
|
73
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import Foundation
|
2
|
+
import Arm64ToSimLib
|
3
|
+
|
4
|
+
guard CommandLine.arguments.count > 1 else {
|
5
|
+
fatalError("Please add a path to command!")
|
6
|
+
}
|
7
|
+
|
8
|
+
let binaryPath = CommandLine.arguments[1]
|
9
|
+
let minos = (CommandLine.arguments.count > 2 ? UInt32(CommandLine.arguments[2]) : nil) ?? 12
|
10
|
+
let sdk = (CommandLine.arguments.count > 3 ? UInt32(CommandLine.arguments[3]) : nil) ?? 13
|
11
|
+
let isDynamic = (CommandLine.arguments.count > 4 ? Bool(CommandLine.arguments[4]) : nil) ?? false
|
12
|
+
if isDynamic {
|
13
|
+
print("[arm64-to-sim] notice: running in dynamic framework mode")
|
14
|
+
}
|
15
|
+
|
16
|
+
Transmogrifier.processBinary(atPath: binaryPath, minos: minos, sdk: sdk, isDynamic: isDynamic)
|
@@ -42,8 +42,18 @@ module XCFrameworkConverter
|
|
42
42
|
extracted_path.rmtree
|
43
43
|
end
|
44
44
|
|
45
|
+
def gem_path(fragment)
|
46
|
+
Pathname.new(__FILE__).dirname.join('../..').join(fragment)
|
47
|
+
end
|
48
|
+
|
45
49
|
def arm2sim_path
|
46
|
-
|
50
|
+
@arm2sim_path ||= begin
|
51
|
+
warn 'Pre-building `arm64-to-sim` with SwiftPM'
|
52
|
+
Dir.chdir gem_path('lib/arm64-to-sim') do
|
53
|
+
system 'xcrun swift build -c release --arch arm64 --arch x86_64'
|
54
|
+
end
|
55
|
+
gem_path('lib/arm64-to-sim/.build/apple/Products/Release/arm64-to-sim')
|
56
|
+
end
|
47
57
|
end
|
48
58
|
|
49
59
|
def patch_arm_binary_static(slice)
|
@@ -55,8 +65,10 @@ module XCFrameworkConverter
|
|
55
65
|
Dir[extracted_path_dir.join('*.o')].each do |object_file|
|
56
66
|
file = MachO::MachOFile.new(object_file)
|
57
67
|
sdk_version = file[:LC_VERSION_MIN_IPHONEOS].first.version_string.to_i
|
58
|
-
|
68
|
+
`\"#{arm2sim_path}\" \"#{object_file}\" \"#{sdk_version}\" \"#{sdk_version}\"`
|
69
|
+
$stderr.printf '.'
|
59
70
|
end
|
71
|
+
$stderr.puts
|
60
72
|
`cd \"#{extracted_path_dir}\" ; ar crv \"#{extracted_path}\" *.o`
|
61
73
|
|
62
74
|
`xcrun lipo \"#{slice.binary_path}\" -replace arm64 \"#{extracted_path}\" -output \"#{slice.binary_path}\"`
|
@@ -44,8 +44,12 @@ module XCFrameworkConverter
|
|
44
44
|
|
45
45
|
convert_xcframeworks_if_present(frameworks_to_convert)
|
46
46
|
|
47
|
+
remember_spec_as_patched(spec) unless frameworks_to_convert.empty?
|
48
|
+
|
47
49
|
remove_troublesome_xcconfig_items(spec)
|
48
50
|
end
|
51
|
+
|
52
|
+
warn "Specs with patched XCFrameworks: #{@patched_specs.sort.join(', ')}"
|
49
53
|
end
|
50
54
|
|
51
55
|
def convert_xcframeworks_if_present(frameworks_to_convert)
|
@@ -61,12 +65,27 @@ module XCFrameworkConverter
|
|
61
65
|
end
|
62
66
|
|
63
67
|
def remove_troublesome_xcconfig_items(spec)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
spec.attributes_hash[
|
68
|
-
|
69
|
-
|
68
|
+
xcconfigs = %w[
|
69
|
+
pod_target_xcconfig
|
70
|
+
user_target_xcconfig
|
71
|
+
].map { |key| spec.attributes_hash[key] }.compact
|
72
|
+
|
73
|
+
xcconfigs.each do |xcconfig|
|
74
|
+
# some pods put these as a way to NOT support arm64 sim
|
75
|
+
# may stop working if a pod decides to put these in a platform proxy
|
76
|
+
excluded_arm = xcconfig['EXCLUDED_ARCHS[sdk=iphonesimulator*]']&.include?('arm64')
|
77
|
+
not_inlcuded_arm = xcconfig['VALID_ARCHS[sdk=iphonesimulator*]'] && !xcconfig['VALID_ARCHS[sdk=iphonesimulator*]'].include?('arm64')
|
78
|
+
|
79
|
+
remember_spec_as_patched(spec) if excluded_arm || not_inlcuded_arm
|
80
|
+
|
81
|
+
xcconfig.delete('EXCLUDED_ARCHS[sdk=iphonesimulator*]')
|
82
|
+
xcconfig.delete('VALID_ARCHS[sdk=iphonesimulator*]')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def remember_spec_as_patched(spec)
|
87
|
+
@patched_specs ||= Set.new
|
88
|
+
@patched_specs << spec.root.name
|
70
89
|
end
|
71
90
|
end
|
72
91
|
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.
|
4
|
+
version: 0.4.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-
|
11
|
+
date: 2022-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cocoapods
|
@@ -51,7 +51,10 @@ files:
|
|
51
51
|
- README.md
|
52
52
|
- bin/xcfconvert
|
53
53
|
- bin/xcfpatch
|
54
|
-
- lib/
|
54
|
+
- lib/arm64-to-sim/Package.swift
|
55
|
+
- lib/arm64-to-sim/Sources/Arm64ToSimLib/Transmogrifier.swift
|
56
|
+
- lib/arm64-to-sim/Sources/Tests/Arm64ToSimTestCase.swift
|
57
|
+
- lib/arm64-to-sim/Sources/arm64-to-sim/main.swift
|
55
58
|
- lib/xcframework_converter.rb
|
56
59
|
- lib/xcframework_converter/arm_patcher.rb
|
57
60
|
- lib/xcframework_converter/creation.rb
|