การย้ายข้อมูลจาก Xcode ไปยัง Bazel

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

หน้านี้จะอธิบายวิธีสร้างหรือทดสอบโปรเจ็กต์ Xcode ด้วย Bazel โดยจะอธิบายความแตกต่างระหว่าง Xcode และ Bazel และให้ขั้นตอนในการแปลงโปรเจ็กต์ Xcode เป็นโปรเจ็กต์ Bazel และยังมีวิธีแก้ปัญหา เพื่อแก้ไขข้อผิดพลาดที่พบบ่อยอีกด้วย

ความแตกต่างระหว่าง Xcode และ Bazel

  • Bazel กำหนดให้คุณระบุเป้าหมายของบิลด์และการอ้างอิงทั้งหมดอย่างชัดเจน รวมถึงการตั้งค่าบิลด์ที่เกี่ยวข้องผ่านกฎบิลด์

  • Bazel กำหนดให้ไฟล์ทั้งหมดที่โปรเจ็กต์ต้องปรากฏภายในไดเรกทอรีพื้นที่ทำงานหรือระบุเป็นการนำเข้าในไฟล์ WORKSPACE

  • เมื่อสร้างโปรเจ็กต์ Xcode ด้วย Bazel ไฟล์ BUILD จะกลายเป็นแหล่งข้อมูลที่ถูกต้อง หากทำงานกับโปรเจ็กต์ใน Xcode คุณต้องสร้างโปรเจ็กต์ Xcode เวอร์ชันใหม่ที่ตรงกับไฟล์ BUILD โดยใช้ rules_xcodeproj ทุกครั้งที่อัปเดตไฟล์ BUILD การเปลี่ยนแปลงบางอย่างในไฟล์ BUILD เช่น การเพิ่มการอ้างอิงไปยังเป้าหมายไม่จำเป็นต้องสร้างโปรเจ็กต์ใหม่ซึ่งจะช่วยให้การพัฒนาเร็วขึ้นได้ หากไม่ได้ใช้ Xcode คำสั่ง bazel build และ bazel test จะให้ความสามารถในการสร้างและทดสอบโดยมีข้อจำกัดบางประการตามที่อธิบายไว้ภายหลังในคู่มือนี้

ก่อนเริ่มต้น

ก่อนที่จะเริ่มต้น ให้ทำดังนี้

  1. ติดตั้ง Bazel หากยังไม่ได้ติดตั้ง

  2. หากไม่คุ้นเคยกับ Bazel และแนวคิดของ Bazel โปรดอ่านบทแนะนำแอป iOS) คุณควรทำความเข้าใจพื้นที่ทำงานของ Bazel รวมถึงไฟล์ WORKSPACE และ BUILD รวมถึงแนวคิดของเป้าหมาย กฎการสร้าง และแพ็กเกจ Bazel

  3. วิเคราะห์และทำความเข้าใจทรัพยากร Dependency ของโปรเจ็กต์

วิเคราะห์ทรัพยากร Dependency ของโปรเจ็กต์

Bazel กำหนดให้คุณประกาศทรัพยากร Dependency ทั้งหมดอย่างชัดเจนสำหรับทุกเป้าหมายในไฟล์ BUILD ซึ่งต่างจาก Xcode

ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากร Dependency ภายนอกได้ที่การทำงานกับทรัพยากร Dependency ภายนอก

สร้างหรือทดสอบโปรเจ็กต์ Xcode ด้วย Bazel

หากต้องการสร้างหรือทดสอบโปรเจ็กต์ Xcode ด้วย Bazel ให้ทําดังนี้

  1. สร้างไฟล์ WORKSPACE

  2. (ทดลอง) ผสานรวมทรัพยากร Dependency ของ SwiftPM

  3. สร้างไฟล์ BUILD ดังนี้

    a. เพิ่มเป้าหมายแอปพลิเคชัน

    b. (ไม่บังคับ) เพิ่มเป้าหมายทดสอบ

    ค. เพิ่มเป้าหมายไลบรารี

  4. (ไม่บังคับ) ปรับแต่งบิลด์

  5. เรียกใช้บิลด์

  6. สร้างโปรเจ็กต์ Xcode ด้วย rules_xcodeproj

ขั้นตอนที่ 1: สร้างไฟล์ WORKSPACE

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

ขั้นตอนที่ 2: (ทดลอง) ผสานรวมทรัพยากร Dependency ของ SwiftPM

