Membangun dengan Platform

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

Halaman ini merangkum kegunaan platform dan menunjukkan cara membangun dengan platform tersebut.

tl;dr: API platform dan toolchain Bazel tersedia, tetapi tidak akan berfungsi di mana saja 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 ini untuk mengetahui tempat yang cocok untuk build Anda.

Untuk dokumentasi yang lebih formal, lihat:

Latar belakang

Platform dan toolchain diperkenalkan untuk menstandarkan cara project software menarget komputer yang berbeda dan mem-build dengan alat bahasa yang tepat.

Ini adalah fitur yang relatif baru untuk Bazel. Kami terinspirasi oleh pengamatan bahwa pengelola bahasa sudah melakukan hal ini secara ad hoc dan tidak kompatibel. Misalnya, aturan C++ menggunakan --cpu dan --crosstool_top untuk menyetel toolchain C++ dan CPU target build. Tak satu pun dari ini yang benar-benar memodelkan "platform". Upaya bersejarah 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 multi-platform yang besar dan multi-bahasa. Hal ini memerlukan dukungan yang lebih berprinsip untuk konsep tersebut, termasuk API jelas yang mendorong interoperabilitas bahasa dan project. Inilah kegunaan API baru ini.

Migrasi

API platform dan toolchain hanya berfungsi saat project benar-benar menggunakannya. Hal ini bukanlah sepele karena logika aturan project, toolchain, dependensi, dan select() harus mendukungnya. Hal ini memerlukan urutan migrasi yang cermat untuk menjaga semua project dan dependensinya berfungsi dengan benar.

Misalnya, Aturan C++ Bazel mendukung platform. Namun, Aturan Apple tidak. Project C++ Anda mungkin tidak memerlukan Apple. Tetapi yang lain mungkin saja. Jadi, masih belum aman untuk mengaktifkan platform secara global untuk semua build C++.

Bagian selanjutnya dari halaman ini menjelaskan urutan migrasi ini serta bagaimana dan kapan project Anda dapat disesuaikan.

Sasaran

Migrasi platform Bazel akan selesai ketika semua project di-build menggunakan formulir:

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

Hal ini menyiratkan:

  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. Salah satu project bergantung pada dukungan Anda //:myplatform atau project Anda mendukung API lama (seperti --crosstool_top).
  4. //:myplatform merujuk [deklarasi umum][Common Platform Declaration]{: .external} dari CPU, OS, dan konsep umum lainnya yang mendukung kompatibilitas lintas project otomatis.
  5. Semua select() project yang relevan 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 suatu tempat yang dapat ditemukan oleh semua project yang mungkin menggunakan platform ini.

API lama akan dihapus segera setelah sasaran ini tercapai. Selanjutnya, langkah ini akan menjadi cara standar project untuk 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, nantinya Anda perlu mendukung API baru. Apakah Anda menunggu sampai migrasi global selesai atau memilih ikut serta lebih awal bergantung pada kebutuhan nilai / biaya spesifik Anda:

Nilai

  • Anda dapat select() atau memilih toolchain pada properti yang diinginkan, bukan flag hard code seperti --cpu. Misalnya, beberapa CPU dapat mendukung set petunjuk yang sama.
  • Build yang lebih tepat. Jika Anda melakukan select() dengan --cpu pada contoh di atas, lalu menambahkan CPU baru yang mendukung kumpulan petunjuk yang sama, select() akan gagal mengenali CPU baru tersebut. Namun, select() di platform tetap akurat.
  • Pengalaman pengguna yang lebih sederhana. Semua project memahami: --platforms=//:myplatform. Tidak perlu beberapa tanda bahasa tertentu pada baris perintah.
  • Desain bahasa yang lebih sederhana. Semua bahasa memiliki API umum yang sama untuk menentukan toolchain, menggunakan toolchain, dan memilih toolchain yang tepat untuk suatu 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 dapat 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 berkembang dan mungkin memerlukan kontribusi awal tambahan.
  • Definisi kanonis untuk toolchain khusus bahasa masih berkembang dan mungkin memerlukan kontribusi awal tambahan.

Peninjauan API

platform adalah kumpulan constraint_value target:

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

constraint_value adalah properti mesin. Nilai "jenis" yang sama dikelompokkan ke dalam constraint_setting yang sama:

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

