Azimjon Abdurasulov

Bazel 1: Bazel nima va nega kerak — build tizimlari evolyutsiyasi, super-kuchlar va motivatsiya

📦 Bazel iOS — Mukammal Qo‘llanma & Amaliyot

Bazel 1: Bazel nima va nega kerak — build tizimlari evolyutsiyasi, super-kuchlar va motivatsiya

Holat: 2026-yil oktabr. Bu dars build tizimi nima ekanini, Xcode qayerda og'riy boshlashini va Bazel qanday g'oyaga asoslanishini noldan tushuntiradi. Kod misollari Bazel 9.3.0 (Bazelisk 1.29.0), rules_swift 4.2.1, apple_support 2.10.1 va Xcode 27.1 bilan Apple M4 Pro'da (12 core, 24 GB) tekshirilgan.

Bu darsdan keyin siz: build tizimi iOS ilovangiz uchun aniq nima qilishini, Xcode'ning qaysi joyi katta loyihada og'riqqa aylanishini va Bazel bu og'riqni qaysi mexanizm bilan yo'qotishini tushunib, 20 darslik kursda sizni nima kutayotganini bilib olasiz.

  • Build tizimining ishini aniq konveyer sifatida ko'rasiz: Swift kompilyatsiyasi → linking → .app yig'ish → imzolash → .ipa.
  • Xcode'ning modelini (target, build phase, DerivedData) va uning katta jamoada qayerda sinishini — project.pbxproj merge konfliktlari, yashirin bog'liqliklar, "clean qilsam tuzaladi" sindromi, jamoa/CI uchun umumiy cache yo'qligi — nomma-nom tushunasiz.
  • Bazel'ning markaziy g'oyasini bilasiz: build — bu e'lon qilingan kirishlardan chiqishlar hosil qiluvchi sof funksiya; undan kelib chiqadigan yetti super-kuchni mexanizmi bilan ko'rasiz.
  • Olti qatorlik BUILD fayl va uning haqiqiy bazel build/bazel test natijasini (shu mashinada o'lchangan raqamlar bilan) ko'rasiz.
  • Spotify, Airbnb kabi kompaniyalar Bazel'dan iOS uchun nima deb foydalanganini va Asana kabi jamoalar nega boshqa yo'l tanlaganini — faqat manbasi bor raqamlar bilan — bilib olasiz.
  • Bazel sizga, hatto bugun Xcode'da ishlasangiz ham, nega foydali ekanini va 20 darslik yo'l xaritasini ko'rasiz.

Mundarija

  1. Build tizimi nima va iOS ilovasida nimani bajaradi
  2. Xcode qanday quradi va u qayerda og'riy boshlaydi
  3. Bazel'ning asosiy g'oyasi: build — bu sof funksiya
  4. Bazel'ning yetti super-kuchi
  5. Birinchi ta'm: olti qatorlik BUILD fayl va haqiqiy natija
  6. Real dunyo: kim Bazel'dan foydalanadi va nima deydi
  7. Halol tomoni: narxi, cheklovlari va kim boshqa yo'l tanlagan
  8. Kim Bazel'ni o'rganishi kerak (Xcode'da ishlasangiz ham)
  9. Kurs xaritasi: 20 dars, noldan ekspertgacha
  10. Amaliy mashqlar
  11. O'zingizni tekshiring
  12. Xulosa
  13. Manbalar

1. Build tizimi nima va iOS ilovasida nimani bajaradi {#build-tizimi}

Siz Xcode'da ⌘R bosganingizda, aslida bir dasturchi uchun ko'rinmaydigan konveyer ishga tushadi. MyApp.swift faylidan simulyatordagi ishlayotgan ilovagacha bo'lgan yo'lda bir nechta bosqich bor, va ularning har biri alohida vosita (tool) tomonidan bajariladi. Keling, bu konveyerni nomma-nom ko'rib chiqaylik, chunki Bazel ham, Xcode ham xuddi shu ishni bajaradi — faqat turlicha boshqaradi.

Oddiy bir iOS ilovasi quriladigan bosqichlar:

  1. Kompilyatsiya (compile). swiftc kompilyatori har bir .swift faylni mashina kodiga (.o object fayl) aylantiradi. Agar loyihada Objective-C bo'lsa, clang ularni alohida kompilyatsiya qiladi. Bu bosqichda tip tekshiruvi (type checking) ham bo'ladi — xatolaringizning aksariyati shu yerda chiqadi.
  2. Linking. Linker (Xcode 27'gacha ld64, endi yangi linker — Xcode 27 release notes'da ld64 olib tashlangan) barcha object fayllarni va kutubxonalarni bitta bajariluvchi binar faylga birlashtiradi. "Undefined symbol" xatosini ko'rgan bo'lsangiz — u aynan shu bosqichdan.
  3. Resurslarni qayta ishlash. Asset catalog (.xcassets) actool bilan Assets.car ga, storyboard/xib ibtool bilan, .strings/.xcstrings lokalizatsiya fayllari o'z formatiga aylantiriladi.
  4. **Bundle yig'ish (.app).** Yuqoridagilarning hammasi — binar, resurslar, Info.plist — ma'lum tuzilishdagi MyApp.app papkasiga joylashtiriladi.
  5. Kod imzolash (codesign). .app raqamli sertifikat va provisioning profil bilan imzolanadi, aks holda qurilma uni ishga tushirmaydi (simulyator imzoga unchalik qattiq talabchil emas, qurilma esa qattiq).
  6. **Paketlash (.ipa).** App Store yoki TestFlight uchun .app qo'shimcha metama'lumotlar bilan .ipa arxiviga joylanadi.

Shu yerda muhim bir narsani tushunib oling: bu bosqichlarning hech biri Xcode yoki Bazelga xos emas. Ikkala vosita ham swiftc, ld, actool, codesign kabi Apple'ning bir xil asboblarini chaqiradi. Farq — bu asboblarni kim, qachon va necha marta chaqirishni boshqarishida. Aynan shu "boshqaruv" katta loyihada hamma narsani hal qiladi: build necha daqiqa davom etadi, natija takrorlanadiganmi, ikki dasturchi bir xil kirishdan bir xil chiqishni oladimi.

Bazel bu bosqichlarni "action" deb ataydi va ularning aniq nomlarini ko'rasiz: rules_apple kutubxonasi iOS ilovasini qurganda BundleApp, linking, SwiftStdlibCopy, imzolash kabi action'larni yaratadi (buni 8-darsda o'z ko'zingiz bilan ko'rasiz). Hozircha asosiysi — bir fikr:

🧠 Esda tuting: Build tizimi — bu "kompilyator" emas. Bu kompilyator, linker, resurs asboblari va imzolovchini to'g'ri tartibda, kerakli paytda va imkon qadar parallel chaqiradigan dirijyor. Dirijyor qanchalik aqlli bo'lsa, build shunchalik tez va ishonchli bo'ladi.

Shu nuqtadan boshlab savol o'zgaradi. "Qaysi vosita Swift'ni tezroq kompilyatsiya qiladi?" — noto'g'ri savol, chunki ikkalasi ham bir xil swiftc ni chaqiradi. To'g'ri savol: "Qaysi vosita keraksiz ishni qilmaslikni yaxshiroq biladi?" Chunki eng tez kompilyatsiya — umuman qilinmagan kompilyatsiya. Mana shu yerda build tizimlari bir-biridan keskin farq qiladi.


2. Xcode qanday quradi va u qayerda og'riy boshlaydi {#xcode-ogriq}

Xcode'ni yomonlash uchun emas — u ajoyib IDE va kichik-o'rta loyihalar uchun deyarli har doim to'g'ri tanlov — balki uning modelini aniq tushunish uchun ko'rib chiqamiz. Chunki Bazel aynan Xcode modelining chegaralariga javoban paydo bo'lgan.

Xcode modeli: target, build phase, scheme, DerivedData

Xcode loyihasi target'lardan iborat. Har bir target (masalan, ilova, framework, test to'plami) ichida build phase'lar ketma-ketligi bor: "Compile Sources", "Link Binary With Libraries", "Copy Bundle Resources", "Run Script" va hokazo. Siz ⌘B bosganingizda Xcode bu fazalarni tartib bilan bajaradi. Scheme qaysi target'larni va qaysi konfiguratsiyada (Debug/Release) qurishni belgilaydi. Qurilgan hamma narsa — oraliq fayllar, indekslar, binarlar — ~/Library/Developer/Xcode/DerivedData ichiga tushadi.

Bu model tanish va qulay. Lekin uni "task-based" (vazifaga asoslangan) build tizimi deb atashadi: har bir build phase, ayniqsa "Run Script", ixtiyoriy kod/skript bo'lishi mumkin. Bazel'ning rasmiy hujjatlari aynan shu modelni va uning cheklovlarini batafsil tahlil qilgan ("Task-Based Build Systems" sahifasi). Asosiy muammo bitta jumlada:

Task-based tizimlar muhandisga juda ko'p kuch, tizimning o'ziga juda kam kuch beradi. Tizim skript nima qilishini bilmagani uchun, u qachon ishni qayta bajarish kerakligini aniq ayta olmaydi — natijada ko'pincha "ehtiyot shart" hammasini qaytadan quradi.

Kichik loyihada bu sezilmaydi. Katta loyihada esa bu to'rtta aniq og'riqqa aylanadi.

Og'riq 1: project.pbxproj va merge konfliktlar

Xcode loyihasining butun tuzilishi — qaysi fayl qaysi target'da, build sozlamalari, fayllar tartibi — bitta project.pbxproj faylida saqlanadi. Bu fayl mashinaga mo'ljallangan, uzun va deyarli o'qib bo'lmaydigan matn. Ikki dasturchi bir vaqtda ikki xil branch'da fayl qo'shsa yoki sozlama o'zgartirsa, git merge paytida shu faylda konflikt chiqadi — va uni qo'lda hal qilish iztirob.

Bu muammo shunchalik haqiqiyki, uni hal qilish uchun alohida vositalar paydo bo'lgan. Tuist (biz bu kursning Tuist modulida o'rganamiz) Xcode 16'ning "synchronized groups" imkoniyatiga asoslangan buildableFolders ni qo'shdi; uning rasmiy e'loniga ko'ra, bunda "Xcode tashqarisida (agent, CLI, CI tomonidan) qo'shilgan fayllar endi qayta generatsiya talab qilmaydi va pbxproj merge konfliktlari kamayadi". Ya'ni butun bir imkoniyat shunchaki bitta faylning konflikt muammosini yumshatish uchun yaratilgan.

Og'riq 2: yashirin bog'liqliklar (implicit dependencies)

Xcode odatiy holda "Find Implicit Dependencies" rejimida ishlaydi: u target'lar orasidagi bog'liqlikni o'zi taxmin qiladi. Qulay — lekin bu bog'liqliklar hech qayerda to'liq, aniq yozilmagan. Natijada tizim "A target'i B'ga bog'liqmi?" degan savolga ba'zan noto'g'ri javob beradi. Bazel hujjatlari task-based tizimlarning aynan shu kasalligini sanaydi: "A vazifasi B ishlab chiqaradigan faylga bog'liq. B egasi boshqalar unga tayanishini bilmay, chiqish joyini o'zgartiradi. Buni kimdir A'ni ishga tushirib, u sinmaguncha sezib bo'lmaydi."

Og'riq 3: "clean qilsam tuzaladi" sindromi

Siz buni ko'rgansiz: build tushunarsiz xato bilan sinadi, siz ⇧⌘K (Clean Build Folder) bosasiz, DerivedData o'chadi, va keyingi build ishlaydi. Nega? Chunki inkremental build noto'g'ri holatga tushib qolgan edi — tizim nimadir o'zgarganini sezmay, eski natijani qayta ishlatdi yoki aksincha.

Bazel hujjatlari buni task-based tizimlarning bevosita oqibati deb ataydi: "Muhandislar har build'dan oldin clean qilish odatiga o'rganib qolishadi — bu esa inkremental build'ning butun ma'nosini yo'qqa chiqaradi." Agar siz har safar ishonch uchun clean qilsangiz, demak sizda inkremental build yo'q — har safar noldan quryapsiz.

⚠️ Diqqat: "Clean qilsam tuzaladi" — bu sizning aybingiz emas va "noto'g'ri" kod belgisi ham emas. Bu task-based build tizimining strukturaviy kamchiligi: tizim ishni qayta bajarish kerakmi-yo'qmi degan savolga har doim ham to'g'ri javob bera olmaydi, shuning uchun ba'zan xato qiladi.

Og'riq 4: jamoa/CI uchun umumiy cache yo'q (yaqingacha)

Eng kattasi — bu. Sizning DerivedData'ingiz faqat sizning mashinangizda. Hamkasbingiz xuddi shu commit'ni qurganda, u noldan quradi. CI serveri xuddi shu commit'ni yana noldan quradi. Ya'ni bir xil kirishdan bir xil chiqish o'nlab marta qayta hisoblanadi — har bir mashinada alohida.

Apple bu bo'shliqni faqat yaqinda, Xcode 26 bilan tan oldi: unga ixtiyoriy (odatiy holda o'chiq) kompilyatsiya cache'i qo'shildi — COMPILATION_CACHE_ENABLE_CACHING=YES. U content-addressed storage (CAS) va action cache modeliga asoslanadi — bu aynan Bazel 10 yildan beri ishlatadigan model. Ushbu mashinada (Xcode 27.1) buni tekshirdik: SWIFT_ENABLE_EXPLICIT_MODULES = YES va COMPILATION_CACHE_CAS_PATH sozlamalari bor, lekin COMPILATION_CACHE_ENABLE_CACHING hali ham odatiy holda yoqilmagan. Ya'ni Apple Bazel modelini ko'chira boshladi — bu Bazel g'oyasining qanchalik to'g'ri ekanining eng kuchli dalili.

Shuni ham halollik bilan aytaylik: Xcode 26 cache'i hamma narsani qamramaydi. Bir manbaga (Bitrise FAQ) ko'ra, u Ld (linking), CompileStoryboard, CompileXIB, PhaseScriptExecution, CompileAssetCatalogVariant kabi action'larni cache qilmaydi — faqat kompilyatsiyani. Bazel esa linking va bundling'ni ham cache qiladi.

🚀 Motivatsiya: Katta jamoada eng ko'p vaqt yeydigan narsa — bir xil ishni qayta-qayta qilish. Agar sizning CI'ingiz har PR'da butun ilovani noldan qursa va 70 daqiqa ketsa (Monzo jamoasi aynan shu holatga tushgan), muammo kompilyatorning sekinligida emas — tizim keraksiz ishni qilayotganida. Bazel'ning butun falsafasi shunga qurilgan: eng tez ish — umuman qilinmagan ish.

Endi savol tug'iladi: tizim qanday qilib "bu ishni qayta qilish shart emas" ekanini ishonch bilan biladi? Javob — Bazel'ning asosiy g'oyasida.


3. Bazel'ning asosiy g'oyasi: build — bu sof funksiya {#asosiy-goya}

Bazel boshqa bir sinfga tegishli: u artifact-based (artefaktga asoslangan) build tizimi. Farqni bitta jumlada aytsak:

Task-based tizimda siz tizimga qanday qurishni aytasiz (qadamma-qadam skript). Artifact-based tizimda siz faqat nimani qurishni aytasiz (deklarativ ro'yxat), qanday qurish — tizimning ishi.

Buni oshxona bilan solishtiring. Task-based build — bu oshpazga qadamma-qadam buyruq berish: "gazni yoq, tovani qo'y, yog' sol, 3 daqiqa kutt...". Agar bir qadamni o'tkazib yuborsangiz yoki tartibni buzsangiz — taom buziladi, va oshpaz nega buzilganini bilmaydi. Artifact-based build — bu menyu berish: "menga osh kerak, mana masalliqlar". Oshxona qanday pishirishni o'zi biladi, qaysi ishni parallel qilishni o'zi hal qiladi, va agar kecha aynan shu oshni pishirgan bo'lsa — qaytadan pishirmay, tayyorini beradi.

Build — matematik funksiya

Bazel hujjatlari bu g'oyani funksional dasturlash bilan tushuntiradi. An'anaviy imperativ til (Java, C, Python) — bu ketma-ket bajariladigan buyruqlar ro'yxati, xuddi task-based build kabi. Funksional til (Haskell, ML) esa — matematik tenglamalar to'plami: siz natijani tasvirlaysiz, uni qachon va qanday hisoblashni kompilyator hal qiladi.

Build tizimi aynan shunga mos keladi, chunki butun build — bu bitta matematik funksiya:

build(manba_fayllar, asboblar, sozlamalar) → binarlar

Agar bir funksiyaga bir xil kirish bersangiz, u doim bir xil chiqish qaytaradi. Demak, agar kirish o'zgarmagan bo'lsa — chiqishni qayta hisoblash shart emas, eskisini ishlatish mumkin. Bazel'ning tezligi va to'g'riligi — hammasi shu bitta g'oyadan kelib chiqadi.

BUILD fayl — deklaratsiya, skript emas

Bazel'da BUILD fayllar imperativ buyruqlar emas, deklarativ manifest: nimani qurish, uning bog'liqliklari va cheklangan sozlamalar. Mana Bazel hujjatlaridagi klassik misol (Java, hozircha g'oyani ko'rsatish uchun):

java_binary(
    name = "MyBinary",
    srcs = ["MyBinary.java"],
    deps = [":mylib"],
)

java_library(
    name = "mylib",
    srcs = ["MyLibrary.java", "MyHelper.java"],
    deps = ["//java/com/example/common"],
)

Bu yerda java_binary va java_library — target'lar, har biri bitta artefaktga mos keladi. Har bir target'da name (nomi), srcs (manba fayllar) va deps (bog'liqliklar) bor. Siz bazel build :MyBinary deganingizda, Bazel:

  1. Barcha BUILD fayllarni o'qib, target'lar orasidagi bog'liqlik grafini quradi.
  2. MyBinary ning transitiv (zanjirli) bog'liqliklarini aniqlaydi.
  3. Har bir bog'liqlikni to'g'ri tartibda quradi — bog'liqligi yo'q target'lardan boshlab, imkon qadar parallel.
  4. Oxirida MyBinary ni yig'adi.

Ikkinchi marta bazel build :MyBinary deganingizda — hech narsa o'zgarmagan bo'lsa — Bazel bir soniyadan kamroq vaqtda "target is up to date" deb chiqadi. Chunki u biladi: har bir target faqat kompilyatorni ishga tushirish natijasi, kompilyator chiqishi esa faqat kirishlariga bog'liq. Kirishlar o'zgarmagan ekan — chiqishni qayta ishlatsa bo'ladi. Va bu tahlil har bir darajada ishlaydi: agar MyBinary.java o'zgarsa, Bazel MyBinary ni qayta quradi, lekin mylib ni qayta ishlatadi.

Content hashing va action key

Bazel "kirish o'zgardimi?" degan savolga fayl sanasiga (timestamp) qarab emas, mazmun hash'iga (content hash) qarab javob beradi. Har bir action uchun u "action key" hisoblaydi — bu action'ning buyruq qatori, muhit o'zgaruvchilari, barcha kirish fayllarining digest'lari va platformasidan tashkil topadi. Agar action key o'zgarmagan bo'lsa — chiqish cache'dan olinadi. Bu mexanizmni 10-darsda chuqur ochamiz; hozircha asosiysi — Bazel ishni ishonch bilan o'tkazib yuboradi, "ehtimol o'zgargandir" degan taxmin bilan emas.

Hermetiklik va sandboxing

Bazel har bir action'ni sandbox ichida bajaradi: action faqat o'zi e'lon qilgan kirishlarni ko'radi, boshqa hech narsani. Agar action e'lon qilmagan faylga murojaat qilmoqchi bo'lsa — u topilmaydi va action sinadi. Bu qattiq ko'rinadi, lekin aynan shu narsa buildni hermetik (yopiq, takrorlanadigan) qiladi: sizning mashinangizdagi tasodifiy fayl buildga ta'sir qila olmaydi, shuning uchun bir xil manba doim bir xil binar beradi — bit-bitigacha.

Tashqi bog'liqliklar (kutubxonalar) ham nazoratda: ularning har biri MODULE.bazel.lock faylida kriptografik hash bilan yozib qo'yiladi. Bog'liqlik serveri buzilsa yoki kimdir faylni almashtirsa — hash mos kelmaydi va build to'xtaydi. Bu ta'minot zanjiri (supply chain) xavfsizligi uchun katta yutuq.

{Fast, Correct} — Choose two

Bazel'ning rasmiy shiori — {Fast, Correct} — Choose two (README'da shunday yozilgan). An'anaviy maqol "tez, arzon, sifatli — ikkitasini tanla" deydi. Bazel esa ataylab aytadi: tezlik va to'g'rilik — ikkalasini ham olasiz. Chunki ikkalasi bir ildizdan o'sadi: Bazel kirishlarni aniq bilgani uchun keraksiz ishni o'tkazib yuboradi (tezlik), va aniq bilgani uchun kerakli ishni hech qachon o'tkazib yubormaydi (to'g'rilik). Hujjatlardagi iborasi bilan: "Cheksiz make clean chaqiruvlariga va manba kodida allaqachon tuzatilgan, lekin hech qachon qayta qurilmagan 'arvoh' xatolarni quvlashga xayr ayting."

Xcode'ning task-based modeli va Bazel'ning action grafi + cache modelini yonma-yon solishtiruvchi diagramma

Yuqoridagi diagramma ikki modelni yonma-yon qo'yadi. Chapda Xcode: build phase'lar ketma-ketligi, har biri "qora quti", va holat chalkashganda yagona yechim — Clean. O'ngda Bazel: e'lon qilingan kirishlardan action grafi quriladi, har bir action'ning natijasi content hash bilan cache'lanadi, va o'zgarmagani cache'dan olinadi — mashinangizda ham, jamoada ham, CI'da ham.

Ikki modelni bir qarashda jadval ham ko'rsatadi. Har bir satr bu darsda ko'rgan mexanizmdan kelib chiqadi:

O'lchovXcode (task-based)Bazel (artifact-based)
Asosiy modelbuild phase ketma-ketligiaction grafi (deklarativ)
Inkremental to'g'rilikkafolatlanmagan ("clean fixes it")content hash bilan kafolatlangan
Jamoa/CI umumiy cacheyo'q (Xcode 26'dan ixtiyoriy)bor (disk + remote), standart
Parallellikcheklanganaction grafi bo'yicha to'liq
Ko'p til / monorepoyo'q (faqat Apple)bor (iOS/Android/backend/tooling)
Build grafini so'rovlashyo'qbazel query
Test natijasi cache'iyo'qbor ((cached) PASSED)
IDE integratsiyasinative (birinchi klass)rules_xcodeproj orqali
Konfiguratsiya fayliproject.pbxproj (merge og'riq)BUILD (kichik, o'qiladigan)
O'rganish egri chizig'ipastbalandroq (Starlark)

Diqqat: bu jadval "Bazel har doim yaxshiroq" degani emas. Oxirgi ikki satr (IDE integratsiyasi va o'rganish egri chizig'i) Xcode foydasiga — va kichik loyihada aynan ular hal qiluvchi bo'lishi mumkin. 7- va 8-bo'limlarda buni halol tortib ko'ramiz.

Qisqa tarix: Blaze'dan Bazel 9'gacha

Bazel osmondan tushmagan — u Google ichidagi 15 yillik tajribadan o'sgan:

  • ~2006, Google ichida — "Blaze". Google o'z serverlarini katta, generatsiya qilingan Makefile'lar bilan qurar edi; bu "sekin va ishonchsiz buildlarga olib keldi" (Bazel FAQ). Yechim sifatida Blaze yaratildi. "Blaze" hali ham Bazel kodida ichki nom — hujjatlar: "Blaze'ni Bazel deb atang".
  • 2015 — Bazel ochiq kodga chiqdi. Google Blaze'ning ochiq versiyasini Bazel nomi bilan chiqardi; 2015-yil sentyabrda u beta bosqichiga yetdi ("Bazel Builder Blasts Beyond Beta Barrier", blog.bazel.build). Bazel Blaze bilan ko'p kodni bo'lishadi.
  • 2019-yil 10-oktabr — Bazel 1.0. Birinchi umumiy (GA) relizi; semantik versiyalashga o'tdi va LTS (uzoq muddatli qo'llab-quvvatlash) siyosatini kiritdi.
  • Bzlmod davri. Tashqi bog'liqliklarni boshqarishning eski WORKSPACE usuli o'rniga MODULE.bazel (Bzlmod) keldi. Bazel 8 WORKSPACE ni odatiy holda o'chirdi, **Bazel 9 (2026-yil 20-yanvar) esa WORKSPACE kodini butunlay olib tashladi** — endi faqat MODULE.bazel. Eski WORKSPACE'ga asoslangan har qanday qo'llanma eskirgan.
  • Bugun. Barqaror reliz — Bazel 9.3.0 (2026-yil 7-oktabr), 8.x LTS liniyasida 8.8.1, va 10.0.0rc1 prereliz. Biz butun kursda .bazelversion ni aniq 9.3.0 ga qotiramiz (takrorlanadigan build uchun).

🧠 Esda tuting: Bazel "yangi, sinovdan o'tmagan" vosita emas. U Google ichida kuniga millionlab build qiladigan tizimning ochiq versiyasi, 2015-yildan ommaviy, 2019-yildan 1.0. Siz o'rganayotgan model — eng katta kod bazalarida pishib yetilgan.


4. Bazel'ning yetti super-kuchi {#super-kuchlar}

Endi g'oyadan amaliyotga o'tamiz. Quyidagi yetti xususiyat — Bazel'ning "super-kuch"lari. Har birini qisqa mexanizm va imkon bo'lsa shu mashinada o'lchangan haqiqiy raqam bilan ko'rsatamiz. Raqamlar 5-bo'limdagi kichik misol loyihadan olingan (Apple M4 Pro, Xcode 27.1, Bazel 9.3.0).

1. To'g'ri inkremental build. Bazel faqat o'zgargan narsani va unga bog'liq narsalarni qayta quradi — na ko'p, na kam. Misol loyihada App/main.swift da bitta qatorni o'zgartirib qayta qurganimda, Bazel butun 295 ta action o'rniga atigi 4 ta process ishlatdi va build 0.916 soniyada tugadi: faqat ilova qayta kompilyatsiya qilindi, kutubxona o'zgarmagani uchun qayta ishlatildi. Bu "clean qilsam tuzaladi" dunyosidan butunlay boshqa dunyo — bu yerda inkremental buildga ishonish mumkin.

2. Hermetiklik va sandboxing. Har bir action izolyatsiya qilingan quti ichida, faqat e'lon qilingan kirishlar bilan ishlaydi. Natijada bir xil manba bir xil chiqish beradi — sizning noutbukingizda, hamkasbingizning mashinasida va CI'da bir xil, bit-bitigacha. "Menda ishlaydi, CI'da ishlamaydi" muammosi tizim darajasida hal qilinadi.

3. Jamoa va CI uchun umumiy cache. Build natijalari disk cache yoki remote (tarmoq) cache'ida saqlanadi va butun jamoa bilan bo'lishiladi. Misol loyihada: birinchi, sovuq build (hamma narsa noldan) 60.4 soniya davom etdi; lekin disk cache to'lgach, output base tozalangan "yangi jamoadosh / ikkinchi checkout" holati atigi 1.8–2.5 soniya oldi (177 ta disk cache hit). Remote cache'da bu "yangi jamoadosh" boshqa mashinada bo'lsa ham xuddi shunday tez bo'ladi — bu jamoaviy tejamkorlikning asosi.

4. Parallel va remote execution. Bazel action grafini tahlil qilib, bir-biriga bog'liq bo'lmagan action'larni bir vaqtda ishga tushiradi — barcha CPU yadrolaringizdan foydalanib. Bundan ham nariga borib, action'larni remote execution orqali boshqa mashinalarga tarqatish mumkin (iOS uchun bu macOS "worker"larni talab qiladi — buni 18-darsda ochamiz). Google ichida minglab action bir vaqtda bajariladi.

5. Bitta vosita — barcha tillar. Bazel faqat iOS uchun emas: bir xil tool va bir xil BUILD fayllar bilan iOS, Android, backend (Go, Java, C++), va ichki asboblaringizni quradi. Monorepo (yagona ulkan repozitoriy)da siz client/server protokolini bitta commit'da o'zgartirib, yangilangan mobil ilova yangilangan server bilan ishlashini bir buildda tekshira olasiz. Xcode buni hech qachon qila olmaydi.

**6. bazel query — build grafini so'rovlash.** Bazel butun bog'liqlik grafini biladi, va siz undan so'rashingiz mumkin: "//App nimalarga bog'liq?", "bu faylni o'zgartirsam, qaysi test'lar ta'sirlanadi?". Aynan shu so'rov CI'da "faqat o'zgargan narsaga tegishli test'larni ishga tushir" degan super-kuchni beradi (11-darsda qo'llaymiz). Xcode'da bunday so'rov umuman yo'q.

