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

รายงานปัญหา ดูแหล่งที่มา

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

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

และดู:

สถานะ

C++

กฎ C++ จะใช้แพลตฟอร์มเพื่อเลือกเชนเครื่องมือเมื่อตั้งค่า --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++ กับแพลตฟอร์ม โปรดดู การย้ายข้อมูลโปรเจ็กต์และ การกำหนดค่าเชนเครื่องมือ C++

Java

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

การดำเนินการนี้จะแทนที่ Flag --java_toolchain, --host_java_toolchain, --javabase และ --host_javabase เดิม

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

Android

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

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

ภาษาอื่นๆ

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

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

ที่มา

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

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

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

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

ความจำเป็นต้องย้ายข้อมูล

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

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

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

การย้ายข้อมูลนี้จึงดำเนินไปอย่างต่อเนื่อง

เป้าหมาย

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

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

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

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

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

ท้ายที่สุดแล้ว นี่จะเป็นวิธีกำหนดค่าสถาปัตยกรรมเพียงอย่างเดียว

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

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

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

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

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

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

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

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

  3. select() และการเปลี่ยนการกำหนดค่าต้องได้รับการแก้ไขอย่างถูกต้อง โปรดดู 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 รูปแบบในระหว่างกรอบเวลาการย้ายข้อมูล

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

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

  1. กำหนด Toolchain ของกฎเกี่ยวกับการแก้ไขตรรกะของกฎด้วย Toolchain API โปรดดู toolchain API (ctx.toolchains)

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

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

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

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

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

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

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

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

หากกฎใช้ระบบปฏิบัติการหรือ 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",
    ],
)

constraint_value เป็นพร็อพเพอร์ตี้ของเครื่อง ระบบจะจัดกลุ่มค่า "kind" เดียวกันไว้ใน 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") ผู้ให้บริการจะส่งข้อมูลนี้ไปยังกฎที่ต้องสร้างด้วยเครื่องมือเหล่านี้

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

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

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

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

คำถาม

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

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

ดูเพิ่มเติม