10 คะแนน โดย GN⁺ 2025-12-09 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • แอปพลิเคชันบน macOS มี องค์ประกอบที่ซับซ้อนกว่าโปรแกรมบรรทัดคำสั่ง และจัดการทรัพยากรอินเทอร์เฟซอย่างหน้าต่างและเมนูแยกเป็นอีกโครงสร้างหนึ่ง
  • ใน Classic Mac OS โค้ดที่รันได้และรีซอร์สจะถูกเก็บไว้ใน resource fork ของไฟล์ แต่ตั้งแต่ Mac OS X เป็นต้นมาได้เปลี่ยนมาใช้โครงสร้าง bundle
  • app bundle ถูกจัดวางโดยมี ไดเรกทอรี Contents เป็นศูนย์กลาง พร้อมโฟลเดอร์ย่อยอย่าง MacOS·Resources·Frameworks และไฟล์สำคัญอย่าง Info.plist
  • ต่อมามีการเพิ่ม code signing·ใบเสร็จ App Store·notarization เข้ามา ทำให้โครงสร้างพัฒนาไปในทิศทางที่เสริมความปลอดภัยและความสมบูรณ์ของไฟล์
  • โครงสร้างแบบ พึ่งพาตัวเองได้ (app bundle) นี้กลายเป็นรากฐานสำคัญที่ช่วยให้การติดตั้ง·อัปเดต·ลบ ทำได้ง่ายขึ้น และเพิ่มทั้ง ความปลอดภัยและประสิทธิภาพในการดูแลรักษา

โครงสร้างแอปของ Classic Mac OS

  • ใน Mac OS ยุคแรก รีซอร์ส UI อย่างหน้าต่างและเมนูจะถูกแยกจากไฟล์ปฏิบัติการ แล้วเก็บไว้ใน resource fork
    • ตัวอย่างเช่น รีซอร์สของ QuarkXPress 4.11 แสดงให้เห็นได้ใน ResEdit
    • โค้ดที่รันได้จะอยู่ใน CODE resource และมีการเก็บข้อมูล type และ creator ของไฟล์ไว้ด้วยเพื่อให้ Finder รู้จัก

โครงสร้าง bundle ของ Mac OS X

  • Mac OS X นำโครงสร้าง bundle ที่สืบทอดมาจาก NeXTSTEP มาใช้
    • แอปมีลักษณะเป็นไดเรกทอรีที่มีนามสกุล .app และภายในมีโฟลเดอร์ Contents
    • โฟลเดอร์ MacOS มีทั้งไฟล์ปฏิบัติการของแอป GUI และเครื่องมือบรรทัดคำสั่ง
    • โฟลเดอร์ Resources ใช้เก็บไฟล์รีซอร์ส เช่น ไอคอนแอป และองค์ประกอบ GUI
    • บางแอปมี โฟลเดอร์ Frameworks เพื่อบรรจุ dylib (ไลบรารีแบบไดนามิก) ไว้ภายใน
  • ไฟล์ Info.plist เป็นสิ่งจำเป็น โดยใช้กำหนดชื่อไฟล์ปฏิบัติการ ไอคอน เวอร์ชัน macOS ขั้นต่ำ ประเภทเอกสาร หมายเลขเวอร์ชัน ฯลฯ
  • ไฟล์ PkgInfo ยังคงเก็บข้อมูล type·creator จาก Classic Mac OS ไว้ แต่ไม่ใช่สิ่งจำเป็น
  • เมื่อรันแอป launchd จะเป็นตัวเริ่มโค้ดปฏิบัติการ และ LaunchServices กับ RunningBoard จะดำเนินขั้นตอนเริ่มต้นตามข้อมูลใน Info.plist

ความปลอดภัยและการขยายใน macOS

  • ตั้งแต่ Mac OS X 10.5 Leopard (2007) เป็นต้นมา มีการนำ Code Signature มาใช้ ทำให้มีการเพิ่มโฟลเดอร์ _CodeSignature
    • ในไฟล์ CodeResources จะมี code directory hash (CDHash) เพื่อใช้ตรวจสอบความสมบูรณ์ของแอป
  • แอปที่แจกจ่ายผ่าน App Store จะมี ใบเสร็จจากสโตร์ อยู่ในโฟลเดอร์ _MASReceipt
  • หลังปี 2018 มีการนำ notarization มาใช้ โดย Apple ออก ticket ที่สามารถ “staple” เข้ากับ bundle ผ่านไฟล์ CodeResources ได้
  • app bundle สมัยใหม่บรรจุองค์ประกอบต่าง ๆ ที่ในอดีตเคยต้องติดตั้งไว้ในโฟลเดอร์ของระบบมาไว้ในตัวเอง
    • โฟลเดอร์ Library: LaunchDaemons, LoginItems เป็นต้น
    • โฟลเดอร์ XPCServices: บริการแยกต่างหากที่แอปใช้งาน
    • โฟลเดอร์ Plugins / Extensions: ความสามารถเสริมของแอปและ App Intents
    • บางแอปยังมีไฟล์ version.plist ด้วย