7. Cache'langan test natijalari. Bazel test natijasini ham cache qiladi: agar test va uning kirishlari o'zgarmagan bo'lsa, test qayta ishga tushmaydi — natija cache'dan olinadi. Misol loyihada ilovani o'zgartirib, keyin kutubxona test'ini ishga tushirganimda: test (cached) PASSED in 2.0s deb chiqdi va 0 ta test aslida bajarildi, chunki test'ning kirishlari (kutubxona + test kodi) o'zgarmagan edi. Katta loyihada bu minglab keraksiz test ishga tushishini o'chiradi.

Bazel'ning yettita super-kuchini qisqa mexanizmi bilan ko'rsatadigan kartochkalar diagrammasi

Diagrammadagi yettita kartochka — yuqoridagi yetti super-kuch, har birida bir qatorli mexanizm. Diqqat qiling: ularning hammasi bitta ildizdan — "build sof funksiya" g'oyasidan — o'sadi. To'g'ri inkremental build, cache va test cache — bularning barchasi "kirish o'zgarmasa, chiqishni qayta ishlatish mumkin" qoidasining turli ko'rinishlari.

💡 Pro tip: Super-kuchlarni bitta mantra bilan eslang: "Bir ishni ikki marta qilma." Bazel'ning hamma yutug'i shu — bir xil kirishdan bir xil chiqish bir marta hisoblanadi, keyin hamma (siz, jamoa, CI) uni qayta ishlatadi. Qolgan hamma narsa — texnik tafsilot.


