Dart 增加交叉编译支持
dart compile
内容
本指南介绍如何使用 dart compile
命令将 Dart 程序编译到目标平台。
概述
使用 dart compile
命令将 Dart 程序编译到 目标平台。 输出 (您可以使用子命令指定) 可以包含 Dart 运行时 或是一个 模块 (也称为 快照).
💡 提示
要了解有关此命令和其他 dart
命令的更多信息,请查看 Dart 命令行工具页面。
以下是一个使用 exe
子命令生成自包含可执行文件 (myapp.exe
) 的示例:
dart compile exe bin/myapp.dart
Generated: /Users/me/myapp/bin/myapp.exe
content_copy
下一个示例使用 aot-snapshot
子命令生成预先 (AOT) 编译的模块 (myapp.aot
)。 然后,它使用 dartaotruntime
命令 (提供 Dart 运行时) 运行 AOT 模块:
dart compile aot-snapshot bin/myapp.dart
Generated: /Users/me/myapp/bin/myapp.aot
dartaotruntime bin/myapp.aot
content_copy
要指定输出文件的路径,请使用 -o
或 --output
选项:
dart compile exe bin/myapp.dart -o bin/runme
content_copy
有关更多选项和用法信息,请运行 dart compile [<subcommand>] --help
:
dart compile exe --help
content_copy
dart compile
命令取代了 dart2native
、dart2aot
和 dart2js
命令。
ℹ️ 注意
您无需在运行 Dart 程序之前对其进行编译。 相反,您可以使用 dart run
命令,该命令使用 Dart VM 的 JIT(即时)编译器,此功能在开发期间尤其有用。 有关 AOT 和 JIT 编译的更多信息,请参见 平台讨论。
请参阅 native_app 示例,以获取使用 dart compile
编译本机应用程序的简单示例,以及运行该应用程序的示例。
子命令
下表显示了 dart compile
的子命令。
子命令 | 输出 | 更多信息
---|---|---
exe
| 自包含可执行文件 | 一个独立的、特定于体系结构的可执行文件,其中包含编译为机器码的源代码和一个小的 Dart 运行时。 了解更多.
aot-snapshot
| AOT 模块 | 一个特定于体系结构的文件,其中包含编译为机器码的源代码,但没有 Dart 运行时。 了解更多.
jit-snapshot
| JIT 模块 | 一个特定于体系结构的文件,其中包含所有源代码的中间表示形式,以及程序训练运行期间执行的源代码的优化表示形式。 如果训练数据良好,则 JIT 编译的代码可能比 AOT 代码具有更快的峰值性能。 了解更多.
kernel
| Kernel 模块 | 源代码的可移植的 中间表示形式。 了解更多.
js
| JavaScript | 一个可部署的 JavaScript 文件,从源代码编译而来。 了解更多.
wasm
| WebAssembly | 一种用于基于堆栈的虚拟机的可移植二进制指令格式。 目前正在开发中。 了解更多.
输出类型
以下各节详细介绍了 dart compile
可以生成的每种类型的输出。
自包含可执行文件 (exe)
exe
子命令生成适用于 Windows、macOS 或 Linux 的独立可执行文件。 独立可执行文件 是从指定的 Dart 文件及其依赖项编译而来的本机机器码,以及处理类型检查和垃圾回收的小型 Dart 运行时。
您可以像分发任何其他可执行文件一样分发和运行输出文件。
编译您的应用并设置输出文件:
dart compile exe bin/myapp.dart -o /tmp/myapp
content_copy
成功后,此命令将输出以下内容:
Generated: /tmp/myapp
content_copy
从 /tmp
目录运行编译后的应用:
./tmp/myapp
content_copy
交叉编译
# 在以下 64 位主机操作系统上支持交叉编译到 Linux x64 和 ARM64:macOS、Windows 和 Linux。
要使用交叉编译,请包括以下标志:
--target-os=linux
:已编译的可执行文件的目标操作系统。 目前支持 Linux 操作系统。--target-arch=value
:已编译的可执行文件的目标架构。 此标志的值可以是arm64
(64 位 ARM 处理器) 或x64
(64 位处理器)。
以下命令演示了如何为 64 位 Linux 系统交叉编译独立可执行文件:
dart compile exe \
--target-os=linux \
--target-arch=x64 \
hello.dart
content_copy
在内部,此命令会下载其他 Dart SDK 二进制文件并将其缓存在 ~/.dart
目录中。 以下是包含在命令中的 --verbose
标志的示例输出:
Downloading https://storage.googleapis.com/dart-archive/channels/dev/signed/hash/...4864.../sdk/gen_snapshot_macos_arm64_linux_x64...
Downloading https://storage.googleapis.com/dart-archive/channels/dev/raw/hash/...64e44.../sdk/dartaotruntime_linux_x64...
Specializing Platform getters for target OS linux.
Generating AOT kernel dill.
Compiling /tmp/hello.dart to /tmp/hello.exe using format Kind.exe:
Generating AOT snapshot. path/to/dir/.dart/3.8.0-265.0.dev/gen_snapshot_macos_arm64_linux_x64 []
Generating executable.
Marking binary executable.
Generated: /tmp/hello.exe
content_copy
签名
使用 dart compile exe
创建的可执行文件支持在 macOS 和 Windows 上签名。
要了解有关特定于平台的代码签名的更多信息,请参阅这些操作系统的平台文档:
- Windows
SignTool.exe
文档 - Apple 代码签名指南
已知限制
exe
子命令具有以下已知限制:
- 不支持
dart:mirrors
和dart:developer
。 有关您可以使用的核心库的完整列表,请参见 多平台 和 本机平台 库表。 - 支持交叉编译,但目标仅限于 Linux。 有关更多信息,请参见 交叉编译。
AOT 模块 (aot-snapshot)
使用 AOT 模块可以减少分发多个命令行应用程序时的磁盘空间需求。 aot-snapshot
子命令会生成一个特定于您编译应用程序的当前体系结构的输出文件。
例如,如果您使用 macOS 创建 .aot
文件,则该文件只能在 macOS 上运行。 Dart 在 Windows、macOS 和 Linux 上支持 AOT 模块。
编译您的应用并设置输出文件:
dart compile aot-snapshot bin/myapp.dart
content_copy
成功后,此命令将输出以下内容:
Generated: /Users/me/myapp/bin/myapp.aot
content_copy
从 /bin
目录运行编译后的应用:
dartaotruntime bin/myapp.aot
content_copy
要了解更多信息,请参见 dartaotruntime
文档。
交叉编译
aot-snapshot
子命令的交叉编译支持与 exe
子命令的交叉编译支持相同。 有关更多信息,请参见 自包含可执行文件 (exe)。
已知限制
aot-snapshot
子命令具有与 exe
子命令相同的限制。 有关更多信息,请参见 自包含可执行文件 (exe)
JIT 模块 (jit-snapshot)
# JIT 模块包括在程序的训练运行期间生成的所有已解析类和已编译代码。
dart compile jit-snapshot bin/myapp.dart
Compiling bin/myapp.dart to jit-snapshot file bin/myapp.jit.
Hello world!
dart run bin/myapp.jit
Hello world!
content_copy 从应用程序模块运行时,Dart VM 不需要解析或编译在训练运行期间已经使用的类和函数,因此 VM 可以更快地开始运行用户代码。
这些模块是特定于体系结构的,这与使用 kernel
子命令 生成的模块不同。
可移植模块 (kernel)
使用 kernel
子命令将应用程序打包到可以在所有操作系统和 CPU 架构上运行的单个可移植文件中。 kernel 模块包含 Dart 程序的抽象语法树的二进制形式 (Kernel AST)。
以下是创建和运行 kernel 模块的示例:
dart compile kernel bin/myapp.dart
Compiling bin/myapp.dart to kernel file bin/myapp.dill.
dart run bin/myapp.dill
content_copy
尽管与 Dart 代码相比,kernel 模块的启动时间有所减少,但与特定于体系结构的 AOT 输出格式相比,它们的启动速度可能会慢得多。
JavaScript (js)
js
子命令将 Dart 代码编译为可部署的 JavaScript。
ℹ️ 注意
使用 webdev
工具 而不是运行 Dart 到 JavaScript 编译器。
选项
#
dart compile js
命令有多个选项可以自定义 javascript 代码编译。
基本选项
#
常用选项包括:
-o <file>
或 --output=<file>
将输出生成到 `<file>` 中。 如果未指定,则输出将进入名为 `out.js` 的文件。
--enable-asserts
启用断言检查。
-O{0|1|2|3|4}
控制优化以减少文件大小并提高代码性能。 要了解有关这些优化的更多信息,请运行 `dart compile js -hv`。
-O0
:禁用许多优化。-O1
:启用默认优化。-O2
:启用-O1
优化,以及尊重语言语义且对所有程序安全的其他优化(例如,最小化)。 ℹ️ 注意 使用-O2
时,类型字符串表示不再与使用开发 JavaScript 编译器编译时 Dart VM 中的类型字符串表示相同。-O3
:启用-O2
优化,并省略隐式类型检查。 ⚠️ 警告 省略类型检查可能会导致您的应用因类型错误而崩溃。 在使用-O3
之前,使用-O2
进行测试,以确保您的应用从不抛出Error
(例如TypeError
) 的子类型。-O4
:启用比-O3
更激进的优化,但具有相同的假设。 ⚠️ 警告-O4
优化容易受到输入数据变化的影响。 在依赖-O4
之前,测试用户输入中的边缘情况。
--no-source-maps
不生成源映射文件。
-h
或 --help
显示帮助。 要获取有关所有选项的信息,请使用 `-hv`。
路径和环境选项
#
其他一些方便的选项包括:
--packages=<path>
指定包解析配置文件的路径。 有关更多信息,请查看 Dart 包配置文件 规范。
-D<flag>=<value>
定义一个环境声明和值对,可以使用 String.fromEnvironment
、int.fromEnvironment
、bool.fromEnvironment
或 bool.hasEnvironment
访问。 要了解有关环境声明的更多信息,请参见 使用编译环境声明配置应用程序。
--version
显示 dart
的版本信息。
显示选项
#
以下选项可帮助您控制编译器输出。
--suppress-warnings
不显示警告。
--suppress-hints
不显示提示。
--terse
发出诊断信息,而不建议如何消除诊断出的问题。
-v
或 --verbose
显示大量信息。
分析选项
#
以下选项控制对 Dart 代码执行的分析。
--fatal-warnings
将警告视为编译错误。
--enable-diagnostic-colors
将颜色添加到诊断消息。
--show-package-warnings
显示从包生成的警告和提示。
--csp
禁用在生成的输出中动态生成代码。 这是满足 CSP 限制所必需的 (请参见 W3C 内容安全策略)。
--dump-info
生成一个文件(带有后缀 .info.json
),其中包含有关生成的代码的信息。 您可以使用 dart2js_info 中的工具检查生成的文件。
编译 Web 应用示例
# 例如,要将 Dart 应用程序编译为优化的 JavaScript,请运行以下命令:
dart compile js -O2 -o out/main.js web/main.dart
content_copy
改进生产 Web 编译
请遵循以下实践来改进类型推断,减少文件大小并提高 JavaScript 性能:
- 不要使用
Function.apply()
。 - 不要覆盖
noSuchMethod()
。 - 避免将变量设置为
null
。 - 确保传递给每个函数或方法的参数类型一致。
💡 提示 不必担心应用程序包含的库的大小。 生产编译器会执行 tree shaking 以省略未使用的类、函数、方法等。 导入您认为需要的库,并让编译器删除不需要的库。
要了解有关构建和部署 JavaScript 应用程序的更多信息,请查看 Web 部署。