- แอปพลิเคชันบน 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 ความคิดเห็น
ความคิดเห็นจาก 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) ที่แย่ที่สุดเท่าที่เคยเจอ
การพยายามแก้เรื่องนี้โดยไม่มีฮาร์ดแวร์ของ 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
แอป Power Mac บน Mac OS แบบคลาสสิกจะ เก็บโค้ด PPC ไว้ใน data fork
ไบนารี CFM-68K ก็เหมือนกัน ส่วนที่ใช้ resource CODE มีแค่โค้ด 68K รุ่นเก่าเท่านั้น
ยังจำได้ว่าสมัยก่อนแก้แอปด้วย ResEdit แล้วสนุกมาก
การที่ ระบบราชการระเบิดตัว แบบในไดอะแกรมสุดท้ายนั้นไม่ใช่สัญญาณที่ดี
ยิ่งทำให้มีเหตุผลน้อยลงที่จะ “อัปเกรด” ไป macOS 26
แม้โครงสร้างปัจจุบันจะเป็น “มาตรฐาน” ของ macOS แต่ก็ ไม่ใช่วิธีเดียว
ถ้าตั้งค่า RPATH ดี ๆ ก็ยังใส่ไลบรารีไว้ในโฟลเดอร์ย่อยอะไรก็ได้และผ่าน notarization ได้
เช่นพาธ AppName.App/Contents/Libraries ก็ใช้ได้
แต่ในทางปฏิบัติแทบไม่มีข้อดีอะไร และจากแอปราว 100 ตัวในเครื่องของฉันก็ไม่มีตัวไหนใช้โฟลเดอร์ /Libraries เลย
ต้องใช้รูปแบบ .framework เท่านั้น ห้ามใช้ .dylib และนี่ก็เป็นกฎที่ไม่ได้มีเอกสารอธิบายไว้
ระบบอาจตรวจเจออัตโนมัติตอนส่งขึ้นและปฏิเสธได้