Re: Support for .so libraries in Gradle builds?

10,057 views
Skip to first unread message

Xavier Ducrohet

unread,
Dec 6, 2012, 12:54:33 PM12/6/12
to adt...@googlegroups.com
This is not implemented yet.

How's your library packaged? Is it just a loose bunch of files that
you manually drop in your project or do you have a jar with the .so
inside?

On Thu, Dec 6, 2012 at 7:55 AM, Martin Liersch <godd...@googlemail.com> wrote:
> Hey everyone,
>
> I'm currently trying to get an app converted to the Gradle based build
> system.
> The app includes native (*.so) libraries from a third party SDK.
>
> When i build the app with eclipse / ant / maven, the resulting APK file
> contains the *.so files in the "libs" folder. However, when i build with
> Gradle, those libraries are not contained in the APK file.
>
> How do I configure that?
>
> Goddchen



--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.
http://developer.android.com | http://tools.android.com

Please do not send me questions directly. Thanks!

Szabolcs Berecz

unread,
Dec 6, 2012, 1:52:57 PM12/6/12
to adt...@googlegroups.com
I have a hack for this, which works with the current release (0.2) of the Android plugin for Gradle, but won't work in later versions without modification: https://gist.github.com/4226923

What it does is copy the *.so files to build/native-libs before any compilation starts and configures PackageApplicationTask to look for *.so files in build/native-libs. Actually, the copying could be done just before the PackageApplicationTask is run, but it's just a temporary hack anyway...

But keep in mind that it's just a hack and it will not work for you without modification.

Martin Liersch

unread,
Dec 7, 2012, 8:50:04 AM12/7/12
to adt...@googlegroups.com
That is awesome, thanks!

Xavier Ducrohet

unread,
Dec 7, 2012, 1:01:31 PM12/7/12
to adt...@googlegroups.com
This is indeed pretty cool! I didn't expect to have all the stuff
almost ready enough to make it work. Nice work Szabolcs!

Crossle Song

unread,
May 21, 2013, 2:51:09 AM5/21/13
to adt...@googlegroups.com
how can package .so to apk? I used   'com.android.tools.build:gradle:0.4'

Xavier Ducrohet

unread,
May 23, 2013, 1:44:35 AM5/23/13
to adt...@googlegroups.com
There were some refactoring in 0.4 and this is not possible for the moment. We are working on NDK integration though.


--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Traun Leyden

unread,
May 28, 2013, 8:39:29 PM5/28/13
to adt...@googlegroups.com

For what it's worth, the following workaround has been working for me on 0.4.1:

task copyNativeLibs(type: Copy) {
    from(new File(project(':CBLite').getProjectDir(), 'native-libs')) { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}

tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'

tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
    pkgTask.jniDir new File(buildDir, 'native-libs')
}

It's a slight modification to the version on github: I changed buildDir -> getProjectDir().  

You'll need to add a new directory in your project called "native-libs" which contains the .so files.

Xavier Ducrohet

unread,
Jun 1, 2013, 7:27:54 PM6/1/13
to adt...@googlegroups.com
This is something I want to do indeed. There are some questions about this is supported. For instance, if someone doesn't support x86/mips, they might not use a classifier in their artifact. In that case how do we know what the ABI is?

Also, we are also planning on supporting ABI filters at the ndk-compilation and packaging levels, so that you can have multi-apks. In that case you'd probably want something like

dependencies {
   x86Apk 'foo:bar:1.0:so:x86'
   mipsApk 'foo:bar:1.0:so:mips'
}

where 'x86' and 'mips' are flavors used to do multi-apk per ABI. Note the use of 'apk' instead of 'compile' as it's strictly a packaging dependency, and is not needed to build the  app code.

In both case, we need to know the ABI of the so so that we can put it in the right folder inside the APK.

The only way to guarantee this is to enforce that the classifier is used, always, and that it matches the ABI name. This would only happen for "so" type artifacts. Such an artifact with no classifier would generate an error.



