使用预构建的静态库进行Android NDK开发

8
我正在尝试构建一个使用现有c++代码的静态库的Android应用程序。然而,我似乎无法构建成功,以下是我迄今为止所采取的步骤。
我已经安装了ndk-r5b,并按照ndk/docs/STANDALINE-TOOLCHAIN.html的说明构建了独立工具链。然后我使用了独立工具链编译器(arm-linux-androideabi-g++)代替Makefile中CXX标志的g++,以编译我需要的静态库。这样编译时没有错误,并且生成了3个静态库。以下是一些用于构建预编译库的标志的代码片段:
CXX = arm-linux-androideabi-g++
SYSTEM_LIBS = -lstdc++ -lm
INCLUDE_PATH += ${NDK_PATH}/platforms/android-8/arch-arm/usr/include/

编译时,makefile 会生成一行示例代码:

arm-linux-androideabi-g++ -c -DTIME_SIM -I./include  -I/home/greg/dev/Android/android-ndk-r5b/platforms/android-8/arch-arm/usr/include/ -fpic -ggdb3 -SimTime.C -o SimTime.o

接下来,我使用以下 Android.mk 命令通过 ndk-build 构建应用程序:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := engine
LOCAL_SRC_FILES := ../libs/libEngine.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := shmem
LOCAL_SRC_FILES := ../libs/libShMem.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := util
LOCAL_SRC_FILES := ../libs/libUtil.a
include $(PREBUILT_STATIC_LIBRARY)

# build server as a shared library
include $(CLEAR_VARS)
LOCAL_MODULE := libServer   
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include 

LOCAL_SRC_FILES := \
    Server.C \
    Router.C \
    RouterMsgs.C \
    Federation.C \
    cripName.C \
    ver.C \
    JNIWrapper.cpp
LOCAL_STATIC_LIBRARIES := engine shmem util
include $(BUILD_SHARED_LIBRARY)

使用Android NDK提供的独立工具链编译预构建库非常顺利。但是当使用ndk-build将共享库链接到预构建库时,会出现许多 unresolved references to ostream 的问题。例如:

/home/android/obj/local/armeabi/libShMem.a(SubscriptionItem.o): In function `SUBSCRIPTION_ITEM::Print(std::basic_ostream<char, std::char_traits<char> >&)':/home/src/comm/SubscriptionItem.C:97: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'

我想我在使用独立编译器进行编译时可能漏掉了一些重要的标志或者做错了一些事情,但是如果您能提供任何帮助或见解,将不胜感激,因为我似乎无法在谷歌或任何安卓NDK文档中找到这个答案。谢谢!


我不太确定这是一个好主意。如果你构建一个完全静态链接的库,它依赖于libstdc++,那么你最终会在库中包含这些函数的副本。但是当你将库加载到手机上时,你将把它加载到一个已经具有libstdc++共享映射的进程中,该应用程序在从zygote分叉时继承了它。这至少是浪费的。使用允许库具有未满足依赖项的构建标志可能更好? - Chris Stratton
2个回答

3

其实你可以通过在与Android.mk文件相同的文件夹中创建一个Application.mk文件来解决这个问题,内容如下:

APP_STL := stlport_static

使用位于Android NDK内部的静态stlport。


1

我曾遇到同样的问题,通过添加标准C++库的模块来解决了这个问题。由ndk-build系统链接的库位于错误的位置(在我的情况中是platforms / android-9 / arch-arm / usr / lib)。

include $(CLEAR_VARS)
LOCAL_MODULE := rightstdc
LOCAL_SRC_FILES := <path to the correct libstdc++.a>
include $(PREBUILT_STATIC_LIBRARY)

将模块标签添加到静态库列表中:
LOCAL_STATIC_LIBRARIES := engine shmem util rightstdc

build/core/build-binary.mk 会在 LOCAL_LDLIBS 中指定了任何库时,将 -L$(SYSROOT)/usr/lib 添加到前面,但在我的情况下,这是错误的路径。

我不知道是否有一个缺失的步骤应该将正确的 libstdc++ 复制到那个位置,但上述方法可以解决问题。


在Application.mk中添加你的C++库相关信息以及一些cpp标志。 - Sumit Kumar Saha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接