toolchain adalah aturan Starlark. 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 dijalankan alatnya (exec_compatible_with = ["@platforms//os:mac"]).

Saat mem-build $ bazel build //:myproject --platforms=//:myplatform, Bazel akan otomatis memilih toolchain yang dapat dijalankan di mesin build dan biner build untuk //:myplatform. 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 mempelajari lebih lanjut.

Status

Dukungan platform saat ini bervariasi antarbahasa. Semua aturan utama Bazel berpindah ke platform. Namun, proses ini akan memakan waktu. Ini karena tiga alasan utama:

  1. Logika aturan harus diperbarui untuk mendapatkan info alat dari toolchain API baru (ctx.toolchains) dan berhenti membaca setelan lama seperti --cpu dan --crosstool_top. 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 membuat aplikasi untuk mesin yang sama yang digunakan Bazel). Umumnya, proyek harus menentukan platformnya sendiri.

  3. Project yang sudah ada harus dimigrasikan. select() dan transisi juga harus dimigrasikan. Inilah tantangan terbesar. Hal ini sangat menantang untuk project multibahasa (yang mungkin gagal jika semua bahasa tidak dapat membaca --platforms).

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

Properti platform umum

Properti platform seperti OS dan CPU yang sama di seluruh project harus dideklarasikan di tempat standar dan 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, ini akan memicu mode "arm" dengan kriteria yang tidak kompatibel.

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

Platform default

Umumnya, pemilik project harus menentukan platform eksplisit untuk menjelaskan jenis mesin yang ingin mereka bangun. Hal ini kemudian dipicu dengan --platforms.

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

C++

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

Ini berarti 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 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, proses ini bergantung pada aturan Apple yang bermigrasi ke platform.

Java

Aturan Java Bazel menggunakan platform.

Ini menggantikan tanda lama --java_toolchain, --host_java_toolchain, --javabase, dan --host_javabase.

Untuk mempelajari cara menggunakan tanda konfigurasi, lihat panduan Bazel dan Java. Untuk informasi tambahan, lihat Dokumen desain.

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

Android

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

Opsi ini tidak diaktifkan secara default. Tetapi migrasi akan berjalan dengan baik.

Apel

Aturan Apple Bazel belum mendukung platform untuk memilih toolchain Apple.

Adaptor ini juga tidak mendukung dependensi C++ yang diaktifkan platform karena menggunakan --crosstool_top lama untuk menyetel toolchain C++. Sebelum ini dimigrasikan, Anda dapat menggabungkan project Apple dengan C++ berkemampuan platorm dengan pemetaan platform (contoh).

Bahasa lainnya

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

select()

Project dapat select() pada target constraint_value, tetapi tidak dapat menyelesaikan platform. Hal ini disengaja agar select() mendukung berbagai mesin sebanyak mungkin. Library dengan sumber khusus ARM harus mendukung semua mesin yang didukung ARM kecuali ada alasan yang lebih spesifik.

Untuk memilih di satu atau beberapa constraint_value, gunakan:

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

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

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

Lihat detail selengkapnya di sini.

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

Transisi

Perubahan Transisi Starlark akan menandai bagian-bagian grafik build Anda ke bawah. Jika project Anda menggunakan transisi yang menetapkan --cpu, --crossstool_top, atau tanda 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" } menjadi return { "//command_line_option:platforms": "//:my_arm_platform" } atau menggunakan pemetaan platform untuk mendukung kedua gaya melalui jendela migrasi.

Cara menggunakan platform saat ini

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

Jika Anda adalah pengelola project, bahasa, atau toolchain dan build 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 pedulikan memiliki pekerjaan.

  2. Jika project yang Anda perlukan masih bergantung pada tanda lama seperti --cpu dan --crosstool_top, gunakan keduanya bersama --platforms:

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

    Proses ini memerlukan biaya pemeliharaan (Anda harus memastikan setelannya secara manual sesuai). Namun, hal ini akan berhasil jika tidak ada transisi yang ditolak.

  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 versi lama berdampingan dalam build yang sama melalui jendela penghentian versi lama.

Pemetaan platform adalah peta platform() ke kumpulan tanda 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 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 detail selengkapnya.

Pertanyaan

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

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

Lihat juga