Bazel dapat mem-build dan menguji kode pada berbagai hardware, sistem operasi, dan konfigurasi sistem, menggunakan berbagai versi alat build seperti linker dan compiler. Untuk membantu menangani kompleksitas ini, Bazel memiliki konsep batasan dan platform. Batasan adalah dimensi yang membuat lingkungan build atau produksi dapat berbeda, seperti arsitektur CPU, ada atau tidak adanya GPU, atau versi compiler yang diinstal sistem. Platform adalah kumpulan pilihan bernama untuk batasan ini, yang mewakili resource tertentu yang tersedia di lingkungan tertentu.
Membuat model lingkungan sebagai platform akan membantu Bazel memilih secara otomatis toolchain yang sesuai untuk tindakan build. Platform juga dapat digunakan bersama aturan config_setting untuk menulis atribut yang dapat dikonfigurasi.
Bazel mengenali tiga peran yang dapat dilayani platform:
- Host - platform tempat Bazel berjalan.
- Eksekusi - platform tempat alat build mengeksekusi tindakan build untuk menghasilkan output menengah dan akhir.
- Target - platform tempat output akhir berada dan dieksekusi.
Bazel mendukung skenario build berikut terkait platform:
Build platform tunggal (default) - platform host, eksekusi, dan target sama. Misalnya, mem-build file Linux yang dapat dieksekusi di Ubuntu yang berjalan di CPU Intel x64.
Build kompilasi silang - platform host dan eksekusi sama, tetapi platform targetnya berbeda. Misalnya, membangun aplikasi iOS di macOS yang berjalan di MacBook Pro.
Build multiplatform - platform host, eksekusi, dan target berbeda-beda.
Menentukan batasan dan platform
Ruang pilihan yang memungkinkan untuk platform ditentukan dengan menggunakan aturan
constraint_setting
dan
constraint_value
dalam file BUILD
.
constraint_setting
membuat dimensi baru, sementara
constraint_value
membuat nilai baru untuk dimensi tertentu; bersama-sama, keduanya
secara efektif menentukan enum dan kemungkinan nilainya. Misalnya, cuplikan
file BUILD
berikut memasukkan batasan untuk versi glibc sistem
dengan dua kemungkinan nilai.
constraint_setting(name = "glibc_version")
constraint_value(
name = "glibc_2_25",
constraint_setting = ":glibc_version",
)
constraint_value(
name = "glibc_2_26",
constraint_setting = ":glibc_version",
)
Batasan dan nilainya dapat ditentukan di berbagai paket di ruang kerja. Class ini direferensikan oleh label dan tunduk pada kontrol visibilitas biasa. Jika visibilitas memungkinkan, Anda dapat memperluas setelan batasan yang ada dengan menentukan nilai Anda sendiri untuknya.
Aturan platform
memperkenalkan platform baru dengan
pilihan nilai batasan tertentu. Contoh berikut akan membuat platform bernama linux_x86
, dan menyatakan bahwa platform tersebut menjelaskan lingkungan apa pun yang menjalankan sistem operasi Linux pada arsitektur x86_64 dengan versi glibc 2.25. (Lihat di bawah untuk mengetahui selengkapnya tentang batasan bawaan Bazel.)
platform(
name = "linux_x86",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":glibc_2_25",
],
)
Batasan dan platform yang umumnya berguna
Agar ekosistem tetap konsisten, tim Bazel mengelola repositori dengan definisi batasan untuk arsitektur CPU dan sistem operasi paling populer. Semuanya ada di https://github.com/bazelbuild/platforms.
Bazel dilengkapi dengan definisi platform khusus berikut:
@platforms//host
(dialias sebagai @bazel_tools//tools:host_platform
). Ini adalah
nilai platform host yang terdeteksi otomatis -
mewakili platform yang terdeteksi otomatis untuk sistem yang menjalankan Bazel.
Menentukan platform untuk build
Anda dapat menentukan platform host dan target untuk build menggunakan tanda command line berikut:
--host_platform
- ditetapkan secara default ke@bazel_tools//tools:host_platform
- Target ini dialiaskan ke
@platforms//host
, yang didukung oleh aturan repo yang mendeteksi OS dan CPU host serta menulis target platform. - Ada juga
@platforms//host:constraints.bzl
, yang menampilkan array bernamaHOST_CONSTRAINTS
, yang dapat digunakan di file BUILD dan Starlark lainnya.
- Target ini dialiaskan ke
--platforms
- ditetapkan secara default ke platform host- Artinya, jika tidak ada tanda lain yang ditetapkan,
@platforms//host
adalah platform target. - Jika
--host_platform
ditetapkan dan bukan--platforms
, nilai--host_platform
adalah platform host dan target.
- Artinya, jika tidak ada tanda lain yang ditetapkan,
Melewati target yang tidak kompatibel
Saat membuat aplikasi untuk platform target tertentu, sebaiknya lewati target yang tidak akan pernah berfungsi di platform tersebut. Misalnya, driver perangkat Windows
mungkin akan menghasilkan banyak error compiler saat membangun di
mesin Linux dengan //...
. Gunakan
atribut target_compatible_with
untuk memberi tahu Bazel batasan platform target yang dimiliki kode Anda.
Penggunaan paling sederhana dari atribut ini akan membatasi target ke satu platform.
Target tidak akan dibuat untuk platform apa pun yang tidak memenuhi semua
batasan. Contoh berikut membatasi win_driver_lib.cc
untuk Windows
64-bit.
cc_library(
name = "win_driver_lib",
srcs = ["win_driver_lib.cc"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
)
:win_driver_lib
hanya kompatibel untuk proses build dengan Windows 64-bit dan
tidak kompatibel dengan lainnya. Inkompatibilitas bersifat transitif. Setiap target
yang secara transitif bergantung pada target yang tidak kompatibel akan dianggap tidak
kompatibel.
Kapan target dilewati?
Target dilewati jika dianggap tidak kompatibel dan disertakan dalam build sebagai bagian dari perluasan pola target. Misalnya, dua pemanggilan berikut akan melewati target tidak kompatibel yang ditemukan dalam perluasan pola target.
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
Pengujian yang tidak kompatibel di test_suite
juga akan dilewati jika test_suite
ditentukan pada command line dengan
--expand_test_suites
.
Dengan kata lain, target test_suite
di command line berperilaku seperti :all
dan
...
. Penggunaan --noexpand_test_suites
akan mencegah perluasan dan menyebabkan
target test_suite
dengan pengujian yang tidak kompatibel juga menjadi tidak kompatibel.
Menentukan secara eksplisit target yang tidak kompatibel pada command line akan menghasilkan pesan error dan build yang gagal.
$ bazel build --platforms=//:myplatform //:target_incompatible_with_myplatform
...
ERROR: Target //:target_incompatible_with_myplatform is incompatible and cannot be built, but was explicitly requested.
...
FAILED: Build did NOT complete successfully
Target eksplisit yang tidak kompatibel akan dilewati otomatis jika
--skip_incompatible_explicit_targets
diaktifkan.
Batasan yang lebih ekspresif
Untuk fleksibilitas yang lebih besar dalam mengekspresikan batasan, gunakan
@platforms//:incompatible
constraint_value
yang tidak terpenuhi oleh platform.
Gunakan select()
bersama dengan
@platforms//:incompatible
untuk menyatakan batasan yang lebih rumit. Misalnya, gunakan logika ATAU untuk menerapkan logika OR dasar. Tanda berikut menandai library
yang kompatibel dengan macOS dan Linux, tetapi tidak dengan platform lain.
cc_library(
name = "unixish_lib",
srcs = ["unixish_lib.cc"],
target_compatible_with = select({
"@platforms//os:osx": [],
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
)
Hal di atas dapat ditafsirkan sebagai berikut:
- Saat menargetkan macOS, target tidak memiliki batasan.
- Saat menargetkan Linux, target tidak memiliki batasan.
- Jika tidak, target memiliki batasan
@platforms//:incompatible
. Karena@platforms//:incompatible
bukan bagian dari platform mana pun, target dianggap tidak kompatibel.
Agar batasan Anda lebih mudah dibaca, gunakan
selects.with_or()
skylib.
Anda dapat menyatakan kompatibilitas terbalik dengan cara yang sama. Contoh berikut menjelaskan library yang kompatibel dengan semua hal, kecuali untuk ARM.
cc_library(
name = "non_arm_lib",
srcs = ["non_arm_lib.cc"],
target_compatible_with = select({
"@platforms//cpu:arm": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
)
Mendeteksi target yang tidak kompatibel menggunakan bazel cquery
Anda dapat menggunakan IncompatiblePlatformProvider
dalam format output Starlark bazel cquery
untuk membedakan target yang tidak kompatibel dengan target yang kompatibel.
Ini dapat digunakan untuk memfilter target yang tidak kompatibel. Contoh di bawah ini hanya akan mencetak label untuk target yang kompatibel. Target yang tidak kompatibel tidak akan dicetak.
$ cat example.cquery
def format(target):
if "IncompatiblePlatformProvider" not in providers(target):
return target.label
return ""
$ bazel cquery //... --output=starlark --starlark:file=example.cquery
Masalah Umum
Target yang tidak kompatibel akan mengabaikan pembatasan visibilitas.