Android NDK - 如何链接 C++与另一个 C++库静态库

发布于 2024-12-04 00:32:17 字数 6184 浏览 0 评论 0原文

我有一个名为 mylib 的 C++ 库,在 CYGWIN 下使用 Android NDK r6b 的 ndk-build 进行编译。生成的库文件称为libmylib.so

我有一个名为 helloworld 的简单应用程序,其中包含 mylib 的 .hpp 文件,并且必须与 libmylib.so 链接。

我能够编译 helloworld,告诉链接器寻找 libmylib.so。 “奇怪”的事实是:

  1. libmylib.so没有与libhelloworld.so合并,所以我必须
  2. 在java代码中手动将libmylib.so复制到目录helloworld/libs/armeabi中,我必须使用System.loadLibrary显式加载mylib我必须在加载 helloworld 库之前加载 mylib (即: System.loadLibrary("mylib"); System.loadLibrary("ndkfoo");),否则应用程序崩溃。

如果我执行 1 和 2,该应用程序将完美运行(在模拟器和真实设备上进行测试)。我想知道如何强制链接器生成与 libmylib.so 合并的 libhelloworld.so,以避免如上所述的 1,2 和 3。

谢谢。

诗。

mylib 的 Android.mk 是:

LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS)
LOCAL_MODULE    := mylib
LOCAL_SRC_FILES := mylib.cpp 
include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_STATIC_LIBRARY)

如果我使用 BUILD_SHARED_LIBRARY,我会像往常一样得到 libmylib.so。如果我使用 BUILD_STATIC_LIBRARY,则 ndk-build 不会生成 .so 或 .a。我真的很想看到一个简单的教程,它解释了如何构建一个 JNI 应用程序(使用 JAVA + C++ 代码),该应用程序使用用 C++ 编写的外部库并放置在另一个目录(不是应用程序的 jni 目录)中。

诗。 当我使用 BUILD_STATIC_LIBRARY mylib 进行编译时,我获得以下内容(基本上,创建的唯一文件位于 dir /mylib/libs/armeabi/ 下,称为 gdb.setup 和 gdbserver):

