This is a personal note that I decided to share. It reflects my understanding of a subject and may contain errors and approximations. Feel free to contribute by contacting me here. Any help will be credited!
Thanks to Alexis Luczak for the review.
Flutter is an open-source framework for building multi-platform applications. For mobile platforms, Flutter applications are natively compiled for iOS and Android.
It results in two executables: .ipa
for IOS and .apk
or .aab
for Android.
To compile in both environments, Flutter needs several tools and components. This exogeneity is sometimes difficult to understand.
The aim of this note is to provide a better understanding of the tools and components involved in building mobile applications with Flutter.
Android
Android build uses Gradle as a build automation tool and dependency manager. Flutter Android build follows the Android build structure.
There are two build.gradle
files:
- Project-level in
android
folder: It contains repositories (dependency repositories), common plugins, properties and settings. - App-level in
android/app
folder: It contains all information necessary to build the app (or module).
In the App-level build.gradle
, we find:
- Dependencies :
- Libraries.
- Platforms (such as Android SDK, Flutter).
- Plugins and their configurations.
- Flavors configuration.
A wrapper script downloads and invokes Gradle. The wrapper configuration, including the Gradle version, is configured in the gradle/wrapper
folder.
The gradle version is directly linked to the Java version and Android SDK.
Gradle and Java compatibility matrix can be found here.
Gradle version is specified in the distributionUrl
in gradle-wrapper.properties
.
It’s possible to specify the Java version used by Flutter build with the given command : flutter config --jdk-dir=<JDK_DIRECTORY>
Build environment
Android executable can be build in a container easily. It provides stability and reproducibility of the build workflow.
IOS
For IOS, the build configuration and dependencies management are not handled by the same tool.
Cocoapods
Cocoapods is a dependency manager for IOS applications (and more, Swift and Objective C applications).
In the ios
app’s folder, there is a Podfile
that defines the dependencies.
Dependencies are downloaded in the Pods
folder on pod install
.
Ruby and Gem?
Cocoapods is a Ruby package, a gem
.
To install cocoapods, we need a Gemfile
, a file that lists all gem
necessary for the project.
Gems are installed with bundler
the dependency management tool of Ruby, on bundle install
.
Xcode Build System
Xcode manages the application’s build process.
It compiles, and links the libraries and system frameworks with the source code. It also signs the resulting executable .ipa
on AppStore deployment.
Xcode basic notions
Xcode has its specific notions:
- Target: A target is a product obtained after a build. It can be an app, framework, library, or even a test suite.
- Project: A project is a repository for files and resources needed to build one or more Targets.
- Workspace: A workspace is a set of projects with relationships between them. Projects in a workspace share the same build directory. Workspace manages dependencies and links them with the project source code.
When building a Flutter app, there is always an Xcode workspace to make everything work.
Xcode files
In the ios
folder, there are three Xcode files/folders:
Pods/Pods.xcodeproj
: Project created by cocoapods to manage dependencies. There are targets for each pod included.project.pbxproj
: Complex file that describes project structure and intra-project dependencies between targets, files, and frameworks.
Runner.xcodeproj
: Project for the application.project.pbxproj
: Complex file that describes project structure and intra-project dependencies between targets, files, and frameworks.
Runner.xcworkspace
: Workspace referencing and linking the two projects above.contents.xcworkspacedata
: list projects of the workspace. In a classic Flutter project, there are two references:Runner.xcodeproj
andPods.xcodeproj
. The project and the dependencies.
Runner
by default.Build environment
IOS executable must be build on macOs. Build an IOS app in a container is challenging, so most of the time, teams use a Mac to build the application. Thus, we can encounter stability and reproducibility issues on build workflow of IOS app.
Fastlane
Android and IOS are two completely different worlds. Each one has its own specifications.
Fastlane eases the automation of building and deploying mobile applications for both platforms. It provides a unique abstraction to simplify developers’ work on Android and IOS builds.
Fastlane introduces the concept of actions
and lanes
:
- An action is a command. Ex:
build
,test
,deliver
… - A lane is a suite of actions. It defines a workflow. Ex: A lane to release the app.
Fastlane is configured via Fastfile
and Appfile
. There is one of each file in android
and ios
folder.
Fastfile
: defines the lanes.- (Optional)
Appfile
: defines global configuration and metadata such as app identifier, bundle ID, apple ID, package name…
Fastlane is also written in Ruby, so it should be declared in Gemfile
. One in each folder android
and ios
or one for the project.
Flutter pub
pub.dev is the Dart and Flutter package manager.
In a Flutter project, there is pubspec.yaml
file that declares information for the current package or project such as:
- Name
- SDK
- Dependencies
- Supported platforms
- …
Flutter dependencies can rely on native IOS and Android libraries. On flutter pub get
, dependencies are resolved as well as transitive dependencies. It can lead to modifications on the build.gradle
and the Podfile
to declare native dependencies.
Tips when Debugging Build Issues
Lock files
pubspec.yaml
, Gemfile
, and Podfile
have lock files once they are processed by pub
, bundler
, pod
. These lock files fix all dependencies version and location to ensure stability and reproduceability for development and build.
Don’t forget to update them when working on dependencies.
Cache and residues
On package removal or package update, some old configurations or code can still reside in some folders, especially on IOS.
Don’t hesitate to clean Pods
, .symlinks
, build
folders.
Don’t forget also that some configuration files exist, such as project.pbxproj
for Xcode. These files can contain references to old or removed packages, which can lead to errors during a Flutter upgrade for example.
File and Structure Summary
Note: This structure can vary depending on the project.
- For multi-module projects, there are multiple
pubspec.yaml
. - Gemfiles can be merged in one
Gemfile
in the project folder.
Project folder:
-
pubspec.yaml
: Configuration file of the project. -
ios
folder:fastlane
folder:Appfile
: Global configuration and metadata.Fastfile
: Lanes configuration.
Gemfile
: Ruby package definitions.Podfile
: ios dependencies definitions.Runner.xcodeproj
: Xcode projet file.Runner.xcworkspace
: Xcode workspace file.
-
android
folder:fastlane
folder:Appfile
: Global configuration and metadata for Android.Fastfile
: Lanes configuration for IOS.
Gemfile
: Ruby package definitions.build.gradle
: project-level Gradle build configuration.app
folder:build.gradle
: app-level Gradle build configuration.

My Flutter Build System Summary Diagram (probably inaccurate)