Undefined reference while compiling Flutter app on Linux

Issue

I built a plugin which uses Dart FFI and a shared lib and published to pub.dev. Whenever I try using the plugin in my app, it always fails with a file not found error and I don’t know where the error is coming from.

Error:

[        ] [        ] origin/stable
[        ] [        ] executing: [/home/francis/Development/flutter/] git ls-remote --get-url origin
[        ] [  +10 ms] Exit code 0 from: git ls-remote --get-url origin
[        ] [        ] https://github.com/flutter/flutter.git
[        ] [ +160 ms] executing: [/home/francis/Development/flutter/] git rev-parse --abbrev-ref HEAD
[        ] [  +12 ms] Exit code 0 from: git rev-parse --abbrev-ref HEAD
[        ] [        ] stable
[        ] [ +139 ms] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[        ] [   +6 ms] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'WindowsUwpEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[        ] [ +212 ms] Artifact Instance of 'MaterialFonts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'GradleWrapper' is not required, skipping update.
[        ] [        ] Artifact Instance of 'AndroidGenSnapshotArtifacts' is not required, skipping update.
[   +9 ms] [        ] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterSdk' is not required, skipping update.
[        ] [        ] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'WindowsUwpEngineArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[        ] [   +3 ms] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'IosUsbArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'FontSubsetArtifacts' is not required, skipping update.
[        ] [        ] Artifact Instance of 'PubDependencies' is not required, skipping update.
[   +1 ms] [  +96 ms] Initializing file store
[        ] [  +28 ms] Done initializing file store
[        ] [  +96 ms] Skipping target: gen_localizations
[        ] [  +16 ms] Skipping target: gen_dart_plugin_registrant
[        ] [+1046 ms] Skipping target: unpack_linux
[        ] [ +989 ms] Skipping target: kernel_snapshot
[        ] [ +391 ms] Skipping target: debug_bundle_linux-x64_assets
[        ] [        ] Persisting file store
[        ] [  +19 ms] Done persisting file store
[        ] [   +7 ms] build succeeded.
[        ] [  +11 ms] "flutter assemble" took 2,983ms.
[        ] [ +260 ms] ensureAnalyticsSent: 255ms
[        ] [   +2 ms] Running shutdown hooks
[        ] [        ] Shutdown hooks complete
[        ] [   +1 ms] exiting with code 0
[ +922 ms] [2/5] Building CXX object CMakeFiles/dspace.dir/flutter/generated_plugin_registrant.cc.o
[   +1 ms] FAILED: CMakeFiles/dspace.dir/flutter/generated_plugin_registrant.cc.o 
[   +5 ms] /usr/bin/clang++ -DAPPLICATION_ID=\"com.example.dspace\"
-I/home/francis/AndroidStudioProjects/dspace/linux/flutter/ephemeral
-I/home/francis/AndroidStudioProjects/dspace/linux/flutter/ephemeral/.plugin_symlinks/size/linux/src -isystem
/usr/include/gtk-3.0 -isystem /usr/include/pango-1.0 -isystem /usr/include/glib-2.0 -isystem
/usr/lib/glib-2.0/include -isystem /usr/include/harfbuzz -isystem /usr/include/freetype2 -isystem
/usr/include/libpng16 -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem
/usr/include/fribidi -isystem /usr/include/cairo -isystem /usr/include/lzo -isystem /usr/include/pixman-1
-isystem /usr/include/gdk-pixbuf-2.0 -isystem /usr/include/gio-unix-2.0 -isystem /usr/include/cloudproviders
-isystem /usr/include/atk-1.0 -isystem /usr/include/at-spi2-atk/2.0 -isystem /usr/include/dbus-1.0 -isystem
/usr/lib/dbus-1.0/include -isystem /usr/include/at-spi-2.0 -g -Wall -Werror -pthread -std=gnu++17 -MD -MT
CMakeFiles/dspace.dir/flutter/generated_plugin_registrant.cc.o -MF
CMakeFiles/dspace.dir/flutter/generated_plugin_registrant.cc.o.d -o
CMakeFiles/dspace.dir/flutter/generated_plugin_registrant.cc.o -c
/home/francis/AndroidStudioProjects/dspace/linux/flutter/generated_plugin_registrant.cc
[  +14 ms] /home/francis/AndroidStudioProjects/dspace/linux/flutter/generated_plugin_registrant.cc:9:10:
fatal error: 'size/size_plugin.h' file not found
[   +1 ms] #include <size/size_plugin.h>
[        ]          ^~~~~~~~~~~~~~~~~~~~
[        ] 1 error generated.
[ +417 ms] [3/5] Building CXX object CMakeFiles/dspace.dir/my_application.cc.o
[   +2 ms] ninja: build stopped: subcommand failed.
[  +42 ms] Building Linux application... (completed in 6.8s)
[+6533 ms] Exception: Build process failed
[   +4 ms] "flutter run" took 13,967ms.
[  +18 ms] 
           #0      throwToolExit (package:flutter_tools/src/base/common.dart:10:3)
           #1      RunCommand.runCommand (package:flutter_tools/src/commands/run.dart:669:9)
           <asynchronous suspension>
           #2      FlutterCommand.run.<anonymous closure>
           (package:flutter_tools/src/runner/flutter_command.dart:1125:27)
           <asynchronous suspension>
           #3      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
           <asynchronous suspension>
           #4      CommandRunner.runCommand (package:args/command_runner.dart:209:13)
           <asynchronous suspension>
           #5      FlutterCommandRunner.runCommand.<anonymous closure>
           (package:flutter_tools/src/runner/flutter_command_runner.dart:288:9)
           <asynchronous suspension>
           #6      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
           <asynchronous suspension>
           #7      FlutterCommandRunner.runCommand
