การปรับกฎของ Bazel เพื่อการเรียกใช้ระยะไกล

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

หน้านี้มีไว้สําหรับผู้ใช้ Bazel ที่เขียนกฎบิลด์และทดสอบที่กำหนดเอง ซึ่งต้องการทำความเข้าใจข้อกำหนดของกฎ Bazel ในบริบทของการดำเนินการระยะไกล

การดำเนินการระยะไกลทำให้ Bazel ดำเนินการต่างๆ บนแพลตฟอร์มที่แยกต่างหากได้ เช่น ศูนย์ข้อมูล Bazel ใช้โปรโตคอล gRPC สำหรับการดำเนินการจากระยะไกล คุณลองใช้การดำเนินการระยะไกลได้ด้วย bazel-buildfarm ซึ่งเป็นโปรเจ็กต์โอเพนซอร์สที่มุ่งให้บริการแพลตฟอร์มการดำเนินการระยะไกลแบบกระจาย

หน้านี้ใช้คำศัพท์ต่อไปนี้เมื่ออ้างถึงประเภทสภาพแวดล้อมหรือแพลตฟอร์มต่างๆ

  • แพลตฟอร์มโฮสต์ - ที่ Bazel ทำงานอยู่
  • แพลตฟอร์มการดำเนินการ - ที่มีการดำเนินการของ Bazel
  • แพลตฟอร์มเป้าหมาย - ที่เอาต์พุตของบิลด์ (และการกระทำบางอย่าง) ทำงาน

ภาพรวม

เมื่อกำหนดค่าบิลด์ Bazel สำหรับการดำเนินการระยะไกล คุณต้องทำตามหลักเกณฑ์ที่อธิบายไว้ในหน้านี้เพื่อดูแลให้บิลด์นี้ดำเนินการจากระยะไกลโดยไม่มีข้อผิดพลาด เนื่องจากลักษณะของการดำเนินการจากระยะไกล ได้แก่

  • การดำเนินการบิลด์ที่แยกไว้ เครื่องมือบิลด์จะไม่เก็บสถานะไว้ และทรัพยากร Dependency จะรั่วไหลระหว่างเครื่องมือไม่ได้

  • สภาพแวดล้อมการดำเนินการที่หลากหลาย การกำหนดค่าบิลด์ในเครื่องอาจไม่เหมาะกับสภาพแวดล้อมการดำเนินการระยะไกลเสมอไป

หน้านี้อธิบายปัญหาที่อาจเกิดขึ้นเมื่อใช้กฎการสร้างและทดสอบ Bazel ที่กำหนดเองสำหรับการดำเนินการจากระยะไกล และวิธีหลีกเลี่ยง ซึ่งครอบคลุมถึงหัวข้อต่อไปนี้

การเรียกใช้เครื่องมือสร้างผ่านกฎ Toolchain

กฎ Toolchain ของ Bazel เป็นผู้ให้บริการกำหนดค่าที่บอกกฎบิลด์ว่าเครื่องมือการสร้าง เช่น คอมไพเลอร์และ Linker ต้องใช้อะไร รวมถึงวิธีกำหนดค่าโดยใช้พารามิเตอร์ที่กำหนดโดยผู้สร้างกฎ กฎเครื่องมือเชนช่วยให้สร้างและทดสอบกฎเพื่อเรียกใช้เครื่องมือบิลด์ในลักษณะที่กำหนดค่าล่วงหน้าและคาดการณ์ได้ ซึ่งใช้ร่วมกับการดำเนินการจากระยะไกลได้ เช่น ใช้กฎ Toolchain แทนการเรียกใช้เครื่องมือสร้างผ่าน PATH, JAVA_HOME หรือตัวแปรอื่นๆ ในเครื่องที่อาจไม่ได้ตั้งเป็นค่าที่เทียบเท่า (หรือเลย) ในสภาพแวดล้อมการดำเนินการระยะไกล

