skip to content

What does dart compile exe produce, and how does it differ from dart compile aot-snapshot run with dartaotruntime?

level: juniorimportance: should knowfreq 40%

answer

  1. runtime inside versus runtime beside
  2. Generated: bin/app.exe
  3. -o sets the output path
  4. one shared runtime for many tools
  5. -D defines for String.fromEnvironment

basics

~10 s

dart compile exe produces a self-contained native executable: AOT machine code plus a small Dart runtime. dart compile aot-snapshot produces the same machine code without the runtime, a .aot file you launch with dartaotruntime.

solid answer

~50 s

`dart compile exe bin/app.dart` writes a **self-contained executable** - native machine code for the host OS and architecture plus a small Dart runtime for garbage collection and type checks - that you distribute and run like any other binary; by default it lands next to the entry point, and `-o` chooses the path. `dart compile aot-snapshot` writes an **AOT module** (`.aot`) with the same compiled code but **no runtime**; you run it with `dartaotruntime app.aot`, which ships in the SDK's `bin` directory. The docs recommend AOT modules to reduce disk space when distributing several command-line apps that can share one runtime. Both are specific to the OS and architecture they were built for, both accept `-D` defines read through `String.fromEnvironment`, and both fail if a dependency has build hooks - that case needs `dart build`.

code

dart · 10 lines
dart
// bin/my_tool.dart
const version = String.fromEnvironment('APP_VERSION', defaultValue: 'dev');

void main(List<String> args) {
  if (args.contains('--version')) {
    print('my_tool $version');
    return;
  }
  print('Hello from my_tool');
}

go deeper

for a junior

Recall that exe gives a standalone executable and aot-snapshot needs dartaotruntime to run.

for a middle

Explain the embedded versus separate runtime, output paths, -D defines and why output is platform specific.

for a senior

Pick the format for a distribution plan, and recognise when build hooks force dart build instead.

for a principal

Decide how internal tools are packaged and versioned so runtime and module stay compatible across machines.

## The two AOT outputs of dart compile Both subcommands run the Dart **ahead-of-time compiler**, so both produce native machine code that starts quickly and needs no compilation at launch. They differ in **where the Dart runtime comes from**. | | `dart compile exe` | `dart compile aot-snapshot` | |---|---|---| | Output | self-contained executable | AOT module, `.aot` | | Dart runtime | embedded in the file | supplied by `dartaotruntime` | | How to run | `./app` | `dartaotruntime app.aot` | | Best for | distributing one tool | many tools sharing one runtime | | Portability | host OS and architecture (Linux cross-compile available) | same | The **Dart runtime** is not optional in either case: it provides the garbage collector, the runtime type checks the sound type system still needs, and isolate management. `exe` bakes it in; `aot-snapshot` leaves it out. ## dart compile exe ``` dart compile exe bin/my_tool.dart Generated: .../bin/my_tool.exe ``` The output is a normal executable. Copy it to another machine with the same OS and CPU architecture and run it - no Dart SDK required. Use `-o` or `--output` to choose the path, for example `-o build/my_tool`. On macOS and Windows the executable can be code-signed with the platform's usual tools. ## dart compile aot-snapshot and dartaotruntime ``` dart compile aot-snapshot bin/my_tool.dart dartaotruntime bin/my_tool.aot ``` The `.aot` file contains the same compiled code without the runtime. `dartaotruntime` lives in the Dart SDK's `bin` directory, so it must be on the `PATH`. The dart.dev guide's reason to prefer this form is **disk space**: if you ship ten command-line tools, one runtime plus ten modules is smaller than ten executables that each embed it. ## Shared options and limits - **`-D<name>=<value>`** defines compile-time environment declarations, read with `String.fromEnvironment`, `int.fromEnvironment` or `bool.fromEnvironment`. A release build can bake in a version string or a flavour this way. - **Platform-specific output.** A file built on macOS runs on macOS only. Cross-compilation exists, but only to Linux targets. - **Library restrictions.** The docs list no support for `dart:mirrors` and `dart:developer` in these outputs. - **Build hooks.** If the package or any dependency has build hooks (native code assets), `dart compile exe` and `aot-snapshot` refuse to build and point you to `dart build`, which runs the hooks and bundles the native libraries. - **Host support.** The source refuses both commands on 32-bit x86 hosts, since AOT compilation is not supported there. ## Scenario: shipping a CLI For a single tool given to users, `exe` is simpler: one file, no instructions beyond "put it on your PATH". For an internal toolbox of many small commands deployed to the same servers, `aot-snapshot` plus one `dartaotruntime` keeps the footprint down. ## Common mistakes - Copying an executable built on macOS to a Linux server and expecting it to run. - Running a `.aot` file directly instead of through `dartaotruntime`. - Expecting `dart compile exe` to handle packages with native build hooks. - Reading configuration with `Platform.environment` when a compile-time `-D` define was intended.

  • Why would you choose aot-snapshot over exe when distributing several Dart tools?
    Each `exe` embeds its own copy of the Dart runtime. With `aot-snapshot`, the tools share one `dartaotruntime`, so shipping many tools takes less disk space. The cost is that the runtime must be installed and on the PATH.
  • What happens if you run dart compile exe on a package whose dependency has build hooks?
    It refuses to build, because `dart compile` does not run build hooks, and it tells you to use `dart build`, which runs the hooks and bundles the native libraries with the executable.

saying these in an interview costs you the question

  • Thinks an aot-snapshot file can be executed directly
  • Believes dart compile exe output needs the Dart SDK installed
  • Expects one executable to run on every operating system
  • Thinks aot-snapshot output contains no machine code
  • Uses Platform.environment for values meant to be compile-time defines