Membangun dengan Platform

Bazel memiliki dukungan canggih untuk memodelkan platform dan toolchain. Mengintegrasikannya dengan project nyata memerlukan kerja sama yang cermat antara pemilik kode, pengelola aturan, dan developer inti Bazel.

Halaman ini merangkum tujuan platform dan menunjukkan cara mem-build dengan platform.

tl;dr: Platform dan toolchain API Bazel tersedia, tetapi tidak akan berfungsi di mana pun hingga semua aturan bahasa, select() dan referensi lama lainnya diupdate. Hal ini akan terus dilakukan. Pada akhirnya, semua build akan berbasis platform. Baca di bawah untuk melihat kesesuaian build Anda.

Untuk dokumentasi yang lebih formal, lihat:

Latar belakang

Platform dan toolchain diperkenalkan untuk menstandarkan cara project software menargetkan berbagai mesin dan mem-build dengan alat bahasa yang tepat.

Ini adalah tambahan yang relatif baru untuk Bazel. Hal ini terinspirasi oleh pengamatan bahwa pengelola bahasa sudah melakukannya dengan cara ad hoc yang tidak kompatibel. Misalnya, aturan C++ menggunakan --cpu dan --crosstool_top untuk menetapkan CPU target dan toolchain C++ build. Tidak ada yang memodelkan "platform" dengan benar. Upaya historis untuk melakukannya menyebabkan build yang canggung dan tidak akurat. Flag ini juga tidak mengontrol kompilasi Java, yang mengembangkan antarmuka independennya sendiri dengan --java_toolchain.

Bazel ditujukan untuk project besar, multi-bahasa, dan multi-platform. Hal ini memerlukan dukungan yang lebih berprinsip untuk konsep ini, termasuk API yang jelas yang mendorong interoperabilitas bahasa dan project. Inilah tujuan API baru ini.

Migrasi

Platform dan toolchain API hanya berfungsi jika project benar-benar menggunakannya. Hal ini tidak mudah karena logika aturan, toolchain, dependensi, dan select() project harus mendukungnya. Hal ini memerlukan urutan migrasi yang cermat agar semua project dan dependensinya berfungsi dengan benar.

Misalnya, Aturan C++ Bazel mendukung platform. Namun, Aturan Apple tidak. Project C++ Anda mungkin tidak peduli dengan Apple. Namun, orang lain mungkin peduli. Jadi, belum aman untuk mengaktifkan platform secara global untuk semua build C++.

Bagian halaman ini menjelaskan urutan migrasi ini serta cara dan waktu project Anda dapat disesuaikan.

Sasaran

Migrasi platform Bazel selesai saat semua project di-build dengan formulir:

bazel build //:myproject --platforms=//:myplatform

Ini berarti bahwa:

  1. Aturan yang digunakan project Anda dapat menyimpulkan toolchain yang benar dari //:myplatform.
  2. Aturan yang digunakan dependensi project Anda dapat menyimpulkan toolchain yang benar dari //:myplatform.
  3. Baik project yang bergantung pada project Anda mendukung //:myplatform atau project Anda mendukung API lama (seperti --crosstool_top).
  4. //:myplatform mereferensikan [deklarasi umum][Common Platform Declaration]{: .external} dari CPU, OS, dan konsep generik lainnya yang mendukung kompatibilitas lintas project otomatis.
  5. `select()` semua project yang relevan select()s memahami properti mesin yang tersirat oleh //:myplatform.
  6. //:myplatform ditentukan di tempat yang jelas dan dapat digunakan kembali: di repo project Anda jika platform tersebut unik untuk project Anda, atau di tempat lain yang dapat ditemukan oleh semua project yang mungkin menggunakan platform ini.

API lama akan dihapus segera setelah sasaran ini tercapai. Kemudian, ini akan menjadi cara standar project memilih platform dan toolchain.

Haruskah saya menggunakan platform?

Jika hanya ingin mem-build atau mengompilasi silang project, Anda harus mengikuti dokumentasi resmi project.

