gradle difference between testRuntime and testProvided - gradle

Single question:
In gradle, there are several configurations provided out of the box.
For example testCompile, testProvided, testRuntime, javaCompile, javaProvided, and so on...
Could you explain what's the difference?

Configurations allow you to scope dependencies. Given this configuration hierarchy:
testRuntime -> testCompile -> runtime -> compile
Each configuration helps you limit where your dependencies are. *Runtime configurations allow you to include a dependency, but not have it as a compile dependency. This is helpful when you want to keep a framework loosely coupled from a project. A runtime dependency means that you need it for the app to run, but don't need it to compile.
The same thing applies for the test* configurations.
Ref:
Gradle Docs - Dependency configurations

In addition to Ethan's answer: the provided configurations contain dependencies that are used during compile but are not packaged to the final artifact. This is for example useful when you develop for a container that provides these dependencies already in its installation.

Related

How to manage gradle transitive dependency conflicts?

I have a project that has a build.gradle that looks like the following:
compile project(':project1')
compile project(':project2')
compileOnly(group: 'org.scala-lang', name: 'scala-library', version: '2.10.5')
Let's say it is not easy to identify the exact dependencies that I need in "project1", which is the main reason why we have this "whole project" dependency in the first place. Assuming that project1 also depends on scala-lang but a wildly different version. At runtime, some part of our code depends on this "scala-lang" from project1 dependencies, while some other part of the code depends on the scala-lang I specified via compileOnly().
This is just one example, my actual code depends on many projects and many many more individual libraries. Let's also assume that breaking the monolithic code base into smaller and more manageable components is not doable at this time. What are some great ways to manage dependencies and transitive dependencies in Java gradle project? Thanks!

Gradle dependency scopes

I was experimenting a little bit with Gradle but as mainly being a Maven user, some dependency scopes are confusing me …
Some are identical to Maven:
compile -> compile
runtime -> runtime
compileOnly -> provided
but I also encounter implementation which sounds like the parent element of Maven POM but then again also not.
Can somebody explain me what is implementation and some other if they exist and I didn’t mention here (test versions of above are clear no need to explain)?
And if implementation is not like parent on Maven, how can we have the parent POM effect of Maven in Gradle?
As commented, please have a look at the documentation or even at this recent webcast (disclaimer: I am co-presenting that webcast)
As for the Maven comparison, view migrating / learning from Maven to Gradle the same as moving from subversion to git: while some vocabulary is the same, understanding the model of the later helps more than comparing.
In short:
Do not use compile or runtime in Gradle, they are deprecated.
implementation relates to dependencies that are required to compile and run your application.
compileOnly and runtimeOnly should be self-explanatory in the context of the above
The java-library plugin adds the api configuration which is reserved for dependencies that consumers of your library will need to compile.
There is no direct equivalent to a Maven parent pom. Whether you are talking about plugins, build config or dependencies, the way to centralize are different. Have a look at the documentation on multi-project authoring.

How to add project dependencies to specific platform targets created by the `kotlin-multiplatform` plugin?

