Tüm Yazılar
KategoriSwift
Okuma Süresi
20 dk okuma
Yayın Tarihi
...
Kelime Sayısı
1.435kelime

Kahveni hazırla - bu içerikli bir makale!

Swift Package Manager plugin sistemiyle kod üretimi, linting, dokümantasyon ve custom build adımlarını otomatikleştirin. Command ve Build Tool plugin türlerini detaylıca öğrenin.

Swift Package Plugins Rehberi: Build Sürecinizi Otomatikleştirin

# Swift Package Plugins Rehberi: Build Sürecinizi Otomatikleştirin

Swift Package Manager artık sadece dependency yönetimi aracı değil — tam teşekküllü bir build otomasyon platformu. Swift 5.6 ile tanıtılan Package Plugins, build sürecinize custom adımlar eklemenize, kod üretmenize ve projenizdeki tekrarlayan görevleri otomatikleştirmenize olanak tanıyor. Eğer hala manuel linting, kod üretimi veya dokümantasyon scriptleri çalıştırıyorsanız, bu rehber hayatınızı değiştirecek.

Not: Bu rehberdeki tüm örnekler Swift 5.9+ ve Xcode 15+ ile test edilmiştir.

İçindekiler


1. Package Plugins Nedir?

Swift Package Plugins, SPM build sürecine müdahale etmenizi sağlayan Swift ile yazılmış araçlardır. İki ana türü vardır:

  1. Build Tool Plugins: Derleme sırasında otomatik çalışır (kod üretimi, asset işleme)
  2. Command Plugins: Manuel olarak tetiklenir (linting, formatting, dokümantasyon)

Her iki tür de sandbox içinde çalışır ve sisteminize sınırlı erişime sahiptir.

Neden Plugin Kullanmalısınız?

  • Tekrarı ortadan kaldırır: Her build öncesi çalıştırdığınız scriptler artık otomatik
  • Platform bağımsız: macOS, Linux — her yerde aynı şekilde çalışır
  • Type-safe: Plugin'ler Swift ile yazılır, derleme zamanı güvenliği sağlar
  • Paylaşılabilir: Plugin'leri package olarak dağıtabilirsiniz
swift
1// Package.swift - Plugin tanımı
2// swift-tools-version: 5.9
3import PackageDescription
4 
5let package = Package(
6 name: "MyApp",
7 products: [
8 .library(name: "MyApp", targets: ["MyApp"])
9 ],
10 targets: [
11 // Ana target
12 .target(
13 name: "MyApp",
14 plugins: [
15 .plugin(name: "CodeGenPlugin")
16 ]
17 ),
18 // Plugin target
19 .plugin(
20 name: "CodeGenPlugin",
21 capability: .buildTool()
22 )
23 ]
24)

2. Plugin Türleri Detaylı Karşılaştırma

Özellik
Build Tool Plugin
Command Plugin
**Çalışma Zamanı**
Her build'de otomatik
Manuel tetikleme
**Sandbox**
Tam sandbox
Kısıtlı (izin ile genişler)
**Dosya Yazma**
Sadece build dizinine
Proje dizinine (izinle)
**Kullanım Alanı**
Kod üretimi, asset işleme
Linting, formatting, deploy
**Performans Etkisi**
Build süresini uzatabilir
Build süresini etkilemez
**Xcode Desteği**
Tam entegrasyon
Sağ tık menüsünden
**CI/CD**
Otomatik çalışır
swift package komutu ile

3. Build Tool Plugin Oluşturma

Build Tool Plugin'ler her derleme öncesinde çalışır ve genellikle kaynak kod üretmek için kullanılır.

Temel Yapı

swift
1// Plugins/CodeGenPlugin/CodeGenPlugin.swift
2import PackagePlugin
3import Foundation
4 
5@main
6struct CodeGenPlugin: BuildToolPlugin {
7 func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
8 // Source target olduğundan emin ol
9 guard let sourceTarget = target as? SourceModuleTarget else {
10 return []
11 }
12 
13 // Giriş dosyalarını bul (.codegen.json uzantılı)
14 let inputFiles = sourceTarget.sourceFiles.filter { file in
15 file.path.extension == "json" && file.path.stem.hasSuffix(".codegen")
16 }
17 
18 // Her dosya için bir build komutu oluştur
19 return inputFiles.map { inputFile in
20 let outputName = inputFile.path.stem
21 .replacingOccurrences(of: ".codegen", with: "")
22 let outputPath = context.pluginWorkDirectory
23 .appending("Generated_\(outputName).swift")
24 
25 return .buildCommand(
26 displayName: "CodeGen: \(outputName)",
27 executable: try! context.tool(named: "codegen-tool").path,
28 arguments: [
29 "--input", inputFile.path.string,
30 "--output", outputPath.string
31 ],
32 inputFiles: [inputFile.path],
33 outputFiles: [outputPath]
34 )
35 }
36 }
37}

Pre-Build vs Build Command

Build Tool Plugin'ler iki tür komut döndürebilir:

  • buildCommand: Giriş dosyaları değiştiğinde çalışır (incremental)
  • prebuildCommand: Her build öncesi çalışır (her seferinde)
swift
1// Prebuild Command örneği - her build'de çalışır
2func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
3 let outputDir = context.pluginWorkDirectory.appending("Generated")
4 
5 return [
6 .prebuildCommand(
7 displayName: "Generate Build Info",
8 executable: try context.tool(named: "build-info-generator").path,
9 arguments: ["--output-dir", outputDir.string],
10 outputFilesDirectory: outputDir
11 )
12 ]
13}

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?


4. Command Plugin Oluşturma

Command Plugin'ler manuel tetiklenir ve proje üzerinde daha geniş yetkiye sahiptir.

