การทำงานกับทรัพยากร Dependency ภายนอก

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

Bazel อาจขึ้นอยู่กับเป้าหมายจากโปรเจ็กต์อื่นๆ ทรัพยากร Dependency จากการแสดงผลอื่นๆ เหล่านี้ โปรเจ็กต์เรียกว่าทรัพยากร Dependency ภายนอก

ไฟล์ WORKSPACE (หรือ WORKSPACE.bazel ไฟล์) ใน ไดเรกทอรี workspace บอก Bazel ถึงวิธีรับโปรเจ็กต์อื่นๆ แหล่งที่มา โปรเจ็กต์อื่นๆ เหล่านี้สามารถ มีไฟล์ BUILD อย่างน้อย 1 ไฟล์ที่มีเป้าหมายของตนเอง BUILD ไฟล์ภายใน โปรเจ็กต์หลักสามารถขึ้นอยู่กับเป้าหมายภายนอกเหล่านี้โดยใช้ชื่อจาก ไฟล์ WORKSPACE

ตัวอย่างเช่น สมมติว่าระบบหนึ่งมี 2 โปรเจ็กต์:

/
  home/
    user/
      project1/
        WORKSPACE
        BUILD
        srcs/
          ...
      project2/
        WORKSPACE
        BUILD
        my-libs/

หาก project1 ต้องการขึ้นอยู่กับเป้าหมาย :foo ซึ่งกำหนดไว้ใน /home/user/project2/BUILD อาจระบุที่เก็บชื่อ project2 อยู่ที่ /home/user/project2 จากนั้นกำหนดเป้าหมายเป็น /home/user/project1/BUILD อาจขึ้นอยู่กับ @project2//:foo

ไฟล์ WORKSPACE ช่วยให้ผู้ใช้อ้างอิงเป้าหมายจากส่วนอื่นๆ ของ ระบบไฟล์หรือดาวน์โหลดจากอินเทอร์เน็ต ใช้ไวยากรณ์เดียวกันกับ BUILD แต่อนุญาตให้ใช้กฎชุดอื่นซึ่งเรียกว่ากฎที่เก็บ (บางครั้ง หรือที่เรียกว่ากฎพื้นที่ทำงาน) Bazel มาพร้อมกล่อง 2-3 ตัว กฎที่เก็บในตัวและชุดของ กฎที่เก็บ Starlark ที่ฝัง ผู้ใช้ยังเขียนกฎที่เก็บที่กำหนดเองได้ด้วย เพื่อให้ได้พฤติกรรมที่ซับซ้อนยิ่งขึ้น

ประเภทของทรัพยากร Dependency ภายนอกที่รองรับ

ประเภททรัพยากร Dependency ภายนอกพื้นฐานที่นำมาใช้ได้มีดังนี้

ขึ้นอยู่กับโปรเจ็กต์ Bazel อื่นๆ

หากต้องการใช้เป้าหมายจากโปรเจ็กต์ Bazel ที่สอง คุณสามารถ ใช้ local_repository git_repository หรือ http_archive เพื่อลิงก์สัญลักษณ์จากระบบไฟล์ในเครื่อง อ้างอิงที่เก็บ Git หรือดาวน์โหลด ตามลำดับ

ตัวอย่างเช่น สมมติว่าคุณกำลังทำโครงการ my-project/ และคุณต้องการให้ จะขึ้นอยู่กับเป้าหมายจากโปรเจ็กต์ของเพื่อนร่วมงานชื่อ coworkers-project/ ทั้ง 2 อย่าง ใช้ Bazel คุณจึงเพิ่มโปรเจ็กต์ของเพื่อนร่วมงานเป็นบุคคลภายนอกได้ ที่ต้องพึ่งพากัน จากนั้นใช้เป้าหมายที่เพื่อนร่วมงานกำหนดไว้จากตัวคุณเอง สร้างไฟล์ คุณจะต้องเพิ่มสิ่งต่อไปนี้ลงใน my_project/WORKSPACE

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

หากเพื่อนร่วมงานมี //foo:bar เป้าหมาย โปรเจ็กต์จะเรียกว่า @coworkers_project//foo:bar ชื่อโปรเจ็กต์ภายนอกต้องเป็น ชื่อพื้นที่ทำงานที่ถูกต้อง

ขึ้นอยู่กับโปรเจ็กต์ที่ไม่ใช่ Bazel

