หน้านี้จะเน้นที่การเขียนกฎที่ใช้ร่วมกับ Windows ได้ ปัญหาที่พบบ่อยเกี่ยวกับการเขียนกฎแบบพกพา และวิธีแก้ปัญหาบางอย่าง
เส้นทาง
ปัญหา
ขีดจํากัดความยาว: ความยาวสูงสุดของเส้นทางคือ 259 อักขระ
แม้ว่า Windows จะรองรับเส้นทางที่ยาวกว่านั้น (สูงสุด 32767 อักขระ) แต่โปรแกรมจำนวนมากก็สร้างขึ้นโดยมีขีดจำกัดที่ต่ำกว่า
โปรดคำนึงถึงเรื่องนี้เกี่ยวกับโปรแกรมที่คุณเรียกใช้ในการดำเนินการ
ไดเรกทอรีที่ใช้งานอยู่: จำกัดอักขระไว้ที่ 259 ตัว
กระบวนการไม่สามารถ
cdไปยังไดเรกทอรีที่มีความยาวเกิน 259 อักขระการคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่: เส้นทาง Windows จะไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ ส่วนเส้นทาง Unix จะคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
โปรดคำนึงถึงเรื่องนี้เมื่อสร้างบรรทัดคำสั่งสำหรับการดำเนินการ
ตัวคั่นเส้นทาง: แบ็กสแลช (
\`), not forward slash (/`)Bazel จะจัดเก็บเส้นทางในสไตล์ Unix ด้วยตัวคั่น
/แม้ว่าโปรแกรม Windows บางโปรแกรมจะรองรับเส้นทางสไตล์ Unix แต่บางโปรแกรมก็ไม่รองรับ คำสั่งในตัวบางรายการใน cmd.exe รองรับ แต่บางรายการไม่รองรับคุณควรใช้
\` separators on Windows: replace/with` เสมอเมื่อสร้างบรรทัดคำสั่งและตัวแปรสภาพแวดล้อมสำหรับการดำเนินการเส้นทางแบบสัมบูรณ์: ไม่ขึ้นต้นด้วยเครื่องหมายทับ (
/)เส้นทางแบบสัมบูรณ์ใน Windows จะขึ้นต้นด้วยอักษรของไดรฟ์ เช่น
C:\foo\bar.txtไม่มีรูทไฟล์ระบบเดียวโปรดคำนึงถึงเรื่องนี้หากกฎของคุณตรวจสอบว่าเส้นทางเป็นแบบสัมบูรณ์หรือไม่ คุณควรหลีกเลี่ยงการใช้ Absolute Path เนื่องจากมักใช้ไม่ได้กับแพลตฟอร์มอื่นๆ
วิธีแก้ไข:
ใช้เส้นทางสั้นๆ
หลีกเลี่ยงชื่อไดเรกทอรีที่ยาว โครงสร้างไดเรกทอรีที่ฝังลึก ชื่อไฟล์ที่ยาว ชื่อเวิร์กスペースที่ยาว ชื่อเป้าหมายที่ยาว
ทั้งหมดนี้อาจกลายเป็นคอมโพเนนต์เส้นทางของไฟล์อินพุตของการดำเนินการ และอาจใช้ความยาวเส้นทางจนหมด
ใช้รูทเอาต์พุตสั้นๆ
ใช้ Flag
--output_user_root=<path>เพื่อระบุเส้นทางสั้นๆ สำหรับเอาต์พุต Bazel เราขอแนะนำให้คุณมีไดรฟ์ (หรือไดรฟ์เสมือน) สำหรับเอาต์พุตของ Bazel โดยเฉพาะ (เช่น ไฟล์D:\`), and adding this line to your.bazelrc)build --output_user_root=D:/หรือ
build --output_user_root=C:/_bzlใช้ทางแยก
Junction หมายถึงลิงก์สัญลักษณ์ของไดเรกทอรี[1] คุณสร้างจัมชันได้ง่ายๆ และสามารถชี้ไปยังไดเรกทอรี (ในคอมพิวเตอร์เครื่องเดียวกัน) ที่มีเส้นทางยาว หากการดำเนินการสร้างสร้างการต่อเชื่อมที่มีเส้นทางสั้นแต่เป้าหมายยาว เครื่องมือที่มีขีดจำกัดเส้นทางสั้นจะเข้าถึงไฟล์ในไดเรกทอรีที่ต่อเชื่อมได้
ในไฟล์
.batหรือใน cmd.exe คุณสามารถสร้างจังก์ชันได้ดังนี้mklink /J c:\path\to\junction c:\path\to\very\long\target\path[1]: ในทางเทคนิคแล้ว Junction ไม่ใช่ลิงก์สัญลักษณ์ แต่เพื่อการดำเนินการสร้าง คุณอาจถือว่า Junction เป็นลิงก์สัญลักษณ์ของไดเรกทอรี
แทนที่
/ด้วย "" ในเส้นทางในการดำเนินการ / envvarsเมื่อคุณสร้างบรรทัดคำสั่งหรือตัวแปรสภาพแวดล้อมสําหรับการดําเนินการ ให้สร้างเส้นทางในสไตล์ Windows ตัวอย่าง
def as_path(p, is_windows): if is_windows: return p.replace("/", "\\") else: return p
ตัวแปรสภาพแวดล้อม
ปัญหา
การคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่: ชื่อตัวแปรสภาพแวดล้อมของ Windows จะไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
เช่น ใน Java
System.getenv("SystemRoot")และSystem.getenv("SYSTEMROOT")จะให้ผลลัพธ์เดียวกัน (ข้อกำหนดนี้มีผลกับภาษาอื่นๆ ด้วย)การปิดผนึก: การดำเนินการควรใช้ตัวแปรสภาพแวดล้อมที่กำหนดเองให้น้อยที่สุด
ตัวแปรสภาพแวดล้อมเป็นส่วนหนึ่งของคีย์แคชของการดำเนินการ หากการดำเนินการใช้ตัวแปรสภาพแวดล้อมที่เปลี่ยนแปลงบ่อยหรือกำหนดเองสำหรับผู้ใช้ จะทำให้แคชกฎได้น้อยลง
วิธีแก้ไข:
ใช้เฉพาะชื่อตัวแปรสภาพแวดล้อมที่เป็นตัวพิมพ์ใหญ่
ซึ่งใช้งานได้ใน Windows, macOS และ Linux
ลดสภาพแวดล้อมการดําเนินการ
เมื่อใช้
ctx.actions.runให้ตั้งค่าสภาพแวดล้อมเป็นctx.configuration.default_shell_envหากการดำเนินการต้องใช้ตัวแปรสภาพแวดล้อมเพิ่มเติม ให้ใส่ตัวแปรทั้งหมดในพจนานุกรมแล้วส่งไปยังการดำเนินการ ตัวอย่างload("@bazel_skylib//lib:dicts.bzl", "dicts") def _make_env(ctx, output_file, is_windows): out_path = output_file.path if is_windows: out_path = out_path.replace("/", "\\") return dicts.add(ctx.configuration.default_shell_env, {"MY_OUTPUT": out_path})
การทำงาน
ปัญหา
เอาต์พุตที่ปฏิบัติการได้: ไฟล์ปฏิบัติการทุกไฟล์ต้องมีนามสกุลที่ปฏิบัติการได้
ส่วนนามสกุลที่พบบ่อยที่สุดคือ
.exe(ไฟล์ไบนารี) และ.bat(สคริปต์แบตช์)โปรดทราบว่าสคริปต์เชลล์ (
.sh) ไม่สามารถเรียกใช้ได้ใน Windows คุณจึงระบุสคริปต์เชลล์เป็นexecutableของctx.actions.runไม่ได้ นอกจากนี้ ไฟล์จะไม่มีสิทธิ์+xด้วย คุณจึงไม่สามารถเรียกใช้ไฟล์ใดก็ได้เหมือนใน Linuxคำสั่ง Bash: หลีกเลี่ยงการเรียกใช้คำสั่ง Bash โดยตรงในการดำเนินการเพื่อความสามารถในการใช้งานร่วมกัน
Bash ใช้งานได้ในระบบที่คล้ายกับ Unix แต่มักไม่พร้อมใช้งานใน Windows Bazel เองก็ใช้ Bash (MSYS2) น้อยลงเรื่อยๆ ดังนั้นในอนาคตผู้ใช้จึงมีแนวโน้มที่จะติดตั้ง MSYS2 ควบคู่ไปกับ Bazel น้อยลง หลีกเลี่ยงการเรียกใช้คําสั่ง Bash ในการดำเนินการเพื่อให้ใช้กฎใน Windows ได้ง่ายขึ้น
การสิ้นสุดบรรทัด: Windows ใช้ CRLF (
\r\n) ส่วนระบบที่คล้าย Unix ใช้ LF (\n)โปรดคำนึงถึงเรื่องนี้เมื่อเปรียบเทียบไฟล์ข้อความ โปรดคำนึงถึงการตั้งค่า Git โดยเฉพาะอย่างยิ่งการสิ้นสุดบรรทัดเมื่อเช็คเอาต์หรือคอมมิต (ดูการตั้งค่า
core.autocrlfของ Git)
วิธีแก้ไข:
ใช้กฎที่เขียนขึ้นเพื่อวัตถุประสงค์โดยเฉพาะซึ่งไม่มี Bash
native.genrule()เป็นเครื่องมือสำหรับห่อคำสั่ง Bash และมักใช้เพื่อแก้ปัญหาง่ายๆ เช่น การคัดลอกไฟล์หรือเขียนไฟล์ข้อความ คุณไม่จำเป็นต้องใช้ Bash (และไม่ต้องคิดค้นสิ่งใหม่) ให้ดูว่า bazel-skylib มีกฎที่สร้างขึ้นเพื่อวัตถุประสงค์ของคุณหรือไม่ ไม่มีรายการใดที่ต้องใช้ Bash เมื่อสร้าง/ทดสอบใน Windowsตัวอย่างการสร้างกฎ
copy_file()(source, documentation): คัดลอกไฟล์ไปยังตำแหน่งอื่น โดยสามารถเลือกทำให้ไฟล์เป็นแบบเรียกใช้ได้write_file()(source, documentation): เขียนไฟล์ข้อความที่มีการตัดบรรทัดที่ต้องการ (auto,unixหรือwindows) (ไม่บังคับ) ทำให้ไฟล์เป็นแบบเรียกใช้ได้ (หากเป็นสคริปต์)run_binary()(source, documentation): เรียกใช้ไบนารี (หรือกฎ*_binary) ด้วยอินพุตที่ระบุและเอาต์พุตที่คาดไว้เป็นการดำเนินการบิลด์ (นี่คือตัวแฝงกฎการสร้างสำหรับctx.actions.run)native_binary()(แหล่งที่มา, เอกสารประกอบ): รวมไบนารีแบบเนทีฟไว้ในกฎ*_binaryซึ่งคุณสามารถbazel runหรือใช้ในแอตทริบิวต์toolของrun_binary()หรือแอตทริบิวต์toolsของnative.genrule()
ตัวอย่างกฎการทดสอบ
diff_test()(source, documentation): ทดสอบที่เปรียบเทียบเนื้อหาของ 2 ไฟล์native_test()(source, documentation): รวมไบนารีแบบเนทีฟไว้ในกฎ*_testซึ่งคุณbazel testได้
ใน Windows ให้พิจารณาใช้สคริปต์
.batสำหรับการดำเนินการเล็กๆ น้อยๆคุณแก้ปัญหาง่ายๆ ด้วยสคริปต์
.batแทนสคริปต์.shได้ตัวอย่างเช่น หากต้องการสคริปต์ที่ไม่ทำอะไรเลย หรือพิมพ์ข้อความ หรือออกมาพร้อมกับรหัสข้อผิดพลาดที่แก้ไขแล้ว ไฟล์
.batธรรมดาก็เพียงพอแล้ว หากกฎแสดงผลDefaultInfo()ผู้ให้บริการ ช่องexecutableอาจอ้างอิงไฟล์.batนั้นใน Windowsและเนื่องจากนามสกุลไฟล์ไม่สำคัญใน macOS และ Linux คุณจึงใช้
.batเป็นนามสกุลได้เสมอ แม้แต่สคริปต์เชลล์โปรดทราบว่าระบบจะไม่สามารถเรียกใช้ไฟล์
.batที่ว่างเปล่า หากต้องการสคริปต์ว่าง ให้เว้นวรรค 1 ครั้งใช้ Bash ตามหลักการ
ในกฎการสร้างและทดสอบของ Starlark ให้ใช้
ctx.actions.run_shellเพื่อเรียกใช้สคริปต์ Bash และคำสั่ง Bash เป็นการดำเนินการในมาโคร Starlark ให้ตัดสคริปต์และคำสั่ง Bash ไว้ใน
native.sh_binary()หรือnative.genrule()Bazel จะตรวจสอบว่า Bash พร้อมใช้งานหรือไม่ และเรียกใช้สคริปต์หรือคําสั่งผ่าน Bashในกฎของที่เก็บ Starlark ให้พยายามหลีกเลี่ยง Bash ทั้งหมด ปัจจุบัน Bazel ไม่มีวิธีเรียกใช้คำสั่ง Bash ในลักษณะที่มีหลักการในกฎของที่เก็บ
กำลังลบไฟล์
ปัญหา
ลบไฟล์ไม่ได้ขณะที่เปิดอยู่
ไฟล์ที่เปิดอยู่จะลบไม่ได้ (โดยค่าเริ่มต้น) การพยายามลบจะทำให้เกิดข้อผิดพลาด "ปฏิเสธการเข้าถึง" หากลบไฟล์ไม่ได้ อาจเป็นเพราะกระบวนการที่ทำงานอยู่ยังคงเปิดไฟล์นั้นอยู่
ไม่สามารถลบไดเรกทอรีการทำงานสำหรับกระบวนการที่ทำงานอยู่
กระบวนการมีแฮนเดิลที่เปิดอยู่ไปยังไดเรกทอรีการทำงาน และคุณจะลบไดเรกทอรีไม่ได้จนกว่ากระบวนการจะสิ้นสุด
วิธีแก้ไข:
ในโค้ด ให้พยายามปิดไฟล์อย่างรวดเร็ว
ใน Java ให้ใช้
try-with-resourcesใน Python ให้ใช้with open(...) as f:โดยหลักการแล้ว ให้ลองปิดแฮนเดิลโดยเร็วที่สุด