ข้อดีของ app bundle

  • การ รวมทุกองค์ประกอบไว้ภายใน bundle ทำให้การติดตั้ง·อัปเดต·ลบ ทำได้สะดวก
  • ลดโอกาสที่องค์ประกอบจะขาดหาย และเสริม ความปลอดภัย ผ่านการป้องกันด้วย ลายเซ็นและ notarization
  • แอปจาก App Store ยังมี ใบเสร็จและ ticket สำหรับ notarization เพิ่มเติมเพื่อสร้างความน่าเชื่อถือ
  • ไม่มีความต่างเชิงโครงสร้างระหว่าง สถาปัตยกรรม Intel และ Arm โดย ไฟล์ปฏิบัติการ Mach-O จะถูกเก็บในรูปแบบ universal (fat) binary ที่มีโค้ดสำหรับทั้งสองแพลตฟอร์ม
    • ภายในไฟล์เดียวกันจะมี signature ของแต่ละสถาปัตยกรรมอยู่ร่วมกัน

ภาพรวมเชิงภาพของโครงสร้างแอป

  • ในไดอะแกรม สีเหลืองอ่อน หมายถึงองค์ประกอบที่จำเป็นหรือพบได้ในเกือบทุกแอป
  • สีเขียว คือรายการที่มีเฉพาะในแอปที่แจกจ่ายผ่าน App Store ส่วน สีน้ำเงิน หมายถึง ticket สำหรับ notarization ที่เป็นตัวเลือก
  • นอกจากนี้ยังอาจมีองค์ประกอบเสริมอย่าง Automator workflow, สคริปต์ เป็นต้น
  • โดยรวมแล้ว แอป macOS ได้พัฒนาไปสู่ โครงสร้างแบบพึ่งพาตัวเองและเน้นความปลอดภัย

1 ความคิดเห็น

 
GN⁺ 2025-12-09
ความคิดเห็นจาก Hacker News
  • ส่วนที่ไฮไลต์เป็นสีน้ำเงินคือ notarisation ticket ซึ่งในทางปฏิบัติแล้วแทบไม่ใช่ตัวเลือก
    แอปที่ไม่ได้ notarize จะสร้างความยุ่งยากให้ผู้ใช้มาก จนสุดท้ายก็ต้องจ่าย ค่าสมัครนักพัฒนา Apple ปีละ $99
    ถ้าสร้างและรันใช้เองก็ไม่เป็นไร แต่ถ้าจะเอาไปแจกจ่าย macOS จะเด้งคำเตือนจนแอปดูเหมือนพัง
    เมื่อก่อนยังคลิกขวาแล้วสั่งเปิดได้ แต่ตอนนี้ต้องเข้าไปอนุญาตใน System Settings ด้วย
    ดูภาพหน้าจอที่เกี่ยวข้องได้ในเอกสารช่วยเหลือของ Apple และข่าวนักพัฒนา
    ฉันชอบแนวคิดด้านความปลอดภัยของ Apple แต่คิดว่า ระบบ notarization สำหรับแอปนอก App Store ทำให้ทุกฝ่ายเสียประโยชน์
    ยังหาเคสที่ notarization ป้องกันปัญหาความปลอดภัยได้จริงไม่เจอ

    • ฉันเคยคิดว่า notarization บน macOS น่ารำคาญแล้ว แต่พอไปลอง แจกจ่ายบน Windows กลับหนักกว่าอีก
      ถ้าจะให้ Windows Defender เชื่อถือ ต้องซื้อ certificate และไม่ว่าจะเป็นบริษัทหรือบุคคลก็ต้องผ่าน การยืนยันตัวตนเชิงลึก
      ยังต้องเซ็นผ่านฮาร์ดแวร์โทเคน ทำให้มีคนปล่อยรีลีสได้แค่คนเดียว
      แถมหน่วยงานออกใบรับรองยังอาจล็อกคีย์แบบตามอำเภอใจได้อีก ถ้าโดนตอนต้องออกแพตช์ความปลอดภัยก็คงแย่มาก
      ในแง่นี้รู้สึกว่า ecosystem ของ macOS ดีกว่ามาก

    • ฉันกำลังพัฒนา ภาษาโปรแกรม ที่คอมไพล์ได้หลายแพลตฟอร์ม ซึ่งการเซ็นและ notarization ไม่เข้ากับกระบวนการนี้เลย
      ระบบการเซ็นแบบนี้เป็นเพียง เครื่องมือควบคุม และเสี่ยงต่อการถูกใช้อย่างมิชอบแบบกรณี Epic
      ถ้าแพลตฟอร์มนั้นไม่เปิดให้รันไบนารีที่ไม่ได้เซ็นได้อย่างสมเหตุสมผล ฉันก็ถือว่าเป็นแพลตฟอร์มปิดและจะไม่รองรับ
      แพลตฟอร์มปิดอย่าง iOS หรือ Android ยังพอทดแทนได้ระดับหนึ่งด้วย PWA
      แต่ตอนนี้ความเชื่อมั่นว่า Google จะยังยอมให้รันแอปที่เซ็นเองต่อไปก็ลดลง

    • ฉันรู้จักอยู่แค่สองกรณีที่ Apple ถอน certificate ของแอปนอก App Store
      อันหนึ่งคือ Research App ของ Facebook อีกอันคือ Screenwise Meter ของ Google
      ทั้งสองเป็นแอปแนวสปายแวร์ที่มุ่งเป้าไปยังวัยรุ่น และการเพิกถอน certificate ก็ทำให้เครื่องมือภายในใช้การไม่ได้ไปด้วย
      หลังจากนั้นดูเหมือนว่า Screenwise Meter จะกลับขึ้น App Store อีกครั้ง
      บทความที่เกี่ยวข้อง: Wired, EFF

    • ประมาณครึ่งหนึ่งของแอปในโฟลเดอร์แอปของฉันไม่ได้ notarize และในทางปฏิบัติก็ ไม่มีปัญหาอะไร

    • หลัง notarize แล้ว stapled ticket ก็ยังเป็นตัวเลือก
      ถ้าไม่แนบ ticket ผู้ใช้จะต้องเช็กสถานะ notarization ผ่านการเชื่อมต่ออินเทอร์เน็ต

  • ระหว่างพัฒนา AppBundler.jl ฉันมีเรื่องไม่พอใจกับโครงสร้างแอปบน macOS เยอะมาก
    การ บังคับโครงสร้างโฟลเดอร์ Frameworks ดูเรียบร้อยก็จริง แต่ในทางปฏิบัติทำให้การ bundle ยุ่งยาก เลยต้องอ้อมไปใช้โฟลเดอร์ Libraries แทน
    ปัญหาใหญ่ที่สุดคือ code signing — การต้องเซ็นทุกไบนารีให้ความรู้สึกสิ้นเปลืองมาก
    เรื่องที่ควรแค่รวบรวม file hash แล้วเซ็นครั้งเดียว กลับถูกทำให้ซับซ้อนขนาดนี้จนเข้าใจยาก
    อีกอย่างคือ entitlements ถูกผูกไว้แค่กับ launcher binary ซึ่งไม่มีประสิทธิภาพ
    และเพราะเกณฑ์ notarization เข้มขึ้นเรื่อย ๆ ตามเวลา วันหนึ่งแอปอาจไม่ผ่านขึ้นมาแบบกะทันหันก็ได้

  • ฉันสมัคร Apple Developer Program เพื่อจะเซ็นและ notarize แอป Tauri แต่ ล้มเหลวมาสามสัปดาห์แล้ว
    เพราะไม่มี Mac เลยพยายามทำผ่าน GitHub Actions แต่ได้ยินว่าการ notarize ครั้งแรกมักใช้เวลานาน
    ค่าใช้จ่ายฝั่ง GitHub ก็เกือบ $100 แล้ว แต่จนตอนนี้ก็ยัง notarize ไม่ผ่าน
    ทีมซัพพอร์ตของ Apple ปฏิเสธจะช่วยเพราะฉันไม่มี Mac และใช้ Tauri
    กระบวนการยืนยันตัวตนของ Notarization API ก็ระดับฝันร้าย — ต้องสร้าง JWT ด้วย PKCS8 แต่เอกสารแทบไม่มีจนต้องเขียนโปรแกรม Node เอง
    นี่เป็น ประสบการณ์นักพัฒนา (DX) ที่แย่ที่สุดเท่าที่เคยเจอ

    • มีคนแนะนำให้ซื้อ Mac mini มือสองสัก $150 แล้วใช้เครื่องนั้นเซ็นแทน
      การพยายามแก้เรื่องนี้โดยไม่มีฮาร์ดแวร์ของ Apple ถูกมองว่าเป็น การเสียเวลาเปล่า
  • พอเห็นภาพหน้าจอ OS ภาพแรกแล้วใจหายเลย
    เมื่อก่อนมันเป็น UI ที่ใช้งานจริงและสะอาดตา แต่เดี๋ยวนี้กลับมีแต่มุมโค้งกับไอคอนฟอง ๆ กินพื้นที่ไปเปล่า ๆ
    ถึงอย่างนั้นก็ยังย้ายไป ThinkPad ไม่ได้ เพราะฮาร์ดแวร์ Mac คุณภาพดีมาก

    • ที่จริงมุมโค้งเป็น คุณสมบัติที่ดีกับการมองเห็นของมนุษย์ มากกว่า
      มีงานวิจัยว่ามุมแหลมทำให้ล้าสายตา
      บทความที่เกี่ยวข้อง: Round Rects Are Everywhere

    • ฉันเองก็ไม่ค่อยชอบ macOS รุ่นใหม่เหมือนกัน แต่ภาพหน้าจอนั้นก็ไม่ได้สมบูรณ์แบบ
      มีเส้นเยอะเกินไปและขาดสี ทำให้สายตาวอกแวก
      สำหรับฉัน Aqua UI ในยุค Leopard มีสมดุลระหว่างความหนาแน่นของข้อมูลกับมิติทางภาพที่ดีกว่า

    • ถ้าวัดกันตามสัดส่วนพิกเซล UI แบบเก่ากลับกินพื้นที่มากกว่า
      ที่ความละเอียด 5K ฝั่ง MacBook Pro ยุคใหม่กลับมีประสิทธิภาพกว่า
      Mac รุ่นคลาสสิกเองก็มีมุมโค้งเล็กน้อยอยู่แล้ว
      ดูได้ที่: Infinite Mac

    • คอมพิวเตอร์ไม่ได้มีไว้ทำงานอย่างเดียว แต่ยังเป็น เครื่องมือเพื่อความเพลิดเพลิน ด้วย
      เพียงแต่ UI สมัยนี้รู้สึกว่าห่างจากความใช้งานได้จริงมากเกินไป

    • ข้อมูลส่วนใหญ่บนหน้าจอเป็นอะไรอย่าง 101101 ที่ไร้ประโยชน์ เลยมองว่ายากจะเรียกว่าใช้งานได้จริง

  • ข้อความที่บอกว่าบน macOS เวลารันเครื่องมือบรรทัดคำสั่ง launchd เป็นตัวสั่งรันนั้นไม่ถูกต้อง
    ความจริงแล้วมันรันจากเชลล์ด้วย fork/spawn เหมือนระบบ UNIX อื่น ๆ

  • ระบบ bundle ของ NeXTSTEP เป็นแรงบันดาลใจให้กับการออกแบบ ไฟล์ JAR ของ Java

    • แต่ JAR ก็เป็นแค่ ไฟล์ ZIP ที่เปลี่ยนนามสกุล เท่านั้น
  • แอป Power Mac บน Mac OS แบบคลาสสิกจะ เก็บโค้ด PPC ไว้ใน data fork
    ไบนารี CFM-68K ก็เหมือนกัน ส่วนที่ใช้ resource CODE มีแค่โค้ด 68K รุ่นเก่าเท่านั้น

  • ยังจำได้ว่าสมัยก่อนแก้แอปด้วย ResEdit แล้วสนุกมาก

  • การที่ ระบบราชการระเบิดตัว แบบในไดอะแกรมสุดท้ายนั้นไม่ใช่สัญญาณที่ดี
    ยิ่งทำให้มีเหตุผลน้อยลงที่จะ “อัปเกรด” ไป macOS 26

    • แต่ก็มีคนมองว่าไม่จำเป็นต้องทำเรื่องใหญ่ แค่มีโฟลเดอร์เพิ่มใน app bundle ไม่กี่อันเท่านั้น
  • แม้โครงสร้างปัจจุบันจะเป็น “มาตรฐาน” ของ macOS แต่ก็ ไม่ใช่วิธีเดียว
    ถ้าตั้งค่า RPATH ดี ๆ ก็ยังใส่ไลบรารีไว้ในโฟลเดอร์ย่อยอะไรก็ได้และผ่าน notarization ได้
    เช่นพาธ AppName.App/Contents/Libraries ก็ใช้ได้
    แต่ในทางปฏิบัติแทบไม่มีข้อดีอะไร และจากแอปราว 100 ตัวในเครื่องของฉันก็ไม่มีตัวไหนใช้โฟลเดอร์ /Libraries เลย

    • ฝั่ง iOS นั้น เข้มงวดกว่าและคลุมเครือกว่า มาก
      ต้องใช้รูปแบบ .framework เท่านั้น ห้ามใช้ .dylib และนี่ก็เป็นกฎที่ไม่ได้มีเอกสารอธิบายไว้
      ระบบอาจตรวจเจออัตโนมัติตอนส่งขึ้นและปฏิเสธได้