กฎที่ขึ้นต้นด้วย new_ เช่น new_local_repository, ช่วยให้คุณสร้างเป้าหมายจากโปรเจ็กต์ที่ไม่ใช้ Bazel

ตัวอย่างเช่น สมมติว่าคุณกำลังทำโครงการ my-project/ และคุณต้องการให้ จะขึ้นอยู่กับโปรเจ็กต์ของเพื่อนร่วมงานชื่อ coworkers-project/ ของเพื่อนร่วมงาน โปรเจ็กต์ใช้ make เพื่อสร้าง แต่คุณต้องการใช้ไฟล์ .so ไฟล์ใดไฟล์หนึ่ง ที่คิดค้นขึ้น วิธีการคือ ให้เพิ่มค่าต่อไปนี้ลงใน my_project/WORKSPACE

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file ระบุไฟล์ BUILD ที่จะวางซ้อนบนโปรเจ็กต์ที่มีอยู่ ตัวอย่าง:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

จากนั้นคุณสามารถใช้ @coworkers_project//:some-lib จากโปรเจ็กต์ของคุณ BUILD ไฟล์

ขึ้นอยู่กับแพ็กเกจภายนอก

อาร์ติแฟกต์และที่เก็บของ Maven

ใช้ชุดกฎ rules_jvm_external เพื่อดาวน์โหลดอาร์ติแฟกต์จากที่เก็บ Maven และทำให้พร้อมใช้งานเป็น Java ทรัพยากร Dependency

กำลังดึงข้อมูลทรัพยากร Dependency

โดยค่าเริ่มต้น ระบบจะดึงข้อมูลทรัพยากร Dependency ภายนอกตามความจำเป็นในช่วง bazel build ถ้า คุณต้องการดึงข้อมูลทรัพยากร Dependency ที่จำเป็นสำหรับชุดเป้าหมายที่เฉพาะเจาะจงไว้ล่วงหน้า ให้ใช้ bazel fetch หากต้องการดึงข้อมูลทรัพยากร Dependency ภายนอกทั้งหมดอย่างไม่มีเงื่อนไข ให้ใช้ bazel sync เนื่องจากที่เก็บที่ดึงข้อมูลมาจัดเก็บไว้ในฐานเอาต์พุต โดยการดึงข้อมูล จะเกิดขึ้นต่อพื้นที่ทำงาน

ทรัพยากร Dependency ที่ไม่มีการแก้ไข

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

โปรเจ็กต์ของฉัน/พื้นที่ทำงาน

workspace(name = "myproject")

local_repository(
    name = "A",
    path = "../A",
)
local_repository(
    name = "B",
    path = "../B",
)

พื้นที่ทำงาน

workspace(name = "A")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "...",
)

B/พื้นที่ทำงาน

workspace(name = "B")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)

ทั้งทรัพยากร Dependency A และ B ต่างกันตรงที่ testrunner แต่ทรัพยากรดังกล่าวขึ้นอยู่กับ เวอร์ชันต่างๆ ของ testrunner ไม่มีเหตุผลที่จะ ไม่ได้อยู่ร่วมกันอย่างสงบภายใน myproject แต่จะปะทะกับ อื่นๆ เพราะมีชื่อเดียวกัน หากต้องการประกาศทรัพยากร Dependency ทั้ง 2 แบบ อัปเดต myproject/WORKSPACE:

workspace(name = "myproject")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner-v1",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "..."
)
http_archive(
    name = "testrunner-v2",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)
local_repository(
    name = "A",
    path = "../A",
    repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
    name = "B",
    path = "../B",
    repo_mapping = {"@testrunner" : "@testrunner-v2"}
)

นอกจากนี้ยังใช้กลไกนี้เพื่อรวมเพชรได้ด้วย ตัวอย่างเช่น หาก A และ B เดียวกันมีทรัพยากร Dependency เดียวกัน แต่เรียกด้วยชื่ออื่น ทรัพยากร Dependency เหล่านี้ เข้าร่วมได้ใน myproject/WORKSPACE

การลบล้างที่เก็บจากบรรทัดคำสั่ง

หากต้องการลบล้างที่เก็บที่ประกาศด้วยที่เก็บในเครื่องจากบรรทัดคำสั่ง ให้ใช้ --override_repository แจ้ง การใช้แฟล็กนี้จะเปลี่ยนแปลงเนื้อหาของที่เก็บภายนอกโดยไม่มี การเปลี่ยนซอร์สโค้ดของคุณ

