Azimjon Abdurasulov

03. Directory Structure va CLI

🚀 Tuist — Mukammal Qo‘llanma & Amaliyot

Tuist 03: Papka tuzilmasi va CLI — har bir buyruq 2026 holatida, real natijalar bilan

Holat: 2026-yil oktabr. Bu dars Tuist loyihasining papka tuzilmasini (Tuist.swift, Tuist/, Projects/, ProjectDescriptionHelpers/), nima commit qilinishi va nima generatsiya qilinishini, hamda Tuist CLI'ning har bir buyrug'ini real ishga tushirish bilan ko'rsatadi. Barcha kod va natijalar Tuist 4.211.1 va Xcode 27.1 bilan Apple M4 Pro'da tekshirilgan.

Bu darsdan keyin siz: bo'sh papkadan to'liq modulli Tuist loyihasini qura olasiz, har bir CLI buyrug'i nima qilishini va qachon kerakligini bilasiz, .gitignore'ni to'g'ri yozib jamoada merge conflict'larni yo'qotasiz.

  • Tavsiya etilgan papka tuzilmasini yod bilan emas, sababini tushungan holda qo'llaysiz.
  • tuist init'dan tuist generate'gacha har bir buyruqni real natijasi bilan ko'rasiz.
  • Implicit va redundant dependency'larni tuist inspect dependencies bilan tutasiz (real xato + yechim).
  • Nima git'da saqlanadi, nima generatsiya qilinadi — chalkashlik qolmaydi.
  • Tuist versiyasini jamoa uchun pin qilishni va TUIST_* env'larni bilasiz.

