So let's say I have project A, which requires certain dependencies. And I have project B, which has project A as one of its dependencies. So I have the following code in project B's build.gradle:
project B's build.gradle:
dependencies {
compile files("projectA_dir/build/libs/projectA.jar")
}
However, since Gradle does not include project A's dependencies in projectA.jar by default. I was wondering if there's a way to let project B successfully compile project A without creating a fatjar for project A.
The jar file doesn't contain the transitive dependencies and doesn't have a pom file which describes the dependencies used by the module.
It means that, if you are importing a jar file using compile files you have to specify the dependencies also in your project.
You should use a maven repository, private or public, to avoid the issue.
In this case, gradle downloads the dependencies using the pom file which will contains the dependencies list.
Related
I have build.gradle in front of me and there are some dependencies declared as provided but in documentation I do not see this dependency scope.
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.2.4.RELEASE")
....
provided 'backport-util-concurrent:backport-util-concurrent:3.1'
provided 'org.javolution:javolution:5.5.1#jar
....
}
Is this provided by a plugin? If so how do I found out which plugin this belongs to?
What is the difference between provided and runtime dependency scope in Gradle?
What is provided scope?
Suppose that a jar is needed to compile your code, but the jar is present in the production environment library collection. Then you don't need to package the jar with your project archives. To support this requirement, Maven has a scope named provided. If you declare any jar dependency as provided, then this jar will be present in your classpath during compilation but will not be packaged with your project archive.
provided scope is very useful, particularly in web applications. For example, servlet-api.jar is needed to be present in your classpath to compile your project, but you don't need this to package servlet-api.jar file with your war. With provided scope one can achieve this requirement.
There is no Scope defined in Gradle java plugin named provided. Also not in war or android plugins. If you want to use provided scope in your project, then you have to define it in your build.gradle file. Following is the code snippet to declare provided scope in gradle:
configurations {
provided
}
sourceSets {
main { compileClasspath += configurations.provided }
}
Now, your second question:
What is the difference between provided and runtime dependency scope in Gradle?
To answer this question first I will define compile dependency. compile dependencies are dependencies, those are necessary to compile your code. Now imagine that if your code uses a library named X then you must declare X as your compile-time dependency. Also imagine that X uses another library Y internally, and you declared Y as your runtime dependency.
During compilation, Gradle will add X into your classpath but will not add Y. Since, Y is not required for compilation. But it will package both X and Y with your project archive since both X and Y are necessary to run your project archive in the production environment. Generally, all the dependencies needed in the production environment are known as runtime dependency.
In Gradle official documentation, it says that runtime dependency are "the dependencies required by the production classes at runtime. By default, also includes the compile time dependencies.".
Now, if you've read this far, then you already know that provided is a compile dependency that we don't want to be present in the runtime dependency (basically, we don't want it to package with the project archive).
Following is an illustration of provided and runtime scope. Here, compile refers to the dependencies that are required to compile the project and non-compile refers to the dependencies that are not required for project compilation.
As from Gradle 2.12, you can use the compileOnly option.
See
https://blog.gradle.org/introducing-compile-only-dependencies
For further clarification, as of the latest version, Gradle 5.5 has compileOnly (same as provided) and runtimeOnly options. The new default "compile and runtime" option is implementation.
Updating the answer as per the latest gradle versions.
From gradle's official documentation at below link:
https://docs.gradle.org/current/userguide/upgrading_version_5.html
Deprecations
Dependencies should no longer be declared using the compile and runtime configurations. The usage of the compile and runtime
configurations in the Java ecosystem plugins has been discouraged
since Gradle 3.4.
The implementation, api, compileOnly and runtimeOnly configurations should be used to declare dependencies and the compileClasspath and
runtimeClasspath configurations to resolve dependencies.
More so, the compile dependency configuration has been removed in the recently released Gradle 7.0 version.
If you try to use compile in your Gradle 3.4+ project you’ll get a warning like this:
Deprecated Gradle features were used in this build, making it
incompatible with Gradle 7.0. Use ‘–warning-mode all’ to show the
individual deprecation warnings.
You should always use implementation rather than compile for dependencies, and use runtimeOnly instead of runtime.
War plugin
The War plugin extends the Java plugin to add support for assembling web application WAR files. It disables the default JAR archive
generation of the Java plugin and adds a default WAR archive task.
The War plugin adds two dependency configurations:
providedCompile
providedRuntime
Adding an entry to providedCompile or providedRuntime will cause that dependency to be excluded from the war file.
Use providedCompile if you have source that relies on some classes
for compiling.
Use providedRuntime if you use it for testing and not
compiling.
Example:
providedCompile 'org.springframework.boot:spring-boot-starter-tomcat:1.1.6.RELEASE'
The above JAR and its transitive dependency will only be available at compile time but it will not be available at runtime. It means, those JAR will not be included in war archive.
How can I include a local jar dependency and its corresponding sources jar (for my IDE, Intellij) in Gradle?
I have tried adding a flatDir to lib (a directory in the same parent directory as all the Gradle stuff) under repositories, where lib contains mylib-1.0.jar and mylib-1.0-sources.jar. I then put implementation name: "mylib-1.0" under dependencies. The jar with compiled classes was included, but not the sources.
I also tried creating a local maven repository. In this case, lib contained
lib/xxx/yyy/mylib/1.0/mylib-1.0.jar
and
lib/xxx/yyy/mylib/1.0/mylib-1.0-sources.jar
where xxx.yyy is the group ID. I added
maven {
url uri("lib")
}
under repositories and
implementation group: "xxx.yyy", name: "mylib", version: "1.0"
under dependencies. Still did not work--neither jars were included this time.
I also tried adding a minimal POM in the same directory as both the jars, but that did not change anything.
Any idea as to where I could be going wrong?
Note: I am no expert at using Gradle or Maven.
Edit: Rationale: in case somebody suggests it, I am aware I can just include as a dependency the jar with the compiled class and "link" the sources jar to it in Intellij, but then every time I refresh gradle I have to re-link them.
I provide below the following approaches.
Prior to gradle 5
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
}
Here libs is the directory which contains the list of jar files and it should be location inside your project base directory.
You can also use in the following manner if you have only one jar file. Here libs refer to the directory which contains only one jar file and libs is available in the project base directory.
dependencies {
compile files('libs/your jar file name.jar')
}
If you want to specify a list of jar files, you can use in the following manner.
dependencies {
compile files(‘libs/a.jar’,
‘libs/b.jar’,
‘libs/c.jar’
)
}
In Gradle 5
You have to use in the follwong manner.
dependencies {
externalLibs files('libs/a.jar', 'libs/b.jar')
}
I am developing two gradle projects, project A and project B. Project A is dependent on project B. I want to add project B into the dependencies of project A, like adding a dependency from maven central.
I could compile project B into a fat jar and add the jar file into the dependencies of project A, but there is a problem: the dependencies of project A and project B conflicted.
For example, there is compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5' in both projects.
I could compile project B into a fat jar and add the jar file into the dependencies of project A
No, never do that, of course it will trigger dependencies issues. ProjectA has no way to determine if a dependency is a duplicate in a fat jar. Gradle has a built-in way to handle it.
project(':projectA') {
dependencies {
compile project(':projectB')
}
}
I am trying to make an android library public on maven, this artifact contains another three modules, and each modules is an aar file, which means it has string, layout resources. The structure of the library A is:
+ Library A
-- Module 1
-- Module 2
-- Module 3
And in build.gradle of library A, I include these three modules by using
compile project (:module1);
compile project (:module2);
compile project (:module3);
But when I use this library in new project's gradle, it cannot find all the submodules. The error message is:(assume all modules version is 1.0)
Could not find module1:1.0
Searched in the following locations:
file:/Users/chan/Documents/AndroidSDK/sdk/extras/m2repository/project/modules/widgets/module1/1.0/module1-1.0.pom
file:/Users/chan/Documents/AndroidSDK/sdk/extras/m2repository/project/modules/widgets/module1/1.0/module1-1.0.jar
file:/Users/chan/Documents/AndroidSDK/sdk/extras/google/m2repository/project/modules/widgets/module1/1.0/module1-1.0.pom
file:/Users/chan/Documents/AndroidSDK/sdk/extras/google/m2repository/project/modules/widgets/module1/1.0/module1-1.0.jar
file:/Users/chan/Documents/AndroidSDK/sdk/extras/android/m2repository/project/modules/widgets/module1/1.0/module1-1.0.pom
file:/Users/chan/Documents/AndroidSDK/sdk/extras/android/m2repository/project/modules/widgets/module1/1.0/module1-1.0.jar
https://maven.google.com/project/modules/widgets/module1/1.0/module1-1.0.pom
https://maven.google.com/project/modules/widgets/module1/1.0/module1-1.0.jar
https://maven.com/artifactory/libs-release-local/project/modules/widgets/module1/1.0/module1-1.0.pom
https://maven.com/artifactory/libs-release-local/project/modules/widgets/module1/1.0/module1-1.0.jar
https://repo1.maven.org/maven2/project/modules/widgets/module1/1.0/module1-1.0.pom
https://repo1.maven.org/maven2/project/modules/widgets/module1/1.0/widgets-unspecified.jar
Same error for module2 and module3.
I dont know why it cannot find the modules.
The Library A is configured in new project:
compile ('LibraryA:1.0#aar') {
transitive=true
}
The followings are what I have tried so far, with no luck:
I have added mavenCentral(), mavenLocal() or jcenter() in reporsitories() but still no luck.
Tried using fat-aar android https://github.com/adwiv/android-fat-aar on library. No luck.Same error
Added flatDir in reporsitories, no luck
Any suggestions would be much appreciated!
My Gradle project has a couple of maven dependencies. I don't want those included in my jar. It also has some dependencies on local jars. How can i include the classes from those in the output jar?
You can refer to a local repository (a directory in this case) with the following:
repositories {
ivy {
// URL can refer to a local directory
url "../local-repo"
}
}
To exclude the dependent jars from your final jar, you can use the compile configuration like this:
compileOnly files('libs/jgrapht-jdk1.6.jar')
compile 'org.simpleframework:simple-xml:2.7'
A more detailed answer can be seen over here:
Gradle dependencies local jar file