หากต้องการผสานรวมทรัพยากร Dependency ของ SwiftPM ลงในพื้นที่ทำงานของ Bazel ด้วย swift_bazel คุณต้องแปลงทรัพยากรเหล่านั้นเป็นแพ็กเกจ Bazel ตามที่อธิบายไว้ในบทแนะนำต่อไปนี้

ขั้นตอนที่ 3: สร้างไฟล์ BUILD

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

เคล็ดลับ: ดูข้อมูลเพิ่มเติมเกี่ยวกับแพ็กเกจและแนวคิดอื่นๆ ของ Bazel ได้ที่พื้นที่ทำงาน แพ็กเกจ และเป้าหมาย

ขั้นตอนที่ 3ก: เพิ่มเป้าหมายแอปพลิเคชัน

เพิ่มเป้าหมายกฎ macos_application หรือ ios_application เป้าหมายนี้จะสร้างชุดแอปพลิเคชัน macOS หรือ iOS ตามลำดับ ในเป้าหมาย ให้ระบุข้อมูลต่อไปนี้อย่างน้อย

  • bundle_id - รหัสชุด (เส้นทาง Reverse-DNS ตามด้วยชื่อแอป) ของไบนารี

  • provisioning_profile - การจัดสรรโปรไฟล์จากบัญชีนักพัฒนาซอฟต์แวร์ Apple (หากสร้างขึ้นสำหรับอุปกรณ์ iOS)

  • families (iOS เท่านั้น) - เลือกว่าจะสร้างแอปพลิเคชันสำหรับ iPhone, iPad หรือทั้ง 2 อย่าง

  • infoplists - รายการไฟล์ .plist ที่จะผสานเข้ากับไฟล์ Info.plist ขั้นสุดท้าย

  • minimum_os_version - macOS หรือ iOS เวอร์ชันต่ำสุดที่แอปพลิเคชันรองรับ วิธีนี้ช่วยให้ Bazel สร้างแอปพลิเคชันด้วยระดับ API ที่ถูกต้อง

ขั้นตอนที่ 3ข: (ไม่บังคับ) เพิ่มเป้าหมายทดสอบ

กฎการสร้างของ Apple ของ Bazel รองรับการเรียกใช้การทดสอบหน่วยและ UI ในทุกแพลตฟอร์มของ Apple เพิ่มเป้าหมายทดสอบดังนี้

  • macos_unit_test เพื่อเรียกใช้การทดสอบหน่วยตามไลบรารีและตามแอปพลิเคชันใน macOS

  • ios_unit_test เพื่อสร้างและเรียกใช้การทดสอบหน่วยตามไลบรารีใน iOS

  • ios_ui_test เพื่อสร้างและเรียกใช้การทดสอบอินเทอร์เฟซผู้ใช้ในเครื่องมือจำลอง iOS

  • และมีกฎการทดสอบที่คล้ายกันสำหรับ tvOS, watchOS และ visionOS

ระบุค่าสำหรับแอตทริบิวต์ minimum_os_version เป็นอย่างน้อย แม้ว่าแอตทริบิวต์แพ็กเกจอื่นๆ เช่น bundle_identifier และ infoplists จะเป็นค่าเริ่มต้นที่ใช้บ่อยที่สุด โปรดตรวจสอบว่าค่าเริ่มต้นเหล่านั้นเข้ากันได้กับโปรเจ็กต์และปรับเปลี่ยนตามความจำเป็น สำหรับการทดสอบที่ต้องใช้โปรแกรมจำลอง iOS ให้ระบุชื่อเป้าหมาย ios_application เป็นค่าของแอตทริบิวต์ test_host ด้วย

ขั้นตอนที่ 3ค: เพิ่มเป้าหมายไลบรารี

เพิ่มเป้าหมาย objc_library สำหรับไลบรารี Objective-C แต่ละรายการและเป้าหมาย swift_library สำหรับไลบรารี Swift แต่ละรายการที่แอปพลิเคชันและ/หรือการทดสอบอ้างอิง

เพิ่มเป้าหมายไลบรารีดังนี้

  • เพิ่มเป้าหมายไลบรารีแอปพลิเคชันเป็นทรัพยากร Dependency ของเป้าหมายแอปพลิเคชัน

  • เพิ่มเป้าหมายไลบรารีทดสอบเป็นทรัพยากร Dependency ของเป้าหมายทดสอบ

  • ระบุแหล่งที่มาของการใช้งานในแอตทริบิวต์ srcs

  • ระบุส่วนหัวในแอตทริบิวต์ hdrs

