Bazel dapat membuat dan menguji kode pada berbagai perangkat keras, sistem operasi, dan konfigurasi sistem, menggunakan berbagai versi alat build seperti penaut dan compiler. Untuk membantu mengelola kerumitan ini, Bazel memiliki konsep batasan dan platform. Batasan adalah dimensi di mana membangun atau lingkungan production mungkin berbeda, seperti arsitektur CPU, keberadaan atau tidak adanya GPU, atau versi kompilator yang diinstal di sistem. Platform adalah kumpulan nama dari pilihan untuk batasan ini, yang mewakili resource yang tersedia di beberapa lingkungan.
Pemodelan lingkungan sebagai platform membantu Bazel untuk otomatis memilih sesuai toolchain untuk tindakan build. Platform ini juga dapat digunakan bersama config_setting aturan untuk menulis atribut yang dapat dikonfigurasi.
Bazel mengenali tiga peran yang mungkin dilayani oleh platform:
- Host - platform tempat Bazel berjalan.
- Execution - platform tempat alat build mengeksekusi tindakan build untuk menghasilkan output perantara atau output akhir.
- Target - platform tempat output akhir berada dan dieksekusi.
Bazel mendukung skenario build berikut terkait platform:
Build satu platform (default) - platform host, eksekusi, dan target sama saja. Misalnya, membangun {i>executable<i} Linux 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 multi-platform - platform host, eksekusi, dan target berbeda.
Menentukan batasan dan platform
Ruang dari pilihan yang memungkinkan untuk platform ditentukan dengan menggunakan
constraint_setting
dan
Aturan constraint_value
dalam file BUILD
.
constraint_setting
membuat dimensi baru, sedangkan
constraint_value
membuat nilai baru untuk dimensi tertentu; bersama-sama mereka
secara efektif menentukan enum dan nilai-nilainya. Misalnya,
cuplikan file BUILD
memperkenalkan 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 didefinisikan di seluruh paket yang berbeda dalam Workspace. Daftar tersebut direferensikan oleh label dan bergantung pada visibilitas biasa kontrol. Jika visibilitas memungkinkan, Anda dapat memperluas setelan batasan yang ada dengan mendefinisikan nilai Anda sendiri.
Aturan platform
memperkenalkan platform baru dengan
pilihan nilai kendala tertentu. Tujuan
berikut membuat platform bernama linux_x86
, dan menjelaskan bahwa setiap
yang menjalankan sistem operasi Linux
pada arsitektur x86_64 dengan
Versi glibc 2.25. (Lihat di bawah untuk 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 secara umum berguna
Untuk menjaga ekosistem yang konsisten, tim Bazel memelihara repositori dengan definisi batasan untuk arsitektur dan operasi CPU yang paling populer, yang berbeda. Semua ini terletak di https://github.com/bazelbuild/platforms.
Bazel mengirimkan definisi platform khusus berikut:
@local_config_platform//:host
. Ini adalah nilai platform host yang terdeteksi otomatis -
mewakili platform yang terdeteksi otomatis
untuk sistem yang dijalankan Bazel.
Menentukan platform untuk build
Anda dapat menentukan platform host dan target untuk build menggunakan flag command line:
--host_platform
- default ke@local_config_platform//:host
@local_config_platform
adalah aturan repositori yang mendeteksi OS host dan CPU dan menulis target platform.- Kode ini juga membuat
@local_config_platform//:constraintz.bzl
, yang mengekspos array yang disebutHOST_CONSTRAINTS
, yang dapat digunakan dalam build lain dan File Starlark.
--platforms
- default ke platform host- Ini berarti bahwa ketika tidak
ada penanda lain yang diatur,
@local_config_platform//:host
adalah platform target. - Jika
--host_platform
ditetapkan dan bukan--platforms
, nilai--host_platform
merupakan host dan platform target.
- Ini berarti bahwa ketika tidak
ada penanda lain yang diatur,
Melewati target yang tidak kompatibel
Saat membangun untuk platform target tertentu, sebaiknya lewati
target yang tidak akan pernah
berhasil di platform tersebut. Misalnya, perangkat Windows Anda
kemungkinan besar akan menghasilkan banyak {i>
error<i} kompiler saat membangun pada
Mesin Linux dengan //...
. Gunakan
target_compatible_with
untuk memberi tahu Bazel tentang batasan platform target apa yang dimiliki kode Anda.
Penggunaan paling sederhana dari atribut ini membatasi target ke satu platform.
Target tidak akan dibuat untuk platform apa pun yang tidak memenuhi semua
batasan data. Contoh berikut membatasi win_driver_lib.cc
ke 64-bit
Windows.
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 membuat aplikasi 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 akan dianggap
dan tidak kompatibel.
Kapan target dilewati?
Target dilewati jika dianggap tidak kompatibel dan disertakan dalam sebagai bagian dari perluasan pola target. Misalnya, dua kode berikut panggilan 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 di test_suite
ditetapkan
juga dilewati jika test_suite
ditentukan pada command line dengan
--expand_test_suites
.
Dengan kata lain, target test_suite
pada command line berperilaku seperti :all
dan
...
. Menggunakan --noexpand_test_suites
akan mencegah perluasan dan penyebab
test_suite
target dengan pengujian yang tidak kompatibel juga tidak kompatibel.
Menentukan secara eksplisit target yang tidak kompatibel pada baris perintah 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 otomatis dilewati 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 dipenuhi oleh platform.
Gunakan select()
bersama dengan
@platforms//:incompatible
untuk mengekspresikan pembatasan yang lebih rumit. Sebagai
misalnya, gunakan untuk mengimplementasikan logika OR dasar. Parameter berikut menandai library
kompatibel dengan macOS dan Linux, tetapi tidak ada 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 apa pun, targetnya adalah dianggap tidak kompatibel.
Untuk membuat batasan Anda lebih mudah dibaca, gunakan
skylib
selects.with_or()
Anda dapat mengekspresikan kompatibilitas terbalik dengan cara yang sama. Contoh berikut menjelaskan library yang kompatibel dengan apa saja, 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 output Starlark bazel cquery
format untuk membedakan
target yang tidak kompatibel
dari target yang kompatibel.
Ini dapat digunakan untuk memfilter target yang tidak kompatibel. Contoh di bawah ini akan hanya mencetak label untuk target yang kompatibel. Target yang tidak kompatibel adalah tidak 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 abaikan visibilitas batasan.