Platform

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 dengan lingkungan build atau produksi yang mungkin berbeda, seperti arsitektur CPU, keberadaan atau ketiadaan GPU, atau versi compiler yang diinstal sistem. Platform adalah kumpulan pilihan bernama untuk batasan ini, yang mewakili resource tertentu yang tersedia di lingkungan tertentu.

Pemodelan lingkungan sebagai platform membantu Bazel secara otomatis memilih toolchain yang sesuai untuk tindakan build. Platform juga dapat digunakan bersama dengan aturan config_setting untuk menulis atribut yang dapat dikonfigurasi.

Bazel mengenali tiga peran yang mungkin dijalankan oleh platform:

  • Host - platform tempat Bazel berjalan.
  • Execution - platform tempat alat build mengeksekusi tindakan build untuk menghasilkan output menengah dan akhir.
  • Target - platform tempat output akhir berada dan dijalankan.

Bazel mendukung skenario build berikut terkait platform:

  • Build platform tunggal (default) - host, eksekusi, dan platform target sama. Misalnya, mem-build file Linux yang dapat dieksekusi di Ubuntu yang berjalan pada 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 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 ditentukan di berbagai paket yang berbeda 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 sendiri untuknya.

Aturan platform memperkenalkan platform baru dengan pilihan tertentu untuk nilai batasan. Yang berikut membuat platform bernama linux_x86, dan menyatakan bahwa platform tersebut menjelaskan semua lingkungan yang menjalankan sistem operasi Linux pada arsitektur x86_64 dengan versi glibc 2,25. (Lihat di bawah ini 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

Agar ekosistem tetap konsisten, tim Bazel mengelola repositori dengan definisi batasan untuk arsitektur CPU dan sistem operasi paling populer. Semuanya terletak di https://github.com/bazelbuild/platforms.

Bazel dilengkapi dengan definisi platform khusus berikut: @local_config_platform//:host. 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//platforms:host_platform
  • --platforms - defaultnya adalah @bazel_tools//platforms:target_platform

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 mem-build di mesin Linux dengan //.... Gunakan atribut target_compatible_with untuk memberi tahu Bazel tentang batasan platform target yang dimiliki kode Anda.

Penggunaan paling sederhana atribut ini 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 mem-build aplikasi dengan Windows 64-bit dan tidak kompatibel dengan yang lainnya. Inkompatibilitas bersifat transitif. Setiap target yang secara transitif bergantung pada target yang tidak kompatibel akan dianggap tidak kompatibel.

Kapan target dilewati?

Target akan dilewatkan jika dianggap tidak kompatibel dan disertakan dalam build sebagai bagian dari perluasan pola target. Misalnya, dua pemanggilan berikut melewati target 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 pada 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 target test_suite dengan pengujian yang tidak kompatibel juga menjadi tidak kompatibel.

Menentukan secara eksplisit target yang tidak kompatibel 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

Batasan yang lebih ekspresif

Agar lebih fleksibel 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 untuk mengimplementasikan logika ATAU dasar. Kode berikut menandai library yang kompatibel dengan macOS dan Linux, tetapi tidak dengan platform lainnya.

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:

  1. Saat menargetkan macOS, target tidak memiliki batasan.
  2. Saat menargetkan Linux, target tidak memiliki batasan.
  3. Jika tidak, target akan memiliki batasan @platforms//:incompatible. Karena @platforms//:incompatible bukan bagian dari platform apa 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 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 pembatasan visibilitas.