From 732c6c9beb7c3b605a58f0b5f86b8046ec11f222 Mon Sep 17 00:00:00 2001 From: Losses Don <1384036+Losses@users.noreply.github.com> Date: Sat, 14 Sep 2024 20:02:23 +0800 Subject: [PATCH 1/7] fix: Unable to build plugins with ffi --- lib/elinux_plugins.dart | 92 ++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/lib/elinux_plugins.dart b/lib/elinux_plugins.dart index 946d77b..9c1a41f 100644 --- a/lib/elinux_plugins.dart +++ b/lib/elinux_plugins.dart @@ -99,6 +99,21 @@ class ELinuxPlugin extends PluginPlatform implements NativeOrDartPlugin { } String get path => directory.parent.path; + + /// Method to return a detailed debug string for the plugin. + @override + String toString() { + return ''' +ELinuxPlugin: + name: $name + directory: ${directory.path} + pluginClass: $pluginClass + dartPluginClass: $dartPluginClass + ffiPlugin: $ffiPlugin + defaultPackage: $defaultPackage + dependencies: ${dependencies?.join(', ')} +'''; + } } /// Source: [_internalCapitalLetterRegex] in `platform_plugins.dart` (exact copy) @@ -426,12 +441,20 @@ Future> findELinuxPlugins( final ELinuxPlugin? plugin = _pluginFromPackage(package.name, packageRoot); if (plugin == null) { continue; - } else if (nativeOnly && - (plugin.pluginClass == null || plugin.pluginClass == 'none')) { + } + + final bool isFfi = plugin.ffiPlugin ?? false; + + if (nativeOnly && + ((plugin.pluginClass == null || plugin.pluginClass == 'none') && + !isFfi)) { continue; - } else if (dartOnly && plugin.dartPluginClass == null) { + } + + if (dartOnly && (plugin.dartPluginClass == null || isFfi)) { continue; } + plugins.add(plugin); } return plugins; @@ -513,18 +536,45 @@ void registerPlugins() { ); } +/// Filters out any plugins that don't use method channels, and thus shouldn't be added to the native generated registrants. +List _filterMethodChannelPlugins(List plugins) { + return plugins.where((ELinuxPlugin plugin) { + return (plugin as NativeOrDartPlugin).hasMethodChannel(); + }).toList(); +} + +/// Filters out Dart-only and method channel plugins. +/// +/// FFI plugins do not need native code registration, but their binaries need to be bundled. +List _filterFfiPlugins(List plugins) { + return plugins.where((ELinuxPlugin plugin) { + final NativeOrDartPlugin plugin_ = plugin as NativeOrDartPlugin; + return plugin_.hasFfi(); + }).toList(); +} + /// See: [_writeWindowsPluginFiles] in `plugins.dart` void _writePluginCmakefileTemplate( ELinuxProject eLinuxProject, Directory registryDirectory, List plugins, ) { - final List> pluginConfigs = - plugins.map((ELinuxPlugin plugin) => plugin.toMap()).toList(); + final List methodChannelPlugins = + _filterMethodChannelPlugins(plugins); + final List ffiPlugins = _filterFfiPlugins(plugins) + ..removeWhere(methodChannelPlugins.contains); + + final List> methodChannelPluginsMap = + methodChannelPlugins.map((ELinuxPlugin plugin) => plugin.toMap()).toList(); + final List> ffiPluginsMap = + ffiPlugins.map((ELinuxPlugin plugin) => plugin.toMap()).toList(); + final Map context = { - 'plugins': pluginConfigs, + 'methodChannelPlugins': methodChannelPluginsMap, + 'ffiPlugins': ffiPluginsMap, 'pluginsDir': _cmakeRelativePluginSymlinkDirectoryPath(eLinuxProject), }; + _renderTemplateToFile( ''' // @@ -547,22 +597,23 @@ void RegisterPlugins(flutter::PluginRegistry* registry); _renderTemplateToFile( ''' // -// Generated file. Do not edit. +// Generated file. Do not edit. // // clang-format off #include "generated_plugin_registrant.h" -{{#plugins}} +{{#methodChannelPlugins}} #include <{{name}}/{{filename}}.h> -{{/plugins}} +{{/methodChannelPlugins}} void RegisterPlugins(flutter::PluginRegistry* registry) { -{{#plugins}} - {{class}}RegisterWithRegistrar( - registry->GetRegistrarForPlugin("{{class}}")); -{{/plugins}} +{{#methodChannelPlugins}} + g_autoptr(FlPluginRegistrar) {{name}}_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "{{class}}"); + {{filename}}_register_with_registrar({{name}}_registrar); +{{/methodChannelPlugins}} } ''', context, @@ -575,9 +626,15 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { # list(APPEND FLUTTER_PLUGIN_LIST -{{#plugins}} +{{#methodChannelPlugins}} {{name}} -{{/plugins}} +{{/methodChannelPlugins}} +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +{{#ffiPlugins}} + {{name}} +{{/ffiPlugins}} ) set(PLUGIN_BUNDLED_LIBRARIES) @@ -588,6 +645,11 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST}) list(APPEND PLUGIN_BUNDLED_LIBRARIES $) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory({{pluginsDir}}/${ffi_plugin}/elinux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) ''', context, registryDirectory.childFile('generated_plugins.cmake').path, From be9854e9c88d778db77801369d70da9da33927ff Mon Sep 17 00:00:00 2001 From: LOSSES Don <1384036+Losses@users.noreply.github.com> Date: Sun, 15 Sep 2024 00:48:00 +0000 Subject: [PATCH 2/7] fix: Format issue --- lib/elinux_plugins.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/elinux_plugins.dart b/lib/elinux_plugins.dart index 9c1a41f..5d4e64b 100644 --- a/lib/elinux_plugins.dart +++ b/lib/elinux_plugins.dart @@ -565,7 +565,9 @@ void _writePluginCmakefileTemplate( ..removeWhere(methodChannelPlugins.contains); final List> methodChannelPluginsMap = - methodChannelPlugins.map((ELinuxPlugin plugin) => plugin.toMap()).toList(); + methodChannelPlugins + .map((ELinuxPlugin plugin) => plugin.toMap()) + .toList(); final List> ffiPluginsMap = ffiPlugins.map((ELinuxPlugin plugin) => plugin.toMap()).toList(); From a351b5b6e00ccd605a75489a5a02af20b868d32e Mon Sep 17 00:00:00 2001 From: LOSSES Don <1384036+Losses@users.noreply.github.com> Date: Sun, 15 Sep 2024 05:33:53 +0000 Subject: [PATCH 3/7] fix: Fix plugin interfaces issue --- lib/elinux_plugins.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/elinux_plugins.dart b/lib/elinux_plugins.dart index 5d4e64b..2463dad 100644 --- a/lib/elinux_plugins.dart +++ b/lib/elinux_plugins.dart @@ -612,9 +612,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry); void RegisterPlugins(flutter::PluginRegistry* registry) { {{#methodChannelPlugins}} - g_autoptr(FlPluginRegistrar) {{name}}_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "{{class}}"); - {{filename}}_register_with_registrar({{name}}_registrar); + {{class}}RegisterWithRegistrar( + registry->GetRegistrarForPlugin("{{class}}")); {{/methodChannelPlugins}} } ''', From 01586ca61fbdb9952336226a65c21f18f20e4033 Mon Sep 17 00:00:00 2001 From: Losses Don <1384036+Losses@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:23:36 +0800 Subject: [PATCH 4/7] fix: CC and CXX are overwritten and void the system config --- lib/elinux_build_target.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/elinux_build_target.dart b/lib/elinux_build_target.dart index 1ffb44b..e11798e 100644 --- a/lib/elinux_build_target.dart +++ b/lib/elinux_build_target.dart @@ -384,12 +384,6 @@ class NativeBundle { eLinuxDir.path, ], workingDirectory: outputDir.path, - environment: (targetToolchain == null) - ? {'CC': 'clang', 'CXX': 'clang++'} - : { - 'CC': '$targetToolchain/bin/clang', - 'CXX': '$targetToolchain/bin/clang++' - }, ); if (result.exitCode != 0) { throwToolExit('Failed to cmake:\n$result'); From 1df2296fc73a0f66754224aca0b9ea6165970f78 Mon Sep 17 00:00:00 2001 From: Losses Don <1384036+Losses@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:16:53 +0800 Subject: [PATCH 5/7] fix: Fix cross-platform compilation issues on certain OSes by supporting diverse compiler invocation commands This commit addresses the issue where certain operating systems (e.g., NixOS) were unable to complete cross-platform compilation. The current implementation assumes that all clang and clang++ invocations are done using specific commands. However, in reality, the invocation of these compilers can vary. For example, on NixOS, the compiler commands are actually: `aarch64-unknown-linux-gnu-clang` and `aarch64-unknown-linux-gnu-clang++`. To resolve this, we should respect the original environment variable settings and allow users to determine the binary names provided by their distribution. This adjustment improves our support for different operating systems and compilation environments, enhancing the cross-platform compatibility of the project. --- lib/elinux_build_target.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/elinux_build_target.dart b/lib/elinux_build_target.dart index e11798e..6162966 100644 --- a/lib/elinux_build_target.dart +++ b/lib/elinux_build_target.dart @@ -402,6 +402,7 @@ class NativeBundle { numProc, ], workingDirectory: outputDir.path, + environment: _buildCMakeEnvironment(targetToolchain), ); if (result.exitCode != 0) { throwToolExit('Failed to cmake build:\n$result'); @@ -426,6 +427,18 @@ class NativeBundle { } } +Map _buildCMakeEnvironment(String? targetToolchain) { + final String? ccEnv = Platform.environment['CC']; + final String? cxxEnv = Platform.environment['CXX']; + + final String cc = ccEnv ?? + (targetToolchain != null ? '$targetToolchain/bin/clang' : 'clang'); + final String cxx = cxxEnv ?? + (targetToolchain != null ? '$targetToolchain/bin/clang++' : 'clang++'); + + return {'CC': cc, 'CXX': cxx}; +} + String _getCurrentHostPlatformArchName() { final HostPlatform hostPlatform = getCurrentHostPlatform(); return hostPlatform.platformName; From 5175f17f1b6eddbe445084b0e91e22f00a321fdf Mon Sep 17 00:00:00 2001 From: Losses Don <1384036+Losses@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:24:02 +0800 Subject: [PATCH 6/7] fix(cmake): Resolve cross-compilation package directory issues This commit added necessary configurations to `CMakeLists.txt` to ensure the correct discovery of package directories during cross-compilation. This includes: - Finding and linking required packages: Fontconfig, X11 with xkbcommon, and OpenGL with EGL. - Utilizing pkg-config to locate Wayland libraries: wayland-egl, wayland-client, and wayland-cursor. - Linking these dependencies to the flutter target. - Including the necessary directories for these dependencies. These changes address the issue where the build system could not correctly locate package directories during cross-compilation, thereby ensuring a successful build process. --- templates/app/flutter/CMakeLists.txt | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/templates/app/flutter/CMakeLists.txt b/templates/app/flutter/CMakeLists.txt index f141a3c..fc327ab 100644 --- a/templates/app/flutter/CMakeLists.txt +++ b/templates/app/flutter/CMakeLists.txt @@ -54,6 +54,35 @@ target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE "${FLUTTER_EMBEDDER_LIBRARY}") add_dependencies(flutter flutter_assemble) +# === Find Dependencies === +find_package(Fontconfig REQUIRED) +find_package(X11 REQUIRED xkbcommon) +find_package(OpenGL REQUIRED COMPONENTS EGL) + +# Use pkg-config to find Wayland libraries +find_package(PkgConfig REQUIRED) +pkg_check_modules(WAYLAND_EGL REQUIRED wayland-egl) +pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client) +pkg_check_modules(WAYLAND_CURSOR REQUIRED wayland-cursor) + +# Link the dependencies to the flutter target +target_link_libraries(flutter INTERFACE + Fontconfig::Fontconfig + X11::xkbcommon + OpenGL::EGL + ${WAYLAND_EGL_LIBRARIES} + ${WAYLAND_CLIENT_LIBRARIES} + ${WAYLAND_CURSOR_LIBRARIES} +) + +# Include directories for the dependencies +target_include_directories(flutter INTERFACE + ${X11_INCLUDE_DIR} + ${WAYLAND_EGL_INCLUDE_DIRS} + ${WAYLAND_CLIENT_INCLUDE_DIRS} + ${WAYLAND_CURSOR_INCLUDE_DIRS} +) + # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE "core_implementations.cc" From fbe5d92863a371ce6fccb9dfdff9e4b20b81ab14 Mon Sep 17 00:00:00 2001 From: Losses Don <1384036+Losses@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:30:24 +0800 Subject: [PATCH 7/7] fix: Oops --- lib/elinux_build_target.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elinux_build_target.dart b/lib/elinux_build_target.dart index 6162966..030d0f0 100644 --- a/lib/elinux_build_target.dart +++ b/lib/elinux_build_target.dart @@ -384,6 +384,7 @@ class NativeBundle { eLinuxDir.path, ], workingDirectory: outputDir.path, + environment: _buildCMakeEnvironment(targetToolchain), ); if (result.exitCode != 0) { throwToolExit('Failed to cmake:\n$result'); @@ -402,7 +403,6 @@ class NativeBundle { numProc, ], workingDirectory: outputDir.path, - environment: _buildCMakeEnvironment(targetToolchain), ); if (result.exitCode != 0) { throwToolExit('Failed to cmake build:\n$result');