godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.46k stars 21.07k forks source link

Compiling Android template linking to custom external shared library #85951

Closed hugarty closed 10 months ago

hugarty commented 10 months ago

Tested versions

4.1.4.rc

System information

Manjaro Linux, Intel i5, NVIDIA GeForce GTX 1060 3GB, Vulkan

Issue description

I get this error when I try to compile Android template. scons platform=android target=template_release arch=arm64

[ 94%] Linking Shared Library bin/libgodot.android.template_release.arm64.so ...
[ 95%] ld: error: unable to find library -lFirst
[ 95%] clang-12: error: linker command failed with exit code 1 (use -v to see invocation)

I followed this guide Binding to external libraries.

When I run scons platform=linuxbsd target=template_debug or template_release it works. But for android it don't work.

I tried to put this lib in other folders than /usr/local/lib but didn't work.

Steps to reproduce

  1. You need to compile the First lib. It's a dummy lib, just for reproduce the error.
  2. Put the lib inside the Custom Module (module-bind-external-library-first) GODOT_ROOT/modules/first
  3. Put the lib inside /usr/local/bin/
  4. Try to run scons platform=android target=template_release arch=arm64

Minimal reproduction project (MRP)

First.zip module-bind-external-library-first.zip godot-test-project.zip

rsubtil commented 10 months ago

Since you mention that it works for Linux, have you compiled the First library for arm64?

akien-mga commented 10 months ago

Since you mention that it works for Linux, have you compiled the First library for arm64?

To clarify, you need to compile the First library for Android (with the NDK) and arm64. An Android app can't use a library compiled for regular Linux distros.

hugarty commented 10 months ago

I run cmake to build arm64-v8a (AArch64, arm64)

cmake -B ./android-build 
  -DANDROID_ABI=arm64-v8a 
  -DANDROID_PLATFORM=android-16 
  -DANDROID_NDK=~/Android/Sdk/ndk/22.0.7026061 
  -DCMAKE_TOOLCHAIN_FILE=~/Android/Sdk/ndk/22.0.7026061/build/cmake/android.toolchain.cmake 
  -G Ninja  

After that I build the sharedLib with Ninja inside android-build folder Ninja. The output is src/libFirst.a.

image

The output of scons platform=android target=template_release arch=arm64 is:

scons: Reading SConscript files ...
Auto-detected 6 CPU cores available for build parallelism. Using 5 cores by default. You can override it with the -j argument.
Checking for Android NDK...
Building for platform "android", architecture "arm64", target "template_release".
Checking for C header file mntent.h... (cached) yes
scons: done reading SConscript files.
scons: Building targets ...
[ 97%] Linking Shared Library bin/libgodot.android.template_release.arm64.so ...
[ 98%] ld: error: unable to find library -lFirst
[ 98%] clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
[ 99%] progress_finish(["progress_finish"], [])
[100%] scons: *** [bin/libgodot.android.template_release.arm64.so] Error 1
scons: building terminated because of errors.
[Time elapsed: 00:00:06.712]
hugarty commented 10 months ago

I tried do build using 3.5.3-stable and 4.2-stable both gave the same problem: unable to find library.

3.5.3-stable

[ 65%] Copy("platform/android/java/lib/libs/release/armeabi-v7a/libc++_shared.so", "/home/hpca/Android/Sdk/ndk/23.2.8568313/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so")
[ 65%] progress_finish(["progress_finish"], [])
[ 68%] Linking Static Library ==> core/libcore.android.opt.arm64.armv7.neon.a
Ranlib Library         ==> core/libcore.android.opt.arm64.armv7.neon.a
[ 68%] Linking Shared Library ==> bin/libgodot.android.opt.arm64.armv7.neon.so
ld: error: unable to find library -lFirst
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
scons: *** [bin/libgodot.android.opt.arm64.armv7.neon.so] Error 1
scons: building terminated because of errors.

4.2-stable

[ 68%] progress_finish(["progress_finish"], [])
[ 71%] Linking Static Library core/libcore.android.template_release.arm64.a ...
Ranlib Library core/libcore.android.template_release.arm64.a ...
[ 71%] Linking Shared Library bin/libgodot.android.template_release.arm64.so ...
ld: error: unable to find library -lFirst
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
scons: *** [bin/libgodot.android.template_release.arm64.so] Error 1

I put the arm64 version at godot/modules/first/libpath/libFirst.a and usr/local/lib/libFirst.a.

When the arm64 version is at usr/local/lib/libFirst.a and I run ld -l First it shows output:

ld: skipping incompatible /usr/local/lib/libFirst.a when searching for -lFirst
ld: cannot find -lFirst: No such file or directory

But when I put the x86_64 at usr/local/lib/libFirst.a the output:

ld: warning: cannot find entry symbol _start; not setting start address

