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 ใช้แพลตฟอร์มเพื่อเลือกเชนเครื่องมือ
แฟล็กนี้มาแทนที่แฟล็กเดิม --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++ ที่แท้จริง) ด้วยการแมปแพลตฟอร์ม
ภาษาอื่นๆ
หากคุณเป็นเจ้าของชุดกฎภาษา โปรดดูการย้ายข้อมูลชุดกฎเพื่อเพิ่มการสนับสนุน
ที่มา
เราเปิดตัวแพลตฟอร์มและเครื่องมือเชนเพื่อสร้างมาตรฐานวิธีที่โปรเจ็กต์ซอฟต์แวร์กำหนดเป้าหมายสถาปัตยกรรมที่แตกต่างกันและการคอมไพล์แบบข้ามระบบ
บทความนี้ได้รับแรงบันดาลใจมาจากการสังเกตที่ว่าผู้รักษาภาษาทำเรื่องนี้แบบเฉพาะกิจและเข้ากันไม่ได้ เช่น กฎ C++ ใช้ --cpu
และ --crosstool_top
เพื่อประกาศ CPU เป้าหมายและ Toolchain ทั้ง 2 อย่างนี้ต่างก็
ไม่มีแบบจำลอง "แพลตฟอร์ม" ที่ถูกต้อง การทำเช่นนี้ทำให้เกิดงานสร้างที่น่าอึดอัดใจและไม่ถูกต้อง
Java, Android และภาษาอื่นๆ พัฒนา Flag ของตัวเองเพื่อวัตถุประสงค์ที่คล้ายกัน โดยไม่มีการทำงานร่วมกันใดๆ ทั้งสิ้น ซึ่งทำให้การสร้างข้ามภาษา ทำให้สับสนและซับซ้อน
Bazel มีไว้สำหรับโปรเจ็กต์แบบหลายแพลตฟอร์มที่มีขนาดใหญ่และรองรับหลายภาษา การดำเนินการนี้ต้องการการสนับสนุนที่มีหลักการมากขึ้นสำหรับแนวคิดเหล่านี้ รวมถึง API มาตรฐานที่ชัดเจน
ความจำเป็นในการย้ายข้อมูล
การอัปเกรดไปใช้ API ใหม่ต้องอาศัยการดำเนินการ 2 อย่าง ได้แก่ การปล่อย API และการอัปเกรดตรรกะของกฎเพื่อนำไปใช้
รายการแรกจบแล้ว แต่รายการที่ 2 ยังดำเนินอยู่ ซึ่งรวมถึงการตรวจสอบการกำหนดแพลตฟอร์มและเชนเครื่องมือเฉพาะภาษา ตรรกะภาษาจะอ่าน Toolchain ของภาษาผ่าน API ใหม่แทนแฟล็กเก่าอย่าง --crosstool_top
และ config_setting
จะเลือก API ใหม่แทนแฟล็กเก่า
การดำเนินงานนี้ไม่ซับซ้อน แต่จะต้องใช้ความพยายามที่แตกต่างกันไปในแต่ละภาษา รวมถึงต้องมีการเตือนอย่างเป็นธรรมเพื่อให้เจ้าของโปรเจ็กต์ทดสอบการเปลี่ยนแปลงที่กำลังจะเกิดขึ้น
จึงเป็นสาเหตุที่ต้องย้ายข้อมูลอย่างต่อเนื่อง
เป้าหมาย
การย้ายข้อมูลนี้จะเสร็จสมบูรณ์เมื่อโปรเจ็กต์ทั้งหมดสร้างด้วยแบบฟอร์มต่อไปนี้
bazel build //:myproject --platforms=//:myplatform
ซึ่งหมายความว่า
- กฎของโปรเจ็กต์เลือกเชนเครื่องมือที่เหมาะสมสำหรับ
//:myplatform
- ทรัพยากร Dependency ของโปรเจ็กต์เลือกเชนเครื่องมือที่เหมาะสมสำหรับ
//:myplatform
//:myplatform
อ้างอิง ประกาศทั่วไป ของCPU
,OS
และพร็อพเพอร์ตี้ทั่วไปอื่นๆ ที่ขึ้นอยู่กับภาษาselect()
ที่เกี่ยวข้องทั้งหมดตรงกับ//:myplatform
อย่างถูกต้อง//:myplatform
ได้รับการกำหนดไว้อย่างชัดเจนและเข้าถึงได้ โดยเป็นที่เก็บของโปรเจ็กต์ในกรณีที่แพลตฟอร์มนั้นไม่ซ้ำกับโปรเจ็กต์ของคุณ หรือที่ที่โปรเจ็กต์ที่ใช้ทั้งหมดทั่วไปสามารถค้นพบได้
ระบบจะเลิกใช้งานและนำแฟล็กเก่าอย่างเช่น --cpu
, --crosstool_top
และ --fat_apk_cpu
ออกทันทีที่สามารถทำได้
ท้ายที่สุดแล้ว วิธีนี้จะเป็นวิธีกำหนดค่าสถาปัตยกรรมเพียงอย่างเดียว
การย้ายข้อมูลโปรเจ็กต์
หากคุณสร้างด้วยภาษาที่รองรับแพลตฟอร์ม บิลด์ของคุณควรใช้งานได้ด้วยการเรียกใช้ เช่น
bazel build //:myproject --platforms=//:myplatform
ดูรายละเอียดอย่างละเอียดได้จากสถานะและเอกสารประกอบของภาษา
หากภาษาใดต้องมีแฟล็กเพื่อเปิดใช้การรองรับแพลตฟอร์ม คุณจะต้องตั้งค่าแฟล็กนั้นด้วย ดูรายละเอียดได้ที่สถานะ
คุณต้องตรวจสอบสิ่งต่อไปนี้ก่อนที่โปรเจ็กต์ที่จะสร้าง
ต้องมี
//:myplatform
โดยทั่วไปแล้ว เจ้าของโปรเจ็กต์จะมีหน้าที่กำหนดแพลตฟอร์ม เนื่องจากโปรเจ็กต์ต่างๆ จะกำหนดเป้าหมายไปยังเครื่องที่ต่างกัน ดูแพลตฟอร์มเริ่มต้นต้องมี Toolchain ที่ต้องการใช้อยู่ หากใช้เครื่องมือเชนหุ้น เจ้าของภาษาควรให้วิธีการลงทะเบียน หากเขียนห่วงโซ่เครื่องมือที่กำหนดเอง คุณจะต้องregisterห่วงโซ่เหล่านั้นใน
WORKSPACE
หรือ--extra_toolchains
select()
และการเปลี่ยนการกำหนดค่าต้องได้รับการแก้ไขอย่างถูกต้อง โปรดดู select() และการเปลี่ยนหากบิลด์ของคุณรวมภาษาที่มีและไม่รองรับแพลตฟอร์ม คุณอาจต้องการแมปแพลตฟอร์มเพื่อช่วยให้ภาษาเดิมทำงานร่วมกับ API ใหม่ได้ ดูรายละเอียดได้ที่การแมปแพลตฟอร์ม
หากยังพบปัญหาอยู่ โปรดติดต่อเพื่อขอรับการสนับสนุน
แพลตฟอร์มเริ่มต้น
เจ้าของโปรเจ็กต์ควรกำหนดแพลตฟอร์มที่ชัดเจนเพื่ออธิบายสถาปัตยกรรมที่ต้องการสร้าง ซึ่งจะทริกเกอร์ด้วย --platforms
เมื่อไม่ได้ตั้งค่า --platforms
Bazel จะกำหนดค่าเริ่มต้นเป็น platform
ที่แสดงถึงเครื่องบิลด์ภายใน ฟีเจอร์นี้จะสร้างขึ้นโดยอัตโนมัติที่ @local_config_platform//:host
คุณจึงไม่จำเป็นต้องระบุอย่างชัดเจน และแมป 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 รูปแบบระหว่างการย้ายข้อมูล
การย้ายข้อมูลชุดกฎ
หากเป็นเจ้าของชุดกฎและต้องการรองรับแพลตฟอร์ม คุณจะต้องทำดังนี้
กำหนด Toolchain ของกฎในการแปลค่าตรรกะด้วย Toolchain API โปรดดู toolchain API (
ctx.toolchains
)ไม่บังคับ: กำหนดแฟล็ก
--incompatible_enable_platforms_for_my_language
เพื่อให้ตรรกะของกฎแก้ไข Toolchain ผ่าน API ใหม่หรือแฟล็กเก่า เช่น--crosstool_top
ในระหว่างการทดสอบการย้ายข้อมูลกำหนดพร็อพเพอร์ตี้ที่เกี่ยวข้องซึ่งประกอบขึ้นเป็นคอมโพเนนต์ของแพลตฟอร์ม ดูพร็อพเพอร์ตี้แพลตฟอร์มทั่วไป
กำหนดห่วงโซ่เครื่องมือมาตรฐานและทำให้ผู้ใช้เข้าถึงได้ผ่านทางวิธีการลงทะเบียนของกฎ (รายละเอียด)
ตรวจสอบว่าแพลตฟอร์มการสนับสนุนของ
select()
และการเปลี่ยนการกำหนดค่า นี่เป็นความท้าทาย ที่ยิ่งใหญ่ที่สุด ซึ่งเป็นเรื่องที่ท้าทายอย่างยิ่งสำหรับโครงการหลายภาษา (ซึ่งอาจล้มเหลวหากภาษาทุกภาษาอ่าน--platforms
ไม่ได้)
หากต้องใช้ร่วมกับกฎที่ไม่รองรับแพลตฟอร์ม คุณอาจต้องการแมปแพลตฟอร์มเพื่อลดช่องว่าง
พร็อพเพอร์ตี้แพลตฟอร์มทั่วไป
ควรประกาศพร็อพเพอร์ตี้แพลตฟอร์มข้ามภาษาทั่วไป เช่น OS
และ CPU
ใน @platforms
ซึ่งส่งเสริมการแชร์ การกำหนดมาตรฐาน และความเข้ากันได้แบบข้ามภาษา
คุณควรประกาศพร็อพเพอร์ตี้เฉพาะสำหรับกฎในที่เก็บของกฎ ซึ่งช่วยให้คุณรักษาสิทธิ์การเป็นเจ้าของที่ชัดเจนต่อแนวคิดที่เจาะจงซึ่งกฎของคุณต้องรับผิดชอบ
หากกฎใช้ระบบปฏิบัติการหรือ CPU ที่มีวัตถุประสงค์ที่กำหนดเอง คุณควรประกาศสิ่งเหล่านี้ในที่เก็บของกฎเทียบกับ @platforms
การแมปแพลตฟอร์ม
การแมปแพลตฟอร์มเป็น API ชั่วคราวที่ช่วยให้ผสมผสานตรรกะแบบ Context-Aware กับตรรกะเดิมในบิลด์เดียวกันได้ เครื่องมือนี้เป็นเครื่องมือแบบทื่อที่มีจุดมุ่งหมายเพียงเพื่อช่วยลดความไม่เข้ากันระหว่างการย้ายข้อมูลที่แตกต่างกัน
การแมปแพลตฟอร์มคือแผนที่ของ platform()
กับชุดแฟล็กเดิมที่ตรงกันหรือแบบย้อนกลับ เช่น
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 ใช้ข้อมูลนี้เพื่อรับประกันว่าระบบจะใช้การตั้งค่าทั้งหมดทั้งตามแพลตฟอร์มและแบบเดิมตลอดบิลด์ รวมถึงผ่านการเปลี่ยนด้วย
โดยค่าเริ่มต้น 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
เป็นพร็อพเพอร์ตี้ของเครื่อง ค่า "ชนิด" เดียวกันจะจัดกลุ่มเป็น 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_value
เครื่องที่กำหนดเป้าหมายได้ (target_compatible_with = ["@platforms//os:linux"]
) และเครื่องที่เครื่องมือทำงานได้ (exec_compatible_with = ["@platforms//os:mac"]
)
เมื่อสร้าง $ bazel build //:myproject --platforms=//:myplatform
Bazel จะเลือก Toolchain ที่ทำงานในเครื่องบิลด์และสร้างไบนารีสำหรับ //:myplatform
ได้โดยอัตโนมัติ วิธีนี้เรียกว่าการแก้ปัญหาของ Toolchain
คุณจะลงทะเบียนชุดเครื่องมือที่ใช้ได้ใน WORKSPACE
ด้วยregister_toolchains
หรือในบรรทัดคำสั่งด้วย --extra_toolchains
ดูข้อมูลเพิ่มเติมที่นี่
คำถาม
หากต้องการการสนับสนุนทั่วไปและมีข้อสงสัยเกี่ยวกับไทม์ไลน์การย้ายข้อมูล โปรดติดต่อ bazel-discuss หรือเจ้าของกฎที่เหมาะสม
หากต้องการพูดคุยเกี่ยวกับการออกแบบและการพัฒนาของแพลตฟอร์ม/toolchain API โปรดติดต่อ bazel-dev