5. Birinchi ta'm: olti qatorlik BUILD fayl va haqiqiy natija {#birinchi-tam}

Nazariya yetarli — keling, Bazel'ni ishda ko'raylik. O'rnatish va har bir faylni batafsil tushuntirish keyingi, 2-darsning ishi; bu yerda shunchaki ta'm beramiz: bir nechta kichik fayl, bitta buyruq, haqiqiy natija. Hammasi shu mashinada haqiqatan qurilgan va ishga tushirilgan.

Kichik bir "Salom" loyihasi: bitta kutubxona (swift_library), uni ishlatadigan macOS buyruq qatori dasturi (swift_binary) va bitta test (swift_test). Fayllar tuzilishi:

salom-taste/
├── .bazelversion          # qaysi Bazel versiyasi
├── MODULE.bazel           # tashqi bog'liqliklar
├── App/
│   ├── BUILD.bazel        # dasturning "retsepti"
│   └── main.swift
└── Salom/
    ├── BUILD.bazel        # kutubxona + test retsepti
    ├── Sources/Salom.swift
    └── Tests/SalomTests.swift

.bazelversion — bitta qator, Bazel versiyasini qotiradi:

9.3.0

MODULE.bazel — qaysi rule'lardan foydalanishni e'lon qiladi (apple_support macOS/Xcode toolchain'ini beradi, rules_swift Swift kompilyatsiyasini):

# MODULE.bazel
module(name = "salom_taste", version = "1.0.0")

bazel_dep(name = "apple_support", version = "2.10.1")
bazel_dep(name = "rules_swift", version = "4.2.1")

Kutubxona kodi — bitta sof funksiya:

// Salom/Sources/Salom.swift
public func salomXabari(_ ism: String) -> String {
    "Salom, \(ism)! Bu Bazel bilan qurilgan."
}

Mana o'sha olti qatorlik BUILD fayl — dasturning butun "retsepti". Diqqat qiling: bu yerda qanday kompilyatsiya qilish haqida bir og'iz ham yo'q, faqat nima (nomi, manbalar, bog'liqlik):

