การย้ายข้อมูลไปยังแพลตฟอร์ม

Bazel มีการรองรับที่ซับซ้อนสำหรับการสร้างแบบจำลองแพลตฟอร์มและ Toolchain สำหรับบิลด์แบบหลายสถาปัตยกรรมและบิลด์ที่คอมไพล์ข้าม

หน้านี้สรุปสถานะของการรองรับนี้

ดูเพิ่มเติม

สถานะ

C++

กฎ C++ ใช้แพลตฟอร์มเพื่อเลือก Toolchain เมื่อตั้งค่า --incompatible_enable_cc_toolchain_resolution

ซึ่งหมายความว่าคุณสามารถกำหนดค่าโปรเจ็กต์ C++ ได้ดังนี้

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

แทนที่จะใช้รูปแบบเดิมดังนี้

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

ระบบจะเปิดใช้ฟีเจอร์นี้โดยค่าเริ่มต้นใน Bazel 7.0 (#7260)

หากต้องการทดสอบโปรเจ็กต์ C++ ด้วยแพลตฟอร์ม โปรดดู การย้ายข้อมูลโปรเจ็กต์ และ การกำหนดค่า Toolchain C++

Java

กฎ Java ใช้แพลตฟอร์มเพื่อเลือก Toolchain

ซึ่งจะแทนที่แฟล็กเดิม --java_toolchain, --host_java_toolchain, --javabase และ --host_javabase

ดูรายละเอียดได้ที่ Java and Bazel

Android

กฎ Android ใช้แพลตฟอร์มเพื่อเลือก Toolchain เมื่อตั้งค่า --incompatible_enable_android_toolchain_resolution

ซึ่งหมายความว่าคุณสามารถกำหนดค่าโปรเจ็กต์ Android ได้ดังนี้

bazel build //:my_android_project --android_platforms=//:my_android_platform

แทนที่จะใช้แฟล็กเดิม เช่น --android_crosstool_top, --android_cpu, และ --fat_apk_cpu

ระบบจะเปิดใช้ฟีเจอร์นี้โดยค่าเริ่มต้นใน Bazel 7.0 (#16285)

หากต้องการทดสอบโปรเจ็กต์ Android ด้วยแพลตฟอร์ม โปรดดู การย้ายข้อมูลโปรเจ็กต์

Apple

กฎ Apple ไม่รองรับแพลตฟอร์มและยังไม่มีกำหนดการ รองรับ

คุณยังคงใช้ API ของแพลตฟอร์มกับบิลด์ Apple ได้ (เช่น เมื่อสร้าง ด้วยกฎ Apple และ C++ แบบเพียวๆ) ด้วย การแมป แพลตฟอร์ม

ภาษาอื่นๆ

  • กฎ Go รองรับแพลตฟอร์มอย่างเต็มรูปแบบ
  • กฎ Rust รองรับแพลตฟอร์มอย่างเต็มรูปแบบ

หากคุณเป็นเจ้าของชุดกฎภาษา โปรดดู การย้ายข้อมูลชุดกฎ เพื่อเพิ่ม การรองรับ

ข้อมูลเบื้องต้น

เราได้เปิดตัว แพลตฟอร์ม และ Toolchain เพื่อกำหนดมาตรฐานวิธีที่โปรเจ็กต์ซอฟต์แวร์กำหนดเป้าหมายเป็นสถาปัตยกรรมต่างๆ และคอมไพล์ข้าม

แนวคิดนี้ได้รับแรงบันดาลใจจากการสังเกตว่าผู้ดูแลภาษาได้ดำเนินการดังกล่าวในลักษณะเฉพาะกิจและไม่เข้ากัน ตัวอย่างเช่น กฎ C++ ใช้ --cpu และ --crosstool_top เพื่อประกาศ CPU เป้าหมายและ Toolchain ซึ่งทั้ง 2 อย่างนี้ไม่ได้สร้างแบบจำลอง "แพลตฟอร์ม" อย่างถูกต้อง จึงทำให้เกิดบิลด์ที่แปลกประหลาดและไม่ถูกต้อง

Java, Android และภาษาอื่นๆ ได้พัฒนาแฟล็กของตนเองเพื่อวัตถุประสงค์ที่คล้ายกัน แต่ไม่มีภาษาใดที่ทำงานร่วมกันได้ จึงทำให้บิลด์แบบข้ามภาษาเกิดความสับสนและซับซ้อน

Bazel ออกแบบมาสำหรับโปรเจ็กต์ขนาดใหญ่ที่มีหลายภาษาและหลายแพลตฟอร์ม จึงต้องมีการรองรับแนวคิดเหล่านี้ตามหลักการมากขึ้น รวมถึง API มาตรฐานที่ชัดเจน

ความจำเป็นในการย้ายข้อมูล

การอัปเกรดเป็น API ใหม่ต้องใช้ความพยายาม 2 อย่าง ได้แก่ การเผยแพร่ API และการอัปเกรดตรรกะของกฎเพื่อใช้ API

เราได้ดำเนินการอย่างแรกเสร็จแล้ว แต่กำลังดำเนินการอย่างที่ 2 อยู่ ซึ่งประกอบด้วยการกำหนดแพลตฟอร์มและ Toolchain ที่เฉพาะเจาะจงกับภาษา ตรรกะของภาษาจะอ่าน Toolchain ผ่าน API ใหม่แทนที่จะใช้แฟล็กเดิม เช่น --crosstool_top และ config_setting จะเลือก API ใหม่แทนที่จะใช้แฟล็กเดิม

งานนี้ตรงไปตรงมา แต่ต้องใช้ความพยายามที่แตกต่างกันสำหรับแต่ละภาษา รวมถึงการแจ้งเตือนล่วงหน้าให้เจ้าของโปรเจ็กต์ทดสอบกับการเปลี่ยนแปลงที่จะเกิดขึ้น

นี่จึงเป็นเหตุผลที่เราต้องย้ายข้อมูลอย่างต่อเนื่อง

เป้าหมาย

การย้ายข้อมูลนี้จะเสร็จสมบูรณ์เมื่อโปรเจ็กต์ทั้งหมดสร้างด้วยรูปแบบต่อไปนี้

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

ซึ่งหมายความว่า

  1. กฎของโปรเจ็กต์จะเลือก Toolchain ที่เหมาะสมสำหรับ //:myplatform
  2. ทรัพยากร Dependency ของโปรเจ็กต์จะเลือก Toolchain ที่เหมาะสมสำหรับ //:myplatform
  3. //:myplatform อ้างอิง การประกาศทั่วไป ของ CPU, OS และพร็อพเพอร์ตี้ทั่วไปอื่นๆ ที่ไม่ขึ้นอยู่กับภาษา
  4. `select()` ที่เกี่ยวข้องทั้งหมดจะจับคู่ //:myplatform อย่างถูกต้องselect()
  5. //:myplatform กำหนดไว้ในตำแหน่งที่ชัดเจนและเข้าถึงได้ง่าย เช่น ในที่เก็บของโปรเจ็กต์หากแพลตฟอร์มนั้นเป็นของโปรเจ็กต์ของคุณโดยเฉพาะ หรือในตำแหน่งทั่วไปที่โปรเจ็กต์ที่ใช้ทั้งหมดสามารถค้นหาได้

เราจะเลิกใช้งานและนำแฟล็กเดิม เช่น --cpu, --crosstool_top และ --fat_apk_cpu ออกทันทีที่ปลอดภัย

ในที่สุด นี่จะเป็นวิธี เดียว ในการกำหนดค่าสถาปัตยกรรม

การย้ายข้อมูลโปรเจ็กต์

หากคุณสร้างด้วยภาษาที่รองรับแพลตฟอร์ม บิลด์ควรทำงานได้อยู่แล้วด้วยการเรียกใช้ เช่น

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

โปรดดูรายละเอียดที่แม่นยำในเอกสารประกอบของ สถานะ และภาษา

หากภาษาต้องใช้แฟล็กเพื่อเปิดใช้การรองรับแพลตฟอร์ม คุณจะต้องตั้งค่าแฟล็กนั้นด้วย ดูรายละเอียดได้จากสถานะ

โปรเจ็กต์จะต้องสร้างได้ คุณจึงต้องตรวจสอบสิ่งต่อไปนี้

  1. //:myplatform ต้องมีอยู่ โดยทั่วไปแล้ว เจ้าของโปรเจ็กต์มีหน้าที่รับผิดชอบในการกำหนดแพลตฟอร์ม เนื่องจากโปรเจ็กต์ต่างๆ กำหนดเป้าหมายเป็นเครื่องที่ต่างกัน ดูแพลตฟอร์มเริ่มต้น

  2. Toolchain ที่คุณต้องการใช้ต้องมีอยู่ หากใช้ Toolchain มาตรฐาน เจ้าของภาษาควรระบุวิธีการลงทะเบียน Toolchain หาก เขียน Toolchain ที่กำหนดเอง คุณต้องลงทะเบียน Toolchain ในไฟล์ MODULE.bazel หรือใช้ --extra_toolchains

  3. select()s และ การเปลี่ยนการกำหนดค่า ต้อง ทำงานอย่างถูกต้อง ดู select() และ การเปลี่ยน

  4. หากบิลด์ของคุณใช้ภาษาที่รองรับและไม่รองรับแพลตฟอร์ม คุณอาจต้องใช้การแมปแพลตฟอร์มเพื่อช่วยให้ภาษาเดิมทำงานกับ API ใหม่ได้ ดูรายละเอียดได้ที่การแมปแพลตฟอร์ม

หากยังพบปัญหาอยู่ โปรดติดต่อขอรับการสนับสนุน

แพลตฟอร์มเริ่มต้น

เจ้าของโปรเจ็กต์ควรกำหนด แพลตฟอร์มที่ชัดเจนเพื่ออธิบายสถาปัตยกรรม ที่ต้องการสร้าง จากนั้นระบบจะทริกเกอร์แพลตฟอร์มเหล่านี้ด้วย --platforms

เมื่อไม่ได้ตั้งค่า --platforms Bazel จะใช้ platform เป็นค่าเริ่มต้น ซึ่งแสดงถึง เครื่องสร้างในเครื่อง ระบบจะสร้างแพลตฟอร์มนี้โดยอัตโนมัติที่ @platforms//host (กำหนดชื่อแทนเป็น @bazel_tools//tools:host_platform) คุณจึงไม่จำเป็นต้องกำหนดแพลตฟอร์มนี้อย่างชัดเจน โดยจะแมป OS และ CPU ของเครื่องในเครื่องกับ constraint_value ที่ประกาศไว้ใน @platforms

select()

โปรเจ็กต์สามารถ select() ในเป้าหมาย constraint_value ได้ แต่ไม่สามารถเลือกแพลตฟอร์มที่สมบูรณ์ เราตั้งใจออกแบบไว้เช่นนี้เพื่อให้ select() รองรับเครื่องที่หลากหลายมากที่สุด ไลบรารีที่มีแหล่งที่มาเฉพาะ ARM ควรจะรองรับเครื่องที่ใช้พลังงานจาก ARM ทั้งหมด เว้นแต่จะมีเหตุผลที่ต้องระบุให้ละเอียดมากขึ้น

หากต้องการเลือก constraint_value อย่างน้อย 1 รายการ ให้ใช้โค้ดต่อไปนี้

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

ซึ่งเทียบเท่ากับการเลือก --cpu แบบเดิม

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

ดูรายละเอียดเพิ่มเติมได้ที่นี่

select ใน --cpu, --crosstool_top ฯลฯ ไม่เข้าใจ --platforms เมื่อย้ายข้อมูลโปรเจ็กต์ไปยังแพลตฟอร์ม คุณต้องแปลงเป็น constraint_values หรือใช้ การแมปแพลตฟอร์ม เพื่อรองรับ ทั้ง 2 สไตล์ระหว่างการย้ายข้อมูล

การเปลี่ยน

การเปลี่ยน Starlark จะเปลี่ยน แฟล็กในส่วนต่างๆ ของกราฟบิลด์ หากโปรเจ็กต์ใช้การเปลี่ยนที่ตั้งค่า --cpu, --crossstool_top หรือแฟล็กเดิมอื่นๆ กฎที่อ่าน --platforms จะไม่เห็นการเปลี่ยนแปลงเหล่านี้

เมื่อย้ายข้อมูลโปรเจ็กต์ไปยังแพลตฟอร์ม คุณต้องแปลงการเปลี่ยนแปลง เช่น return { "//command_line_option:cpu": "arm" } เป็น return { "//command_line_option:platforms": "//:my_arm_platform" } หรือใช้ การแมปแพลตฟอร์ม เพื่อรองรับทั้ง 2 สไตล์ระหว่างการย้ายข้อมูล window.

การย้ายข้อมูลชุดกฎ

หากคุณเป็นเจ้าของชุดกฎและต้องการรองรับแพลตฟอร์ม คุณต้องดำเนินการต่อไปนี้

  1. กำหนดให้ตรรกะของกฎแก้ปัญหา Toolchain ด้วย Toolchain API ดู Toolchain API (ctx.toolchains)

  2. ไม่บังคับ: กำหนดแฟล็ก --incompatible_enable_platforms_for_my_language เพื่อให้ตรรกะของกฎแก้ปัญหา Toolchain ผ่าน API ใหม่หรือแฟล็กเดิม เช่น --crosstool_top ระหว่างการทดสอบการย้ายข้อมูล

  3. กำหนดพร็อพเพอร์ตี้ที่เกี่ยวข้องซึ่งประกอบขึ้นเป็นคอมโพเนนต์ของแพลตฟอร์ม ดู พร็อพเพอร์ตี้แพลตฟอร์มทั่วไป

  4. กำหนด Toolchain มาตรฐานและทำให้ผู้ใช้เข้าถึง Toolchain ได้ผ่านวิธีการลงทะเบียนของกฎ (รายละเอียด)

  5. ตรวจสอบว่า select()s และ การเปลี่ยนการกำหนดค่า รองรับแพลตฟอร์ม ซึ่งเป็นความท้าทายที่ใหญ่ที่สุด โดยเฉพาะอย่างยิ่งสำหรับโปรเจ็กต์ที่มีหลายภาษา (ซึ่งอาจล้มเหลวหาก ทุก ภาษาอ่าน --platforms ไม่ได้)

หากคุณต้องใช้ร่วมกับกฎที่ไม่รองรับแพลตฟอร์ม คุณอาจต้องใช้ การแมปแพลตฟอร์มเพื่อเชื่อมช่องว่าง

พร็อพเพอร์ตี้แพลตฟอร์มทั่วไป

พร็อพเพอร์ตี้แพลตฟอร์มทั่วไปแบบข้ามภาษา เช่น OS และ CPU ควร ประกาศไว้ใน @platforms ซึ่งจะส่งเสริมการแชร์ การกำหนดมาตรฐาน และความเข้ากันได้แบบข้ามภาษา

พร็อพเพอร์ตี้เฉพาะของกฎควรประกาศไว้ในที่เก็บของกฎ ซึ่งจะช่วยให้คุณรักษาความเป็นเจ้าของที่ชัดเจนในแนวคิดเฉพาะที่กฎของคุณรับผิดชอบ

หากกฎใช้ OS หรือ CPU ที่มีวัตถุประสงค์ที่กำหนดเอง คุณควรประกาศ OS หรือ CPU เหล่านี้ใน ที่เก็บของกฎเทียบกับ @platforms

การแมปแพลตฟอร์ม

การแมปแพลตฟอร์ม คือ API ชั่วคราวที่ช่วยให้ตรรกะที่รับรู้แพลตฟอร์มทำงานร่วมกับตรรกะเดิมในบิลด์เดียวกันได้ ซึ่งเป็นเครื่องมือที่ไม่ซับซ้อนและมีไว้เพื่อลดความไม่เข้ากันกับกรอบเวลาการย้ายข้อมูลที่แตกต่างกัน

การแมปแพลตฟอร์มคือการแมป platform() กับชุดแฟล็กเดิมที่เกี่ยวข้อง หรือการแมปย้อนกลับ เช่น

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 ใช้การแมปนี้เพื่อรับประกันว่าการตั้งค่าทั้งหมด ทั้งแบบอิงตามแพลตฟอร์มและ แบบเดิม จะนำไปใช้อย่างสอดคล้องกันตลอดทั้งบิลด์ รวมถึงผ่าน การเปลี่ยน

โดยค่าเริ่มต้น Bazel จะอ่านการแมปจากไฟล์ platform_mappings ในรูทของพื้นที่ทำงาน นอกจากนี้ คุณยังตั้งค่า --platform_mappings=//:my_custom_mapping ได้ด้วย

ดูรายละเอียดได้ที่การออกแบบการแมปแพลตฟอร์ม

การตรวจสอบ API

platform คือคอลเล็กชันของ constraint_value เป้าหมาย:

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

A constraint_value คือพร็อพเพอร์ตี้ของเครื่อง ค่าที่มี "ประเภท" เดียวกันจะจัดกลุ่มไว้ภายใต้ constraint_setting ทั่วไป

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

toolchain คือ กฎ Starlark แอตทริบิวต์ของกฎจะประกาศเครื่องมือของภาษา (เช่น compiler = "//mytoolchain:custom_gcc") และ ผู้ให้บริการจะส่งข้อมูลนี้ไปยังกฎที่ต้องสร้างด้วยเครื่องมือเหล่านี้

Toolchain จะประกาศ constraint_value ของเครื่องที่กำหนดเป้าหมายได้ (target_compatible_with = ["@platforms//os:linux"]) และเครื่องที่เครื่องมือของ Toolchain ทำงานได้ (exec_compatible_with = ["@platforms//os:mac"])

เมื่อสร้าง $ bazel build //:myproject --platforms=//:myplatform Bazel จะเลือก Toolchain ที่ทำงานบนเครื่องสร้างและ สร้างไบนารีสำหรับ //:myplatform โดยอัตโนมัติ ซึ่งเรียกว่า การแก้ปัญหา Toolchain

คุณสามารถลงทะเบียนชุด Toolchain ที่พร้อมใช้งานในไฟล์ MODULE.bazel ด้วย register_toolchains หรือในบรรทัดคำสั่งด้วย --extra_toolchains

ดูข้อมูลเพิ่มเติมที่ นี่

คำถาม

หากต้องการรับการสนับสนุนทั่วไปและมีคำถามเกี่ยวกับไทม์ไลน์การย้ายข้อมูล โปรดติดต่อ bazel-discuss หรือเจ้าของกฎที่เหมาะสม

หากต้องการพูดคุยเกี่ยวกับการออกแบบและการพัฒนา API ของแพลตฟอร์ม/Toolchain โปรดติดต่อ bazel-dev

ดูเพิ่มเติม