SPM (Swift Package Manager) Swift ماحولیاتی نظام میں شامل ایک پیکیج مینیجر ہے، جسے Apple نے تیسرے فریق کی لائبریریوں کو جوڑنے، بنانے اور اپ ڈیٹ کرنے کے خودکار کرنے کے لیے تیار کیا ہے۔ SPM ورژن 3.0 (2016) سے Swift کمپائلر کا حصہ ہے اور اسے علیحدہ انسٹالیشن کی ضرورت نہیں ہے۔ CocoaPods اور Carthage کے برعکس، SPM براہ راست کمپائلر اور Xcode کے ساتھ مربوط ہے، جو اسے جدید Swift پروجیکٹس میں انحصار کے انتظام کا معیاری ٹول بناتا ہے۔ اس مضمون میں ہم Package.swift کی ساخت، SPM کمانڈز، اپنے پیکیج بنانے اور متبادل مینیجرز سے منتقلی کا جائزہ لیں گے۔
اہم نکات
SPM (Swift Package Manager) Swift زبان کا سرکاری پیکیج مینیجر ہے، جو swiftc کمپائلر اور Xcode ڈیولپمنٹ ماحول میں شامل ہے۔ یہ ڈیولپرز کو تیسرے فریق کی لائبریریاں شامل کرنے، ان کے ورژن کا انتظام کرنے اور اپنے پیکیج شائع کرنے کی اجازت دیتا ہے۔ SPM پہلی بار Swift 3.0 (ستمبر 2016) میں کمانڈ لائن ٹول کے طور پر ظاہر ہوا اور Xcode 11 (2019) سے گرافیکل انٹرفیس کے ساتھ مکمل طور پر مربوط ہو گیا — اب انحصارات File → Add Packages مینو کے ذریعے شامل کی جاتی ہیں۔
SPM خود بخود Git ریپوزٹریز سے انحصارات کا سورس کوڈ ڈاؤن لوڈ کرتا ہے، انہیں مرکزی پروجیکٹ کے ساتھ متوازی طور پر بناتا ہے اور نتائج کو کیش کرتا ہے تاکہ بعد میں بنانے کے عمل تیز تر ہوں۔ CocoaPods کے برعکس، SPM علیحدہ ورک اسپیس (xcworkspace) نہیں بناتا — انحصارات مرکزی Xcode پروجیکٹ کا حصہ بن جاتے ہیں۔ Swift.org ڈیولپر سروے (2024) کے مطابق، 67% iOS ڈیولپرز SPM استعمال کرتے ہیں، جو اسے Swift ماحولیاتی نظام میں انحصار کے انتظام کا سب سے مقبول ٹول بناتا ہے۔
SPM تین پلیٹ فارمز کو سپورٹ کرتا ہے: Apple (iOS، macOS، tvOS، watchOS، visionOS)، Linux (Ubuntu، CentOS، Amazon Linux) اور سرور سائیڈ Swift (Vapor, Kitura)۔ Linux پر، SPM Xcode کے بغیر مکمل طور پر کمانڈ لائن کے ذریعے کام کرتا ہے۔
SPM تین اہم تصورات کے گرد بنایا گیا ہے: پیکیجز (packages)، مصنوعات (products) اور ہدف (targets)۔ پیکیج Package.swift مینی فیسٹ کے ساتھ ایک Git ریپوزٹری ہے۔ مصنوعہ بنانے کا نتیجہ ہے (ایک لائبریری یا قابل عمل فائل)۔ ہدف پیکیج کے اندر ایک ماڈیول ہے جو ایک بلڈ یونٹ میں کمپائل ہوتا ہے۔
جب کوئی ڈیولپر Package.swift میں انحصار شامل کرتا ہے، SPM درج ذیل اقدامات کرتا ہے:
~Library/Caches/org.swift.swiftpm/ میں محفوظ کرتا ہے۔Package.resolved فائل تمام انحصاروں کے صحیح ورژن کو مقفل کرتی ہے تاکہ ڈیولپمنٹ ٹیم لائبریریوں کے ایک جیسے سیٹ کے ساتھ کام کرے۔ اس فائل کو ورژن کنٹرول (git) میں شامل کیا جانا چاہیے۔
متبادل کے مقابلے میں SPM کا ایک اہم فائدہ مرکزی رجسٹری کی عدم موجودگی ہے۔ پیکیجز کسی بھی عوامی Git ریپوزٹری میں رہ سکتے ہیں: GitHub، GitLab، Bitbucket، نیز کمپنی کے پرائیویٹ Git سرورز پر۔ Swift 5.2 سے، SPM بائنری انحصار (binary targets) کو سپورٹ کرتا ہے — بند ماخذ لائبریریاں جو سورس کوڈ فراہم کیے بغیر XCFramework کے طور پر تقسیم کی جاتی ہیں۔
Package.swift ایک Swift فائل ہے جو پیکیج کی ساخت اور اس کے انحصار کو بیان کرتی ہے۔ فائل خود Swift میں لکھی جاتی ہے (JSON یا YAML نہیں)، جو مینی فیسٹ کے اندر مشروط منطق، حساب شدہ مستقل اور فنکشن استعمال کرنے کی اجازت دیتی ہے۔
Package.swift کی بنیادی ساخت:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyLibrary",
platforms: [
.iOS(.v16),
.macOS(.v13)
],
products: [
.library(
name: "MyLibrary",
targets: ["MyLibrary"]
),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git",
from: "5.9.0"),
.package(url: "https://github.com/onevcat/Kingfisher.git",
from: "7.12.0"),
],
targets: [
.target(
name: "MyLibrary",
dependencies: [
"Alamofire",
"Kingfisher"
]
),
.testTarget(
name: "MyLibraryTests",
dependencies: ["MyLibrary"]
),
]
)
آئیے اہم عناصر کا جائزہ لیں:
// swift-tools-version: 5.9 — ہدایت جو SPM ورژن بتاتی ہے؛ اس پر مینی فیسٹ کا دستیاب نحو منحصر ہے۔name — پیکیج کا نام، Xcode میں ظاہر ہوتا ہے اور انحصار کے لنکس میں استعمال ہوتا ہے۔platforms — کم از کم پلیٹ فارم ورژن؛ SPM پرانے OS ورژن پر پیکیج بنانے کی اجازت نہیں دے گا۔products — پیکیج "برآمد" کیا کرتا ہے: ایک لائبریری (.library) یا قابل عمل فائل (.executable)۔dependencies — URL اور ورژن کے ساتھ بیرونی پیکیجز کی فہرست؛ from:، exact:، branch:، revision: سپورٹ کرتا ہے۔targets — بلڈ اہداف؛ ہر ہدف میں متعلقہ ڈائرکٹری (Sources/TargetName/) سے انحصار، وسائل اور swift فائلوں کی فہرست ہوتی ہے۔عین ورژن، برانچ اور کمٹ کی وضاحت کی مثال:
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git",
exact: "1.17.3"),
.package(url: "https://github.com/pointfreeco/swift-composable-architecture.git",
branch: "main"),
.package(url: "https://github.com/apple/swift-log.git",
revision: "e5c6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4"),
]
Swift 5.9 سے، Package.swift میں static framework اور linkerSettings کے لیے سپورٹ شامل کیا گیا ہے، جو جامد اور متحرک لائبریریوں کے لیے زیادہ درست لنکر کنفیگریشن کی اجازت دیتا ہے۔
Swift Package Manager ٹرمینل کے ذریعے کام کرنے کے لیے کمانڈز کا ایک سیٹ فراہم کرتا ہے۔ کمانڈز پیکیج کی روٹ ڈائرکٹری (جہاں Package.swift موجود ہے) سے چلائے جاتے ہیں۔
# لائبریری کے ساتھ نیا پیکیج بنائیں
swift package init --type library
# قابل عمل پیکیج بنائیں (کنسول ایپلیکیشن)
swift package init --type executable
# پروجیکٹ بنائیں
swift build
# ریلیز کنفیگریشن میں بنائیں
swift build -c release
# ٹیسٹ چلائیں
swift test
# مخصوص ٹیسٹ چلائیں
swift test --filter "MyLibraryTests/testExample"
# انحصار ڈاؤن لوڈ اور حل کریں
swift package resolve
# انحصار کو تازہ ترین ورژن میں اپ ڈیٹ کریں
swift package update
# انحصار گراف دکھائیں
swift package show-dependencies
# بلڈ کیش صاف کریں
swift package clean
# Xcode پروجیکٹ بنائیں (Xcode 11 سے پہلے)
swift package generate-xcodeproj
Xcode کے اندر کام کرتے وقت، ان میں سے زیادہ تر کمانڈز خود بخود انجام پاتی ہیں: پروجیکٹ کھلنے پر انحصار حل ہو جاتے ہیں، ⌘B سے بلڈ شروع ہوتا ہے، ⌘U سے ٹیسٹ۔ تاہم، CI/CD پائپ لائنز (GitHub Actions، GitLab CI، Jenkins) کے لیے ٹرمینل کمانڈز کا علم ضروری ہے جہاں Xcode دستیاب نہیں ہے۔
swift package resolve کمانڈ Package.resolved فائل بناتی یا اپ ڈیٹ کرتی ہے۔ یہ فائل متعدی سمیت تمام انحصاروں کے عین ورژن کو مقفل کرتی ہے اور اسے git میں شامل کیا جانا چاہیے۔ ہر نئی فیچر برانچ سے پہلے تازہ ترین لائبریری ورژن کے ساتھ کام کرنے کے لیے swift package update چلانے کی سفارش کی جاتی ہے۔
اپنا SPM پیکیج بنانا ملٹی ماڈیول پروجیکٹس میں کاروباری منطق کو سمیٹنے اور اوپن سورس لائبریریاں شائع کرنے کے لیے مفید ہے۔ آئیے مرحلہ وار عمل دیکھتے ہیں۔
mkdir MyNetworkKit
cd MyNetworkKit
swift package init --type library
swift package init کمانڈ مندرجہ ذیل ساخت بناتا ہے:
MyNetworkKit/
├── Package.swift
├── README.md
├── Sources/
│ └── MyNetworkKit/
│ └── MyNetworkKit.swift
└── Tests/
└── MyNetworkKitTests/
└── MyNetworkKitTests.swift
SPM خود بخود Sources/ اور Tests/ ڈائرکٹریز کو اسکین کرتا ہے: Sources کے اندر ہر ذیلی ڈائرکٹری ایک ہدف (target) سے مطابقت رکھتی ہے۔
آئیے انحصار شامل کریں اور ہدف پلیٹ فارم ترتیب دیں:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyNetworkKit",
platforms: [
.iOS(.v15),
.macOS(.v12)
],
products: [
.library(
name: "MyNetworkKit",
targets: ["MyNetworkKit"]
),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git",
from: "5.9.0"),
],
targets: [
.target(
name: "MyNetworkKit",
dependencies: ["Alamofire"]
),
.testTarget(
name: "MyNetworkKitTests",
dependencies: ["MyNetworkKit"]
),
]
)
// Sources/MyNetworkKit/MyNetworkKit.swift
import Foundation
import Alamofire
public struct NetworkClient {
private let session: Session
public init() {
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30
self.session = Session(configuration: configuration)
}
public func fetchData(from url: String) async throws -> Data {
let response = try await session.request(url).serializingData().value
return response
}
}
پیکیج کو Git ریپوزٹری میں پش کریں اور SemVer ٹیگ بنائیں:
git init
git add .
git commit -m "Initial commit: MyNetworkKit"
git remote add origin https://github.com/username/MyNetworkKit.git
git push -u origin main
git tag 1.0.0
git push --tags
اس کے بعد، کوئی بھی ڈیولپر .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0") استعمال کرکے آپ کا پیکیج شامل کر سکتا ہے۔
Alamofire Swift کے لیے سب سے مقبول HTTP کلائنٹ ہے۔ آئیے اسے SPM کے ذریعے شامل کریں اور GET درخواست کریں۔
import Alamofire
func fetchUsers() {
AF.request("https://jsonplaceholder.typicode.com/users")
.validate()
.responseDecodable(of: [User].self) { response in
switch response.result {
case .success(let users):
print("(users.count) صارفین موصول ہوئے")
case .failure(let error):
print("خرابی: (error.localizedDescription)")
}
}
}
Swinject لائبریری Swift کے لیے DI کنٹینر فراہم کرتی ہے۔ یہ .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0") کے ذریعے شامل کی جاتی ہے۔
import Swinject
let container = Container()
container.register(NetworkServiceProtocol.self) { _ in NetworkService() }
container.register(DataRepositoryProtocol.self) { r in
DataRepository(networkService: r.resolve(NetworkServiceProtocol.self)!)
}
let repository = container.resolve(DataRepositoryProtocol.self)
repository?.loadData()
Apple کا swift-log پیکیج ایک متحد لاگنگ API فراہم کرتا ہے جو متعدد بیک اینڈز (OSLog، کنسول، فائلیں) کو سپورٹ کرتا ہے۔
import Logging
var logger = Logger(label: "com.myapp.network")
logger.logLevel = .debug
logger.info("نیٹ ورک کی درخواست شروع ہوئی", metadata: [
"url": "(requestURL)",
"method": "GET"
])
logger.warning("جوابی وقت 2 سیکنڈ سے تجاوز کر گیا")
logger.error("کنکشن کی خرابی: انٹرنیٹ نہیں ہے")
یہ تینوں مثالیں SPM کے عام استعمال کے منظرناموں کا احاطہ کرتی ہیں: HTTP کلائنٹس، DI کنٹینرز اور نظام کا بنیادی ڈھانچہ۔ لائبریری کا انتخاب اتفاقی نہیں ہے — Alamofire، Swinject اور swift-log GitHub پر سب سے زیادہ ستاروں والے ٹاپ 20 Swift پیکیجز میں شامل ہیں۔
اگر آپ کا پروجیکٹ CocoaPods یا Carthage استعمال کرتا ہے، تو SPM میں منتقلی چند مراحل میں کی جاتی ہے۔ یہ عمل محفوظ ہے: SPM انحصار ایک ہی پروجیکٹ میں CocoaPods اور Carthage کے ساتھ ایک ساتھ رہ سکتے ہیں، جس سے بتدریج منتقلی ممکن ہوتی ہے۔
.xcworkspace ہٹائیں، .xcodeproj کھولیں اور Clean Build Folder کریں۔rm -rf Carthage/ چلائیں۔2025 تک، SPM زیادہ تر مقبول Swift لائبریریوں کو سپورٹ کرتا ہے۔ مستثنیات کچھ ObjC فریم ورک ہیں جن میں ماڈیول میپ نہیں ہے۔ اگر کوئی لائبریری ابھی تک SPM کو سپورٹ نہیں کرتی — تو اس کے README میں Installation سیکشن دیکھیں؛ زیادہ تر مصنفین نے تازہ ترین ورژنز میں SPM سپورٹ پہلے ہی شامل کر دیا ہے۔
اکثر پوچھے گئے سوالات
SPM Swift کمپائلر اور Xcode میں شامل ہے، اسے gem یا Homebrew کے ذریعے انسٹالیشن کی ضرورت نہیں ہے۔ CocoaPods ایک مرکزی Specs رجسٹری استعمال کرتا ہے اور علیحدہ ورک اسپیس بناتا ہے۔ Carthage پروجیکٹ انضمام کے بغیر فریم ورک کے ذریعے کام کرتا ہے۔ SPM واحد مینیجر ہے جو کمپائلر کی سطح پر مربوط ہے: انحصار مرکزی کوڈ کے ساتھ متوازی طور پر حل، کیش اور بنائے جاتے ہیں۔
ہاں، SPM مخلوط Swift + Objective-C پروجیکٹس کو سپورٹ کرتا ہے۔ SPM پیکیج کے اندر ObjC فائلیں خود بخود Umbrella Header میں شامل ہو جاتی ہیں بشرطیکہ درست modulemap موجود ہو۔ تاہم، SPM ان جامد ObjC لائبریریوں کو سپورٹ نہیں کرتا جن کے پاس ماڈیول میپ نہیں ہے۔ ObjC لائبریریوں کو SPM کے ذریعے صرف اس صورت میں جوڑنے کی سفارش کی جاتی ہے اگر وہ modulemap فراہم کریں یا خالص C میں لکھی گئی ہوں۔
SPM سیمینٹک ورژننگ (SemVer) استعمال کرتا ہے۔ اگر پیکیج A کو Alamofire 5.8+ درکار ہے اور پیکیج B کو Alamofire 5.9+ درکار ہے، SPM 5.9.x ورژن منتخب کرے گا جو دونوں کو پورا کرتا ہے۔ اگر تنازع حل نہ ہو سکے (ایک پیکیج کو 5.x درکار ہے، دوسرے کو 6.x)، SPM خرابی کی اطلاع دے گا۔ اس صورت میں، آپ کو ایک پیکیج کو اپ ڈیٹ کرنا ہوگا یا انحصار کو دونوں ضروریات کے مطابق ورژن میں تبدیل کرنا ہوگا۔
macOS پر: ~Library/Caches/org.swift.swiftpm/ اور ~/Library/Developer/Xcode/DerivedData/۔ Linux پر: ~cache/swiftpm/۔ بلڈ کے دوران، SPM سورس کوڈ اور کمپائل شدہ آبجیکٹ فائلوں کو کیش کرتا ہے۔ کیش کو مکمل طور پر صاف کرنے کے لیے، swift package reset چلائیں — یہ کمانڈ موجودہ پروجیکٹ کے لیے انحصار کیش اور DerivedData کو ہٹا دیتا ہے۔
ہاں، Swift 5.2 سے SPM بائنری اہداف (binary targets) کو سپورٹ کرتا ہے۔ بند ماخذ لائبریری XCFramework کے طور پر تقسیم کی جاتی ہے اور .xcframework کا راستہ Package.swift میں بتایا جاتا ہے۔ سورس کوڈ ظاہر نہیں کیا جاتا۔ بائنری ہدف .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework") کے ذریعے بتایا جاتا ہے۔ یہ لائسنس معاہدوں کی خلاف ورزی کیے بغیر تجارتی SDKs کو جوڑنے کی اجازت دیتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