# ⚡ Cache, Build Optimization va Debugging

> *"Vaqt — eng qimmat resurs. Tuist cache bilan 15 daqiqalik build'ni 15 soniyaga tushiring!"*

---

## Binary Caching nima?

**Binary Caching** — bu Tuist'ning eng kuchli feature'laridan biri. U o'zgarmagan modullarni qayta compile qilish o'rniga, oldindan tayyor qilingan **binary (xcframework)** sifatida ishlatadi.

### Muammo

```
Loyihangizda 20 ta module bor:
├── CoreModule          (o'zgarMAgan ❌)
├── NetworkKit          (o'zgarMAgan ❌)
├── DesignSystem        (o'zgarMAgan ❌)
├── HomeFeature         (O'ZGARGAN ✅)  ← faqat shu 1 ta
├── ProfileFeature      (o'zgarMAgan ❌)
└── ... (yana 15 ta o'zgarMAgan modul)

❌ Xcode: Barcha 20 ta modulni qayta compile qiladi → 15 daqiqa
✅ Tuist: Faqat HomeFeature compile qiladi, qolganlar binary → 15 soniya
```

### Qanday ishlaydi?

```
1-Qadam: tuist cache
┌─────────────────────────────────────────┐
│ Tuist har bir modulni compile qiladi    │
│ va .xcframework formatda saqlaydi       │
│                                         │
│ CoreModule.xcframework      → Cache ✅  │
│ NetworkKit.xcframework      → Cache ✅  │
│ DesignSystem.xcframework    → Cache ✅  │
│ HomeFeature.xcframework     → Cache ✅  │
│ ProfileFeature.xcframework  → Cache ✅  │
└─────────────────────────────────────────┘

2-Qadam: Siz HomeFeature da kod o'zgartirdingiz

3-Qadam: tuist generate HomeFeature
┌─────────────────────────────────────────┐
│ CoreModule      → Binary (cache dan) ⚡ │
│ NetworkKit      → Binary (cache dan) ⚡ │
│ DesignSystem    → Binary (cache dan) ⚡ │
│ HomeFeature     → SOURCE (compile) 🔨   │
│ ProfileFeature  → Binary (cache dan) ⚡ │
└─────────────────────────────────────────┘
```

---

## Cache Buyruqlari

### `tuist cache` — Modullarni Cache'lash

```bash
# Barcha modullarni cache'lash
tuist cache

# Faqat dependency'larni cache'lash (o'zingiz ishlayotgan modulni emas)
tuist cache --dependencies-only

# Ma'lum modulni cache'lash
tuist cache CoreModule NetworkKit
```

### Cache'dan foydalanish

```bash
# Barcha cache'langan modullarni binary bilan generate
tuist generate

# Faqat bitta feature ni generate (qolganlar binary)
tuist generate HomeFeature
```

### Cache Tozalash

```bash
# Cache tozalash
tuist clean
```

---

## Hashing Mexanizmi

Tuist har bir module uchun **hash** hisoblab, o'zgarganligini aniqlaydi.

### Nima hisobga olinadi?

| Ma'lumot | Misol |
|----------|-------|
| Source fayllari | `HomeView.swift` mazmuni |
| Resource fayllari | `Assets.xcassets`, rasmlar |
| Dependencies | `CoreModule` hash'i |
| Build settings | Compiler flaglar, optimization level |
| Swift versiya | `SWIFT_VERSION = 5.9` |

### Hash qanday ishlaydi?

```
HomeFeature hash = SHA256(
    HomeView.swift +
    HomeViewModel.swift +
    Assets.xcassets +
    CoreModule.hash +     ← dependency hash
    build_settings +
    swift_version
)

Agar hash o'zgarMAsa → cache'dan binary ishlating
Agar hash o'zgarSA → qayta compile qiling
```

### Cache bir nechta kompyuterda

Tuist Server (cloud) bilan cache **jamoa bo'ylab** ulashiladi:

```bash
# Tuist Cloud auth
tuist auth

# Cache'ni upload qilish
tuist cache --upload

# Boshqa dasturchi download qiladi
tuist generate  # Avtomatik cloud cache'dan oladi
```

