Skip to content

Instantly share code, notes, and snippets.

@MapaX
Last active April 28, 2021 12:45
Swift command line tool to make any .framework to .xcframework which works then in Apple Silicon M1 mac. The script is used with command "MakeXCFramework.swift myFramework.framework"
#!/usr/bin/env swift
import Foundation
func shell(_ command: String) -> String {
print("Running command: \(command)")
let task = Process()
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.arguments = ["-c", command]
task.launchPath = "/bin/zsh"
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!
return output
}
extension String {
func trim() -> String {
return self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
let frameworkName: String = CommandLine.arguments[1]
let frameworkBegin = frameworkName.components(separatedBy: ".").first!.trim()
print("Found framework \(frameworkName)")
let architectures = shell("lipo -i \(frameworkName)/\(frameworkBegin)")
print("Supported architectures \(architectures)")
let architecturesString: String = architectures.components(separatedBy: ":").last!.trim()
var architecturesArray = architecturesString.components(separatedBy: " ")
if architecturesArray.contains("armv7") {
let oneArchName = "./\(frameworkName)/\(frameworkBegin)"
_ = shell("lipo -remove armv7 \(oneArchName) -o \(oneArchName)")
architecturesArray.remove(at: architecturesArray.firstIndex(of: "armv7")!)
}
if architecturesArray.contains("i386") {
let oneArchName = "./\(frameworkName)/\(frameworkBegin)"
_ = shell("lipo -remove i386 \(oneArchName) -o \(oneArchName)")
architecturesArray.remove(at: architecturesArray.firstIndex(of: "i386")!)
}
var directoryNameArray: [String] = []
for arch in architecturesArray {
let directoryName = "\(frameworkBegin)_\(arch)"
directoryNameArray.append(directoryName)
_ = shell("mkdir \(directoryName)")
_ = shell("cp -R ./\(frameworkName) ./\(directoryName)")
var removedArchs: [String] = architecturesArray
if let index = removedArchs.firstIndex(of: arch){
removedArchs.remove(at: index)
}
for removeArch in removedArchs {
let oneArchName = "./\(directoryName)/\(frameworkName)/\(frameworkBegin)"
_ = shell("lipo -remove \(removeArch) \(oneArchName) -o \(oneArchName)")
}
}
let joinerString = "/\(frameworkName)/ -framework "
let buildResult = shell("xcodebuild -create-xcframework -framework \(directoryNameArray.joined(separator: joinerString))/\(frameworkName)/ -output \(frameworkBegin).xcframework")
print("Building completed: \(buildResult)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment