Bitbang3r
Bitbang3r

Reputation: 6914

How to set srcPaths in Gradle to specific subdirectory within collection of subdirectories

I'm attempting to massage an existing open-source library from Github that was originally created (and is currently maintained as) a very, very large and complex set of Eclipse projects into something that can be directly built within Android Studio using Gradle.

The projects are in this repo: https://github.com/unidata/awips2-core

Its dependencies are in this repo: https://github.com/unidata/awips2-core-foss

The awips2-core repo has the following directory structure:

./awips2-core/common/
./awips2-core/edex/
./awips2-core/features/
.awips2-core/viz/

Those four directories each contain the top-level directories for multiple projects, with names like "com.raytheon.uf.common.util"

Those directories have the following contents (using the 'util' project as an example):

META-INF
src  (contains ./com/raytheon/uf/common/util/*.java)
tests (same as src)
.classpath
.project
build.properites
com.raytheon.uf.common.util.ecl

I created the Android Studio project with a minimal Activity and module named 'app' in c:\src\awips2core-android, then proceeded to check out the two Git repos into subdirectories of the project's root directory:

cd \src\awips2core-android
git clone https://github.com/unidata/awips2-core
git clone https://github.com/unidata/awips2-core-foss

I then modified settings.gradle:

include ':awips2core'
include ':app'

project(':awips2core').projectDir = new File('./awips2-core')

... and added /src/awips2core-android/awips2-core/build.gradle:

apply plugin: 'java'

sourceSets {
    main {
        java {
            srcDirs = ['common/com.raytheon.uf.common.util/src', 'common/com.raytheon.uf.common.wxmath/src']
        }
    }
}

dependencies {
    compile fileTree(dir: '../awips2-core-foss')
}

This works.

The problem:

I have another 41 srcDirs under common/, and almost a hundred when you include the ones under edex/, features/, and viz/.

What I'd LIKE to do is add them programmatically, instead of one by one. In Java terms, something like:

List<File> srcPaths = new ArrayList<File>();
String[] paths =  {"common", "features", "edex", "viz"};
for(String subdir : paths) {
    // the path "c:/src/awips2core-android/awips2-core" would be implied by the project's definition in gradle.settings
    File projDir = new File("c:/src/awips2core-android/awips2-core", subdir);
    File[] subprojectDirs = projDir.listFiles();
    for (File dir : subprojectDirs)
        srcPaths.add(new File(dir, "src"));
}

// now, set set Gradle's srcDirs to srcPaths' elements...

So... How would I implement this in Groovy for Gradle, or what's the proper way to achieve this using Gradle?

Upvotes: 0

Views: 367

Answers (1)

Marcell Lipusz
Marcell Lipusz

Reputation: 93

This sounds like a multi-project build: https://guides.gradle.org/creating-multi-project-builds/

I would either put everything under the same root or put the foss into a separate project create the jar file and publish to somewhere(mavenLocal for test) and create a multi-project from the awips2-core project.

update

The great thing with gradle that the build files are code too.

I didn't try your java code, but that should work more or less to collect the directories as it is valid in groovy too. Once you've collected the directories into a collection(srcDirs is a Set according to the gradle documentation), then you can use that in the sourceSets block.

I would write something along this using streams:

def srcPaths = ["common", "features", "edex", "viz"].stream()
        .map { new File(projectDir, it) }
        .flatMap { it.listFiles().toList().stream() }
        .map { new File(it, "src") }
        .toSet()

sourceSets {
    main {
        java {
            srcDirs = srcPaths
        }
    }
}

Upvotes: 1

Related Questions