Android NDK build cmake include .so library included in .aar library
Asked Answered
A

2

10

I have an android_library.aar file that containing library.so and some other resources and java files.

I imported android_library.aar to my project. My project uses c++ code with NDK. My problem is I can not compile C++ code that dependent with library.so with CMake. How could I extract library.so from aar before CMake compile? I want to include library.so to my C++ code directly without java. I know how to include .so in a project but I don't know how to do it from inside of aar.

Argue answered 20/8, 2018 at 12:31 Comment(4)
Very nice indeed! I believe that gradle does extract the .so files if the .aar is a dependency.Howze
I thought so. But it does not extract before cmake build. I don't know why. I searched for it and did not find any answer easy than this method.Argue
… but in your solution the aar is not declared as dependency of your project, s it?Howze
It's also must declare library as dependency. Because of Java part of library. I don't know much about dependency decleration also affecting to JNI part or not.Argue
A
3

I found a solution on my own after 1-week research. I found some code from Google GVR code. But it hasn't worked for my case. I changed build.dependsOn to preBuild.dependsOn then it worked. It might help some people in the future.

Here is the example code:

In the module's build.gradle file:

sourceSets {
    main {
        jniLibs.srcDirs = ["jniLibs"]
    }
}

task extractSo(type: Copy) {
    println 'Extracting *.so file(s)....'

    from zipTree("${project.rootDir}/ModuleName/ModuleName.aar")
    into "${project.rootDir}/${project.name}/src/main/jniLibs/"
    include "jni/**/*.so"

    eachFile {
        def segments = it.getRelativePath().getSegments() as List
        println segments
        it.setPath(segments.tail().join("/"))
        return it
    }
    includeEmptyDirs = false
}

preBuild.dependsOn extractSo
Argue answered 15/5, 2020 at 15:45 Comment(0)
R
2

Nowadays this is possible without much boiler plate. Prerequisite is that your AAR file includes a prefab folder. So the library maintainer needs to properly set things up.

If this is the case then it's as easy as adding following to app/build.gradle:

android {
    // ...
    buildFeatures {
        prefab true // extracts native libraries from AAR for usage in C++
    }
}

Then in CMakeLists.txt you can find and register the lib:

# Locate the native library:
find_package(ModuleName REQUIRED CONFIG)        
# Replace ModuleName with the actual name of your module.
# It can be found in `prefab/prefab.json` file of your AAR.

target_link_libraries(
        app
        ModuleName::nameOfSoFileWithoutFileEnding
)

Example with the OpenCV AAR library on Maven:

# ...
find_package(OpenCV REQUIRED CONFIG)    

target_link_libraries(
        app
        OpenCV::opencv_java4
)

This will register opencv_java4.so that is part of the AAR file. The C++ header files would be added as well.

Referee answered 29/2 at 0:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.