Platform

Laporkan masalah Lihat sumber Per Malam · 7,2 · 7,1 · 7,0 · 6,5 · 6,4

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 @bazel_tools//platforms:host_platform
  • --platforms - default ke @bazel_tools//platforms:target_platform

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

Batasan yang lebih ekspresif

Untuk fleksibilitas yang lebih besar dalam mengekspresikan batasan, gunakan @platforms//:incompatible constraint_value yang tidak memiliki platform memuaskan.

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:

  1. Saat menargetkan macOS, target tidak memiliki batasan.
  2. Saat menargetkan Linux, target tidak memiliki batasan.
  3. 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 semua jenis aplikasi, 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.