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

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

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

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

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

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

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

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

    • การวิเคราะห์แบบคงที่ น้ำยาล้างที่อยู่ และตัวทำความสะอาดชุดข้อความอาจใช้งานไม่ได้ เนื่องจาก Bazel ไม่ได้สร้างเอาต์พุตที่ Xcode คาดหวังสำหรับฟีเจอร์เหล่านั้น

    • หากคุณสร้างโปรเจ็กต์ Xcode ด้วย Tulsi และใช้โปรเจ็กต์นั้นเพื่อเรียกใช้การทดสอบจากภายใน Xcode Xcode จะเรียกใช้การทดสอบแทน Bazel หากต้องการเรียกใช้การทดสอบด้วย Bazel ให้เรียกใช้คำสั่ง 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 ของ CocoaPods

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

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

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

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

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

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

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

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

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

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

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

ขั้นตอนที่ 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 รองรับการเรียกใช้การทดสอบหน่วยตามไลบรารีใน iOS และ macOS รวมถึงการทดสอบที่อิงตามแอปพลิเคชันใน macOS สำหรับการทดสอบบนแอปพลิเคชันใน iOS หรือการทดสอบ UI ในแพลตฟอร์มทั้งสอง Bazel จะสร้างเอาต์พุตการทดสอบ แต่การทดสอบต้องทำงานภายใน Xcode ผ่านโปรเจ็กต์ที่สร้างด้วย Tulsi เพิ่มเป้าหมายทดสอบดังนี้

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

  • ios_unit_test เพื่อทำการทดสอบหน่วยตามไลบรารีใน iOS สำหรับการทดสอบที่ต้องใช้โปรแกรมจำลอง iOS นั้น Bazel จะสร้างเอาต์พุตทดสอบแต่ไม่ได้เรียกใช้การทดสอบ คุณต้องสร้างโปรเจ็กต์ Xcode ด้วย Tulsi และเรียกใช้การทดสอบจากภายใน Xcode

  • ios_ui_test เพื่อสร้างเอาต์พุตที่จำเป็นต่อการเรียกใช้การทดสอบอินเทอร์เฟซผู้ใช้ในเครื่องมือจำลอง iOS โดยใช้ Xcode คุณต้องสร้างโปรเจ็กต์ Xcode ด้วย Tulsi และเรียกใช้การทดสอบจากภายใน Xcode Bazel ทำการทดสอบ UI แบบดั้งเดิมไม่ได้

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

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

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

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

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

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

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

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับกฎการสร้างได้ที่กฎของ 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 ด้วย Tulsi

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

การแก้ปัญหา

ข้อผิดพลาด 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 ได้ด้วย