Jika Anda adalah pengelola project, bahasa, atau toolchain, Anda pada akhirnya akan ingin mendukung API baru. Apakah Anda menunggu hingga migrasi global selesai atau memilih untuk ikut serta lebih awal bergantung pada kebutuhan nilai / biaya spesifik Anda:

Nilai

  • Anda dapat select() atau memilih toolchain pada properti yang Anda inginkan, bukan flag yang dikodekan secara permanen seperti --cpu. Misalnya, beberapa CPU dapat mendukung set instruksi yang sama.
  • Build yang lebih benar. Jika Anda select() dengan --cpu dalam contoh di atas, lalu menambahkan CPU baru yang mendukung set instruksi yang sama, select() akan gagal mengenali CPU baru. Namun, select() di platform tetap akurat.
  • Pengalaman pengguna yang lebih sederhana. Semua project memahami: --platforms=//:myplatform. Tidak perlu beberapa flag khusus bahasa di command line.
  • Desain bahasa yang lebih sederhana. Semua bahasa menggunakan API umum untuk menentukan toolchain, menggunakan toolchain, dan memilih toolchain yang tepat untuk platform.
  • Target dapat dilewati dalam fase build dan pengujian jika tidak kompatibel dengan platform target.

Biaya

  • Project dependen yang belum mendukung platform mungkin tidak otomatis berfungsi dengan project Anda.
  • Agar berfungsi, mungkin diperlukan pemeliharaan sementara tambahan.
  • Koeksistensi API baru dan lama memerlukan panduan pengguna yang lebih cermat untuk menghindari kebingungan.
  • Definisi kanonis untuk properti umum seperti OS dan CPU masih terus berkembang dan mungkin memerlukan kontribusi awal tambahan.
  • Definisi kanonis untuk toolchain khusus bahasa masih terus berkembang dan mungkin memerlukan kontribusi awal tambahan.

Peninjauan API

A platform adalah kumpulan target constraint_value:

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

A constraint_value adalah properti mesin. Nilai dari "jenis" yang sama dikelompokkan dalam constraint_setting umum:

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

A toolchain adalah aturan Starlark. Its atributnya mendeklarasikan alat bahasa (seperti compiler = "//mytoolchain:custom_gcc"). Penyedianya meneruskan informasi ini ke aturan yang perlu di-build dengan alat ini.

Toolchain mendeklarasikan constraint_value mesin yang dapat ditargetkan (target_compatible_with = ["@platforms//os:linux"]) dan mesin yang dapat menjalankan alatnya dijalankan (exec_compatible_with = ["@platforms//os:mac"]).

Saat mem-build $ bazel build //:myproject --platforms=//:myplatform, Bazel akan otomatis memilih toolchain yang dapat berjalan di mesin build dan mem-build biner untuk //:myplatform. Hal ini dikenal sebagai resolusi toolchain.

Kumpulan toolchain yang tersedia dapat didaftarkan di WORKSPACE dengan register_toolchains atau di command line dengan --extra_toolchains.

Lihat di sini untuk mengetahui detailnya.

Status

Dukungan platform saat ini bervariasi di antara bahasa. Semua aturan utama Bazel beralih ke platform. Namun, proses ini akan memerlukan waktu. Hal ini karena tiga alasan utama:

  1. Logika aturan harus diupdate untuk mendapatkan info alat dari toolchain API baru (ctx.toolchains) dan berhenti membaca setelan lama seperti --cpu dan --crosstool_top. Hal ini relatif mudah.

  2. Pengelola toolchain harus menentukan toolchain dan membuatnya dapat diakses oleh pengguna (di repositori GitHub dan entri WORKSPACE). Secara teknis, hal ini mudah, tetapi harus diatur dengan cerdas untuk mempertahankan pengalaman pengguna yang mudah.

    Definisi platform juga diperlukan (kecuali jika Anda mem-build untuk mesin yang sama dengan Bazel). Umumnya, project harus menentukan platformnya sendiri.

  3. Project yang ada harus dimigrasikan. select() dan transisi juga harus di migrasikan. Ini adalah tantangan terbesar. Hal ini sangat menantang untuk project multi-bahasa (yang mungkin gagal jika semua bahasa tidak dapat membaca --platforms).

