# 安装包的组成

前面的比喻中提到了包裹中都有什么。在Mac系统中，安装包主要包含三个部分：安装文件、脚本和配置信息等资源。配置信息就如同货运单，而脚本就如同必要的填充物和货运单的注意事项。下面我们对着三个部分一一介绍。&#x20;

**负载文件**：就像包裹中的货物，在英文中一般被称作**payload**，也就是前面提到的负载的概念。后面我们一般使用“负载”或者“安装文件”。所需安装的文件包括需要被复制到目标卷宗中的文件本身及其属性。其中文件本身，可以是一个普通文件，也可能是软连接和设备文件等等。

**文件属性**可能包括：比如文件的UNIX属性：生成、被打开和修改日期，文件所属用户和群组，以及用户和组的权限；也有可能包含访问控制列表（ACLs）信息等；还有文件的扩展属性； 对于Mac的HFS+或APFS 等文件系统，还可能包含文件相关的元数据（meta data） 等等。对于一个应用程序来说，文件属性是特别重要的信息，换句话说，丢失必要的属性或者错误的文件属性会导致应用无法正常运行。

**脚本**：在这里我们简单地定义下脚本，它是一系列命令的有机组合，用于完成一个或多个任务，并通过返回值或标准输出来反馈运行的结果。在安装包中，有两种基本脚本：预安装脚本和后安装脚本。这两种脚本担负着各自不同的任务，并对安装结果起到至关重要的作用，如果它们任何一个返回错误，会导致安装或被禁止或失败，只有脚本都运行成功，安装才可能成功。 脚本返回值0代表成功，任何其他值都是失败。

**预安装脚本**：顾名思义，就是安装前运行的脚本，其实它是在安装器执行复制文件操作之前被首先运行的脚本。有的安装包需要特殊前提条件，比如：只能安装在Mac笔记本或者只能是某一些特定版本的硬件，或许判断是否是公司自己的设备，或者是EFI必须存在且完整，或者必须输入正确的密码或注册码等等。这些条件可能对于软件是至关重要的目标电脑环境因素，也可能是管理员或者公司规定等要求的人为因素。如果预安装失败，安装器不会执行后面的复制文件操作而直接跳转到摘要这一步。

**后安装脚本**：这个脚本实在安装后运行的脚本。一般用来做善后工作，比如删除临时文件，确保文件属性正确，设置并运行服务和更新日志等等。

**配置信息**：主要是一些关于安装包的协议，版本，图片，支持语言等有助于安装的文件，如果支持多语言本地化，那么会有本地语言资源。

以后会遇到的主要是两种安装包。

* **组件包：** 组件包（component package）是一种安装包，它完成比较单一的任务，比如将应用软件或者一个程序包（bundle）等复制到目标系统目录中。这种包不能用于App商店的发布软件，也不支持丰富的界面定制。组件包与下面的所介绍的产品包相对而言实现最基本的安装功能。
* **产品包**（档）： 一个软件产品可能会包括多个组成部分，每个单独组成部分可以用组件包打包，然后按照先后顺序等再合并为一个完整的软件安装包。\
  \
  产品包英文是Production Package（有时也叫 Production Archive ）或者叫分发包（Distribution Package）。它也是.pkg文件后缀，同样用安装器安装，且可用于在应用商店上发布。 \
  \
  产品包是将一个最终产品中的各个组成部分的组件包组装成一个完整产品的具有有效签名的安装包，可以使用macOS的内置命令productbuild制作。\
  \
  一个产品包含多个组成部分完整的产品，由多个小组或者团队开发，比如主程序、辅助资源、产品注册管理等等，而每个团队开发完自己的程序后，将其打包为一个一个的组件安装包，每个组件可以独立地安装自己所必须的环境。在产品“总装”中，根据每个组件的顺序依次安装。用户还可以选择安装一部分组件。可以看出，产品包里面会包含多个组件包pkg文件。\
  \
  比较典型的产品包就是微软的Office套件了，它包括了Word、Excel、PowerPoint和Outlook等等组件，而且他们都有公共部分，比如字体等组件，用户也可以根据自己的需要只安装其中的一部分，比如不安装Outlook或者AutoUpdate组件等等。

在实际工作中，还有一种叫做“**复合包**”的，也是常见的一种安装包的形式，它是为了一种目的将多个（或者一个）安装包的组合为一个安装包。它可以是产品包，也可以不是。一般使用特殊的技术不是使用**productbuild**命令制作的。
