Bazel has sophisticated support for modeling platforms and toolchains for multi-architecture and cross-compiled builds.
Trang này tóm tắt trạng thái của tính năng hỗ trợ này.
Xem thêm:
Trạng thái
C++
Các quy tắc C++ sử dụng nền tảng để chọn chuỗi công cụ khi
--incompatible_enable_cc_toolchain_resolution được đặt.
Điều này có nghĩa là bạn có thể định cấu hình một dự án C++ bằng:
bazel build //:my_cpp_project --platforms=//:myplatformthay vì:
bazel build //:my_cpp_project` --cpu=... --crosstool_top=... --compiler=...Tính năng này sẽ được bật theo mặc định trong Bazel 7.0 (#7260).
Để kiểm thử dự án C++ bằng nền tảng, hãy xem bài viết Di chuyển dự án và Định cấu hình chuỗi công cụ C++.
Java
Các quy tắc Java sử dụng nền tảng để chọn chuỗi công cụ.
Điều này sẽ thay thế các cờ cũ --java_toolchain, --host_java_toolchain,
--javabase và --host_javabase.
Hãy xem bài viết Java và Bazel để biết thông tin chi tiết.
Android
Các quy tắc Android sử dụng nền tảng để chọn chuỗi công cụ khi
--incompatible_enable_android_toolchain_resolution được đặt.
Điều này có nghĩa là bạn có thể định cấu hình một dự án Android bằng:
bazel build //:my_android_project --android_platforms=//:my_android_platformthay vì sử dụng các cờ cũ như --android_crosstool_top, --android_cpu,
và --fat_apk_cpu.
Tính năng này sẽ được bật theo mặc định trong Bazel 7.0 (#16285).
Để kiểm thử dự án Android bằng nền tảng, hãy xem bài viết Di chuyển dự án.
Apple
Các quy tắc Apple không hỗ trợ nền tảng và chưa được lên lịch hỗ trợ.
Bạn vẫn có thể sử dụng API nền tảng với các bản dựng Apple (ví dụ: khi tạo bằng hỗn hợp các quy tắc Apple và C++ thuần tuý) bằng cách sử dụng các bản đồ nền tảng.
Ngôn ngữ khác
- Các quy tắc Go hỗ trợ đầy đủ nền tảng
- Các quy tắc Rust hỗ trợ đầy đủ nền tảng.
Nếu bạn sở hữu một bộ quy tắc ngôn ngữ, hãy xem bài viết Di chuyển bộ quy tắc để thêm tính năng hỗ trợ.
Thông tin cơ bản
Nền tảng và chuỗi công cụ được giới thiệu để chuẩn hoá cách các dự án phần mềm nhắm mục tiêu đến các kiến trúc khác nhau và biên dịch chéo.
Điều này được
lấy cảm hứng
từ việc quan sát thấy rằng những người duy trì ngôn ngữ đã thực hiện việc này theo những cách đặc
biệt, không tương thích. Ví dụ: các quy tắc C++ sử dụng --cpu và
--crosstool_top để khai báo CPU và chuỗi công cụ mục tiêu. Không có quy tắc nào trong số này
mô hình hoá chính xác một "nền tảng". Điều này tạo ra các bản dựng không chính xác và khó xử.
Java, Android và các ngôn ngữ khác đã phát triển các cờ riêng cho các mục đích tương tự, không có cờ nào tương tác với nhau. Điều này khiến các bản dựng đa ngôn ngữ trở nên khó hiểu và phức tạp.
Bazel được thiết kế cho các dự án lớn, đa ngôn ngữ và đa nền tảng. Điều này đòi hỏi sự hỗ trợ có nguyên tắc hơn cho các khái niệm này, bao gồm cả API tiêu chuẩn rõ ràng.
Cần di chuyển
Việc nâng cấp lên API mới đòi hỏi 2 nỗ lực: phát hành API và nâng cấp logic quy tắc để sử dụng API đó.
Nỗ lực đầu tiên đã hoàn tất nhưng nỗ lực thứ hai vẫn đang diễn ra. Nỗ lực này bao gồm việc đảm bảo
xác định các nền tảng và chuỗi công cụ dành riêng cho ngôn ngữ, logic ngôn ngữ đọc
chuỗi công cụ thông qua API mới thay vì các cờ cũ như --crosstool_top và
config_setting chọn trên API mới thay vì các cờ cũ.
Công việc này rất đơn giản nhưng đòi hỏi nỗ lực riêng biệt cho từng ngôn ngữ, cộng với cảnh báo công bằng cho chủ sở hữu dự án để kiểm thử các thay đổi sắp tới.
Đây là lý do quá trình di chuyển này đang diễn ra.
Mục tiêu
Quá trình di chuyển này hoàn tất khi tất cả các dự án tạo bằng biểu mẫu:
bazel build //:myproject --platforms=//:myplatformĐiều này ngụ ý:
- Các quy tắc của dự án chọn đúng chuỗi công cụ cho
//:myplatform. - Các phần phụ thuộc của dự án chọn đúng chuỗi công cụ cho
//:myplatform. //:myplatformtham chiếu các khai báo chung củaCPU,OS, và các thuộc tính chung, độc lập với ngôn ngữ khác- Tất cả
select()có liên quan đều khớp đúng với//:myplatform. //:myplatformđược xác định ở một vị trí rõ ràng, dễ truy cập: trong kho lưu trữ của dự án nếu nền tảng là duy nhất đối với dự án của bạn hoặc một vị trí chung nào đó mà tất cả các dự án tiêu thụ đều có thể tìm thấy
Các cờ cũ như --cpu, --crosstool_top và --fat_apk_cpu sẽ bị
ngừng sử dụng và xoá ngay khi an toàn để thực hiện.
Cuối cùng, đây sẽ là cách duy nhất để định cấu hình kiến trúc.
Di chuyển dự án
Nếu bạn tạo bằng các ngôn ngữ hỗ trợ nền tảng, thì bản dựng của bạn sẽ hoạt động với một lệnh gọi như:
bazel build //:myproject --platforms=//:myplatformHãy xem phần Trạng thái và tài liệu của ngôn ngữ để biết thông tin chi tiết chính xác.
Nếu một ngôn ngữ yêu cầu một cờ để bật tính năng hỗ trợ nền tảng, bạn cũng cần đặt cờ đó. Hãy xem phần Trạng thái để biết thông tin chi tiết.
Để dự án của bạn tạo, bạn cần kiểm tra những điều sau:
//:myplatformphải tồn tại. Thông thường, chủ sở hữu dự án có trách nhiệm xác định nền tảng vì các dự án khác nhau nhắm mục tiêu đến các máy khác nhau. Hãy xem phần Nền tảng mặc định.Các chuỗi công cụ bạn muốn sử dụng phải tồn tại. Nếu sử dụng chuỗi công cụ chứng khoán, thì các chủ sở hữu ngôn ngữ phải đưa ra hướng dẫn về cách đăng ký các chuỗi công cụ đó. Nếu viết chuỗi công cụ tuỳ chỉnh của riêng mình, bạn cần đăng ký các chuỗi công cụ đó trong tệp
MODULE.bazelhoặc bằng--extra_toolchains.select()s và quá trình chuyển đổi cấu hình phải phân giải đúng cách. Hãy xem phần select() và Kiểu chuyển cảnh.Nếu bản dựng của bạn kết hợp các ngôn ngữ hỗ trợ và không hỗ trợ nền tảng, thì bạn có thể cần các bản đồ nền tảng để giúp các ngôn ngữ cũ hoạt động với API mới. Hãy xem phần Bản đồ nền tảng để biết thông tin chi tiết.
Nếu bạn vẫn gặp vấn đề, hãy liên hệ để được hỗ trợ.
Nền tảng mặc định
Chủ sở hữu dự án nên xác định các
nền tảng rõ ràng để mô tả các kiến trúc
mà họ muốn tạo. Sau đó, các nền tảng này được kích hoạt bằng --platforms.
Khi --platforms không được đặt, Bazel sẽ mặc định là platform đại diện cho
máy tạo cục bộ. Nền tảng này được tạo tự động tại @platforms//host (được đặt bí danh là
@bazel_tools//tools:host_platform)
nên bạn không cần xác định rõ ràng. Nền tảng này liên kết OS
và CPU của máy cục bộ với constraint_value được khai báo trong
@platforms.
select()
Các dự án có thể select() trên
constraint_value các mục tiêu nhưng không hoàn tất
nền tảng. Đây là mục đích để select() hỗ trợ nhiều loại
máy nhất có thể. Thư viện có các nguồn dành riêng cho ARM phải hỗ trợ tất cả
các máy chạy ARM trừ phi có lý do để cụ thể hơn.
Để chọn một hoặc nhiều constraint_value, hãy sử dụng:
config_setting(
name = "is_arm",
constraint_values = [
"@platforms//cpu:arm",
],
)
Điều này tương đương với việc chọn theo truyền thống trên --cpu:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
Xem thêm chi tiết tại đây.
select trên --cpu, --crosstool_top, v.v. không hiểu --platforms.
Khi di chuyển dự án sang nền tảng, bạn phải chuyển đổi các nền tảng đó thành
constraint_values hoặc sử dụng bản đồ nền tảng để hỗ trợ
cả hai kiểu trong quá trình di chuyển.
Kiểu chuyển cảnh
Quá trình chuyển đổi Starlark thay đổi
các cờ xuống các phần của biểu đồ bản dựng. Nếu dự án của bạn sử dụng quá trình chuyển đổi đặt --cpu, --crossstool_top hoặc các cờ cũ khác, thì các quy tắc đọc --platforms sẽ không thấy những thay đổi này.
Khi di chuyển dự án sang nền tảng, bạn phải chuyển đổi các thay đổi như
return { "//command_line_option:cpu": "arm" } thành return {
"//command_line_option:platforms": "//:my_arm_platform" } hoặc sử dụng bản đồ
nền tảng để hỗ trợ cả hai kiểu trong quá trình di chuyển.
window.
Di chuyển bộ quy tắc
Nếu sở hữu một bộ quy tắc và muốn hỗ trợ nền tảng, bạn cần:
Có logic quy tắc phân giải chuỗi công cụ bằng API chuỗi công cụ. Xem API chuỗi công cụ (
ctx.toolchains).Không bắt buộc: xác định cờ
--incompatible_enable_platforms_for_my_languageđể logic quy tắc lần lượt phân giải chuỗi công cụ thông qua API mới hoặc các cờ cũ như--crosstool_toptrong quá trình kiểm thử di chuyển.Xác định các thuộc tính có liên quan tạo nên các thành phần nền tảng. Xem phần Thuộc tính nền tảng chung
Xác định các chuỗi công cụ tiêu chuẩn và giúp người dùng truy cập các chuỗi công cụ này thông qua hướng dẫn đăng ký quy tắc của bạn (thông tin chi tiết)
Đảm bảo
select()s và quá trình chuyển đổi cấu hình hỗ trợ nền tảng. Đây là thách thức lớn nhất. Thách thức này đặc biệt khó khăn đối với các dự án đa ngôn ngữ (có thể không thành công nếu tất cả các ngôn ngữ không thể đọc--platforms).
Nếu cần kết hợp với các quy tắc không hỗ trợ nền tảng, bạn có thể cần các bản đồ nền tảng để thu hẹp khoảng cách.
Thuộc tính nền tảng chung
Các thuộc tính nền tảng chung, đa ngôn ngữ như OS và CPU phải được
khai báo trong @platforms.
Điều này khuyến khích việc chia sẻ, chuẩn hoá và khả năng tương thích đa ngôn ngữ.
Các thuộc tính riêng biệt đối với quy tắc của bạn phải được khai báo trong kho lưu trữ của quy tắc. Điều này cho phép bạn duy trì quyền sở hữu rõ ràng đối với các khái niệm cụ thể mà quy tắc của bạn chịu trách nhiệm.
Nếu quy tắc của bạn sử dụng hệ điều hành hoặc CPU có mục đích tuỳ chỉnh, thì các quy tắc này phải được khai báo trong
kho lưu trữ của quy tắc thay vì
@platforms.
Bản đồ nền tảng
Bản đồ nền tảng là một API tạm thời cho phép logic nhận biết nền tảng kết hợp với logic cũ trong cùng một bản dựng. Đây là một công cụ đơn giản chỉ nhằm mục đích làm mượt các điểm không tương thích với các khung thời gian di chuyển khác nhau.
Bản đồ nền tảng là bản đồ của platform() đến một
tập hợp cờ cũ tương ứng hoặc ngược lại. Ví dụ:
platforms:
# Maps "--platforms=//platforms:ios" to "--ios_multi_cpus=x86_64 --apple_platform_type=ios".
//platforms:ios
--ios_multi_cpus=x86_64
--apple_platform_type=ios
flags:
# Maps "--ios_multi_cpus=x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
--ios_multi_cpus=x86_64
--apple_platform_type=ios
//platforms:ios
# Maps "--cpu=darwin_x86_64 --apple_platform_type=macos" to "//platform:macos".
--cpu=darwin_x86_64
--apple_platform_type=macos
//platforms:macos
Bazel sử dụng bản đồ này để đảm bảo tất cả các chế độ cài đặt, cả dựa trên nền tảng và cũ, đều được áp dụng nhất quán trong suốt quá trình tạo, kể cả thông qua quá trình chuyển đổi.
Theo mặc định, Bazel đọc các bản đồ từ tệp platform_mappings trong thư mục gốc của không gian làm việc. Bạn cũng có thể đặt
--platform_mappings=//:my_custom_mapping.
Hãy xem thiết kế bản đồ nền tảng để biết thông tin chi tiết.
Đánh giá bằng API
Một platform là một tập hợp các mục tiêu
constraint_value:
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
A constraint_value là một thuộc tính của máy. Các giá trị của cùng một "loại" được nhóm trong một
constraint_setting chung:
constraint_setting(name = "os")
constraint_value(
name = "linux",
constraint_setting = ":os",
)
constraint_value(
name = "mac",
constraint_setting = ":os",
)
A toolchain là một quy tắc Starlark. Các
thuộc tính của quy tắc này khai báo các công cụ của ngôn ngữ (như compiler =
"//mytoolchain:custom_gcc"). Các nhà cung cấp của quy tắc này chuyển
thông tin này đến các quy tắc cần tạo bằng các công cụ này.
Chuỗi công cụ khai báo constraint_value của các máy mà chúng có thể
nhắm mục tiêu
(target_compatible_with = ["@platforms//os:linux"]) và các máy mà công cụ của chúng có thể
chạy
(exec_compatible_with = ["@platforms//os:mac"]).
Khi tạo $ bazel build //:myproject --platforms=//:myplatform, Bazel
sẽ tự động chọn một chuỗi công cụ có thể chạy trên máy tạo và
tạo tệp nhị phân cho //:myplatform. Đây được gọi là phân giải chuỗi công cụ.
Tập hợp các chuỗi công cụ có sẵn có thể được đăng ký trong tệp MODULE.bazelfile
bằng register_toolchains hoặc tại
dòng lệnh bằng --extra_toolchains.
Để biết thêm thông tin, hãy xem tại đây.
Câu hỏi
Để được hỗ trợ chung và có câu hỏi về tiến trình di chuyển, hãy liên hệ với bazel-discuss hoặc chủ sở hữu của các quy tắc thích hợp.
Để thảo luận về thiết kế và sự phát triển của API nền tảng/chuỗi công cụ, hãy liên hệ với bazel-dev.