(package:flutter_tools/src/runner/flutter_command_runner.dart:236:5)
           <asynchronous suspension>
           #8      run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:62:9)
           <asynchronous suspension>
           #9      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
           <asynchronous suspension>
           #10     main (package:flutter_tools/executable.dart:92:3)
           <asynchronous suspension>
           
           
[ +260 ms] ensureAnalyticsSent: 254ms
[   +1 ms] Running shutdown hooks
[        ] Shutdown hooks complete
[        ] exiting with code 1

I’ve modified my cmake file severally to fix this and tried various include methods but to no avail.
Current cmake:

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17) # Use C++17 lib
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1)
#set(CMAKE_BUILD_TYPE RELEASE)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
project(size_plugin VERSION 1.0.0 LANGUAGES CXX)
set(PLUGIN_NAME "size_plugin")
set(HEADER_FILES "src/size_plugin.h")
set(SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/size_plugin.cc")
message(${FLUTTER_MANAGED_DIR})
message(${HEADER_FILES} ${CMAKE_SOURCE_DIR})
#add_library(size SHARED src/fsize.cpp)
add_library(${PLUGIN_NAME} SHARED
  ${HEADER_FILES}
  ${SOURCE_FILES}  
)
apply_standard_settings(${PLUGIN_NAME})
#target_include_directories(${PLUGIN_NAME} INTERFACE ${HEADER_FILES})
target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)

#add_executable(size_test src/fsize.cpp)

My pubspec

name: size
description: A simple plugin that can display disk size on desktop.
version: 1.0.3
repository: https://github.com/Clashkid155/size
issue_tracker: https://github.com/Clashkid155/size/issues
# homepage: https://www.example.com

environment:
  sdk: '>=2.14.3 <3.0.0'
  flutter: '>=1.20.0 '
flutter:
  plugin:
    platforms:
      linux:
        pluginClass: SizePlugin
      windows:
        pluginClass: SizePlugin

dependencies:
  ffi: ^1.1.2
  path: ^1.8.0

Every info provided is from my plugin and not the flutter app am trying to build cause the whole issue started when i add that plugin

I’ve been using this as reference.
My only option now is to rebuild the plugin using method channel as that was the first iteration of the plugin but i didn’t what to depend on flutter and dart FFI was easier with less code needed.

Update:
I’ve solved the above error by regenerating the plugin as a flutter plugin which added the missing file.
Now I’ve another build error

