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 mengelola kompleksitas ini, Bazel memiliki konsep batasan dan platform. Batasan adalah dimensi yang dapat membedakan lingkungan build atau produksi, seperti arsitektur CPU, keberadaan 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 beberapa lingkungan.
Memodelkan lingkungan sebagai platform membantu Bazel memilih toolchain yang sesuai untuk tindakan build secara otomatis. Platform juga dapat digunakan bersama dengan aturan config_setting untuk menulis atribut yang dapat dikonfigurasi.
Bazel mengenali tiga peran yang dapat digunakan oleh platform:
- Host - platform tempat Bazel berjalan.
- Eksekusi - platform tempat alat build menjalankan tindakan build untuk menghasilkan output perantara 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 executable Linux di Ubuntu yang berjalan di CPU Intel x64.
Build kompilasi silang - platform host dan eksekusi sama, tetapi platform target berbeda. Misalnya, mem-build aplikasi iOS di macOS yang berjalan di MacBook Pro.
Build multi-platform - platform host, eksekusi, dan target semuanya berbeda.
Menentukan batasan dan platform
Ruang pilihan yang mungkin untuk platform ditentukan dengan menggunakan aturan
constraint_setting dan
constraint_value dalam file BUILD.
constraint_setting membuat dimensi baru, sedangkan constraint_value membuat nilai baru untuk dimensi tertentu; keduanya secara efektif menentukan enum dan nilai yang mungkin. Misalnya, cuplikan file BUILD berikut memperkenalkan batasan untuk versi glibc sistem dengan dua nilai yang mungkin.
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. Batasan dan nilainya direferensikan berdasarkan label dan tunduk pada kontrol visibilitas biasa. Jika visibilitas memungkinkan, Anda dapat memperluas setelan batasan yang ada dengan menentukan nilai Anda sendiri untuk setelan tersebut.
Aturan platform memperkenalkan platform baru dengan
pilihan nilai batasan tertentu. Berikut ini 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 informasi 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
Untuk menjaga konsistensi ekosistem, tim Bazel mengelola repositori dengan definisi batasan untuk arsitektur CPU dan sistem operasi yang paling populer. Semua definisi batasan ini terletak di https://github.com/bazelbuild/platforms.
Bazel dilengkapi dengan definisi platform khusus berikut: @platforms//host (diberi alias sebagai @bazel_tools//tools:host_platform). Ini adalah nilai platform host yang terdeteksi otomatis - mewakili platform yang terdeteksi otomatis untuk sistem tempat Bazel berjalan.
Menentukan platform untuk build
Anda dapat menentukan platform host dan target untuk build menggunakan tanda command line berikut:
--host_platform- defaultnya adalah@bazel_tools//tools:host_platform- Target ini diberi alias 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 mengekspos array bernamaHOST_CONSTRAINTS, yang dapat digunakan di file BUILD dan Starlark lainnya.
- Target ini diberi alias ke
--platforms- defaultnya adalah platform host- Artinya, jika tidak ada tanda lain yang ditetapkan,
@platforms//hostadalah platform target. - Jika
--host_platformditetapkan dan bukan--platforms, nilai--host_platformadalah platform host dan target.
- Artinya, jika tidak ada tanda lain yang ditetapkan,
Melewati target yang tidak kompatibel
Saat mem-build untuk platform target tertentu, sering kali Anda ingin melewati target yang tidak akan pernah berfungsi di platform tersebut. Misalnya, driver perangkat Windows Anda kemungkinan akan menghasilkan banyak error compiler saat mem-build di mesin Linux dengan //.... Gunakan atribut
target_compatible_with
untuk memberi tahu Bazel batasan platform target yang dimiliki kode Anda.
Penggunaan atribut ini yang paling sederhana adalah membatasi target ke satu platform.
Target tidak akan di-build untuk platform apa pun yang tidak memenuhi semua batasan. Contoh berikut membatasi win_driver_lib.cc ke 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 mem-build dengan Windows 64-bit dan tidak kompatibel dengan yang lainnya. Inkompatibilitas bersifat transitif. Target apa pun yang bergantung secara transitif pada target yang tidak kompatibel juga 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 yang tidak kompatibel yang ditemukan dalam perluasan pola target.
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
Pengujian yang tidak kompatibel dalam test_suite juga dilewati jika test_suite ditentukan di command line dengan
--expand_test_suites.
Dengan kata lain, target test_suite di command line berperilaku seperti :all dan .... Menggunakan --noexpand_test_suites akan mencegah perluasan dan menyebabkan
test_suite target dengan pengujian yang tidak kompatibel juga tidak kompatibel.
Menentukan target yang tidak kompatibel secara eksplisit di 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 secara diam-diam jika --skip_incompatible_explicit_targets diaktifkan.
Batasan yang lebih ekspresif
Untuk lebih fleksibel dalam mengekspresikan batasan, gunakan yang tidak memenuhi platform.@platforms//:incompatibleconstraint_value
Gunakan select() bersama dengan
@platforms//:incompatible untuk mengekspresikan batasan yang lebih rumit. Misalnya, gunakan untuk menerapkan logika OR dasar. Berikut ini 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 diinterpretasikan 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//:incompatiblebukan bagian dari platform mana pun, target dianggap tidak kompatibel.
Untuk membuat batasan Anda lebih mudah dibaca, gunakan
skylib's
selects.with_or().
Anda dapat mengekspresikan kompatibilitas terbalik dengan cara yang sama. Contoh berikut menjelaskan library yang kompatibel dengan semuanya kecuali 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 bazel cquery's format output Starlark untuk membedakan target yang tidak kompatibel dari target yang kompatibel.
Hal ini dapat digunakan untuk memfilter target yang tidak kompatibel. Contoh di bawah 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 mengabaikan visibilitas batasan.