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

รายงานปัญหา ดูซอร์สโค้ด รุ่น Nightly · 8.0 7.4 7.3 · 7.2 · 7.1 · 7.0 · 6.5

หน้านี้จะอธิบายวิธีสร้างหรือทดสอบโปรเจ็กต์ 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 จะมีความสามารถในการสร้างและทดสอบ โดยมีข้อจำกัดบางอย่างที่อธิบายไว้ในส่วนถัดไปของคู่มือนี้

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

โปรดทำตามขั้นตอนต่อไปนี้ก่อนเริ่มต้น

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

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

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

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

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

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

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

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

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

  2. (ทดลอง) ผสานรวมข้อกําหนดของ SwiftPM

  3. สร้างไฟล์ BUILD

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

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

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

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

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

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

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

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

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

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

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

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

เคล็ดลับ: ดูข้อมูลเพิ่มเติมเกี่ยวกับแพ็กเกจและแนวคิดอื่นๆ ของ 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 หน่วยที่อิงตามไลบรารีและที่อิงตามแอปพลิเคชันใน macOS

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

  • ios_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 ด้วย