Bazel có khả năng hỗ trợ tinh vi để mô hình hoá các 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 dịch vụ 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=//: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++ bằng các nền tảng, hãy xem phần 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ụ.
Thao tác này sẽ thay thế các cờ cũ --java_toolchain
, --host_java_toolchain
, --javabase
và --host_javabase
.
Hãy xem phần 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_platform
thay vì 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 của bạn bằng các nền tảng, hãy xem phần Di chuyển dự án.
Apple
Quy tắc của Apple không hỗ trợ các 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 bản dựng Apple (ví dụ: khi tạo bằng hỗn hợp các quy tắc của Apple và C++ thuần tuý) bằng các ánh xạ nền tảng.
Ngôn ngữ khác
- Go rules hỗ trợ đầy đủ các nền tảng
- Các quy tắc Rust hỗ trợ đầy đủ 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 để thêm thông tin 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.
Điều này được lấy cảm hứng từ việc nhận thấy rằng những người duy trì ngôn ngữ đã làm việc này theo những cách đặc biệt và 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ó nền tảng 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 vụng về và không chính xác.
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ự, nhưng 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ả 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 đó.
Công việc đầu tiên đã hoàn tất nhưng công việc thứ hai vẫn đang diễn ra. Việc này bao gồm đả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, 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 khá đơ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ử đối với những thay đổi sắp tới.
Đó là lý do đây là một quá trình di chuyển liên tục.
Mục tiêu
Quá trình di chuyển này sẽ hoàn tất khi tất cả các dự án đều được tạo 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 sẽ chọn chuỗi công cụ phù hợp cho
//:myplatform
. - Các phần phụ thuộc của dự án sẽ chọn chuỗi công cụ phù hợp cho
//:myplatform
. //:myplatform
tham 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 nơi rõ ràng, dễ truy cập: trong kho lưu trữ của dự án nếu nền tảng này là duy nhất đối với dự án của bạn, hoặc một nơi chung mà tất cả các dự án sử dụng đều có thể tìm thấy
Các cờ cũ như --cpu
, --crosstool_top
và --fat_apk_cpu
sẽ không được dùng nữa và bị xoá ngay khi có thể.
Cuối cùng, đây sẽ là cách duy nhất để định cấu hình các cấu 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=//:myplatform
Hãy xem Trạng thái và tài liệu bằng ngôn ngữ của bạn để biết thông tin chi tiết 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, 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 được tạo, bạn cần kiểm tra những điều sau:
//:myplatform
phải tồn tại. Thông thường, chủ sở hữu dự án có trách nhiệm xác định các nền tảng vì các dự án khác nhau nhắm đến các máy khác nhau. Xem Nền tảng mặc định.Phải có sẵn các chuỗi công cụ mà bạn muốn sử dụng. Nếu sử dụng chuỗi công cụ gố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
WORKSPACE
hoặc bằng--extra_toolchains
.select()
và các quá trình chuyển đổi cấu hình phải phân giải đúng cách. Xem select() và Transitions (Hiệu ứng chuyển cảnh).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 các mối liên kết 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 Ánh xạ 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 phải xác định rõ các nền tảng để mô tả những cấu trúc mà họ muốn tạo. Sau đó, các hàm này sẽ được kích hoạt bằng --platforms
.
Khi --platforms
không được thiết lập, Bazel sẽ mặc định là platform
đại diện cho máy tạo cục bộ. Thư mục 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. Thao tác này ánh xạ OS
và CPU
của máy cục bộ với constraint_value
được khai báo trong @platforms
.
select()
Bạn có thể select()
dự án trên constraint_value
mục tiêu nhưng không thể hoàn tất các nền tảng. Đây là điều có chủ ý để select()
hỗ trợ nhiều loại máy nhất có thể. Một 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 để chỉ định 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 cách truyền thống:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
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 dự án sang constraint_values
hoặc sử dụng các ánh xạ nền tảng để hỗ trợ cả hai kiểu trong quá trình di chuyển.
Kiểu chuyển cảnh
Các quá trình chuyển đổi Starlark 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 một hiệu ứng chuyển cảnh đặ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 các 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 các mối liên kết 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ợ các nền tảng, bạn cần:
Cho phép logic quy tắc giải quyết 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_top
trong quá trình kiểm thử di chuyển.Xác định các thuộc tính liên quan tạo nên các thành phần nền tảng. Xem Các thuộc tính chung của nền tảng
Xác định các chuỗi công cụ tiêu chuẩn và cung cấp cho người dùng thông qua hướng dẫn đăng ký quy tắc (thông tin chi tiết)
Đảm bảo
select()
s và các nền tảng hỗ trợ quá trình chuyển đổi cấu hình. Đâ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ữ không đọc đượ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 mối liên kết nền tảng để thu hẹp khoảng cách.
Các tài sản phổ biến của nền tảng
Các thuộc tính nền tảng phổ biến, đ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ẻ, tiêu chuẩn hoá và khả năng tương thích giữa các ngôn ngữ.
Các thuộc tính riêng biệt cho quy tắc của bạn phải được khai báo trong kho lưu trữ quy tắc. Điều này giúp bạn duy trì quyền sở hữu rõ ràng đối với những khái niệm cụ thể mà các 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 CPU hoặc hệ điều hành cho mục đích tuỳ chỉnh, thì bạn nên khai báo các quy tắc này trong kho lưu trữ quy tắc thay vì @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 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 giảm thiểu các điểm không tương thích với nhiều khung thời gian di chuyển.
Hoạt động liên kết nền tảng là hoạt động liên kết platform()
với 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 "--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_x86_64 --apple_platform_type=macos" to "//platform:macos".
--cpu=darwin_x86_64
--apple_platform_type=macos
//platforms:macos
Bazel sử dụng chế độ này để đảm bảo tất cả các chế độ cài đặt (cả dựa trên nền tảng và chế độ cũ) đều được áp dụng nhất quán trong suốt quá trình tạo, kể cả thông qua các quá trình 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
.
Hãy xem thiết kế ánh xạ nền tảng để biết thông tin chi tiết.
Đánh giá bằng API
platform
là một tập hợp gồm 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 của máy. Các giá trị có cùng "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",
)
toolchain
là một quy tắc Starlark. Các thuộc tính của nó khai báo các công cụ của một ngôn ngữ (chẳng hạn như compiler =
"//mytoolchain:custom_gcc"
). Nhà cung cấp của nó sẽ truyền thông tin này đến các quy tắc cần được xây dựng bằng những 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 đến (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 tạo và tạo các tệp nhị phân cho //:myplatform
. Đây được gọi là phân giải chuỗi công cụ.
Bạn có thể đăng ký tập hợp các chuỗi công cụ có sẵn trong WORKSPACE
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à giải đáp thắc mắc 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 các API nền tảng/chuỗi công cụ, hãy liên hệ với bazel-dev.