Di chuyển sang nền tảng

Báo cáo sự cố Xem nguồn

Bazel có dịch vụ hỗ trợ tinh vi cho việc lập mô hình nền tảngchuỗi công cụ cho các bản dựng đa kiến trúc và bản dựng đượ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 bạn đặt --incompatible_enable_cc_toolchain_resolution.

Điều này có nghĩa là bạn có thể định cấu hình dự án C++ bằng:

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

thay vì chế độ 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Đị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--host_javabase.

Xem Java và Bazel để biết 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 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ì các cờ cũ như --android_crosstool_top, --android_cpu--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 trên các nền tảng, hãy xem phần Di chuyển dự án của bạn.

Quả táo

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 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 ánh xạ nền tảng.

Ngôn ngữ khác

Nếu bạn sở hữu bộ quy tắc ngôn ngữ, hãy xem bài viết Di chuyển bộ quy tắc để thêm hỗ trợ.

Thông tin khái quát

Nền tảngchuỗi công cụ được ra mắt để 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 truyền cảm hứng từ việc quan sát thấy các trình bảo trì ngôn ngữ đã thực hiện việc này theo những cách không tương thích và đặc biệt. Ví dụ: các quy tắc C++ sử dụng --cpu--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 hoá đúng một "nền tảng". Điều này đã tạo ra các bản dựng không đúng và không chính xác.

Java, Android và các ngôn ngữ khác đã phát triển cờ của riêng mình cho các mục đích tương tự nhau, 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 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. Để làm được như vậy, bạn cần 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 đó.

Việc đầu tiên đã hoàn tất nhưng việc thứ hai vẫn đang diễn ra. Điều này bao gồm đảm bảo các nền tảng và chuỗi công cụ theo ngôn ngữ cụ thể được xác định, logic của 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ông việc này đơn giản nhưng đòi hỏi nỗ lực riêng cho từng ngôn ngữ, cộng với cảnh báo hợp lý để chủ sở hữu dự án kiểm thử những thay đổi sắp tới.

Vì vậy, 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 tạo bằng biểu mẫu:

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

Điều này có nghĩa là:

  1. Các quy tắc của dự án chọn chuỗi công cụ phù hợp cho //:myplatform.
  2. Các phần phụ thuộc của dự án sẽ chọn chuỗi công cụ phù hợp cho //:myplatform.
  3. //:myplatform tham chiếu đến các nội dung khai báo phổ biến của CPU, OS và các thuộc tính chung, không phụ thuộc vào ngôn ngữ khác
  4. Tất cả select() có liên quan đều khớp đúng với //:myplatform.
  5. //:myplatform được xác định ở một vị trí rõ ràng, dễ truy cập: trong kho lưu trữ dự án của bạn nếu nền tảng là dành riêng cho dự án của bạn hoặc một vị trí phổ biến mà tất cả dự án đang dùng đều có thể tìm thấy nền tảng đó

Những cờ cũ như --cpu, --crosstool_top--fat_apk_cpu sẽ không được dùng nữa và sẽ bị xoá ngay khi an toàn.

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 tạo bản dựng bằng ngôn ngữ hỗ trợ nền tảng, thì bản dựng phải hoạt động được 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 về 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, thì bạn cũng cần đặt cờ đó. Xem 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:

  1. //:myplatform phải tồn tại. Nhìn chung, 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 đến các máy khác nhau. Vui lòng xem nội dung Nền tảng mặc định.

  2. Phải có các chuỗi công cụ mà bạn muốn dùng. Nếu sử dụng chuỗi công cụ chứng khoán, 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 các chuỗi công cụ tuỳ chỉnh của riêng mình, bạn cần register các chuỗi công cụ đó trong tệp MODULE.bazel hoặc thông qua --extra_toolchains.

  3. Các select()chuyển đổi cấu hình phải được giải quyết đúng cách. Xem select()Transitions.

  4. 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 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 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 sự cố, 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 xây dựng. Sau đó, các trình xử lý này được kích hoạt bằng --platforms.

Khi không đặt --platforms, Bazel sẽ mặc định sử dụng platform đại diện cho máy tạo bản dựng cục bộ. Chuỗi này được tạo tự động tại @local_config_platform//:host, do đó, bạn không cần phải xác định rõ ràng. Công cụ này liên kết OSCPU 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 các nền tảng. Việc này là 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ả máy sử dụng ARM trừ khi 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 cách thông thường trên --cpu:

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

Tìm hiểu thêm 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 dự án đó thành constraint_values hoặc sử dụng mối liên kết 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 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 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 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 tính năng liên kết nền tảng để hỗ trợ cả hai kiểu trong cửa sổ di chuyển.

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:

  1. Cung cấp logic quy tắc phân giải chuỗi công cụ bằng API chuỗi công cụ. Hãy xem API chuỗi công cụ (ctx.toolchains).

  2. 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ũ như --crosstool_top trong quá trình kiểm thử quá trình di chuyển.

  3. 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 phổ biến của nền tảng

  4. Xác định các chuỗi công cụ tiêu chuẩn và cho phé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)

  5. Đảm bảo các nền tảng hỗ trợ select()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ả 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 mối liên kết nền tảng để thu hẹp khoảng cách.

Các thuộc tính phổ biến của nền tảng

Các thuộc tính phổ biến của nền tảng nhiều ngôn ngữ như OSCPU 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 cần 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ì các quy tắc này phải được khai báo trong kho lưu trữ quy tắc so với @platforms.

Liên kết nền tảng

Liên kết 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ùng để xử lý tình trạng không tương thích mượt mà với nhiều khung thời gian di chuyển.

Ánh xạ nền tảng là bản đồ của platform() với một tập hợp cờ cũ tương ứng hoặc 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 tính năng 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 một cách nhất quán trong suốt quá trình tạo bản dựng, bao gồm cả quá trình chuyển đổi.

Theo mặc định, Bazel đọ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 các 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ó cùng "loại" được nhóm lại 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 thuộc tính này khai báo các công cụ của ngôn ngữ (chẳng hạn như compiler = "//mytoolchain:custom_gcc"). Trình cung cấp của nó sẽ 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à những máy mà các công cụ đó 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 bản dựng và tạo tệp nhị phân cho //:myplatform. Đây gọi là độ phân giải 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

Để đượ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-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.

Xem thêm