跳转至

教程 3 - 打包与分发

到目前为止,我们一直在“开发者模式”下运行应用程序。这可以让我们轻松地在本地运行应用程序,但我们真正想要的是能将我们的应用程序提供给其他人。

但是,我们不想教用户怎样安装 Python、创建虚拟环境、克隆 git 仓库和在开发者模式下运行 Briefcase。我们宁可只给他们一个安装程序,让应用程序能够正常运行。

Briefcase 可用于打包应用程序,以便以这种方式发布。

创建应用程序脚手架

由于这是我们第一次打包应用程序,我们需要创建一些配置文件和其他脚手架来支持打包过程。在 helloworld 目录中,运行:

(beeware-venv) $ briefcase create

[helloworld] 生成应用程序模板...
使用应用程序模板:https://github.com/beeware/briefcase-macOS-app-template.git,分支 v0.3.18
...

[helloworld] 安装支持包...
...

[helloworld] 安装应用程序代码...
正在安装 src/helloworld... 完成

[helloworld] 正在安装依赖项...
...

[helloworld] 正在安装应用程序资源...
...

[helloworld] 正在移除不需要的应用程序内容...
正在移除不需要的应用程序包内容... 完成

[helloworld] 已创建 build/helloworld/macos/app
(beeware-venv) $ briefcase create

[helloworld] 正在完成应用程序配置...
目标系统:ubuntu:jammy(基于 Debian 的供应商系统)
正在确定 glibc 版本... 完成
目标 glibc 版本:2.35
目标 Python 版本:3.10

[helloworld] 正在生成应用程序模板...
使用应用模板:https://github.com/beeware/briefcase-linux-AppImage-template.git,分支 v0.3.18
...

[helloworld] 安装支持包...
无需安装支持包。

[helloworld] 安装应用代码...
安装 src/helloworld... 完成

[helloworld] 安装依赖项...
...

[helloworld] 安装应用程序资源...
...

[helloworld] 移除不需要的应用程序内容...
移除不需要的应用程序包内容... 完成

[helloworld] 已创建 build/helloworld/linux/ubuntu/jammy

有关 Python 版本的错误

如果您收到类似如下的错误信息:

用于运行 Briefcase 的 Python 版本 (3.12) 不是系统 python3 (3.10)。

您将需要使用系统的 python3 重新创建您的虚拟环境。打包您的应用程序要求使用系统 Python。

(beeware-venv) C:\...>briefcase create

[helloworld] 生成应用程序模板...
使用应用程序模板:https://github.com/beeware/briefcase-windows-app-template.git,分支 v0.3.18
...

[helloworld] 安装支持包...
...

[helloworld] 安装应用程序代码...
安装 src/helloworld... 完成

[helloworld] 安装依赖项...
...

[helloworld] 安装应用程序资源...
...

[helloworld] 已创建 build\helloworld\windows\app

您可能刚刚在终端上看到了几页内容滑过......刚刚发生了什么?Briefcase 做了以下工作:

  1. 生成一个应用程序模板。除了实际应用程序的代码之外,构建本机安装程序还需要许多文件和配置。这些额外的脚手架对于同一平台上的每个应用程序几乎都是一样的,除了正在构建的实际应用程序的名称–因此,Briefcase 为其支持的每个平台提供了一个应用程序模板。这一步将推出模板,根据需要替换应用程序名称、捆绑 ID 和配置文件的其他属性,以支持正在构建的平台。如果对 Briefcase 提供的模板不满意,可以提供自己的模板。不过,在使用 Briefcase 的默认模板积累更多经验之前,您可能不想这样做。

  2. 下载并安装了一个支持包。Briefcase 所采用的打包方法被描述为 "最简单可行的方法"–它将一个完整、独立的 Python 解释器作为其构建的每个应用程序的一部分(Linux 本机系统包构建除外)。这在空间利用上略显不足–如果有 5 个应用程序打包到 Briefcase 中,就会有 5 份 Python 解释器副本。但是,这种方法保证了每个应用程序都是完全独立的,使用的 Python 版本是已知的可与应用程序一起工作的特定版本。同样,Briefcase 为每个平台提供了默认的支持包;如果需要,您可以提供自己的支持包,并将该包作为构建过程的一部分。如果您需要启用 Python 解释器中的特定选项,或者如果您想从标准库中剥离运行时不需要的模块,您可能需要这样做。公文包会维护支持包的本地缓存,因此一旦下载了特定的支持包,该缓存副本将在未来的构建中使用。如上所述,当 Briefcase 将应用程序打包为本地 Linux 系统包(Linux 的默认包格式)时,支持包不会随应用程序一起提供。相反,应用程序将使用目标 Linux 发行版提供的 Python。

  3. 它\ 安装应用程序的依赖项。您的应用程序可以指定运行时所需的任何第三方模块。这些模块将会被用 pip 安装到应用程序的安装程序中。

  4. 它\ 安装您的应用程序代码。您的应用程序将有自己的代码和资源(如运行时需要的图像);这些文件会被复制到安装程序中。

  5. 最后,它还会\ 添加安装程序本身所需的其他资源。这包括需要附加到最终应用程序的图标和启动画面等。