$ /cygdrive/d/android/android-ndk-r6b/ndk-build NDK_LOG=1 V=1 -B
Android NDK: NDK installation path auto-detected: '/cygdrive/d/android/android-n
dk-r6b'
Android NDK: GNU Make version 3.81 detected
Android NDK: Host OS was auto-detected: windows
Android NDK: Host CPU was auto-detected: x86
Android NDK: HOST_TAG set to windows
Android NDK: Host awk tool was auto-detected: awk
Android NDK: Host awk test returned: Pass
Android NDK:  Probing for 'cygpath' program
Android NDK:  'cygpath' found as: /usr/bin/cygpath
Using cygwin substitution rules:
/cygdrive/d => D:
/cygdrive/c => C:
/cygdrive/D => D:
/cygdrive/C => C:
/usr/lib => C:/cygwin/lib
/usr/bin => C:/cygwin/bin
/ => C:/cygwin
Android NDK:  This NDK supports the following toolchains and target ABIs:
Android NDK:    arm-linux-androideabi-4.4.3:  armeabi armeabi-v7a
Android NDK:    x86-4.4.3:  x86
Android NDK: Found platform root directory: /cygdrive/d/android/android-ndk-r6b/
platforms
Android NDK: Found supported platforms: android-3 android-4 android-5 android-8
android-9
Android NDK: PLATFORM android-3 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-3/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-3/arch-x86
Android NDK: PLATFORM android-4 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-4/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-4/arch-x86
Android NDK: PLATFORM android-5 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-5/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-5/arch-x86
Android NDK: PLATFORM android-8 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-8/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-8/arch-x86
Android NDK: PLATFORM android-9 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-9/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-9/arch-x86
Android NDK: Found stable platform levels: 3 4 5 8 9
Android NDK: Found max platform level: 9
Android NDK: Looking for AndroidManifest.xml in /cygdrive/d/android/workspace/my
lib/jni
Android NDK: Looking for AndroidManifest.xml in /cygdrive/d/android/workspace/my
lib
Android NDK:     Found it !
Android NDK: Found project path: /cygdrive/d/android/workspace/mylib
Android NDK: Parsing /cygdrive/d/android/workspace/mylib/jni/Application.mk
Android NDK:   Found APP_PLATFORM=android-9 in /cygdrive/d/android/workspace/myl
ib/default.properties
Android NDK:   Defaulted to APP_BUILD_SCRIPT=/cygdrive/d/android/workspace/mylib
/jni/Android.mk
Android NDK: Application 'local' *is* debuggable
Android NDK: Selecting debug optimization mode (app is debuggable)
Android NDK: Adding import directory: /cygdrive/d/android/android-ndk-r6b/source
s
Android NDK: Building application 'local' for ABI 'armeabi'
Android NDK: Using target toolchain 'arm-linux-androideabi-4.4.3' for 'armeabi'
ABI
Android NDK: Looking for imported module with tag 'cxx-stl/system'
Android NDK:   Probing /cygdrive/d/android/android-ndk-r6b/sources/cxx-stl/syste
m/Android.mk
Android NDK:     Found in /cygdrive/d/android/android-ndk-r6b/sources/cxx-stl/sy
stem
Android NDK: Module 'mylib' has C++ sources
rm -f /cygdrive/d/android/workspace/mylib/libs/armeabi/lib*.so /cygdrive/d/andro
id/workspace/mylib/libs/armeabi-v7a/lib*.so /cygdrive/d/android/workspace/mylib/
libs/x86/lib*.so
rm -f /cygdrive/d/android/workspace/mylib/libs/armeabi/gdbserver /cygdrive/d/and
roid/workspace/mylib/libs/armeabi-v7a/gdbserver /cygdrive/d/android/workspace/my
lib/libs/x86/gdbserver
rm -f /cygdrive/d/android/workspace/mylib/libs/armeabi/gdb.setup /cygdrive/d/and
roid/workspace/mylib/libs/armeabi-v7a/gdb.setup /cygdrive/d/android/workspace/my
lib/libs/x86/gdb.setup
Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
mkdir -p /cygdrive/d/android/workspace/mylib/libs/armeabi
install -p /cygdrive/d/android/android-ndk-r6b/toolchains/arm-linux-androideabi-
4.4.3/prebuilt/gdbserver /cygdrive/d/android/workspace/mylib/libs/armeabi/gdbser
ver
Gdbsetup       : libs/armeabi/gdb.setup
mkdir -p /cygdrive/d/android/workspace/mylib/libs/armeabi
echo "set solib-search-path D:/android/workspace/mylib/obj/local/armeabi" > /cyg
drive/d/android/workspace/mylib/libs/armeabi/gdb.setup
echo "directory D:/android/android-ndk-r6b/platforms/android-9/arch-arm/usr/incl
ude D:/android/android-ndk-r6b/sources/cxx-stl/system/include D:/android/workspa
ce/mylib/jni" >> /cygdrive/d/android/workspace/mylib/libs/armeabi/gdb.setup

I have a C++ lib called mylib, compiled with ndk-build of Android NDK r6b under CYGWIN. The resulting library file is called libmylib.so.

I have a simple app called helloworld that includes the .hpp files of mylib and have to be linked with libmylib.so.

I am able to compile helloworld, telling the linker to look for libmylib.so. The "strange" facts are:

  1. libmylib.so is not merged with libhelloworld.so, so i have to copy libmylib.so into the directory helloworld/libs/armeabi manually
  2. in the java code, i have to load explicitly mylib with System.loadLibrary and i have to load mylib BEFORE i load helloworld library (that is: System.loadLibrary("mylib");
    System.loadLibrary("ndkfoo");
    ), otherwise the app crashes.

If i do 1 and 2, the app works perfectly (tested both on the emulator and on a real device). I would like to know how can to force the linker to produce a libhelloworld.so merged with libmylib.so, so to avoid 1,2 and 3 as mentioned above.

