หน้านี้อธิบายเฟรมเวิร์ก Toolchain ซึ่งเป็นวิธีที่ผู้เขียนกฎสามารถ แยกตรรกะกฎจากการเลือกเครื่องมือตามแพลตฟอร์ม ใช่เลย ขอแนะนำให้อ่านกฎและแพลตฟอร์ม ก่อนที่จะดำเนินการต่อ หน้านี้จะอธิบายถึงเหตุผลที่ต้องใช้ Toolchain ดังกล่าวแล้ว วิธีการ กําหนดและใช้งาน รวมถึงวิธีที่ Bazel เลือกเครื่องมือเชนที่เหมาะสม โดยพิจารณาจาก ข้อจำกัดของแพลตฟอร์ม
แรงจูงใจ
เรามาดูกันที่เครื่องมือแก้ปัญหาที่ออกแบบมาเพื่อแก้ไขกันก่อน สมมติว่าคุณ
กำลังเขียนกฎเพื่อสนับสนุน "แถบ" ภาษาโปรแกรม bar_binary
ของคุณ
ระบบจะคอมไพล์ไฟล์ *.bar
โดยใช้คอมไพเลอร์ barc
ซึ่งเป็นเครื่องมือที่
สร้างเป็นเป้าหมายอีกเป้าหมายหนึ่งในพื้นที่ทํางาน เนื่องจากผู้ใช้ที่เขียน bar_binary
ไม่ควรระบุการพึ่งพาในคอมไพเลอร์ จึงเป็น
การขึ้นต่อกันโดยปริยายโดยการเพิ่มไว้ในคำจำกัดความของกฎเป็นแอตทริบิวต์ส่วนตัว
bar_binary = rule(
implementation = _bar_binary_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
...
"_compiler": attr.label(
default = "//bar_tools:barc_linux", # the compiler running on linux
providers = [BarcInfo],
),
},
)
//bar_tools:barc_linux
เป็นทรัพยากร Dependency ของเป้าหมาย bar_binary
ทุกๆ เป้าหมายแล้ว ดังนั้น
โดยจะสร้างขึ้นก่อนเป้าหมาย bar_binary
ใดๆ สามารถเข้าถึงได้โดย
ฟังก์ชันการใช้งานเช่นเดียวกับแอตทริบิวต์อื่นๆ
BarcInfo = provider(
doc = "Information about how to invoke the barc compiler.",
# In the real world, compiler_path and system_lib might hold File objects,
# but for simplicity they are strings for this example. arch_flags is a list
# of strings.
fields = ["compiler_path", "system_lib", "arch_flags"],
)
def _bar_binary_impl(ctx):
...
info = ctx.attr._compiler[BarcInfo]
command = "%s -l %s %s" % (
info.compiler_path,
info.system_lib,
" ".join(info.arch_flags),
)
...
ปัญหาก็คือป้ายกำกับของคอมไพเลอร์ได้รับการฮาร์ดโค้ดเป็น bar_binary
เป้าหมายที่แตกต่างกันอาจต้องใช้คอมไพเลอร์ที่แตกต่างกัน ขึ้นอยู่กับแพลตฟอร์มที่พวกเขา
สร้างขึ้นเพื่อแพลตฟอร์มใดและแพลตฟอร์มที่พวกเขากำลังสร้างขึ้น ซึ่งเรียกว่า
แพลตฟอร์มเป้าหมายและแพลตฟอร์มการดำเนินการตามลำดับ นอกจากนี้ กฎ
ไม่จำเป็นที่จะต้องรู้จักเครื่องมือและแพลตฟอร์ม
ที่มีอยู่ทั้งหมด ดังนั้น
เป็นไปไม่ได้ที่จะฮาร์ดโค้ดแท็กไว้ในคำจำกัดความของกฎ
ทางออกที่ไม่ค่อยทันสมัยคือ สร้างภาระให้ผู้ใช้ โดยทำให้
แอตทริบิวต์ _compiler
แบบไม่เป็นส่วนตัว เป้าหมายแต่ละรายการอาจเป็น
ฮาร์ดโค้ดเพื่อสร้าง
สำหรับแพลตฟอร์มใดแพลตฟอร์มหนึ่ง
bar_binary(
name = "myprog_on_linux",
srcs = ["mysrc.bar"],
compiler = "//bar_tools:barc_linux",
)
bar_binary(
name = "myprog_on_windows",
srcs = ["mysrc.bar"],
compiler = "//bar_tools:barc_windows",
)
คุณสามารถปรับปรุงโซลูชันนี้ได้โดยใช้ select
เพื่อเลือก compiler
อิงตามแพลตฟอร์ม
config_setting(
name = "on_linux",
constraint_values = [
"@platforms//os:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@platforms//os:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
แต่สิ่งนี้น่าเบื่อหน่ายและค่อนข้างมากที่จะถามผู้ใช้ bar_binary
ทุกคน
หากใช้สไตล์นี้อย่างไม่สม่ำเสมอทั่วทั้งพื้นที่ทำงาน จะนำไปสู่
ที่ทำงานได้ดีบนแพลตฟอร์มเดียว แต่ล้มเหลวเมื่อขยายไปยัง
หลายแพลตฟอร์ม และไม่ได้ช่วยแก้ปัญหาของการเพิ่มการสนับสนุน
สำหรับแพลตฟอร์มและคอมไพเลอร์ใหม่ๆ โดยไม่มีการปรับเปลี่ยนกฎหรือเป้าหมายที่มีอยู่
เฟรมเวิร์กเครื่องมือเชนจะแก้ปัญหานี้ด้วยการเพิ่มระดับ ทางอ้อม โดยพื้นฐานแล้ว คุณประกาศว่ากฎของคุณมีการขึ้นต่อกันแบบนามธรรม ในสมาชิกบางส่วนในกลุ่มเป้าหมาย (ประเภทเครื่องมือโซ่) และ Bazel จะแก้ไขปัญหานี้กับเป้าหมายหนึ่งๆ (เครื่องมือเชน) โดยอัตโนมัติโดยอิงตาม ข้อจำกัดแพลตฟอร์มที่เกี่ยวข้อง ไม่ใช่ทั้งผู้เขียนกฎและผู้เขียนเป้าหมาย จำเป็นต้องทราบชุดแพลตฟอร์มและ Toolchain ที่มีให้ใช้งานทั้งหมด
การเขียนกฎที่ใช้ Toolchain
ภายใต้เฟรมเวิร์ก Toolchain นั้น แทนที่จะมีกฎที่ต้องอาศัยเครื่องมือโดยตรง แต่จะขึ้นอยู่กับประเภทเครื่องมือเชนแทน ประเภท Toolchain เป็นเป้าหมายที่เรียบง่าย ที่แสดงถึงคลาสของเครื่องมือที่ทำงานเดียวกันสำหรับ ใหม่ เช่น ประกาศประเภทที่แสดงถึงแถบ คอมไพเลอร์:
# By convention, toolchain_type targets are named "toolchain_type" and
# distinguished by their package path. So the full path for this would be
# //bar_tools:toolchain_type.
toolchain_type(name = "toolchain_type")
คำจำกัดความกฎในส่วนก่อนหน้านี้มีการแก้ไขเพื่อให้
ที่นำคอมไพเลอร์เป็นแอตทริบิวต์
ระบบแจ้งว่าคีย์นี้ต้องใช้
เครื่องมือเชน //bar_tools:toolchain_type
bar_binary = rule(
implementation = _bar_binary_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
...
# No `_compiler` attribute anymore.
},
toolchains = ["//bar_tools:toolchain_type"],
)
ตอนนี้ฟังก์ชันการติดตั้งใช้งานเข้าถึงทรัพยากร Dependency นี้ภายใต้ ctx.toolchains
แล้ว
แทน ctx.attr
โดยใช้ประเภท Toolchain เป็นคีย์
def _bar_binary_impl(ctx):
...
info = ctx.toolchains["//bar_tools:toolchain_type"].barcinfo
# The rest is unchanged.
command = "%s -l %s %s" % (
info.compiler_path,
info.system_lib,
" ".join(info.arch_flags),
)
...
ctx.toolchains["//bar_tools:toolchain_type"]
แสดงผล
ผู้ให้บริการ ToolchainInfo
ราย
ของเป้าหมายที่ Bazel แก้ไขการพึ่งพา Toolchain ฟิลด์ของ
ออบเจ็กต์ ToolchainInfo
ได้รับการตั้งค่าโดยกฎของเครื่องมือที่สำคัญ ในช่วงต่อจากนี้
กฎนี้จะกำหนดให้มีฟิลด์ barcinfo
ที่รวม
BarcInfo
มีการอธิบายขั้นตอนของการแปลเครื่องมือเชนของ Bazel กับเป้าหมาย
ด้านล่าง จริงๆ แล้วเฉพาะเป้าหมาย Toolchain ที่แก้ไขแล้วเท่านั้น
อิงตามเป้าหมาย bar_binary
ไม่ใช่พื้นที่ทั้งหมดของผู้สมัคร
Toolchain
เชนเครื่องมือที่จำเป็นและที่ไม่บังคับ
โดยค่าเริ่มต้น เมื่อกฎแสดงทรัพยากร Dependency ของประเภท Toolchain โดยใช้ป้ายกำกับเปล่า (ดังที่แสดงด้านบน) ประเภท Toolchain ถือเป็นจำเป็น ถ้า Bazel ไม่พบ Toolchain ที่ตรงกัน (โปรดดู ความละเอียดของ Toolchain ด้านล่าง) สำหรับ Toolchain ที่จำเป็น เป็นประเภทข้อผิดพลาดและการหยุดวิเคราะห์
คุณอาจประกาศทรัพยากร Dependency ของประเภท Toolchain ที่ไม่บังคับแทนได้ เนื่องจาก ดังต่อไปนี้:
bar_binary = rule(
...
toolchains = [
config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
],
)
เมื่อแก้ไขประเภท Toolchain ที่ไม่บังคับไม่ได้ การวิเคราะห์จะดำเนินต่อไป และ
ผลลัพธ์ของ ctx.toolchains["//bar_tools:toolchain_type"]
คือ None
config_common.toolchain_type
มีค่าเริ่มต้นเป็น "บังคับ"
คุณใช้แบบฟอร์มต่อไปนี้ได้
- ประเภท Toolchain ที่จำเป็นมีดังนี้
toolchains = ["//bar_tools:toolchain_type"]
toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type")]
toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = True)]
- ประเภท Toolchain ที่ไม่บังคับมีดังนี้
toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False)]
bar_binary = rule(
...
toolchains = [
"//foo_tools:toolchain_type",
config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
],
)
นอกจากนี้ยังผสมผสานแบบฟอร์มในกฎเดียวกันได้ด้วย แต่หาก มีการแสดงประเภท Toolchain หลายครั้ง ซึ่งจะเป็นเวอร์ชันที่เข้มงวดที่สุด ในกรณีที่ข้อบังคับเข้มงวดกว่าแบบไม่บังคับ
การเขียนด้านต่างๆ ที่ใช้ Toolchain
Aspects มีสิทธิ์เข้าถึง Toolchain API เดียวกับกฎ ซึ่งคุณสามารถกำหนด ประเภท Toolchain เข้าถึง Toolchain ผ่านบริบท และใช้ข้อมูลดังกล่าวเพื่อสร้างใหม่ โดยใช้ Toolchain
bar_aspect = aspect(
implementation = _bar_aspect_impl,
attrs = {},
toolchains = ['//bar_tools:toolchain_type'],
)
def _bar_aspect_impl(target, ctx):
toolchain = ctx.toolchains['//bar_tools:toolchain_type']
# Use the toolchain provider like in a rule.
return []
การกำหนด Toolchain
คุณต้องมี 3 สิ่งต่อไปนี้เพื่อกำหนด Toolchain บางประเภทสำหรับประเภท Toolchain ที่กำหนด
กฎเฉพาะภาษาที่แสดงถึงประเภทของเครื่องมือหรือชุดเครื่องมือ โดย ชื่อกฎนี้จะต่อท้ายด้วย "_toolchain"
- หมายเหตุ: กฎ
\_toolchain
สร้างการดำเนินการบิลด์ไม่ได้ แต่เป็นการรวบรวมอาร์ติแฟกต์จากกฎอื่นๆ แล้วส่งต่อไปยัง ที่ใช้ Toolchain กฎนั้นมีหน้าที่สร้าง การทำงานของบิลด์
- หมายเหตุ: กฎ
เป้าหมายหลายอย่างของกฎนี้ โดยแสดงถึงเวอร์ชันของเครื่องมือหรือเครื่องมือ สำหรับแพลตฟอร์มต่างๆ
สำหรับเป้าหมายดังกล่าวแต่ละรายการ เป้าหมายที่เกี่ยวข้องของเป้าหมายทั่วไป
toolchain
เพื่อระบุข้อมูลเมตาที่เฟรมเวิร์กเครื่องมือเชนใช้toolchain
เครื่องนี้ target ยังหมายถึงtoolchain_type
ที่เชื่อมโยงกับ Toolchain นี้ด้วย ซึ่งหมายความว่ากฎ_toolchain
ที่ระบุอาจเชื่อมโยงกับtoolchain_type
และเฉพาะในอินสแตนซ์toolchain
ที่ใช้ กฎ_toolchain
นี้ที่กฎเชื่อมโยงกับtoolchain_type
สำหรับตัวอย่างการทำงานของเรา นี่คือคำจำกัดความของกฎ bar_toolchain
ตัวอย่างเช่น มีเพียงคอมไพเลอร์ แต่เครื่องมืออื่นๆ เช่น Linker ยังอาจ
ที่จัดกลุ่มไว้ใต้บทความนั้น
def _bar_toolchain_impl(ctx):
toolchain_info = platform_common.ToolchainInfo(
barcinfo = BarcInfo(
compiler_path = ctx.attr.compiler_path,
system_lib = ctx.attr.system_lib,
arch_flags = ctx.attr.arch_flags,
),
)
return [toolchain_info]
bar_toolchain = rule(
implementation = _bar_toolchain_impl,
attrs = {
"compiler_path": attr.string(),
"system_lib": attr.string(),
"arch_flags": attr.string_list(),
},
)
กฎจะต้องแสดงผลผู้ให้บริการ ToolchainInfo
ซึ่งจะกลายเป็นออบเจ็กต์ที่
กฎการใช้จะดึงข้อมูลโดยใช้ ctx.toolchains
และป้ายกำกับของ
Toolchain ToolchainInfo
เช่น struct
จะมีค่าฟิลด์ที่กำหนดเองได้
คู่ ข้อกำหนดเฉพาะของฟิลด์ที่จะเพิ่มลงใน ToolchainInfo
ควรระบุไว้อย่างชัดเจนที่ประเภท Toolchain ในตัวอย่างนี้ ค่า
แสดงผลในออบเจ็กต์ BarcInfo
เพื่อใช้สคีมาที่กําหนดไว้ข้างต้นซ้ำ นี้
น่าจะมีประโยชน์ในการตรวจสอบความถูกต้องและใช้โค้ดซ้ำ
ตอนนี้คุณสามารถกำหนดเป้าหมายสำหรับคอมไพเลอร์ barc
ที่เฉพาะเจาะจงได้แล้ว
bar_toolchain(
name = "barc_linux",
arch_flags = [
"--arch=Linux",
"--debug_everything",
],
compiler_path = "/path/to/barc/on/linux",
system_lib = "/usr/lib/libbarc.so",
)
bar_toolchain(
name = "barc_windows",
arch_flags = [
"--arch=Windows",
# Different flags, no debug support on windows.
],
compiler_path = "C:\\path\\on\\windows\\barc.exe",
system_lib = "C:\\path\\on\\windows\\barclib.dll",
)
ขั้นตอนสุดท้าย คุณสร้างคำจำกัดความ toolchain
สำหรับเป้าหมาย bar_toolchain
2 รายการ
คําจํากัดความเหล่านี้จะลิงก์เป้าหมายเฉพาะภาษากับประเภทเครื่องมือเชนและ
ระบุข้อมูลข้อจำกัดที่จะบอก Bazel เมื่อ Toolchain
เหมาะสมกับแพลตฟอร์มนั้นๆ
toolchain(
name = "barc_linux_toolchain",
exec_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
toolchain = ":barc_linux",
toolchain_type = ":toolchain_type",
)
toolchain(
name = "barc_windows_toolchain",
exec_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
toolchain = ":barc_windows",
toolchain_type = ":toolchain_type",
)
การใช้ไวยากรณ์เส้นทางแบบสัมพัทธ์ข้างต้นจะชี้ว่าคำจำกัดความเหล่านี้จะอยู่ใน
แพ็กเกจเดียวกัน แต่ไม่มีเหตุผลที่ทำให้ประเภท Toolchain เจาะจงภาษา
เป้าหมายเครื่องมือเชนและเป้าหมายคำจำกัดความ toolchain
รายการต้องแยกกันอยู่ไม่ได้
แพ็กเกจของคุณ
โปรดดูgo_toolchain
สำหรับตัวอย่างที่เกิดขึ้นจริง
เชนเครื่องมือและการกำหนดค่า
คำถามสำคัญสำหรับผู้เขียนกฎก็คือ เมื่อเป้าหมาย bar_toolchain
คือ
ได้วิเคราะห์ว่า การกำหนดค่า เห็นอะไร และการเปลี่ยนแปลงใด
ควรใช้สำหรับทรัพยากร Dependency หรือไม่ ตัวอย่างด้านบนใช้แอตทริบิวต์สตริง แต่
จะเกิดอะไรขึ้นกับ Toolchain ที่ซับซ้อนมากขึ้นซึ่งขึ้นอยู่กับเป้าหมายอื่นๆ
ในที่เก็บ Bazel ไหม
มาดู bar_toolchain
เวอร์ชันที่ซับซ้อนขึ้นกัน
def _bar_toolchain_impl(ctx):
# The implementation is mostly the same as above, so skipping.
pass
bar_toolchain = rule(
implementation = _bar_toolchain_impl,
attrs = {
"compiler": attr.label(
executable = True,
mandatory = True,
cfg = "exec",
),
"system_lib": attr.label(
mandatory = True,
cfg = "target",
),
"arch_flags": attr.string_list(),
},
)
การใช้ attr.label
จะเหมือนกับการใช้กฎมาตรฐาน
แต่ความหมายของพารามิเตอร์ cfg
นั้นต่างกันเล็กน้อย
ทรัพยากร Dependency จากเป้าหมาย (เรียกว่า "หลัก") ไปยัง Toolchain ผ่าน Toolchain
การแก้ปัญหาจะใช้การเปลี่ยนการกำหนดค่าพิเศษที่เรียกว่า "toolchain
การเปลี่ยนแปลง" การเปลี่ยนเครื่องมือเชนจะคงการกำหนดค่าไว้เหมือนเดิม ยกเว้น
ซึ่งจะบังคับให้แพลตฟอร์มการดำเนินการสำหรับ Toolchain เหมือนกัน
หลัก (ไม่เช่นนั้น การแปลง Toolchain สำหรับ Toolchain สามารถเลือก
และไม่จำเป็นต้องเหมือนกับแพลตฟอร์มหลัก) ช่วงเวลานี้
ช่วยให้ทรัพยากร Dependency ของ exec
ของ Toolchain สามารถสั่งการสำหรับ
การดำเนินการบิลด์ของผู้ปกครอง ทรัพยากร Dependency ของ Toolchain ที่ใช้ cfg =
"target"
(หรือที่ไม่ได้ระบุ cfg
เนื่องจาก "target" เป็นค่าเริ่มต้น) มีดังนี้
สำหรับแพลตฟอร์มเป้าหมายเดียวกับ
แพลตฟอร์มหลัก ซึ่งจะช่วยให้กฎเครื่องมือเชนสามารถ
มีส่วนร่วมทั้งไลบรารี (แอตทริบิวต์ system_lib
ด้านบน) และเครื่องมือ (
compiler
) ไปยังกฎบิลด์ที่จำเป็นต้องใช้ ไลบรารีระบบ
จะเชื่อมโยงกับอาร์ติแฟกต์สุดท้าย และจึงต้องสร้างขึ้นสำหรับ
ในขณะที่คอมไพเลอร์เป็นเครื่องมือที่นำมาใช้ระหว่างการสร้าง และ
สามารถทำงานบนแพลตฟอร์มการดำเนินการได้
การลงทะเบียนและการสร้างด้วย Toolchain
ณ จุดนี้ ได้มีการนำองค์ประกอบทั้งหมดมาประกอบกัน แล้วคุณก็แค่ทำให้
Toolchain ที่มีให้ใช้งานสำหรับขั้นตอนการแก้ปัญหาของ Bazel ซึ่งทำโดย
การลงทะเบียน Toolchain ในไฟล์ WORKSPACE
โดยใช้
register_toolchains()
หรือโดยการส่งผ่าน Toolchain ป้ายกำกับในคำสั่ง
โดยใช้แฟล็ก --extra_toolchains
register_toolchains(
"//bar_tools:barc_linux_toolchain",
"//bar_tools:barc_windows_toolchain",
# Target patterns are also permitted, so you could have also written:
# "//bar_tools:all",
# or even
# "//bar_tools/...",
)
เมื่อใช้รูปแบบเป้าหมายในการลงทะเบียน Toolchain คำสั่งซื้อที่ จะมีการจดทะเบียน Toolchain แต่ละรายการจะกำหนดตามกฎต่อไปนี้
- Toolchains ที่กำหนดไว้ในแพ็กเกจย่อยของแพ็กเกจจะได้รับการลงทะเบียนก่อน Toolchains ที่กำหนดไว้ในแพ็กเกจเอง
- ภายในแพ็กเกจ มีการลงทะเบียน Toolchain ในลำดับแบบพจนานุกรมดังนี้ ชื่อของพวกเขา
ตอนนี้เมื่อคุณสร้างเป้าหมายที่ขึ้นอยู่กับประเภท Toolchain ระบบจะเลือก Toolchain ตามแพลตฟอร์มเป้าหมายและการดำเนินการ
# my_pkg/BUILD
platform(
name = "my_target_platform",
constraint_values = [
"@platforms//os:linux",
],
)
bar_binary(
name = "my_bar_binary",
...
)
bazel build //my_pkg:my_bar_binary --platforms=//my_pkg:my_target_platform
Bazel จะเห็นว่า //my_pkg:my_bar_binary
กำลังสร้างขึ้นด้วยแพลตฟอร์มที่
มี @platforms//os:linux
ดังนั้นจึงระบุค่า
//bar_tools:toolchain_type
อ้างอิงไปยัง //bar_tools:barc_linux_toolchain
การดำเนินการนี้จะเป็นการสร้าง //bar_tools:barc_linux
แต่ไม่
//bar_tools:barc_windows
ความละเอียดของ Toolchain
สําหรับเป้าหมายแต่ละรายการที่ใช้ Toolchain นั้น ขั้นตอนการแก้ไข Toolchain ของ Bazel ระบุทรัพยากร Dependency ของ Toolchain ที่เป็นรูปธรรมของเป้าหมาย กระบวนการนี้จะใช้เป็นอินพุต ชุดประเภท Toolchain ที่จำเป็น แพลตฟอร์มเป้าหมาย และรายการที่พร้อมใช้งาน แพลตฟอร์มการดำเนินการ และรายการ Toolchain ที่ใช้ได้ ซึ่งเอาต์พุตคือ Toolchain ที่เลือกสำหรับ Toolchain แต่ละประเภท รวมถึงการดําเนินการที่เลือก แพลตฟอร์มสำหรับเป้าหมายปัจจุบัน
แพลตฟอร์มการดำเนินการและ Toolchain ที่ใช้ได้รวบรวมมาจาก
WORKSPACE
ไฟล์ผ่าน
register_execution_platforms
และ
register_toolchains
รวมทั้งอาจระบุแพลตฟอร์มและ Toolchain สำหรับการดำเนินการเพิ่มเติมไว้ในไฟล์
บรรทัดคำสั่งผ่าน
--extra_execution_platforms
และ
--extra_toolchains
ระบบจะรวมแพลตฟอร์มโฮสต์ไว้เป็นแพลตฟอร์มการดำเนินการที่พร้อมใช้งานโดยอัตโนมัติ
แพลตฟอร์มและ Toolchain ที่พร้อมใช้งานจะได้รับการติดตามเป็นรายการตามลำดับสำหรับการกำหนด
ด้วยค่ากำหนดที่กำหนดให้กับรายการก่อนหน้าในลิสต์
ชุด Toolchain ที่มีให้ใช้งานตามลำดับความสำคัญนั้นสร้างขึ้นจาก
--extra_toolchains
และ register_toolchains
:
- ระบบจะเพิ่มเครื่องมือเชนที่ลงทะเบียนโดยใช้
--extra_toolchains
ก่อน- ภายในเครื่องมือเหล่านี้ เครื่องมือเชนสุดท้ายมีลำดับความสำคัญสูงสุด
- Toolchains ที่ลงทะเบียนโดยใช้
register_toolchains
- ภายในเครื่องมือเหล่านี้ Toolchain แรกที่กล่าวถึงมีลำดับความสำคัญสูงสุด
หมายเหตุ: เป้าหมายที่ไม่เป็นจริง เช่น :all
, :*
และ
/...
สั่งซื้อตามแพ็กเกจของ Bazel
กลไกการโหลด ซึ่งใช้การเรียงลำดับแบบพจนานุกรม
ขั้นตอนการแก้ปัญหามีดังนี้
วรรค
target_compatible_with
หรือexec_compatible_with
ตรงกับ แพลตฟอร์ม หากมีแต่ละconstraint_value
ในรายการconstraint_value
นั้น (โดยชัดเจนหรือเป็นค่าเริ่มต้น)หากแพลตฟอร์มมี
constraint_value
วินาทีจากconstraint_setting
วินาที ที่อ้างอิงตามวรรคผลิตภัณฑ์เหล่านี้จะไม่มีผลต่อการจับคู่หากเป้าหมายที่กำลังสร้างระบุพารามิเตอร์ แอตทริบิวต์
exec_compatible_with
(หรือคำจำกัดความของกฎระบุ อาร์กิวเมนต์exec_compatible_with
) ระบบจะกรองรายการแพลตฟอร์มการดำเนินการที่ใช้ได้เพื่อนำออก รายการที่ไม่ตรงกับข้อจำกัดในการดำเนินการสำหรับแพลตฟอร์มการดำเนินการที่ใช้ได้แต่ละรายการ คุณจะต้องเชื่อมโยง Toolchain แต่ละประเภทกับ Toolchain แรกที่พร้อมใช้งาน (หากมี) ที่ใช้กับการดําเนินการนี้ได้ แพลตฟอร์มและแพลตฟอร์มเป้าหมาย
แพลตฟอร์มการดำเนินการที่ค้นหา Toolchain ที่บังคับซึ่งเข้ากันไม่ได้ สำหรับประเภท Toolchain ประเภทใดประเภทหนึ่งถูกตัด ในแพลตฟอร์มอื่นๆ ที่เหลือ รายการแรกจะเป็นแพลตฟอร์มดำเนินการของเป้าหมายปัจจุบัน และที่เกี่ยวข้อง Toolchains (หากมี) จะกลายเป็น Dependency ของเป้าหมาย
แพลตฟอร์มการดำเนินการที่เลือกไว้จะใช้เพื่อเรียกใช้การดำเนินการทั้งหมดที่การกำหนดเป้าหมาย สร้างได้
ในกรณีที่สามารถสร้างเป้าหมายเดียวกันในการกำหนดค่าหลายรายการ (เช่น สำหรับ CPU ที่ต่างกัน) ภายในบิลด์เดียวกัน ระบบจะใช้กระบวนการแก้ปัญหา กับเป้าหมายแต่ละเวอร์ชันแยกกัน
หากกฎใช้กลุ่มการดำเนินการ การดำเนินการแต่ละรายการ จะดำเนินการกับการแปลง Toolchain แยกกันและมีการดำเนินการเป็นของตนเอง แพลตฟอร์มและ Toolchain
การแก้ไขข้อบกพร่องเกี่ยวกับโซ่เครื่องมือ
หากคุณกำลังเพิ่มการสนับสนุน Toolchain ในกฎที่มีอยู่ ให้ใช้
แฟล็ก --toolchain_resolution_debug=regex
ระหว่างการแปลง Toolchain นั้น
ให้เอาต์พุตแบบละเอียดสำหรับประเภท Toolchain หรือชื่อเป้าหมายที่ตรงกับตัวแปรนิพจน์ทั่วไป คุณ
สามารถใช้ .*
เพื่อแสดงข้อมูลทั้งหมด Bazel จะแสดงชื่อของเครื่องมือเชน
ตรวจสอบและข้ามระหว่างกระบวนการแก้ปัญหา
หากต้องการดูว่าทรัพยากร Dependency ของ cquery
ใดมาจาก Toolchain
ความละเอียด ให้ใช้แฟล็ก --transitions
ของ cquery
:
# Find all direct dependencies of //cc:my_cc_lib. This includes explicitly
# declared dependencies, implicit dependencies, and toolchain dependencies.
$ bazel cquery 'deps(//cc:my_cc_lib, 1)'
//cc:my_cc_lib (96d6638)
@bazel_tools//tools/cpp:toolchain (96d6638)
@bazel_tools//tools/def_parser:def_parser (HOST)
//cc:my_cc_dep (96d6638)
@local_config_platform//:host (96d6638)
@bazel_tools//tools/cpp:toolchain_type (96d6638)
//:default_host_platform (96d6638)
@local_config_cc//:cc-compiler-k8 (HOST)
//cc:my_cc_lib.cc (null)
@bazel_tools//tools/cpp:grep-includes (HOST)
# Which of these are from toolchain resolution?
$ bazel cquery 'deps(//cc:my_cc_lib, 1)' --transitions=lite | grep "toolchain dependency"
[toolchain dependency]#@local_config_cc//:cc-compiler-k8#HostTransition -> b6df211