Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Gradle Adding static library

In old traditional android ndk we will specify the static library to be linked in the Android.mk file.

Android.mk

PLATFORM_PREFIX := /opt/android-ext/
LOCAL_PATH := $(PLATFORM_PREFIX)/lib
include $(CLEAR_VARS)
LOCAL_MODULE := library
LOCAL_SRC_FILES := library.a
include $(PREBUILT_STATIC_LIBRARY)

LOCAL_STATIC_LIBRARIES := android_native_app_glue library

Here is my Question

I am little bit Confused when switching to Gradle experimental plugin for NDK. Share your ideas on how to link Static library in App build.gradle file.

I had followed the latest gradle experimental plug-in documentation given here.

like image 714
Sankar ganesh Avatar asked Sep 09 '15 05:09

Sankar ganesh


2 Answers

Have a look at this sample.

  1. Tell the compiler where the headers are (in android.ndk{}):

    CFlags += "-I${file("path/to/headers")}".toString() cppFlags += CFlags

  2. Tell the linker where the .a file is (in android.ndk{} or where defining the flavors - make sure to add abiFilter - for example abiFilters += "armeabi-v7")

    ldFlags += "-L${file(path/to/library.a)}".toString() ldLibs += ["nameOfLibrary"]

    Note that the name of the library by convention is the string after "lib" in the .a file name. For example, for a file named libNative.a you should add ldLibs += ["native"] to gradle.

  3. Create a new module and use apply plugin: 'java' to apply java plugin. In the build.gradle write the necessary code to get and place the .a file in the appropriate directory (where you will get it from your module which is using it). Don't forget to add a dependency in the module using the library (compile project(':libraryModule') in dependencies{}) and to include it in the project in settings.gradle file with include ':libraryModule'. If you want to place the module in a specified by you folder (for example where currently your Android.mk file is), just add project(':libraryModule').projectDir = new File(settingsDir, 'path/to/module').

That should do it.

like image 106
Nedko Avatar answered Oct 16 '22 05:10

Nedko


The above answers work around gradle's prior insufficient NDK integration. This answer illustrates new gradle integration with the NDK.

Take a look at this proposed sample written against gradle 2.9 and the android plugin 0.6.0-alpha1. In constrast to how the question is posed, this answer contains a separate project for the library. This functionality can be explored to allow gradle to build that library before it is used by the app project. The other answers rely on the presumption that the library had already been built.

The :secondlib com.android.model.application builds libsecondlib.so (loaded in Java code with System.loadLibrary("secondlib"). The name 'secondlib' is poorly named. I like to think of it as a .so "wrapper" for all other native libraries linked for use by the app.

That shared library is statically linked against firstlib.a as built by the :firstlib com.android.model.native.

The headers are exported from the :firstlib to any dependent projects (:secondlib in this example) as per the exportedHeaders clause. This way dependent projects know how to link against the .so/.a. This replaces the CFlags+="-I/path/to/headers" syntax in a prior answer.

:secondlib links against :firstlib statically as per the following clause:

android.sources {
    main {
         jni {
             dependencies {
                 project ":firstlib" buildType "debug" linkage "static"
             }
         }
         // TODO(proppy): show jniLibs dependencies on .so
    }
}

As shown by the comment, the example is incomplete. The finishing syntax is shown in the 'NDK Dependencies' section of the experimental android plugin documentation. Within that document the syntax for how to statically link instead of dynamically link should be clear.

There are currently some shortcomings (e.g. the buildType of the dependency shown above is by default 'debug' and not the current buildType being built).

EDIT: Here is a work-in-progress sample of the new dependencies syntax in app/build.gradle pulled out of one of my projects:

  android.sources {
    main {
      jni {
        //for exportedHeaders
        dependencies { project ":libfoo" linkage "shared" }
      }
      jniLibs {
        //Where the swig wrapped library .so is. I use swig to create code to interface with libfoo.so within :app
        source { srcDirs 'libs' }
        //for file in $(model.repositories.libs.libfoo)
        dependencies { library "libfoo" }
      }
    }
  }

  repositories {
    libs(PrebuiltLibraries) {
      libevdev {
        //headers already available from our libfoo project via exportedHeaders
        //headers.srcDir "../libfoo/src/main/jni/"
        binaries.withType(SharedLibraryBinary) {
          sharedLibraryFile = file("../libfoo/build/intermediates/binaries/debug/lib/${targetPlatform.getName()}/libfoo.so")
        }
      }
    }
  }
like image 3
Andrew Smart Avatar answered Oct 16 '22 05:10

Andrew Smart