Thanks.

Ps.

The Android.mk of mylib is:

LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS)
LOCAL_MODULE    := mylib
LOCAL_SRC_FILES := mylib.cpp 
include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_STATIC_LIBRARY)

If i use BUILD_SHARED_LIBRARY, i got libmylib.so as usual. If i use, instead, BUILD_STATIC_LIBRARY, no .so or .a is generated by ndk-build. I really would like to see a simple tutorial which explains how to build a JNI app (with JAVA + c++ code) that uses an external library written in C++ and placed in another directory (not the jni directory of the app).

Pss.
When i compile with BUILD_STATIC_LIBRARY mylib, i obtain the following (basically, the only file created are under the dir /mylib/libs/armeabi/ and are called gdb.setup and gdbserver):

$ /cygdrive/d/android/android-ndk-r6b/ndk-build NDK_LOG=1 V=1 -B
Android NDK: NDK installation path auto-detected: '/cygdrive/d/android/android-n
dk-r6b'
Android NDK: GNU Make version 3.81 detected
Android NDK: Host OS was auto-detected: windows
Android NDK: Host CPU was auto-detected: x86
Android NDK: HOST_TAG set to windows
Android NDK: Host awk tool was auto-detected: awk
Android NDK: Host awk test returned: Pass
Android NDK:  Probing for 'cygpath' program
Android NDK:  'cygpath' found as: /usr/bin/cygpath
Using cygwin substitution rules:
/cygdrive/d => D:
/cygdrive/c => C:
/cygdrive/D => D:
/cygdrive/C => C:
/usr/lib => C:/cygwin/lib
/usr/bin => C:/cygwin/bin
/ => C:/cygwin
Android NDK:  This NDK supports the following toolchains and target ABIs:
Android NDK:    arm-linux-androideabi-4.4.3:  armeabi armeabi-v7a
Android NDK:    x86-4.4.3:  x86
Android NDK: Found platform root directory: /cygdrive/d/android/android-ndk-r6b/
platforms
Android NDK: Found supported platforms: android-3 android-4 android-5 android-8
android-9
Android NDK: PLATFORM android-3 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-3/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-3/arch-x86
Android NDK: PLATFORM android-4 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-4/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-4/arch-x86
Android NDK: PLATFORM android-5 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-5/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-5/arch-x86
Android NDK: PLATFORM android-8 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-8/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-8/arch-x86
Android NDK: PLATFORM android-9 supports: arm x86
Android NDK:   ABI arm sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-9/arch-arm
Android NDK:   ABI x86 sysroot is: /cygdrive/d/android/android-ndk-r6b/platforms
/android-9/arch-x86
Android NDK: Found stable platform levels: 3 4 5 8 9
Android NDK: Found max platform level: 9
Android NDK: Looking for AndroidManifest.xml in /cygdrive/d/android/workspace/my
lib/jni
Android NDK: Looking for AndroidManifest.xml in /cygdrive/d/android/workspace/my
lib
Android NDK:     Found it !
Android NDK: Found project path: /cygdrive/d/android/workspace/mylib
Android NDK: Parsing /cygdrive/d/android/workspace/mylib/jni/Application.mk
Android NDK:   Found APP_PLATFORM=android-9 in /cygdrive/d/android/workspace/myl
ib/default.properties
Android NDK:   Defaulted to APP_BUILD_SCRIPT=/cygdrive/d/android/workspace/mylib
/jni/Android.mk
Android NDK: Application 'local' *is* debuggable
Android NDK: Selecting debug optimization mode (app is debuggable)
Android NDK: Adding import directory: /cygdrive/d/android/android-ndk-r6b/source
s
Android NDK: Building application 'local' for ABI 'armeabi'
Android NDK: Using target toolchain 'arm-linux-androideabi-4.4.3' for 'armeabi'
ABI
Android NDK: Looking for imported module with tag 'cxx-stl/system'
Android NDK:   Probing /cygdrive/d/android/android-ndk-r6b/sources/cxx-stl/syste
m/Android.mk
Android NDK:     Found in /cygdrive/d/android/android-ndk-r6b/sources/cxx-stl/sy
stem
Android NDK: Module 'mylib' has C++ sources
rm -f /cygdrive/d/android/workspace/mylib/libs/armeabi/lib*.so /cygdrive/d/andro
id/workspace/mylib/libs/armeabi-v7a/lib*.so /cygdrive/d/android/workspace/mylib/
libs/x86/lib*.so
rm -f /cygdrive/d/android/workspace/mylib/libs/armeabi/gdbserver /cygdrive/d/and
roid/workspace/mylib/libs/armeabi-v7a/gdbserver /cygdrive/d/android/workspace/my
lib/libs/x86/gdbserver
rm -f /cygdrive/d/android/workspace/mylib/libs/armeabi/gdb.setup /cygdrive/d/and
roid/workspace/mylib/libs/armeabi-v7a/gdb.setup /cygdrive/d/android/workspace/my
lib/libs/x86/gdb.setup
Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
mkdir -p /cygdrive/d/android/workspace/mylib/libs/armeabi
install -p /cygdrive/d/android/android-ndk-r6b/toolchains/arm-linux-androideabi-
4.4.3/prebuilt/gdbserver /cygdrive/d/android/workspace/mylib/libs/armeabi/gdbser
ver
Gdbsetup       : libs/armeabi/gdb.setup
mkdir -p /cygdrive/d/android/workspace/mylib/libs/armeabi
echo "set solib-search-path D:/android/workspace/mylib/obj/local/armeabi" > /cyg
drive/d/android/workspace/mylib/libs/armeabi/gdb.setup
echo "directory D:/android/android-ndk-r6b/platforms/android-9/arch-arm/usr/incl
ude D:/android/android-ndk-r6b/sources/cxx-stl/system/include D:/android/workspa
ce/mylib/jni" >> /cygdrive/d/android/workspace/mylib/libs/armeabi/gdb.setup

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怎会甘心 2024-12-11 00:32:17