Mundarija

  1. Nega papka tuzilmasi hal qiluvchi ahamiyatga ega
  2. Tavsiya etilgan papka tuzilmasi
  3. Har bir fayl va papka nima qiladi
  4. Nima commit qilinadi, nima generatsiya qilinadi
  5. [tuist init — noldan loyiha](#tuist-init)
  6. CLI xaritasi — buyruqlar ish bosqichi bo'yicha
  7. Kundalik oqim: install, generate, edit
  8. Ko'rish buyruqlari: graph va dump
  9. Tekshirish: inspect dependencies va hash
  10. Build va test: xcodebuild, tuist test, run
  11. Cache va tozalash: cache, clean
  12. Server buyruqlari (akkaunt kerak)
  13. Environment variable'lar va kataloglar
  14. Versiyani pin qilish (release channels)
  15. Real natijalar: o'lchangan vaqtlar
  16. Amaliy mashqlar
  17. O'zingizni tekshiring
  18. Xulosa
  19. Manbalar

1. Nega papka tuzilmasi hal qiluvchi ahamiyatga ega {#nega-struktura}

Xcode loyihasida papka tuzilmasi ikkinchi darajali masala — .xcodeproj ichida hamma narsa yashiringan va siz Xcode UI orqali fayl qo'shasiz. Tuist'da aksincha: papka tuzilmasi — bu loyihaning o'zi. Tuist .xcodeproj'ni har safar Swift manifest'lardan va diskdagi papkalardan qayta yasaydi. Shu sababli tuzilmani tushunmasdan Tuist'ni o'zlashtirib bo'lmaydi.

Bu nazariy gap emas. Asana muhandislik jamoasi (Mobile Foundations, 2023-yil 21-fevral) ~300 ming qator Swift kodini deyarli bitta target'da olib yurar edi. Ular Bazel'ni ham sinab ko'rishdi, lekin developer experience muammolari (og'ir sozlash, breakpoint'lar bilan nizolar) sababli Tuist'ni tanlashdi. Loyiha manifest'i ~1 400 qatorga yetdi; uni bir necha haftada yozishdi, so'ng kodni modullarga ko'chirish ~3 oy davom etdi. Natijada "o'zgartir va qayta qur" (change-and-rebuild) sikli odatdagi ~45 soniyadan ~15 soniyaga (median) tushdi.

🚀 Motivatsiya: Tuist papka tuzilmasi — bu shunchaki "chiroyli tartib" emas. To'g'ri tuzilma sizga uchta aniq narsani beradi: (1) git konfliktlari deyarli yo'qoladi, chunki .xcodeproj endi git'da yo'q; (2) jamoadagi har bir developer bir xil loyihani ko'radi, chunki uni kod yasaydi; (3) modullarga bo'linish binary cache va selective testing uchun yo'l ochadi (keyingi darslarda o'lchab ko'rsatamiz). Asana'ning 45s → 15s siklini aynan shu tuzilma mumkin qildi.

⚠️ Diqqat: Asana o'z postida halol tan oladi — jamoaning faqat ozchiligi Tuist'ning ichki ishlashini chuqur tushunardi. Ya'ni tuzilma kuchli, lekin jamoaga uni o'rgatish kerak. Shuning uchun bu darsda biz "shunchaki nusxa ko'chir" demaymiz — har bir papka nega borligini tushuntiramiz.

Avvalgi darsda (02. Manifest fayllar) biz Project.swift, Workspace.swift, Tuist.swift va Package.swift sintaksisini o'rgandik. Endi bu fayllar diskda qayerda turishi va ularni CLI qanday topishini ko'ramiz.


2. Tavsiya etilgan papka tuzilmasi {#papka-tuzilmasi}

Tuist rasmiy hujjatidagi standart loyiha tuzilmasi quyidagicha ko'rinadi (manba: directory-structure):

Tuist.swift
Tuist/
  Package.swift
  ProjectDescriptionHelpers/
Projects/
  App/
    Project.swift
  Feature/
    Project.swift
Workspace.swift

Biz butun dars davomida shu tuzilmani real loyihada quramiz. "Kutubxona" degan oddiy ilova bo'ladi — kitoblar ro'yxati. Mana biz yaratgan va tekshirgan to'liq daraxt:

Kutubxona/
├── Tuist.swift                         ← root marker + global config
├── Tuist/
│   ├── Package.swift                   ← tashqi SPM dependency'lar
│   └── ProjectDescriptionHelpers/
│       └── Module.swift                ← manifest'lar orasida shared kod
├── Workspace.swift                     ← bir nechta Project'ni birlashtiradi
├── Projects/
│   ├── App/
│   │   ├── Project.swift               ← ilova (App target)
│   │   ├── Sources/
│   │   │   └── KutubxonaApp.swift
│   │   └── Resources/
│   ├── CoreKit/
│   │   ├── Project.swift               ← domen modeli (static framework)
│   │   ├── Sources/
│   │   │   └── Book.swift
│   │   └── Tests/
│   │       └── LibraryTests.swift
│   └── Logger/
│       ├── Project.swift
│       ├── Sources/
│       └── Tests/
└── .gitignore

Ikkita asosiy qoida bu tuzilmani boshqaradi:

  1. **Tuist papkasi loyihaning ildizini (root) belgilaydi.** Tuist buyruqlarini loyihaning istalgan sub-papkasidan ishga tushirsangiz ham, Tuist yuqoriga qarab Tuist/ papkasini (yoki Tuist.swift'ni) qidiradi va shuni ildiz deb biladi. Barcha nisbiy yo'llar shu ildizdan hisoblanadi.
  2. **Project.swift yoki Workspace.swift — loyihaga kirish nuqtasi.** Buyruqlar joriy papkada (yoki --path bilan ko'rsatilgan papkada) shu fayllardan birini kutadi.

🧠 Esda tuting: Tuist/ papkasi (ichida Package.swift yoki ProjectDescriptionHelpers/ bo'lgan) — bu kompas. Siz Projects/App/ ichida tursangiz ham, tuist generate yuqoriga qarab ildizni topadi. Agar tuistni butunlay boshqa papkada ishga tushirsangiz, u "Tuist loyihasini topa olmadim" deydi — demak siz ildizdan tashqaridasiz.

💡 Pro tip: Xcode workspace'larni avval "merge conflict kamaysin" deb bir nechta .xcodeproj'ga bo'lib ishlatishardi. Tuist'da bunga ehtiyoj yo'q — Tuist bitta Project.swift'dan ham avtomatik workspace yasaydi (loyiha + uning dependency'lari). Workspace.swift'ni faqat bir nechta mustaqil Project'ni qo'lda guruhlash kerak bo'lgandagina yozasiz (manba: directory-structure doc).


3. Har bir fayl va papka nima qiladi {#har-bir-fayl}

Tuist.swift — ildiz belgisi va global config

Loyihaning eng yuqori papkasida turadi va ikki vazifani bajaradi: (1) "loyiha shu yerdan boshlanadi" deb belgilaydi; (2) barcha loyihalar uchun umumiy sozlamalarni saqlaydi.

2026-yilda minimal Tuist.swift juda qisqa:

// Tuist.swift
import ProjectDescription

let tuist = Tuist(project: .tuist())

⚠️ Diqqat: Eski darsliklar va blog postlarida Tuist.swift ichida generationOptions: .options(enforceExplicitDependencies: true) yozilgan. Tuist 4.211.1'da **enforceExplicitDependencies deprecated** — uning o'rnini tuist inspect dependencies buyrug'i egalladi (9-bo'limda ko'rasiz). Shuning uchun minimal konfiguratsiya endi faqat Tuist(project: .tuist()). Agar eski loyihada u qolgan bo'lsa, ogohlantirish chiqadi.

Tuist/ papkasi

Ildiz ichidagi bu papka ikki narsani saqlaydi.

**1. Tuist/Package.swift — tashqi SPM dependency'lar.** Bu oddiy SPM Package.swift'dan farq qiladi: bu yerda faqat dependency'lar sanaladi, sizning target'laringiz emas. #if TUIST bloki esa Tuist'ga paketlarni qanday integratsiya qilishni aytadi:

// Tuist/Package.swift
// swift-tools-version: 6.0
import PackageDescription

#if TUIST
    import struct ProjectDescription.PackageSettings

    let packageSettings = PackageSettings(
        // Mahsulot turini moslash mumkin. Default — .staticFramework
        // productTypes: ["Alamofire": .framework]
        productTypes: [:]
    )
#endif

let package = Package(
    name: "Kutubxona",
    dependencies: [
        // .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
    ]
)

Bu aynan tuist init yasaydigan fayl (biz 5-bo'limda real ishga tushiramiz). Dependency'larni to'liq boshqarish keyingi darsda: 04. Dependency'lar.

**2. Tuist/ProjectDescriptionHelpers/ — manifest'lar orasidagi shared kod.** Bu papkadagi Swift fayllarni istalgan manifest import ProjectDescriptionHelpers bilan ishlatishi mumkin. Bu takrorlanishni kamaytiradi. Mana bizning helper — bitta framework modul + uning test target'ini yasaydigan factory:

// Tuist/ProjectDescriptionHelpers/Module.swift
import ProjectDescription

extension Project {
    // Bitta framework modul + test target yaratadigan helper.
    public static func module(
        name: String,
        dependencies: [TargetDependency] = []
    ) -> Project {
        Project(
            name: name,
            targets: [
                .target(
                    name: name,
                    destinations: .iOS,
                    product: .staticFramework,
                    bundleId: "uz.azimjondev.kutubxona.\(name.lowercased())",
                    deploymentTargets: .iOS("17.0"),
                    buildableFolders: ["Sources"],
                    dependencies: dependencies
                ),
                .target(
                    name: "\(name)Tests",
                    destinations: .iOS,
                    product: .unitTests,
                    bundleId: "uz.azimjondev.kutubxona.\(name.lowercased())tests",
                    deploymentTargets: .iOS("17.0"),
                    buildableFolders: ["Tests"],
                    dependencies: [.target(name: name)]
                ),
            ]
        )
    }
}

Endi CoreKit moduli atigi uch qatorda ta'riflanadi:

// Projects/CoreKit/Project.swift
import ProjectDescription
import ProjectDescriptionHelpers

let project = Project.module(name: "CoreKit")

📊 Real raqamlar: Bu helper bir modulda ~30 qator Project.swift yozishni 3 qatorga tushiradi. 10 modulli loyihada bu ~300 qator o'rniga ~30 qator — va eng muhimi, barcha modullar bir xil qoidaga (bundleId formati, deployment target, test target) bo'ysunadi. Bu Asana'ning ~1 400 qatorli manifest'ini boshqarib bo'ladigan qilgan asosiy usul (manba: Asana eng blog).

🧠 Esda tuting: Eski oqimda tuist install tashqi paketlarni Tuist/Dependencies/ papkasiga yuklardi. Tuist 4'da bu o'zgargan — paketlar Tuist/.build/ (SwiftPM'ning build papkasi) ichiga resolve bo'ladi. Shuning uchun .gitignore'ga Tuist/.build yoziladi, Tuist/Dependencies emas.

Project.swift — Xcode project ta'rifi

Har bir Project.swift bitta Xcode project yasaydi. Loyiha nomi name property'dan olinadi. Bizning App loyihamiz CoreKit va Logger modullariga bog'lanadi:

// Projects/App/Project.swift
import ProjectDescription

let project = Project(
    name: "App",
    targets: [
        .target(
            name: "App",
            destinations: .iOS,
            product: .app,
            bundleId: "uz.azimjondev.kutubxona",
            deploymentTargets: .iOS("17.0"),
            infoPlist: .extendingDefault(with: ["UILaunchScreen": [:]]),
            buildableFolders: ["Sources", "Resources"],
            dependencies: [
                .project(target: "CoreKit", path: "../CoreKit"),
                .project(target: "Logger", path: "../Logger"),
            ]
        ),
    ]
)

Bu yerda buildableFolders ishlatilgan — bu 2026-yilgi tavsiya etilgan yondashuv. sources: ["Sources/**"] glob'idan farqli o'laroq, buildableFolders papkani Xcode'ning "folder reference" sifatida qo'shadi: fayl qo'shganda yoki o'chirganda tuist generate'ni qayta ishga tushirish shart emas, va .pbxproj har bir fayl uchun o'zgarmaydi (manba: generated_app_with_buildable_folders fixture, Tuist repo).

Workspace.swift — bir nechta Project'ni birlashtirish

// Workspace.swift
import ProjectDescription

let workspace = Workspace(
    name: "Kutubxona",
    projects: ["Projects/App", "Projects/CoreKit", "Projects/Logger"]
)

Agar Workspace.swift bo'lmasa, tuist generate App'ning o'zidan va uning dependency'laridan avtomatik workspace yasaydi. Workspace.swift'ni faqat loyihalarni qo'lda guruhlash (yoki workspace'ga qo'shimcha fayl/scheme qo'shish) kerak bo'lganda yozasiz.


4. Nima commit qilinadi, nima generatsiya qilinadi {#commit-vs-generatsiya}

Bu — Tuist'dagi eng ko'p chalkashlik tug'diradigan nuqta. Qoidani bir marta tushunib oling: **manba (Swift manifest + kod) git'da; Xcode loyihalari esa generatsiya qilinadi va .gitignore'da.**

Chapda git'da saqlanadigan manba fayllar (Tuist.swift, Tuist/, Projects/, Workspace.swift, .gitignore), o'ngda tuist generate yasaydigan va gitignore qilinadigan fayllar (.xcworkspace, .xcodeproj, Derived/, Tuist/.build)

Chap panelda — git'da saqlanadigan yagona narsalar: Swift manifest'lar, helper'lar va sizning kodingiz. O'ng panelda — tuist generate har safar qayta yasaydigan va shuning uchun .gitignore'ga tushadigan fayllar.

tuist init loyiha bilan birga .gitignore ham yasaydi. Mana uning Tuist'ga tegishli oxirgi qismi (real, tuist init chiqargani):

### Projects ###
*.xcodeproj
*.xcworkspace

### Tuist derived files ###
graph.dot
Derived/

### Tuist managed dependencies ###
Tuist/.build

⚠️ Diqqat: .xcodeproj va .xcworkspace'ni git'ga qo'shmang. Agar qo'shsangiz, ikki muammo paydo bo'ladi: (1) har bir developer tuist generate ishga tushirganda ming qatorli .pbxproj diff'i chiqadi va har PR'da merge conflict beradi — bu aynan Tuist hal qilmoqchi bo'lgan muammo; (2) generatsiya natijasi mashinaga bog'liq (yo'llar absolyut bo'lishi mumkin), shuning uchun uni commit qilish ma'nosiz. Bitta istisno: agar siz Tuist'ni mavjud Xcode loyiha ustiga qo'shayotgan bo'lsangiz (migration), o'sha paytda .xcodeproj hali git'da bo'ladi — buni 05. Migratsiya darsida ko'ramiz.

🧠 Esda tuting: Loyihani clone qilgan yangi developer uchun ishga tushirish ketma-ketligi: tuist install (paketlarni oladi) → tuist generate (Xcode loyihani yasaydi) → Xcode'da ishlang. .xcodeproj git'da bo'lmagani — bu kamchilik emas, balki dizayn: har kim bir xil, toza loyihani oladi.


5. tuist init — noldan loyiha {#tuist-init}

Tuist 4.211.1'da tuist init endi interaktiv sehrgar (wizard) sifatida ishlaydi va to'rt turdagi integratsiyani taklif qiladi: xcode (mavjud Xcode loyihaga ulanish), generated-xcode (yangi Tuist-generated loyiha), gradle, bazel. Barcha so'rovlarni flag'lar bilan oldindan javoblab, non-interaktiv ishga tushirsangiz ham bo'ladi:

# Yangi, Tuist generatsiya qiladigan iOS loyiha; serversiz (akkaunt shart emas)
tuist init --build-system generated-xcode --platform ios --name Demo --no-server

Natija (real, qisqartirilgan):

ℹ︎ Creating generated project
   ✔︎ Generated project created [0.1s]
✔ Success 
  You are all set to explore the Tuist universe 

  Takeaways: 
   ▸ Choose the project directory with 'cd Demo'
   ▸ Generate your project with 'tuist generate'
   ▸ Visualize your project graph with 'tuist graph'

tuist init quyidagi fayllarni yasaydi (biz yuqorida qo'lda qurgan tuzilmaning aynan o'zi): Tuist.swift, Tuist/Package.swift, Project.swift, Demo/Sources/{DemoApp.swift, ContentView.swift}, Demo/Tests/DemoTests.swift, Demo/Resources/Assets.xcassets/... va .gitignore.

Muhim: yasalgan Project.swift ham **buildableFolders** ishlatadi va yasalgan Tuist.swift ham minimal — bu 2026-yilgi standart ekanini tasdiqlaydi:

// tuist init yasagan Project.swift (qisqartirilgan)
.target(
    name: "Demo",
    destinations: .iOS,
    product: .app,
    bundleId: "dev.tuist.Demo",
    infoPlist: .extendingDefault(with: ["UILaunchScreen": [...]]),
    buildableFolders: ["Demo/Sources", "Demo/Resources"],
    dependencies: []
)

💡 Pro tip: --no-server flag'i muhim. Default holatda tuist init Tuist serveriga ulanmoqchi bo'ladi (cache va insights uchun), bu esa akkaunt talab qiladi. O'rganish bosqichida yoki akkauntsiz ishlashda doim --no-server qo'shing. Akkaunt kerak bo'ladigan funksiyalarni 12-bo'limda ajratib ko'rsatamiz.

⚠️ Diqqat: tuist init loyihani joriy papka nomidan oladi (--name berilmasa). Shuning uchun uni to'g'ri nomli bo'sh papka ichida ishga tushiring, aks holda papka nomi loyiha nomiga aylanadi.


6. CLI xaritasi — buyruqlar ish bosqichi bo'yicha {#cli-xaritasi}

tuist --help 25+ buyruqni ko'rsatadi — bu dastlab qo'rqitadi. Lekin ularni ish bosqichi bo'yicha guruhlasangiz, manzara soddalashadi. Quyidagi xarita barcha asosiy buyruqlarni to'rt toifaga ajratadi:

Tuist CLI buyruqlari xaritasi: yuqorida kundalik oqim (init, install, generate, Xcode build/run, test), pastda to'rt panel — ko'rish (graph, dump), tekshirish (inspect, hash, migration), cache va tozalash (cache, clean, scaffold), server/akkaunt (auth, share, registry, account)

Yuqori qator — kundalik oqim: bu buyruqlarni har kuni ishlatasiz. Pastdagi to'rt panel — yordamchi buyruqlar: kerak bo'lganda chaqirasiz. Qulf belgisi (🔒) Tuist akkaunti talab qiladigan buyruqlarni bildiradi.

To'liq ro'yxatni ko'rish uchun:

tuist --help

Natija (real, qisqartirilgan — toifalar bo'yicha):

GET STARTED SUBCOMMANDS:
  init          Get started with Tuist in your project.
DEVELOP SUBCOMMANDS:
  hash          Utilities to debug the hashing logic ...
  build         A set of commands to manage your project builds.
  cache         Cache-related commands.
  clean         Clean all the artifacts stored locally
  dump          Outputs the manifest as a JSON
  edit          Generates a temporary project to edit the project ...
  generate      Generate a project or inspect generation runs.
  graph         Generates a graph from the workspace or project ...
  install       Installs any remote content (e.g. dependencies) ...
  migration     A set of utilities to assist in the migration ...
  run           Runs a preview or a scheme from a generated project.
  scaffold      Generates new project based on a template
  test          Tests a project
  inspect       Inspect your project to identify issues ...
  xcodebuild    tuist xcodebuild extends the xcodebuild CLI ...
SHARE SUBCOMMANDS:
  share         Generate a link to share your app.
ACCOUNT SUBCOMMANDS:
  account, project, bundle, organization, auth

🧠 Esda tuting: build buyrug'i nomi aldamchi — bu build qiluvchi buyruq emas. 4.211'da tuist build faqat build yozuvlarini (records) ko'rsatadi (list, show, xcode, gradle). Haqiqiy build'ni Xcode qiladi (tuist generate → Cmd+R) yoki xcodebuild / tuist xcodebuild build (insights bilan). Eski tuist build <scheme> olib tashlangan.


7. Kundalik oqim: install, generate, edit {#kundalik-oqim}

tuist install — paketlarni olish

Tuist/Package.swift'dagi tashqi SPM dependency'larni resolve va yuklab oladi. Bizning loyihada tashqi paket yo'q, shuning uchun u faqat plugin'larni tekshiradi:

tuist install
Resolving and fetching plugins.
Resolving and fetching dependencies.
✔ Success 
  Plugins resolved and fetched successfully. 

Qachon ishlatasiz: loyihani birinchi marta clone qilganda, yangi paket qo'shganda yoki versiyasini o'zgartirganda. tuist install --update esa paketlarni yangi versiyalarga ko'taradi.

tuist generate — Xcode loyihani yasash

Eng ko'p ishlatiladigan buyruq. Manifest'lardan .xcworkspace va .xcodeproj yasaydi va Xcode'da ochadi:

# --no-open: Xcode'ni avtomatik ochmaslik (CI va o'lchov uchun qulay)
tuist generate --no-open
Loading and constructing the graph
It might take a while if the cache is empty
Using cache binaries for the following targets: 
Generating workspace Kutubxona.xcworkspace
Generating project App
Generating project CoreKit
Generating project Logger
Total time taken: 1.611s
✔ Success 
  Project generated. 

Yasalgan fayllar: ildizda Kutubxona.xcworkspace, har bir loyiha papkasida <Nom>.xcodeproj va Derived/.

Fokuslangan generatsiya (focused generation). Katta loyihada hamma narsani ochish shart emas. Bitta (yoki bir nechta) target'ga fokuslansangiz, qolganlari (agar binary cache bor bo'lsa) manba o'rniga binary sifatida ulanadi:

# Faqat App'ga fokus
tuist generate App --no-open

# Tag bo'yicha fokus (metadata tag'lari 16-darsda)
tuist generate tag:feature --no-open

⚠️ Diqqat: Eski tuist focus buyrug'i olib tashlangan — uning o'rniga tuist generate <target> ishlatiladi. Muhim nuance: fokus faqat binary cache bo'lganda tezlashtiradi. Agar cache bo'sh bo'lsa, tuist generate App baribir CoreKit va Logger'ni manba sifatida yasaydi (bizning o'lchovda fokus va to'liq generatsiya ikkalasi ham ~0.55s bo'ldi — chunki cache bo'sh edi). Binary cache bilan real tezlanishni 07. Cache va 11. E-Commerce darslarida o'lchaymiz.

Cache profili. tuist generate'ning binary cache'dan qanday foydalanishini --cache-profile boshqaradi:

tuist generate --cache-profile only-external   # faqat tashqi paketlar (default)
tuist generate --cache-profile all-possible    # imkon qadar ko'proq target binary
tuist generate --cache-profile none            # hammasi manbadan
tuist generate --no-binary-cache               # cache'ni butunlay e'tiborsiz qoldirish

--help'dan to'g'ridan-to'g'ri: profil berilmasa, Tuist.swift'dagi sozlama ishlaydi, u ham bo'lmasa only-external.

Generatsiya tarixini ko'rish (akkaunt kerak). tuist generate list / show — bu server funksiyasi:

tuist generate list
✖ Error 
  We couldn't list generations because the full handle is missing. You can pass
  either its value or a path to a Tuist project. 

Ya'ni generate list/show faqat loyiha Tuist serveriga ulangan bo'lsa ishlaydi. Lokal tuist generate run (default subcommand) esa doim ishlaydi.

tuist edit — manifest'larni Xcode'da tahrirlash

Manifest'lar oddiy Swift kod, lekin ularni to'g'ridan-to'g'ri yasalgan loyihadan tahrirlab bo'lmaydi (bu ataylab shunday — yasalgan loyiha Tuist'ga bog'liq bo'lib qolmasligi uchun). tuist edit maxsus vaqtinchalik Xcode project ochadi, unda autocomplete, syntax highlighting va kompilyatsiya tekshiruvi ishlaydi:

tuist edit

Bu buyruq Xcode'ni ochib, jarayonni bloklaydi (siz tahrirni tugatib Xcode'ni yopguningizcha kutadi). Shuning uchun uni CI'da yoki fon rejimida ishlatmang. Oqim: tuist edit → Xcode'da Project.swift'ni o'zgartiring → Xcode'ni yoping → tuist generate.

💡 Pro tip: tuist edit --permanent doimiy edit-project'ni joriy papkada yasaydi va jarayonni bloklamaydi — buni skriptlarda qulay. tuist edit --only-current-directory esa faqat joriy papkadagi manifest'ni qo'shadi (katta loyihada edit-project tez ochilishi uchun).


8. Ko'rish buyruqlari: graph va dump {#korish-buyruqlari}

tuist graph — dependency grafini ko'rish

Loyihadagi target'lar va ularning bog'liqliklarini vizual yoki matn ko'rinishida chiqaradi. Formatlar: dot, json, png, svg (png/svg uchun tizimda dot/graphviz kerak):

# PNG o'rniga dot (matn) — graphviz'siz ham ishlaydi, git'da diff qilsa bo'ladi
tuist graph --format dot --no-open

Yasalgan graph.dot (real, bizning 3 modulli loyiha uchun):

digraph {
  App [fillcolor=deepskyblue penwidth="1.5" shape=box3d style=filled]
  CoreKit [fillcolor=coral1 shape=cylinder style=filled]
  CoreKitTests [fillcolor=limegreen shape=octagon style=filled]
  App -> CoreKit
  CoreKitTests -> CoreKit
}

Grafni o'qish: App → CoreKit (ilova domen modeliga bog'langan), CoreKitTests → CoreKit (test o'z modulini sinaydi). Shakllar turini bildiradi: box3d — ilova, cylinder — framework, octagon — test.

Foydali flag'lar (--help'dan): --skip-test-targets (test'larsiz toza graf), --skip-external-dependencies (tashqi paketlarsiz), --platform ios, va <targets> — faqat ko'rsatilgan target'lar va ularga bog'liqlarini chizadi.

💡 Pro tip: tuist graph --format dot'ni CI'da saqlab, PR'larda diff qiling — kimdir keraksiz yangi dependency qo'shsa, graph.dot diff'ida darhol ko'rinadi. Bu arxitekturani "lint" qilishning arzon usuli. (Lekin graph.dot'ni .gitignore'dan chiqarib qo'yishni unutmang — tuist init uni default ignore qiladi.)

tuist dump — manifest'ni JSON sifatida chiqarish

Manifest Swift kodini Tuist qanday "ko'rishini" JSON'da ko'rsatadi. Debug va skriptlar uchun foydali:

tuist dump project --path Projects/App
{
  "additionalFiles": [

  ],
  "name": "App",
  ...
}

<manifest> argumenti project (default), workspace, config, template, plugin yoki package bo'lishi mumkin.


9. Tekshirish: inspect dependencies va hash {#tekshirish}

tuist inspect dependencies — implicit va redundant bog'liqliklarni tutish

Bu — enforceExplicitDependencies'ning o'rnini bosgan buyruq va Tuist'ning eng kuchli "arxitektura linter"laridan biri. U ikki muammoni topadi:

  • Implicit dependency: target biror modulni import qiladi, lekin uni dependency sifatida e'lon qilmagan. Kod kompilyatsiya bo'lishi mumkin (chunki modul grafda boshqa yo'l orqali ko'rinadi), ammo bog'liqlik yashirin — ertaga grafni o'zgartirsangiz, kutilmaganda buziladi.
  • Redundant dependency: target modulni dependency sifatida e'lon qilgan, lekin uni hech qayerda import qilmaydi — keraksiz bog'liqlik.

Keling, buni ataylab buzib ko'rsatamiz. Faraz qiling, App kodida Logger'ni ishlatamiz, lekin Project.swift'da uni e'lon qilishni unutamiz; va CoreKit esa Logger'ni e'lon qiladi-yu, aslida ishlatmaydi:

// Projects/App/Sources/KutubxonaApp.swift
import CoreKit
import Logger   // ← ishlatamiz, lekin Project.swift'da e'lon qilinmagan!

func bootLog() { Logger.log("ilova ishga tushdi") }
tuist inspect dependencies

Natija (real xato — ikkala muammoni ham tutdi):

Loading and constructing the graph
It might take a while if the cache is empty
✖ Error 
  The following implicit dependencies were found: 
   - App implicitly depends on: Logger 
  The following redundant dependencies were found: 
   - CoreKit redundantly depends on: Logger 

Bitta buyruq ikkala kasallikni ham ko'rsatdi: App yashirin ravishda Logger'ga bog'liq, CoreKit esa Logger'ni behuda e'lon qilgan. Buyruq muammo topilsa 1 bilan chiqadi (exit code), shuning uchun uni CI'da to'siq (gate) sifatida ishlatsa bo'ladi.

Faqat bitta tekshiruvni ishlatish mumkin:

tuist inspect dependencies --only implicit    # faqat implicit
tuist inspect dependencies --only redundant   # faqat redundant
  The following implicit dependencies were found: 
   - App implicitly depends on: Logger 

Yechim. App endi Logger'ni ochiq e'lon qiladi, CoreKit esa keraksiz e'londan xalos bo'ladi:

// Projects/App/Project.swift — App endi Logger'ni ochiq e'lon qiladi
dependencies: [
    .project(target: "CoreKit", path: "../CoreKit"),
    .project(target: "Logger", path: "../Logger"),
]
// Projects/CoreKit/Project.swift — Logger'ni olib tashladik (ishlatilmaydi)
let project = Project.module(name: "CoreKit")

Qayta generatsiya va tekshiruv:

tuist generate --no-open && tuist inspect dependencies
We did not find any dependency issues in your project (checked: implicit, redundant).

Exit code endi 0 — graf toza.

🧠 Esda tuting: tuist inspect dependencies — bu implicit import muammosini ushlaydigan asosiy vosita. Eski enforceExplicitDependencies generatsiya paytida xato berardi; yangi yondashuv esa alohida buyruq bo'lgani uchun CI'da moslashuvchan (siz qaysi tekshiruvni qachon ishga tushirishni hal qilasiz). Implicit dependency'ning chuqur mexanikasi va ko'proq misollar — 04. Dependency'lar darsida.

⚠️ Diqqat: --output summary va --json formatlari --help'da bor, lekin 4.211.1'da muammo topilgan holatda ular standart chiqishga topilmalarni yozmaydi (faqat exit code'ni qaytaradi). Shuning uchun odam o'qiydigan natija uchun default text formatidan foydalaning; CI'da esa exit code'ga tayaning.

tuist hash — cache va selective testing hash'larini ko'rish

Tuist binary cache va selective testing uchun har bir target'ni hash qiladi (fayllar, sozlamalar, dependency'lar asosida). tuist hash bu hash'larni ko'rsatadi — debug uchun:

tuist hash cache
Loading and constructing the graph
It might take a while if the cache is empty
CoreKit - fb8a606dbf4388b778d6c60d94b04207

Faqat cache qilsa bo'ladigan target'lar (framework'lar) ko'rsatiladi — App (ilova) va test target'lari bu ro'yxatda yo'q.

Selective testing uchun hash'lar alohida:

tuist hash selective-testing
CoreKit - e07a49c190f8eae3553f13641c362a14
CoreKitTests - e1a4d0c0d13137fe137e6f3ed55973a1

💡 Pro tip: Bir fayl o'zgarsa, faqat o'sha target'ning (va unga bog'liqlarning) hash'i o'zgaradi — shuning uchun cache qolgan hammasini qayta ishlatadi. Agar "nega cache miss bo'ldi?" degan savol tug'ilsa, tuist hash cache'ni o'zgarishdan oldin va keyin solishtiring. Hashing'ning ichki mexanikasi 07. Cache darsida.


10. Build va test: xcodebuild, tuist test, run {#build-test}

Build qilish

Yuqorida aytganimizdek, Tuist 4'da tuist build endi build qilmaydi. Loyihani ikki yo'l bilan quriladi:

1. Xcode orqali (kundalik ish): tuist generate → Xcode ochiladi → Cmd+R.

**2. Terminaldan xcodebuild bilan** (CI uchun). Yasalgan workspace oddiy Xcode workspace, shuning uchun to'g'ridan-to'g'ri xcodebuild ishlaydi:

tuist generate --no-open
xcodebuild -workspace Kutubxona.xcworkspace -scheme App \
  -destination 'generic/platform=iOS Simulator' \
  -derivedDataPath .dd build

Bizning loyihada bu natija bilan tugadi (real):

** BUILD SUCCEEDED **

Ya'ni 3 modulli (App → CoreKit, App → Logger) buildableFolders'li tuzilma Xcode 27.1'da muammosiz kompilyatsiya bo'ldi.

💡 Pro tip: Insights (build analytics) kerak bo'lsa, xcodebuild o'rniga tuist xcodebuild build ... ishlating — u aynan xcodebuild'ni o'raydi, lekin build ma'lumotlarini Tuist serveriga yuboradi (akkaunt kerak). tuist xcodebuild subkomandalar: build, test, build-for-testing, test-without-building, archive.

🧠 Esda tuting: CI'da yoki o'lchovda doim o'z work-dir'ingiz ichida -derivedDataPath bering (.dd kabi). Shunda DerivedData loyihaga yopishib qolmaydi va boshqa loyihalar bilan aralashmaydi.

tuist test — selective testing bilan

tuist test test scheme'larini topib ishga tushiradi, lekin eng qimmatli xususiyati — selective testing: o'tgan safardan beri o'zgarmagan target'lar testini qayta o'tkazmaydi (lokal, akkauntsiz ishlaydi).

# Simulyatorni ro'yxatdan tanlang: xcrun simctl list devices available
tuist test CoreKit --device "iPhone 17" --os 27.0

FACTS.md'da bu mashinada (Apple M4 Pro, Xcode 27.1, Tuist 4.211.1) tasdiqlangan xatti-harakat: shunga o'xshash modulli loyihada birinchi tuist test ~26 soniyada o'tdi, ikkinchi marta esa ~1 soniya:

The scheme Core's test action has no tests to run, finishing early.

Ya'ni kod o'zgarmagani uchun Tuist test'ni o'tkazib yubordi. Selective testing'ni o'chirish uchun --no-selective-testing.

⚠️ Diqqat: Ikki nozik nuqta. (1) Selective testing faqat generated loyihalar uchun (tuist test). tuist xcodebuild test esa insights, sharding va quarantine beradi, lekin 4.211.1'da selective testing emas. (2) Simulyator nomi aniq mavjud bo'lishi kerak — FACTS.md'da --device "iPhone 17 Pro" "Could not find a suitable device" bilan yiqildi, chunki o'sha nomli simulyator yo'q edi. Doim xcrun simctl list devices available bilan tekshiring. Selective testing'ni 09. ToDo App loyihasida o'lchab ko'rsatamiz.

tuist run — scheme yoki preview'ni ishga tushirish

tuist run yasalgan loyihadan scheme'ni (yoki serverdagi preview'ni) build qilib, simulyatorda ishga tushiradi:

tuist run App --device "iPhone 17" --os 27.0

App@latest, App@feature-branch yoki App@<sha> ko'rinishidagi preview specifier'lari Tuist serveridagi preview'ni ishga tushiradi (akkaunt kerak) — buni 15. Tuist platformasi darsida ko'ramiz.


11. Cache va tozalash: cache, clean {#cache-tozalash}

tuist cache — binary cache

Modullarni oldindan kompilyatsiya qilib, .xcframework sifatida saqlaydi — keyin tuist generate ularni manba o'rniga tayyor binary bilan almashtiradi. Lokal cache akkauntsiz ishlaydi:

# Lokal cache'ni "isitish", serverga yuklamasdan
tuist cache warm --no-upload

FACTS.md'da tasdiqlangan: bu buyruq CoreKit'ni qurib ~/.cache/tuist/Binaries/<hash>/CoreKit.xcframework ga saqlaydi va xulosa chiqaradi:

Cache warm summary: 0 remote hits, 0 local hits, 1 misses

So'ng tuist generate --cache-profile all-possible "Using cache binaries for the following targets: CoreKit" deb yozadi va loyiha binary'dan foydalanadi. Cache'ning to'liq mexanikasi, profillari va o'lchangan tezlanishi — 07. Cache.

⚠️ Diqqat: tuist cache subkomandalari — warm (default) va config. Eski --external-only flag'i deprecated bo'ldi; uning o'rniga --cache-profile only-external ishlating. Remote cache (jamoa orasida ulashiladigan) Tuist akkaunti va rejasini talab qiladi; lokal cache esa bepul.

tuist clean — lokal artefaktlarni tozalash

"Tushunarsiz xato" chiqqanda yoki cache eskirganda ishlatasiz. Diqqat qiling — tuist clean aniq toifalarni oladi:

tuist clean                              # hammasini tozalaydi
tuist clean manifests projectDescriptionHelpers   # faqat manifest cache
tuist clean binaries                     # faqat binary cache

--help ko'rsatadigan to'liq toifalar ro'yxati: plugins, generatedAutomationProjects, projectDescriptionHelpers, manifests, editProjects, runs, binaries, selectiveTests, generationMetadata, dependencies. --remote esa remote cache'ni tozalaydi (akkaunt kerak).

💡 Pro tip: Butun loyihani emas, aniq muammoni tozalang. Manifest o'zgarishi "yopishib qolgan" bo'lsa — tuist clean manifests projectDescriptionHelpers. Binary cache shubhali bo'lsa — tuist clean binaries. Bu to'liq tuist clean'dan ancha tez (keyingi generatsiya hamma narsani qayta kompilyatsiya qilmaydi).

tuist scaffold — template'dan kod yasash

Loyihada aniqlangan template'lardan (masalan, yangi µFeature skeleti) kod yasaydi:

tuist scaffold list              # mavjud template'lar
tuist scaffold <template> --name MyFeature

Template'lar, plugin'lar va ProjectDescriptionHelpers'ni chuqur o'rganish — 08. Kodni qayta ishlatish.


12. Server buyruqlari (akkaunt kerak) {#server-buyruqlari}

Quyidagi buyruqlar Tuist serveriga (tuist.dev) ulanishni talab qiladi. Ularni ro'yxatlab, nima qilishini bilib qo'yish foydali, lekin ishlatish uchun akkaunt kerak. Barchasi --help orqali tekshirildi.

BuyruqNima qiladiAkkaunt
tuist auth login / logout / whoamiTuist serveriga kirish / chiqish✅ kerak
tuist shareIlovadan ulashiladigan preview havolasi yasaydi✅ kerak
tuist registry setup / loginSwift Package Registry orqali tez resolve✅ kerak
tuist account / project / organization / bundleAkkaunt, loyiha, tashkilot va bundle boshqaruvi✅ kerak
tuist runner ssh / volumeCI runner'lari bilan ishlash✅ kerak
tuist setup cache / insightsXcode compilation cache va insights daemon sozlashqisman
# Kirish (brauzer ochiladi)
tuist auth login
# Kim kirgan?
tuist auth whoami

🧠 Esda tuting: tuist registry — bu dependency'larni tezroq resolve qilish uchun (Swift Package Registry protokoli orqali). tuist share esa build qilingan ilovani boshqalarga havola orqali ko'rsatish (preview). Ikkalasi ham Tuist akkaunti talab qiladi. Narx rejalar (2026-10 holatida): Air (bepul, karta kerak emas, barcha funksiyalar bepul limit ichida), Pro (limitdan oshsa to'lov), Enterprise (self-hosting, korxona uchun). Open source loyihalar uchun bepul. To'liq platforma — 15. Tuist platformasi.

💡 Pro tip: tuist setup cache qisman mahalliy ishlaydi — u Xcode'ning compilation cache'ini (LLVM CAS) proxy orqali ulaydi. Lekin remote cache'dan to'liq foyda olish uchun server kerak. Bu — Bazel'ning remote action cache'iga o'xshash, lekin Xcode'ning o'z build tizimi ustida. Taqqoslash 14. Best practices va Bazel moduli (bazel-01-kirish...) da.

tuist migration — mavjud Xcode loyihasidan ko'chirish

Serverga bog'liq emas; mavjud .xcodeproj'dan Tuist'ga o'tishga yordam beradi:

tuist migration settings-to-xcconfig -p App.xcodeproj -x App.xcconfig
tuist migration list-targets -p App.xcodeproj
tuist migration check-empty-settings -p App.xcodeproj

To'liq migratsiya oqimi — 05. Migratsiya.


13. Environment variable'lar va kataloglar {#env-kataloglar}

TUIST_* env'lar — har bir flag'ni avtomatlashtirish

Tuist'ning deyarli har bir flag'ini environment variable orqali ham berish mumkin — bu CI'da qulay. --help chiqishi har bir flag yonida mos env nomini ko'rsatadi, masalan:

-o, --open/--no-open    ... (env: TUIST_GENERATE_OPEN) (default: --open)
--cache-profile ...     ... (env: TUIST_GENERATE_CACHE_PROFILE)

Shunday qilib CI'da flag yozish o'rniga:

export TUIST_GENERATE_OPEN=0            # --no-open bilan bir xil
export TUIST_GENERATE_CACHE_PROFILE=all-possible
tuist generate

Tuist kataloglari (XDG)

Tuist o'z fayllarini XDG standartiga ko'ra uchta katalogda saqlaydi (manba: cli/directories):

KatalogDefaultNima saqlanadi
Config~/.config/tuistServer credential'lari
Cache~/.cache/tuistBinaries, Manifests, ProjectDescriptionHelpers, Plugins, SelectiveTests, Runs
State~/.local/state/tuistSessiya loglari (sessions/<uuid>/), lock'lar

Har birini TUIST_XDG_* (ustunlik) yoki standart XDG_* bilan o'zgartirish mumkin. Bu CI'da yoki loyihani izolyatsiya qilishda juda foydali:

# CI'da vaqtinchalik kataloglar
export TUIST_XDG_CACHE_HOME=/tmp/tuist-cache
export TUIST_XDG_STATE_HOME=/tmp/tuist-state
tuist generate

💡 Pro tip: Biror buyruq g'alati xato bersa, log fayliga qarang — Tuist har sessiyada yo'lni ko'rsatadi: ~/.local/state/tuist/sessions/<uuid>/logs.txt. Biz tuist generate list xatosida aynan shu havolani ko'rdik. Bu birinchi debug qadami.

🧠 Esda tuting: ~/.cache/tuist/Binaries — binary cache shu yerda. "Cache'ni to'liq tozalamoqchiman" desangiz, tuist clean binaries yoki bu papkani o'chirish kifoya — loyihangizga tegmaydi. Bu Bazel'ning ~/Library/Caches/bazel output base'iga o'xshash g'oya: artefaktlar loyihadan tashqarida, markaziy joyda.


14. Versiyani pin qilish (release channels) {#versiya-pin}

Jamoada eng ko'p uchraydigan muammo — turli developerlarda turli Tuist versiyasi. Bir kishida tuist generate ishlaydi, boshqasida xato — chunki manifest API versiyaga bog'liq. Yechim: versiyani pin qilish.

Tuist uchta kanal orqali tarqaladi (manba: release-channels):

KanalFormatQachon chiqadiDefault?
CanaryX.Y.0-canary.NHar commit (main'ga)Yo'q
Release candidateX.Y.0-rc.NHar dushanba, ~1 hafta sinaladiYo'q
StableX.Y.ZRC toza o'tgach, dushanbada✅ Ha

Mise (tavsiya etilgan) bilan pin qilish:

mise use tuist@4.211.1         # aniq versiyaga pin (eng barqaror)
mise use tuist@4.211           # stable liniyaga pin (faqat backport fix'lar)
mise use tuist@latest          # oxirgi stable

Mise loyiha papkasiga mise.toml yozadi; jamoadoshingiz mise install bilan aynan o'sha versiyani oladi. Homebrew ham ishlaydi, lekin u faqat global versiyani boshqaradi:

brew tap tuist/tuist
brew install --formula tuist        # oxirgi stable
brew install --formula tuist@x.y.z  # aniq versiya

🧠 Esda tuting: Bu darsdagi hamma narsa Tuist 4.211.1 bilan tekshirilgan (Homebrew cask orqali o'rnatilgan). tuist@latest faqat stable'ni oladi — canary va RC'lar hech qachon latest'ga tushmaydi, ularga faqat ataylab o'tiladi. Tavsiya: stable liniyaga pin qiling (masalan tuist@4.211), yangi minor'ga esa RC'da sinab ko'rgach o'ting. Tuist 5 hali yo'q.

⚠️ Diqqat: Tuist versiyasini mise.toml'da pin qilib, uni git'ga commit qiling — bu .gitignore'dagi generatsiya fayllaridan farqli o'laroq, manba konfiguratsiyaning bir qismi. Shunda CI va har bir developer bir xil Tuist ishlatadi.


15. Real natijalar: o'lchangan vaqtlar {#real-natijalar}

Quyidagi vaqtlar bizning 3 modulli Kutubxona loyihasida (App → CoreKit, App → Logger) Apple M4 Pro (12 yadro, 24 GB), Xcode 27.1, Tuist 4.211.1 da o'lchandi. Timing o'lchovlari eksklyuziv build-slot lock ostida olingan (boshqa jarayonlar aralashmasligi uchun).

BuyruqShartVaqt
tuist generate --no-opento'liq, 3 modul, manifest cache iliq~0.55 s
tuist generate --no-opentuist clean manifests'dan keyin (cold)1.32 s
tuist generate App --no-openfokus, binary cache yo'q~0.55 s
tuist graph --format dot --no-opendot eksport0.32 s
xcodebuild ... -scheme App build3 modul, cold** BUILD SUCCEEDED **

📊 Real raqamlar: Uchta xulosa. (1) tuist generate arzon — iliq manifest cache bilan ~0.55 s. Shuning uchun undan qo'rqmang: har safar git pull'dan keyin bemalol ishga tushiring. (2) "Cold" (manifest cache tozalangan) holat ikki baravar sekinroq — ~1.32 s — chunki Tuist manifest'larni va helper'larni qaytadan kompilyatsiya qiladi. (3) Fokus bu loyihada tezlashtirmadi (~0.55 s ikkalasida) — chunki binary cache bo'sh edi, shuning uchun CoreKit va Logger baribir manbadan yasaldi. Fokus faqat binary cache bilan birga ma'no kasb etadi; buni 07. Cache va 11. E-Commerce da katta loyihada o'lchaymiz.

🚀 Motivatsiya: 0.55 soniyalik generatsiya — bu sizning kundalik tsiklingiz deyarli "bepul" degani. Asana'da 45s → 15s (change-and-rebuild) tejamkorlik aynan shu modulli tuzilma + binary cache'dan keldi. Bu darsda siz tuzilmani qurdingiz; keyingi darslarda cache'ni qo'shib, o'sha tejamkorlikni o'z loyihangizda o'lchaysiz.


Amaliy mashqlar {#mashqlar}

  1. Noldan loyiha. Bo'sh papka yarating va tuist init --build-system generated-xcode --platform ios --name Mashq --no-server bilan loyiha yasang. Yasalgan .gitignore'da Tuist/.build va Derived/ borligini tekshiring. tuist generate --no-open bilan loyihani yasang.
  2. Helper yozish. Tuist/ProjectDescriptionHelpers/Module.swift'ga darsdagi Project.module(name:) helper'ini yozing, ikkita modul (CoreKit, Logger) yarating, Workspace.swift bilan birlashtiring va tuist generate --no-open bilan yasang. Har bir modul uchun atigi 3 qator Project.swift yozilganiga ishonch hosil qiling.
  3. ⭐ Implicit dependency'ni tutish. Bir modulni boshqasida import qiling, lekin Project.swift'da dependency'ni e'lon qilmang. tuist inspect dependencies ishga tushiring va "implicitly depends on" xatosini oling. So'ng dependency'ni e'lon qilib, tekshiruv "We did not find any dependency issues" berishini tasdiqlang. Exit code'ni echo $? bilan tekshiring (xato: 1, toza: 0).
  4. Grafni o'qish. tuist graph --format dot --no-open ishga tushiring va graph.dot'ni oching. Qaysi target qaysi target'ga strelka chizadi? Test target'lari grafda qanday shaklda ko'rinadi?
  5. ⭐ Hash o'zgarishini kuzatish. tuist hash cache'ni ishga tushirib hash'ni yozib oling. Bir modulning Swift faylini o'zgartiring va qayta ishga tushiring. Qaysi hash o'zgardi, qaysi biri o'zgarmadi? Bu cache qanday "nima qayta qurilishi"ni hal qilishini ko'rsatadi.
  6. Versiyani pin qilish. Loyihada mise use tuist@4.211.1 bilan versiyani pin qiling (yoki mise.toml'ni qo'lda yozing). mise.toml'ni git'ga qo'shing, lekin .xcodeproj/.xcworkspace .gitignore'da ekanini tasdiqlang. Nega biri commit qilinadi, boshqasi yo'q — bir jumlada tushuntiring.

O'zingizni tekshiring {#checklist}

  • [ ] Tuist/ papkasi (yoki Tuist.swift) loyiha ildizini belgilashini va buyruqlar uni yuqoriga qarab qidirishini tushunaman.
  • [ ] .xcodeproj, .xcworkspace, Derived/, Tuist/.build — bularning hammasi .gitignore'da bo'lishi kerakligini bilaman.
  • [ ] Yangi loyiha oqimini bilaman: tuist install → tuist generate → Xcode.
  • [ ] tuist build endi build qilmasligini (faqat yozuvlarni ko'rsatishini) bilaman.
  • [ ] tuist inspect dependencies implicit va redundant bog'liqliklarni topishini va CI gate sifatida ishlashini bilaman.
  • [ ] tuist focus → tuist generate <target>, tuist fetch → tuist install o'zgarishlarini bilaman.
  • [ ] Tashqi SPM paketlar Tuist/.build'ga resolve bo'lishini (eski Tuist/Dependencies emas) bilaman.
  • [ ] Tuist versiyasini mise.toml'da pin qilib, uni git'ga commit qilish kerakligini bilaman.

Xulosa {#xulosa}

  • Tuist'da papka tuzilmasi — loyihaning o'zi. .xcodeproj har safar Swift manifest'lardan generatsiya qilinadi, shuning uchun tuzilmani tushunish birinchi qadam.
  • **Tuist/ papkasi** ildizni belgilaydi; ichida Package.swift (tashqi deps) va ProjectDescriptionHelpers/ (shared kod) bo'ladi. Helper factory manifest'larni o'nlab marta qisqartiradi.
  • Git'da faqat manba: manifest'lar + kod + .gitignore + mise.toml. Generatsiya fayllari (*.xcodeproj, *.xcworkspace, Derived/, Tuist/.build) — .gitignore'da. Bu merge conflict'larni yo'qotadi.
  • CLI to'rt toifa: kundalik oqim (init, install, generate, test), ko'rish (graph, dump), tekshirish (inspect, hash, migration), server (auth, share, registry, account — akkaunt kerak).
  • **tuist inspect dependencies** eski enforceExplicitDependencies'ning o'rnini bosdi — bitta buyruq implicit va redundant bog'liqliklarni tutadi va exit code 1 bilan CI'ni to'xtatadi.
  • O'zgargan buyruqlarni yodda tuting: focus → generate <target>, fetch → install, build <scheme> → xcodebuild, --external-only → --cache-profile only-external, Config.swift → Tuist.swift.
  • O'lchangan: tuist generate ~0.55 s (iliq), 1.32 s (cold) — arzon, bemalol ishlating.
  • Keyingi dars: 04. Dependency'lar — target, project, SPM paketlari, XCFramework, macro'lar, Registry va implicit import tekshiruvi

Manbalar {#manbalar}

  1. Tuist — Directory structure — tavsiya etilgan papka tuzilmasi, Tuist/ ildizi
  2. Tuist — Editing — tuist edit oqimi va .tuistignore
  3. Tuist — CLI directories — TUIST_XDG_* env'lar, config/cache/state kataloglari
  4. Tuist — Release channels — canary / RC / stable, versiyani pin qilish
  5. Tuist — Install Tuist — mise va Homebrew bilan o'rnatish
  6. Tuist — CLI reference — barcha buyruqlar ro'yxati
  7. Asana — Scaling a mature iOS codebase with Tuist — ~1 400 qatorli manifest, Tuist vs Bazel tanlovi, 45s → 15s
  8. Tuist GitHub — releases — versiyalar tarixi (4.211.x)

Markdown manba

iOS Lessons