完成后,若查看项目中的 build 目录,您应能看到一个对应您平台的目录(macOS, linux, 或 windows),其中包含额外文件。这是您应用程序的平台特定打包配置。例如在 macOS 上,您的项目目录现在将包含:

helloworld/
└── build/
    └── helloworld/
 └── macos/

构建您的应用程序

现在可以编译应用程序了。此步骤将执行任何使应用程序在目标平台上可执行所必须的二进制编译。

(beeware-venv) $ briefcase build

[helloworld] 正在对应用程序进行临时签名...
...
正在对 build/helloworld/macos/app/Hello World.app 进行签名
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 00:07

[helloworld] 已构建 build/helloworld/macos/app/Hello World.app

在 macOS 上,build\ 命令不需要\ 编译\ 任何内容,但需要对二进制文件的内容进行(数字)签名,以便执行。这种签名是一种\ 临时 (ad hoc)\ 签名–它只能在\ 你的\ 机器上工作;如果你想将应用程序发布给其他人,就需要提供完整的签名。

(beeware-venv) $ briefcase build

[helloworld] 正在完成应用程序配置...
目标平台:ubuntu:jammy(基于 Debian 的供应商发行版)
正在确定 glibc 版本... 完成
目标 glibc 版本:2.35
目标 Python 版本:3.10

[helloworld] 正在构建应用程序...
构建引导二进制文件...
make: 进入目录 '/home/brutus/beeware-tutorial/helloworld/build/linux/ubuntu/jammy/bootstrap'
...
make: 离开目录 '/home/brutus/beeware-tutorial/helloworld/build/linux/ubuntu/jammy/bootstrap'
正在构建引导二进制文件... 完成
正在安装许可证... 完成
正在安装变更日志... 完成
正在安装手册页... 完成
正在更新文件权限... 完成
正在剥离二进制文件... 完成

[helloworld] 已构建 build/helloworld/linux/ubuntu/jammy/helloworld-0.0.1/usr/bin/helloworld

