How can I generate both Android and pure Java libraries from a single code base?

Cross posting from StackOverflow ( because I suspect there is better understanding of Gradle, over here.

I am working with a codebase that is Java bindings for a native library. From this single codebase I would like to generate:

  • aars for several Android ABIs
  • jars for x86 on Windows, Mac and a Linux OSs

The artifacts must include both the Java bindings and the appropriate variant of the native library: arm/android, x86/linux, etc.

I am able to accomplish this feat with a gradle project that looks like this:

+ - build.gradle (does roughly nothing)  
+ - art
|    + - build.gradle (uses ndk/cmake to build jars for Android)
+ - jvm
|    + - build.gradle (uses gradle java and native to build jars for the JVM)
+ - src (the source from which both of the modules are built)

That is, two modules that contain nothing except build scripts, both of which build exactly the same source.

This seems somewhat clumsy. I’ve attempted to combine the two builds.gradle files, but:

> The 'java' plugin has been applied, but it is not compatible with the Android plugins.

Is there a more straightforward way of configuring this build?


Please note that my knowledge of Android builds is by far very limited. I’ll share what I would do for the jvm subproject in the hope it can provide some useful hints for you:


plugins {
    // obviously you'll add java or a plugin that adds java itself

// Configure java to use a non conventional layout
sourceSets {
	main {
		java {
			srcDirs "${project.rootProject.projectDir}/src/main/java", 'src/main/java'
		resources {
			srcDirs "${project.rootProject.projectDir}/src/main/resources", 'src/main/resources'

// ...

If such configuration is not applicable to the android subproject, then a copying task might do the trick, but it will be far less efficient:


plugins {
    // ...
def copyProvider = tasks.register('copySources', Copy) {
    from "${project.rootProject.projectDir}/src"
    into project.projectDir
tasks.named("name-of-the-build-task") {
    dependsOn copyProvider

Hey! Thanks @Pierre1! My build scripts look almost exactly as you suggest, except that both projects point at the source in the root directory, instead of copying it.
The thing that is making my spider sense tingle, however, is that I have to have two separate build scripts to build a single codebase. In some sense these are just variants artifacts build by using different tools chains on a single source, It seems odd, to me, that they would have to be separate modules…