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

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.

Related

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.

Gradle: After conversion of maven to gradle, what are the next steps to match up files?

Ive been working off the guides which mention to start by doing
gradle init
on the project. So this creates build.grade. However, the rest of the gradle file is very thinly padded. Im quite new to doing these conversions, but broadly speaking, what would be the next step to get things in harmony?
The Gradle docs lists the following features of the Maven POM conversion:
Uses effective POM and effective settings (support for POM inheritance, dependency management, properties)
Supports both single module and multimodule projects
Supports custom module names (that differ from directory names)
Generates general metadata - id, description and version
Applies maven, java and war plugins (as needed)
Supports packaging war projects as jars if needed
Generates dependencies (both external and inter-module)
Generates download repositories (inc. local Maven repository)
Adjusts Java compiler settings
Supports packaging of sources and tests
Supports TestNG runner
Generates global exclusions from Maven enforcer plugin settings
This means, every required functionality beyond these features must be added manually, either by searching and applying plugins equivalent to the ones used in Maven or by implementing the functionality on your own.

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.

Custom dependency management plugin in Gradle

How do you write a custom gradle plugin to handle dependencies in a custom module descriptor, from a custom repository? The gradle documentation says the following, but I haven't been able to find anything that tells me how.
Even if your project is using a custom dependency management system or
something like an Eclipse .classpath file as master data for
dependency management, it is very easy to write a Gradle plugin to use
this data in Gradle.
I've been maintaining a Custom Ivy resolver for ATG projects (forked from this project), but Gradle recently deprecated this with version 1.8, and I need to port the implementation to a native Gradle plugin.
Implementations of ATG use 'modules' (not unlike Gradle projects), that have a MANIFEST.MF file for a module descriptor. These files define other 'modules' that a module depends on, and also a list of paths (jars or directories) that form the (direct) classpath for the current module.
e.g.
ATG-Class-Path: lib/classes.jar lib/commons-beanutils-1.7.jar
ATG-Required: MyProj.core MyProj.integration.webservices DAF.Endeca.Assembler
Module dependencies are transitive, and may refer to custom modules or modules that sit within the ATG product installation. Hence, I need to define a custom repository that can use the ATG product installation as a source of artifacts.
Without Gradle, I need to maintain dependencies in the form of
ATG's MANIFEST.MF files
Eclipse .classpath files
Dependencies for the Ant build-script
SonarQube configurations
Since I can't get rid of the ATG MANIFEST.MF files, I would like to write a write a custom plugin to allows them to be used in Gradle builds. I can then use Gradle as my build system, which can also generate Eclipse .classpath and .project files, and run Sonar against the project.
Gradle seems to have a lot of source code, and rummaging through it for the last couple of days hasn't got me anywhere.
If someone can point me to a list of interfaces that need to be implemented to (1) implement a custom repository, and (2) implement a custom dependency resolver (to use custom files as module descriptors), that should be enough to get me started.
The Eclipse .classpath use case mentioned above can be solved by parsing that file and translating it to Gradle file dependencies. It isn't currently possible to plug in a custom repository implementation.

Resources