หน้านี้มุ่งเน้นที่การเขียนกฎที่ใช้ได้กับ 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 เนื่องจากมักจะย้ายไม่ได้
วิธีแก้ไข:
เส้นทางควรสั้น
หลีกเลี่ยงชื่อไดเรกทอรีที่ยาว โครงสร้างไดเรกทอรีที่ซ้อนกันลึก ชื่อไฟล์ที่ยาว ชื่อเวิร์กสเปซที่ยาว และชื่อเป้าหมายที่ยาว
รายการทั้งหมดนี้อาจกลายเป็นคอมโพเนนต์เส้นทางของไฟล์อินพุตของการดำเนินการ และอาจทำให้ความยาวเส้นทางเกินขีดจำกัด
ใช้รูทเอาต์พุตแบบสั้น
ใช้แฟล็ก
--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
ใช้ทางแยก
พูดอย่างคร่าวๆ[1] จังก์ชันคือลิงก์สัญลักษณ์ของไดเรกทอรี สร้าง Junction ได้ง่ายๆ และสามารถชี้ไปยังไดเรกทอรี (ในคอมพิวเตอร์เครื่องเดียวกัน) ที่มีเส้นทางยาว หากการดำเนินการบิลด์สร้าง จังก์ชันที่มีเส้นทางสั้นแต่มีเป้าหมายยาว เครื่องมือที่มีขีดจำกัดเส้นทางสั้นจะเข้าถึง ไฟล์ในไดเรกทอรีที่เชื่อมต่อได้
ในไฟล์
.bat
หรือใน cmd.exe คุณสามารถสร้าง Junction ได้ดังนี้mklink /J c:\path\to\junction c:\path\to\very\long\target\path
[1]: พูดอย่างเคร่งครัด Junction ไม่ใช่ลิงก์สัญลักษณ์ แต่เพื่อ ประโยชน์ของการดำเนินการสร้าง คุณอาจถือว่า Junction เป็น Symlink ของไดเรกทอรี
แทนที่
/
ด้วย `` ในเส้นทางในการดำเนินการ / ตัวแปรสภาพแวดล้อมเมื่อสร้างบรรทัดคำสั่งหรือตัวแปรสภาพแวดล้อมสำหรับการดำเนินการ ให้ใช้เส้นทางรูปแบบ Windows ตัวอย่าง
def as_path(p, is_windows): if is_windows: return p.replace("/", "\\") else: return p
ตัวแปรสภาพแวดล้อม
ปัญหา
การคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่: ชื่อตัวแปรสภาพแวดล้อมของ Windows ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่
เช่น ใน Java
System.getenv("SystemRoot")
และSystem.getenv("SYSTEMROOT")
จะให้ผลลัพธ์เดียวกัน (ซึ่งมีผลกับภาษาอื่นๆ ด้วย)Hermeticity: การดำเนินการควรใช้ตัวแปรสภาพแวดล้อมที่กำหนดเองให้น้อยที่สุด
ตัวแปรสภาพแวดล้อมเป็นส่วนหนึ่งของคีย์แคชของการดำเนินการ หากการดำเนินการใช้ตัวแปรสภาพแวดล้อม ที่มีการเปลี่ยนแปลงบ่อยหรือเป็นตัวแปรที่กำหนดเองสำหรับผู้ใช้ จะทำให้กฎแคชน้อยลง
วิธีแก้ไข:
ใช้เฉพาะชื่อตัวแปรสภาพแวดล้อมที่เป็นตัวพิมพ์ใหญ่เท่านั้น
โดยจะใช้งานได้บน 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 ไม่ได้ คุณจึงระบุเป็นctx.actions.run
ของexecutable
ไม่ได้ นอกจากนี้ยังไม่มีสิทธิ์+x
ที่ไฟล์จะมีได้ด้วย ดังนั้นคุณจึง เรียกใช้ไฟล์ใดก็ได้ไม่ได้เหมือนใน Linuxคำสั่ง Bash: เพื่อให้สามารถพกพาได้ ให้หลีกเลี่ยงการเรียกใช้คำสั่ง Bash โดยตรงใน Actions
Bash มีการใช้งานอย่างแพร่หลายในระบบที่คล้าย Unix แต่โดยทั่วไปจะใช้ไม่ได้ใน Windows Bazel เองก็ พึ่งพา Bash (MSYS2) น้อยลงเรื่อยๆ ดังนั้นในอนาคตผู้ใช้ก็ไม่น่าจะต้องติดตั้ง MSYS2 พร้อมกับ Bazel หากต้องการให้ใช้กฎใน Windows ได้ง่ายขึ้น ให้หลีกเลี่ยงการเรียกใช้คำสั่ง Bash ใน การดำเนินการ
การจบบรรทัด: Windows ใช้ CRLF (
\r\n
) ส่วนระบบที่คล้าย Unix ใช้ LF (\n
)โปรดทราบถึงข้อจำกัดนี้เมื่อเปรียบเทียบไฟล์ข้อความ โปรดคำนึงถึงการตั้งค่า Git โดยเฉพาะการสิ้นสุดบรรทัดเมื่อเช็คเอาต์หรือคอมมิต (ดู
core.autocrlf
การตั้งค่าของ Git)
วิธีแก้ไข:
ใช้กฎที่สร้างขึ้นโดยเฉพาะซึ่งไม่มี Bash
native.genrule()
เป็น Wrapper สำหรับคำสั่ง Bash และมักใช้เพื่อแก้ปัญหาเล็กๆ น้อยๆ เช่น การคัดลอกไฟล์หรือการเขียนไฟล์ข้อความ คุณหลีกเลี่ยงการใช้ Bash (และไม่ต้องประดิษฐ์ล้อใหม่) ได้โดยดูว่า bazel-skylib มีกฎที่สร้างขึ้นเพื่อตอบสนองความต้องการของคุณหรือไม่ โดยไม่มีตัวใดที่ต้องใช้ Bash เมื่อสร้าง/ทดสอบใน Windowsตัวอย่างกฎการสร้าง
copy_file()
(source, documentation): คัดลอกไฟล์ไปยังที่อื่น และเลือกทำให้ไฟล์นั้นเรียกใช้งานได้write_file()
(source, documentation): writes a text file, with the desired line endings (auto
,unix
, orwindows
), optionally making it executable (if it's a script)run_binary()
(source, documentation): เรียกใช้ไบนารี (หรือ*_binary
rule) ด้วยอินพุตที่ระบุและเอาต์พุตที่คาดไว้เป็นการดำเนินการบิลด์ (นี่คือ Wrapper ของกฎบิลด์สำหรับctx.actions.run
)native_binary()
(source, documentation): wraps a native binary in a*_binary
rule, which you canbazel run
or use inrun_binary()
'stool
attribute ornative.genrule()
'stools
attribute
ตัวอย่างกฎการทดสอบ
diff_test()
(source, documentation): ทดสอบที่เปรียบเทียบเนื้อหาของไฟล์ 2 ไฟล์native_test()
(source, documentation): wraps a native binary in a*_test
rule, which you canbazel test
ใน Windows ให้พิจารณาใช้สคริปต์
.bat
สำหรับสิ่งเล็กๆ น้อยๆคุณสามารถใช้สคริปต์
.bat
แทนสคริปต์.sh
เพื่อแก้ปัญหางานเล็กๆ น้อยๆ ได้เช่น หากคุณต้องการสคริปต์ที่ไม่ทำอะไรเลย หรือพิมพ์ข้อความ หรือออกด้วยรหัสข้อผิดพลาดที่กำหนดไว้
.bat
ไฟล์ธรรมดาก็เพียงพอแล้ว หากกฎแสดงผลDefaultInfo()
provider ฟิลด์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:
ในทางทฤษฎี ให้พยายาม ปิดแฮนเดิลโดยเร็วที่สุด