ปัจจุบันกฎห่วงโซ่เครื่องมือมีให้ใช้งานสำหรับกฎการสร้างและทดสอบของ Bazel สำหรับ Scala, Rust และ Go นอกจากนี้กฎเชนเครื่องมือใหม่ยังพร้อมให้บริการในภาษาและเครื่องมืออื่นๆ เช่น Bash ด้วย หากไม่มีกฎ Toolchain สำหรับเครื่องมือที่กฎใช้ ให้ลองสร้างกฎ Toolchain

การจัดการทรัพยากร Dependency โดยนัย

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

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

เพื่อช่วยในการตรวจหาและขจัดปัญหาทรัพยากร Dependency เหล่านี้ Bazel 0.14.1 มีแซนด์บ็อกซ์ Docker ในเครื่อง ซึ่งมีข้อจำกัดสำหรับทรัพยากร Dependency เหมือนกับการดำเนินการระยะไกล ใช้แซนด์บ็อกซ์เพื่อเตรียมบิลด์สำหรับการดำเนินการระยะไกลด้วยการระบุและแก้ไขข้อผิดพลาดของบิลด์ที่เกี่ยวข้องกับทรัพยากร Dependency ดูข้อมูลเพิ่มเติมได้ที่การแก้ปัญหา Bazel Remote Execution ด้วย Docker Sandbox

การจัดการไบนารีที่ขึ้นอยู่กับแพลตฟอร์ม

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

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

  • จัดส่งหรืออ้างอิงซอร์สโค้ดสำหรับเครื่องมือจากภายนอกเพื่อให้สร้างสำหรับแพลตฟอร์มการดำเนินการระยะไกลได้

  • ติดตั้งเครื่องมือไว้ล่วงหน้าในสภาพแวดล้อมการดำเนินการระยะไกล (เช่น คอนเทนเนอร์ Toolchain) หากมีความเสถียรเพียงพอและใช้กฎ Toolchain เพื่อเรียกใช้ในบิลด์ของคุณ

การจัดการกฎ WORKSPACE รูปแบบการกำหนดค่า

กฎ WORKSPACE ของ Bazel สามารถนำไปใช้เพื่อตรวจสอบแพลตฟอร์มโฮสต์สำหรับเครื่องมือและไลบรารีที่บิลด์ต้องใช้ ซึ่งเป็นแพลตฟอร์มการดำเนินการของ Bazel ด้วย หากบิลด์ขึ้นอยู่กับเครื่องมือบิลด์ในเครื่องและอาร์ติแฟกต์อย่างชัดเจน บิลด์จะล้มเหลวในระหว่างการดำเนินการระยะไกลหากแพลตฟอร์มการดำเนินการระยะไกลไม่เหมือนกับแพลตฟอร์มโฮสต์

การดำเนินการต่อไปนี้ซึ่งทำโดยกฎ WORKSPACE ใช้ไม่ได้กับการดำเนินการระยะไกล

  • การสร้างไบนารี การดำเนินการคอมไพล์ในกฎ WORKSPACE จะทำให้เกิดไบนารีที่เข้ากันไม่ได้กับแพลตฟอร์มการดำเนินการระยะไกลหากแตกต่างจากแพลตฟอร์มโฮสต์

  • กำลังติดตั้งแพ็กเกจ pip แพ็กเกจ แพ็กเกจ pip ที่ติดตั้งผ่านกฎ WORKSPACE กำหนดให้ติดตั้งทรัพยากร Dependency ล่วงหน้าในแพลตฟอร์มโฮสต์ แพ็กเกจดังกล่าวสร้างขึ้นสำหรับแพลตฟอร์มโฮสต์โดยเฉพาะ จะใช้ร่วมกับแพลตฟอร์มการดำเนินการระยะไกลไม่ได้หากแตกต่างจากแพลตฟอร์มโฮสต์

  • การลิงก์สัญลักษณ์ไปยังเครื่องมือในเครื่องหรืออาร์ติแฟกต์ Symlink ไปยังเครื่องมือหรือไลบรารีที่ติดตั้งในแพลตฟอร์มโฮสต์ที่สร้างผ่านกฎ WORKSPACE จะทำให้การสร้างล้มเหลวในแพลตฟอร์มการดำเนินการระยะไกลเนื่องจาก Bazel จะค้นหาไม่พบ แต่ให้สร้างลิงก์สัญลักษณ์โดยใช้การดำเนินการบิลด์แบบมาตรฐานแทน เพื่อให้เข้าถึงเครื่องมือและไลบรารีแบบซิมลิงก์ได้จากแผนผัง runfiles ของ Bazel อย่าใช้ repository_ctx.symlink เพื่อลิงก์สัญลักษณ์ไฟล์เป้าหมายที่อยู่นอกไดเรกทอรีที่เก็บภายนอก

  • การปิดแพลตฟอร์มโฮสต์ หลีกเลี่ยงการสร้างไฟล์นอกโครงสร้าง Bazel runfiles การสร้างตัวแปรสภาพแวดล้อม และการดำเนินการที่คล้ายกัน เนื่องจากตัวแปรเหล่านี้อาจทำงานโดยไม่คาดคิดในแพลตฟอร์มการดำเนินการระยะไกล