[  +71 ms] [4/7] Building CXX object CMakeFiles/dspace.dir/my_application.cc.o
[  +91 ms] [5/7] Linking CXX shared library plugins/size/libsize_plugin.so
[ +255 ms] [6/7] Linking CXX executable intermediates_do_not_run/dspace
[        ] FAILED: intermediates_do_not_run/dspace 
[   +2 ms] : && /usr/bin/clang++ -g  CMakeFiles/dspace.dir/main.cc.o
CMakeFiles/dspace.dir/my_application.cc.o CMakeFiles/dspace.dir/flutter/generated_plugin_registrant.cc.o -o
intermediates_do_not_run/dspace
-Wl,-rpath,/home/francis/AndroidStudioProjects/dspace/build/linux/x64/debug/plugins/size:/home/francis/Androi
dStudioProjects/dspace/linux/flutter/ephemeral:  plugins/size/libsize_plugin.so
/home/francis/AndroidStudioProjects/dspace/linux/flutter/ephemeral/libflutter_linux_gtk.so
/usr/lib/libgtk-3.so  /usr/lib/libgdk-3.so  /usr/lib/libz.so  /usr/lib/libpangocairo-1.0.so
/usr/lib/libpango-1.0.so  /usr/lib/libharfbuzz.so  /usr/lib/libatk-1.0.so  /usr/lib/libcairo-gobject.so
/usr/lib/libcairo.so  /usr/lib/libgdk_pixbuf-2.0.so  /usr/lib/libgio-2.0.so  /usr/lib/libgobject-2.0.so
/usr/lib/libglib-2.0.so && :
[   +1 ms] /usr/bin/ld: CMakeFiles/dspace.dir/flutter/generated_plugin_registrant.cc.o: in function
`fl_register_plugins(_FlPluginRegistry*)':
[        ] /home/francis/AndroidStudioProjects/dspace/linux/flutter/generated_plugin_registrant.cc:14:
undefined reference to `size_plugin_register_with_registrar'
[   +1 ms] clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
[   +4 ms] ninja: build stopped: subcommand failed.
[  +26 ms] Building Linux application... (completed in 26.1s)
[   +1 ms] Exception: Build process failed
[   +2 ms] "flutter run" took 26,807ms.
[   +6 ms] 
           #0      throwToolExit (package:flutter_tools/src/base/common.dart:10:3)
           #1      RunCommand.runCommand (package:flutter_tools/src/commands/run.dart:669:9)
           <asynchronous suspension>
           #2      FlutterCommand.run.<anonymous closure>
           (package:flutter_tools/src/runner/flutter_command.dart:1125:27)
           <asynchronous suspension>
           #3      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
           <asynchronous suspension>
           #4      CommandRunner.runCommand (package:args/command_runner.dart:209:13)
           <asynchronous suspension>
           #5      FlutterCommandRunner.runCommand.<anonymous closure>
           (package:flutter_tools/src/runner/flutter_command_runner.dart:288:9)
           <asynchronous suspension>
           #6      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
           <asynchronous suspension>
           #7      FlutterCommandRunner.runCommand
(package:flutter_tools/src/runner/flutter_command_runner.dart:236:5)
           <asynchronous suspension>
           #8      run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:62:9)
           <asynchronous suspension>
           #9      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
           <asynchronous suspension>
           #10     main (package:flutter_tools/executable.dart:92:3)
           <asynchronous suspension>
           
           
[ +257 ms] ensureAnalyticsSent: 253ms
[   +2 ms] Running shutdown hooks
[        ] Shutdown hooks complete
[        ] exiting with code 1

Content of generated_plugin_registrant.cc

//
//  Generated file. Do not edit.
//

// clang-format off

#include "generated_plugin_registrant.h"

#include <size/size_plugin.h>

void fl_register_plugins(FlPluginRegistry* registry) {
  g_autoptr(FlPluginRegistrar) size_registrar =
      fl_plugin_registry_get_registrar_for_plugin(registry, "SizePlugin");
  size_plugin_register_with_registrar(size_registrar);
}

Content of size_plugin.h

#ifndef FLUTTER_PLUGIN_SIZE_PLUGIN_H_
#define FLUTTER_PLUGIN_SIZE_PLUGIN_H_

#include <flutter_linux/flutter_linux.h>

G_BEGIN_DECLS

#ifdef FLUTTER_PLUGIN_IMPL
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
#else
#define FLUTTER_PLUGIN_EXPORT
#endif

typedef struct _SizePlugin SizePlugin;
typedef struct {
  GObjectClass parent_class;
} SizePluginClass;

FLUTTER_PLUGIN_EXPORT GType size_plugin_get_type();

FLUTTER_PLUGIN_EXPORT void size_plugin_register_with_registrar(
    FlPluginRegistrar* registrar);

G_END_DECLS

#endif  // FLUTTER_PLUGIN_SIZE_PLUGIN_H_

Content of generated_plugin_registrant.h

//
//  Generated file. Do not edit.
//

// clang-format off

#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_

#include <flutter_linux/flutter_linux.h>

// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);

#endif  // GENERATED_PLUGIN_REGISTRANT_

Solution

Flutter plugins follow a very specific format, and the tooling requires core elements of that format to exist. That includes the public header file with the correct path, as you have discovered, and also the plugin registration, which is the second issues you have (it sounds like you have restored the declaration, but not the implementation).

If your goal is to build your own FFI library code by piggy-backing on the plugin template, you need to leave those core elements in place. Your registration method doesn’t need to do anything, but it must exist because the flutter tool will generate a call to it.

It’s likely that in the future there will be tooling support for FFI-specific builds, but until then you need to make your library follow the required elements of the plugin structure.

Answered By – smorgan

Answer Checked By – Terry (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *