Flutter构建跨平台桌面应用安装包:MacOS、Windows和Linux打包完全指南

7,584 阅读12分钟

前言

Flutter 是一个跨平台的应用开发框架,目前已稳定支持 Android、iOS、Macos、Windows、Linux、Web 六个平台。之前主要用其来开发跨平台的移动应用,对于桌面应用和 Web 都只是写过一些实验性的代码,最近因为需要写一些桌面应用的小工具所以用到了 Flutter 来进行跨平台的桌面应用开发,这就面临了开发完成后对桌面应用的打包分发。

在本文中,将详细介绍如何将 Flutter 开发的桌面应用打包成对应平台的可执行程序包,以便于分发给不同平台的用户方便其安装使用。

因为讲解了三个平台的打包方式,且为了让大家更好了解打包的细节,本篇的图片比较多导致篇幅比较长情耐心阅读,或你只对某一个平台的打包感兴趣则可直接跳到对应平台的打包介绍。

Macos 打包

Macos 打包需要在 Macos 系统上进行

编译

首先需要将 Flutter 的应用程序使用命令编译成 Macos 的 app ,执行如下命令进行打包:

flutter build macos --release

打包完成后会在 build/macos/Build/Products/Release 目录下生成对应的 .app文件,不如我这项目名为 flutter_build_demo 则会在该目录下生成 flutter_build_demo.app ,这就是我们最终需要的编译产物,如下图所示: image.png 实际上直接双击这个 .app就能直接打开我们的应用,我们可以直接将该 app 文件分发给用户进行使用,但是我们一般在网上下载的 Macos 的应用程序包都是 .dmg结尾的,打开基本上都是一个窗口,显示将对应的 app 程序拖入 Applications 中,如下图这样: image.png 那我们能不能将 flutter 打包的 app 也制作成这样的 .dmg文件呢?答案是肯定的,下面就详细介绍如何制作。

准备

准备好需要的文件:

  • 打包出来的 app,即 flutter_build_demo.app
  • 背景图,如下:
dmg_bg3.png

创建磁盘映像

需要的文件准备好后,下面打开磁盘工具: image.png 然后选择顶部菜单文件->新建映像->空白映像... image.png 填写名称的磁盘大小,比如这里我填写 flutter_build_demo,如下图:

image.png

注意大小必须要比上面 flutter 打包出来的 app 的文件大小要大,不然放不进去,这里可以先设置大一点,后面会对其进行压缩,然后点击存储,就会创建磁盘映像,稍等一会儿就会在你指定的目录下生成一个 dmg 文件。 点击打开创建好的 dmg 文件会发现是一个空白窗口:

image.png

如果你开启了显示隐藏文件夹,则里面会有一个 .fseventsd的文件夹

如果你打开的窗口不是上面那样,而是这样:

image.png

左边有目录上边还有操作按钮,这是因为没有隐藏工具栏的关系,只需点击`显示->隐藏边栏`即可,且并不会影响其他文件夹的状态

image.png

链接 Application

接下来通过终端命令在文件里链接一个应用程序的文件夹,命令如下:

cd /Volumes/flutter_build_demo
ln -s /Applications Applications

这样文件夹里就有了一个 Applications 的文件夹了,如下图:

image.png

放入文件 & 设置背景

再把我们准备好的 app 和背景图片拖入其中:

image.png

再设置窗口的背景图片,在文件夹空白处点击右键选择查看显示选项,在弹出的窗口中最下面的背景选择图片,然后将我们放进去的图片拖入到右侧的方框中,如下: b1.gif 这样窗口就会显示背景图片,然后调整图标的大小和位置以及窗口的大小,让窗口刚好背景图片大小,如下: b21.gif 调整完后看着好看多了,但是还有一个图片在上面很影响美观,我们可通过终端将图片隐藏,命令如下:

chflags hidden dmg_bg3.png

这里 dmg_bg3.png是我的背景图片名称,将其换成你的即可,再来看下效果: image.png 这样是不是就跟上面网易云音乐的效果差不多了。

注意,如果你或者用户电脑开启了显示隐藏文件,那这里还是能看到.fseventsd文件夹以及我们刚才隐藏的背景图片,如下: image.png 此时可以先将窗口拉大一点,把隐藏文件拖到边上,然后在将窗口大小调整回来,如下所示: b3.gif 这样即使用户开启了显示隐藏文件的功能也看不到多余的文件

转换压缩映像

最后就是对磁盘映像进行转换压缩,先在文件夹中推出刚才打开的 flutter_buid_demo 磁盘映像(如果之前执行命令的终端还开着记得退出映像目录或者关闭终端,否则无法推出),然后再次打开磁盘工具,选择映像->转换

iShot\_2023-04-12\_16.13.49.png

再选择之前创建的 .dmg 文件:

iShot\_2023-04-12\_16.14.50.png

重新命名一下,点击转换就生成了最终打包的 dmg 安装包了,双击打开看看效果: image.png