# App/BUILD.bazel
load("@rules_swift//swift:swift.bzl", "swift_binary")

swift_binary(
    name = "salom",
    srcs = ["main.swift"],
    deps = ["//Salom"],
)

Dastur kutubxonadan foydalanadi:

// App/main.swift
import Salom

print(salomXabari("dunyo"))

Kutubxona va test bitta BUILD faylda:

# Salom/BUILD.bazel
load("@rules_swift//swift:swift.bzl", "swift_library", "swift_test")

swift_library(
    name = "Salom",
    srcs = ["Sources/Salom.swift"],
    module_name = "Salom",
    visibility = ["//visibility:public"],
)

swift_test(
    name = "SalomTests",
    srcs = ["Tests/SalomTests.swift"],
    deps = [":Salom"],
)

Test — oddiy XCTest (Bazel uni macOS'da simulyatorsiz, to'g'ridan-to'g'ri ishga tushiradi):

// Salom/Tests/SalomTests.swift
import XCTest
@testable import Salom

final class SalomTests: XCTestCase {
    func testXabarIsmniOzIchigaOladi() {
        XCTAssertEqual(salomXabari("Azimjon"),
                       "Salom, Azimjon! Bu Bazel bilan qurilgan.")
    }
}

Endi dasturni ishga tushiramiz. bazel run kerak bo'lsa avval quradi, keyin ishga tushiradi:

bazel run //App:salom

Natija:

INFO: Found 1 target...
Target //App:salom up-to-date:
  bazel-bin/App/salom
INFO: Running command line: bazel-bin/App/salom
Salom, dunyo! Bu Bazel bilan qurilgan.

Test'ni ishga tushiramiz:

bazel test //Salom:SalomTests
INFO: Found 1 test target...
//Salom:SalomTests                                    PASSED in 2.0s

Executed 1 out of 1 test: 1 test passes.

Endi super-kuchlarni o'z ko'zingiz bilan ko'ring. Hech narsa o'zgartirmay test'ni qayta ishga tushiring:

//Salom:SalomTests                           (cached) PASSED in 2.0s

Executed 0 out of 1 test: 1 test passes.

(cached) PASSED va Executed 0 out of 1 test — test umuman ishga tushmadi, natija cache'dan keldi, chunki kirishlar o'zgarmadi. Endi App/main.swift da bitta qatorni o'zgartirib ("dunyo" → "Bazel") qayta quramiz — Bazel atigi kerakli qismni qayta kompilyatsiya qiladi:

INFO: Elapsed time: 0.916s, Critical Path: 0.82s
INFO: 4 processes: 2 internal, 1 darwin-sandbox, 1 worker.

295 ta action o'rniga 4 ta process — faqat ilova qayta qurildi, kutubxona va test'lar tegilmadi.

O'lchangan raqamlar

Mana shu kichik loyihada aniq o'lchangan vaqtlar. Bu raqamlar faqat shu misol va shu mashina uchun — lekin ular nisbatni aniq ko'rsatadi:

HolatVaqtIzoh
Birinchi (sovuq) build: output base tozalangan, disk cache o'chirilgan60.4 sko'p vaqt rules_swift'ning worker vositasini (abseil kutubxonasidan) kompilyatsiya qilishga ketadi — mashinaga bir martalik narx
Toza output base, lekin disk cache to'la ("yangi jamoadosh" / 2-checkout)1.8–2.5 s177 ta disk cache hit — ish allaqachon bir marta hisoblangan
O'zgarishsiz qayta build (no-op)0.125 s"up-to-date", hech narsa qilinmaydi
App/main.swift da 1 qator o'zgartirib qayta build0.916 satigi 4 ta process, faqat ilova qayta kompilyatsiya
Test birinchi marta~16.8 skompilyatsiya + ishga tushirish
Test o'zgarishsiz qayta**(cached) PASSED**0 ta test bajariladi, natija cache'dan

📊 Real raqamlar: Apple M4 Pro (12 core, 24 GB), Xcode 27.1 (27A9275), Bazel 9.3.0, rules_swift 4.2.1, apple_support 2.10.1 bilan shu misol loyihada o'lchangan (2026-10-13). Taqqoslash uchun: xuddi shu mashinada o'lchangan ikki modulli SwiftUI iOS ilovasida sovuq build 83.7 s, disk cache bilan qayta build 1.9 s, bir Swift faylni o'zgartirib inkremental build 3.0 s chiqqan.

Diqqat qiling: 60.4 soniya "sovuq" raqam sizni cho'chitmasin. U mashinada bir marta to'lanadi (worker vositasi kompilyatsiyasi), keyin disk cache orqali hamma build va hamma jamoadosh undan foydalanadi. Kundalik hayot — bu 0.1–1 soniyalik inkremental buildlar va cache'langan test'lar. Aynan shu narsa Xcode'ning "clean qilib, 2 daqiqa kutish" dunyosidan farq qiladi.

Build grafini ko'rish: bazel query

Xuddi shu kichik loyihada Bazel'ning 6-super-kuchini — build grafini so'rovlashni — ham sinab ko'rsak bo'ladi. "salom dasturi nimalarga bog'liq?" degan savolga Bazel aniq javob beradi:

bazel query 'deps(//App:salom)' --output label
//App:main.swift
//App:salom
//Salom:Salom
//Salom:Sources/Salom.swift

Teskari savol yanada qiziq: "Salom kutubxonasini o'zgartirsam, nima ta'sirlanadi?" — rdeps (reverse deps) buni aytadi:

bazel query 'rdeps(//..., //Salom:Salom)'
//App:salom
//Salom:Salom
//Salom:SalomTests

Ya'ni Salom'ni o'zgartirsak, salom dasturi ham, SalomTests test'i ham qayta qurilishi/ishga tushishi kerak — boshqa hech nima. Katta loyihada aynan shu so'rov CI'ga "faqat shu o'zgarishdan ta'sirlangan test'larni ishga tushir" deyish imkonini beradi (11-darsda qo'llaymiz). Xcode'da bunday savolga javob beradigan vosita yo'q — bog'liqliklarni o'z xotirangizda saqlashga majbursiz.


6. Real dunyo: kim Bazel'dan foydalanadi va nima deydi {#real-dunyo}

Bu kursning qattiq qoidasi — faqat manbasi bor raqamlar. Shuning uchun quyida har bir da'vo ortida havola bor, va qaysi raqam vendor (sotuvchi) tomonidan e'lon qilinganini alohida belgilaymiz.

Kimlar Bazel'ni iOS uchun ishlatadi

rules_xcodeproj (Bazel loyihasidan Xcode loyihasi generatsiya qiluvchi vosita, 9-darsda o'rganamiz) o'z README'sida foydalanuvchilarini sanaydi. Bu ro'yxatni biz disk'dagi manba nusxada o'z ko'zimiz bilan tekshirdik: Cash App, Lyft, Reddit, Robinhood, Slack, Snap, Spotify, Square, Tinder, Gojek, Mercari, Faire Wholesale, Envoy Mobile. Bular — iOS ilovalarini Bazel bilan quradigan, nomi tanish kompaniyalar. Bu ro'yxatning o'zi bir dalil: Bazel katta iOS jamoalarida sinovdan o'tgan.

Spotify: p75 kutish vaqti to'rt baravar qisqardi

Spotify iOS ilovasini Buck'dan keyin Bazel'ga o'tkazdi. InfoQ'ning xabariga ko'ra (2023-yil 21-oktabr, Sergio De Simone; asl post Spotify muhandisi Patrick Balestra'niki): PR'ni merge qilishdan oldingi p75 (75-protsentil) kutish vaqti 2022-yil mayda ~80 daqiqa edi, Bazel'dan keyin ~20 daqiqaga tushdi — "to'rt baravar". Eng og'ir CI konfiguratsiyasi (3 millionga yaqin qator kod va 800+ test target bilan) Xcode'da 45+ daqiqa olardi, Bazel'da 10 daqiqadan kamga tushdi. Spotify 3 yil tajriba qilgach, 2020-yilda Bazel'ni rasmiy build tizimi qilib tanladi va yutuqni "Bazel'ning samarali remote cache'i" bilan bog'ladi.

Airbnb: generatsiya −60%, Xcode ochilishi −70%

Airbnb iOS build tizimini Buck'dan Bazel'ga ko'chirdi. InfoQ'ga ko'ra (2024-yil 21-fevral, asl post muhandislar Qing Yang va Andy Bartholomew'niki): maqsad "backend va frontend bo'ylab yagona, samarali build tajribasi" edi. Buck bilan taqqoslaganda loyiha generatsiyasi 60% tezlashdi, Xcode ochilish vaqti 70%'dan ko'proq qisqardi. Inkremental buildlar ham yaxshilandi, lekin asl post aniq foiz keltirmaydi (shuning uchun biz ham keltirmaymiz).

🏢 Real-world: Rappi ham Bazel'ni (Buck o'rniga) tanladi, lekin bir muammoga duch keldi: CocoaPods pod'lari o'rtasida bo'lishilgan private header'lar tufayli sandboxing'ni o'chirishga majbur bo'ldi. Bu — Bazel'ning hermetiklik talabining real narxi: agar kodingiz e'lon qilinmagan fayllarga tayansa, Bazel buni sezadi va to'xtaydi; ba'zan sandboxing'ni o'chirish tezroq yo'l bo'ladi, lekin shunda hermetiklikning bir qismini yo'qotasiz.