swift
1// Plugins/LintPlugin/LintPlugin.swift
2import PackagePlugin
3 
4@main
5struct LintPlugin: CommandPlugin {
6 func performCommand(
7 context: PluginContext,
8 arguments: [String]
9 ) async throws {
10 // SwiftLint aracını bul
11 let swiftLint = try context.tool(named: "swiftlint")
12 
13 // Target'ları belirle
14 var argExtractor = ArgumentExtractor(arguments)
15 let targetNames = argExtractor.extractOption(named: "target")
16 
17 let targets: [Target]
18 if targetNames.isEmpty {
19 targets = context.package.targets
20 } else {
21 targets = try context.package.targets(named: targetNames)
22 }
23 
24 // Her target için lint çalıştır
25 for target in targets {
26 guard let sourceTarget = target as? SourceModuleTarget else {
27 continue
28 }
29 
30 let process = Process()
31 process.executableURL = URL(fileURLWithPath: swiftLint.path.string)
32 process.arguments = [
33 "lint",
34 "--path", sourceTarget.directory.string,
35 "--reporter", "emoji"
36 ]
37 
38 try process.run()
39 process.waitUntilExit()
40 
41 if process.terminationStatus != 0 {
42 Diagnostics.warning("SwiftLint \(target.name) icin uyarilar buldu")
43 }
44 }
45 }
46}

5. Gerçek Dünya Örnekleri

Örnek 1: Mock Generator Plugin

Test dosyalarınız için otomatik mock üretimi:

swift
1// Plugins/MockGenPlugin/MockGenPlugin.swift
2import PackagePlugin
3 
4@main
5struct MockGenPlugin: BuildToolPlugin {
6 func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
7 guard let target = target as? SourceModuleTarget else { return [] }
8 
9 // Protocol dosyalarını bul
10 let protocolFiles = target.sourceFiles.filter { file in
11 file.path.extension == "swift"
12 }
13 
14 let outputDir = context.pluginWorkDirectory.appending("Mocks")
15 
16 return [
17 .prebuildCommand(
18 displayName: "Generate Mocks for \(target.name)",
19 executable: try context.tool(named: "mockgen").path,
20 arguments: [
21 "--sources", target.directory.string,
22 "--output", outputDir.string,
23 "--testable-import", target.name
24 ],
25 outputFilesDirectory: outputDir
26 )
27 ]
28 }
29}

Örnek 2: Asset Catalog Validator

Build sırasında asset'lerinizi doğrulayın:

swift
1struct AssetValidatorPlugin: BuildToolPlugin {
2 func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
3 guard let target = target as? SourceModuleTarget else { return [] }
4 
5 // .xcassets dizinlerini bul
6 let assetCatalogs = target.sourceFiles.filter { file in
7 file.path.extension == "xcassets"
8 }
9 
10 guard !assetCatalogs.isEmpty else { return [] }
11 
12 let reportPath = context.pluginWorkDirectory.appending("asset-report.txt")
13 
14 return [
15 .prebuildCommand(
16 displayName: "Validate Assets",
17 executable: try context.tool(named: "asset-validator").path,
18 arguments: assetCatalogs.map { item in item.path.string } +
19 ["--output", reportPath.string],
20 outputFilesDirectory: context.pluginWorkDirectory
21 )
22 ]
23 }
24}

6. Plugin Güvenlik Modeli

SPM plugin'leri sandbox içinde çalışır. Bu güvenlik katmanını anlamak kritik öneme sahiptir.

Sandbox Kuralları

İzin
Build Tool
Command (varsayılan)
Command (genişletilmiş)
Kaynak okuma
Sadece target dizini
Sadece target dizini
Tüm proje
Dosya yazma
Plugin work dir
Yok
Proje dizini
Ağ erişimi
Yok
Yok
Yok
Process çalıştırma
Tanımlı araçlar
Tanımlı araçlar
Tanımlı araçlar
Ortam değişkenleri
Sınırlı
Sınırlı
Sınırlı

7. CI/CD Entegrasyonu

Plugin'lerinizi CI/CD pipeline'ına entegre etmek kolaydır:

bash
1# GitHub Actions - Command plugin kullanımı
2swift package plugin --allow-writing-to-package-directory lint-code
3swift package plugin --allow-writing-to-package-directory format-code --target MyApp
4 
5# Build tool plugin'ler otomatik çalışır
6swift build
7swift test

swift
1// Cache-aware build tool plugin
2func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
3 let cacheFile = context.pluginWorkDirectory.appending("input-hashes.json")
4 var cachedHashes = loadHashes(from: cacheFile)
5 
6 let sourceTarget = target as! SourceModuleTarget
7 let changedFiles = sourceTarget.sourceFiles.filter { file in
8 let currentHash = computeSHA256(file.path)
9 let isCached = cachedHashes[file.path.string] == currentHash
10 cachedHashes[file.path.string] = currentHash
11 if isCached { Diagnostics.remark("Cache hit: \(file.path.lastComponent)") }
12 return !isCached
13 }
14 
15 saveHashes(cachedHashes, to: cacheFile)
16 // Sadece degisen dosyalar icin build command olustur
17 return changedFiles.map { createCommand(for: $0, context: context) }
18}

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:

Sonuç ve Öneriler

Swift Package Plugins, build sürecinizi modernleştirmenin en etkili yoludur. Manuel scriptlerden kurtulun, tekrarlayan görevleri otomatikleştirin ve ekibinizin verimliliğini artırın. Build Tool Plugin'lerle kod üretimi yapın, Command Plugin'lerle linting ve formatting'i standartlaştırın. Plugin'lerinizi ayrı package olarak yayınlayarak toplulukla paylaşmayı da unutmayın.

Etiketler

#Swift#SPM#Plugins#Build Tools#Automation#DevOps
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz