macOS 的应用并不是一整个 .app 文件,而是 App 的软件包(Package),即整合了运行一个应用所需的代码和资源文件的目录(文件夹)。
虽然软件包只是一个普通的文件夹,但由于扩展名是 .app,加上其内部的结构较特殊,因此会被 macOS 当作一个独立的文件对待[1]。
其实,“把目录当作文件”的特性,早在 Mac OS 9 的时代就有所采用,被称为“包”。它类似于 RISC OS 和 ROX Desktop 中的应用程序目录,以及使用 SpatialBundle 技术的 GNU/Linux 发行版(例如 Debian、Ubuntu)。
但“软件包”概念的引入,却构成了 macOS 易用的特点之一,这是因为:
- 在用户面前,软件包将所有的应用资源资源抽象为一个文件,应用的内部不对用户默认展示,这一定程度上减少了应用被用户意外修改而带来的影响。
- 既然软件包可被抽象为一个文件,那么用户就可以移动、拷贝和删除软件包,从而达到安装和卸载软件本体的目的。
在 macOS 上,用户也完全可以查看软件包内的资源,方法是在访达中随便选一个 macOS 应用(注意不是从 App Store 下载的 iOS 应用),右击选择“显示包内容”。
然后双击里面的“Contents”文件夹,就能看到这个软件包的内部结构了。
一般地,macOS App 软件包的结构大致如下:
(iOS 的软件包格式虽然与 macOS 本质上无区别,但结构有所不同,感兴趣的读者可以用同样的方法自行探索)
而在这种看似简单却又错综复杂的结构中,给 macOS 软件开发者带来了一个非常现实的问题:“如何保证 .app 软件包按原样分发?”
这里所谓的“按原样”,不仅有应用结构和内容的完整性,还有内部文件权限的一致性。因为 macOS 的内核是类 Unix 的 Darwin,而 Unix 和类 Unix 系列的系统,对于文件权限有一套严格的管理机制,如果不对此加以重视,就有可能无意之中丢失文件的权限信息,甚至会一定程度影响到应用程序的行为。
从而,如何为应用寻找一个合适的打包方法,是解决这个问题的关键。
回到苹果桌面操作系统的发展史上来,在 OS X 之前的时代(OS X 起源于 2001 年,若干年后改名为 macOS),软件的安装介质基本上是软盘和光盘,而安装软件要么是将应用程序直接从介质拷贝到 Mac,要么是使用介质内的安装程序。
尤其是更加古早的 System Software 时期,网络技术远不如今天那么发达,一个软件的安装往往是以多张软盘的更换为代价的。
到了 OS X 的时代,互联网开始进步,个人电脑的用户数目也有了一定规模,软盘因存储能力不能满足人们的需求,逐渐被光盘淘汰;在 OS X 更名为 macOS 时,随着存储和通讯技术的更新换代,光盘的地位也开始削弱。
而 OS X 初期推出的磁盘映像格式 .dmg,随着时间的推移展现了它的优势。
要说 .dmg 这个格式,虽然第一个采用它来分发软件的厂商或开发者已不可考,但苹果在推广 .dmg 格式的过程中无疑起到了很大的作用(比如旧版的 Xcode 的附加工具里有 .dmg 的制作,直到今天,苹果为开发者提供的一些资源都会装在 .dmg 里)。
.dmg 格式也有一些优点,除了具备磁盘映像的长处之外,还能实现安全加密,支持不同的文件系统(HFS、HFS+、FAT 等)。
私以为,许多软件开发商(包括苹果官方)之所以选用 .dmg 作为软件包分发的形式,有以下四点原因:
①符合软件行业合规的需要,让厂商可以自定义。.dmg 文件可以内嵌用户协议,使得用户只有同意软件协议,才能打开 .dmg 映像里的内容安装程序,否则映像会被直接推出。
另外,.dmg 不仅可以随意放置其图标的布局,还可以设置背景图片,因此有些厂商能在 .dmg 上“玩出花”,给用户带来不一般的视觉感受,加深用户对自己产品的印象。
②使软件的分发更加可靠。前面提到,软件包被抽象为一个文件后,可以作为一个整体移动和复制,但软件包本身并不适合直接发布。
.dmg 文件属于磁盘映像,因此它在忠实记录了文件系统信息的同时,能很好地按原样存储数据,.app 软件包也不例外。因此,如果将软件包复制到 .dmg 内,就像把应用装进密闭的罐子一样,达到了软件分发的目的。
对于用户而言,在双击 .dmg 文件时,macOS 会检查校验和,只有不损坏、无篡改的 .dmg 才能被系统装载,在拷贝软件的过程中,.dmg 格式也确保了文件复制的不出错。因此,用户会有意识地关注下载的 .dmg 是否完整,从而让软件能被正确安装。
(当然,在某些情况下,即便用户不将软件安装到 Mac 上,仍可以通过双击 .dmg 内的应用程序试用软件)
③与 OS X 的文件系统相适应。在计算机的文件系统中,fork 指的是与文件系统对象相关的一组数据,OS X 有一个 resource fork 机制,继承自以往的 Mac OS(甚至保留到了现在的 macOS),它以特定的形式记录 OS X 应用程序的图标、本地化的字符串、菜单和对话框,还有应用程序代码等信息。但 resource fork 的数据在混合网络环境中不能传输,.dmg 格式则很好地解决了这一问题。
④延续以往安装软件的逻辑。.dmg 文件的图标里有一个磁盘,可以看得出它与磁盘相关,对软件包打包为 .dmg 的过程,和过去制作安装软盘/光盘的逻辑类似,而从 .dmg 安装应用程序、安装完毕后推出映像的逻辑,也与以往插入和弹出软盘/光盘的操作很像。
由于 .dmg 是 OS X 时代初期引入的,这意味着对那些曾经用过 Mac OS 的老 Macintosh 用户来说,安装软件不会感到陌生,对于初入 OS X 的用户来说,这种设计也会让他们感到新鲜。
再往后,.dmg 可以设计成只要将应用拖入“‘应用程序’文件夹”(这里加引号是因为它是“替身(Alias)”,也就是/Applications
的链接文件)就能安装应用,这种独特而高效的方式受到了许多 OS X 用户的青睐。
因此,将 .dmg 作为安装包也成为了一种传统,延续至今。
综上所述,.dmg 作为行业分发 macOS 软件的首选,背后并非没有道理。
此外补充几点——
①.dmg 不只用作安装包,还有其他的妙用,比如隐藏文件,整理资料,备份和恢复自己优盘和 SD 卡的数据,这些都可以利用 macOS 的磁盘工具来实现,在此就不作展开了。
如果你感兴趣,除磁盘工具外,也可以用第三方工具(比如 DMG Canvas 和 DropDMG)来制作属于自己的 .dmg 文件。
②并不是所有的 macOS 应用都会打包在 .dmg 文件里,除去 .dmg 之外,还有两种形式,一是 .pkg 的安装包,二是将 .app 应用直接打包为压缩文件。
前者是将一个软件所需的资源和安装脚本包装在一个 .pkg 文件内(有的厂商会将多个 .pkg 文件组成为 .mpkg 的安装包,当然 .mpkg 也是一个文件夹),用户双击打开 .pkg 或 .mpkg 安装包后,通过安装向导的提示逐步操作,直至完成安装。
(甚至 App Store 上架的 macOS 应用,也是以 .pkg 格式下载并安装到 Mac 上的,这可以从活动监视器取样进程发现)
而后者之所以也会采用,是因为用 zip、gzip 或 tar 打包现在的 macOS 应用的时候,不再出现以往 OS X 时代存在的问题,因此直接用压缩包封装也是完全可以的。