Some of my dependencies are in Artifactory as zip files that have been distributed by a vendor.
The jars are required to compile and the dll/so and html templates are required for debugging/runtime.
Creating a dependency on local files is straightforward:
dependencies {
compile fileTree(dir: "${projectDir}/sec-lib", includes: ['*.jar'])
}
Extracting dependencies is straightforward too:
dependencies {
compile 'com.thirdparty.sec-lib:1.0#zip'
}
task copyToLib(type: Copy) {
into "${projectDir}/sec-lib"
from configurations.compile
}
How do I use them together though?
I can change the zip to a new configuration so only that one is extracted:
configurations {
zipCompile
}
dependencies {
zipCompile 'com.thirdparty.sec-lib:1.0#zip'
compile fileTree(dir: "${projectDir}/sec-lib", includes: ['*.jar'])
}
task copyToLib(type: Copy) {
into "${projectDir}/sec-lib"
from configurations.zipCompile
}
However, the copyToLib task has to run in order for the dependencies to resolve but the dependencies need to resolve for the copyToLib task to run.
How do I fix this circular dependency issue?
I don't want to have to have a README that says "make sure you run this task first or the project wont compile or import into your IDE".
I also have multiple zip files like this I need to deal with.
Does the compileJava task from the Gradle java plugin depend on the compileSourceSetJava task of any source sets I've created? Or do I need to manually use dependsOn to make sure all source sets are compiled when I run compileJava?va`?
I believe it doesn't automatically depend on anything. If you just create an empty source set, it's just that - a set of sources. But depends on your use case, there might be an implicit dependency. Consider the following gradle script:
apply plugin: "java"
sourceSets {
integrationTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
}
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
task integrationTest(type: Test) {
testClassesDir = project.sourceSets.integrationTest.output.classesDir
classpath = project.sourceSets.integrationTest.runtimeClasspath
}
Because the integrationTest source set references the main java source set, gradle automatically creates a dependency on compileJava (and processResources).
So the answer is "it depends" (pun not intended). There might be implicit dependencies based on how have you defined the source sets and configurations. However if you don't define any relation between the two source sets, there is no reason why would they automatically create any dependencies.
BTW There is a nice gradle plugin for generating task graphs if you would like to explore that more.
I have the following in my build.gradle:
configurations {
runtime.exclude group: 'org.apache.spark'
runtime.exclude group: 'org.apache.hadoop'
}
and for some reason this also excludes all Hadoop/Spark code from the test classpath. If I comment out this configuration - the tests are passing fine, otherwise I get all sorts of java.lang.NoClassDefFoundError: org/apache/hadoop/hdfs/MiniDFSCluster$Builder issues.
I tried to use this:
test {
classpath += configurations.compile
}
No luck.
What am I missing here?
In gradle scoping, test inherits from runtime. Your test code is excluding the minicluster dependency because runtime excludes it.
See this diagram for the scope inheritance tree for the java plugin:
Instead of adding a global exclude to the runtime configuration, you might want to make the spark dependencies into compileOnly scoped dependencies which is available since gradle 2.12.
configurations {
compileOnly 'org.apache.spark:spark:2.11'
test 'org.apache.hadoop:hadoop-minicluster:2.7.2'
}
More information about gradle scoping is available in the gradle manual:
Alternatively, you could add another configuration that inherits from runtime, and add exclusions to that, then use that as the basis of your shadowJar. This could be helpful if you want to optionally build a jar with spark dependencies bundled in or not. Your tests will use the configuration without exclusions, but the jar you package won't include the spark dependencies.
configurations {
sparkConfiguration {
extendsFrom runtime
exclude group: 'org.apache.hadoop'
exclude group: 'org.apache.spark'
}
}
task sparkExcludedJar(type: ShadowJar) {
group = "Shadow"
configurations = [project.configurations.sparkConfiguration]
classifier = 'sparkExcluded'
}
I'm going through Google's documentation on "Add Google Play Services to Your Project" in Android Studio:
https://developer.android.com/google/play-services/setup.html
I'm using that documentation to modify the build.gradle file of a freshly created Android project. In Step 2 (Add Google Play Services to Your Project), it states:
Add this line:
apply plugin: 'android'
Under Dependencies, add this:
compile 'com.google.android.gms:play-services:5.0.77'
It also says to update that version after updating Google Play Services, which is now at 18 according to Android SDK Manager.
Here is my entire build.gradle file at the top-level (parent of this file is the root folder).
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply plugin: 'android'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
compile 'com.google.android.gms:play-services:18'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
Upon saving, it prompts for a Sync. I Sync it, but get:
Build script error, unsupported Gradle DSL method found: 'compile()'!
Error:(10, 0) Possible causes could be:
- you are using a Gradle version where the method is absent
- you didn't apply Gradle plugin which provides the method
- or there is a mistake in a build script
I'm using Android Studio 0.8.2. I didn't install Gradle, just using the plugin that came with Android Studio.
It's interesting to note that the build.gradle file generated when I made this new project says:
//NOTE: Do not place your application dependencies here
But Google's documentation says (which conflicts with the above):
Note: Android Studio projects contain a top-level build.gradle file and a build.gradle
file for each module. Be sure to edit the file for your application module.
What's wrong with my build.gradle file (or environment)?
The Google documentation you quoted is correct, and doesn't conflict. There's more than one build.gradle file. Instead of putting dependencies in the top-level one as you have, put them in the build file that's in your module's directory.
Also, don't put an apply plugin: 'android' statement in that top-level build file; it will cause an error.
You can also add dependencies through the Project Structure UI, which does the right thing.
Do not add dependencies in your project by editing its most 'external' build.gradle (YourProject/build.gradle). Edit the one that is under the 'app' module instead (YourProject/app/build.gradle).
There, by the way, you will find the declaration of one dependency, such as:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
This block will be just below android { ... } configuration block.
In my case, I am just adding leeloo dependencies, so it became:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'net.smartam.leeloo:oauth2-client:0.1'
compile 'net.smartam.leeloo:oauth2-common:0.1'
}
Then sync your project and dependencies will be downloaded. Hope it helps!
the compile-time dependencies should reside in the dependencies block under allprojects, not under buildscript:
apply plugin: 'android'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
}
}
allprojects {
repositories {
jcenter()
}
dependencies {
compile 'com.google.android.gms:play-services:18'
}
}
This should work fine.
Think of “Gradle DSL method” as a Java method. So in Gradle, methods can be distinguished by either {} or “.”. So
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
is the same as
dependencies.compile fileTree(dir: 'libs', include: ['*.jar'])
where both “dependencies” and “compile” are methods.
So you are including a method somewhere in your build.gradle file that is not supported by your program. For example, make your dependencies this:
dependencies {
nothing 'this.does.nothing.build:gradle:0.7.+'
}
Which is the same as writing:
dependencies.nothing 'this.does.nothing.build:gradle:0.7.+'
And you will see an error saying “unsupported Gradle DSL method found: ‘nothing()’!”
Obviously "nothing" is not a real method. I just made it up.
So one of your "compile" methods inside your build.gradle is wrong.
When I faced this problem I used android developer UI to import dependencies as follows:-
1 Go to View ---> Open Module Settings
Select Dependency tab. Click + to add a dependency and select Library dependency. Choose the downloaded library here.
So I have the following dependencies section in gradle
dependencies {
compile project(':sdi-master')
compile fileTree(dir: '../webserver/lib', include: '*.jar')
compile fileTree(dir: '../webserver/play-1.2.4/framework/lib', include: '*.jar')
compile fileTree(dir: '../webserver/play-1.2.4/framework', include: 'play-*.jar')
}
I also have a copy jars task like so
task deleteJars(type: Delete) {
ext.collection = files { genLibDir.listFiles() }
delete ext.collection
}
task copyJars(type: Copy) {
from(configurations.compile) {}
into genLibDir
}
copyJars.dependsOn('deleteJars')
classes.dependsOn('copyJars')
Notice how it depends on sdi-master which then has ONE compile fileTree as well. When I run copyJars, as expected, I get all the jars from the sdi-master as well copied into genLibDir. When I run the eclipse task however, those jars do NOT show up in the .classpath file as I would expect so my project doesn't compile in eclipse.
Is this a gradle eclipse task bug I need to report or is this supposed to be the behavior(though it seems very inconsistent with the copy jars using configurations.compile.
thanks,
Dean
Eclipse understands transitive dependencies, so the dependencies of sdi-master will not (and should not) show up in the current project's .classpath file. They should just show up in sdi-master's .classpath file and should be marked as exported there.