On Sat, Jun 1, 2013 at 3:43 PM, Jeff Campbell <jeff...@gmail.com> wrote:
We have the same issue.... except we depend on both armeabi AND x86 native libraries (we use sqlcipher and want to support both ARM and Intel processors).  Unfortunately this big issue for us, as we cannot ship unless our database is encrypted.  Currently, we are using Maven and we uploaded the .so files to our Nexus Maven Repository and have the following dependencies in our pom.xml (note the <classifier/>):

        <dependency>
            <groupId>net.sqlcipher</groupId>
            <artifactId>sqlcipher</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>net.sqlcipher</groupId>
            <artifactId>libdatabase_sqlcipher</artifactId>
            <version>2.1.1</version>
            <type>so</type>
            <classifier>armeabi</classifier>
        </dependency>
        <dependency>
            <groupId>net.sqlcipher</groupId>
            <artifactId>libstlport_shared</artifactId>
            <version>2.1.1</version>
            <type>so</type>
            <classifier>armeabi</classifier>
        </dependency>
        <dependency>
            <groupId>net.sqlcipher</groupId>
            <artifactId>libsqlcipher_android</artifactId>
            <version>2.1.1</version>
            <type>so</type>
            <classifier>armeabi</classifier>
        </dependency>
        <dependency>
            <groupId>net.sqlcipher</groupId>
            <artifactId>libdatabase_sqlcipher</artifactId>
            <version>2.1.1</version>
            <type>so</type>
            <classifier>x86</classifier>
        </dependency>
        <dependency>
            <groupId>net.sqlcipher</groupId>
            <artifactId>libstlport_shared</artifactId>
            <version>2.1.1</version>
            <type>so</type>
            <classifier>x86</classifier>
        </dependency>
        <dependency>
            <groupId>net.sqlcipher</groupId>
            <artifactId>libsqlcipher_android</artifactId>
            <version>2.1.1</version>
            <type>so</type>
            <classifier>x86</classifier>
        </dependency>


It would be nice to have the same type of support in the Gradle project (use a Maven dependency) like the following:

dependencies {
    compile 'net.sqlcipher:sqlcipher:2.1.1'

    compile 'net.sqlcipher:libdatabase_sqlcipher:2.1.1:so:armeabi'
    compile 'net.sqlcipher:libstlport_shared:2.1.1:so:armeabi'
    compile 'net.sqlcipher:libsqlcipher_android:2.1.1:so:armeabi'

    compile 'net.sqlcipher:libdatabase_sqlcipher:2.1.1:so:x86'
    compile 'net.sqlcipher:libstlport_shared:2.1.1:so:x86'
    compile 'net.sqlcipher:libsqlcipher_android:2.1.1:so:x86'
}


On Thursday, December 6, 2012 8:55:52 AM UTC-7, Martin Liersch wrote:
Hey everyone,

I'm currently trying to get an app converted to the Gradle based build system.
The app includes native (*.so) libraries from a third party SDK.

When i build the app with eclipse / ant / maven, the resulting APK file contains the *.so files in the "libs" folder. However, when i build with Gradle, those libraries are not contained in the APK file.

How do I configure that?

Goddchen

--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Jeff Campbell

unread,
Jun 1, 2013, 8:36:38 PM6/1/13
to adt...@googlegroups.com
Actually the Maven plugin, at first, would assume that if no classifier was specified, then it assumed armeabi.  With recent versions of the plugin, it now forces a classifier (armeabi, x86, etc) on all .so dependencies.  I actually prefer this, because it leaves no question to what platform the .so library is built for.




--
You received this message because you are subscribed to a topic in the Google Groups "adt-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/adt-dev/SOs6mxZGjMM/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to adt-dev+u...@googlegroups.com.
Message has been deleted
Message has been deleted

Crossle Song

unread,
Jun 7, 2013, 4:40:43 AM6/7/13
to adt...@googlegroups.com
Thanks

Traun Leyden

unread,
Jun 7, 2013, 2:09:14 PM6/7/13
to adt...@googlegroups.com

westh...@gmail.com

unread,
Oct 17, 2013, 6:24:28 PM10/17/13
to adt...@googlegroups.com
How do you use this technique for Android Library projects?  I find that the following doesn't work for Android Library projects:

tasks.withType(com.android.build.gradle.tasks.PackageApplication) {
    pkgTask -> pkgTask.jniDir new File(buildDir, 'native-libs')
}

The type needs to be something different than com.android.build.gradle.tasks.PackageApplication.  It needs to be something different to get into the .aar, I'm just not sure what it is....

Johnathan Raymond

unread,
Oct 22, 2013, 1:03:10 PM10/22/13
to adt...@googlegroups.com
So far there doesn't seem to be an equivalent task.  I'm considering wrapping the functionality into my own version of "PackageLibrary."  If I should get it working I'll post/submit it

Daniele Segato

unread,
Oct 23, 2013, 10:57:55 AM10/23/13
to adt...@googlegroups.com
This is the snipped of code I have in my build.gradle to integrate NDK

