Flutter: from Mobile to Desktop

Building applications for smartphones and desktops with the Google framework.

Check here the portuguese version / Acesse aqui a versão em português

Introduction

If you’re developing applications for smartphones, probably you’ve heard of a new development framework, Google’s Flutter. It is a framework that allows you to develop applications with a single code base in the Dart language, also from Google, and publish them for both the Android and iOS platforms.

The framework has not yet reached the 1.0 version, but has already been announced as production ready by Google since its beta 3 version, released in May this year. In addition, there is the possibility of building applications with Flutter for desktop environments (Windows, macOS and Linux), which is the subject that this article will address.

Support for desktop platforms is currently provided through two projects, both still in development. One of them is even developed by Google, but has an indication that the company does not support it. The projects can be found in the following Github repositories:

Both projects are classified as Custom Flutter Engine Embedders, that is, they are implementations of the Flutter API so that projects developed in this framework can run on operating systems other than those officially supported by the Flutter project (Android, Fuchsia and iOS).

They use OpenGL through the GLFW library (except for the macOS version of the Google project), which provides an API for creating windows and handling keyboard and mouse input, among other features, on desktop platforms. Therefore, the platform where the application that is being developed will run must have drivers installed for OpenGL.


Flutter Install

To install Flutter, follow the steps listed on the official install page according to your operating system. Click here to access the install page. It will be required to run the projects later in this article. Don’t forget to include Flutter in your PATH environment variable.


Project 1: Desktop Embedding for Flutter (Google)

This project currently has some limitations, which are indicated in the Caveats section of the repository documentation.

Unlike the second project, which will be presented later in this article, this project does not have binary files that make it possible to quickly run the sample project or set up your own Flutter project to run it on desktop platforms. You need to compile the source code for this project in your operating system and then include the generated libraries into an executable file that will be part of the application. In the future this process will be simplified, as stated in the current repository documentation.

To compile the project source code and create your desktop applications with Flutter through this project, follow the instructions here and here.


Project 2: Go Flutter desktop embedder (Drakirus)

The second project is developed through Google’s Go (Golang) programming language.

In the project repository there are download releases where you can test examples of desktop applications through already compiled executable files. In addition, creating new Flutter desktop applications is quite simple.

The following items show how to run the existing sample project in the project repository and also how to run your own project developed in Flutter, now as a desktop application.

Executing the sample project:

  1. Access the project releases here.
  2. Download the sample file according to your platform in the section named Prebuilt Binaries example for Linux, Windows and MacOS, the v0.2.1-alpha version.
  3. Unzip the downloaded file to a location of your choice.
  4. Run the stocks executable (macOS and Linux) or socks.exe (Windows) in the root directory of the uncompressed set of files. It will run like any other operating system application that you use (examples in the images below).
Sample application developed in Flutter running in the Windows 10 desktop environment.
Sample application developed in Flutter running in the macOS Mojave desktop environment.
Sample application developed in Flutter running in the Ubuntu Budgie 18.04 desktop environment.

NOTE: In the following guides, the macOS version of the desktop application is starting with a black screen, but the application loads normally after maximizing the screen. As soon as I figure out the solution to this problem, I will update this article.

Running your own project (using precompiled files):

  1. Download the precompiled file for your operating system here.
  2. Unzip the contents to a directory of your choice.
  3. Edit the config.json file of the template directory by changing the value of the parameters according to the information of your environment and application. FlutterPath: directory of your Flutter installation. FlutterProjectPath: your project (developed in Flutter) directory. IconPath: path to the desktop application icon file (default value can be maintained). ScreenHeight: initial screen height of the desktop application. ScreenWidth: initial screen width of the desktop application. Use double backslashes (\\) instead of simple ones (\) in directory paths if you are using Windows.
  4. Run the flutter-desktop-template executable, on macOS or Linux, or flutter-desktop-template.exe executable, on Windows, and the application will start. It will run like any other operating system application that you use

