3

我有一个使用 Android NDK 编写的 android 项目。在项目中,我使用了两个预构建的共享库(GpkgSDK 和 spatialite)并构建了另外两个共享库(WFSHelpers 和 com_example_gpkgviewer_jni_WKTConverter)。与应用程序的 Java 级别交互的唯一库是 com_example_gpkgviewer_jni_WKTConverter 库。

库之间的依赖关系如下图所示:

  • WFSHelpers 依赖于 GpkgSDK 和 spatialite
  • com_example_gpkgviewer_jni_WKTConverter 依赖于 WFSHelpers

我遇到的问题是,当我尝试运行 ndk-build 时,在尝试构建 com_example_gpkgviewer_jni_WKTConverter 库时会收到很多未定义的引用。其他库已成功构建。我通常解决这些未定义引用的方法是在我的 com_example_gpkgviewer_jni_WKTConverter 模块定义中包含以下内容:

LOCAL_SHARED_LIBRARY := WFSHelpers

我不确定是否还需要包含 WFSHelpers 所依赖的库,如下所示:

LOCAL_SHARED_LIBRARY := WFSHelpers GpkgSDK spatialite

我也像这样以不同的顺序尝试过它们,但它似乎并没有解决我的问题:

  • LOCAL_SHARED_LIBRARY := GpkgSDK spatialite WFSHelpers

我的 Application.mk 包含在下面:

NDK_TOOLCHAIN_VERSION := 4.8
# APP_STL := stlport_shared  --> does not seem to contain C++11 features
APP_STL := gnustl_shared

# Enable c++11 extentions in source code
APP_CPPFLAGS += -std=c++11
APP_CPPFLAGS += -frtti 
APP_CPPFLAGS += -fexceptions

APP_MODULES := GpkgSDK spatialite WFSHelpers com_example_gpkgviewer_jni_WKTConverter

APP_ABI := armeabi armeabi-v7a

我的 Android.mk 如下所示:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := GpkgSDK
LOCAL_SRC_FILES := libMP.so
LOCAL_EXPORT_C_INCLUDES := \
$(LOCAL_PATH)/include \
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := spatialite
LOCAL_SRC_FILES := spatialamal/prebuilt/$(TARGET_ARCH_ABI)/libspatialite.so
LOCAL_EXPORT_C_INCLUDES :=     spatialamal/headers/spatialite \
                            spatialamal/headers
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := WFSHelpers
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
LOCAL_SRC_FILES := \
GPKGReader/Debug.h \
GPKGReader/DLLExport.h \
GPKGReader/DBQueryResult.cpp \
GPKGReader/GeoPackageDB.cpp \
GPKGReader/GPKGReader.cpp \
GPKGReader/order32.h \
GPKGReader/SpecDefinitions.h \
GPKGReader/WKBGenericGeometry.cpp \
GPKGReader/WKBLineString.cpp \
GPKGReader/WKBMultiLineString.cpp \
GPKGReader/WKBMultiPolygon.cpp \
GPKGReader/WKBPoint.cpp \
GPKGReader/WKBPolygon.cpp \
GPKGDataLayer/GPKGDataLayer.cpp
LOCAL_SHARED_LIBRARIES := GpkgSDK spatialite
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
LOCAL_MODULE    := com_example_gpkgviewer_jni_WKTConverter
LOCAL_SRC_FILES := com_example_gpkgviewer_jni_WKTConverter.cpp
LOCAL_SHARED_LIBRARY := WFSHelpers GpkgSDK spatialite
include $(BUILD_SHARED_LIBRARY)

我得到的未定义参考错误的示例如下所示:

[armeabi] SharedLibrary  : libcom_example_gpkgviewer_jni_WKTConverter.so
jni/com_example_gpkgviewer_jni_WKTConverter.cpp:59: error: undefined reference
o 'WKBGenericGeometry::readInt32(unsigned char, unsigned char*, unsigned int)'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [obj/local/armeabi/libcom_example_gpkgviewer_jni_WKTConverter.so]
Error 1

com_example_gpkgviewer_jni_WKTConverter.cpp 中导致此错误的代码行如下所示:

*id_arg = WKBGenericGeometry::readInt32(byte_order, &(bytes[4]), length - 4);

关于如何解决依赖关系的任何建议。

4

1 回答 1

4

在试图让它建立多年之后,我终于能够让它工作了。虽然,我不太确定有什么区别,所以欢迎任何能对此有所了解的人这样做。我的问题是我依赖于其他库。该文档指出以下内容:

LOCAL_SHARED_LIBRARIES
此模块在运行时依赖的共享库模块列表。这在链接时是必要的,并将相应的信息嵌入到生成的文件中。

LOCAL_LDLIBS
构建共享库或可执行文件时要使用的附加链接器标志列表。这对于传递带有“-l”前缀的特定系统库的名称很有用。例如,下面将告诉链接器在加载时生成一个链接到 /system/lib/libz.so 的模块:

LOCAL_LDLIBS := -lz

有关可以与此 NDK 版本链接的公开系统库列表,请参阅 STABLE-APIS。
注意:静态库会忽略这一点,如果您在此类模块中定义它,ndk-build 将打印警告。

因此,在我的 Android.mk 文件中,我必须使用 LOCAL_LDLIBS 而不是 LOCAL_SHARED_LIBRARIES 来指示依赖关系。

我新建的 Android.mk 如下图所示:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := GpkgSDK
LOCAL_SRC_FILES := libMP.so
LOCAL_EXPORT_C_INCLUDES := \
$(LOCAL_PATH)/include \
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := spatialite
LOCAL_SRC_FILES := spatialamal/prebuilt/$(TARGET_ARCH_ABI)/libspatialite.so
LOCAL_EXPORT_C_INCLUDES :=     spatialamal/headers/spatialite \
                            spatialamal/headers
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := WFSHelpers
LOCAL_SRC_FILES := \
GPKGReader/Debug.h \
GPKGReader/DLLExport.h \
GPKGReader/DBQueryResult.cpp \
GPKGReader/GeoPackageDB.cpp \
GPKGReader/GPKGReader.cpp \
GPKGReader/order32.h \
GPKGReader/SpecDefinitions.h \
GPKGReader/WKBGenericGeometry.cpp \
GPKGReader/WKBLineString.cpp \
GPKGReader/WKBMultiLineString.cpp \
GPKGReader/WKBMultiPolygon.cpp \
GPKGReader/WKBPoint.cpp \
GPKGReader/WKBPolygon.cpp \
GPKGDataLayer/GPKGDataLayer.cpp
LOCAL_LDLIBS := libs/$(TARGET_ARCH_ABI)/libGpkgSDK.so
LOCAL_LDLIBS += libs/$(TARGET_ARCH_ABI)/libspatialite.so
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := com_example_gpkgviewer_jni_WKTConverter
LOCAL_SRC_FILES := com_example_gpkgviewer_jni_WKTConverter.cpp
LOCAL_LDLIBS := libs/$(TARGET_ARCH_ABI)/libWFSHelpers.so
LOCAL_LDLIBS += libs/$(TARGET_ARCH_ABI)/libGpkgSDK.so
include $(BUILD_SHARED_LIBRARY)

我将暂时保留这个答案,因为我不完全确定 LOCAL_LDLIBS 和 LOCAL_SHARED_LIBRARIES 之间的区别是什么。如果有人可以给我一个解释,请做。如果没有,我会在给它一段时间后将此答案标记为已接受。谢谢 !

于 2014-03-19T17:06:05.737 回答