Previously, building multiplatform projects using Gradle relied on separate Gradle plugins per targeted platform: kotlin-platform-common, kotlin-platform-js, and kotlin-platform-jvm.
Starting from Kotlin 1.3, this is now unified using one kotlin-multiplatform plugin. The current documentation specifies how to set up multiplatform projects using this approach.
However, in my project I have multiple multiplatform projects with some dependencies between them. With the old multiplatform configuration, each different platform is a separate module and adding dependencies between projects required adding project references in each platform-specific module to corresponding modules in the other project: e.g., project(':some-library:some-library-js') to add a dependency to the JS module from within another JS module.
While migrating to the new multiplatform configuration, I now need to add a dependency from a project configured using the old configuration method to a project configured using the new kotlin-multiplatform plugin.
Given that platform-specific modules are now specified and managed by the new plugin, how do I go about this?
I'm not certain whether the following approach is the recommended method, or I overlooked any potential issues, but my projects compile and all tests pass.
In Gradle, you can add dependencies to specific project configurations:
dependencies {
implementation project(path: ':some-library', configuration: 'configName')
}
By trial and error I figured out that specifying the following configuration dependencies per platform module type works:
common: configuration: 'archives'. Without this, Gradle configuration fails as code dependencies are not found.
Without the following, compilation fails:
jvm: configuration: 'jvmDefault'
js: configuration: 'jsDefault'
For example, for the JS module as specified in the question:
dependencies {
implementation project(path: ':some-library', configuration: 'jsDefault')
}
Basically, you don't need to specify the platform in project-to-project dependencies involving Kotlin Muiltiplatform projects. The Kotlin plugin sets up dependency resolution in a way that Gradle will choose the appropriate target's artifacts automatically.
So, for example, in a Kotlin/JVM single-target project, you can just use a project("...") dependency on a Multiplatform project:
dependencies {
implementation(project(":multiplatform-library")
}
If :multiplatform-library has a JVM target, this dependency will get resolved to the JVM target's artifact. Otherwise, you will encounter a dependency resolution failure with candidate configurartions listed.
This is described in the Kotlin reference, Building Multiplatform Projects with Gradle – Adding Dependencies, but is applicable to single-platform projects, too:
<...> a project('...') dependency on another multiplatform project is resolved to an appropriate target automatically. It is enough to specify a single project('...') dependency in a source set's dependencies, and the compilations that include the source set will receive a corresponding platform-specific artifact of that project, given that it has a compatible target.
If this does not happen for you, please post the specific dependency resolution failure log, or file an issue at https://kotl.in/issue.

What is the difference between an app dependency and a module dependency/plugin?

When using some 3rd party libraries, I add a dependency to my module's build.gradle file.
compile 'com.android.support:appcompat-v7:24.1.1'
Or I add a plugin
apply plugin: 'com.neenbedankt.android-apt'
Some other times, the library requires adding a dependency to my app's build.gradle file.
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
What is the difference between these dependencies and plugins?
Why can't they all be set in a single build.gradle file?
All suggestions are appreciated, I'm having trouble searching for info on this
Three things. Gradle plugin, module dependency, a build dependency which is placed on the classpath of the build tool.
A plugin is how Gradle knows what tasks to use. There are many plugins. For more info, see Gradle - Plugin Documentation
A dependency is a library that is compiled with your code. The following line makes your module depend on the Android AppCompat V7 library. For the most part, you search Maven or Jcenter for these.
compile 'com.android.support:appcompat-v7:24.1.1'
The classpath setting is needed for Gradle, not your app. For example, this allows this includes the Gradle Build Tools for Android into the classpath, and allows Gradle to build apps.
classpath 'com.android.tools.build:gradle:2.1.2'
Why can't they all be in one build.gradle file?
They probably can be. It is simply more modular to not.
I got this answer from a colleague, and this helped me understand. "A gradle plugin is like the tools you use to build the app. The dependencies are the libraries included in the app. A gradle plugin is usually the tasks - like ktlint, etc."
I didn't understand this myself so here is what i found. My answer is based on gradle build tool.
Plugins:
Add additional tasks, repositories, new DSL elements, configuration for classpaths/build/run or dependency management for subsequent development. Plugins are developed for a larger scope of development like java, kotlin or spring-boot.
Dependencies:
modules/libraries for tasks like http, serialization or database are dependencies stored remotely at repositories or locally that are needed at runTime, test or build are resolved by gradle in a configured fashion.
Sources:
Spring boot gradle plugin: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin
Gradle documentation on plugins/dependencies: https://docs.gradle.org/current/userguide/plugins.html
https://docs.gradle.org/current/userguide/core_dependency_management.html
Remote repositories:
https://mvnrepository.com/
In simple words:
Plugins are used to add some additonal features to the software/tools(like Gradle). Gradle will use the added plugins at the time of building the App.
Dependecies are used to add some addtional code to your source code, so a dependency will make some extra code (like Classes in Java) in the form of library available for your source code.

How do I prevent Gradle from exporting a dependency?

I have two Android apps that share a subproject. The build.gradle in the subproject contains a dependency like this:
dependencies {
compile "my.library.dependency:${version}"
}
What I'd like is to use this dependency at compile time, but not runtime. This is because the two apps need to link against slightly different versions of the dependency (same API).
The Gradle docs describe dependency configurations like this:
compile The dependencies required to compile the production source of
the project.
runtime The dependencies required by the production classes at
runtime. By default, also includes the compile time dependencies.
If runtime also includes compile dependencies, does this mean the library is exported from the subproject to the parent projects (and included in my apk)? If so, how do I prevent this? I assume it's possible because it says "by default".
Thanks in advance...
It's not clear if your subproject is using the android-library plugin, but if it is, v0.8 has added a provided scope -- see http://tools.android.com/recent/androidstudio043released.
This should work:
dependencies {
provided "my.library.dependency:${version}"
}
If you upgrade to 0.8 of the plugin, you'll need to run Gradle 1.10 (update gradle-wrapper.properties if you're using the wrapper), and if you're using Android Studio, upgrade to 0.4.3.

Resources