คุณเรียกดูตัวอย่างที่มีอยู่ของแอปพลิเคชันประเภทต่างๆ ได้โดยตรงในไดเรกทอรีตัวอย่างrules_apple เช่น

ดูข้อมูลเพิ่มเติมเกี่ยวกับกฎการสร้างได้ที่กฎของ Apple สำหรับ Bazel

ณ จุดนี้ เป็นความคิดที่ดีที่จะทดสอบบิลด์:

bazel build //:<application_target>

ขั้นตอนที่ 4: (ไม่บังคับ) ปรับแต่งบิลด์

หากโปรเจ็กต์มีขนาดใหญ่หรือเมื่อขยายใหญ่ขึ้น ให้พิจารณาแบ่งโปรเจ็กต์ออกเป็นแพ็กเกจ Bazel หลายๆ แพ็กเกจ รายละเอียดที่เพิ่มขึ้นนี้มอบสิ่งต่อไปนี้

  • ส่วนเพิ่มของบิลด์

  • เพิ่มงานบิวด์พร้อมกัน

  • เพื่อการบำรุงรักษาที่ดีขึ้นสำหรับผู้ใช้ในอนาคต

  • ควบคุมการแสดงซอร์สโค้ดในเป้าหมายและแพ็กเกจได้ดียิ่งขึ้น ซึ่งเป็นการป้องกันปัญหาต่างๆ เช่น ไลบรารีที่มีรายละเอียดการใช้งานรั่วไหลเข้าสู่ API สาธารณะ

เคล็ดลับสำหรับความละเอียดของโครงการ

  • ใส่ไลบรารีแต่ละรายการลงในแพ็กเกจ Bazel ของตนเอง เริ่มจากโปรแกรมที่ต้องใช้ทรัพยากร Dependency น้อยที่สุด แล้วค่อยๆ เพิ่มทรัพยากร Dependency ให้สูงขึ้น

  • เมื่อเพิ่มไฟล์ BUILD และระบุเป้าหมาย ให้เพิ่มเป้าหมายใหม่เหล่านี้ลงในแอตทริบิวต์ deps ของเป้าหมายที่จำเป็นต้องใช้

  • ฟังก์ชัน glob() จะไม่ข้ามขอบเขตของแพ็กเกจ ดังนั้นเมื่อจำนวนแพ็กเกจเพิ่มขึ้น ไฟล์ที่ตรงกับ glob() จะลดลง

  • เมื่อเพิ่มไฟล์ BUILD ในไดเรกทอรี main ให้เพิ่มไฟล์ BUILD ในไดเรกทอรี test ที่เกี่ยวข้องด้วย

  • บังคับใช้ขีดจำกัดระดับการเข้าถึงที่มีประสิทธิภาพในแพ็กเกจต่างๆ

  • สร้างโปรเจ็กต์หลังการเปลี่ยนแปลงสำคัญแต่ละครั้งในไฟล์ BUILD และแก้ไขข้อผิดพลาดของรุ่นที่พบ

ขั้นตอนที่ 5: เรียกใช้บิลด์

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

เช่น

bazel build //:my-target

ขั้นตอนที่ 6: สร้างโปรเจ็กต์ Xcode ด้วย rules_xcodeproj

เมื่อสร้างด้วย Bazel ไฟล์ WORKSPACE และ BUILD จะกลายเป็นแหล่งที่มา ที่แท้จริงเกี่ยวกับบิลด์ หากต้องการให้ Xcode ตระหนักถึงเรื่องนี้ คุณต้องสร้างโปรเจ็กต์ Xcode ที่เข้ากันได้กับ Bard โดยใช้ rules_xcodeproj

การแก้ปัญหา

ข้อผิดพลาด Bazel อาจเกิดขึ้นเมื่อแอปไม่ซิงค์กับ Xcode เวอร์ชันที่เลือก เช่น เมื่อคุณใช้การอัปเดต ต่อไปนี้เป็นสิ่งที่ควรลองทำเมื่อพบข้อผิดพลาดกับ Xcode เช่น "ต้องระบุเวอร์ชัน Xcode เพื่อใช้ Apple CROSSTOOL"

  • เรียกใช้ Xcode ด้วยตนเองและยอมรับข้อกำหนดในการให้บริการ

  • ใช้การเลือก Xcode เพื่อระบุเวอร์ชันที่ถูกต้อง ยอมรับใบอนุญาต และล้างสถานะของ Bazel

  sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
  sudo xcodebuild -license
  bazel sync --configure
  • หากไม่ได้ผล คุณสามารถลองเรียกใช้ bazel clean --expunge ได้ด้วย