三方打包工具

除了上面介绍的手动打包外,如果嫌流程太繁琐也可以使用三方打包工具,这里推荐两个:DMG Canvas、DropDMG,下面简单介绍一下两个工具的使用

DMG Canvas

下载安装后打开如下界面: image.png 在这个界面可点击上面的加号添加应用程序文件、背景图片、Applications文件夹、文字,在右边可调整图标大小、窗口大小等,设置完后如图 b4.gif 最后点击右上角锤子按钮就可生成 dmg 安装包

DropDMG

DropDMG 安装打开后是如下界面:

image.png

在此界面我们可以直接拖入要打包的文件生成对应的 dmg 安装包,也可以点击设置界面进行布局相关的设置,如下图:

image.png

默认是一个未命名的配置,我们可以在此基础上进行配置或者新建一个配置,选择格式、加密方式等; 在布局中我们可对安装界面进行配置比如背景图片、图片位置、图标大小、文字等,如下所示:

b5.gif

然后回到配置选择对应的布局,然后回到最开始的界面选择对应的配置再拖入应用程序即可生成 dmg 安装包。

image.png

Windows 打包

编译

首先还是用 flutter 命令将项目编程成 Windows 的可执行程序,命令如下:

flutter build windows --release

生成的目录在 build/windows/runner/Release下: image.png 包含可执行的 exe 文件、dll 文件(可能有多个)以及 data 数据文件夹,此时双击 exe 文件可正常打开应用,我们可将该文件夹内的所有内容打包发给用户使用,也可以使用下面的介绍将内容打包成一个单独的 exe 安装文件

打包 exe

打包使用到的工具是 Inno ,点击可进行下载安装,安装后打开 Inno 界面:

iShot\_2023-04-12\_18.04.26.png

选择 Create a new script file using tne Script Wizard后点击 OK,下面以一个 gif 简单展示一下软件的使用: b7.gif

下面对一些关键步骤进行详细说明

  • 填写应用名称和版本:

image.png

  • 添加应用可执行文件、dll文件、data文件夹:

iShot\_2023-04-12\_18.24.17.png

Application main executable file选择程序的可执行文件,也就是前面编译生产的 exe 文件,然后再在下面点击 Add file(s)添加应用的 dll 文件,也就是上面编译生成的 Release 目录下的所有 dll 文件,这里 demo 只有一个如果有多个的话需要都添加进来。

点击 Add folder添加 data 文件,选择编译生成的 data 文件夹,在弹出的对话框中选择

iShot\_2023-04-12\_18.22.39.png

image.png

然后选中添加的 data 文件夹,选择右边的 Edit按钮,在弹出的对话框中的 Destination subfolder中输入 data(否则可能会出错),如下图:

iShot\_2023-04-12\_18.23.41.png

  • 选择输出目录和输出文件名称、图标、密码:

image.png

最后配置完成后会询问是否保存配置文件,建议进行保存,后面可直接根据配置文件打包而无需重复进行上面的配置。生成的配置文件和打包界面如下: image.png 打包完成后会在指定的目录生成一个 exe 的安装包,双击即可像我们安装普通程序一样点击下一步、下一步进行安装。 看一下安装预览:

b6.gif

Linux 打包

编译

首先还是用 flutter 命令将项目编程成 Linux 的可执行程序,命令如下:

flutter build linux --release

生成的目录在 build/linux/x86/release/bundle,如下图:

image.png

直接双击或者终端运行生成的可执行文件即可打开应用程序,我们可以直接将bundle目录打成压缩包进行分发,也可以选择下面介绍的将其打包成 deb 文件进行分发。

打包 deb

deb 是 Debian Linux 操作系统中的一种软件包格式,用于安装和管理软件程序。也被许多基于 Debian 的 Linux发行版所使用,如 Ubuntu、Linux Mint 等。

deb 包通常包含一个或多个二进制文件、配置文件、库文件、文档以及软件依赖关系等。它可以通过 dpkg 工具进行安装、卸载和更新。dpkg 是 Debian Linux 系统中的包管理工具,用于管理 deb 软件包。

deb 包通常具有一个规范的文件结构,其中包括控制文件、数据文件和安装脚本等。控制文件包含了软件包的元数据信息,例如软件名称、版本、作者、描述、依赖关系等。数据文件包含软件程序的二进制文件、配置文件、库文件、文档等。安装脚本包含软件程序的安装、卸载、配置和升级等操作指令。 下面我们就使用 dpkg 命令将 Flutter 编译好的文件打包成 deb 包。

首先我们新建一个文件夹作为我们打包的文件夹,文件夹名可以随便取,比如就叫 package ,然后在文件夹下在创建一个文件夹用于放打包的文件,比如就叫项目名 flutter_build_demo ,完整结构如下:

package/
└── flutter_build_demo
    ├── DEBIAN
    │   ├── control
    │   ├── postinst
    │   └── postrm
    ├── opt
    │   └── flutter_build_demo
    │       ├── data
    │       ├── flutter_build_demo
    │       └── lib
    └── usr
        └── share
            ├── applications
            │   └── flutter_build_demo.desktop
            └── icons
                └── flutter_build_demo.png

其中 DEBIAN是固定目录,下面至少包含 control文件,还可以有 preinst(preinstallation)、postinst(postinstallation)、prerm(preremove)、postrm(postremove)、copyright (版权)、changlog (修订记录)和 conffiles,具体作用如下:

  • control:描述软件包的名称(Package),版本(Version),描述(Description)等,是 deb 包必须具备的描述性文件,以便于软件的安装管理和索引
  • preinst:解包前运行的脚本,需要可执行权限
  • postinst:解包完成并将目录文件拷贝到系统后,所需要执行的配置工作,即安装时执行,需要可执行权限
  • prerm:文软件卸载前需要执行的脚本,需要可执行权限
  • postrm:软件卸载后需要执行的脚本,通常利用该脚本来清理环境,需要可执行权限

这里我们只放了 postinstpostrm 两个文件作为示例。

opt、usr 目录下放的文件则会在安装的时候将对应的文件复制到系统的对应文件夹里,其中 opt 中放的应用的可执行程序、数据、以及依赖包,即安装时会将其复制到系统的 /opt/flutter_build_demo 目录下;

usr 下放的是桌面应用的配置文件和图标文件,将会分别复制到系统的 /usr/share/applications/sur/share/icons下,这样就能在 Linux 系统的应用中看到我们安装的应用了。 下面看一下各个文件具体的内容:

control:

Package: flutter-build-demo
Version: 1.0.0
Section: free
Priority: optional
Essential: no
Architecture: all
Maintainer: loongwind <loongwind@gmail.com>
Provides: flutter_build_demo
Description: flutter build demo

主要填写应用的名称、版本、描述、作者等信息, Architecture应用支持的架构,如果支持所有架构就填 all,支持指定架构就填指定的架构名称,比如支持 arm 架构就填 armhf。

postinst:

#!/bin/bash

if [ "$1" = "upgrade" ] || [ "$1" = "install" ];then
        echo "flutter build demo installing"
fi

就简单输出了个提示,可根据应用实际情况进行相关处理。

postrm:

#!/bin/bash

if [ "$1" = "upgrade" ] ; then
        echo "upgrade"
elif [ "$1" = "remove" ] || [ "$1" = "purge" ] ; then
        echo "remove"

fi

也只是进行了简单输出

flutter_build_demo.desktop

[Desktop Entry]
Name=Flutter Build Demo
Name[zh_CN]=打包示例
Comment=Flutter Build Demo application
Exec=/opt/flutter_build_demo/flutter_build_demo
Icon=/usr/share/icons/flutter_build_demo.png
Terminal=false
Type=Application
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;
StartupNotify=true

填写应用的名称、描述等信息,最重要的是 Exec字段,是应用的可执行文件的路径,也就是我们安装时拷贝到系统 /opt下面的可执行文件路径,Icon则是指定应用图标

完成上面所有文件的准备工作后,我们在终端中进入 package 目录就可以使用 dpkg 命令进行打包了,打包命令如下:

sudo dpkg-deb -b flutter_build_demo flutter_build_demo_1.0.0.deb

执行完成后就会在当前目录生成 flutter_build_demo_1.0.0.deb的文件,后面就可以使用 dpkg -i 命令对这个 deb 包进行安装。

后续如果应用更新的话只需要将编译生成的文件拷贝到这个打包目录的 opt/flutter_build_demo 目录下修改版本信息再重新打包即可,如果嫌每次都要手动拷贝麻烦也可以写个脚本来处理,比如 package.sh如下:

#!/bin/bash

# flutter 编译
flutter build linux --release
# 拷贝编译后的文件到打包目录
cp -r /build/linux/x64/release/bundle/* pacakge/flutter_build_demo/opt/flutter_build_demo/
# 打包
sudo dpkg-deb -b pacakge/flutter_build_demo pacakge/flutter_build_demo_1.0.0.deb

这样就实现了一键编译、拷贝、打包

安装

deb 文件打包好了,下面就来看看如何进行安装,安装还是使用 dpkg 命令,如下:

sudo dpkg -i flutter_build_demo_1.0.0.deb

执行完成后会在应用中生成一个 Flutter Build Demo 的应用,如下图:

image.png

点击即可打开应用

最后

本文篇幅比较长,详细讲解了如何将使用 Flutter 编写的桌面应用程序分别打包成 Macos 使用的 dmg 安装包、Windows 的 exe 安装包以及 Linux 使用的 deb 安装包方便用户在不同平台进行安装使用,如果你有打包 Flutter 桌面应用的需求的话希望对你有所帮助。

本文正在参加「金石计划」