【问题标题】:Include Pre-compiled Static LIbrary using NDK使用 NDK 包含预编译的静态库
【发布时间】:2015-02-16 09:12:04
【问题描述】:

我希望在我的 Android Studio NDK 项目中包含一个预编译的静态库。我正在使用 Android Studio 1.0.1,在 SO 上尝试此问题的任何解决方案似乎都已过时(或涉及创建库项目并包含它)。

结构如下:

app
/--src
/--main
/--java
+--jni
+--jniLibs
   /--armeabi
       /--libpng.a
    --armeabiv7
       /--libpng.a
    ...(for each abi)

我正在尝试包含库 libpng。我尝试创建 jniLibs(根据 ph0b(真棒指南,顺便说一句)并将 libpng.a 添加到相应的 ABI 文件夹。这仍然给我错误 - 当我尝试编译时找不到 -llibpng使用以下代码:

ndk {
        moduleName "game" 
        cFlags "-std=c++11 -fexceptions -DANDROID -I${project.buildDir}/../src/main/jni/include \
                -I${project.buildDir}/../src/main/jni/include/png"
        ldLibs "EGL", "GLESv3", "dl", "log", "android", "libpng"
        stl "gnustl_static"
}

【问题讨论】:

  • 您在 ndk.ldLibs 表达式中是否尝试过“png”。即不包括前缀'lib'。
  • @RobertRowntree yes :( 已经尝试过那个。还尝试将 libpng 添加到 ndk/platforms/android-21/usr/lib 中的相应平台作为最后的努力。尝试过 .so 和.a,无济于事。唯一有效的方法是将所有源文件用于 libpng 并将它们粘贴在一个目录中,并将其包含在我的 jni.srcDirs 中……非常混乱,笨重,并且需要一分钟立即建造。
  • 我仍然对 NDK 使用 ph0b 技术,您可以使用自己的 'sourceSets.main' 覆盖 NDK 插件来覆盖框架... jni.srcDirs = [] /*禁用自动 ndk-build 调用*/ jniLibs.srcDir 'src/main/libs' 如果我不更改实际的 cpp 源文件,它根本不会增加构建时间,并根据 ph0b 使用我自己的 Android.mk 文件
  • 这就是我现在正在做的事情,正在切换到 ph0b 的设置。从我阅读数小时后获得的信息来看,我只是不认为 Android Studio 支持我需要的东西。感谢您的意见!
  • ph0b.com/android-studio-gradle-and-ndk-integration 如果你还没有……别忘了获取最新的 NDK。 ( 10c )

标签: android android-ndk android-studio


【解决方案1】:

现在可以通过实验性插件正常工作。

有关完整说明,请参阅 this whole excellent article,这是我从中获取的,但我自己也在使用它并且它有效。

这是我的build.gradle - 请注意,在我的情况下,它是用于库项目,我使用的是静态链接而不是共享链接。

buildscript {
    dependencies
            {
                classpath "com.android.tools.build:gradle-experimental:0.7.0-alpha3"
            }
}
apply plugin: 'com.android.model.library'

model {
    repositories {
        libs(PrebuiltLibraries) {
            v8_base {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_base.a")
                }
            }
            v8_libbase {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_libbase.a")
                }
            }
            v8_libplatform {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_libplatform.a")
                }
            }
            v8_nosnapshot {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_nosnapshot.a")
                }
            }
        }
    }

    android {

        compileSdkVersion 23
        buildToolsVersion "23.0.2"

        sources {
            main {
                jni {
                    source {
                        srcDir "src/main/jni"
                    }
                    dependencies {
                        library "v8_base" linkage "static"
                        library "v8_libbase" linkage "static"
                        library "v8_libplatform" linkage "static"
                        library "v8_nosnapshot" linkage "static"
                    }
                }
            }
        }

        ndk {
            moduleName "v8example"
            cppFlags.add("-std=c++11")
            cppFlags.add("-I${file("src/main/jni/include")}".toString())
            cppFlags.add("-fexceptions")
            ldLibs.add("log")
            stl "stlport_static"
            abiFilters.add("armeabi armeabi-v7a x86")
        }
    }
}