Raqamlarga qanday qarash kerak

Bu raqamlar ilhomlantiradi, lekin ularni to'g'ri o'qish muhim:

  • Har bir raqam — bir kompaniyaning o'z o'tmishi bilan taqqoslovi. "Bazel Xcode'dan X% tez" degan universal haqiqat yo'q. Spotify o'z Xcode/Buck sozlamasi bilan, Airbnb o'z Buck sozlamasi bilan taqqoslagan.
  • Uch tomonlama (Bazel vs Tuist vs Xcode) neytral benchmark umuman mavjud emas — biz qidirdik, topilmadi. Mavjud raqamlarning aksariyati yo kompaniyaning o'z o'tmishi bilan taqqoslovi, yo vendor (masalan Tuist yoki BuildBuddy) tomonidan o'tkazilgan.
  • "Katta iOS jamoasi" degani — yuzlab modul va o'nlab muhandis. Keyingi bo'limda ko'ramizki, kichik jamoalar ko'pincha ataylab boshqa yo'l tanlaydi, va bu to'g'ri qaror.

⚠️ Diqqat: Gojek va Bumble haqida internetda yuradigan ba'zi raqamlarni (masalan "Gojek CI 30 daqiqadan 10 daqiqaga") biz bu darsga kiritmadik, chunki birlamchi manbalarni (Medium maqolalari) ocha olmadik — ular 403 qaytardi. Manbasini tekshira olmagan raqamni keltirmaslik — bu kursning qoidasi.


