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

时间:2017-06-01 02:09:57

标签: android-ndk openssl android-gradle

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

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

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

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

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

  1. 使用Gradle和CMakeLists.txt编译库,将其与openssl和libcrypto链接,并将最终库与我的Android Studio项目链接。
  2. 能够从我的Java代码中调用这些库中的本机函数。 (我知道这需要一个JNI Java Wrapper)
  3. (我已经设法为android需要的所有arch构建libssl和libcrypto,但我不确定如何处理.a / .so文件。)

    对此事的任何帮助都会非常感激。

    由于

    修改

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

    文件结构:

    .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
    

    然后我在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)
    

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

3 个答案:

答案 0 :(得分:6)

  • 0。为Android构建openssl库;你必须选择ABI( armeabi-v7a x86 通常就足够了)。你可以找到official tutorial长而无聊的人。在这种情况下,您可以在GitHub或其他地方找到预构建的二进制文件。决定是否需要共享库或静态库。

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

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

  • 3. 您需要一个JNI包装器来将Java代码与C代码连接起来。在Java端,在一个或多个类中声明必要的 native 方法。这些方法必须在C / C ++端实现,如Android JNI walkthrough中所述。您的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)

几条评论澄清了上述内容:

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

    ndk-build APP_ABI="x86 armeabi-v7a"

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

答案 1 :(得分:4)

您可以使用本机开发进行数千次操作(我的意思是C / C ++)。这些语言非常简单,您可以执行从Java到C / C ++的繁重操作。例如,Camera硬件是Android设备中最重且最差的硬件之一。所以,当你试图处理这个并添加自己的操作时,它真的很糟糕。在本地开发方面,这种操作在CPU上工作,不需要通过Dalvik或其他方式进行翻译。这就是为什么你需要Android设备的所有CPU架构。因为,每个拱门都有自己的计算速度或技术。如果有任何协处理器,您也应该考虑到这一点。这是关于NDK的简短概述。

对于构建或重建本机库,您有两种方法,CMake和NDK构建。这两个建筑系统之间没有太多差异,所以我想用NDK建筑解释我的答案。

对于本机开发,您应该有main / jni文件夹,您应该将库和本机源放在其中并在此文件夹中构建它们。在您创建两个文件之前,Android.mk和Application.mk。 Android.mk用于构建本机库(模块),添加标志等。您可以在Android.mk中构建静态库和共享库。构建C源时,它会创建静态库(.a)。但是这些库不适合在Java端使用。您只能使用它们来创建共享库(.so)。为此,您应该构建C ++源代码,如果需要,可以将静态库添加到此。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))

LOCAL_MODULE := myLibrary

LOCAL_SHARED_LIBRARIES := cpufeatures opencv_imgproc opencv_core 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/c-files

LOCAL_SRC_FILES := $(LOCAL_PATH)/myJni.cpp

include $(BUILD_SHARED_LIBRARY)

---第1行返回main / jni路径。

---第二行清除所有旧的LOCAL_***变量。

---每个拱门的第3行构建模块在那里声明。

---第4行显示模块名称,当你构建它时,NDK会自动添加lib和.so扩展名(libmyLibrary.so)。

---第5行添加了其他共享库,您需要在本地源中使用它们。

---第6行将C文件添加到您的模块中。

---第7行显示了您尝试构建的C ++源代码。

---第8行是建筑指挥。

在Application.mk中,您可以在发布模式或调试模式下为项目提供类似的命令。你应该在这个文件中给出arch。例如APP_ABI := armeabi-v7a x86 arm64-v8a x86_64等等

当您尝试构建库并在java端使用它们时,您应该执行一些操作。

  1. 检查项目文件夹中local.properties文件中的ndk路径。它显示了构建makefile的ndk-bundle路径。

    ndk.dir = /用户/../库/ Android设备/ SDK / NDK束

  2. 在gradle文件中检查构建脚本。此脚本显示共享库的位置:

    sourceSets.main {
        jni.srcDirs = []
        jniLibs.srcDir 'src/main/libs'
    }
    
  3. 并将您的makefile路径显示为gradle。

    externalNativeBuild {
       ndkBuild {
          path 'src/main/jni/Android.mk'
       }
    }
    
  4. 我认为我的回答将帮助您理解一些细节。另外,您还可以查看这些答案。

    1. 用于调用本机方法:Enter

    2. 用于链接共享库:Enter

    3. 享受!

答案 2 :(得分:0)

首先,您需要已经交叉编译(针对Android平台和ABI)OpenSSL lib,或者在AS Project中进行编译。 然后,如果您熟悉cmake和gradle,这是最简单的方法,您可以在https://github.com/googlesamples/android-ndk/tree/master/hello-libs找到您想要的完整示例。 请特别注意cmake脚本CMakeLists.txt和gradle脚本app / build.gradle和gen-libs / build.gradle。我希望这可以帮到你