Bazel 2: O'rnatish va birinchi build — Bazelisk, .bazelversion, MODULE.bazel, .bazelrc va "Salom, Bazel!"
📦 Bazel iOS — Mukammal Qo‘llanma & Amaliyot
Bazel 2: O'rnatish va birinchi build — Bazelisk, .bazelversion, MODULE.bazel, .bazelrc va "Salom, Bazel!"
Holat: 2026-yil oktabr. Bu darsda Bazel'ni Bazelisk orqali o'rnatamiz, noldan minimal workspace yig'amiz (
.bazelversion,MODULE.bazel,BUILD.bazel), birinchiswift_binary— "Salom, Bazel!" macOS CLI'sini build va run qilamiz, keyin output daraxti, client/server arxitekturasi va.bazelrc'ni chuqur o'rganamiz. Kod misollari Bazel 9.3.0, rules_swift 4.2.1 va Xcode 27.1 bilan Apple M4 Pro'da tekshirilgan.
Bu darsdan keyin siz: bo'sh papkadan boshlab ishlaydigan Bazel loyihasini o'z qo'lingiz bilan yig'asiz, birinchi target'ingizni build/run qilasiz va Bazel nima qayerga yozishini tushunasiz.
- Bazelisk'ni o'rnatasiz va
.bazelversionorqali jamoadagi hamma bir xil Bazel versiyasini ishlatishini ta'minlaysiz. - Minimal workspace'ning har bir faylini —
MODULE.bazel,BUILD.bazel,.bazelrc— nima uchun kerakligini bilib yozasiz. bazel buildvabazel runfarqini, output daraxtini (bazel-bin,bazel-out, output base) va nega ikkinchi build birinchisidan o'nlab barobar tez ekanini tushunasiz..bazelrc'dacommon/build/test/runbo'limlari,--configguruhlari va eng muhim flaglarni sozlaysiz.bazel info,bazel cleanvs--expunge,MODULE.bazel.lock,.gitignoreva Buildifier'ni kundalik ishda to'g'ri ishlatasiz.
Mundarija
- Bazelisk bilan o'rnatish
- Birinchi workspace: to'rt fayl
- Birinchi build va run — "Salom, Bazel!"
- Ikkinchi modul: swift_library qo'shamiz
- Output daraxti: Bazel nima qayerga yozadi
- Client/server: nega ikkinchi build tez
- .bazelrc chuqur: flaglarni bir marta yozib qo'yish
- Kundalik buyruqlar: info, clean, lock, gitignore, Buildifier
- Amaliy mashqlar
- O'zingizni tekshiring
- Xulosa
- Manbalar
1. Bazelisk bilan o'rnatish {#ornatish}
Oldingi darsda (Bazel 1: Bazel nima va nega kerak) Bazel'ning nima ekani va nega katta iOS jamoalariga kerakligini ko'rdik. Endi uni ishga tushiramiz. Birinchi savol: Bazel'ning o'zini qanday o'rnatamiz?
Bazel'ni to'g'ridan-to'g'ri o'rnatish mumkin, lekin bu yo'l tavsiya etilmaydi. Muammo oddiy: loyihangiz Bazel 9.3.0'da ishlaydi, hamkasbingiz noutbukida Bazel 8.8 turibdi, CI serverida esa yana boshqa versiya. Build xatti-harakati versiyadan versiyaga o'zgaradi — kimdir build qila oladi, boshqasi yo'q. Bu "menda ishlayapti-ku" muammosining aynan build tizimidagi ko'rinishi.
Yechim — Bazelisk. Bu Bazel'ning rasmiy launcher'i (ishga tushiruvchisi): siz bazel deb yozasiz, lekin aslida Bazelisk ishlaydi, u loyihangiz talab qilgan aynan o'sha Bazel versiyasini yuklab oladi va ishga tushiradi. Node'dagi nvm, Ruby'dagi rbenv yoki Tuist'dagi mise nima vazifani bajarsa, Bazelisk ham Bazel uchun shuni qiladi.
O'rnatish (macOS, Homebrew)
brew install bazelisk
Homebrew bazelisk'ni o'rnatadi va bazel nomini ham unga ulaydi (symlink). Ya'ni siz terminalda bazel deb yozsangiz ham, aslida Bazelisk ishlaydi. Tekshiramiz:
which bazel bazelisk
bazel --version
Bizning mashinada natija:
/opt/homebrew/bin/bazel
/opt/homebrew/bin/bazelisk
bazel 9.3.0
bazel va bazelisk bir xil joyga ishora qiladi — demak bazel buyrug'i Bazelisk orqali ketyapti. Versiya 9.3.0 chiqdi, chunki pastda ko'rsatamiz — loyihamizda shu versiyani so'raganmiz.
🧠 Esda tuting:
bazel installdegan buyruq yo'q. Bazel'ni o'rnatish — bu Bazelisk'ni o'rnatish. Keyin har bir loyiha o'ziga kerak Bazel versiyasini.bazelversionfaylida aytadi, Bazelisk esa uni avtomatik yuklab, keshlab, ishga tushiradi.
Bazelisk qaysi versiyani tanlashini qanday hal qiladi?
Bazelisk versiyani quyidagi tartibda qidiradi (birinchi topilgani yutadi):
USE_BAZEL_VERSIONmuhit o'zgaruvchisi (environment variable) — CI'da bitta buyruq uchun versiyani majburlash uchun qulay..bazeliskrcfayli..bazelversionfayli — joriy papkadan boshlab yuqoriga (ota-papkalarga) qarab qidiriladi.USE_BAZEL_FALLBACK_VERSION.- Hech biri bo'lmasa — eng oxirgi release.
Amalda 99% hollarda siz faqat .bazelversion faylidan foydalanasiz. U loyiha ildizida turadigan, ichida bitta qator — versiya raqami bo'lgan oddiy matn fayl:
# .bazelversion
9.3.0
.bazelversion qabul qiladigan yorliqlar faqat aniq raqam (9.3.0) bilan cheklanmaydi:
| Yorliq | Ma'nosi |
|---|---|
9.3.0 | Aynan shu versiya (loyihalar uchun eng yaxshi — takrorlanadigan build) |
9.x | Shu LTS liniyasining eng yangi release'i (RC'larsiz) |
9.* | Shu liniya, RC'lar bilan birga |
latest | Eng oxirgi barqaror release |
latest-1 | Undan bitta oldingi |
last_green | HEAD'dagi oxirgi yashil (sinovdan o'tgan) build |
rolling | Eng yangi rolling release |
💡 Pro tip: Loyihangizda aniq versiyani (
9.3.0) yozing,latest'ni emas. "Latest" bugun 9.3.0, ertaga 9.4.0 bo'lishi mumkin — va o'sha kuni CI'ingiz kutilmaganda sinishi mumkin. rules_apple'ning o'z repozitoriysi ham.bazelversion'da9.xdan foydalanadi, lekin o'z mahsulot loyihangizda aniq raqam xavfsizroq: hamma — siz, hamkasbingiz, CI — millimetrgacha bir xil Bazel ishlatadi.
LTS va rolling: qaysi versiyani tanlash kerak?
Bazel 4.0'dan beri ikki xil release liniyasi bor:
- LTS (Long Term Support) — har ~12 oyda bitta yangi major versiya (masalan Bazel 8, Bazel 9). Har bir major o'z ichida minor (
9.1,9.2,9.3) va patch (9.3.0) release'lari oladi. Bu liniya barqaror va uzoq qo'llab-quvvatlanadi. - Rolling — HEAD'dan har ~2 haftada chiqadigan "oldindan ko'rish" release'lari. Ular keyingi LTS'ning nima bo'lishini ko'rsatadi, lekin mos kelmaydigan o'zgarishlar (incompatible changes) olib kelishi mumkin.
Bazel'ning rasmiy release modeliga ko'ra har bir major versiya to'rt bosqichdan o'tadi: Rolling → Active → Maintenance → Deprecated. Active — joriy tavsiya etilgan LTS; Maintenance — faqat xavfsizlik va OS-moslik tuzatishlari backport qilinadigan eski LTS.
2026-yil oktabr holatiga ko'ra:
| Versiya | Holati | Izoh |
|---|---|---|
| 9.3.0 | eng yangi barqaror (2026-10-07) | biz shu bilan ishlaymiz |
| 8.8.1 | 8.x LTS liniyasi (2026-09-24) | oldingi avlod, hali qo'llab-quvvatlanadi |
| 10.0.0rc1 | pre-release (2026-10-07) | hali RC — mahsulotda ishlatmang |
⚠️ Diqqat:
10.0.0rc1chiqqan bo'lsa ham,.bazelversion'ga uni yozmang. "rc" — release candidate, ya'ni hali sinov bosqichida. Loyihangizda oxirgi barqaror versiyani (9.3.0) pinlang.
Bazel 9 — nega eski darsliklar ishlamaydi
Agar internetdan Bazel bo'yicha eski qo'llanma topsangiz va unda WORKSPACE fayli haqida gap ketsa — u eskirgan. Buni bilib qo'ying, chunki bu eng ko'p vaqt yeydigan tuzoq:
- Bazel 9.0'dan boshlab Bzlmod har doim yoqilgan,
WORKSPACEfayli mantiqi esa butunlay olib tashlangan.--enable_bzlmodva--enable_workspaceflaglari endi hech narsa qilmaydi (no-op). Tashqi bog'liqliklar faqatMODULE.bazelorqali e'lon qilinadi. - Bazel 9'da barcha C/C++ va Objective-C rule'lari (
cc_library,objc_library, ...) Bazel yadrosidan chiqarildi — ularni endi@rules_cc'dan aniqload()qilish kerak. Sof Swift loyihalar uchun bu muammo emas, lekin ObjC aralash kod yozsangiz buni eslang. - Bazel 9'da macOS'da output base (Bazel hamma narsani yozadigan joy)
/private/var/tmp'dan~/Library/Caches/bazel'ga ko'chdi — shuning uchun kesh OS yangilanishidan keyin ham saqlanadi.
Demak bu darsda ko'radigan hamma narsa — MODULE.bazel, bazel_dep, Bzlmod — Bazel 9'ning zamonaviy, yagona to'g'ri usuli. WORKSPACE so'zini unuting.
2. Birinchi workspace: to'rt fayl {#workspace}
Endi noldan ishlaydigan loyiha yig'amiz. Bazel dunyosida loyiha workspace deb ataladi — bu Bazel boshqaradigan fayllar daraxtining ildizi. Workspace'ni nima belgilaydi? Ildizda MODULE.bazel faylining mavjudligi. Bazel'ni shu fayl turgan papkadan (yoki uning ichki papkasidan) ishga tushirish shart — aks holda "repozitoriya topilmadi" degan xato chiqadi.
"Salom, Bazel!" macOS buyruq-qatori (CLI) dasturini yasaymiz. Bor-yo'g'i to'rtta fayl kerak:
salom/
├── .bazelversion # Bazelisk uchun: qaysi Bazel versiyasi
├── MODULE.bazel # modul nomi + tashqi bog'liqliklar (bazel_dep)
├── BUILD.bazel # target'lar (nima build qilinadi)
└── main.swift # Swift kodimiz
Har birini yozamiz.
.bazelversion
# .bazelversion
9.3.0
Bitta qator. Bu faylni ko'rgan Bazelisk aynan 9.3.0'ni yuklab ishga tushiradi.
MODULE.bazel
Bu — loyihaning "pasporti". U ikki ishni qiladi: (1) modulingizga nom beradi, (2) tashqi bog'liqliklarni (bazel_dep) e'lon qiladi. Swift kodini build qilish uchun Bazel'ga rules_swift kerak — bu Swift'ni qanday kompilyatsiya qilishni biladigan rasmiy rule to'plami.
# MODULE.bazel
module(
name = "salom_bazel",
version = "1.0.0",
)
bazel_dep(name = "rules_swift", version = "4.2.1")
module() — moduling nomi va versiyasi. bazel_dep() — tashqi modulga bog'lanish. rules_swift qayerdan keladi? Bazel Central Registry (BCR) dan — bu npm'ning registry.npmjs.org'i yoki CocoaPods'ning trunk'iga o'xshash markaziy ombor (bcr.bazel.build). Siz versiyani aytasiz, Bazel BCR'dan o'zi yuklab oladi. Hech qanday URL yoki git-hash yozish shart emas.
🧠 Esda tuting:
rules_swift— bu Apple'ning rasmiy repozitoriysi (bazelbuild/rules_swift), lekin u Bazel yadrosining qismi EMAS. Bazel o'zi til bilmaydi; har bir tilni alohida rule to'plami o'rgatadi. Swift uchunrules_swift, iOS ilovalari uchunrules_apple(keyingi darslarda), C++ uchunrules_cc. Bu Bazel'ning kuchi: u ko'p tilli (polyglot).
2026-yil oktabr holatida BCR'dagi dolzarb versiyalar: rules_swift 4.2.1, rules_apple 5.3.0, apple_support 2.10.1. Hozircha sof Swift CLI uchun bizga faqat rules_swift yetarli.
BUILD.bazel
Bu fayl papkani packagega aylantiradi va unda targetlar e'lon qilinadi. Target — Bazel qura oladigan bir narsa: kutubxona, bajariladigan fayl, test. Bizning target — bajariladigan Swift dastur, uni swift_binary rule yasaydi.
# BUILD.bazel
load("@rules_swift//swift:swift_binary.bzl", "swift_binary")
swift_binary(
name = "salom",
srcs = ["main.swift"],
)
Ikki qism bor:
load(...)—swift_binaryrule'inirules_swiftmodulidan olib keladi.@rules_swift— bizMODULE.bazel'da e'lon qilgan modulga ishora. Bazel'da hech bir rule o'z-o'zidan mavjud bo'lmaydi: har birini ishlatishdan oldin aniqload()qilish kerak. Bu — Swift'dagiimportkabi.swift_binary(...)— target'ning o'zi.name— target nomi (undan//:salomlabel hosil bo'ladi),srcs— manba fayllar ro'yxati.
💡 Pro tip: rules_swift 4.2.1'da ikkita
loadyo'li ishlaydi:@rules_swift//swift:swift_binary.bzl(har bir rule alohida faylda — yangi, tavsiya etilgan uslub) va@rules_swift//swift:swift.bzl(hamma rule'ni bitta joydan re-eksport qiladigan eski "to'plam" fayl). Ikkalasi ham bir xilswift_binary'ni beradi. Biz yangi, aniq yo'lni ishlatamiz — kelajakdaswift.bzleskirishi mumkin.
main.swift
// main.swift
print("Salom, Bazel!")
Oddiy Swift. @main ham, main.swift'da hech qanday boilerplate ham kerak emas — main.swift nomli fayl o'zi dastur kirish nuqtasi bo'ladi (bu Swift tilining qoidasi, Bazel'niki emas).
Quyidagi xarita workspace'ning har bir faylini va uning vazifasini bir ko'rinishda jamlaydi. Bu to'rt fayl — zarur minimum; .bazelrc ixtiyoriy (uni 7-bo'limda qo'shamiz), MODULE.bazel.lock va bazel-* symlink'lari esa birinchi build'dan keyin o'zi paydo bo'ladi:
Minimal Bazel workspace anatomiyasi: .bazelversion, MODULE.bazel, MODULE.bazel.lock, .bazelrc, BUILD.bazel, main.swift va bazel-* symlink'lari — har birining vazifasi va qaysilari git'ga commit qilinishi.
Chap tomonda — fayllar daraxti, o'ngda — har birining roli; pastda qaysilari git'ga commit qilinishi (manba fayllar) va qaysilari .gitignore'ga ketishi (symlink'lar) ko'rsatilgan.
To'rt fayl tayyor. Endi build qilamiz.
3. Birinchi build va run — "Salom, Bazel!" {#birinchi-build}
bazel build — faqat quramiz
bazel build //:salom
//:salom — bu label. Uni shunday o'qing: // — workspace ildizi, :salom — ildizdagi BUILD.bazel'da turgan salom nomli target. Labellar haqida to'liq keyingi darsda (Bazel 3), hozircha "qaysi target'ni build qilaman" degan manzil deb bilsangiz yetarli.
Birinchi marta ishga tushirganda Bazel ancha "band" bo'ladi. Bizning mashinada birinchi (sovuq) build natijasi:
[255 / 289] Compiling absl/crc/crc32c.cc [for tool]; 2s darwin-sandbox ... (12 actions running)
[278 / 289] Compiling absl/synchronization/internal/stdcpp_waiter.cc [for tool]; 1s darwin-sandbox
[286 / 289] Compiling Swift module //:salom; 0s worker
Target //:salom up-to-date:
bazel-bin/salom
INFO: Elapsed time: 44.230s, Critical Path: 11.65s
INFO: 289 processes: 117 internal, 171 darwin-sandbox, 1 worker.
INFO: Build completed successfully, 289 total actions
44 soniya — bitta print uchun? Ha, va bu normal. Sababini bilish muhim: bizning salom target'imiz 289 ta action'dan faqat bittasi. Qolgan 288'tasi — rules_swift'ning o'z persistent worker vositasini (Swift'ni tez kompilyatsiya qiladigan yordamchi dastur) noldan yig'ish. U C++'da yozilgan va abseil kutubxonasiga tayanadi — log'dagi Compiling absl/... qatorlari aynan shu. Bu bir martalik narx: mashinangizda bir marta to'lanadi, keyin kesh'da qoladi.
📊 Real raqamlar: Apple M4 Pro (12 yadro, 24 GB), Bazel 9.3.0, Xcode 27.1. Sovuq birinchi build (bo'sh output base, disk cache o'chirilgan): 44.2 s, 289 action. Shundan ~288'tasi — rules_swift worker'ini (abseil) kompilyatsiya qilish, bir martalik. Bizning bitta
salomtarget'i esa oxirgi 0 soniyalik qadam.
Natija bazel-bin/salom'da — bu bajariladigan fayl. Uni to'g'ridan-to'g'ri ishga tushirsak ham bo'ladi:
./bazel-bin/salom
Salom, Bazel!
bazel run — quramiz va ishga tushiramiz
Ko'pincha "qur va darhol ishga tushir" kerak bo'ladi. Buning uchun bazel run:
bazel run //:salom
INFO: Elapsed time: 0.091s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/salom
Salom, Bazel!
E'tibor bering: bu safar 0.091 s — chunki hech narsa o'zgarmagan, Bazel qayta build qilmadi, to'g'ridan-to'g'ri bazel-bin/salom'ni ishga tushirdi. bazel build va bazel run farqi shu: build faqat quradi, run quradi (agar kerak bo'lsa) va natijani bajaradi.
🚀 Motivatsiya: Birinchi build 44 soniya bo'ldi, lekin ikkinchisi — 0.16 soniyada "up-to-date" bo'ldi (hech narsa qurilmadi). Bu Bazel'ning asosiy va'dasi: o'zgarmagan ishni ikkinchi marta bajarmaydi. Katta loyihada bu farq soatlarni tejaydi. Buni o'z ko'zingiz bilan ko'rish uchun
main.swift'ni ozgina o'zgartirib, qayta build qiling.
Inkremental build: bitta faylni o'zgartiramiz
main.swift'ni o'zgartiramiz:
// main.swift
let kim = "Bazel"
print("Salom, \(kim)!")
print("Birinchi build tizimi loyiham ishga tushdi.")
bazel build //:salom
Target //:salom up-to-date:
INFO: Elapsed time: 0.353s, Critical Path: 0.28s
INFO: 4 processes: 2 internal, 1 darwin-sandbox, 1 worker.
INFO: Build completed successfully, 4 total actions
289 action o'rniga atigi 4 ta — faqat o'zgargan faylga bog'liq ishlar qayta bajarildi. worker allaqachon tayyor (kesh'da), abseil qayta kompilyatsiya qilinmadi. Natija:
Salom, Bazel!
Birinchi build tizimi loyiham ishga tushdi.
📊 Real raqamlar: O'sha mashina. Bitta Swift faylni tahrirlab qayta build: 0.353 s, 289 o'rniga 4 action. Bu — Bazel'ning inkremental build'i: faqat o'zgarishga bog'liq bo'lgan qismni qayta quradi.
Mana Bazel'ning asosiy g'oyasi amalda: sovuq 44.2 s → inkremental 0.35 s. Build grafigi va action keshi tufayli Bazel aniq biladi — nima o'zgardi va nimani qayta qurish shart emas.
4. Ikkinchi modul: swift_library qo'shamiz {#swift-library}
Bitta swift_binary — bu boshlanish. Bazel'ning asl kuchi loyihani modullarga bo'lganda ko'rinadi: har bir modul alohida swift_library, Bazel esa faqat o'zgargan modulni qayta quradi. Buni hozir kichik miqyosda ko'ramiz — salomlashish mantiqini alohida kutubxonaga ajratamiz.
Yangi papka ochamiz: greeter/. Ichida ikki fayl.
greeter/Greeter.swift — kutubxona kodi
// greeter/Greeter.swift
public struct Greeter {
public init() {}
public func salom(_ kim: String) -> String {
"Salom, \(kim)!"
}
}
public muhim: boshqa modul (salom binary) bu tipdan foydalanishi uchun u ochiq bo'lishi kerak. Swift'da modul tashqarisiga chiqadigan hamma narsa public bo'lishi shart.
greeter/BUILD.bazel — kutubxona target'i
# greeter/BUILD.bazel
load("@rules_swift//swift:swift_library.bzl", "swift_library")
swift_library(
name = "greeter",
srcs = ["Greeter.swift"],
module_name = "Greeter",
visibility = ["//visibility:public"],
)
Uch atribut:
srcs— kutubxona manba fayllari.module_name = "Greeter"— Swift modul nomi. Bu belgilanmasa, Bazel target label'idan avtomatik nom yasaydi (greeter), lekin aniq nom bergan ma'qul —import Greetershunga bog'liq.visibility = ["//visibility:public"]— bu target'ni kim ishlatishi mumkinligini belgilaydi.public— hamma. Visibility — Bazel'ning arxitektura qoidalarini majburlash mexanizmi (to'liq Bazel 3da); hozircha "boshqa papkadagi target shundan foydalana olsin" deb qo'yamiz.
Binary'ni kutubxonaga bog'laymiz
Root BUILD.bazel'ga deps qo'shamiz:
# BUILD.bazel
load("@rules_swift//swift:swift_binary.bzl", "swift_binary")
swift_binary(
name = "salom",
srcs = ["main.swift"],
deps = ["//greeter"],
)
deps = ["//greeter"] — salom binary'si greeter kutubxonasiga bog'liq. //greeter — bu label: //greeter papkasidagi greeter nomli target (nom papka nomi bilan bir xil bo'lsa, :greeter qismi tushib qoladi).
main.swift — kutubxonadan foydalanamiz
// main.swift
import Greeter
let greeter = Greeter()
print(greeter.salom("Bazel"))
print(greeter.salom("iOS dasturchi"))
Build va run:
bazel run //:salom
INFO: Elapsed time: 1.964s, Critical Path: 1.81s
INFO: 8 processes: 3 action cache hit, 4 internal, 2 darwin-sandbox, 2 worker.
INFO: Running command line: bazel-bin/salom
Salom, Bazel!
Salom, iOS dasturchi!
Ikkita modul, ikkita swift_library/swift_binary, bitta deps bog'lanishi. Worker allaqachon kesh'da bo'lgani uchun bu build atigi ~2 soniya — rules_swift'ning C++ worker'ini qayta qurish shart emas edi.
📊 Real raqamlar: Apple M4 Pro, Bazel 9.3.0. Ikki modulli loyihani (greeter + salom) build + run: 1.964 s, 8 action. Worker kesh'da bo'lgani sabab 44 soniyalik sovuq narx qaytmadi.
Build grafigini ko'rish: bazel query
Bazel aniq biladi — qaysi target qaysisiga bog'liq. bazel query bu grafikni ko'rsatadi:
bazel query 'deps(//:salom)'
Natijaning loyihamizga tegishli qismi (tashqi modullar chiqarib tashlangan):
//:main.swift
//:salom
//greeter:Greeter.swift
//greeter:greeter
//:salom //greeter:greeter'ga, u esa o'z manbasiga bog'liq. Bu grafik — Bazel inkremental build'ining asosi: greeter/Greeter.swift'ni o'zgartirsangiz, Bazel faqat greeter va unga bog'liq salom'ni qayta quradi; main.swift'ni o'zgartirsangiz — faqat salom'ni, greeter tegilmaydi. Build grafigi va query haqida to'liq keyingi darsda.
🚀 Motivatsiya: Hozir atigi ikki modul. Tasavvur qiling — 200 modulli ilova. Bitta ekranni o'zgartirsangiz, Bazel qolgan 199 modulni tegmay, faqat o'shani qayta quradi. Oldingi darsda ko'rgan real jamoalar (Monzo, Trendyol) build vaqtini aynan shu tamoyil bilan daqiqalardan soniyalarga tushirgan.
5. Output daraxti: Bazel nima qayerga yozadi {#output-tree}
Birinchi build'dan keyin workspace'ingizda yangi narsalar paydo bo'ldi. Ularni ko'ramiz:
ls -la
$ ls -la # (qisqartirilgan: egasi/sana ustunlari olib tashlandi, hash … bilan)
lrwxr-xr-x bazel-bin -> /Users/.../_bazel_codingtech/c632aa8f…/execroot/_main/bazel-out/darwin_arm64-fastbuild/bin
lrwxr-xr-x bazel-out -> /Users/.../_bazel_codingtech/c632aa8f…/execroot/_main/bazel-out
lrwxr-xr-x bazel-salom -> /Users/.../_bazel_codingtech/c632aa8f…/execroot/_main
lrwxr-xr-x bazel-testlogs -> /Users/.../_bazel_codingtech/c632aa8f…/execroot/_main/bazel-out/darwin_arm64-fastbuild/testlogs
bazel-bin, bazel-out, bazel-<workspace-nomi> — bular oddiy papka emas, symlinklar (-> belgisiga e'tibor bering). Ular workspace'ingizdan tashqaridagi haqiqiy build papkalariga ishora qiladi. Nega tashqarida? Chunki build natijalari (vaqtinchalik, qayta yaratiladigan) manba kodingiz bilan aralashmasligi kerak.
Output base — hamma narsa shu yerda
Bazel hamma ishni output base degan papkada bajaradi. Uning yo'lini bazel info ko'rsatadi:
bazel info output_base
bazel info execution_root
bazel info bazel-bin
Bizning mashinada:
output_base: /Users/codingtech/Library/Caches/bazel/_bazel_codingtech/c632aa8fbc05321e1c324ab1e0f95e76
execution_root: <output_base>/execroot/_main
bazel-bin: <output_base>/execroot/_main/bazel-out/darwin_arm64-fastbuild/bin
release: release 9.3.0
Yo'lni tahlil qilamiz. Bazel 9'da macOS'da ildiz — ~/Library/Caches/bazel (Bazel 8 va undan oldin /private/var/tmp edi). Undan keyin:
_bazel_<user>/— foydalanuvchi bo'yicha papka. Bitta mashinada bir nechta odam ishlasa, har kimning o'z papkasi bo'ladi.<hash>/— bu workspace yo'lining MD5 hash'i. Shuning uchun har bir workspace o'z output base'iga ega. Ikki xil papkadagi ikki loyiha bir-biriga xalaqit bermaydi.
Output base ichidagi muhim qismlar (rasmiy hujjat layout'idan):
~/Library/Caches/bazel/_bazel_<user>/<hash>/
├── action_cache/ # qaysi action bajarilgani — inkremental build'ning xotirasi
├── command.log # oxirgi buyruqning stdout/stderr nusxasi
├── external/ # yuklab olingan tashqi modullar (rules_swift ...)
├── server/ # Bazel server fayllari (socket, log)
│ └── jvm.out # server debug chiqishi
└── execroot/
└── _main/ # build ishlaydigan daraxt (execution root)
└── bazel-out/ # BARCHA build natijalari shu yerda
└── .../bin/salom # bizning bajariladigan faylimiz
Qulaylik symlink'lari
Workspace ildizidagi symlink'lar shu chuqur yo'llarga qisqa yo'l beradi:
| Symlink | Ishora qiladi | Nima uchun |
|---|---|---|
bazel-bin | .../bin | build qilingan binary'lar (bazel-bin/salom) |
bazel-out | .../bazel-out | barcha output (bin, genfiles, testlogs) |
bazel-testlogs | .../testlogs | test log'lari (keyingi darsda) |
bazel-<dir> | .../execroot/_main | execution root (source + output aralash ko'rinish) |
Bazel'ning o'zi bu symlink'lardan foydalanmaydi — ular faqat siz uchun qulaylik. Shuning uchun ularni .gitignore'ga qo'yish shart (pastda ko'ramiz).
🧠 Esda tuting:
bazel info— eng foydali diagnostika buyrug'i.bazel info output_baseserverni qidirmay turib javob beradi;bazel info releaseesa joriy Bazel versiyasini aytadi. "Build qayerda?" degan savol tug'ilsa —bazel info bazel-bin.
6. Client/server: nega ikkinchi build tez {#client-server}
3-bo'limda bir g'alati narsani ko'rdik: birinchi build 44 soniya, ikkinchisi — bir soniyadan kam. Buning sababi Bazel'ning ichki arxitekturasida.
Bazel ikki qismdan iborat: client va server. Siz terminalda bazel deb yozganingizda, aslida yengil client ishga tushadi. U haqiqiy ishni o'zi qilmaydi — uzoq yashovchi server (JVM jarayoni) bilan gaplashadi. Server esa build grafigini, o'qilgan BUILD/MODULE fayllarni va action keshini xotirada saqlaydi.
Bazel client/server arxitekturasi: yengil client gRPC orqali uzoq yashovchi JVM server bilan gaplashadi, server build grafigini xotirada saqlaydi, output base'ga yozadi.
Yuqoridagi sxema oqimni ko'rsatadi: client (bazel build //:salom) → server (xotiradagi graph + cache) → output base (diskdagi natijalar). Workspace ichidagi symlink'lar output base'ga ishora qiladi.
Nega bu muhim
- Birinchi build: client serverni ishga tushiradi (yoki avval ishga tushirgan bo'lsa, topadi), server
MODULE.bazel/BUILD.bazel'ni o'qiydi, tashqi modullarni yuklaydi, build grafigini noldan quradi, rules_swift worker'ini kompilyatsiya qiladi. 44.2 s shuning uchun. - Ikkinchi build: server allaqachon ishlab turibdi, graph uning xotirasida. Hech narsa o'zgarmagan bo'lsa, server darhol "up-to-date" deydi. Fayl yuklash, qayta tahlil — hech biri kerak emas.
Buni ps bilan ko'rish mumkin — server jarayoni workspace nomi bilan ko'rinadi:
ps -e | grep "bazel("
Server nomi bazel(salom) ko'rinishida bo'ladi (salom — workspace papka nomi). Har bir workspace uchun alohida server — shuning uchun bir nechta loyihada parallel ishlash mumkin.
Server qachon o'chadi
Server abadiy ishlamaydi. Standart holatda 3 soat bo'sh turgach o'chadi. Buni --max_idle_secs startup flagi bilan o'zgartirish mumkin:
# server 3 daqiqa bo'sh turgach o'chsin
bazel --max_idle_secs=180 build //:salom
Yoki .bazelrc'da doimiy qilib qo'yish mumkin: startup --max_idle_secs=180.
Serverni qo'lda o'chirish:
bazel shutdown
⚠️ Diqqat: Server o'chgandan keyingi birinchi build yana sekinroq bo'ladi — graph'ni qayta qurish kerak (lekin worker va action'lar disk cache'da bo'lsa, baribir sovuq 44 soniyadan ancha tez). Agar skript yozsangiz va u ko'p papkalarda build qilsa, bo'sh serverlar to'planib ketmasligi uchun ularni
bazel shutdownbilan yoping yoki qisqa--max_idle_secsqo'ying. Rasmiy hujjat aynan shuni tavsiya qiladi.
🚀 Motivatsiya: Client/server modeli — Bazel tezligining yuragi. Xcode har safar loyihani "noldan tushunadi"; Bazel esa bir marta tushunib, xotirada saqlaydi. Katta loyihada (yuzlab modul) bu farq ulkan: grafik qurish o'zi daqiqalar olishi mumkin, Bazel uni bir marta qilib, keyingi barcha buyruqlarda qayta ishlatadi.
7. .bazelrc chuqur: flaglarni bir marta yozib qo'yish {#bazelrc}
Bazel'da juda ko'p flag bor. Ayrimlari har build'da o'zgaradi, ko'pchiligi esa doim bir xil qoladi (masalan disk cache yo'li yoki simulator nomi). Har safar qo'lda yozmaslik uchun ularni .bazelrc faylida bir marta yozib qo'yasiz. Bu — build sozlamalaringizning yagona manbasi.
Bazel qaysi rc fayllarni o'qiydi va qaysi tartibda
Bazel rc fayllarini quyidagi tartibda o'qiydi (keyingisi oldingisini bekor qila oladi):
- System rc —
/etc/bazel.bazelrc(butun mashina uchun). - Workspace rc — workspace ildizidagi
.bazelrc(loyiha uchun; git'ga commit qilinadi). - Home rc —
$HOME/.bazelrc(sizning shaxsiy sozlamalaringiz). - Environment rc —
BAZELRCmuhit o'zgaruvchisi ko'rsatgan fayl(lar). - User-specified —
--bazelrc=faylbilan buyruq qatorida berilgan.
Amalda ishlatadiganingiz — **workspace .bazelrc (loyiha bilan birga ketadi, hamma uchun bir xil) va ba'zan home ~/.bazelrc** (faqat sizning mashinangizdagi afzalliklar). Masalan bu darsni yozayotgan mashinada home rc'da bitta qator bor:
# ~/.bazelrc
startup --max_idle_secs=180
Bu — server bo'sh turganida necha soniyada o'chishini belgilaydi (buni 6-bo'limda ko'rganmiz).
Sintaksis: har qator kimga tegishli
.bazelrc'ning har bir qatori <kim> <flaglar> ko'rinishida. Birinchi so'z flag qaysi buyruqlarga tegishli ekanini aytadi:
startup— startup flaglari (buyruqdan oldin keladi, masalan--max_idle_secs).common— flagni qo'llab-quvvatlaydigan barcha buyruqlarga. Agar biror buyruq flagni bilmasa, u shunchaki e'tiborsiz qoldiriladi (xato bermaydi).always— barcha buyruqlarga; agar buyruq flagni bilmasa — xato beradi.build,test,run,query, ... — aniq buyruqqa (va undan meros oladigan buyruqlarga).
Eng muhim nuqta — meros (inheritance). test buyrug'i build'dan meros oladi. Ya'ni build qatoridagi hamma flag bazel test'ga ham tegishli. Rasmiy hujjatdagi meros grafigi:
- Har bir buyruq
common'dan meros oladi. build'dan meros oladiganlar:test,run,clean,mobile-install,info,print_action,config,cquery,aquery.coverage,fetch,vendoresatest'dan meros oladi.
# .bazelrc
# Hammaga tegishli
common --disk_cache=~/.cache/bazel-disk
# Faqat build (va undan meros oladigan test/run/...)
build --verbose_failures
# Faqat test
test --test_output=errors
Bu misolda bazel test buyrug'i uchta flagni ham oladi: --disk_cache (common'dan), --verbose_failures (build'dan meros), --test_output=errors (o'ziniki).
🧠 Esda tuting: Buyruq qatorida bergan flag har doim
.bazelrc'dagidan ustun. Agar rc'dabuild -c opttursa-yu, sizbazel build -c dbgdesangiz —dbgyutadi. rc fayllar faqat standart qiymat beradi, majburlamaydi.
--config: flaglarni guruhlash
.bazelrc'da bir nechta flagni nom ostida guruhlash mumkin. Buning uchun buyruqdan keyin :nom qo'shasiz. Oddiy holatda bu flaglar e'tiborsiz qoldiriladi, faqat --config=nom berganda yoqiladi.
# .bazelrc
# "release" konfiguratsiyasi — optimallashtirilgan build
build:release -c opt
build:release --features=swift.enable_v6
# "ci" konfiguratsiyasi
build:ci --disk_cache=
build:ci --keep_going
bazel build //:salom --config=release # -c opt + swift.enable_v6 qo'llanadi
Bu — eng ko'p ishlatiladigan naqsh. Masalan --config=ci CI serverida, --config=release relizda, --config=debug kundalik ishda. Keyingi darslarda (cache, CI/CD) buni ko'p ishlatamiz.
💡 Pro tip: Shaxsiy (home) rc'dagi config nomlarini
_bilan boshlang (build:_tez ...) — shunda ular loyiha rc'sidagi nomlar bilan to'qnashmaydi.
try-import: shaxsiy sozlamalar uchun
Jamoada har kimning o'z afzalliklari bo'ladi (masalan --jobs soni yoki local simulator). Buni loyiha rc'siga yozib bo'lmaydi — u hammaga tegishli. Yechim: try-import.
# .bazelrc (loyiha, git'ga commit qilinadi)
common --disk_cache=~/.cache/bazel-disk
build --verbose_failures
# Har bir dasturchining o'z sozlamalari (git'ga qo'shilmaydi)
try-import %workspace%/user.bazelrc
import— fayl bo'lmasa Bazel xato beradi.try-import— fayl bo'lmasa xato bermaydi, shunchaki o'tkazib yuboradi.%workspace%— workspace ildiziga nisbatan yo'l.
user.bazelrc'ni .gitignore'ga qo'shing. Endi har bir dasturchi o'ziga kerak flaglarni o'sha faylga yozadi, loyiha rc'si esa toza qoladi.
Kundalik ishda eng foydali flaglar
Quyidagilar — har kuni ishlatiladigan flaglar va ularning ta'siri:
| Flag | Nima qiladi |
|---|---|
-c fastbuild | Standart rejim: optimizatsiyasiz, tez kompilyatsiya (kundalik ish) |
-c dbg | Debug ma'lumotlari bilan (breakpoint, LLDB) |
-c opt | Optimallashtirilgan (reliz, performance test) |
--disk_cache=<yo'l> | Build natijalarini diskda keshlash (workspace'lar orasida bo'lishiladi) |
--jobs=N | Parallel action soni (standart — CPU yadrolari soni) |
--keep_going / -k | Bitta target sinsa ham qolganini qurishda davom etish |
--verbose_failures | Singan action'ning to'liq buyruq qatorini ko'rsatish |
-s / --subcommands | Har bir action'ning aniq buyruq qatorini chop etish |
--announce_rc | Qaysi rc fayllar va flaglar qo'llanganini ko'rsatish |
--announce_rc: nima qo'llanayotganini ko'rish
"Mening flagim qayerdan kelyapti?" degan savol tug'ilsa, --announce_rc javob beradi:
bazel build //:salom --announce_rc
Inherited 'common' options: --isatty=0 --terminal_columns=80
INFO: Reading rc options for 'build' from <workspace>/.bazelrc:
Inherited 'common' options: --disk_cache=~/.cache/bazel-disk
-s: Bazel aslida qanday buyruq ishga tushiradi
Bazel "qora quti" emas. -s (subcommands) bilan har bir action'ning aniq buyruq qatorini ko'rasiz — masalan swiftc qanday chaqirilgani. greeter modulini misol qilamiz:
bazel build //greeter:greeter -s
Chiqishning modulni kompilyatsiya qiladigan qismi (qisqartirilgan):
SUBCOMMAND: # swift_library rule target //greeter:greeter [action 'Compiling Swift module
//greeter:greeter', ..., mnemonic: SwiftCompile]
(cd /Users/.../_bazel_codingtech/c632aa8f…/execroot/_main && \
bazel-out/darwin_arm64-opt-exec/bin/external/rules_swift+/tools/worker/worker \
swiftc @bazel-out/darwin_arm64-fastbuild/bin/greeter/Greeter.swiftmodule-0.params)
[283 / 285] Compiling Swift module //greeter:greeter; 1s disk-cache, worker
Diqqat qilinadigan narsa: Bazel swiftc'ni to'g'ridan-to'g'ri emas, rules_swift'ning persistent worker'i orqali chaqiradi va unga .params flagfile beradi (Greeter.swiftmodule-0.params). O'sha fayl ichida aniq flaglar turadi: -target, -sdk, -emit-object, -module-name, -swift-version, -Onone (fastbuild rejimi) va boshqalar. -s — debugging uchun oltin: "nega bu fayl bunday kompilyatsiya qilindi?" degan savolga aniq javob beradi.
⚠️ Diqqat:
-schiqishi juda uzun bo'ladi (har bir action uchun bir nechta qator). Uni faqat muayyan muammoni tekshirayotganda yoqing, doimiy.bazelrc'ga qo'ymang.
8. Kundalik buyruqlar: info, clean, lock, gitignore, Buildifier {#kundalik}
Loyiha ishga tushdi. Endi har kuni ishlatadigan buyruqlar va fayllarni ko'rib chiqamiz.
bazel info — "qayerda, qaysi versiya?"
bazel info — diagnostika buyrug'i. Argumentsiz chaqirsangiz, o'nlab qatorli ma'lumot beradi; aniq kalit bersangiz — faqat o'shani:
bazel info release # Bazel versiyasi
bazel info workspace # workspace ildizi
bazel info output_base # hamma narsa yoziladigan joy
bazel info bazel-bin # binary'lar qayerda
bazel info execution_root # build ishlaydigan daraxt
release 9.3.0
bazel info release — eng oddiy "Bazel ishlayaptimi va qaysi versiya?" tekshiruvi.
bazel clean vs bazel clean --expunge
Ba'zan build holatini tozalash kerak bo'ladi. Ikki daraja bor:
- **
bazel clean** — build chiqishini (bazel-out), action keshini va workspace symlink'larini o'chiradi. Server ishlashda qoladi, tashqi modullar (external/) saqlanadi. - **
bazel clean --expunge** — butun output base'ni o'chiradi: tashqi modullar, yuklab olingan hamma narsa ham ketadi. Serverni ham to'xtatadi.
⚠️ Diqqat:
bazel clean'ni muammoni "hal qilish" uchun refleks sifatida ishlatmang. Bazel inkremental build'i ishonchli — toza build kamdan-kam kerak.clean44 soniyalik sovuq narxni qaytaradi.--expungeesa bundan ham qimmatroq (tashqi modullarni qayta yuklaydi). Ularni faqat haqiqatan kesh buzilganiga ishonchingiz komil bo'lganda ishlating. Rasmiy hujjat ham aytadi:cleanbirinchi navbatda disk bo'shatish uchun, "muammoni tuzatish" uchun emas.
Lekin yaxshi xabar: **disk cache clean'dan omon qoladi**. Agar .bazelrc'da --disk_cache yoqilgan bo'lsa, bazel clean'dan keyingi build disk cache'dan tiklanadi:
bazel clean
bazel build //:salom
INFO: Elapsed time: 1.062s, Critical Path: 0.05s
INFO: 289 processes: 172 disk cache hit, 117 internal.
44 soniya o'rniga 1 soniya — 172 action disk cache'dan olindi, hech narsa qayta kompilyatsiya qilinmadi. Shuning uchun --disk_cache darsning boshidan .bazelrc'da turibdi.
📊 Real raqamlar: Apple M4 Pro, Bazel 9.3.0.
bazel clean+ qayta build, disk cache yoqilgan: 1.062 s, 172 ta disk cache hit. Disk cachecleandan omon qoladi, shuning uchun toza build ham sovuq emas.
MODULE.bazel.lock — commit qiling
Birinchi build'dan keyin MODULE.bazel.lock fayli paydo bo'ladi. Bu — tashqi bog'liqliklarning aniq qulflangan holati (npm'dagi package-lock.json, Swift'dagi Package.resolved kabi). U BCR'dan yuklangan modullarning aniq versiyalari va hash'larini yozadi.
Bu faylni git'ga commit qiling. Shunda hamkasbingiz va CI aynan siz ishlatgan modul versiyalarini oladi — "menda boshqa versiya yuklandi" muammosi bo'lmaydi.
🧠 Esda tuting: Commit qilinadigan:
.bazelversion,MODULE.bazel,MODULE.bazel.lock,.bazelrc,BUILD.bazelfayllari va manba kod. Commit qilinmaydigan:bazel-*symlink'lari vauser.bazelrc.
.gitignore
Bazel loyihasining .gitignore'i qisqa:
# .gitignore
# Bazel qulaylik symlink'lari (output base'ga ishora qiladi, qayta yaratiladi)
/bazel-*
# Shaxsiy rc (try-import orqali ulanadi)
/user.bazelrc
bazel-bin, bazel-out, bazel-testlogs, bazel-<dir> — hammasi symlink, har build'da qayta yaratiladi. Ularni commit qilish keraksiz va zararli.
Buildifier — BUILD fayllar uchun formatter va linter
BUILD.bazel va .bzl fayllar ham kod — ularni ham formatlash kerak. Buning rasmiy vositasi — Buildifier (Bazel jamoasining buildtools to'plamidan, Swift'dagi SwiftFormat/SwiftLint kabi).
brew install buildifier
Bizning mashinada Homebrew buildifier 10.1.0'ni o'rnatdi.
Formatlash. Tartibsiz yozilgan BUILD faylni ko'ramiz:
# BUILD.bazel (tartibsiz)
load("@rules_swift//swift:swift_binary.bzl","swift_binary")
swift_binary(name="salom",srcs=["main.swift"],deps=["//greeter"])
buildifier --mode=diff nima o'zgarishini ko'rsatadi (hech narsa o'zgartirmay):
-load("@rules_swift//swift:swift_binary.bzl","swift_binary")
-swift_binary(name="salom",srcs=["main.swift"],deps=["//greeter"])
+load("@rules_swift//swift:swift_binary.bzl", "swift_binary")
+
+swift_binary(
+ name = "salom",
+ srcs = ["main.swift"],
+ deps = ["//greeter"],
+)
buildifier BUILD.bazel (argumentsiz) esa faylni joyida formatlaydi: bo'sh joylar, har atribut alohida qatorga, standart ko'rinish.
deps'ni avtomatik tartiblaydi. BUILD fayllarda buildifier ro'yxatlarni (masalan deps) alifbo tartibida saralaydi:
deps = [
- "//zebra",
"//apple",
"//mango",
+ "//zebra",
],
Bu merge-conflict'larni kamaytiradi: hamma deps'ni bir xil tartibda saqlasa, ikki kishi bir vaqtda dependency qo'shganda to'qnashuv kamroq bo'ladi.
Lint. buildifier -lint=warn shubhali naqshlarni topadi. Masalan .bzl faylda bitta o'zgaruvchini ikki marta e'lon qilsangiz:
buildifier -lint=warn lintbad.bazel
lintbad.bazel:10: redefined-variable: Variable "x" has already been defined.
Redefining a global value is discouraged and will be forbidden in the future.
Consider using a new variable instead.
(https://github.com/bazel-contrib/buildtools/blob/main/WARNINGS.md#redefined-variable)
Har warning'da tushuntirish va hujjat havolasi bor. CI'da buildifier --mode=check qo'ysangiz, formatlanmagan BUILD fayl build'ni to'xtatadi — bu kodni toza saqlashning amaliy usuli.
Editor: VS Code
VS Code'da Bazel kengaytmasini (BazelBuild.vscode-bazel) o'rnating. U BUILD.bazel va .bzl fayllarga sintaksis ta'kidlash, target'larni ro'yxatda ko'rsatish va Buildifier bilan avtomatik formatlash beradi. Formatlashni saqlanganda ishga tushirish uchun .vscode/settings.json:
{
"[starlark]": {
"editor.defaultFormatter": "BazelBuild.vscode-bazel",
"editor.formatOnSave": true
}
}
Amaliy mashqlar {#mashqlar}
Bu mashqlarni o'z mashinangizda bajaring — Bazel'ni faqat o'qib emas, qo'l bilan yozib o'rganadigan tizim.
- O'rnatish va tekshirish.
brew install bazeliskqiling, bo'sh papka ochib ichida.bazelversionyarating (9.3.0),bazel --versionishga tushiring. Natijabazel 9.3.0chiqishi kerak. Keyin.bazelversion'ni9.xga o'zgartirib,bazel --versionqayta ishga tushiring — Bazelisk eng yangi 9.x liniyasini tanlashini ko'ring. - "Salom, Bazel!" noldan. Darsdagi to'rt faylni (
.bazelversion,MODULE.bazel,BUILD.bazel,main.swift) o'zingiz yozing.bazel run //:salombilan ishga tushiring. Keyinmain.swift'da matnni o'zingiznikiga o'zgartirib, qayta run qiling. - O'z raqamlaringizni o'lchang. Quyidagi jadvalni o'z mashinangizdagi natijalar bilan to'ldiring (
INFO: Elapsed timeqatoridan oling):
| Build turi | Buyruq | Vaqt |
|---|---|---|
| Sovuq (birinchi) | bazel build //:salom (bo'sh workspace) | ? |
| No-op (ikkinchi) | yana bazel build //:salom | ? |
| Inkremental | main.swift'ni o'zgartirib build | ? |
Sizning raqamlaringiz biznikidan farq qilishi normal — mashina va kesh holatiga bog'liq.
- Ikkinchi modul.
greeter/papkasidaswift_libraryyarating,salombinary'sini ungadepsorqali bog'lang,import Greeterbilan ishlating. Keyinbazel query 'deps(//:salom)'bilan bog'liqlik grafigini ko'ring.greeter/Greeter.swift'ni o'zgartiring va qayta build qiling — nechta action qayta bajarilganini kuzating. - **⭐
.bazelrckonfiguratsiyasi.**.bazelrc'dabuild:release -c optguruhini vatry-import %workspace%/user.bazelrcqatorini yozing.user.bazelrc'ni yaratib ichigabuild --jobs=4yozing.bazel build //:salom --config=release --announce_rcbilan qaysi flag qayerdan kelayotganini tekshiring.user.bazelrc'ni.gitignore'ga qo'shing. - ⭐ Buildifier.
brew install buildifierqiling.BUILD.bazel'ni ataylab tartibsiz yozing (bo'sh joysiz, bir qatorda),buildifier --mode=diff BUILD.bazelbilan o'zgarishlarni ko'ring, keyinbuildifier BUILD.bazelbilan formatlang.depsro'yxatini teskari tartibda yozib, buildifier uni qanday saralashini ko'ring.
O'zingizni tekshiring {#checklist}
- [ ] Nega to'g'ridan-to'g'ri Bazel emas, Bazelisk o'rnatiladi — tushuntira olasizmi?
- [ ]
.bazelversionnima vazifa bajaradi va nega aniq versiya (9.3.0) yoziladi,latestemas? - [ ] Minimal workspace'dagi
MODULE.bazelvaBUILD.bazelfarqini ayta olasizmi? - [ ]
bazel buildvabazel runfarqi nima? - [ ] Nega birinchi build 44 soniya, ikkinchisi bir soniyadan kam — client/server bilan tushuntira olasizmi?
- [ ]
bazel-binnima — oddiy papkami yoki symlink? U qayerga ishora qiladi? - [ ]
.bazelrc'dagicommon,build,testqatorlari farqi va--confignima uchun kerak? - [ ] Qaysi fayllar git'ga commit qilinadi, qaysilari
.gitignore'ga ketadi? - [ ]
bazel cleanvabazel clean --expungefarqi, va negaclean'ni refleks sifatida ishlatmaslik kerak?
Xulosa {#xulosa}
- Bazelisk — Bazel'ni o'rnatishning to'g'ri yo'li.
.bazelversionfayli jamoadagi hamma bir xil Bazel versiyasini ishlatishini ta'minlaydi; aniq versiya (9.3.0) pinlang,latestemas. - Minimal workspace — to'rt fayl:
.bazelversion(versiya),MODULE.bazel(modul +bazel_dep),BUILD.bazel(target'lar), manba kod. Bazel 9'da faqat Bzlmod (MODULE.bazel) ishlatiladi —WORKSPACEbutunlay olib tashlangan. swift_binaryvaswift_library—rules_swift'danload()qilinadi. Bazel yadrosida til yo'q; har bir tilni alohida rule to'plami o'rgatadi.- Birinchi build sekin (bizda 44.2 s — asosan rules_swift worker'ini kompilyatsiya qilish, bir martalik), ikkinchisi tez (0.16 s), inkremental ham tez (0.35 s). Bu Bazel'ning asosiy va'dasi: o'zgarmaganni qayta qilmaydi.
- Sababi — client/server arxitekturasi: yengil client uzoq yashovchi JVM server bilan gaplashadi, server build grafigini xotirada saqlaydi.
--max_idle_secsserverni qachon o'chishini,bazel shutdownqo'lda to'xtatishni boshqaradi. - Bazel hamma narsani output base'da saqlaydi (
~/Library/Caches/bazel/...),bazel-binkabi symlink'lar unga qisqa yo'l beradi — ularni.gitignore'ga qo'ying. .bazelrc— flaglarning yagona manbasi:common/build/test/runbo'limlari,--configguruhlari, shaxsiy sozlamalar uchuntry-import.MODULE.bazel.lock'ni commit qiling;bazel info,bazel query, Buildifier — kundalik asboblar.bazel clean'ni ehtiyot bo'lib ishlating, lekin--disk_cachecleandan omon qoladi (bizda clean'dan keyin 1 soniyada tiklandi).- Keyingi dars: Bazel 3: Asosiy tushunchalar — workspace, package, target, label, rule, visibility va build graph — bu darsda ishlatgan
//:salom,//greeterlabellari,visibilityva build grafigi aslida qanday ishlashini chuqur o'rganamiz.
Manbalar {#manbalar}
- Bazelisk — rasmiy launcher (versiya tanlash tartibi) —
USE_BAZEL_VERSION,.bazelversion, qabul qilinadigan yorliqlar. - Bazel release modeli — LTS va rolling — qo'llab-quvvatlash bosqichlari va release kadansi.
- Bazel 9.0 blogi (2026-01-20) — Bzlmod har doim yoqilgan, WORKSPACE olib tashlandi, output base macOS'da ko'chdi.
- Bazel 9.3.0 release (2026-10-07) — joriy barqaror versiya.
- [
.bazelrckonfiguratsiya fayllari](https://bazel.build/run/bazelrc) — rc fayl joylari, sintaksis,--config,try-import, meros tartibi. - Bazel client/server implementatsiyasi — server,
--max_idle_secs,bazel shutdown. - Output Directory Layout — output base, execroot, symlink'lar,
bazel cleanvs--expunge. - rules_swift — releases (4.2.1) — joriy versiya, Swift 6.4 moslik.
- [rules_swift —
swift_binary/swift_libraryhujjati](https://github.com/bazelbuild/rules_swift/blob/main/doc/rules.md) — rule atributlari valoadyo'llari. - Bazel Central Registry (BCR) —
bazel_depmodullari manbai. - Buildifier / buildtools — BUILD fayl formatter va linter, warning ro'yxati.
- VS Code Bazel kengaytmasi — sintaksis, target ro'yxati, Buildifier integratsiyasi.