Bazel có dịch vụ hỗ trợ tinh vi cho việc lập mô hình nền tảng và chuỗi công cụ cho các bản dựng đa kiến trúc và được biên dịch chéo.
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 bạn đặt --incompatible_enable_cc_toolchain_resolution
.
Tức là bạn có thể định cấu hình dự án C++ bằng:
bazel build //:my_cpp_project --platforms=//:myplatform
thay vì phiên bản cũ:
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++ với các nền tảng, hãy xem phần Di chuyển dự án của bạ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ụ.
Thao tác này sẽ thay thế các cờ cũ --java_toolchain
, --host_java_toolchain
, --javabase
và --host_javabase
.
Xem Java và Bazel để biết chi tiết.
Android
Các quy tắc của Android sử dụng nền tảng để chọn chuỗi công cụ khi bạn đặt --incompatible_enable_android_toolchain_resolution
.
Tức là bạn có thể định cấu hình dự án Android bằng:
bazel build //:my_android_project --android_platforms=//:my_android_platform
thay vì với 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ử với các nền tảng trong dự án Android, hãy xem phần Di chuyển dự án của bạn.
Quả táo
Các quy tắc của 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 các API nền tảng với các bản dựng của Apple (ví dụ: khi xây dựng bằng cách kết hợp các quy tắc của Apple và C++ thuần tuý) với các mục ánh xạ nền tảng.
Ngôn ngữ khác
- Quy tắc Go hỗ trợ đầy đủ các nền tảng
- Các quy tắc Rust hỗ trợ đầy đủ cho các nền tảng.
Nếu bạn sở hữu một bộ quy tắc ngôn ngữ, hãy xem phần Di chuyển bộ quy tắc của bạn để thêm tính năng hỗ trợ.
Thông tin khái quát
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 đến nhiều cấu trúc và biên dịch chéo.
Việc này được lấy cảm hứng từ quan sát cho thấy các nhà duy trì ngôn ngữ đã làm việc này theo những cách không tương thích, đặc biệt. Ví dụ: các quy tắc C++ đã sử dụng --cpu
và --crosstool_top
để khai báo CPU mục tiêu và chuỗi công cụ. Không có mô hình nào trong số này mô hình chính xác một "nền tảng". Điều này tạo ra các bản dựng rườm rà và không chính xác.
Java, Android và các ngôn ngữ khác đã phát triển cờ riêng cho các mục đích tương tự, không có ngôn ngữ nào trong số đó hoạt động với nhau. Điều này khiến các bản dựng bằng nhiều ngôn ngữ trở nên khó hiểu và phức tạp.
Bazel dành cho các dự án lớn, đa ngôn ngữ và đa nền tảng. Việc này đòi hỏi phải hỗ trợ theo nguyên tắc hơn cho các khái niệm này, bao gồm cả một 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 đó.
Đã hoàn tất yêu cầu đầu tiên nhưng yêu cầu thứ hai đang diễn ra. Điều này bao gồm việc đảm bảo các nền tảng và chuỗi công cụ dành riêng cho ngôn ngữ được xác định, chuỗi công cụ đọc logic ngôn ngữ 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 sự nỗ lực riêng cho từng ngôn ngữ, cộng với cảnh báo công bằng để chủ sở hữu dự án kiểm thử những thay đổi sắp tới.
Đó là lý do tại sao quá trình di chuyển này đang diễn ra liên tục.
Mục tiêu
Quá trình di chuyển này hoàn tất khi tất cả dự án được xây dựng bằng biểu mẫu:
bazel build //:myproject --platforms=//:myplatform
Điều này có nghĩa là:
- Các quy tắc của dự án chọn chuỗi công cụ phù hợp cho
//:myplatform
. - Các phần phụ thuộc của dự án chọn chuỗi công cụ phù hợp cho
//:myplatform
. //:myplatform
tham chiếu đến các nội dung khai báo phổ biến củaCPU
,OS
và các thuộc tính chung, không phụ thuộc vào ngôn ngữ khác- Tất cả
select()
có liên quan đều khớp với//:myplatform
. //:myplatform
được xác định ở một vị trí rõ ràng, dễ tiếp cận: trong kho lưu trữ của dự án nếu nền tảng là duy nhất cho dự án của bạn hoặc ở một nơi phổ biến mà mọi dự án sử dụng đều có thể tìm thấy
Những cờ cũ như --cpu
, --crosstool_top
và --fat_apk_cpu
sẽ không được dùng nữa và bị xoá ngay khi thấy an toàn.
Cuối cùng, đây sẽ là cách duy nhất để định cấu hình cấu trúc.
Di chuyển dự án
Nếu bạn tạo bản dựng bằng các ngôn ngữ hỗ trợ nền tảng, thì bản dựng của bạn phải hoạt động được với một lệnh gọi như:
bazel build //:myproject --platforms=//:myplatform
Xem phần Trạng thái và tài liệu về ngôn ngữ của bạn để biết thông tin chính xác.
Nếu một ngôn ngữ yêu cầu cờ để bật tính năng hỗ trợ nền tảng, thì bạn cũng cần đặt cờ đó. Xem phần Trạng thái để biết thông tin chi tiết.
Để tạo dự án, bạn cần kiểm tra những điều sau:
//:myplatform
phải tồn tại. Nhìn chung, chủ sở hữu dự án có trách nhiệm xác định các nền tảng vì mỗi dự án sẽ nhắm đến các máy khác nhau. Hãy xem nội dung Nền tảng mặc định.Các chuỗi công cụ mà bạn muốn sử dụng phải tồn tại. Nếu bạn sử dụng chuỗi công cụ kho hàng, chủ sở hữu ngôn ngữ phải đưa ra hướng dẫn về cách đăng ký. Nếu tự viết chuỗi công cụ tuỳ chỉnh, bạn cần register các chuỗi công cụ đó trong tệp
MODULE.bazel
hoặc bằng--extra_toolchains
.select()
và chuyển đổi cấu hình phải được phân giải đúng cách. Xem select() và Transitions.Nếu bản dựng của bạn kết hợp các ngôn ngữ có và không hỗ trợ nền tảng, thì bạn có thể cần ánh xạ nền tảng để giúp các ngôn ngữ cũ hoạt động với API mới. Hãy xem bài viết Liên kết 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 nền tảng rõ ràng để mô tả cấu trúc mà họ muốn xây dựng. Sau đó, các sự kiện này được kích hoạt bằng --platforms
.
Khi bạn không đặt --platforms
, Bazel sẽ mặc định dùng một platform
đại diện cho máy tạo bản dựng cục bộ. Mã này được tạo tự động tại @platforms//host
(đặt bí danh là @bazel_tools//tools:host_platform
) nên không cần xác định rõ ràng. Phương thức này liên kết OS
và CPU
của máy cục bộ với các constraint_value
được khai báo trong @platforms
.
select()
Các dự án có thể select()
trên constraint_value
mục tiêu nhưng không thể hoàn thành nền tảng. Đây là trường hợp có chủ đí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ả 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 trên --cpu
theo truyền thống:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
Bạn có thể xem thêm thông tin tại đây.
select
trên --cpu
, --crosstool_top
, v.v. không hiểu --platforms
.
Khi di chuyển dự án sang các 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
Chuyển đổi Starlark sẽ thay đổi 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 hiệu ứng chuyển đổi đặt --cpu
, --crossstool_top
hoặc các cờ cũ khác, thì những 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 tính năng ánh xạ nền tảng để hỗ trợ cả hai kiểu trong quá trình di chuyển
cửa sổ.
Di chuyển bộ quy tắc
Nếu sở hữu một bộ quy tắc và muốn hỗ trợ các nền tảng, bạn cần phải:
Có chuỗi công cụ phân giải logic quy tắc bằng API chuỗi công cụ. Hãy xem API chuỗi công cụ (
ctx.toolchains
).Không bắt buộc: xác định một cờ
--incompatible_enable_platforms_for_my_language
để logic quy tắc phân giải luân phiên các chuỗi công cụ thông qua API mới hoặc các cờ cũ như--crosstool_top
trong 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 Các thuộc tính phổ biến của nền tảng
Xác định chuỗi công cụ chuẩn và giúp người dùng truy cập vào các chuỗi công cụ đó thông qua hướng dẫn đăng ký của quy tắc (thông tin chi tiết)
Đảm bảo các
select()
và chuyển đổi cấu hình có hỗ trợ các nền tảng. Đây là thách thức lớn nhất. Điều 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ả ngôn ngữ đều 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 ánh xạ nền tảng để thu hẹp khoảng cách này.
Thuộc tính nền tảng phổ biến
Các thuộc tính nền tảng phổ biến và sử dụng nhiều 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à tương thích nhiều ngôn ngữ.
Bạn phải khai báo các thuộc tính dành riêng cho quy tắc của mình trong kho lưu trữ 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 các 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ì bạn phải khai báo các quy tắc này trong kho lưu trữ của quy tắc so với @platforms
.
Liên kết nền tảng
Ánh xạ nền tảng là một API tạm thời cho phép kết hợp logic nhận biết nền tảng với logic cũ trong cùng một bản dựng. Đây là một công cụ cùn chỉ dành để khắc phục tình trạng không tương thích với nhiều khung thời gian di chuyển khác nhau.
Ánh xạ nền tảng là bản đồ của platform()
đến một tập hợp cờ cũ tương ứng hoặc tập hợp 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 phương pháp này để đảm bảo tất cả chế độ cài đặt, cả dựa trên nền tảng và cũ, được áp dụng nhất quán trong suốt quá trình tạo bản dựng, bao gồm cả việc chuyển đổi.
Theo mặc định, Bazel đọc các mối liên kết 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
.
Xem thiết kế của mối liên kết nền tảng để biết thông tin chi tiết.
Xem xét API
platform
là một tập hợp constraint_value
mục tiêu:
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
constraint_value
là một thuộc tính máy. Các giá trị cùng "loại" được nhóm vào một constraint_setting
chung:
constraint_setting(name = "os")
constraint_value(
name = "linux",
constraint_setting = ":os",
)
constraint_value(
name = "mac",
constraint_setting = ":os",
)
toolchain
là một quy tắc Starlark. Các thuộc tính của ngôn ngữ đó khai báo các công cụ của ngôn ngữ (chẳng hạn như compiler =
"//mytoolchain:custom_gcc"
). Nhà cung cấp của ngôn ngữ đó 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
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 trên (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 xây dựng và tạo các tệp nhị phân cho //:myplatform
. Đây được gọi là giải pháp của chuỗi công cụ.
Bạn có thể đăng ký tập hợp chuỗi công cụ có sẵn trong tệp MODULE.bazel
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
Nếu cần được hỗ trợ chung và có thắc mắc về tiến trình di chuyển, hãy liên hệ với bazel-thảo luận 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.