TL;DR
I have this C function in meaning_of_life.c
:
#define FFI_PLUGIN_EXPORT
FFI_PLUGIN_EXPORT int getMeaningOfLife(){
return 42;
}
I tried to compile it to a shared library (.so
) using alot of ways but I keep getting errors when I try to use it on android like incompatible target
and file in wrong format
. Can you tell me the right way to do it?
What I tried:
- create the above C file
- create a flutter_ffi plugin that will use it like this(this is somewhat irrelevant here):
add_library(meaningoflife SHARED IMPORTED )
set_target_properties(meaningoflife
PROPERTIES
IMPORTED_LOCATION
/home/haidar/dev_haidar/c++/meaning_of_life/Src/libLife.so
)
target_link_libraries(my_plugin meaningoflife)
- Read alot, alot... of docs, and searched alot here on SO but most related questions and answers are very old and use old ways ( they don't use cmake )
- Create a flutter app that will use the plugin
- Create a
.so
shared library from the plugin, first I tried the method on this page (using the NDK compilers and toolchain):
cd /home/haidar/dev_haidar/c++/meaning_of_life/Src
comp=/home/haidar/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/bin
$comp/aarch64-linux-android26-clang -fPIC meaning_of_life.c -o libLife.so -shared // also tried with other compilers as armv7a-linux-androideabi26-clang
The library is generated, but when I use it, I get one of the errors mentioned above (depending on the compiler used to create it), for example, here is some part of the error:
[ ] FAILURE: Build failed with an exception.
[ ] * What went wrong:
[ ] Execution failed for task ':image_magick_ffi:buildCMakeDebug[armeabi-v7a]'.
[ ] > Build command failed.
[ ] Error while executing process /home/haidar/Android/Sdk/cmake/3.18.1/bin/ninja with arguments {-C /home/haidar/dev_haidar/flutter/image_magick_ffi/android/.cxx/Debug/b5x10294/armeabi-v7a image_magick_ffi}
[ ] ninja: Entering directory `/home/haidar/dev_haidar/flutter/image_magick_ffi/android/.cxx/Debug/b5x10294/armeabi-v7a'
[ ] [1/1] Linking C shared library /home/haidar/dev_haidar/flutter/magick_app/build/image_magick_ffi/intermediates/cxx/Debug/b5x10294/obj/armeabi-v7a/libimage_magick_ffi.so
[ ] FAILED: /home/haidar/dev_haidar/flutter/magick_app/build/image_magick_ffi/intermediates/cxx/Debug/b5x10294/obj/armeabi-v7a/libimage_magick_ffi.so
[ ] : && /home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi16 --gcc-toolchain=/home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libimage_magick_ffi.so -o /home/haidar/dev_haidar/flutter/magick_app/build/image_magick_ffi/intermediates/cxx/Debug/b5x10294/obj/armeabi-v7a/libimage_magick_ffi.so CMakeFiles/image_magick_ffi.dir/image_magick_ffi.c.o /home/haidar/dev_haidar/c++/meaning_of_life/Src/libLife.so -latomic -lm && :
[ ] /home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: /home/haidar/dev_haidar/c++/meaning_of_life/Src/libLife.so: incompatible target
[ ] clang: error: linker command failed with exit code 1 (use -v to see invocation)
[ ] ninja: build stopped: subcommand failed.
[ ] * Try:
[ ] > Run with --debug option to get more log output.
[ ] > Run with --scan to get full insights.
[ ] * Exception is:
[ ] org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':image_magick_ffi:buildCMakeDebug[armeabi-v7a]'.
[ ] at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:147)
[ ] at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:282)
[ ] at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:145)
[ ] at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:133)
[ ] at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:77)
[ ] at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
[ ] at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
[ ] at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
[ ] at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
[ ] at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
[ ] at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
[ ] at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:74)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:333)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:320)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:313)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:299)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:143)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:227)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:218)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:140)
[ ] at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
[ ] at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
[ ] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[ ] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[ ] at java.base/java.lang.Thread.run(Thread.java:829)
[ ] Caused by: org.gradle.internal.UncheckedException: Build command failed.
[ ] Error while executing process /home/haidar/Android/Sdk/cmake/3.18.1/bin/ninja with arguments {-C /home/haidar/dev_haidar/flutter/image_magick_ffi/android/.cxx/Debug/b5x10294/armeabi-v7a image_magick_ffi}
[ ] ninja: Entering directory `/home/haidar/dev_haidar/flutter/image_magick_ffi/android/.cxx/Debug/b5x10294/armeabi-v7a'
[ ] [1/1] Linking C shared library /home/haidar/dev_haidar/flutter/magick_app/build/image_magick_ffi/intermediates/cxx/Debug/b5x10294/obj/armeabi-v7a/libimage_magick_ffi.so
[ ] FAILED: /home/haidar/dev_haidar/flutter/magick_app/build/image_magick_ffi/intermediates/cxx/Debug/b5x10294/obj/armeabi-v7a/libimage_magick_ffi.so
[ ] : && /home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi16 --gcc-toolchain=/home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libimage_magick_ffi.so -o /home/haidar/dev_haidar/flutter/magick_app/build/image_magick_ffi/intermediates/cxx/Debug/b5x10294/obj/armeabi-v7a/libimage_magick_ffi.so CMakeFiles/image_magick_ffi.dir/image_magick_ffi.c.o /home/haidar/dev_haidar/c++/meaning_of_life/Src/libLife.so -latomic -lm && :
[ ] /home/haidar/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: /home/haidar/dev_haidar/c++/meaning_of_life/Src/libLife.so: incompatible target
[ ] clang: error: linker command failed with exit code 1 (use -v to see invocation)
[ ] ninja: build stopped: subcommand failed.
[ ] at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:68)
[ ] at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:41)
[ ] at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:107)
[ ] at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
[ ] at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
[ ] at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
[ ] at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:242)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
[ ] at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
[ ] at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:227)
[ ] at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:210)
[ ] at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:193)
[ ] at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:171)
[ ] at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:89)
[ ] at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:40)
[ ] at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:53)
[ ] at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:50)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
[ ] at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
[ ] at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:50)
[ ] at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:40)
[ ] at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:68)
[ ] at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:38)
[ ] at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:48)
[ ] at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:36)
[ ] at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:41)
[ ] at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:74)
[ ] at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
[ ] at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:51)
[ ] at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:29)
[ ] at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:61)
[ ] at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:42)
[ ] at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:60)
[ ] at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:27)
[ ] at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:180)
[ ] at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$1(BuildCacheStep.java:75)
[ ] at org.gradle.internal.Either$Right.fold(Either.java:175)
[ ] at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:59)
[ ] at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:73)
[ ] at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:48)
[ ] at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:36)
[ ] at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:25)
[ ] at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:36)
[ ] at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:22)
[ ] at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:110)
[ ] at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:56)
[ ] at java.base/java.util.Optional.orElseGet(Optional.java:369)
[ ] at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:56)
[ ] at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:38)
[ ] at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:73)
[ ] at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:44)
[ ] at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37)
[ ] at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27)
[ ] at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:89)
[ ] at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:50)
[ ] at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:114)
[ ] at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:57)
[ ] at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:76)
[ ] at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:50)
[ ] at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNoEmptySources(SkipEmptyWorkStep.java:249)
[ ] at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:86)
[ ] at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:54)
[ ] at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:32)
[ ] at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:21)
[ ] at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
[ ] at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:43)
[ ] at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:31)
[ ] at org.gradle.internal.execution.steps.AssignWorkspaceStep.lambda$execute$0(AssignWorkspaceStep.java:40)
[ ] at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:287)
[ ] at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:40)
[ ] at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:30)
[ ] at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:37)
[ ] at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:27)
[ ] at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:44)
[ ] at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:33)
[ ] at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:76)
[ ] at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:144)
[ ] at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:133)
[ ] at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:77)
[ ] at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
[ ] at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
[ ] at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
[ ] at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
[ ] at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
[ ] at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
[ ] at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
[ ] at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
[ ] at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:74)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:333)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:320)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:313)
[ ] at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:299)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:143)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:227)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:218)
[ ] at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:140)
[ ] at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
[ ] at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
[ ] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[ ] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[ ] at java.base/java.lang.Thread.run(Thread.java:829)
[ ] Caused by: Build command failed.
...
- Create a
.so
shared library from the plugin, This time I tried the method on the official android docs page, I used this command which generated a json file with another command to compile the C file above, but I don't understand how to create the shared library in this case (the template of the command is from the same page):
cmake -H/home/haidar/dev_haidar/c++/meaning_of_life -DCMAKE_FIND_ROOT_PATH=/home/haidar/dev_haidar/c++/meaning_of_life -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=/home/haidar/Android/Sdk/ndk/25.1.8937393/build/cmake/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DANDROID_NDK=/home/haidar/Android/Sdk/ndk/25.1.8937393 -DANDROID_PLATFORM=android-23 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_ANDROID_NDK=/home/haidar/Android/Sdk/ndk/25.1.8937393 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/home/haidar/dev_haidar/c++/meaning_of_life -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/home/haidar/dev_haidar/c++/meaning_of_life -DCMAKE_MAKE_PROGRAM=/home/haidar/Android/Sdk/cmake/3.22.1/bin/ninja -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=26 -B/home/haidar/dev_haidar/c++/meaning_of_life -GNinja
Note: The device I tried to run the flutter app (that uses the plugin, that uses the .so
library) on is a Huawei p10 lite, which has a CPU that supports arm63-v8a, armeabi-v7a, armeabi.
Listing the steps to solve this or tips would be much appreciated. Thanks.
Update
I found this shell script on github (which is very similar to what I did in step 6 above), I tweaked it to fit my paths and it successfully generated the .so
files for each architecture. I created a pure android app and called it from the app and everything worked fine.
add_library(getnumber SHARED IMPORTED)
set_target_properties(getnumber PROPERTIES IMPORTED_LOCATION
/home/haidar/dev_haidar/c++/getnumber/Src/prebuilt/release/arm64-v8a/libgetnumber.so
)
target_link_libraries(imagemagicknativeapp getnumber)
and everything worked fine.
When I depended on it in the flutter plugin in the exact same way
add_library(getnumber SHARED IMPORTED )
set_target_properties(getnumber
PROPERTIES
IMPORTED_LOCATION
/home/haidar/dev_haidar/flutter/image_magick_ffi/src/Dependencies/ImageMagick/lib/android/arm64-v8a/libgetnumber.so
)
target_link_libraries(image_magick_ffi getnumber)
I still get an error
ld: error: /home/haidar/dev_haidar/flutter/image_magick_ffi/src/Dependencies/ImageMagick/lib/android/arm64-v8a/libgetnumber.so is incompatible with armelf_linux_eabi
I know the problem is related to the compilation/linking target being different than the actual target (my phone), but how can I tell flutter to change this behavior?