เช่น หากต้องการลบล้าง @foo ในไดเรกทอรีในเครื่อง /path/to/local/foo ผ่านแฟล็ก --override_repository=foo=/path/to/local/foo

ตัวอย่างกรณีการใช้งานมีดังนี้

  • การแก้ปัญหา เช่น คุณลบล้างที่เก็บ http_archive ได้ ลงในไดเรกทอรีภายในเครื่อง เพื่อให้คุณทำการเปลี่ยนแปลงได้ง่ายขึ้น
  • ตัวแทนจำหน่ายรายย่อย หากคุณอยู่ในสภาพแวดล้อมที่ไม่สามารถเรียกใช้เครือข่าย ลบล้างกฎที่เก็บตามเครือข่ายเพื่อชี้ไปยังไดเรกทอรีในเครื่อง แทน

การใช้พร็อกซี

Bazel จะรับที่อยู่พร็อกซีจาก HTTPS_PROXY และ HTTP_PROXY ตัวแปรสภาพแวดล้อมและใช้ตัวแปรเหล่านี้เพื่อดาวน์โหลดไฟล์ HTTP/HTTPS (หากระบุ)

รองรับ IPv6

บนเครื่องที่ใช้ IPv6 เท่านั้น Bazel จะดาวน์โหลดทรัพยากร Dependency ที่มี ไม่มีการเปลี่ยนแปลง อย่างไรก็ตาม สำหรับเครื่อง IPv4/IPv6 แบบ 2 สแต็ก Bazel จะใช้ แบบ Java: หากเปิดใช้งาน IPv4 แนะนำให้ใช้ IPv4 ในบางสถานการณ์ ตัวอย่างเช่น เมื่อเครือข่าย IPv4 ไม่สามารถแปลค่า/เข้าถึงที่อยู่ภายนอก ซึ่งอาจทำให้เกิดข้อยกเว้น Network unreachable รายการและเวอร์ชันของบิลด์ไม่สำเร็จ ในกรณีเหล่านี้ คุณอาจลบล้างลักษณะการทำงานของ Bazel หากต้องการเลือกใช้ IPv6 โดยใช้พร็อพเพอร์ตี้ระบบ java.net.preferIPv6Addresses=true กล่าวอย่างเจาะจงคือ

  • ใช้ --host_jvm_args=-Djava.net.preferIPv6Addresses=true ตัวเลือกการเริ่มต้นใช้งาน เช่น ด้วยการเพิ่มบรรทัดต่อไปนี้ใน .bazelrc ไฟล์:

    startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true

  • หากคุณใช้เป้าหมายบิลด์ Java ที่ต้องเชื่อมต่ออินเทอร์เน็ต (บางครั้งต้องมีการทดสอบการผสานรวม) ให้ใช้ --jvmopt=-Djava.net.preferIPv6Addresses=true แฟล็กเครื่องมือ เช่น การมี บรรทัดต่อไปนี้ใน .bazelrc ไฟล์ของคุณ:

    build --jvmopt=-Djava.net.preferIPv6Addresses

  • หากคุณกำลังใช้ rules_jvm_external, ตัวอย่างเช่น สำหรับการแปลงเวอร์ชันของทรัพยากร Dependency ให้เพิ่ม -Djava.net.preferIPv6Addresses=true ไปยัง COURSIER_OPTS ตัวแปรสภาพแวดล้อมเพื่อระบุตัวเลือก JVM สำหรับ Coursier

ทรัพยากร Dependency แบบทรานซิทีฟ

Bazel จะอ่านเฉพาะทรัพยากร Dependency ที่ระบุไว้ในไฟล์ WORKSPACE เท่านั้น หากโปรเจ็กต์ของคุณ (A) ขึ้นอยู่กับโปรเจ็กต์อื่น (B) ซึ่งแสดงรายการทรัพยากร Dependency ของหนึ่งในสาม โปรเจ็กต์ (C) ในไฟล์ WORKSPACE ของโปรเจ็กต์ คุณจะต้องเพิ่มทั้ง B และ C ลงในไฟล์ WORKSPACE ของโครงการ ข้อกำหนดนี้อาจทำให้ ไฟล์ WORKSPACE ขนาด แต่จำกัดโอกาสการมีไลบรารีเดียว มี C ในเวอร์ชัน 1.0 และอีกเวอร์ชันคือ C เวอร์ชัน 2.0

การแคชทรัพยากร Dependency ภายนอก

