使用NDK,Gradle& amp;链接外部库。在Android Studio

时间:2018-04-11 17:29:32

标签: android c++ android-studio cmake android-ndk

我已经回到Android开发之后出现差距,我的旧ANT构建链似乎不再运行(这是一个单独的问题)与最新的SDK,所以我试图以新的方式做事,这是基于gradle和CMake。

我有许多预先构建的静态和动态第三方库,我的项目需要这些库,但我无法成功链接这些库。
从我可以收集的内容来看,这些内容需要在' CMakeLists.txt '中指定。文件而不是' build.gradle '文件,但我是两个系统的新手,所以如果我错了,请纠正我。

这是我迄今为止所做的尝试:

  • 首先,我尝试解决子弹的位置。我尝试过变种,省略了' lib' ' .a'和#armeabi-v7a' (希望它能够选择正确的CPU变体),但没有一个工作

     find_library(bullet_lib libBullet.a HINTS ${LIBBASE}bullet3/build3/Android/obj/local/armeabi-v7a)
    

    我不确定这与target_link_libraries

    中包含的库有何不同
    add_library(bullet_lib STATIC IMPORTED)
    

    这会发现内置库很好,但是我发现了#9; bullet'和其他第三方图书馆

    target_link_libraries(my_project_name android log EGL GLESv2 bullet_lib) 
    

${LIBBASE}是第三方图书馆的基础目录,似乎没问题,但是,另外还有一件事:CMake错误似乎不会出现在Android工作室中!我可以通过在包含' CMakeLists.txt ' CMakeLists.txt 的文件夹中运行cmake .来解决问题所在。文件,但我不太确定我用正确的参数调用它:无论Android Studio使用cmake做什么,此时该文件对我来说都是黑盒子。

我在android studio中看到的唯一消息是链接器错误(它没有提到关于找不到库的CMake错误,这是导致这些链接器错误的原因:)

Build command failed.
Error while executing process E:\prog\Android\cmake\3.6.4111459\bin\cmake.exe with arguments {--build E:\prog\anthracite\gradle\AnthracitePlayerAPI21\app\.externalNativeBuild\cmake\debug\x86_64 --target anthracite-lib}
[1/1] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\x86_64\libanthracite-lib.so
FAILED: cmd.exe /C "cd . && E:\prog\Android\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe  --target=x86_64-none-linux-android --gcc-toolchain=E:/prog/Android/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64 --sysroot=E:/prog/Android/ndk-bundle/sysroot -fPIC -isystem E:/prog/Android/ndk-bundle/sysroot/usr/include/x86_64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security  -std=c++11 -fexceptions -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a --sysroot E:/prog/Android/ndk-bundle/platforms/android-21/arch-x86_64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libanthracite-lib.so -o ..\..\..\..\build\intermediates\cmake\debug\obj\x86_64\libanthracite-lib.so @CMakeFiles/anthracite-lib.rsp  && cd ."

E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:237: error: undefined reference to 'btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache*)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:240: error: undefined reference to 'btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btDefaultCollisionConstructionInfo const&)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:242: error: undefined reference to 'btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration*)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:243: error: undefined reference to 'btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:246: error: undefined reference to 'btDefaultSoftBodySolver::btDefaultSoftBodySolver()'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:247: error: undefined reference to 'btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher*, btBroadphaseInterface*, btConstraintSolver*, btCollisionConfiguration*, btSoftBodySolver*)'
E:\prog\anthracite\src/CCmpPhysicsScene3D.cpp:250: error: undefined reference to 'btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher*, btBroadphaseInterface*, btConstraintSolver*, btCollisionConfiguration*)'
E:\prog\anthracite\src/CCmpPhysJointHinge.cpp:117: error: undefined reference to 'btHingeConstraint::btHingeConstraint(btRigidBody&, btVector3 const&, btVector3 const&, bool)'

clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

跑步' cmake。'从命令行给出:

-- Selecting Windows SDK version 10.0.16299.0 to target Windows 10.0.17133.
CMake Warning at CMakeLists.txt:447 (message):
  resolved libraries:


CMake Warning at CMakeLists.txt:448 (message):
  e:/prog/libs/bullet3/build3/Android/obj/local/armeabi-v7a


CMake Warning at CMakeLists.txt:449 (message):
  bullet_lib-NOTFOUND



-- Configuring done
-- Generating done
-- Build files have been written to: E:/prog/anthracite/gradle/AnthracitePlayerAPI21/app
但是,正如我上面提到的那样,我不确定该输出的准确性作为调用参数来实现' cmake'可能与Android Studio内部完全不同。 (例如,它违反了Windows版本,所以我不确定它是否会寻找' .lib'库而不是' .a'或者' .so')

另外,我在我的' CMakeLists.txt '中使用了这些行。用于报告构建状态的文件:

message(WARNING "resolved libraries:")
message(WARNING ${LIBBASE}bullet3/build3/Android/obj/local/armeabi-v7a)
message(WARNING ${bullet_lib})

无论如何,我显然遗漏了一些东西,而且我还没有找到任何关于此的明确指南。这似乎是一个非常简单明显的事情(链接一个库),但它似乎是一个巨大的痛苦。 我很感激任何指示。

1 个答案:

答案 0 :(得分:1)

您必须注意ABI不兼容性。您正在为 x86_64 构建 libanthracite-lib.so ,因此您需要 libBullet.a 的相同变体。如果您只需 armeabi-v7a ,则必须在 build.gradle 中指定,例如

android {
  externalNativeBuild {
    cmake {
      path 'CMakeLists.txt'
    }
  }
  defaultConfig {
     ndk {
        abiFilters 'armeabi-v7a'
    }
    externalNativeBuild {
      cmake {
         arguments '-DCMAKE_VERBOSE_MAKEFILE=ON'
      }
    }
  }
}

E:\prog\anthracite\gradle\AnthracitePlayerAPI21\app\CMakeLists.txt

add_library(bullet_lib STATIC IMPORTED)
set_target_properties(bullet_lib PROPERTIES IMPORTED_LOCATION
 ${LIBBASE}/bullet3/build3/Android/obj/local/${ANDROID_ABI}/libBullet.a)
target_link_libraries(my_project_name bullet_lib android log EGL GLESv2) 

target_link_libraries中库的顺序可能很重要,因此请在左侧保留静态库。

我猜你用 ndk-build 构建 libBullet.a 。您可以创建一个单独的库模块(让我们在 bullet_module 中调用)到您的AS项目,即使它没有Java文件,并将其指向Android.mk

apply plugin: 'com.android.library'

android {
  compileSdkVersion 27

  defaultConfig {
    ndk {
      abiFilters 'armeabi-v7a'
    }
    externalNativeBuild {
      ndkBuild {
        targets 'Bullet'
      }
    }
  }
  externalNativeBuild {
    ndkBuild {
      path "${LIBBASE}/bullet3/build3/Android/jni/Android.mk"
    }
  }
}

现在您可以更改 CMakeLists.txt 以查看 bullet_module 构建的结果:

set_target_properties(bullet_lib PROPERTIES IMPORTED_LOCATION
  <path/to/bullet_module>/build/intermediates/ndkBuild/debug/obj/local/${ANDROID_ABI}/libBullet.a)