หน้านี้จะอธิบายวิธีสร้างหรือทดสอบโปรเจ็กต์ Xcode ด้วย Bazel ซึ่งอธิบายความแตกต่างระหว่าง Xcode กับ Bazel และแสดงขั้นตอนในการแปลงโปรเจ็กต์ Xcode เป็นโปรเจ็กต์ Bazel รวมถึงให้วิธีแก้ปัญหาเพื่อแก้ไขข้อผิดพลาดที่พบบ่อย
ความแตกต่างระหว่าง Xcode กับ Bazel
Bazel กำหนดให้คุณระบุเป้าหมายการสร้างและทรัพยากร Dependency ทั้งหมดอย่างชัดเจน รวมถึงการตั้งค่าการสร้างที่เกี่ยวข้องผ่านกฎการสร้าง
Bazel กำหนดให้ไฟล์ทั้งหมดที่โครงการใช้ต้องอยู่ในไดเรกทอรี Workspace หรือระบุเป็นการนำเข้าในไฟล์
WORKSPACE
เมื่อสร้างโปรเจ็กต์ Xcode ด้วย Bazel ไฟล์
BUILD
จะเป็นแหล่งข้อมูล หากทํางานในโปรเจ็กต์ใน Xcode คุณต้องสร้างโปรเจ็กต์ Xcode เวอร์ชันใหม่ที่ตรงกับไฟล์BUILD
โดยใช้ rules_xcodeproj ทุกครั้งที่อัปเดตไฟล์BUILD
การเปลี่ยนแปลงบางอย่างในไฟล์BUILD
เช่น การเพิ่มการพึ่งพาไปยังเป้าหมาย ไม่จำเป็นต้องสร้างโปรเจ็กต์ขึ้นมาใหม่ ซึ่งจะช่วยเร่งการพัฒนาได้ หากคุณไม่ได้ใช้ Xcode คำสั่งbazel build
และbazel test
จะมีความสามารถในการสร้างและทดสอบ โดยมีข้อจำกัดบางอย่างที่อธิบายไว้ในส่วนถัดไปของคู่มือนี้
ก่อนเริ่มต้น
โปรดทำตามขั้นตอนต่อไปนี้ก่อนเริ่มต้น
ติดตั้ง Bazel หากยังไม่ได้ทำ
หากคุณไม่คุ้นเคยกับ Bazel และแนวคิดต่างๆ โปรดดูบทแนะนำสำหรับแอป iOS คุณควรทำความเข้าใจเวิร์กสเปซ Bazel ซึ่งรวมถึงไฟล์
WORKSPACE
และBUILD
ตลอดจนแนวคิดเกี่ยวกับเป้าหมาย กฎการสร้าง และแพ็กเกจ Bazelวิเคราะห์และทำความเข้าใจทรัพยากร Dependency ของโปรเจ็กต์
วิเคราะห์ทรัพยากร Dependency ของโปรเจ็กต์
ซึ่งแตกต่างจาก Xcode เนื่องจาก Bazel กำหนดให้คุณประกาศการอ้างอิงทั้งหมดสำหรับเป้าหมายทุกรายการในไฟล์ BUILD
อย่างชัดเจน
ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากรภายนอกได้ที่หัวข้อการทํางานกับทรัพยากรภายนอก
บิลด์หรือทดสอบโปรเจ็กต์ Xcode ด้วย Bazel
หากต้องการสร้างหรือทดสอบโปรเจ็กต์ Xcode ด้วย Bazel ให้ทําดังนี้
ขั้นตอนที่ 1: สร้างไฟล์ WORKSPACE
สร้างไฟล์ WORKSPACE
ในไดเรกทอรีใหม่ ไดเรกทอรีนี้จะกลายเป็นรูทเวิร์กสเปซของ Bazel หากโปรเจ็กต์ไม่ใช้ทรัพยากรภายนอก ไฟล์นี้อาจเป็นไฟล์ว่าง หากโปรเจ็กต์ใช้ไฟล์หรือแพ็กเกจที่ไม่ได้อยู่ในไดเรกทอรีของโปรเจ็กต์ ให้ระบุการพึ่งพาภายนอกเหล่านี้ในไฟล์ WORKSPACE
ขั้นตอนที่ 2: (ทดลอง) ผสานรวมทรัพยากร Dependency ของ SwiftPM
หากต้องการผสานรวมข้อกำหนดของ SwiftPM เข้ากับเวิร์กช็อป Bazel ด้วย swift_bazel คุณจะต้องแปลงข้อกำหนดเหล่านั้นเป็นแพ็กเกจ Bazel ตามที่อธิบายไว้ในบทแนะนำต่อไปนี้
ขั้นตอนที่ 3: สร้างไฟล์ BUILD
เมื่อกำหนดพื้นที่ทำงานและไลบรารีภายนอกแล้ว คุณจะต้องสร้างไฟล์ BUILD
เพื่อบอก Bazel ว่าโปรเจ็กต์มีโครงสร้างอย่างไร สร้างไฟล์ BUILD
ที่รูทของพื้นที่ทํางาน Bazel และกำหนดค่าให้ทำการบิลด์โปรเจ็กต์ครั้งแรกดังนี้
- ขั้นตอนที่ 3ก: เพิ่มเป้าหมายแอปพลิเคชัน
- ขั้นตอนที่ 3ข: (ไม่บังคับ) เพิ่มเป้าหมายการทดสอบ
- ขั้นตอนที่ 3ค: เพิ่มเป้าหมายคลัง
เคล็ดลับ: ดูข้อมูลเพิ่มเติมเกี่ยวกับแพ็กเกจและแนวคิดอื่นๆ ของ Bazel ได้ที่หัวข้อเวิร์กช็อป แพ็กเกจ และเป้าหมาย
ขั้นตอนที่ 3ก: เพิ่มเป้าหมายแอปพลิเคชัน
เพิ่มเป้าหมายกฎ macos_application
หรือ ios_application
เป้าหมายนี้จะสร้าง App Bundle ของ macOS หรือ iOS ตามลำดับ
ในเป้าหมาย ให้ระบุข้อมูลต่อไปนี้เป็นอย่างน้อย
bundle_id
- รหัสกลุ่ม (เส้นทาง DNS แบบย้อนกลับตามด้วยชื่อแอป) ของไฟล์ไบนารีprovisioning_profile
- โปรไฟล์การกําหนดค่าจากบัญชีนักพัฒนาแอป Apple (หากสร้างสําหรับอุปกรณ์ iOS)families
(iOS เท่านั้น) - เลือกว่าจะสร้างแอปพลิเคชันสำหรับ iPhone, iPad หรือทั้ง 2 อย่างinfoplists
- รายการไฟล์ .plist ที่จะผสานลงในไฟล์ Info.plist สุดท้ายminimum_os_version
- เวอร์ชัน macOS หรือ iOS ขั้นต่ำที่แอปพลิเคชันรองรับ วิธีนี้ช่วยให้มั่นใจว่า Bazel จะสร้างแอปพลิเคชันด้วยระดับ API ที่ถูกต้อง
ขั้นตอนที่ 3ข: (ไม่บังคับ) เพิ่มเป้าหมายการทดสอบ
กฎการสร้างของ Apple ของ Bazel รองรับการเรียกใช้การทดสอบยูนิตที่อิงตามไลบรารีใน iOS และ macOS รวมถึงการทดสอบที่อิงตามแอปพลิเคชันใน macOS สําหรับการทดสอบที่อิงตามแอปพลิเคชันใน iOS หรือการทดสอบ UI บนแพลตฟอร์มใดแพลตฟอร์มหนึ่ง Bazel จะสร้างเอาต์พุตการทดสอบ แต่การทดสอบต้องทํางานภายใน Xcode ผ่านโปรเจ็กต์ที่สร้างด้วย rules_xcodeproj เพิ่มเป้าหมายการทดสอบดังนี้
macos_unit_test
เพื่อเรียกใช้การทดสอบ 1 หน่วยที่อิงตามไลบรารีและที่อิงตามแอปพลิเคชันใน macOSios_unit_test
เพื่อเรียกใช้การทดสอบ 1 หน่วยที่อิงตามไลบรารีใน iOS สําหรับการทดสอบที่ต้องใช้โปรแกรมจําลอง iOS Bazel จะสร้างเอาต์พุตการทดสอบ แต่ไม่เรียกใช้การทดสอบ คุณต้องสร้างโปรเจ็กต์ Xcode ด้วย rules_xcodeproj และเรียกใช้การทดสอบจากภายใน Xcodeios_ui_test
เพื่อสร้างเอาต์พุตที่จําเป็นสําหรับการเรียกใช้การทดสอบอินเทอร์เฟซผู้ใช้ในโปรแกรมจําลอง iOS ใช้ Xcode คุณต้องสร้างโปรเจ็กต์ Xcode ด้วย rules_xcodeproj และเรียกใช้การทดสอบจากภายใน Xcode Bazel ไม่สามารถเรียกใช้การทดสอบ UI เองได้
ระบุค่าสำหรับแอตทริบิวต์ minimum_os_version
เป็นอย่างน้อย แม้ว่าแอตทริบิวต์การบรรจุอื่นๆ เช่น bundle_identifier
และ infoplists
จะมีค่าเริ่มต้นเป็นค่าที่ใช้กันมากที่สุด แต่โปรดตรวจสอบว่าค่าเริ่มต้นเหล่านั้นเข้ากันได้กับโปรเจ็กต์และปรับค่าตามความจำเป็น สําหรับการทดสอบที่ต้องใช้โปรแกรมจําลอง iOS ให้ระบุios_application
ชื่อเป้าหมายเป็นค่าของแอตทริบิวต์ test_host
ด้วย
ขั้นตอนที่ 3ค: เพิ่มเป้าหมายคลัง
เพิ่มเป้าหมาย objc_library
ให้กับไลบรารี Objective-C แต่ละรายการ และเป้าหมาย swift_library
ให้กับไลบรารี Swift แต่ละรายการที่แอปพลิเคชันและ/หรือการทดสอบใช้
เพิ่มเป้าหมายของไลบรารีดังนี้
เพิ่มเป้าหมายของไลบรารีแอปพลิเคชันเป็นข้อกำหนดของเป้าหมายแอปพลิเคชัน
เพิ่มเป้าหมายของไลบรารีทดสอบเป็นข้อกําหนดของเป้าหมายการทดสอบ
แสดงแหล่งที่มาของการติดตั้งใช้งานในแอตทริบิวต์
srcs
แสดงรายการส่วนหัวในแอตทริบิวต์
hdrs
คุณสามารถเรียกดูตัวอย่างที่มีอยู่สำหรับแอปพลิเคชันประเภทต่างๆ ได้โดยตรงในไดเรกทอรีตัวอย่าง rules_apple เช่น
ดูข้อมูลเพิ่มเติมเกี่ยวกับกฎการสร้างได้ที่กฎของ Apple สำหรับ Bazel
ตอนนี้คุณควรทดสอบบิลด์ โดยทำดังนี้
bazel build //:<application_target>
ขั้นตอนที่ 4: (ไม่บังคับ) ปรับแต่งบิลด์ให้ละเอียดยิ่งขึ้น
หากโปรเจ็กต์มีขนาดใหญ่หรือมีขนาดใหญ่ขึ้นเรื่อยๆ ให้พิจารณาแบ่งโปรเจ็กต์ออกเป็นแพ็กเกจ Bazel หลายรายการ รายละเอียดที่ละเอียดยิ่งขึ้นนี้ให้ประโยชน์ดังนี้
การเพิ่มจำนวนบิลด์
เพิ่มการทํางานแบบขนานของงานสร้าง
ความสามารถในการบำรุงรักษาที่ดียิ่งขึ้นสำหรับผู้ใช้ในอนาคต
ควบคุมระดับการเข้าถึงซอร์สโค้ดในเป้าหมายและแพ็กเกจต่างๆ ได้ดียิ่งขึ้น วิธีนี้ช่วยป้องกันปัญหาต่างๆ เช่น ไลบรารีที่มีรายละเอียดการใช้งานรั่วไหลไปยัง API สาธารณะ
เคล็ดลับในการทำให้โปรเจ็กต์มีรายละเอียดมากขึ้น
ใส่ไลบรารีแต่ละรายการในแพ็กเกจ Bazel ของตัวเอง เริ่มจากรายการที่ต้องอาศัยการอ้างอิงน้อยที่สุด แล้วค่อยๆ ไล่ไปตามลําดับชั้นการอ้างอิง
เมื่อคุณเพิ่มไฟล์
BUILD
และระบุเป้าหมาย ให้เพิ่มเป้าหมายใหม่เหล่านี้ลงในแอตทริบิวต์deps
ของเป้าหมายที่ขึ้นอยู่กับไฟล์BUILD
ฟังก์ชัน
glob()
จะไม่ข้ามขอบเขตของแพ็กเกจ ดังนั้นเมื่อจำนวนแพ็กเกจเพิ่มขึ้น ไฟล์ที่ตรงกับglob()
ก็จะลดลงเมื่อเพิ่มไฟล์
BUILD
ลงในไดเรกทอรีmain
ให้เพิ่มไฟล์BUILD
ลงในไดเรกทอรีtest
ที่เกี่ยวข้องด้วยบังคับใช้ขีดจํากัดการแสดงผลที่เหมาะสมในแพ็กเกจต่างๆ
บิลด์โปรเจ็กต์หลังจากการเปลี่ยนแปลงที่สำคัญแต่ละครั้งในไฟล์
BUILD
และแก้ไขข้อผิดพลาดในการบิลด์เมื่อพบ
ขั้นตอนที่ 5: เรียกใช้บิลด์
เรียกใช้บิลด์ที่ย้ายข้อมูลแล้วทั้งหมดเพื่อให้แน่ใจว่าดำเนินการเสร็จสมบูรณ์โดยไม่มีข้อผิดพลาดหรือคำเตือน เรียกใช้แอปพลิเคชันและเป้าหมายการทดสอบแต่ละรายการแยกกันเพื่อให้ค้นหาแหล่งที่มาของข้อผิดพลาดที่เกิดขึ้นได้ง่ายขึ้น
เช่น
bazel build //:my-target
ขั้นตอนที่ 6: สร้างโปรเจ็กต์ Xcode ด้วย rules_xcodeproj
เมื่อสร้างด้วย Bazel ไฟล์ WORKSPACE
และ BUILD
จะเป็นแหล่งที่มาของข้อมูลเกี่ยวกับบิลด์ หากต้องการให้ Xcode ทราบถึงการดำเนินการนี้ คุณต้องสร้างโปรเจ็กต์ Xcode ที่เข้ากันได้กับ Bazel โดยใช้ rules_xcodeproj
การแก้ปัญหา
ข้อผิดพลาดของ Bazel อาจเกิดขึ้นเมื่อไม่ซิงค์กับเวอร์ชัน Xcode ที่เลือก เช่น เมื่อคุณใช้การอัปเดต ลองทำตามขั้นตอนต่อไปนี้หากพบข้อผิดพลาดเกี่ยวกับ Xcode เช่น "ต้องระบุเวอร์ชัน Xcode เพื่อใช้ Apple CROSSTOOL"
เรียกใช้ Xcode ด้วยตนเองและยอมรับข้อกำหนดและเงื่อนไข
ใช้ Xcode Select เพื่อระบุเวอร์ชันที่ถูกต้อง ยอมรับใบอนุญาต และล้างสถานะของ Bazel
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license
bazel sync --configure
- หากไม่ได้ผล ให้ลองเรียกใช้
bazel clean --expunge
ด้วย