โดยค่าเริ่มต้น Bazel จะดาวน์โหลดทรัพยากร Dependency ภายนอกใหม่ก็ต่อเมื่อ เปลี่ยนคำจำกัดความ การเปลี่ยนแปลงไฟล์ที่อ้างอิงในคำจำกัดความ (เช่น แพตช์ หรือ BUILD ไฟล์) จะได้รับการพิจารณาด้วย Bazel

หากต้องการบังคับให้ดาวน์โหลดใหม่ ให้ใช้ bazel sync

เลย์เอาต์

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

ls $(bazel info output_base)/external

โปรดทราบว่าการเรียกใช้ bazel clean จะไม่ลบไฟล์ภายนอก ไดเรกทอรี หากต้องการนำอาร์ติแฟกต์ภายนอกทั้งหมดออก ให้ใช้ bazel clean --expunge

บิลด์แบบออฟไลน์

บางครั้งการสร้างงานแบบออฟไลน์ก็เป็นไปตามความต้องการหรือจำเป็น สำหรับ กรณีการใช้งานง่ายๆ เช่น การเดินทางบนเครื่องบิน prefetching ที่เก็บที่มี bazel fetch หรือ bazel sync ก็อาจเพียงพอแล้ว ยิ่งไปกว่านั้น โดยใช้ตัวเลือก --nofetch ทำให้สามารถปิดใช้การดึงข้อมูลที่เก็บเพิ่มเติม ระหว่างการสร้าง

สำหรับบิลด์แบบออฟไลน์อย่างแท้จริง ซึ่งเป็นที่ที่ต้องจัดเตรียมไฟล์ที่จำเป็น โดยเอนทิตีที่แตกต่างจาก bazel, bazel สนับสนุนตัวเลือก --distdir เมื่อกฎที่เก็บขอให้ Bazel ดึงข้อมูลไฟล์ผ่าน ctx.download หรือ ctx.download_and_extract และระบุแฮชผลรวมของไฟล์ ขั้นแรก bazel จะพิจารณาไดเรกทอรีที่ระบุโดยตัวเลือกนั้นสำหรับ ไฟล์ที่ตรงกับชื่อฐานของ URL แรกที่ระบุ และใช้สำเนาในเครื่องนั้น หากแฮชตรงกัน

Bazel เองก็ใช้เทคนิคนี้เพื่อกระตุ้นให้ทำงานแบบออฟไลน์จากการกระจาย อาร์ติแฟกต์ แต่ทําโดยรวบรวมข้อมูลภายนอกที่จําเป็นทั้งหมด ทรัพยากร Dependency ภายใน distdir_tar

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

แนวทางปฏิบัติแนะนำ

กฎที่เก็บ

โดยทั่วไปกฎที่เก็บควรมีหน้าที่ต่อไปนี้

  • กำลังตรวจหาการตั้งค่าระบบและเขียนลงในไฟล์
  • กำลังค้นหาแหล่งข้อมูลในส่วนอื่นๆ ของระบบ
  • กำลังดาวน์โหลดทรัพยากรจาก URL
  • กำลังสร้างหรือ Symlink ไฟล์ BUILD ลงในไดเรกทอรีที่เก็บภายนอก

หลีกเลี่ยงการใช้ repository_ctx.execute เมื่อเป็นไปได้ เช่น เมื่อใช้ไฟล์ C++ ที่ไม่ใช่ Bazel ไลบรารีที่มีบิลด์ที่ใช้Make ควรใช้ repository_ctx.download() จากนั้น เขียนไฟล์ BUILD ที่สร้าง แทนที่จะเรียกใช้ ctx.execute(["make"])

ให้ใช้ http_archive เป็น git_repository และ new_git_repository เหตุผลมีดังนี้

  • กฎที่เก็บ Git ขึ้นอยู่กับ git(1) ของระบบในขณะที่เครื่องมือดาวน์โหลด HTTP สร้างขึ้น ลงใน Bazel และไม่มีทรัพยากร Dependency ของระบบ
  • http_archive รองรับรายการ urls เป็นมิเรอร์ และ git_repository รองรับเฉพาะรายการ remote รายการเดียว
  • http_archive ใช้งานได้กับแคชที่เก็บ แต่ไม่สามารถใช้ได้กับ git_repository โปรดดู #5116 เพื่อดูข้อมูลเพิ่มเติม

อย่าใช้ bind() โปรดดู "โปรดพิจารณาการลบ เชื่อมโยง" เป็นเวลานาน การอภิปรายเกี่ยวกับประเด็นและทางเลือก