Jika mendesain kumpulan aturan baru, Anda harus mendukung platform sejak awal. Hal ini akan otomatis membuat aturan Anda kompatibel dengan aturan dan project lain, dengan nilai yang meningkat seiring dengan semakin banyaknya penggunaan platform API.

Properti platform umum

Properti platform seperti OS dan CPU yang umum di seluruh project harus dideklarasikan di tempat standar yang terpusat. Hal ini mendorong kompatibilitas lintas project dan lintas bahasa.

Misalnya, jika MyApp memiliki select() di constraint_value @myapp//cpus:arm dan SomeCommonLib memiliki select() di @commonlib//constraints:arm, keduanya akan memicu mode "arm" dengan kriteria yang tidak kompatibel.

Properti yang umum secara global dideklarasikan di repo @platforms (sehingga label kanonis untuk contoh di atas adalah @platforms//cpu:arm). Properti yang umum untuk bahasa harus dideklarasikan di repo bahasa masing-masing.

Platform default

Umumnya, pemilik project harus menentukan platform eksplisit untuk menjelaskan jenis mesin yang ingin mereka build. Kemudian, platform ini akan dipicu dengan --platforms.

Jika --platforms tidak ditetapkan, Bazel akan menggunakan platform default yang mewakili mesin build lokal. Platform ini dibuat secara otomatis di @local_config_platform//:host sehingga Anda tidak perlu menentukannya secara eksplisit. Platform ini memetakan OS dan CPU mesin lokal dengan constraint_values yang dideklarasikan di @platforms.

C++

Aturan C++ Bazel menggunakan platform untuk memilih toolchain saat Anda menetapkan --incompatible_enable_cc_toolchain_resolution (#7260).

Artinya, Anda dapat mengonfigurasi project C++ dengan:

bazel build //:my_cpp_project --platforms=//:myplatform

bukan yang lama:

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

Jika project Anda adalah C++ murni dan tidak bergantung pada project non-C++, Anda dapat menggunakan platform dengan aman selama select dan transisi Anda kompatibel. Lihat #7260 dan Mengonfigurasi toolchain C++ untuk panduan selengkapnya.

Mode ini tidak diaktifkan secara default. Hal ini karena project Apple masih mengonfigurasi dependensi C++ dengan --cpu dan --crosstool_top (contoh). Jadi, hal ini bergantung pada migrasi aturan Apple ke platform.

Java

Aturan Java Bazel menggunakan platform.

Hal ini menggantikan flag lama --java_toolchain, --host_java_toolchain, --javabase, dan --host_javabase.

Untuk mempelajari cara menggunakan flag konfigurasi, lihat manual Bazel dan Java. Untuk informasi tambahan, lihat Dokumen desain.

Jika Anda masih menggunakan flag lama, ikuti proses migrasi di Masalah #7849.

Android

Aturan Android Bazel menggunakan platform untuk memilih toolchain saat Anda menetapkan --incompatible_enable_android_toolchain_resolution.

Fitur ini tidak diaktifkan secara default. Namun, migrasi sudah berjalan dengan baik.

Apple

Aturan Apple Bazel belum mendukung platform untuk memilih toolchain Apple.

Aturan ini juga tidak mendukung dependensi C++ yang diaktifkan platform karena menggunakan --crosstool_top lama untuk menetapkan toolchain C++. Hingga dimigrasikan, Anda dapat menggabungkan project Apple dengan C++ yang diaktifkan platform dengan pemetaan platform (contoh).

Bahasa lainnya

  • Aturan Rust Bazel sepenuhnya mendukung platform.
  • Aturan Go Bazel sepenuhnya mendukung platform (detail).

Jika mendesain aturan untuk bahasa baru, gunakan platform untuk memilih toolchain bahasa Anda. Lihat dokumentasi toolchain untuk panduan yang baik.

select()

Project dapat select() pada constraint_value target tetapi tidak pada platform lengkap. Hal ini disengaja agar select() mendukung variasi mesin seluas mungkin. Library dengan sumber khusus ARM harus mendukung semua mesin yang didukung ARM kecuali jika ada alasan untuk lebih spesifik.

Untuk memilih satu atau beberapa constraint_value, gunakan:

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

Hal ini setara dengan memilih secara tradisional di --cpu:

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

Informasi selengkapnya di sini.

select di --cpu, --crosstool_top, dll. tidak memahami --platforms. Saat memigrasikan project ke platform, Anda harus mengonversinya ke constraint_values atau menggunakan pemetaan platform untuk mendukung kedua gaya selama periode migrasi.

Transisi

Transisi Starlark mengubah flag di bagian bawah grafik build Anda. Jika project Anda menggunakan transisi yang menetapkan --cpu, --crossstool_top, atau flag lama lainnya, aturan yang membaca --platforms tidak akan melihat perubahan ini.

Saat memigrasikan project ke platform, Anda harus mengonversi perubahan seperti return { "//command_line_option:cpu": "arm" } ke return { "//command_line_option:platforms": "//:my_arm_platform" } atau menggunakan pemetaan platform untuk mendukung kedua gaya selama periode migrasi window.

Cara menggunakan platform saat ini

Jika hanya ingin mem-build atau mengompilasi silang project, Anda harus mengikuti dokumentasi resmi project. Pengelola bahasa dan project harus menentukan cara dan waktu untuk berintegrasi dengan platform, serta nilai yang ditawarkan.

Jika Anda adalah pengelola project, bahasa, atau toolchain dan build Anda tidak menggunakan platform secara default, Anda memiliki tiga opsi (selain menunggu migrasi global):

  1. Aktifkan flag "gunakan platform" untuk bahasa project Anda (jika ada) dan lakukan pengujian apa pun yang diperlukan untuk melihat apakah project yang Anda inginkan berfungsi.

  2. Jika project yang Anda inginkan masih bergantung pada flag lama seperti --cpu dan --crosstool_top, gunakan flag ini bersama dengan --platforms:

    bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...

    Hal ini memiliki biaya pemeliharaan (Anda harus memastikan setelan cocok secara manual). Namun, hal ini akan berfungsi jika tidak ada transisi yang tidak sah.

  3. Tulis pemetaan platform untuk mendukung kedua gaya dengan memetakan setelan gaya --cpu ke platform yang sesuai dan sebaliknya.

Pemetaan platform

Pemetaan platform adalah API sementara yang memungkinkan logika yang didukung platform dan yang didukung lama dapat berdampingan dalam build yang sama melalui periode penghentian penggunaan yang terakhir.

Pemetaan platform adalah peta platform() ke kumpulan flag lama yang sesuai atau sebaliknya. Contoh:

platforms:
  # Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
  //platforms:ios
    --cpu=ios_x86_64
    --apple_platform_type=ios

flags:
  # Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
  --cpu=ios_x86_64
  --apple_platform_type=ios
    //platforms:ios

  # Maps "--cpu=darwin --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin
  --apple_platform_type=macos
    //platforms:macos

Bazel menggunakan pemetaan ini untuk menjamin semua setelan, baik berbasis platform maupun lama, diterapkan secara konsisten di seluruh build, termasuk melalui transisi.

Secara default, Bazel membaca pemetaan dari file platform_mappings di root ruang kerja Anda. Anda juga dapat menetapkan --platform_mappings=//:my_custom_mapping.

Lihat di sini untuk mengetahui detail lengkapnya.

Pertanyaan

Untuk dukungan umum dan pertanyaan tentang linimasa migrasi, hubungi bazel-discuss@googlegroups.com atau pemilik aturan yang sesuai.

Untuk diskusi tentang desain dan evolusi platform/toolchain API, hubungi bazel-dev@googlegroups.com.

Lihat juga