Running your own project (compiling the Go desktop project):

  1. Download and install the Go programming language through its downloads page here (instructions for install and configuration of the tools in the PATH environment variable are provided on the download page).
  2. If you do not have gcc installed on your machine, you will need to install it to compile some code files from the desktop project in Go. For Windows, I suggest tdm64-gcc. For macOS, the one provided by Xcode Command Line Tools is used. For Linux, probably you already have a gcc installed on your system.
  3. Download and install Git here if you don’t have it installed in your system.
  4. Create your Flutter project normally through the flutter create command or an IDE.
  5. Include the following import in the main.dart file of your Flutter project:import 'package:flutter/foundation.dart' show debugDefaultTargetPlatformOverride;
  6. Include the following code at the beginning of the main method (before calling the runApp method) from the main.dart file of your Flutter project (this code is required because desktop platforms are not officially supported by the Flutter project): debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
  7. In a terminal, run the flutter build bundle command in the directory of your Flutter project (a directory will be created with the files needed to run the application in Flutter by the template that will be downloaded and configured in the following steps).
  8. Also in a terminal, run the go get -u github.com/go-gl/glfw/v3.2/glfw command to download the GLFW library for the Go language (if there is a problem, check the Troubleshooting item at the end of this article). You must verify that you have all the dependencies quoted in this link before installing it.
  9. Download the desktop project in Go here (version that is currently running and supporting Windows, macOS and Linux).
  10. Unzip the contents of the downloaded file to any directory on your operating system.
  11. Rename the directory extracted from go-flutter-desktop-embedder-0.2.1-alpha to go-flutter-desktop-embedder.
  12. Copy the extracted (now renamed) directory into the src\github.com\Drakirus directory (or src/github.com/Drakirus on Windows), which must be created in your GOPATH (GOPATH is an environment variable that indicates where are installed the libraries that are downloaded for the Go language; on Windows and macOS usually it is the go directory inside the user’s personal folder).
  13. Download or clone the template repository needed for this walkthrough here (it will be used to make it easier to run the application without having to program in the Go language). Unzip the downloaded file to a directory of your preference if you have chosen to download it instead of cloning the repository.
  14. Download the Flutter library (required for template operation) by using the https://storage.googleapis.com/flutter_infra/flutter/74625aed323d04f2add0410e84038d250f51b616/linux-x64/linux-x64-embedder link on Linux, https://storage.googleapis.com/flutter_infra/flutter/74625aed323d04f2add0410e84038d250f51b616/darwin-x64/FlutterEmbedder.framework.zip on macOS or https://storage.googleapis.com/flutter_infra/flutter/74625aed323d04f2add0410e84038d250f51b616/windows-x64/windows-x64-embedder.zip on Windows (replacing bold text, which is the hash of beta version 0.9.4, with the hash corresponding to the version of Flutter you are using in your project, what you can get by looking at the file bin\internal\engine.version inside your Flutter install path).
  15. Unzip the downloaded file and copy the libflutter_engine.so file in Linux, FlutterEmbedder.framework (the contents of the FlutterEmbedder.framework.zip file as a directory with the name FlutterEmbedder.framework) on macOS or flutter_engine.dll on Windows into the directory template, where the main.go file is located, and also into the go-flutter-desktop-embedder directory, which was previously copied to your GOPATH.
  16. On a terminal, go to the go-flutter-desktop-embedder directory and run the export CGO_LDFLAGS="-L${PWD}" command on Linux, the set CGO_LDFLAGS=-L%cd% command on Windows or export CGO_LDFLAGS="-F${PWD} -Wl,-rpath,@executable_path" command on macOS. Keep the terminal open.
  17. On the same terminal, run the go install command inside the go-flutter-desktop-embedder directory. Still keep the terminal open.
  18. Edit the config.json file of the template directory by changing the value of the parameters according to the information of your environment and application. FlutterPath: directory of your Flutter installation. FlutterProjectPath: your project (developed in Flutter) directory. IconPath: path to the desktop application icon file (default value can be maintained). ScreenHeight: initial screen height of the desktop application. ScreenWidth: initial screen width of the desktop application. Use double backslashes (\\) instead of simple ones (\) in directory paths if you are using Windows.
  19. Still in the same terminal, repeat step 16 and execute the go build command, but now in the directory where you unzipped the template, where the main.go file is located. On Windows, use the go build -ldflags -H=windowsgui command instead of go build so that a terminal is not displayed along with the application when running it. On macOS, it may be necessary to package the directory according to the platform standards so that a terminal is not shown along with the application.
  20. An executable file will be created (it will have the same name as the project directory, flutter-desktop-template on Linux and Mac or flutter-desktop-template.exe on Windows if the template directory is flutter-desktop-template).
  21. Run the created executable file and the application will start. It will run like any other operating system application that you use (examples in the images below).
Application developed in Flutter running in the Windows 10 desktop environment.
Application developed in Flutter running in the macOS Mojave desktop environment.
Application developed in Flutter running in the Ubuntu Budgie 18.04 desktop environment.
  • Whenever any changes are made to the Flutter project, repeat step 7 (running the flutter build bundle command in the project directory) again.
  • The version of Flutter used in the project should be the same as that downloaded in step 14.
  • Whenever you make any changes to the config.json file of the template, repeat steps 16 and 19.

Packaging your application for distribution

To distribute your desktop application developed in Flutter so that it can run on computers that do not have Flutter installed, follow the steps below after running one of the above guides to run your own project.

  1. Make sure you are using the current version of the template, which is version 1.1.0.
  2. Create a directory to store all the files needed to run your application. In the following steps, this directory will be called as application directory.
  3. Include in the application directory the flutter-desktop-template executable (on Linux and macOS) or flutter-desktop-template.exe (on Windows). Rename the executable according to the name of your application.
  4. Also include the Flutter library in the application directory. This library is the libflutter_engine.so file on Linux, the FlutterEmbedder.framework directory on macOS, or the flutter_engine.dll file on Windows.
  5. Copy the config.json file to the application directory. Edit this file by changing the value of FlutterPath and FlutterProjectPath to blank (leave the values empty).
  6. Include the assets directory with the icon image in the application directory. If you have chosen another image, copy that image to the application directory and correct its path in the IconPath value in the config.json file.
  7. Copy to the application directory the flutter_assets directory, located in the build directory of your Flutter project.
  8. Finally, copy the icudtl.dat file located in the bin\cache\artifacts\engine\windows-x64 (on Windows), bin/cache/artifacts/engine/linux-x64 (on Linux) or bin/cache/artifacts/engine/darwin-x64 (on macOS) path from your Flutter installation to the application directory.
  9. On macOS, it may be necessary to package the directory according to the platform standards so that a terminal is not shown along with the application.

Now you can distribute your application and install it in environments without installing Flutter along with it.


Troubleshooting

If you experience some problem while performing step 8 of running your own project guide (Go GLFW library) in a Linux environment, resulting in a message similar to the one below, you can ignore it. These are only warnings that do not cause any problem.

# github.com/go-gl/glfw/v3.2/glfw In file included from ../../go-gl/glfw/v3.2/glfw/c_glfw_linbsd.go:24:0: ../../go-gl/glfw/v3.2/glfw/glfw/src/linux_joystick.c: In function ‘_glfwInitJoysticksLinux’: ../../go-gl/glfw/v3.2/glfw/glfw/src/linux_joystick.c:224:42: warning: ‘%s’ directive output may be truncated writing up to 255 bytes into a region of size 9 [-Wformat-truncation=] snprintf(path, sizeof(path), “%s/%s”, dirname, entry->d_name); ^~~~~~~ In file included from /usr/include/stdio.h:862:0, from /usr/include/X11/Xcursor/Xcursor.h:26, from ../../go-gl/glfw/v3.2/glfw/glfw/src/x11_platform.h:39, from ../../go-gl/glfw/v3.2/glfw/glfw/src/internal.h:169, from ../../go-gl/glfw/v3.2/glfw/glfw/src/x11_init.c:28, from ../../go-gl/glfw/v3.2/glfw/c_glfw_linbsd.go:19: /usr/include/x86_64-linux-gnu/bits/stdio2.h:64:10: note: ‘__builtin___snprintf_chk’ output between 12 and 267 bytes into a destination of size 20 return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL — 1, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __bos (__s), __fmt, __va_arg_pack ()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Conclusion

The two projects presented in this article allow applications developed with the Flutter framework to be run in desktop environments. The first is developed by Google itself, but does not offer support. The second allows for both greater ease in running applications built on Flutter and desktop applications as well as greater familiarity for developers working with the Go (Golang) programming language, also made by Google.

For cases where an application should be developed for desktop and mobile environments, so that the code can be reused, the two projects presented in this article are great solutions.

For questions, leave your comment. I will answer as soon as possible.

Thanks for reading!


Flutter Community

Articles and Stories from the Flutter Community

Marcelo Henrique Neppel

Written by

Fullstack Dart/Flutter — Backend Go & Rust — https://github.com/marceloneppel

Flutter Community

Articles and Stories from the Flutter Community