将 mylib 构建为静态库而不是共享对象(.so 文件)。然后,在定义 helloworld 的 Android.mk 中,将静态库列为依赖项:

LOCAL_STATIC_LIBRARIES := libmylib

Build mylib as a static library instead of a Shared Object (a .so file). Then, in your Android.mk which defines helloworld, list the static library as a dependency:

LOCAL_STATIC_LIBRARIES := libmylib
秋风の叶未落 2024-12-11 00:32:17

请注意,在您为 Android.mk 文件列出的内容中,您在最后有:

#include $(BUILD_STATIC_LIBRARY)

而不是:

include $(BUILD_STATIC_LIBRARY)

后者可能是您所需要的。请注意“固定”版本中排除了井号标签。我发现了这个异常并在谷歌上搜索了一个示例 android.mk 文件。我点击的第一个,果然,它是一个 Hello-World 示例,类似于您可能想要做的事情。希望有帮助。

**编辑:
即使我的回答解决了您的一些问题,仍然要听取 NuSkooler 的建议。他的回答描述了 make 文件如何“看到” mylib.a 文件的名称。相信他,如果你用 libmylib 而不是 mylib.a ,它就会起作用。我已经在 GCC 编译器(例如 MinGW32)的 make 文件中完成了它。
**

Noticed that in what you listed for your Android.mk file you have at the very end:

#include $(BUILD_STATIC_LIBRARY)

instead of:

include $(BUILD_STATIC_LIBRARY)

The later is probably what you need. Notice the exclusion of the hash-tag in the 'fixed' version. I found this anomaly and googled for an example android.mk file. The first one I clicked and sure enough, it was for a Hello-World example similar to what you are probably trying to do. Hope that helps.

**Edit:
Even if my answer fixes some of your issues, still heed the advice from NuSkooler. His answer describes how the make files "sees" the name of your mylib.a file. Trust him, if you put libmylib instead of mylib.a it will work. I've done it in make files for GCC compilers such as MinGW32.
**

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文