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

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

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

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

  • 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. วิเคราะห์และทำความเข้าใจการขึ้นต่อกันของโปรเจ็กต์

วิเคราะห์การขึ้นต่อกันของโปรเจ็กต์

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

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

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

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

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

  2. (ทดลอง) ผสานรวมการขึ้นต่อกันของ SwiftPM

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

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

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

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

  4. (ไม่บังคับ) แยกย่อยบิลด์

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

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

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

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

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

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

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

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

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

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

เพิ่มเป้าหมายกฎ macos_application หรือ ios_application เป้าหมายนี้จะสร้างชุดแอปพลิเคชัน 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 รองรับ การเรียกใช้การทดสอบหน่วยและการทดสอบ UI ในแพลตฟอร์ม Apple ทั้งหมด เพิ่มเป้าหมายการทดสอบดังนี้

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

  • ios_unit_test เพื่อสร้างและเรียกใช้การทำ 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 ของตัวเอง เริ่มจากไลบรารีที่ต้องใช้การขึ้นต่อกันน้อยที่สุด แล้วค่อยๆ ไล่ขึ้นไปตามแผนผังการขึ้นต่อกัน

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

  • ฟังก์ชัน 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 อาจเกิดขึ้นเมื่อ 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