_If you've never built the engine before, first see [Setting up the Engine development environment](Setting-up-the-Engine-development-environment.md)._

# Contents

Depending on the platform you are making changes for, you may be interested in all or only some of the sections below:

* [General Compilation Tips](#general-compilation-tips)
* [Using a custom Dart SDK](#using-a-custom-dart-sdk)
* [Compiling for Android](#compiling-for-android-from-macos-or-linux)
* [Compiling for iOS (from macOS)](#compiling-for-ios-from-macos)
* [Compiling for macOS or Linux](#compiling-for-macos-or-linux)
* [Compiling for Windows](#compiling-for-windows)
* [Compiling for Fuchsia](#compiling-for-fuchsia)
* [Compiling for the Web](#compiling-for-the-web)
* [Compiling for testing](#compiling-for-testing)

## General Compilation Tips

- Instead of compiling manually as described in this file, it's recommended to use `et`,
  the engine tool, located at
  https://github.com/flutter/flutter/blob/master/engine/src/flutter/tools/engine_tool.
- For local development and testing, it's generally preferable to use `--unopt` builds.
  These builds will have additional logging and checks enabled, and generally use build
  and link flags that lead to faster compilation and better debugging symbols.
  If you are trying to do performance testing with a local build, do not use the `--unopt`
  flag.
- Link Time Optimization: Optimized builds also perform Link Time Optimization of all
  binaries. This makes the linker take a lot of time and memory to produce binaries. If
  you need optimized binaries but don't want to perform LTO, add the `--no-lto` flag.
- Android and iOS expect both a `host` and `android` (or `ios`) build. It is critical to
  recompile the host build after upgrading the Dart SDK (e.g. via a `gclient sync` after
  merging up to head), since artifacts from the host build need to be version matched to
  artifacts in the Android/iOS build.
- Web, Desktop, and Fuchsia builds have only one build target (i.e. `host` or `fuchsia`).
- Make sure to exclude the `out` directory from any backup scripts, as many large binary
  artifacts are generated. This is also generally true for all of the directories outside
  of the `engine/src/flutter` directory.

## Updating the engine
Before compiling, you should typically make sure that your engine code is up to date with the latest `master`:

```sh
git fetch upstream master
git rebase upstream/master
gclient sync -D
```

## Using a custom Dart SDK

When targeting the host and desktop, on CI we use a pre-built Dart SDK vended by the Dart team.
To build and use the SDK from the Dart sources downloaded by `gclient sync`, after editing those
source files, pass the flag `--no-prebuilt-dart-sdk` to `//flutter/tools/gn`.

## Compiling for Android (from macOS or Linux)

These steps build the engine used by `flutter run` for Android devices.

Run the following steps from the `engine/src` directory in your local checkout. See [Setting up the Engine development environment](Setting-up-the-Engine-development-environment.md).

1. Make sure your engine code is [up to date](https://github.com/flutter/flutter/blob/master/engine/src/flutter/docs/contributing/Compiling-the-engine.md#updating-the-engine).

2. Prepare your build files
    * `./flutter/tools/gn --android --unoptimized` for device-side executables.
    * `./flutter/tools/gn --android --android-cpu arm64 --unoptimized` for newer 64-bit Android devices.
    * `./flutter/tools/gn --android --android-cpu x86 --unoptimized` for x86 emulators.
    * `./flutter/tools/gn --android --android-cpu x64 --unoptimized` for x64 emulators.
    * `./flutter/tools/gn --unoptimized` for host-side executables, needed to compile the code.
      * On Apple Silicon ("M" chips), add `--mac-cpu arm64` to avoid using emulation. This will generate `host_debug_unopt_arm64`.

> 💡 **TIP**: When developing on a Mac with ARM (M CPU), prefer `host_debug_unopt_arm64`.
>
> You can continue to use `host_debug_unopt` (required for Intel Macs), but the engine will be run under Rosetta
> which may be slower. See [Developing with Flutter on Apple Silicon](https://github.com/flutter/flutter/blob/master/docs/platforms/desktop/macos/Developing-with-Flutter-on-Apple-Silicon.md)
> for more information.

3. Build your executables
    * `ninja -C out/android_debug_unopt` for device-side executables.
    * `ninja -C out/android_debug_unopt_arm64` for newer 64-bit Android devices.
    * `ninja -C out/android_debug_unopt_x86` for x86 emulators.
    * `ninja -C out/android_debug_unopt_x64` for x64 emulators.
    * `ninja -C out/host_debug_unopt` (or `ninja -C out/host_debug_unopt_arm64`, see above) for host-side executables.
    * These commands can be combined. Ex: `ninja -C out/android_debug_unopt && ninja -C out/host_debug_unopt`
    * For MacOS, you will need older version of XCode(9.4 or below) to compile android_debug_unopt and android_debug_unopt_x86. If you only care about x64, you can ignore this

This builds a debug-enabled ("unoptimized") binary configured to run Dart in
checked mode ("debug"). There are other versions, see [Flutter's modes](../Flutter's-modes.md).

If you're going to be debugging crashes in the engine, make sure you add
`android:debuggable="true"` to the `<application>` element in the
`android/AndroidManifest.xml` file for the Flutter app you are using
to test the engine.

See [The flutter tool](https://github.com/flutter/flutter/blob/master/docs/tool/README.md) for instructions on how to use the `flutter` tool with a local engine.
You will typically use the `android_debug_unopt` build to debug the engine on a device, and
`android_debug_unopt_x64` to debug in on a simulator. Modifying dart sources in the engine will
require adding a `dependency_override` section in you app's `pubspec.yaml` as detailed
[here](https://github.com/flutter/flutter/blob/master/docs/tool/README.md#using-a-locally-built-engine-with-the-flutter-tool).

Note that if you use particular android or ios engine build, you will need to have corresponding
host build available next to it: if you use `android_debug_unopt`, you should have built `host_debug_unopt`,
`android_profile` -> `host_profile`, etc. One caveat concerns cpu-flavored builds like `android_debug_unopt_x86`: you won't be able to build `host_debug_unopt_x86` as that configuration is not supported. What you are expected to do is to build `host_debug_unopt` and symlink `host_debug_unopt_x86` to it.

### Compiling everything that matters on Linux

The following script will update all the builds that matter if you're developing on Linux and testing on Android and your `.gclient` file is located at `~/dev/flutter/engine/.gclient`:

```bash
set -ex

cd ~/dev/flutter
git fetch upstream master
git rebase upstream/master
cd engine
gclient sync -D
cd src

flutter/tools/gn --unoptimized --runtime-mode=debug
flutter/tools/gn --android --unoptimized --runtime-mode=debug
flutter/tools/gn --android --runtime-mode=profile
flutter/tools/gn --android --runtime-mode=release

cd out
find . -mindepth 1 -maxdepth 1 -type d | xargs -n 1 sh -c 'ninja -C $0 || exit 255'
```
For `--runtime-mode=profile` build, please also consider adding `--no-lto` option to the `gn` command. It will make linking much faster with a small sacrifice on the binary size and memory usage (which probably doesn't matter for debugging or performance benchmark purposes.)

## Compiling for iOS (from macOS)

These steps build the engine used by `flutter run` for iOS devices.

Run the following steps, from the `engine/src` directory:

1. Make sure your engine code is [up to date](https://github.com/flutter/flutter/blob/master/engine/src/flutter/docs/contributing/Compiling-the-engine.md#updating-the-engine).

2. `./flutter/tools/gn --ios --unoptimized` to prepare build files for device-side executables (or `--ios --simulator --unoptimized` for simulator).
   * This also produces an Xcode project for working with the engine source code at `out/ios_debug_unopt/flutter_engine.xcodeproj`
   * For a discussion on the various flags and modes, see [Flutter's modes](../Flutter's-modes.md).
   * Add the `--simulator-cpu=arm64` argument for an arm64 Mac simulator to output to `out/ios_debug_sim_unopt_arm64`.

3. `./flutter/tools/gn --unoptimized` to prepare the build files for host-side executables.
   * On Apple Silicon ("M" chips), add `--mac-cpu arm64` to avoid using emulation. This will generate `host_debug_unopt_arm64`.

4. `ninja -C out/ios_debug_unopt && ninja -C out/host_debug_unopt` to build all artifacts (use `out/ios_debug_sim_unopt` for Simulator).

See [The flutter tool](https://github.com/flutter/flutter/blob/master/docs/tool/README.md) for instructions on how to use the `flutter` tool with a local engine.
You will typically use the `ios_debug_unopt` build to debug the engine on a device, and
`ios_debug_sim_unopt` to debug in on a simulator. Modifying dart sources in the engine will
require adding a `dependency_override` section in you app's `pubspec.yaml` as detailed
[here](https://github.com/flutter/flutter/blob/master/docs/tool/README.md#using-a-locally-built-engine-with-the-flutter-tool).

See also [instructions for debugging the engine in a Flutter app in Xcode](../Debugging-the-engine.md#debugging-ios-builds-with-xcode).

## Compiling for macOS or Linux

These steps build the desktop embedding, and the engine used by `flutter test` on a host workstation.

1. Make sure your engine code is [up to date](https://github.com/flutter/flutter/blob/master/engine/src/flutter/docs/contributing/Compiling-the-engine.md#updating-the-engine).

2. `./flutter/tools/gn --unoptimized` to prepare your build files.
   * `--unoptimized` disables C++ compiler optimizations. On macOS, binaries are emitted unstripped; on Linux, unstripped binaries are emitted to an `exe.unstripped` subdirectory of the build.

3. `ninja -C out/host_debug_unopt` to build a desktop unoptimized binary.
    * If you skipped `--unoptimized`, use `ninja -C out/host_debug` instead.

See [The flutter tool](https://github.com/flutter/flutter/blob/master/docs/tool/README.md) for instructions on how to use the `flutter` tool with a local engine.
You will typically use the `host_debug_unopt` build in this setup. Modifying dart sources in the engine will
require adding a `dependency_override` section in you app's `pubspec.yaml` as detailed
[here](https://github.com/flutter/flutter/blob/master/docs/tool/README.md#using-a-locally-built-engine-with-the-flutter-tool).


## Compiling for Windows

> [!WARNING]
> You can only build selected binaries on Windows (mainly `gen_snapshot` and the desktop embedding).

On Windows, ensure that the engine checkout is not deeply nested. This avoid the issue of the build scripts working with excessively long paths.

1. Make sure you have Visual Studio installed (non-Googlers only). [Debugging Tools for Windows 10](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools#small-classic-windbg-preview-logo-debugging-tools-for-windows-10-windbg) must be installed.

2. Make sure your engine code is [up to date](https://github.com/flutter/flutter/blob/master/engine/src/flutter/docs/contributing/Compiling-the-engine.md#updating-the-engine).

3. Ensure long path support is enabled on your machine. Launch PowerShell as an administrator and run:
```
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -Force
```

4. If you are not a Google employee, you must set the following environment variables to point the depot tools at Visual Studio:
```shell
DEPOT_TOOLS_WIN_TOOLCHAIN=0
GYP_MSVS_OVERRIDE_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community" # (or your location for Visual Studio)
WINDOWSSDKDIR="C:\Program Files (x86)\Windows Kits\10" # (or your location for Windows Kits)
```
Also, be sure that Python27 is before any other python in your Path.

5. switch to `engine/src/` directory.

6. `python .\flutter\tools\gn --unoptimized` to prepare your build files.
   * If you are only building `gen_snapshot`: `python .\flutter\tools\gn [--unoptimized] --runtime-mode=[debug|profile|release] [--android]`.

7. `ninja -C .\out\<dir created by previous step>` to build.
   * If you used a non-debug configuration, use `ninja -C .\out\<dir created by previous step> gen_snapshot`.
     Release and profile are not yet supported for the desktop shell.

## Compiling for Fuchsia

### Build components for Fuchsia

1. Building fuchsia is only supported on linux. You need to update `engine/.gclient`, or `../.gclient` if current directory is `engine/src`, with `custom_vars`.

```
solutions = [
  {
    # ...
    "custom_vars": {
      "download_fuchsia_deps": True,
      "run_fuchsia_emu": True,
    },
  },
]
```

> You may ignore `"run_fuchsia_emu": True` if you won't run tests locally.

Run `gclient sync -D`.

> [!WARNING]
> When running tests locally, you will also need kvm enabled, or nested virtualization on the gcloud VMs. Fuchsia and the tests will all be executed on the qemu.

2. Prepare and build

```
./flutter/tools/gn --fuchsia --no-lto
```

  * It will create a `out/fuchsia_debug_x64`.
  * Use `--fuchsia-cpu arm64` to build components for arm64. It will be created in a folder `out/fuchsia_debug_arm64`.
  * Use `--runtime-mode=release` or `--runtime-mode=profile` to select other profiles as other platforms.
  * Ignore `--no-lto` to use lto or link-time optimization.

```
ninja -C out/fuchsia_debug_x64 -k 0
```

  * It builds all but ignores known errors.
  * Or specify following targets to avoid using `-k 0`.

```
flutter/shell/platform/fuchsia:fuchsia \
flutter/shell/platform/fuchsia/dart_runner:dart_runner_tests \
fuchsia_tests
```

  * Use `autoninja` if it's available.
  * `-C out/fuchsia_release_x64` for release build; other configurations are similar with a different folder name in `out/`.

3. Run all tests locally

```
python3 flutter/tools/fuchsia/with_envs.py flutter/testing/fuchsia/run_tests.py
```

  * It runs the tests in `out/fuchsia_debug_x64` by default. According to the configuration, it may take 5 minutes with regular gtest output to the terminal.
  * Add `fuchsia_release_x64` at the end of the command for release build; other configurations are similar with a different folder name in `out/`.

```
python3 flutter/tools/fuchsia/with_envs.py flutter/testing/fuchsia/run_tests.py fuchsia_release_x64
```

## Compiling for the Web

For building the engine for the Web we use the [felt](https://github.com/flutter/flutter/blob/master/engine/src/flutter/lib/web_ui/README.md) tool.

To test Flutter with a local build of the Web engine, add `--local-web-sdk=wasm_release` to your `flutter` command, e.g.:

```
flutter run --local-web-sdk=wasm_release -d chrome
flutter test --local-web-sdk=wasm_release test/path/to/your_test.dart
```

## Compiling for the Web on Windows

Compiling the web engine might take a few extra steps on Windows. Use cmd.exe and "run as administrator".

1. Make sure you have Visual Studio installed. Set the following environment variables. For Visual Studio use the path of the version you installed.
   * `GYP_MSVS_OVERRIDE_PATH = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community"`
   * `GYP_MSVS_VERSION = 2017`
2. Make sure, depot_tools, ninja and python are installed and added to the path. Also set the following environment variable for depot tools:
   * `DEPOT_TOOLS_WIN_TOOLCHAIN = 0`
   * Tip: if you get a python error try to use Python 2 instead of 3
3. Make sure your engine code is [up to date](https://github.com/flutter/flutter/blob/master/engine/src/flutter/docs/contributing/Compiling-the-engine.md#updating-the-engine).
   * Tip: If you get a git authentication errors on this step try Git Bash instead
5. `python .\flutter\tools\gn --unoptimized --full-dart-sdk` to prepare your build files.
6. `ninja -C .\out\<dir created by previous step>` to build.

To test Flutter with a local build of the Web engine, add `--local-web-sdk=wasm_release` to your `flutter` command, e.g.:

```
flutter run --local-web-sdk=wasm_release -d chrome
flutter test --local-web-sdk=wasm_release test/path/to/your_test.dart
```

For testing the engine again use [felt](https://github.com/flutter/engine/blob/main/lib/web_ui/README.md) tool
this time with felt_windows.bat.

```
felt_windows.bat test
```

## Compiling for testing

### Dart tests

To run dart tests, build the engine:

```
flutter/tools/gn --unoptimized
ninja -C out/host_debug_unopt/
```

execute `run_tests` for native:
```
python3 flutter/testing/run_tests.py --type dart
```

and `felt` for web:
```
cd flutter/lib/web_ui
dev/felt test [test file]
```


## Troubleshooting Compile Errors

### Version Solving Failed

From time to time, as the Dart versions increase, you might see dependency errors such as:

```
The current Dart SDK version is 2.7.0-dev.0.0.flutter-1ef444139c.

Because ui depends on <a pub package> 1.0.0 which requires SDK version >=2.7.0 <3.0.0, version solving failed.
```

Running `gclient sync` does not update the tags, there are two solutions:
1. under `engine/src/third_party/dart` run `git fetch --tags origin`
2. or run gclient sync with with tags parameter: `gclient sync --with_tags`

_See also: [Debugging the engine](../Debugging-the-engine.md), which includes instructions on running a Flutter app with a local engine._