/////////////
// NDK Support
//////////////
// If using this, Android studio will fail run the following to set the environment variable for android studio:
// export ANDROID_NDK_HOME=/Android/android-ndk-r8e (Linux)
// launchctl setenv ANDROID_NDK_HOME /Android/android-ndk-r8e (Mac)
// or, better, add the export to the .profile of your user home and re-login
task copyNativeLibs(type: Copy, dependsOn: 'buildNative') {
    from(new File('src/main/libs')) { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}

// TODO fix deprecated
tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'

tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
    pkgTask.jniDir new File(buildDir, 'native-libs')
}

task buildNative(type: Exec) {
    def ndkBuild;
    def ndkBuildingDir = new File("src/main");
//    def ndkSourcesDir = new File(ndkBuildingDir, "jni")
//    def ndkOutputDir = new File(buildDir, 'native-libs')
    def hasNdk = false;
    if (System.env.ANDROID_NDK_HOME != null) {
        hasNdk = true;
        ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build')
    }

//    inputs.files fileTree(ndkSourcesDir)
//    outputs.dir ndkOutputDir
    commandLine ndkBuild, "--directory", ndkBuildingDir

    doFirst {
        if (!hasNdk) {
            logger.error('##################')
            logger.error("Failed NDK build")
            logger.error('Reason: Reason: ANDROID_NDK_HOME not set.')
            logger.error('##################')
        }
        assert hasNdk : "ANDROID_NDK_HOME not set."
    }
}

task cleanNative(type: Exec) {
    def ndkBuild;
    def ndkBuildingDir = new File("src/main");
    def hasNdk = false;
    if (System.env.ANDROID_NDK_HOME != null) {
        hasNdk = true;
        ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build')
    }

    commandLine ndkBuild, "--directory", ndkBuildingDir, "clean"

    doFirst {
        if (!hasNdk) {
            logger.error('##################')
            logger.error("Failed NDK build")
            logger.error('Reason: Reason: ANDROID_NDK_HOME not set.')
            logger.error('##################')
        }
        assert hasNdk : "ANDROID_NDK_HOME not set."
    }
}

clean.dependsOn 'cleanNative'


----------

Hope it helps.

Regards,
Daniele


--

Nabil Hachicha

unread,
Jun 1, 2014, 2:33:22 PM6/1/14
to adt...@googlegroups.com
I know this thread is old but a lot of Google searches end up here: 
BTW this plugin could be useful:


it allows you to write something like this:

native_dependencies {
    artifact 'foo:bar:1.0:armeabi'
    artifact 'foo:bar:1.0:x86'
}

Cheers,

Vyacheslav Blinov

unread,
Dec 5, 2014, 10:47:24 AM12/5/14
to adt...@googlegroups.com
I tried your plugin and unfortunately it breaks apart gradle integration with Android Studio :)

I'd love to see such thing in gradle itself, but it looks like nobody care on dependency management with native artifacts (which is strange).

воскресенье, 1 июня 2014 г., 21:33:22 UTC+3 пользователь Nabil Hachicha написал:

Tom Billiet

unread,
Dec 8, 2014, 9:38:25 AM12/8/14
to adt...@googlegroups.com
I care too, but I've solved it quite easily. I've a jarfile in my local maven repository where the content is structured like this:
lib/armeabi/libtest.so
lib/x86/libtest.so

And then in my gradle script:
dependencies {
    releaseApk  group: "org.test", name: "test",         version: "1.2.3", classifier: 'native-android'
    debugApk    group: "org.test", name: "test",         version: "1.2.3", classifier: 'native-android-debug'
}

This magically puts the correct so files in the resulting apks. And you can even specify a different so file for release and debug apk (or any flavor for that matter).

Tom

Op vrijdag 5 december 2014 16:47:24 UTC+1 schreef Vyacheslav Blinov:

Vyacheslav Blinov

unread,
Dec 8, 2014, 9:45:39 AM12/8/14
to adt...@googlegroups.com
Thanks for sharing this, this is very interesting to know. I currently solved my problem by creating aar library with native-only so files as part of native library build/deployment, which feels natural and straightforward currently, but still I would prefer direct so dependency as it helps to build native libs depending on other native files.
> --
> You received this message because you are subscribed to the Google Groups "adt-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Regards,
Vyacheslav Blinov
https://github.com/dant3

Reply all
Reply to author
Forward
0 new messages