7. Halol tomoni: narxi, cheklovlari va kim boshqa yo'l tanlagan {#halol-tomoni}

Bu kurs sizga Bazel'ni sotmaydi — o'rgatadi. Shuning uchun uning narxini ham xuddi super-kuchlari kabi ochiq aytamiz. Bazel — bepul vaqt-mashinasi emas; u aniq qiymatga ega.

Narxi va cheklovlari

O'rganish egri chizig'i va Starlark. Bazel'ning BUILD fayllari Starlark tilida yoziladi (Python'ning qism to'plami, 4-darsda o'rganamiz). Bu yangi til va yangi tafakkur modeli. Asana muhandislari o'z tajribalarini (bu Tuist haqida, lekin Bazel bilan solishtirib) shunday yozgan: ular Bazel'ni rad etishdi, chunki u "juda og'ir asboblar to'plami bo'lib, yangi mental modellar talab qiladi".

Xcode bilan integratsiya — alohida vosita talab qiladi. Bazel BUILD fayllar bilan ishlaydi, Xcode esa .xcodeproj bilan. Ularni bog'lash uchun rules_xcodeproj kerak. Va bu integratsiyaning ochiq kamchiliklari bor:

  • SwiftUI Preview hali ham to'liq ishlamaydi. rules_xcodeproj README'si "Xcode Previews" ni imkoniyat sifatida sanaydi, lekin 4.1.0 generatori hali ham ENABLE_DEBUG_DYLIB = NO o'rnatadi (muammo #3042), va bu Xcode 16+ preview'lariga to'sqinlik qiladi. Native preview qo'llab-quvvatlash so'rovi (muammo #3201) 2025-yil iyundan beri ochiq; buni hal qiladigan PR (#3325) ham hali ochiq, hech narsa reliz qilinmagan. Ya'ni Bazel generatsiya qilgan loyihada SwiftUI Preview'ga hozircha tayanib bo'lmaydi.
  • Xcode'ning Archive amali rules_xcodeproj loyihalarida qo'llab-quvvatlanmaydi — App Store uchun .ipa ni to'g'ridan-to'g'ri bazel build bilan quriladi (BuildBuddy'ning migratsiya qo'llanmasi va rules_xcodeproj FAQ). Tanish "Product → Archive → Organizer" oqimi o'zgaradi.

Migratsiya — oson emas. Spotify Bazel bilan 3 yil tajriba qilgach, 2020-yilda uni rasmiy qilib oldi. Qo'shimcha narx: rule'larning major (katta) versiyalari tez-tez sinadi — rules_xcodeproj 2.0.0 (2024-yil aprel) → 3.0.0 (2025-yil iyun) → 4.0.0 (2026-yil mart), har biri buzuvchi o'zgarishlar bilan. Bu — doimiy saqlash (maintenance) narxi.

rules_ios eskirmoqda. Bir vaqtlar mashhur bo'lgan muqobil rules_ios ruleset'idan Square (uning asosiy homiysi) 2025-yil noyabrda faol hissa qo'shishni to'xtatdi va undan ko'chmoqda (muhokama #952); u o'rniga rules_apple + rules_swift ni tavsiya qiladi. Shuning uchun bu kurs faqat rules_apple + rules_swift ni o'rgatadi — biz zamonaviy va qo'llab-quvvatlanadigan yo'ldamiz.

Katta miqyosda — build muhandisi kerak. iOS uchun remote execution macOS "worker" pool'larini talab qiladi (Apple toolchain'lari Linux'da ishlamaydi) — bu qimmat va murakkab (MacStadium/Orka hujjatlari). Shuning uchun amaliy yutuq ko'pincha remote cacheda (execution emas). Umuman, katta Bazel sozlamasi odatda hech bo'lmaganda bitta maxsus build/platforma muhandisini talab qiladi.

Mana shu cheklovlarning qisqa jadvali:

KamchilikNimani anglatadiQachon muhim
Starlark + yangi modelBUILD fayllar va mental modelni o'rganish kerakboshida, butun jamoa uchun
rules_xcodeproj kerakXcode integratsiyasi to'g'ridan-to'g'ri emaskundalik Xcode ishi
SwiftUI Preview gappreview'ga tayanib bo'lmaydi (#3201 ochiq)UI'ni preview bilan ishlaganda
Archive qo'llab-quvvatlanmaydi.ipa ni bazel build bilan quriladiApp Store'ga chiqarishda
Major versiyalar sinadi2.0→3.0→4.0 ~2 yildahar yangilanishda
Remote execution qimmatmacOS worker pool kerakjuda katta jamoada

Kim ataylab boshqa yo'l tanlagan

Eng foydali tajriba — Bazel'ni rad etgan jamoalarniki, chunki ular nega kerak emasligini aniq tushuntirib bergan.

Asana → Tuist. Asana (2022-yil boshida ~10 muhandis, ~300 ming qator Swift, deyarli hammasi bitta target'da) Bazel o'rniga Tuist'ni tanladi (post 2023-yil 21-fevral). Rad etish sabablari (asl matndan): Bazel'da "developer experience bilan jiddiy muammolar" bor edi, u "yangi mental modellar talab qiladigan juda og'ir asboblar to'plami", va "breakpoint'lar bilan ish oqimini buzadigan muammolar" bor edi. Tuist bilan natijalar: funksiyani o'zgartirib simulyatorda qayta qurish odatda ~45 soniyadan (Intel'da ~90 s edi) median 15 soniyaga (Scalyr log) tushdi; Inbox modulida bir qator o'zgartirish 30–50 soniyadan 4 soniyaga tushdi. Narxi: git checkout 5–15 soniya sekinlashdi, modullarga bo'lish ~3 oy oldi, va muhandislarning "faqat ozchiligi" Tuist ichki ishidan qulay his qildi.

Back Market → Tuist. Back Market ham (iOS-only, ikki ilovali sozlama) Bazel o'rniga Tuist'ni tanladi — Bazel ularning hajmi uchun ortiqcha edi. (Aniq raqamlarini keltirmaymiz, chunki asl postni ocha olmadik.)

🧠 Esda tuting: Bazel'ni rad etish — mag'lubiyat emas, muhandislik qarori. Agar sizda 10 ta muhandis va bitta ilova bo'lsa, Asana kabi Tuist (yoki shunchaki yaxshi sozlangan Xcode) to'g'riroq tanlov bo'lishi mumkin. Keyingi bo'limda qachon qaysi birini tanlashni aniq ko'ramiz.


8. Kim Bazel'ni o'rganishi kerak (Xcode'da ishlasangiz ham) {#kimga}

Qachon Bazel kerak EMAS

Halollik bilan: ko'pchilik iOS loyihalari uchun Bazel ortiqcha. Quyidagi holatlarda uni tanlamang:

  • Bitta iOS ilova yoki kichik jamoa. Asana ~10 muhandis / 300k qator bilan Tuist'ni tanladi — va bu to'g'ri qaror edi.
  • Maxsus build/platforma muhandisi yo'q. Bazel rule'lari tez-tez sinadi; ularni kuzatib boradigan odam kerak.
  • SwiftUI Preview, Archive/Organizer yoki Xcode boshqaradigan imzolashga qattiq tayanasiz. Bular Bazel + rules_xcodeproj'da buzilgan yoki cheklangan.
  • CI vaqtingiz allaqachon maqbul. Agar PR 10 daqiqada o'tsa, migratsiya narxi o'zini oqlamaydi.
  • Backend/Android bilan monorepo kerak emas. Bazel'ning eng katta kuchi — ko'p tilli monorepo; bu sizga kerak bo'lmasa, kuchning yarmi ishlamay qoladi.

Qachon Bazel yutadi

  • Katta, ko'p ilovali yoki ko'p tilli monorepo (iOS + Android + backend).
  • Yuzlab muhandis o'rtasida bo'lishiladigan remote cache — bu yerda cache hit stavkasi hamma narsani hal qiladi (Google ichida 99%'dan yuqori).
  • Hermetik, takrorlanadigan CI — "menda ishlaydi" muammosini tizim darajasida o'ldirish.
  • Har bir action'ni cache qilish — jumladan linking va bundling, ularni Xcode 26 cache'i hali to'liq qamramaydi (bir manbaga ko'ra, Ld cache qilinmaydi).

Nega bu Xcode'da ishlasangiz ham foydali

Faraz qilaylik, sizning kompaniyangiz hech qachon Bazel'ga o'tmaydi. Baribir bu kursni o'rganish foydali, chunki g'oyalar ko'chadi:

  • Tuist (bu saytdagi parallel modul, tuist-01-kirish-va-ornatish) binary cache, target hashing va selective testing'ni ishlatadi — bularning hammasi aynan "build sof funksiya" g'oyasidan. Bazel'ni tushunsangiz, Tuist'ni ancha osonroq o'zlashtirasiz.
  • Xcode 26+ kompilyatsiya cache'i Bazel bilan bir xil modelda ishlaydi: action cache + content-addressed storage (CAS). Apple Bazel g'oyasini ko'chirdi; siz asl g'oyani tushunsangiz, Apple'ning sozlamalarini ham tushunasiz.
  • Gradle (Android) ham artifact-based tomon harakat qilmoqda; Buck2 (Meta) to'g'ridan-to'g'ri Bazel modeliga qurilgan. Build grafi, action key, cache — bu tushunchalar barcha zamonaviy build tizimlarida bir xil.

Karyera nuqtai nazaridan: yuqorida ko'rgan ro'yxat (Spotify, Lyft, Reddit, Robinhood, Slack, Snap, Square, Tinder, Cash App, Gojek, Mercari...) — bu aynan platforma/infratuzilma muhandislarini yollaydigan kompaniyalar. Build tizimlarini tushunish — mobil infratuzilma (mobile infrastructure / developer experience) rollari uchun kam uchraydigan va qadrli ko'nikma. Biz bu yerda aniq ish e'lonlari sonini keltirmaymiz (manbasiz raqam keltirmaslik qoidasi), lekin yo'nalish aniq: bu bilim sizni oddiy ilova dasturchisidan ajratib turadi.


9. Kurs xaritasi: 20 dars, noldan ekspertgacha {#kurs-xaritasi}

Bu kurs sizni Bazel haqida hech narsa bilmaydigan holatdan — o'z rule'laringizni yozadigan, remote cache sozlaydigan va real loyihalarni Bazel'ga ko'chiradigan darajagacha olib boradi. 20 dars besh bosqichga bo'lingan.

Bazel kursining 20 darsini besh bosqichga bo'lib ko'rsatuvchi yo'l xaritasi diagrammasi: asoslar, iOS, tezlik, loyihalar, ekspert

1-bosqich — Asoslar (1–4-darslar). Bu bosqichdan keyin siz minimal workspace qurib, asosiy tushunchalarni (target, label, rule, build graph) bilib, Starlark'da oddiy macro yoza olasiz.

  • 1-dars — Bazel nima va nega kerak (shu dars).
  • 2-dars — O'rnatish va birinchi build: Bazelisk, .bazelversion, MODULE.bazel, .bazelrc va "Salom, Bazel!".
  • 3-dars — Asosiy tushunchalar: workspace, package, target, label, rule, visibility va build graph.
  • 4-dars — Starlark tili: BUILD va .bzl fayllar, macro'lar, select() va konfiguratsiya.

2-bosqich — iOS'ni Bazel bilan qurish (5–9-darslar). Bu bosqichdan keyin siz SwiftUI ilovani qurib, test yozib, tashqi SPM paketlarni ulab, uni Xcode'da ocha olasiz.

  • 5-dars — Birinchi iOS ilova: rules_apple, rules_swift, SwiftUI, Info.plist va simulyator.
  • 6-dars — Testlar: ios_unit_test, XCTest va Swift Testing, test cache, coverage va UI testlar.
  • 7-dars — Tashqi dependency'lar: Bzlmod, BCR, SPM paketlari va xcframework'lar.
  • 8-dars — Haqiqiy ilova anatomiyasi: resurslar, lokalizatsiya, widget extension, framework, entitlements va signing.
  • 9-dars — Xcode bilan ishlash: rules_xcodeproj, indexing, debugging, SwiftUI Preview va VS Code.

3-bosqich — Jamoa miqyosidagi tezlik (10–11-darslar). Bu bosqichdan keyin siz action key'ni tushunib, remote cache sozlab, CI'da faqat o'zgargan narsani qura olasiz.

  • 10-dars — Cache: action key, disk cache, remote cache, Build without the Bytes va cache-miss detektivligi.
  • 11-dars — CI/CD: GitHub Actions, remote cache, faqat o'zgarganini build/test qilish va release.

4-bosqich — Besh loyiha (12–16-darslar). Bu bosqichdan keyin siz CLI'dan to 12 modulli "SuperApp" va monorepo'gacha real loyihalarni Bazel bilan qurgan bo'lasiz.

  • 12-dars — Loyiha #1: "Valyuta" CLI — Swift kutubxona + macOS buyruq qatori + testlar va birinchi o'lchovlar.
  • 13-dars — Loyiha #2: "Vazifalar" iOS ilova — 4 modul, SwiftUI, JSON persistence va testlar.
  • 14-dars — Loyiha #3: "Ob-havo" ilova — Networking, SPM dependency, resurslar va mock testlar.
  • 15-dars — Loyiha #4: 12 modulli "SuperApp" va jamoaviy remote cache.
  • 16-dars — Loyiha #5: Monorepo — iOS ilova + macOS CLI + umumiy kutubxona, visibility, query va "faqat ta'sirlanganini test qil".

5-bosqich — Ekspert va ustalik (17–20-darslar). Bu bosqichdan keyin siz o'z rule'laringizni yozib, performance'ni profil qilib, real loyihani Bazel'ga ko'chira olasiz va qachon qaysi vositani tanlashni bilasiz.

  • 17-dars — O'z rule'laringiz: genrule, rule(), provider'lar, depset'lar, aspect'lar va toolchain'lar.
  • 18-dars — Performance tuning va Remote Execution: profil, critical path, worker'lar, xotira va RBE.
  • 19-dars — Xcode/SPM loyihasidan Bazel'ga migratsiya: strategiya, bosqichma-bosqich o'tish va real hikoyalar.
  • 20-dars — Best practices, troubleshooting va karyera: Bazel vs Tuist vs SPM, qachon nimani tanlash.

🚀 Motivatsiya: Hoziroq hamma narsani tushunmasangiz — bu normal. Bu dars xarita, keyingi darslar — yo'l. 2-darsda birinchi bazel build ni o'z mashinangizda ko'rasiz, 5-darsda simulyatorda SwiftUI ilovangiz ishga tushadi, 15-darsda esa jamoaviy cache build vaqtini sezilarli qisqartirganini o'z o'lchovlaringiz bilan ko'rasiz. Har bir dars — bitta aniq ko'nikma.


Amaliy mashqlar {#mashqlar}

Bu dars motivatsiya va tushunchalar haqida, shuning uchun mashqlar ham ko'proq kuzatish va o'lchashga qaratilgan. To'liq o'rnatish va qo'l bilan build 2-darsda.

  1. O'z og'riqlaringizni aniqlang. Oxirgi marta qachon Xcode'da "Clean Build Folder" qilgansiz va nega? project.pbxproj tufayli git merge konflikti bo'lganmi? Uch-to'rt jumlada yozing — bu og'riqlarning qaysi biri Bazel hal qiladigan turdan ekanini 2-bo'limga qarab aniqlang.
  2. O'z CI baseline'ingizni o'lchang. Joriy loyihangizda oxirgi 5 ta PR'da CI necha daqiqa ketgan (o'rtacha va eng yomoni)? Lokal clean build qancha vaqt oladi? Bu raqamlarni yozib qo'ying — bu "o'lchab ko'r, keyin qaror qil" (measure-before-adopt) usuli, va kurs oxirida Bazel qanchalik yordam berishini aynan shu raqamlar bilan solishtirasiz.
  3. Task-based va artifact-based farqini o'z so'zlaringiz bilan. Nega task-based tizim (masalan, Xcode'ning "Run Script" fazalari) ba'zan keraksiz ishni qayta qiladi? Nega artifact-based tizim (Bazel) buni "ishonch bilan" o'tkazib yubora oladi? 3-bo'limga qaramasdan yozib ko'ring, keyin tekshiring.
  4. ⭐ Real raqamni toping. 6-bo'limdagi adopter ro'yxatidan (Spotify, Lyft, Reddit, Slack, Snap, Cash App...) bitta kompaniyani tanlang, ularning muhandislik blogi yoki konferentsiya chiqishidan Bazel/build haqidagi materialni toping va bitta aniq raqamni manba havolasi bilan yozing. (Maslahat: "<kompaniya> engineering bazel ios" deb qidiring.)
  5. ⭐ O'z qaroringizni chiqaring. 8-bo'limdagi "qachon kerak / qachon kerak emas" mezonlariga joriy loyihangiz uchun javob bering: jamoa hajmi? ilovalar soni? maxsus build muhandisi bormi? SwiftUI Preview'ga tayanasizmi? CI vaqti maqbulmi? Shu asosda — Bazel sizga kerakmi? Qaroringizni bir xatboshida asoslang.
  6. Kurs xaritasini belgilang. 9-bo'limdagi 20 darsdan qaysi uchtasi sizning joriy ehtiyojingizga eng yaqinini belgilang (masalan, cache, CI/CD yoki migratsiya) — kursni o'qib borar ekansiz, shu darslarga alohida e'tibor bering.

O'zingizni tekshiring {#checklist}

  • [ ] Build tizimi iOS ilovasida bajaradigan oltita bosqichni (compile → link → resurs → bundle → imzolash → .ipa) sanab bera olaman.
  • [ ] Task-based va artifact-based build tizimlari orasidagi farqni ("qanday"ni aytish vs "nima"ni aytish) tushuntira olaman.
  • [ ] "Clean qilsam tuzaladi" sindromi nega task-based tizimning strukturaviy kamchiligi ekanini bilaman.
  • [ ] "Build — bu sof funksiya" degani nimani anglatishini va bundan tezlik hamda to'g'rilik qanday kelib chiqishini aytib bera olaman.
  • [ ] Bazel'ning content hashing / action key timestamp'ga emas, mazmunga qarashini bilaman.
  • [ ] Bazel'ning yettita super-kuchidan kamida beshtasini mexanizmi bilan ayta olaman.
  • [ ] Bazel'ni qachon tanlamaslik kerakligini (kichik jamoa, Preview'ga tayanish, maxsus muhandis yo'q) kamida uchta sabab bilan tushuntira olaman.
  • [ ] {Fast, Correct} — Choose two shiorining ma'nosini va Blaze → Bazel tarixining asosiy sanalarini bilaman.

Xulosa {#xulosa}

  • Build tizimi — dirijyor, kompilyator emas. Xcode ham, Bazel ham bir xil Apple asboblarini (swiftc, ld, codesign) chaqiradi; farq — ularni qanchalik aqlli boshqarishda.
  • Xcode task-based model katta loyihada to'rt joyda og'riydi: project.pbxproj merge konfliktlari, yashirin bog'liqliklar, "clean qilsam tuzaladi" sindromi va jamoa/CI uchun umumiy cache yo'qligi.
  • Bazel artifact-based: siz faqat nimani qurishni e'lon qilasiz, qandayni tizim hal qiladi. Build — bu sof funksiya; kirish o'zgarmasa, chiqish qayta ishlatiladi.
  • Yetti super-kuch bitta g'oyadan o'sadi: to'g'ri inkremental build, hermetiklik, jamoaviy cache, parallel/remote execution, ko'p tilli monorepo, bazel query va cache'langan test natijalari. Shu mashinada: 1 qatorlik o'zgarish → 0.9 soniyalik inkremental build, o'zgarmagan test → (cached) PASSED.
  • Real tajriba, manba bilan: Spotify p75 kutish vaqtini 4 baravar (80→20 daqiqa) qisqartirdi, Airbnb loyiha generatsiyasini 60% tezlashtirdi. Lekin uch tomonlama neytral benchmark yo'q — har bir raqam kompaniyaning o'z o'tmishi bilan taqqoslovi.
  • Narxi ham bor: Starlark o'rganish, rules_xcodeproj, SwiftUI Preview gap, Archive qo'llab-quvvatlanmasligi, tez sinadigan major versiyalar. Asana (~10 muhandis, bitta ilova) ataylab Tuist'ni tanladi — va bu to'g'ri qaror edi.
  • Bazel bilim sifatida qimmatli, hatto Xcode'da qolsangiz ham: g'oyalar Tuist'ga, Xcode 26 kompilyatsiya cache'iga, Gradle va Buck2'ga ko'chadi.
  • Keyingi dars: Bazel 2: O'rnatish va birinchi build — Bazelisk, .bazelversion, MODULE.bazel, .bazelrc va "Salom, Bazel!"

Manbalar {#manbalar}

  1. Bazel — Task-Based Build Systems — task-based tizimlar va ularning kamchiliklari.
  2. Bazel — Artifact-Based Build Systems — Bazel modeli, "build sof funksiya" g'oyasi, sandboxing, tashqi bog'liqlik hashing.
  3. Bazel — Why Bazel? — fast / correct / extensible; Google'da 99%'dan yuqori cache hit.
  4. Bazel — FAQ — Blaze ichki nomi, Google'ning Makefile tarixi, nega Bazel yaratilgan.
  5. Bazel GitHub README — {Fast, Correct} — Choose two shiori.
  6. Bazel 9.0 blog (2026-01-20) — WORKSPACE olib tashlandi, Bzlmod doimiy yoqilgan.
  7. Bazel 1.0 (2019-10-10) va Bazel Reaches 1.0 Milestone (2019-10-17) — birinchi GA reliz, semantik versiyalash, LTS.
  8. Bazel reaches Beta (2015-09, Google Open Source blog) — Bazel'ning ochiq kodga chiqishi.
  9. Bazel GitHub Releases — 9.3.0 (2026-10-07), 8.8.1, 10.0.0rc1 sanalari.
  10. rules_swift docs (rules.md) — swift_binary, swift_library, swift_test atributlari.
  11. rules_apple — iOS rule'lari; BundleApp/linking/signing action'lari.
  12. rules_xcodeproj README — foydalanuvchilar ro'yxati (Cash App, Lyft, Reddit, Slack, Snap, Spotify, Square, Tinder, Gojek, Mercari...).
  13. rules_xcodeproj — SwiftUI Preview support (issue #3201) — ochiq preview muammosi.
  14. rules_ios — maintainers winding down (discussion #952) — Square faol hissani to'xtatmoqda, rules_apple + rules_swift tavsiyasi.
  15. How Spotify Transitioned to Bazel (InfoQ, 2023-10-21) — p75 kutish vaqti 80→20 daqiqa, eng og'ir CI 45+→<10 daqiqa.
  16. Airbnb migrates iOS build from Buck to Bazel (InfoQ, 2024-02-21) — generatsiya −60%, Xcode ochilishi −70%.
  17. Asana — Scaling a mature iOS codebase with Tuist (2023-02-21) — nega Bazel rad etilgan, Tuist raqamlari.
  18. BuildBuddy — How to migrate an iOS app to Bazel (2024-03-13) — migratsiya bosqichlari, Archive qo'llab-quvvatlanmasligi.
  19. Tuist — Xcode compilation cache (2025-10-22) — Xcode 26 cache'i action cache + CAS modeli (Bazel kabi); cache qilinmaydigan action'lar.

Markdown manba

iOS Lessons