> **Foyda:** Dasturchi A `CoreModule` ni cache'ladi → Dasturchi B uni compile qilmasdan binary oladi.

---

## Xcode Build Optimization

Tuist'dan tashqari, Xcode'ning o'zi ham build'ni tezlashtirish sozlamalari bor.

### 1. Parallel Builds (Parallel Qurilish)

Xcode → Build Settings:
```
PARALLEL_BUILD = YES    # (Default: YES)
```

Xcode bir vaqtda bir nechta target'ni compile qila oladi — agar ular bir-biriga bog'liq bo'lmasa.

```
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│  CoreModule  │  │ DesignSystem│  │  Analytics  │
│  (Thread 1)  │  │  (Thread 2) │  │  (Thread 3) │
└──────┬───────┘  └──────┬──────┘  └──────┬──────┘
       │                 │                │
       └────────┬────────┘                │
                │                         │
       ┌────────▼────────┐                │
       │   HomeFeature   │────────────────┘
       │   (Thread 1)    │
       └────────┬────────┘
                │
       ┌────────▼────────┐
       │     MyApp       │
       └─────────────────┘
```

### 2. Incremental Builds

Xcode faqat **o'zgargan fayllar**ni qayta compile qiladi. Buning ishlashi uchun:

```
✅ Derived Data'ni o'chirmang (Clean build sekin!)
✅ Build folder yagona bo'lsin
✅ Module'lar kichik bo'lsin (TMA bilan!)
```

### 3. Build Timing Summary

Qaysi fayl/target eng sekin compile bo'layotganini aniqlash:

```bash
# Xcode da build time ko'rsatish
defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES

# xcodebuild bilan timing summary
xcodebuild build \
    -workspace MyApp.xcworkspace \
    -scheme MyApp \
    -showBuildTimingSummary
```

**Natija (misol):**
```
CompileSwift (1 file) HomeView.swift         0.8s
CompileSwift (1 file) HomeViewModel.swift     0.3s
CompileSwift (1 file) NetworkClient.swift     2.1s  ← SEKIN!
Ld                    HomeFeature.framework   0.2s
```

> `NetworkClient.swift` 2.1 soniya! — Bu faylni optimize qilish kerak (masalan, generics'ni kamaytirish yoki faylni bo'laklash).

### 4. Compilation Mode

```
// Debug uchun — Incremental (tezroq)
SWIFT_COMPILATION_MODE = incremental

// Release uchun — Whole Module (optimizatsiya)
SWIFT_COMPILATION_MODE = wholemodule
```

**`wholemodule`** — Swift compiler butun modulni bir vaqtda compile qiladi. Bu ko'proq optimizatsiya imkonini beradi lekin sekinroq.
**`incremental`** — Faqat o'zgargan fayllarni compile qiladi. Tezroq lekin kamroq optimizatsiya.

### 5. Build Active Architecture Only

```
// Debug uchun — faqat joriy arxitektura (tezroq)
ONLY_ACTIVE_ARCH = YES

// Release uchun — barcha arxitekturalar
ONLY_ACTIVE_ARCH = NO
```

Tuist da sozlash:
```swift
settings: .settings(
    base: [
        "ONLY_ACTIVE_ARCH[config=Debug]": "YES",
        "ONLY_ACTIVE_ARCH[config=Release]": "NO",
    ]
)
```

---

## Xcode Indexing va Cache

### Indexing nima?

Xcode **index** — bu loyihadagi barcha symbol'lar (function'lar, class'lar, protocol'lar) haqida ma'lumot bazasi. U quyidagilar uchun kerak:

- ✅ **Autocomplete** — kod yozayotganda tavsiyalar
- ✅ **Jump to Definition** — Cmd+Click bilan deklaratsiyaga o'tish
- ✅ **Find Usages** — symbol qayerda ishlatilganini topish
- ✅ **Syntax Highlighting** — kod ranglanishi

### Index qayerda saqlanadi?

