การใช้ Bazel บน Windows

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

หน้านี้จะพูดถึงแนวทางปฏิบัติแนะนำในการใช้ Bazel บน Windows โปรดดูวิธีการติดตั้งในหัวข้อติดตั้ง Bazel ใน Windows

ปัญหาที่ทราบแล้ว

ปัญหาเกี่ยวกับ Bazel ที่เกี่ยวข้องกับ Windows จะมีป้ายกำกับ "team-Windows" ใน GitHub คุณดูปัญหาที่ยังไม่ได้รับการแก้ไขได้ที่นี่

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

หลีกเลี่ยงปัญหาเส้นทางยาว

เครื่องมือบางอย่างมีขีดจำกัดความยาวเส้นทางสูงสุดใน Windows รวมถึงคอมไพเลอร์ MSVC เพื่อหลีกเลี่ยงไม่ให้เกิดปัญหานี้ คุณระบุไดเรกทอรีเอาต์พุตสั้นๆ สำหรับ Bazel ได้ด้วยแฟล็ก --output_user_root

ตัวอย่างเช่น เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ bazelrc

startup --output_user_root=C:/tmp

เปิดใช้การสนับสนุนชื่อไฟล์ 8.3

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

fsutil 8dot3name set 0

ฟีเจอร์บางอย่างกำหนดให้ Bazel สร้างลิงก์สัญลักษณ์ของไฟล์ใน Windows ได้โดยเปิดใช้โหมดนักพัฒนาซอฟต์แวร์ (ใน Windows 10 เวอร์ชัน 1703 ขึ้นไป) หรือเรียกใช้ Bazel ในฐานะผู้ดูแลระบบ การดำเนินการนี้จะเปิดใช้ฟีเจอร์ต่อไปนี้

เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ bazelrc ของคุณเพื่อให้ง่ายขึ้น

startup --windows_enable_symlinks
build --enable_runfiles

หมายเหตุ: การสร้างลิงก์สัญลักษณ์บน Windows เป็นการดำเนินการที่มีค่าใช้จ่ายสูง แฟล็ก --enable_runfiles อาจสร้างลิงก์สัญลักษณ์ของไฟล์จำนวนมากได้ เปิดใช้ฟีเจอร์นี้เมื่อคุณต้องการเท่านั้น

การเรียกใช้ Bazel: เชลล์ของ MSYS2 กับพรอมต์คำสั่งกับ PowerShell

คำแนะนำ: เรียกใช้ Bazel จาก Command Prompt (cmd.exe) หรือจาก PowerShell