替代方法是您使用自己调用 ndkBuild 的旧 Gradle 方法,从而使用 .mk 文件。这也可以正常工作,但是您会失去与 Android Studio 的良好集成,例如您的 jni 文件正确显示。

【讨论】:

    【解决方案2】:

    在 Android Studio 1.0.2 中添加 .so 库

    1. 在“src/main/”中创建文件夹“jniLibs”
    2. 将所有 .so 库放入“src/main/jniLibs”文件夹中
    3. 文件夹结构看起来像,
      |--应用:
      |--|--src:
      |--|--|--主要
      |--|--|--|--jniLibs
      |--|--|--|--|--armeabi
      |--|--|--|--|--|--.so 文件
    4. 无需额外的代码,只需同步您的项目并运行您的应用程序。

      参考
      https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

    【讨论】:

    • 我已经用 .a-files(静态库)做到了这一点,但现在呢?如何在我的 java 代码中使用在这个库中声明的类和函数?
    【解决方案3】:

    由于 ndk 支持现在在 gradle 中受到限制,您可以尝试对不同 abi 的静态库进行此操作。

        ndk {
            moduleName "game" 
            ....
            ldLibs ..., file(projectDir).absolutePath+"/src/main/jniLibs/\$(TARGET_ARCH_ABI)/libpng.a"
            ....
        }
    

    【讨论】:

      【解决方案4】:

      您不能只包含 .so 文件,您还需要有 src 文件夹,这些文件夹实际上提供了访问这些 .so 文件中的方法的接口。我建议不要以这种方式将您的项目耦合到库。

      最好的方法是将它作为 android studio 的库模块包含在内,并丢弃 jni 文件夹以禁用 ndkbuild,并将 jnilib 指向 /libs 文件夹,方法是将以下内容添加到 build.gradle 文件中

      jni.srcDirs = [] //disable automatic ndk-build call
      jniLibs.srcDirs = [ 'libs' ] //no need to copy the .so files from /libs to /jniLibs folder
      

      (检查libs目录是否也被android studio正确导入了.so文件)

      将库作为模块导入会自动完成以下操作

      a)yourlibrary 项目文件夹中的库文件夹,并根据 gradle 约定进行了重组 b) 导入项目(在 settings.gradle 中包含“:yourlibrary”)和
      c)创建依赖项(“文件 -> 项目结构 -> 从左侧子窗口中选择主应用程序模块 -> 依赖项(最后一个选项卡) -> 按右侧的绿色“+” -> yourlibrary作为模块依赖 -> OK”)

      【讨论】:

        【解决方案5】:

        这真的很难看,但它有效!您可以诱骗 Gradle 允许您将代码注入到生成的 Android.mk 文件中:

            ndk {
                abiFilter "armeabi-v7a"
        
                // We need to inject the static library into the
                // NDK build, and Gradle doesn't offer a way to directly
                // modify the Android.mk file... So we hack it!
                //
                // You can see the end result at:
                //   build/intermediates/ndk/debug/Android.mk
        
                moduleName "This_is_a_terrible_Gradle_hack\n" +
        
                "include \$(CLEAR_VARS)\n" +
        
                "LOCAL_MODULE := mystaticlib_prebuilt\n" +
                "LOCAL_EXPORT_C_INCLUDES := mystaticlib/include\n" +
                "LOCAL_SRC_FILES := mystaticlib/libmystaticlib.a\n" +
        
                "include \$(PREBUILT_STATIC_LIBRARY)\n" +
        
                "include \$(CLEAR_VARS)\n" +
                "LOCAL_MODULE := MyActualModule\n" +
                "LOCAL_STATIC_LIBRARIES += mystaticlib_prebuilt"
        
                cFlags "-std=c++11 -fexceptions -frtti -pthread"
                stl "gnustl_shared"
                ldLibs "log", "OpenSLES", "z"
            }
        

        【讨论】:

        猜你喜欢
        • 2011-07-24
        • 1970-01-01
        • 2011-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-24
        • 2017-07-17
        • 1970-01-01
        相关资源
        最近更新 更多