此步骤完成后,[build\ 文件夹将包含一个\helloworld-0.0.1\ 文件夹,其中包含一个 Linux/usr文件系统的镜像。这个文件系统镜像将包含一个\bin\ 文件夹,里面有一个\helloworld\ 二进制文件,以及支持二进制文件所需的\lib\ 和\share`\ 文件夹。

(beeware-venv) C:\...>briefcase build
正在设置占位应用程序的详细信息... 完成

[helloworld] 已构建 build\helloworld\windows\app\src\Hello World.exe

在 Windows 上,build 命令不需要\ 编译\ 任何东西,但它确实需要写入一些元数据,以便应用程序知道它的名称、版本等。

触发杀毒软件

由于这些元数据是在 create 命令中直接写入从模板推出的预编译二进制文件的,因此可能会触发机器上运行的杀毒软件,从而阻止元数据的写入。在这种情况下,请指示杀毒软件允许工具(名为 rcedit-x64.exe)运行,并重新运行上述命令。

运行应用程序

现在您可以使用 Briefcase 运行应用程序了:

(beeware-venv) $ briefcase run

[helloworld] 正在启动应用程序...
===========================================================================
正在配置隔离的 Python...
正在预初始化 Python 运行时...
PythonHome: /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python-stdlib
PYTHONPATH:
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python311.zip
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python-stdlib
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/support/python-stdlib/lib-dynload
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/app_packages
- /Users/brutus/beeware-tutorial/helloworld/macOS/app/Hello World/Hello World.app/Contents/Resources/app
配置 argc/argv...
初始化 Python 运行时...
正在安装 Python NSLog 处理程序...
正在运行应用程序模块:helloworld
---------------------------------------------------------------------------
(beeware-venv) $ briefcase run

[helloworld] 正在完成应用程序配置...
目标环境:ubuntu:jammy(基于 Debian 的供应商发行版)
正在确定 glibc 版本... 完成
目标 glibc 版本:2.35
目标 Python 版本:3.10

[helloworld] 启动应用程序...
===========================================================================
安装路径:/home/brutus/beeware-tutorial/helloworld/build/helloworld/linux/ubuntu/jammy/helloworld-0.0.1/usr
预初始化 Python 运行时...
PYTHONPATH:
- /usr/lib/python3.10
- /usr/lib/python3.10/lib-dynload
- /home/brutus/beeware-tutorial/helloworld/build/helloworld/linux/ubuntu/jammy/helloworld-0.0.1/usr/lib/helloworld/app
- /home/brutus/beeware-tutorial/helloworld/build/helloworld/linux/ubuntu/jammy/helloworld-0.0.1/usr/lib/helloworld/app_packages
配置 argc/argv...
初始化 Python 运行时...
运行应用程序模块:helloworld
---------------------------------------------------------------------------
(beeware-venv) C:\...>briefcase run

[helloworld] 正在启动应用程序...

===========================================================================
日志开始时间:2023-04-23 04:47:45Z
正在预初始化 Python 运行时...
PythonHome: C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src
PYTHONPATH:
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src\python39.zip
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src\app_packages
- C:\Users\brutus\beeware-tutorial\helloworld\windows\app\Hello World\src\app
配置 argc/argv...
初始化 Python 运行时...
运行 app 模块:helloworld
---------------------------------------------------------------------------

这将使用 build 命令的输出开始运行原生应用程序。

你可能会注意到应用程序运行时的外观有一些细微差别。例如,操作系统显示的图标和名称可能与在开发者模式下运行时略有不同。这也是因为您使用的是打包的应用程序,而不仅仅是运行 Python 代码。从操作系统的角度来看,您现在运行的是“一个应用程序”,而不是“一个 Python 程序"”,这也反映在应用程序的显示方式上。

在继续之前,关闭应用程序。和之前的教程步骤一样,您可以使用应用程序窗口上的关闭按钮、从应用程序的菜单栏选择关闭/退出、或在您运行 briefcase dev 的命令行窗口中按 Ctrl+C 以关闭应用程序。

创建安装程序

现在,您可以使用 package 命令打包应用程序,以便发布。打包命令会执行将脚手架项目转换为最终可发布产品所需的编译工作。根据平台的不同,这可能涉及编译安装程序、执行代码签名或执行其他发布前任务。

(beeware-venv) $ briefcase package --adhoc-sign

[helloworld] 正在对应用程序进行签名...

*************************************************************************
** 警告:使用临时身份进行签名 **
*************************************************************************

 此应用正在使用临时身份进行签名。生成的
    应用将在本机上运行,但无法在其他人的
    计算机上运行。

 若要生成可分发给他人的应用,您必须
    从 Apple 获取应用分发证书,并在
    运行 'briefcase package' 时选择与该证书关联的
    开发者身份。

*************************************************************************

正在使用临时身份证书对应用程序进行签名...
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 00:07

[helloworld] 正在构建 DMG...
正在构建 dist/Hello World-0.0.1.dmg

[helloworld] 已打包 dist/Hello World-0.0.1.dmg

dist 文件夹将包含一个名为 Hello World-0.0.1.dmg 的文件。如果在 Finder 中找到该文件,并双击其图标,就会加载 DMG,从而获得 Hello World 应用程序的副本,并链接到 Applications 文件夹以方便安装。将应用程序文件拖入 Applications,就安装好了应用程序。将 DMG 文件发送给朋友,他们应该也能完成同样的操作。

在本例中,我们使用了 --adhoc-sign 选项–也就是说,我们使用 ad hoc 凭据(仅在你的机器上有效的临时凭据)来签署我们的应用程序。我们这样做是为了让教程简单明了。设置代码签名身份有点麻烦,而且只有当你打算将应用程序发布给他人时\ \ 需要。如果我们要发布一个真正的应用程序供他人使用,我们就需要指定真实的凭据。

当你准备发布一个真正的应用程序时,请查看公文包操作指南中的 设置 macOS 代码签名身份

软件包步骤的输出会因 Linux 发行版的不同而略有不同。如果你使用的是 Debian 衍生发行版,你会看到:

(beeware-venv) $ briefcase package

[helloworld] 正在完成应用程序配置...
目标系统:ubuntu:jammy(基于 Debian 的供应商发行版)
正在确定 glibc 版本... 完成
目标 glibc 版本:2.35
目标 Python 版本:3.10

[helloworld] 正在构建 .deb 包...
写入 Debian 包控制文件... 完成

dpkg-deb: 正在构建包 'helloworld' 到 'helloworld-0.0.1.deb'。
构建 Debian 包... 完成

[helloworld] 已打包 dist/helloworld_0.0.1-1~ubuntu-jammy_amd64.deb

dist 文件夹将包含生成的 .deb 文件。

如果你使用的是基于 RHEL 的发行版,你就会看到:

(beeware-venv) $ briefcase package

[helloworld] 正在完成应用程序配置...
目标平台:fedora:40(供应商基础版 rhel)
确定 glibc 版本... 完成
目标 glibc 2.39
目标 Python 3.12

[helloworld] 构建 .rpm 包...
生成 rpmbuild 布局... 完成

写入 RPM 规范文件... 完成

构建源代码归档... 完成

执行(%prep):/bin/sh -e /var/tmp/rpm-tmp.Kav9H7
+ umask 022
...
+ exit 0
构建 RPM 包... 完成

[helloworld] 打包 dist/helloworld-0.0.1-1.fc40.x86_64.rpm

dist 文件夹将包含生成的 .rpm 文件。

如果你使用的是基于 Arch 的发行版,你就会看到:

(beeware-venv) $ briefcase package

[helloworld] 正在完成应用程序配置...
目标架构:arch:20240101(供应商基础架构)
正在确定 glibc 版本... 完成
目标 glibc 版本为 2.38
目标 Python 3.12

[helloworld] 构建 .pkg.tar.zst 包...
...
构建 Arch 包... 完成

[helloworld] 已打包 dist/helloworld-0.0.1-1-x86_64.pkg.tar.zst

dist 文件夹将包含生成的 .pkg.tar.zst 文件。

目前不支持其他 Linux 发行版的打包。

如果你想为你正在使用的 Linux 发行版之外的其他发行版构建软件包,Briefcase 也能提供帮助,但你需要安装 Docker。

Docker Engine 的官方安装程序适用于一系列 Unix 发行版。请按照您所在平台的说明进行操作;不过,请确保不要在 rootless 模式下安装 Docker。

安装好 Docker 后,你就可以启动 Linux 容器了,例如:

$ docker run --rm -it ubuntu:22.04

将显示 Ubuntu 22.04 Docker 容器中的 Unix 提示符(类似于 root@84444e31cff9:/#)。键入 Ctrl-D 退出 Docker 并返回本地 shell。

一旦安装了 Docker,只要将 Docker 镜像作为参数传递,就可以使用 Briefcase 为 Briefcase 支持的任何 Linux 发行版构建软件包。例如,要为 Ubuntu 22.04 (Jammy) 构建一个 DEB 包,无论你使用的是哪种操作系统,你都可以运行:

$ briefcase package --target ubuntu:jammy

这将下载所选操作系统的 Docker 镜像,创建一个能够运行 Briefcase 构建的容器,并在镜像中构建应用程序软件包。完成后,dist 文件夹将包含目标 Linux 发行版的软件包。

(beeware-venv) C:\...>briefcase package

*************************************************************************
** 警告:未提供签名身份 **
*************************************************************************

    Briefcase 不会对应用程序进行签名。若要提供签名身份,
    请使用 `--identity` 选项;或者,若要明确禁用签名,
    请使用 `--adhoc-sign`。

*************************************************************************

[helloworld] 正在构建 MSI...
编译应用程序清单...
编译中... 完成

编译应用程序安装程序...
helloworld.wxs
helloworld-manifest.wxs
编译中... 完成

链接应用程序安装程序...
链接中... 完成

[helloworld] 已打包 dist\Hello_World-0.0.1.msi

在本例中,我们没有签署我们的应用程序。因此,当您使用安装程序时,您将收到系统警告,该应用程序来自未知开发人员。我们这样做是为了保持教程的简单性。设置代码签名身份比较复杂,只有当您打算将您的应用程序分发给其他人时,它们才需要。如果我们发布一个真实的应用程序供其他人使用,我们需要指定一个真实的签名身份;当该签名的应用程序安装时,系统将通知用户该应用程序来自与证书关联的已知身份。

当您准备发布实际应用程序时,请查看公文包操作指南中的 设置 Windows 代码签名身份

此步骤完成后,dist 文件夹中将包含一个名为 `Hello_World-0.0.1.msi`` 的文件。如果双击运行该安装程序,就会进入熟悉的 Windows 安装过程。安装完成后,开始菜单中将出现 "Hello World "条目。

下一步

现在,我们已将应用程序打包发布到桌面平台上。但是,当我们需要更新应用程序中的代码时该怎么办?我们如何将这些更新添加到打包的应用程序中?请参阅 教程 4 了解详情…