Update Linux template for headless mode (#56618)
diff --git a/packages/flutter_tools/templates/app/linux.tmpl/Makefile b/packages/flutter_tools/templates/app/linux.tmpl/Makefile
index c27a1ad..2a3e5ba 100644
--- a/packages/flutter_tools/templates/app/linux.tmpl/Makefile
+++ b/packages/flutter_tools/templates/app/linux.tmpl/Makefile
@@ -49,6 +49,7 @@
# issues if they start with one or more '../'s.
WRAPPER_ROOT=$(abspath $(FLUTTER_EPHEMERAL_DIR)/cpp_client_wrapper_glfw)
WRAPPER_SOURCES= \
+ $(WRAPPER_ROOT)/flutter_engine.cc \
$(WRAPPER_ROOT)/flutter_window_controller.cc \
$(WRAPPER_ROOT)/plugin_registrar.cc \
$(WRAPPER_ROOT)/engine_method_result.cc
diff --git a/packages/flutter_tools/templates/app/linux.tmpl/main.cc b/packages/flutter_tools/templates/app/linux.tmpl/main.cc
index 47b0343..e92332d 100644
--- a/packages/flutter_tools/templates/app/linux.tmpl/main.cc
+++ b/packages/flutter_tools/templates/app/linux.tmpl/main.cc
@@ -1,3 +1,4 @@
+#include <flutter/flutter_engine.h>
#include <flutter/flutter_window_controller.h>
#include <linux/limits.h>
#include <unistd.h>
@@ -12,34 +13,22 @@
namespace {
-// Returns the path of the directory containing this executable, or an empty
-// string if the directory cannot be found.
-std::string GetExecutableDirectory() {
- char buffer[PATH_MAX + 1];
- ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
- if (length > PATH_MAX) {
- std::cerr << "Couldn't locate executable" << std::endl;
- return "";
+// Runs the application in headless mode, without a window.
+void RunHeadless(const std::string& icu_data_path,
+ const std::string& assets_path,
+ const std::vector<std::string>& arguments) {
+ flutter::FlutterEngine engine;
+ engine.Start(icu_data_path, assets_path, arguments);
+ RegisterPlugins(&engine);
+ while (true) {
+ engine.RunEventLoopWithTimeout();
}
- std::string executable_path(buffer, length);
- size_t last_separator_position = executable_path.find_last_of('/');
- if (last_separator_position == std::string::npos) {
- std::cerr << "Unabled to find parent directory of " << executable_path
- << std::endl;
- return "";
- }
- return executable_path.substr(0, last_separator_position);
}
} // namespace
int main(int argc, char **argv) {
- // Resources are located relative to the executable.
- std::string base_directory = GetExecutableDirectory();
- if (base_directory.empty()) {
- base_directory = ".";
- }
- std::string data_directory = base_directory + "/data";
+ std::string data_directory = "data";
std::string assets_path = data_directory + "/flutter_assets";
std::string icu_data_path = data_directory + "/icudtl.dat";
@@ -55,13 +44,17 @@
// Start the engine.
if (!flutter_controller.CreateWindow(window_properties, assets_path,
arguments)) {
+ if (getenv("DISPLAY") == nullptr) {
+ std::cout << "No DISPLAY; falling back to headless mode." << std::endl;
+ RunHeadless(icu_data_path, assets_path, arguments);
+ return EXIT_SUCCESS;
+ }
return EXIT_FAILURE;
}
RegisterPlugins(&flutter_controller);
// Run until the window is closed.
- while (flutter_controller.RunEventLoopWithTimeout(
- std::chrono::milliseconds::max())) {
+ while (flutter_controller.RunEventLoopWithTimeout()) {
}
return EXIT_SUCCESS;
}