```
~/Library/Developer/Xcode/DerivedData/
└── MyApp-abc123def/
    ├── Build/                  ← Build artifacts
    └── Index.noindex/          ← INDEX DATABASE
        └── DataStore/
```

### Cache bilan Index qanday ishlaydi?

Tuist binary cache ishlatganda — **pre-built module** larning index'i ham tayyor bo'ladi:

```
Cached module (binary):
├── CoreModule.xcframework      ← Compile qilingan kod
├── CoreModule.swiftmodule      ← Swift interface (autocomplete uchun)
└── CoreModule.swiftdoc         ← Dokumentatsiya

→ Xcode bu fayllardan INDEX yaratadi — compile qilmasdan!
→ Autocomplete va Jump to Definition ishlaydi ✅
```

### Index muammolari va hal qilish

| Muammo | Yechim |
|--------|--------|
| Autocomplete ishlamayapti | `Cmd+Shift+K` (Clean) yoki Derived Data o'chirish |
| "Indexing..." doimiy ko'rsatadi | Loyihani yoping, Derived Data o'chiring, qayta oching |
| Binary module'da autocomplete yo'q | `.swiftmodule` fayl borligini tekshiring |
| Index juda sekin | Module'larni kichiklating (TMA bilan) |

```bash
# Derived Data to'liq tozalash
rm -rf ~/Library/Developer/Xcode/DerivedData

# Faqat bitta loyiha uchun
rm -rf ~/Library/Developer/Xcode/DerivedData/MyApp-*
```

---

## Tuist Loyihalarida Debugging

### 1. Breakpoints

Tuist bilan generate qilingan loyihada breakpoints **oddiy Xcode loyiha** kabi ishlaydi.

```swift
// HomeViewModel.swift
func loadProducts() async {
    isLoading = true
    do {
        products = try await service.fetchProducts()  // ← Breakpoint qo'ying
        isLoading = false
    } catch {
        errorMessage = error.localizedDescription
        isLoading = false
    }
}
```

> **Muhim:** Binary cache'dan kelgan module'larda breakpoint qo'yish **mumkin emas** (chunki source kod yo'q). Agar debug qilmoqchi bo'lsangiz — o'sha module'ni source'dan generate qiling:

```bash
# Faqat debug qilmoqchi bo'lgan module'ni source bilan
tuist generate HomeFeature CoreModule
# CoreModule source bo'lgani uchun — breakpoint qo'yish mumkin
```

### 2. LLDB — Terminal Debugging

Xcode debug paytida **LLDB** console'da:

```lldb
// O'zgaruvchi qiymatini ko'rish
(lldb) po products
// → [Product(id: "1", name: "iPhone"), Product(id: "2", name: "MacBook")]

// O'zgaruvchi o'zgartirish
(lldb) expr isLoading = false

// Function chaqirish
(lldb) expr service.fetchProducts()

// Memory address ko'rish
(lldb) p &products
```

### 3. Scheme Settings — Debug Configuration

`Project.swift` da debug uchun maxsus sozlamalar:

```swift
schemes: [
    .scheme(
        name: "MyApp-Debug",
        shared: true,
        buildAction: .buildAction(targets: ["MyApp"]),
        runAction: .runAction(
            configuration: .debug,
            executable: "MyApp",
            arguments: .arguments(
                environmentVariables: [
                    "ENABLE_LOGGING": .environmentVariable(value: "1", isEnabled: true),
                    "API_BASE_URL": .environmentVariable(
                        value: "https://staging.api.example.com",
                        isEnabled: true
                    ),
                ],
                launchArguments: [
                    .launchArgument(name: "-com.apple.CoreData.SQLDebug 1", isEnabled: true),
                    .launchArgument(name: "-UITesting", isEnabled: false),
                ]
            )
        ),
        testAction: .targets(
            ["MyAppTests"],
            configuration: .debug,
            options: .options(coverage: true)
        )
    )
]
```

### 4. Environment Variables bilan Debug

```swift
// AppDelegate yoki App.swift da
#if DEBUG
let baseURL = ProcessInfo.processInfo.environment["API_BASE_URL"]
    ?? "https://api.example.com"
#else
let baseURL = "https://api.example.com"
#endif
```

