Update GLFW embedding to support AOT mode (flutter/engine#18423)

Unblocks: flutter/flutter#57135

Part of https://github.com/flutter/flutter/issues/38478
This commit is contained in:
Marcus Tomlinson 2020-05-29 01:53:54 +01:00 committed by GitHub
parent db630fbd93
commit 4bc087feb8
6 changed files with 80 additions and 7 deletions

View File

@ -15,7 +15,8 @@ FlutterEngine::~FlutterEngine() {}
bool FlutterEngine::Start(const std::string& icu_data_path,
const std::string& assets_path,
const std::vector<std::string>& arguments) {
const std::vector<std::string>& arguments,
const std::string& aot_library_path) {
if (engine_) {
std::cerr << "Cannot run an already running engine. Create a new instance "
"or call ShutDown first."
@ -26,6 +27,7 @@ bool FlutterEngine::Start(const std::string& icu_data_path,
FlutterDesktopEngineProperties c_engine_properties = {};
c_engine_properties.assets_path = assets_path.c_str();
c_engine_properties.icu_data_path = icu_data_path.c_str();
c_engine_properties.aot_library_path = aot_library_path.c_str();
std::vector<const char*> engine_switches;
std::transform(
arguments.begin(), arguments.end(), std::back_inserter(engine_switches),

View File

@ -27,7 +27,8 @@ FlutterWindowController::~FlutterWindowController() {
bool FlutterWindowController::CreateWindow(
const WindowProperties& window_properties,
const std::string& assets_path,
const std::vector<std::string>& arguments) {
const std::vector<std::string>& arguments,
const std::string& aot_library_path) {
if (!init_succeeded_) {
std::cerr << "Could not create window; FlutterDesktopInit failed."
<< std::endl;
@ -47,6 +48,7 @@ bool FlutterWindowController::CreateWindow(
FlutterDesktopEngineProperties c_engine_properties = {};
c_engine_properties.assets_path = assets_path.c_str();
c_engine_properties.aot_library_path = aot_library_path.c_str();
c_engine_properties.icu_data_path = icu_data_path_.c_str();
std::vector<const char*> engine_switches;
std::transform(

View File

@ -32,7 +32,8 @@ class FlutterEngine : public PluginRegistry {
// successful.
bool Start(const std::string& icu_data_path,
const std::string& assets_path,
const std::vector<std::string>& arguments);
const std::vector<std::string>& arguments,
const std::string& aot_library_path = "");
// Terminates the running engine.
void ShutDown();

View File

@ -46,6 +46,9 @@ class FlutterWindowController : public PluginRegistry {
// There must be only one instance of this class in an application at any
// given time, as Flutter does not support multiple engines in one process,
// or multiple views in one engine.
//
// |icu_data_path| is the path to the icudtl.dat file for the version of
// Flutter you are using.
explicit FlutterWindowController(const std::string& icu_data_path);
virtual ~FlutterWindowController();
@ -57,17 +60,21 @@ class FlutterWindowController : public PluginRegistry {
// Creates and displays a window for displaying Flutter content.
//
// The |assets_path| is the path to the flutter_assets folder for the Flutter
// application to be run. |icu_data_path| is the path to the icudtl.dat file
// for the version of Flutter you are using.
// application to be run.
//
// The |arguments| are passed to the Flutter engine. See:
// https://github.com/flutter/engine/blob/master/shell/common/switches.h for
// for details. Not all arguments will apply to desktop.
//
// The |aot_library_path| is the path to the libapp.so file for the Flutter
// application to be run. While this parameter is only required in AOT mode,
// it is perfectly safe to provide the path in non-AOT mode too.
//
// Only one Flutter window can exist at a time; see constructor comment.
bool CreateWindow(const WindowProperties& window_properties,
const std::string& assets_path,
const std::vector<std::string>& arguments);
const std::vector<std::string>& arguments,
const std::string& aot_library_path = "");
// Destroys the current window, if any.
//

View File

@ -91,6 +91,15 @@ struct FlutterDesktopWindow {
bool skip_next_window_refresh = false;
};
// Custom deleter for FlutterEngineAOTData.
struct AOTDataDeleter {
void operator()(FlutterEngineAOTData aot_data) {
FlutterEngineCollectAOTData(aot_data);
}
};
using UniqueAotDataPtr = std::unique_ptr<_FlutterEngineAOTData, AOTDataDeleter>;
// Struct for storing state of a Flutter engine instance.
struct FlutterDesktopEngineState {
// The handle to the Flutter engine instance.
@ -117,6 +126,9 @@ struct FlutterDesktopEngineState {
// The controller associated with this engine instance, if any.
// This will always be null for a headless engine.
FlutterDesktopWindowControllerState* window_controller = nullptr;
// AOT data for this engine instance, if applicable.
UniqueAotDataPtr aot_data = nullptr;
};
// State associated with the plugin registrar.
@ -550,6 +562,33 @@ static void GLFWErrorCallback(int error_code, const char* description) {
std::cerr << "GLFW error " << error_code << ": " << description << std::endl;
}
// Attempts to load AOT data from the given path, which must be absolute and
// non-empty. Logs and returns nullptr on failure.
UniqueAotDataPtr LoadAotData(std::filesystem::path aot_data_path) {
if (aot_data_path.empty()) {
std::cerr
<< "Attempted to load AOT data, but no aot_data_path was provided."
<< std::endl;
return nullptr;
}
if (!std::filesystem::exists(aot_data_path)) {
std::cerr << "Can't load AOT data from " << aot_data_path.u8string()
<< "; no such file." << std::endl;
return nullptr;
}
std::string path_string = aot_data_path.u8string();
FlutterEngineAOTDataSource source = {};
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
source.elf_path = path_string.c_str();
FlutterEngineAOTData data = nullptr;
auto result = FlutterEngineCreateAOTData(&source, &data);
if (result != kSuccess) {
std::cerr << "Failed to load AOT data from: " << path_string << std::endl;
return nullptr;
}
return UniqueAotDataPtr(data);
}
// Starts an instance of the Flutter Engine.
//
// Configures the engine according to |engine_propreties| and using |event_loop|
@ -574,7 +613,10 @@ static bool RunFlutterEngine(
std::filesystem::u8path(engine_properties.assets_path);
std::filesystem::path icu_path =
std::filesystem::u8path(engine_properties.icu_data_path);
if (assets_path.is_relative() || icu_path.is_relative()) {
std::filesystem::path aot_library_path =
std::filesystem::u8path(engine_properties.aot_library_path);
if (assets_path.is_relative() || icu_path.is_relative() ||
(!aot_library_path.empty() && aot_library_path.is_relative())) {
// Treat relative paths as relative to the directory of this executable.
std::filesystem::path executable_location =
flutter::GetExecutableDirectory();
@ -585,9 +627,14 @@ static bool RunFlutterEngine(
}
assets_path = std::filesystem::path(executable_location) / assets_path;
icu_path = std::filesystem::path(executable_location) / icu_path;
if (!aot_library_path.empty()) {
aot_library_path =
std::filesystem::path(executable_location) / aot_library_path;
}
}
std::string assets_path_string = assets_path.u8string();
std::string icu_path_string = icu_path.u8string();
std::string lib_path_string = aot_library_path.u8string();
// Configure a task runner using the event loop.
engine_state->event_loop = std::move(event_loop);
@ -618,6 +665,16 @@ static bool RunFlutterEngine(
args.command_line_argv = &argv[0];
args.platform_message_callback = EngineOnFlutterPlatformMessage;
args.custom_task_runners = &task_runners;
if (FlutterEngineRunsAOTCompiledDartCode()) {
engine_state->aot_data = LoadAotData(lib_path_string);
if (!engine_state->aot_data) {
std::cerr << "Unable to start engine without AOT data." << std::endl;
return false;
}
args.aot_data = engine_state->aot_data.get();
}
FLUTTER_API_SYMBOL(FlutterEngine) engine = nullptr;
auto result = FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args,
engine_state, &engine);

View File

@ -45,6 +45,10 @@ typedef struct {
// This can either be an absolute path, or on Windows or Linux, a path
// relative to the directory containing the executable.
const char* icu_data_path;
// The path to the libapp.so file for the application to be run.
// This can either be an absolute path or a path relative to the directory
// containing the executable.
const char* aot_library_path;
// The switches to pass to the Flutter engine.
//
// See: https://github.com/flutter/engine/blob/master/shell/common/switches.h