เชนเครื่องมือ

วันที่ รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

หน้านี้อธิบายเฟรมเวิร์ก 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 ที่กำหนด

  1. กฎเฉพาะภาษาที่แสดงถึงประเภทของเครื่องมือหรือชุดเครื่องมือ โดย ชื่อกฎนี้จะต่อท้ายด้วย "_toolchain"

    1. หมายเหตุ: กฎ \_toolchain สร้างการดำเนินการบิลด์ไม่ได้ แต่เป็นการรวบรวมอาร์ติแฟกต์จากกฎอื่นๆ แล้วส่งต่อไปยัง ที่ใช้ Toolchain กฎนั้นมีหน้าที่สร้าง การทำงานของบิลด์
  2. เป้าหมายหลายอย่างของกฎนี้ โดยแสดงถึงเวอร์ชันของเครื่องมือหรือเครื่องมือ สำหรับแพลตฟอร์มต่างๆ

  3. สำหรับเป้าหมายดังกล่าวแต่ละรายการ เป้าหมายที่เกี่ยวข้องของเป้าหมายทั่วไป 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",
)

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

ขั้นตอนการแก้ปัญหามีดังนี้

  1. วรรค target_compatible_with หรือ exec_compatible_with ตรงกับ แพลตฟอร์ม หากมีแต่ละ constraint_value ในรายการ constraint_value นั้น (โดยชัดเจนหรือเป็นค่าเริ่มต้น)

    หากแพลตฟอร์มมี constraint_value วินาทีจาก constraint_setting วินาที ที่อ้างอิงตามวรรคผลิตภัณฑ์เหล่านี้จะไม่มีผลต่อการจับคู่

  2. หากเป้าหมายที่กำลังสร้างระบุพารามิเตอร์ แอตทริบิวต์ exec_compatible_with (หรือคำจำกัดความของกฎระบุ อาร์กิวเมนต์ exec_compatible_with) ระบบจะกรองรายการแพลตฟอร์มการดำเนินการที่ใช้ได้เพื่อนำออก รายการที่ไม่ตรงกับข้อจำกัดในการดำเนินการ

  3. สำหรับแพลตฟอร์มการดำเนินการที่ใช้ได้แต่ละรายการ คุณจะต้องเชื่อมโยง Toolchain แต่ละประเภทกับ Toolchain แรกที่พร้อมใช้งาน (หากมี) ที่ใช้กับการดําเนินการนี้ได้ แพลตฟอร์มและแพลตฟอร์มเป้าหมาย

  4. แพลตฟอร์มการดำเนินการที่ค้นหา 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