### 5. Network Debugging

```swift
// Tuist manifest da NSAllowsArbitraryLoads
infoPlist: .extendingDefault(with: [
    "NSAppTransportSecurity": [
        "NSAllowsArbitraryLoads": true,  // ⚠️ Faqat Debug uchun!
    ],
])
```

---

## Build Vaqtini O'lchash

### Xcode Build Time ko'rsatish

```bash
# Terminal da yoqish
defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES

# Xcode'ni qayta ishga tushiring
# Endi build tugaganda vaqt ko'rinadi:
# "Build: Succeeded | 12.3s"
```

### xcodebuild Timing Summary

```bash
xcodebuild build \
    -workspace MyApp.xcworkspace \
    -scheme MyApp \
    -destination "platform=iOS Simulator,name=iPhone 16" \
    -showBuildTimingSummary 2>&1 | tail -20
```

**Natija:**
```
Build Timing Summary
CompileSwift          35 tasks    24.5s
Ld                    8 tasks     3.2s
CopySwiftLibs         1 task      0.5s
ProcessInfoPlistFile  2 tasks     0.1s
Total                             28.3s
```

### Sekin Compile bo'ladigan Fayllarni Topish

Xcode → Product → Build Settings ga qo'shing:
```
OTHER_SWIFT_FLAGS = $(inherited) -Xfrontend -warn-long-function-bodies=200
-Xfrontend -warn-long-expression-type-checking=200
```

> Bu 200ms dan uzoq compile bo'ladigan function/expression'lar uchun warning beradi.

---

## Selective Testing

Tuist faqat **o'zgargan modul va unga bog'liq modul'larni** test qiladi:

```bash
# Barcha testlarni ishga tushirish
tuist test

# Faqat o'zgargan modullarning testlarini
tuist test --selective
```

```
O'zgargan modul: CoreModule

Tuist aniqlaydi:
├── CoreModule        → TEST ✅ (o'zgargan)
├── HomeFeature       → TEST ✅ (CoreModule ga bog'liq)
├── ProfileFeature    → TEST ✅ (CoreModule ga bog'liq)
├── DesignSystem      → SKIP ⏭️ (CoreModule ga bog'liq EMAS)
└── Analytics         → SKIP ⏭️ (CoreModule ga bog'liq EMAS)

Natija: 3 ta modul test qilindi (5 ta o'rniga)
```

---

## CI/CD da Cache Strategiyasi

### GitHub Actions misol

```yaml
# .github/workflows/build.yml
name: Build & Test

on: [push, pull_request]

jobs:
  build:
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v4

      # Mise bilan Tuist o'rnatish
      - name: Install Mise
        run: curl https://mise.run | sh

      - name: Install Tuist
        run: mise install tuist

      # Cache restore
      - name: Restore Tuist Cache
        uses: actions/cache@v3
        with:
          path: ~/.tuist/Cache
          key: tuist-cache-${{ hashFiles('**/*.swift') }}

      # Build
      - name: Install Dependencies
        run: tuist install

      - name: Generate
        run: tuist generate --no-open

      - name: Build
        run: tuist build

      # Test (selective)
      - name: Test
        run: tuist test
```

---

## Xulosa

| Feature | Buyruq | Foyda |
|---------|--------|-------|
| **Binary Cache** | `tuist cache` | Build vaqtini ~10x tezlashtirish |
| **Selective Testing** | `tuist test --selective` | Faqat o'zgargan modullarni test |
| **Build Timing** | `-showBuildTimingSummary` | Sekin fayllarni aniqlash |
| **Parallel Build** | `PARALLEL_BUILD=YES` | Modullarni parallel compile |
| **Debugging** | Breakpoints, LLDB, Scheme env vars | Xcode'dek oddiy debug |

---

> 💡 **Keyingi darslik:** [Code Sharing, Templates va App Store Publish](08_code_sharing.md) — ProjectDescriptionHelpers, plugins, va App Store ga chiqarish.

> *"Tez build = tez development = tez delivery. Cache — bu sizning superkuchingiz!"* ⚡
