编译依赖于使用Android NDK运行的其他本机库的本机库?

Nat*_* F. 6 openssl android-ndk android-gradle-plugin

我有一个很大的C文件库,它依赖于OpenSSL,我对使用本机库非常陌生,尤其是使用android的新手.我已经成功地在iOS上实现了这个库而没有任何问题.

我一直在网上寻找有关如何做到这一点的教程/信息,但到目前为止我还没有发现任何我能理解的内容.这对我来说都很困惑.

本质上我正在试图弄清楚如何使用NDK将C文件库编译成本机库,并使用imy android应用程序编译库.

根据我的理解,我需要一个自定义的cmake文件用于android本身,但我不知道从哪里开始,我发现的文档非常难以理解.

所以,我需要一些帮助来理解在以下庄园中编译库的过程:

  1. 编译库,使用Gradle和CMakeLists.txt将其与openssl和libcrypto链接,并将最终库与我的Android Studio项目链接.
  2. 能够从我的Java代码中调用这些库中的本机函数.(我知道这需要一个JNI Java Wrapper)

(我已经设法为android需要的所有arch构建libssl和libcrypto,但我不知道如何处理.a/ .sofiles.)

任何有关此事的帮助都会令人难以置信.

谢谢

编辑:

我设法使用以下内容生成一些库文件.

文件结构:

.idea
app
build
gradle
jni    <--- I made this folder specifically fo this.
    Android.mk <-- This is the important file.
    include
        openssl
            <openssl header files>
    libs
        arm64-v8a
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        armeabi
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        armeabi--v7a
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        mips
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        mips64
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        x86
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        x86_64
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
    src <--- These are example files that i used to build this with.
        myc_files.c
        myother_c_files.c
        myc_heades.h
        myother_c_headers.h
Run Code Online (Sandbox Code Playgroud)

然后我在Android.mk中使用以下内容通过运行生成一些库ndk-build.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Select from arm64-v8a armeabi armeabi-v7a mips mips64 x86 x86_64
ARCH := armeabi

APP_UNIFIED_HEADERS := true

#APP_ABI := $(ARCH)
# TARGET_ARCH := $(ARCH)
TARGET_PLATFORM := android-14

SRC_DIR := $(LOCAL_PATH)/src
HDR_DIR := $(LOCAL_PATH)/include
LIB_DIR := $(LOCAL_PATH)/libs

LOCAL_C_INCLUDES := $(HDR_DIR)
LOCAL_MODULE := myclib
LOCAL_SRC_FILES := $(SRC_DIR)/myc_files.c $(SRC_DIR)/myother_c_files.c
LOCAL_LDLIBS += -L$(LIB_DIR)/$(ARCH) -lssl -lcrypto

include $(BUILD_STATIC_LIBRARY)
Run Code Online (Sandbox Code Playgroud)

这些库被放入PROJECT/obj/local,我不知道从哪里开始,或者如果Android.mk文件实际上正确构建了库.

Ale*_*ohn 7

  • 0.为Android构建openssl库; 你必须选择ABI(armeabi-v7ax86通常就足够了).你可以找到冗长乏味的官方教程.在这种情况下,您可以在GitHub或其他地方找到预构建的二进制文件.确定是否需要共享库或静态库.

  • 1.使用Android Studio 2.3,您可以通过集成的externalNativeBuild gradle任务构建您的库.但您可以使用ndk-build命令单独构建它.

  • 2.如果您选择不使用gradle,请将构建的共享库复制到app/src/main/jniLibsAndroid项目的目录中.

  • 3.您需要一个JNI包装器来将Java代码与C代码连接起来.在Java端,在一个或多个类中声明必要的本机方法.这些方法必须可以实现在C/C++侧,如在Android JNI描述漫游.您的Java代码必须显式加载包含这些本机方法实现的共享库.请注意,即使导出了这些函数,也无法直接调用库中的本机函数或opensssl库中的本机函数.

工作的Android.mk:

include $(CLEAR_VARS)

LOCAL_MODULE := vrazovpn
LOCAL_SRC_FILES := src/myc_files.c src/myother_c_files.c
LOCAL_STATIC_LIBRARIES := openssl libcrypto
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := openssl
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libssl.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libcrypto
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libcrypto.a
include $(PREBUILT_STATIC_LIBRARY)
Run Code Online (Sandbox Code Playgroud)

几条评论澄清以上内容:

  • LOCAL_SRC_FILES路径相对于LOCAL_PATH.
  • LOCAL_C_INCLUDE路径是相对于工作目录的,这就是我们经常为它们添加前缀的原因$(LOCAL_PATH).
  • 可以使用LOCAL_C_INCLUDES来引用属于我们使用的某个库的标头,但使用LOCAL_EXPORT_C_INCLUDES的强大功能将这些标头导出到库中会更安全,更清晰 ; 还有其他可以类似导出的设置.
  • Android.mk不应该(也不能)设置目标ABI; 它接收目标ABI ndk-build.您可以通过将它们列在Application.mk文件中或命令行中来控制要在构建中包含哪些ABI ,例如

    ndk-build APP_ABI="x86 armeabi-v7a"

如果您使用gradle插件在Android Studio 2.3或更高版本中构建库,APP_ABI则会忽略该设置.您必须在abiFilters中指定列表.