I think it's correct. The libFirst.a don't has an entry point.

hugarty commented 10 months ago

I tried three different NDK (22.0.7026061, 23.2.8568313, 26.1.10909125), but don't work.

[ 97%] Linking Shared Library bin/libgodot.android.template_release.arm64.so ...
[ 98%] : error: unable to find library -lFirst
[ 98%] clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
[100%] progress_finish(["progress_finish"], [])
rsubtil commented 10 months ago

Try compilling in verbose mode:

$ scons ... verbose=yes

This should print the commands given to the linker, giving some more information on the files/paths being supplied in that step.

hugarty commented 10 months ago
scons platform=android target=template_release arch=arm64 verbose=yes

[ 97%] /home/aaaa/Android/Sdk/ndk/23.2.8568313/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -o bin/libgodot.android.template_release.arm64.so -target aarch64-linux-android21 -Wl,--gc-sections -Wl,--no-undefined -Wl,-z,now -Wl,-soname,libgodot_android.so -s -shared platform/android/os_android.os platform/android/android_input_handler.os platform/android/file_access_android.os platform/android/file_access_filesystem_jandroid.os platform/android/audio_driver_opensl.os platform/android/dir_access_jandroid.os platform/android/tts_android.os platform/android/thread_jandroid.os platform/android/net_socket_android.os platform/android/java_godot_lib_jni.os platform/android/java_class_wrapper.os platform/android/java_godot_wrapper.os platform/android/java_godot_view_wrapper.os platform/android/java_godot_io_wrapper.os platform/android/jni_utils.os platform/android/android_keys_utils.os platform/android/display_server_android.os platform/android/plugin/godot_plugin_jni.os platform/android/vulkan_context_android.os thirdparty/misc/ifaddrs-android.os -Lplatform/android/libpath main/libmain.android.template_release.arm64.a modules/libmodules.android.template_release.arm64.a modules/libmodule_ktx.android.template_release.arm64.a modules/libmodule_msdfgen.android.template_release.arm64.a modules/libmodule_theora.android.template_release.arm64.a modules/libmodule_vorbis.android.template_release.arm64.a modules/libmodule_basis_universal.android.template_release.arm64.a modules/libmodule_bmp.android.template_release.arm64.a modules/libmodule_csg.android.template_release.arm64.a modules/libmodule_dds.android.template_release.arm64.a modules/libmodule_enet.android.template_release.arm64.a modules/libmodule_first.android.template_release.arm64.a modules/libmodule_freetype.android.template_release.arm64.a modules/libmodule_gdscript.android.template_release.arm64.a modules/libmodule_glslang.android.template_release.arm64.a modules/libmodule_gltf.android.template_release.arm64.a modules/libmodule_gridmap.android.template_release.arm64.a modules/libmodule_hdr.android.template_release.arm64.a modules/libmodule_jpg.android.template_release.arm64.a modules/libmodule_jsonrpc.android.template_release.arm64.a modules/libmodule_mbedtls.android.template_release.arm64.a modules/libmodule_meshoptimizer.android.template_release.arm64.a modules/libmodule_minimp3.android.template_release.arm64.a modules/libmodule_mobile_vr.android.template_release.arm64.a modules/libmodule_multiplayer.android.template_release.arm64.a modules/libmodule_navigation.android.template_release.arm64.a modules/libmodule_noise.android.template_release.arm64.a modules/libmodule_ogg.android.template_release.arm64.a modules/libmodule_openxr.android.template_release.arm64.a modules/libmodule_raycast.android.template_release.arm64.a modules/libmodule_regex.android.template_release.arm64.a modules/libmodule_squish.android.template_release.arm64.a modules/libmodule_svg.android.template_release.arm64.a modules/libmodule_text_server_adv.android.template_release.arm64.a modules/libmodule_tga.android.template_release.arm64.a modules/libmodule_upnp.android.template_release.arm64.a modules/libmodule_vhacd.android.template_release.arm64.a modules/libmodule_webp.android.template_release.arm64.a modules/libmodule_webrtc.android.template_release.arm64.a modules/libmodule_websocket.android.template_release.arm64.a modules/libmodule_webxr.android.template_release.arm64.a modules/libmodule_zip.android.template_release.arm64.a platform/libplatform.android.template_release.arm64.a drivers/libdrivers.android.template_release.arm64.a scene/libscene.android.template_release.arm64.a servers/libservers.android.template_release.arm64.a core/libcore.android.template_release.arm64.a modules/text_server_adv/libharfbuzz_builtin.android.template_release.arm64.a modules/text_server_adv/libgraphite_builtin.android.template_release.arm64.a modules/text_server_adv/libicu_builtin.android.template_release.arm64.a modules/freetype/libfreetype_builtin.android.template_release.arm64.a modules/msdfgen/libmsdfgen_builtin.android.template_release.arm64.a -lOpenSLES -lEGL -landroid -llog -lz -ldl -lGLESv3 -lFirst

