# Contributing to the Flutter engine _See also: [Flutter's code of conduct][code_of_conduct]_ ## Welcome For an introduction to contributing to Flutter, see [our contributor guide][contrib_guide]. For specific instructions regarding building Flutter's engine, see [Setting up the Engine development environment][engine_dev_setup] on our wiki. Those instructions are part of the broader onboarding instructions described in the contributing guide. ## Style The Flutter engine _generally_ follows Google style for the languages it uses, with some exceptions. ### C/C++ Follows the [Google C++ Style Guide][google_cpp_style] and is automatically formatted with `clang-format`. Some additional considerations that are in compliance with the style guide, but are worth noting: #### Judiciously use shared_ptr The engine currently (as of 2024-05-15) uses `shared_ptr` liberally, which can be expensive to copy, and is not always necessary. The C++ style guide has a [section on ownership and smart pointers][cpp_ownership] worth reading: > Do not design your code to use shared ownership without a very good reason. > One such reason is to avoid expensive copy operations, but you should only do > this if the performance benefits are significant, and the underlying object is > immutable. Prefer using `std::unique_ptr` when possible. #### Judiciously use `auto` The C++ style guide has a [section on type deduction][cpp_auto] that is worth reading: > The fundamental rule is: use type deduction only to make the code clearer or > safer, and do not use it merely to avoid the inconvenience of writing an > explicit type. When judging whether the code is clearer, keep in mind that > your readers are not necessarily on your team, or familiar with your project, > so types that you and your reviewer experience as unnecessary clutter will > very often provide useful information to others. For example, you can assume > that the return type of `make_unique()` is obvious, but the return type > of `MyWidgetFactory()` probably isn't. Due to our codebase's extensive use of `shared_ptr`, `auto` can have surprising performance implications. See [#49801][pr_49801] for an example. #### Linux Embedding > [!NOTE] > The Linux embedding instead follows idiomatic GObject-based C style. Use of C++ in the [Linux embedding][] is discouraged in that embedding to avoid creating hybrid code that feels unfamiliar to either developers used to working with `GObject` or C++ developers. For example, _do not_ use STL collections or `std::string`, but _do_: - Use C++ casts (C-style casts are forbidden). - Use `nullptr` rather than `NULL`. - Avoid `#define`; for internal constants use `static constexpr` instead. ### Dart The Flutter engine _intends_ to follow the [Dart style guide][dart_style] but currently follows the [Flutter style guide][flutter_style], with the following exceptions: #### Use of type inference is allowed The [Dart style guide][dart_inference] only requires explicit types when type inference is not possible, but the Flutter style guide always requires explicit types. The engine is moving towards the Dart style guide, but this is a gradual process. In the meantime, follow these guidelines: - **Always** annotate when inference is not possible. - **Prefer** annotating when inference is possible but the type is not obvious. Some cases when using `var`/`final`/`const` is appropriate: - When the type is obvious from the right-hand side of the assignment: ```dart // Capitalized constructor name always returns a Foo. var foo = Foo(); // Similar with factory constructors. var bar = Bar.create(); // Literals (strings, numbers, lists, maps, etc) always return the same type. var name = 'John Doe'; var flag = true; var numbers = [1, 2, 3]; var map = {'one': 1, 'two': 2, 'three': 3}; ``` - When the type is obvious from the method name: ```dart // toString() always returns a String. var string = foo().toString(); // It's reasonable to assume that length returns an int. var length = string.length; ``` - When the type is obvious from the context: ```dart // When variables are in the same scope, reduce() clearly returns an int. var list = [1, 2, 3]; var sum = list.reduce((a, b) => a + b); ``` Some cases where an explicit type should be considered: - When the type is not obvious from the right-hand side of the assignment: ```dart // What does 'fetchLatest()' return? ImageBuffer buffer = fetchLatest(); // What does this large chain of method calls return? Iterable numbers = foo().bar().map((b) => b.baz()); ``` - When there are semantic implications to the type: ```dart // Without 'num', the map would be inferred as 'Map'. const map = {'one': 1, 'two': 2, 'three': 3}; ``` - Or, **when a reviewer requests it**! Remember that the goal is to make the code more readable and maintainable, and explicit types _can_ help with that. Code can be changed, so it's always possible to add or remove type annotations later as the code evolves, so avoid bikeshedding over this. ### Java Follows the [Google Java Style Guide][java_style] and is automatically formatted with `google-java-format`. ### Objective-C Follows the [Google Objective-C Style Guide][objc_style], including for Objective-C++ and is automatically formatted with `clang-format`. ### Python Follows the [Google Python Style Guide][google_python_style] and is automatically formatted with `yapf`. > [!WARNING] > Historically, the engine grew a number of one-off Python scripts, often as > part of the testing or build infrastructure (i.e. command-line tools). We are > instead moving towards using Dart for these tasks, so new Python scripts > should be avoided whenever possible. ### GN Automatically formatted with `gn format`. [cpp_auto]: https://google.github.io/styleguide/cppguide.html#Type_deduction [cpp_ownership]: https://google.github.io/styleguide/cppguide.html#Ownership_and_Smart_Pointers [dart_inference]: https://dart.dev/effective-dart/design#types [dart_style]: https://dart.dev/effective-dart/style [linux embedding]: shell/platform/linux [google_cpp_style]: https://google.github.io/styleguide/cppguide.html [pr_49801]: https://github.com/flutter/engine/pull/49801 [code_of_conduct]: https://github.com/flutter/flutter/blob/master/CODE_OF_CONDUCT.md [contrib_guide]: https://github.com/flutter/flutter/blob/master/CONTRIBUTING.md [engine_dev_setup]: docs/contributing/Setting-up-the-Engine-development-environment.md [flutter_style]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [objc_style]: https://google.github.io/styleguide/objcguide.html [java_style]: https://google.github.io/styleguide/javaguide.html [google_python_style]: https://google.github.io/styleguide/pyguide.html ## Testing The testing policy for contributing to the flutter engine can be found at the [Tree Hygiene Wiki][tree_hygiene_wiki]. The summary is that all PR's to the engine should be tested or have an explicit test exemption. Because the engine targets multiple platforms the testing infrastructure is fairly complicated. Here are some more resources to help guide writing tests: - [Testing the engine wiki][testing_the_engine_wiki] - A guide on writing tests for the engine including an overview of the different tests and the different technologies the engine uses. - [`//testing`](./testing) - This is where the `run_tests.py` script is located. All tests will have the ability to be executed with `run_tests.py`. - [`//ci/builders`](./ci/builders) - The JSON files that determine how tests are executed on CI. Tests will be executed on CI, but some tests will be executed before PR's can be merged (presubmit) and others after they have been merged (postsubmit). Ideally everything would be presubmit but tests that take up more resources are executed in postsubmit. ### Skia Gold The Flutter engine uses [Skia Gold][skia_gold] for image comparison tests which fail if: - The image is different from an accepted baseline. - An image is not uploaded but is expected to be (see [`dir_contents_diff`][dir_contents_diff]). [skia_gold]: https://flutter-engine-gold.skia.org/ [dir_contents_diff]: ./tools/dir_contents_diff/ Any untriaged failures will block presubmit and postsubmit tests. ### Example run_tests.py invocation ```sh # Configure host build for macOS arm64 debug. $ flutter/tools/gn --runtime-mode=debug --unoptimized --no-lto --mac-cpu=arm64 # Compile default targets (should cover all applicable run_tests.py requirements). $ ninja -j100 -C out/host_debug_unopt_arm64 # Run all cross-platform C++ tests for the debug build arm64 variant. $ cd flutter/testing $ ./run_tests.py --variant=host_debug_unopt_arm64 --type=engine ``` ### Directory | Name | run_tests.py type | Description | | ---------------------------------------- | ------------------- | --------------------------------------------------------------- | | accessibility_unittests | engine | | | client_wrapper_glfw_unittests | engine | | | client_wrapper_unittests | engine | | | common_cpp_core_unittests | engine | | | common_cpp_unittests | engine | | | dart_plugin_registrant_unittests | engine | | | display_list_rendertests | engine | | | display_list_unittests | engine | | | embedder_a11y_unittests | engine | | | embedder_proctable_unittests | engine | | | embedder_unittests | engine | | | felt | n/a | The test runner for flutter web. See //lib/web_ui | | flow_unittests | engine | | | flutter_tester | dart | Launcher for engine dart tests. | | fml_arc_unittests | engine | | | fml_unittests | engine | Unit tests for //fml | | framework_common_unittests | engine(mac) | | | gpu_surface_metal_unittests | engine(mac) | | | impeller_dart_unittests | engine | | | impeller_golden_tests | engine(mac) | Generates golden images for impeller (vulkan, metal, opengles). | | impeller_unittests | engine | impeller unit tests and interactive tests | | ios_test_flutter | objc | dynamic library of objc tests to be run with XCTest | | jni_unittests | engine(not windows) | | | no_dart_plugin_registrant_unittests | engine | | | platform_view_android_delegate_unittests | engine(not windows) | | | runtime_unittests | engine | | | shell_unittests | engine(not windows) | | | scenario_app | android | Integration and golden tests for Android, iOS | | testing_unittests | engine | | | tonic_unittests | engine | Unit tests for //third_party/tonic | | txt_unittests | engine(linux) | | | ui_unittests | engine | | [tree_hygiene_wiki]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [testing_the_engine_wiki]: https://github.com/flutter/flutter/wiki/Testing-the-engine ## Fuchsia Contributions from Googlers Googlers contributing to Fuchsia should follow the additional steps at: go/flutter-fuchsia-pr-policy.