ตั้งแต่วันที่ 15/01/2020 อย่าเรียกใช้ Bazel จาก bash ไม่ว่าจะจาก Shell MSYS2 หรือ Git Bash หรือ Cygwin หรือตัวแปร Bash อื่นๆ แม้ว่า Bazel อาจทำงานได้สำหรับกรณีการใช้งานส่วนใหญ่ แต่ก็มีบางอย่างไม่ทำงาน เช่น ขัดจังหวะบิลด์ด้วย Ctrl+C จาก MSYS2) นอกจากนี้ หากเลือกที่จะใช้ MSYS2 คุณต้องปิดใช้การแปลงเส้นทางอัตโนมัติของ MSYS2 ไม่เช่นนั้น MSYS จะแปลงอาร์กิวเมนต์บรรทัดคำสั่งที่มีลักษณะเส้นทาง Unix (เช่น //foo:bar) ให้เป็นเส้นทาง Windows ดูรายละเอียดได้ที่คำตอบ StackOverflow นี้

การใช้ Bazel โดยไม่ใช้ Bash (MSYS2)

การใช้บิลด์ Bazel โดยไม่มี Bash

ก่อนหน้านี้ Bazel เวอร์ชัน 1.0 เคยต้องใช้ Bash ในการสร้างกฎ

เริ่มต้นด้วย Bazel 1.0 คุณสามารถสร้างกฎอะไรก็ได้โดยไม่ใช้ Bash เว้นแต่จะเป็น

  • genrule เนื่องจาก genrules เรียกใช้คำสั่ง Bash
  • กฎ sh_binary หรือ sh_test เนื่องจากโดยพื้นฐานแล้วต้องใช้ Bash
  • กฎ Starlark ที่ใช้ ctx.actions.run_shell() หรือ ctx.resolve_command()

อย่างไรก็ตาม genrule มักใช้สำหรับงานง่ายๆ เช่น การคัดลอกไฟล์หรือการเขียนไฟล์ข้อความ แทนที่จะใช้ genrule (และขึ้นอยู่กับ Bash) คุณอาจเห็นกฎที่เหมาะสมในที่เก็บbazel-skylib เมื่อสร้างใน Windows กฎเหล่านี้ไม่จำเป็นต้องใช้ Bash

การใช้การทดสอบ Bazel โดยไม่มี Bash

Bazel เวอร์ชันก่อน 1.0 เคยต้องใช้ Bash กับ bazel test อะไรก็ได้

เริ่มต้นด้วย Bazel 1.0 คุณสามารถทดสอบกฎใดก็ได้โดยไม่ใช้ Bash ยกเว้นเมื่อ

  • คุณใช้ --run_under
  • ตัวกฎทดสอบเองต้องใช้ Bash (เพราะไฟล์ปฏิบัติการเป็นสคริปต์เชลล์)

ใช้การวิ่งแบบ Bazel โดยไม่ใช้ Bash

Bazel เวอร์ชันก่อน 1.0 เคยต้องใช้ Bash กับ bazel run อะไรก็ได้

เริ่มต้นด้วย Bazel 1.0 คุณสามารถเรียกใช้กฎใดก็ได้โดยไม่ใช้ Bash ยกเว้นในกรณีต่อไปนี้

  • คุณใช้ --run_under หรือ --script_path
  • ตัวกฎทดสอบเองต้องใช้ Bash (เพราะไฟล์ปฏิบัติการเป็นสคริปต์เชลล์)

การใช้กฎ sh_binary และ sh_* และ ctx.actions.run_shell() โดยไม่ใช้ Bash

คุณต้องมี Bash เพื่อสร้างและทดสอบกฎ sh_* รวมถึงเพื่อสร้างและทดสอบกฎ Starlark ที่ใช้ ctx.actions.run_shell() และ ctx.resolve_command() วิธีนี้ไม่ได้มีผลเฉพาะกับกฎในโปรเจ็กต์เท่านั้น แต่ยังมีผลกับกฎในที่เก็บภายนอกที่โปรเจ็กต์ของคุณอ้างอิงอยู่ (หรืออาจมีผลทางอ้อมก็ได้)

ในอนาคต อาจมีตัวเลือกให้ใช้ระบบย่อยของ Windows สำหรับ Linux (WSL) เพื่อสร้างกฎเหล่านี้ แต่ขณะนี้ยังไม่มีลำดับความสำคัญสำหรับทีมย่อย Bazel บน Windows

การตั้งค่าตัวแปรสภาพแวดล้อม

ระบบจะตั้งค่าตัวแปรสภาพแวดล้อมที่ตั้งค่าไว้ใน Windows Command Prompt (cmd.exe) ในเซสชัน Command Prompt ดังกล่าวเท่านั้น หากเริ่มต้น cmd.exe ใหม่ คุณต้องตั้งค่าตัวแปรอีกครั้ง หากต้องการตั้งค่าตัวแปรทุกครั้งเมื่อ cmd.exe เริ่มต้น ให้เพิ่มค่าลงในตัวแปรของผู้ใช้หรือตัวแปรของระบบในกล่องโต้ตอบ Control Panel > System Properties > Advanced > Environment Variables...

สร้างบน Windows

สร้าง C++ ด้วย MSVC

หากต้องการสร้างเป้าหมาย C++ ด้วย MSVC คุณต้องมีสิ่งต่อไปนี้

  • คอมไพเลอร์ Visual C++

  • (ไม่บังคับ) ตัวแปรสภาพแวดล้อม BAZEL_VC และ BAZEL_VC_FULL_VERSION

    Bazel จะตรวจหาคอมไพเลอร์ Visual C++ ในระบบของคุณโดยอัตโนมัติ หากต้องการบอกให้ Bazel ใช้การติดตั้ง VC ที่เฉพาะเจาะจง คุณสามารถตั้งค่าตัวแปรสภาพแวดล้อมต่อไปนี้

    สำหรับ Visual Studio 2017 และ 2019 ให้ตั้งค่าเป็น BAZEL_VC นอกจากนี้คุณยังสามารถตั้งค่า BAZEL_VC_FULL_VERSION ได้อีกด้วย

    • BAZEL_VC ไดเรกทอรีการติดตั้งเครื่องมือสร้างบิลด์ของ Visual C++

      set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC
      
    • BAZEL_VC_FULL_VERSION (ไม่บังคับ) สำหรับ Visual Studio 2017 และ 2019 เท่านั้น คุณจะเห็นหมายเลขเวอร์ชันแบบเต็มของเครื่องมือสร้าง Visual C++ คุณจะเลือกเวอร์ชันเครื่องมือสร้างเวอร์ชัน Visual C++ ที่ถูกต้องได้ผ่านทาง BAZEL_VC_FULL_VERSION หากมีการติดตั้งไว้มากกว่า 1 เวอร์ชัน ไม่เช่นนั้น Bazel จะเลือกเวอร์ชันล่าสุด

      set BAZEL_VC_FULL_VERSION=14.16.27023
      

    สำหรับ Visual Studio 2015 หรือเก่ากว่า ให้ตั้งค่า BAZEL_VC (ไม่รองรับ BAZEL_VC_FULL_VERSION)

    • BAZEL_VC ไดเรกทอรีการติดตั้งเครื่องมือสร้างบิลด์ของ Visual C++

      set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
      
  • Windows SDK

    Windows SDK มีไฟล์ส่วนหัวและไลบรารีที่คุณจำเป็นต้องใช้เมื่อสร้างแอปพลิเคชัน Windows ซึ่งรวมถึง Bazel ด้วย โดยค่าเริ่มต้น ระบบจะใช้ Windows SDK ล่าสุดที่ติดตั้ง นอกจากนี้ คุณยังระบุเวอร์ชันของ Windows SDK ได้โดยการตั้งค่า BAZEL_WINSDK_FULL_VERSION คุณสามารถใช้หมายเลข SDK ของ Windows 10 SDK แบบเต็ม เช่น 10.0.10240.0 หรือระบุ 8.1 เพื่อใช้ SDK ของ Windows 8.1 (มี Windows 8.1 SDK เพียงเวอร์ชันเดียวเท่านั้น) โปรดตรวจสอบว่าคุณได้ติดตั้ง Windows SDK ที่ระบุแล้ว

    ข้อกำหนด: รองรับ VC 2017 และ 2019 เครื่องมือสร้าง VC 2015 แบบสแตนด์อโลนไม่รองรับการเลือก Windows SDK คุณจะต้องติดตั้ง Visual Studio 2015 อย่างเต็มรูปแบบ มิฉะนั้นระบบจะไม่สนใจ BAZEL_WINSDK_FULL_VERSION

    set BAZEL_WINSDK_FULL_VERSION=10.0.10240.0
    

หากตั้งค่าทุกอย่างเรียบร้อยแล้ว คุณก็สร้างเป้าหมาย C++ ได้เลย

ลองสร้างเป้าหมายจากโปรเจ็กต์ตัวอย่างของเรา ดังนี้

bazel build //examples/cpp:hello-world
bazel-bin\examples\cpp\hello-world.exe

โดยค่าเริ่มต้น ไบนารีที่สร้างจะกำหนดเป้าหมายสถาปัตยกรรม x64 หากต้องการระบุสถาปัตยกรรมเป้าหมายอื่น ให้ตั้งค่าตัวเลือกบิลด์ --cpu สำหรับสถาปัตยกรรมเป้าหมายดังนี้ * x64 (ค่าเริ่มต้น): ตัวเลือก --cpu=x64_windows หรือไม่ใส่ * x86: --cpu=x64_x86_windows * ARM: --cpu=x64_arm_windows * ARM64: --cpu=arm64_windows

เช่น หากต้องการสร้างเป้าหมายสำหรับสถาปัตยกรรม ARM ให้เรียกใช้คำสั่งต่อไปนี้

bazel build //examples/cpp:hello-world --cpu=x64_arm_windows

หากต้องการสร้างและใช้ไลบรารีที่เชื่อมโยงแบบไดนามิก (ไฟล์ DLL) โปรดดูตัวอย่างนี้

ขีดจำกัดความยาวบรรทัดคำสั่ง: หากต้องการป้องกันปัญหาขีดจำกัดความยาวของบรรทัดคำสั่งของ Windows ให้เปิดใช้ฟีเจอร์ไฟล์พารามิเตอร์ของคอมไพเลอร์ผ่าน --features=compiler_param_file

สร้าง C++ ด้วยภาษา Clang

Bazel รองรับการสร้างด้วยไดรเวอร์คอมไพเลอร์ที่ใช้ร่วมกับ MSVC ได้ตั้งแต่ 0.29.0 เป็นต้นไป (clang-cl.exe)

ข้อกำหนด: หากต้องการสร้างด้วย Clang คุณต้องติดตั้งทั้งเครื่องมือ LLVM และ Visual C++ Build เพราะถึงจะใช้ clang-cl.exe เป็นคอมไพเลอร์ แต่ก็ยังต้องลิงก์กับไลบรารี Visual C++

Bazel สามารถตรวจหาการติดตั้ง LLVM ในระบบของคุณโดยอัตโนมัติ หรือคุณจะบอก Bazel ว่าติดตั้ง LLVM ไว้ที่ใดโดย BAZEL_LLVM ก็ได้

  • BAZEL_LLVM ไดเรกทอรีการติดตั้ง LLVM

    set BAZEL_LLVM=C:\Program Files\LLVM
    

มีหลายสถานการณ์ในการเปิดใช้เครื่องมือ Clang เพื่อสร้าง C++

  • ในภาษา Bazel 0.28 และเก่ากว่า: ไม่รองรับ Clang

  • หากไม่มี --incompatible_enable_cc_toolchain_resolution: คุณจะเปิดใช้เชนเครื่องมือ Clang ได้ด้วยแฟล็กบิลด์ --compiler=clang-cl

  • เมื่อใช้ --incompatible_enable_cc_toolchain_resolution คุณต้องเพิ่มเป้าหมายแพลตฟอร์มไปยัง BUILD file (เช่น ไฟล์ BUILD ระดับบนสุด) ดังนี้

    platform(
        name = "x64_windows-clang-cl",
        constraint_values = [
            "@platforms//cpu:x86_64",
            "@platforms//os:windows",
            "@bazel_tools//tools/cpp:clang-cl",
        ],
    )
    

    จากนั้นจึงเปิดใช้เชนเครื่องมือ Clang ด้วยวิธีใดวิธีหนึ่งต่อไปนี้

    • ระบุแฟล็กบิลด์ต่อไปนี้
    --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl --extra_execution_platforms=//:x64_windows-clang-cl
    
    • ลงทะเบียนแพลตฟอร์มและ Toolchain ในไฟล์ MODULE.bazel
    register_execution_platforms(
        ":x64_windows-clang-cl"
    )
    
    register_toolchains(
        "@local_config_cc//:cc-toolchain-x64_windows-clang-cl",
    )
    

    เราวางแผนที่จะเปิดใช้แฟล็ก --incompatible_enable_cc_toolchain_resolution โดยค่าเริ่มต้นสำหรับรุ่น Bazel ในอนาคต เราจึงขอแนะนำให้เปิดใช้การรองรับ Clang ด้วยวิธีการที่ 2

บิลด์ Java

หากต้องการสร้างเป้าหมาย Java คุณต้องมีสิ่งต่อไปนี้

Bazel จะสร้างไฟล์เอาต์พุต 2 ไฟล์สำหรับกฎ java_binary ใน Windows ดังนี้

  • ไฟล์ .jar
  • ไฟล์ .exe ที่ตั้งค่าสภาพแวดล้อมสำหรับ JVM และเรียกใช้ไบนารีได้

ลองสร้างเป้าหมายจากโปรเจ็กต์ตัวอย่างของเรา ดังนี้

  bazel build //examples/java-native/src/main/java/com/example/myproject:hello-world
  bazel-bin\examples\java-native\src\main\java\com\example\myproject\hello-world.exe

สร้าง Python

หากต้องการสร้างเป้าหมาย Python คุณต้องมีสิ่งต่อไปนี้

Bazel จะสร้างไฟล์เอาต์พุต 2 ไฟล์สำหรับกฎ py_binary ใน Windows ดังนี้

  • ไฟล์ ZIP ที่ดึงตัวเองออกมา
  • ไฟล์ปฏิบัติการที่สามารถเรียกใช้อินเทอร์พรีเตอร์ของ Python โดยมีไฟล์ ZIP ที่แยกตัวเองเป็นอาร์กิวเมนต์

คุณจะเรียกใช้ไฟล์ปฏิบัติการ (ไฟล์มีนามสกุล .exe) หรือเรียกใช้ Python โดยใช้ไฟล์ ZIP ที่แตกตัวเองเป็นอาร์กิวเมนต์ก็ได้

ลองสร้างเป้าหมายจากโปรเจ็กต์ตัวอย่างของเรา ดังนี้

  bazel build //examples/py_native:bin
  bazel-bin\examples\py_native\bin.exe
  python bazel-bin\examples\py_native\bin.zip

หากสนใจรายละเอียดเกี่ยวกับวิธีที่ Bazel สร้างเป้าหมาย Python บน Windows โปรดดูเอกสารการออกแบบนี้