[100%] progress_finish(["progress_finish"], [])
[100%] ld: error: unable to find library -lFirst
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)

It's odd because it uses ndk/23.2.8568313, but in my ~/.zshrc I set other version of NDK.

echo $ANDROID_NDK_HOME   
~/Android/Sdk/ndk/26.1.10909125
echo $ANDROID_NDK_ROOT
~/Android/Sdk/ndk/26.1.10909125

I ran both commands (scons ... verbose=yes, echo $ANDROI...) in the same terminal.

I try with 22, 23 and 26 and don't work.

akien-mga commented 10 months ago

Godot only supports NDK 23.2.8568313, it's hardcoded in the gradle config.

I think the problem here is that you may not be adding the path to library's folder in the env["LIBPATH"], so it can't find the library. The linker command should include -L/path/to/your/lib/folder.

env.Append(LIBPATH=["/path/to/your/lib/folder"])

I tried to put this lib in other folders than /usr/local/lib but didn't work.

I guess Android builds won't look there, there's no reason an Android library would be next to Linux libraries. You don't want to link libraries from your host OS, only from the NDK, or custom provided ones.

hugarty commented 10 months ago

You all are AMAZING!

It worked!

_server_adv/libicu_builtin.android.template_release.arm64.a modules/freetype/libfreetype_builtin.android.template_release.arm64.a modules/msdfgen/libmsdfgen_builtin.android.template_release.arm64.a -lOpenSLES -lEGL -landroid -llog -lz -ldl -lGLESv3 -lFirst
[ 99%] progress_finish(["progress_finish"], [])
[100%] Move("platform/android/java/lib/libs/release/arm64-v8a/libgodot_android.so", "bin/libgodot.android.template_release.arm64.so")
[100%] scons: done building targets.
[Time elapsed: 00:00:07.444]

I changed my SCsub from:

env.Append(LIBPATH=['libpath'])

to:

env.Append(LIBPATH=['/usr/local/lib'])

Can I use this Issue to open a pull request to change godot/docs to change the text that say to use env.Append(LIBPATH=['libpath']) ?

# This is a path relative to /modules/tts/ where your .a libraries reside. # If you are compiling the module externally (not in the godot source tree), # these will need to be full paths. env.Append(LIBPATH=['libpath'])

akien-mga commented 10 months ago

Well a relative folder in the module would be a better recommendation that putting non-Linux libraries in /usr/local/lib. It's also more portable as you can add the library in your module repo directly for users to use (even though commiting binaries to Git is not recommended).

Did you try to put the library in modules/first/libpath/libFirst.a?

rsubtil commented 10 months ago

I'm not being able to compile it too, with the same linking error (with Linux version). From what I've been testing now, the LIBPATH seems to remain a relative path, and it's not being converted to an absolute path. Changing the provided SCsub to an absolute path has fixed it for me:

import os
env.Append(LIBPATH=[os.path.abspath('libpath')])
Resulting linker command (now with correct -L path in bold): clang++ -o bin/godot.linuxbsd.editor.x86_64.llvm -fuse-ld=mold platform/linuxbsd/godot_linuxbsd.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/crash_handler_linuxbsd.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/os_linuxbsd.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/joypad_linux.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/freedesktop_portal_desktop.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/freedesktop_screensaver.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/xkbcommon-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/display_server_x11.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/key_mapping_x11.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/dynwrappers/xext-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/vulkan_context_x11.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/gl_manager_x11_egl.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/gl_manager_x11.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/x11/detect_prime_x11.linuxbsd.editor.x86_64.llvm.o thirdparty/glad/glx.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/tts_linux.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/speechd-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/fontconfig-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/libudev-so_wrap.linuxbsd.editor.x86_64.llvm.o platform/linuxbsd/dbus-so_wrap.linuxbsd.editor.x86_64.llvm.o -Lmodules/first/libpath main/libmain.linuxbsd.editor.x86_64.llvm.a tests/libtests.linuxbsd.editor.x86_64.llvm.a modules/libmodules.linuxbsd.editor.x86_64.llvm.a modules/libmodule_ktx.linuxbsd.editor.x86_64.llvm.a modules/libmodule_msdfgen.linuxbsd.editor.x86_64.llvm.a modules/libmodule_theora.linuxbsd.editor.x86_64.llvm.a modules/libmodule_vorbis.linuxbsd.editor.x86_64.llvm.a modules/libmodule_astcenc.linuxbsd.editor.x86_64.llvm.a modules/libmodule_basis_universal.linuxbsd.editor.x86_64.llvm.a modules/libmodule_bmp.linuxbsd.editor.x86_64.llvm.a modules/libmodule_csg.linuxbsd.editor.x86_64.llvm.a modules/libmodule_cvtt.linuxbsd.editor.x86_64.llvm.a modules/libmodule_dds.linuxbsd.editor.x86_64.llvm.a modules/libmodule_enet.linuxbsd.editor.x86_64.llvm.a modules/libmodule_etcpak.linuxbsd.editor.x86_64.llvm.a modules/libmodule_first.linuxbsd.editor.x86_64.llvm.a modules/libmodule_freetype.linuxbsd.editor.x86_64.llvm.a modules/libmodule_gdscript.linuxbsd.editor.x86_64.llvm.a modules/libmodule_glslang.linuxbsd.editor.x86_64.llvm.a modules/libmodule_gltf.linuxbsd.editor.x86_64.llvm.a modules/libmodule_gridmap.linuxbsd.editor.x86_64.llvm.a modules/libmodule_hdr.linuxbsd.editor.x86_64.llvm.a modules/libmodule_jpg.linuxbsd.editor.x86_64.llvm.a modules/libmodule_jsonrpc.linuxbsd.editor.x86_64.llvm.a modules/libmodule_lightmapper_rd.linuxbsd.editor.x86_64.llvm.a modules/libmodule_mbedtls.linuxbsd.editor.x86_64.llvm.a modules/libmodule_meshoptimizer.linuxbsd.editor.x86_64.llvm.a modules/libmodule_minimp3.linuxbsd.editor.x86_64.llvm.a modules/libmodule_mobile_vr.linuxbsd.editor.x86_64.llvm.a modules/libmodule_multiplayer.linuxbsd.editor.x86_64.llvm.a modules/libmodule_navigation.linuxbsd.editor.x86_64.llvm.a modules/libmodule_noise.linuxbsd.editor.x86_64.llvm.a modules/libmodule_ogg.linuxbsd.editor.x86_64.llvm.a modules/libmodule_openxr.linuxbsd.editor.x86_64.llvm.a modules/libmodule_raycast.linuxbsd.editor.x86_64.llvm.a modules/libmodule_regex.linuxbsd.editor.x86_64.llvm.a modules/libmodule_squish.linuxbsd.editor.x86_64.llvm.a modules/libmodule_svg.linuxbsd.editor.x86_64.llvm.a modules/libmodule_text_server_adv.linuxbsd.editor.x86_64.llvm.a modules/libmodule_tga.linuxbsd.editor.x86_64.llvm.a modules/libmodule_tinyexr.linuxbsd.editor.x86_64.llvm.a modules/libmodule_upnp.linuxbsd.editor.x86_64.llvm.a modules/libmodule_vhacd.linuxbsd.editor.x86_64.llvm.a modules/libmodule_webp.linuxbsd.editor.x86_64.llvm.a modules/libmodule_webrtc.linuxbsd.editor.x86_64.llvm.a modules/libmodule_websocket.linuxbsd.editor.x86_64.llvm.a modules/libmodule_webxr.linuxbsd.editor.x86_64.llvm.a modules/libmodule_xatlas_unwrap.linuxbsd.editor.x86_64.llvm.a modules/libmodule_zip.linuxbsd.editor.x86_64.llvm.a platform/libplatform.linuxbsd.editor.x86_64.llvm.a drivers/libdrivers.linuxbsd.editor.x86_64.llvm.a editor/libeditor.linuxbsd.editor.x86_64.llvm.a scene/libscene.linuxbsd.editor.x86_64.llvm.a servers/libservers.linuxbsd.editor.x86_64.llvm.a core/libcore.linuxbsd.editor.x86_64.llvm.a modules/text_server_adv/libharfbuzz_builtin.linuxbsd.editor.x86_64.llvm.a modules/text_server_adv/libgraphite_builtin.linuxbsd.editor.x86_64.llvm.a modules/text_server_adv/libicu_builtin.linuxbsd.editor.x86_64.llvm.a modules/freetype/libfreetype_builtin.linuxbsd.editor.x86_64.llvm.a modules/msdfgen/libmsdfgen_builtin.linuxbsd.editor.x86_64.llvm.a -lpthread -ldl -latomic -lFirst

I'll try compiling the docs example to check it it's also happening there as well.

rsubtil commented 10 months ago

It looks like LIBPATH should be an absolute path indeed. The example fails to compile unless I specify an absolute path:

...
# This is a path relative to /modules/tts/ where your .a libraries reside.
# If you are compiling the module externally (not in the godot source tree),
# these will need to be full paths.
-env.Append(LIBPATH=['libpath'])
+env.Append(LIBPATH=[Dir('libpath').abspath])

Some more examples of Godot modules using absolute paths on LIBPATH:

Might be a documentation issue, then?