mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
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:
parent
db630fbd93
commit
4bc087feb8
@ -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),
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
//
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user