คุณสามารถใช้บันทึกกฎของ Workspace เพื่อค้นหาลักษณะการทำงานที่ไม่อยู่ภายใต้องค์ประกอบที่อาจเกิดขึ้นได้

หากทรัพยากร Dependency ภายนอกเรียกใช้การดำเนินการที่เฉพาะเจาะจงโดยอิงตามแพลตฟอร์มโฮสต์ คุณควรแยกการดำเนินการเหล่านั้นระหว่าง WORKSPACE และสร้างกฎดังนี้

  • การตรวจสอบแพลตฟอร์มและการแจงนับทรัพยากร Dependency การดำเนินการเหล่านี้ปลอดภัยสำหรับการเรียกใช้ในเครื่องผ่านกฎ WORKSPACE ซึ่งจะตรวจสอบได้ว่าไลบรารีใดติดตั้งอยู่ ดาวน์โหลดแพ็กเกจที่ต้องสร้าง และเตรียมอาร์ติแฟกต์ที่จำเป็นสำหรับการคอมไพล์ สำหรับการดำเนินการจากระยะไกล กฎเหล่านี้ต้องรองรับการใช้อาร์ติแฟกต์ที่ตรวจสอบไว้ล่วงหน้าด้วยเพื่อให้ข้อมูลที่จะได้รับระหว่างการตรวจสอบแพลตฟอร์มโฮสต์ตามปกติ อาร์ติแฟกต์ที่ตรวจสอบล่วงหน้าช่วยให้ Bazel อธิบายทรัพยากร Dependency ได้ราวกับว่าเป็นของในพื้นที่ โปรดใช้คำสั่งแบบมีเงื่อนไขหรือแฟล็ก --override_repository สำหรับกรณีนี้

  • การสร้างหรือคอมไพล์อาร์ติแฟกต์เฉพาะเป้าหมายและการกลายพันธุ์ของแพลตฟอร์ม การดำเนินการเหล่านี้ต้องดำเนินการผ่านกฎบิลด์ทั่วไป การดำเนินการที่สร้างอาร์ติแฟกต์เฉพาะเป้าหมายสำหรับทรัพยากร Dependency ภายนอกต้องเรียกใช้ระหว่างบิลด์

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

เช่น ในกฎของ Tensorflow สำหรับ cuda และ python กฎ WORKSPACE จะสร้าง BUILD files ต่อไปนี้ สำหรับการดำเนินการในเครื่อง ระบบจะใช้ไฟล์ที่สร้างโดยการตรวจสอบสภาพแวดล้อมของโฮสต์ สำหรับการดำเนินการระยะไกล คำสั่งแบบมีเงื่อนไขในตัวแปรสภาพแวดล้อมช่วยให้กฎใช้ไฟล์ที่ตรวจสอบในที่เก็บได้

ไฟล์ BUILD จะประกาศว่า genrules ทำงานได้ทั้งในเครื่องและจากระยะไกล และทำการประมวลผลที่จำเป็นซึ่งดำเนินการผ่าน repository_ctx.symlink ก่อนหน้านี้ดังที่แสดงที่นี่