Gradle Dependencies and Dependency Configurations TODEPLETE
Internal
Overview
Configuration, in this context, does not refer to a configuration file, as in a settings configuration or a build configuration. It refers to named set of dependencies or artifacts, and it can probably thought of as being a concept similar to a Maven scope.
TO Deplete
Dependency
A dependency is an artifact, usually located in a repository, the project needs to build. It can be seen as a pointer to another piece of software.
In Gradle, dependencies are declared in build.gradle.
At runtime, Gradle will attempt to locate declared dependencies needed for the task being executed. This process may involve access and download from a remote repository, retrieval from a local directory, or building another project, in case of a multi-project build. This process is called dependency resolution https://docs.gradle.org/current/userguide/introduction_dependency_management.html#sec:dependency_resolution. A specific dependency may find itself in the dependency graph because it was declared in the build script or it is dependency of a declared dependency (transitive dependency).
Whenever Gradle tries to resolve a dependency in a repository, it looks for a metadata file and the default artifact file, a JAR. The build fails if none of these artifact files can be resolved. Under certain conditions, tweaking the way Gradle resolves artifacts for a dependency might be desired. TODO https://docs.gradle.org/current/userguide/declaring_dependencies.html#sub:resolve_specific_artifacts_from_dependency
Once a dependency is resolved, Gradle stores into a local cache, referred to as the dependency cache.
Dependencies are declared with:
dependencies {
...
}
in:
Dependency Management
Dependency management is a technique for declaring, resolving and using dependencies required by the project in an automated fashion.
Dependency Types
Module Dependency
Module dependency is the most common form of dependency. It refers to a module in a repository.
TODO https://docs.gradle.org/current/userguide/dependency_types.html#sub:module_dependencies
Local File Dependency
TODO:
- https://docs.gradle.org/current/userguide/declaring_dependencies.html#sec:declaring_file_dependency
- https://docs.gradle.org/current/userguide/dependency_types.html#sub:file_dependencies
Project Dependency
TODO:
- https://docs.gradle.org/current/userguide/dependency_types.html#sub:project_dependencies
- https://docs.gradle.org/current/userguide/declaring_dependencies.html#sec:declaring_project_dependency
Gradle Distribution-Specific Dependency
TODO https://docs.gradle.org/current/userguide/dependency_types.html#sub:api_dependencies
Dependency Configuration
A dependency configuration is a named set of dependencies grouped together for a specific goal. For example, some dependencies should be used during the compilation phase, whereas others need to be available during the testing phase, or at runtime. These are dependency scopes, and Gradle represents the scope of a dependency with the help of a Configuration. Each configuration can be identified by a unique name. Many Gradle plugins add pre-defined configurations to the project. For example, the Java plugin adds configurations to represent the various classpaths needed for compilation, testing, etc. A dependency configuration has three main purposes:
- To declare dependencies: plugins use dependency configurations to allow build authors to declare what other subproject of external artifacts are needed during the execution of tasks defined by the plugin.
- To resolve dependencies: plugins use dependency configurations to find and download inputs to the tasks it defines.
- To expose artifacts for consumption: plugins use dependency configurations to define what artifacts it generates. Configurations are using during the artifact publishing process.
Configurations can be displayed with:
task configs {
configurations.each { println it.name }
}
The same configurations (with more details attached) are displayed by
gradle dependencies
Custom configurations may be defined: https://docs.gradle.org/current/userguide/managing_dependency_configurations.html#_defining_custom_configurations.
Configuration Hierarchy
A configuration can extend other configurations to form an inheritance hierarchy. Child configurations inherit the whole set of dependencies declared for any of its superconfigurations. Dependencies may be inherited from other configurations: https://docs.gradle.org/current/userguide/managing_dependency_configurations.html#sub:inheriting_dependencies_from_other_configurations.
Dependency Constraint
A dependency constraint defines requirements that need to be met by a module to make it a valid result for a dependency resolution process. A recommended practice for large projects is to declare dependencies without versions and use dependency constraints for version declaration. The advantage is that dependency constrains allow you to manage versions of all dependencies, including transitive ones, in one place.
Dynamic Version
An aggressive approach for consuming dependencies is to declare that a module depends on the latest version of a dependency, or the latest version of a version range. This approach is called dynamic versioning. By default, Gradle caches dynamic versions of dependencies for 24 hours. Within this time frame, Gradle does not try to resolve newer versions from the declared repositories. This threshold can be configured. The build.gradle syntax for dynamic versioning is:
dependencies {
implementation 'org.slf4j:slf4j-api:1.2.+'
}
Changing Versions or Snapshots
In Maven, changing versions are referred to as napshots.
TODO when needed https://docs.gradle.org/current/userguide/declaring_dependencies.html#sub:declaring_dependency_with_changing_version
Resolution Rule
A resolution rule influences the behavior of how a dependency is resolved. Resolution rules are defined as part of the build logic. TODO https://docs.gradle.org/current/userguide/customizing_dependency_resolution_behavior.html.
Transitive Dependency
A transitive dependency is a dependency of a dependency of a module. The immediate dependencies are declared in a module's metadata, and the build system is supposed to automatically resolve the dependency graph. TODO: https://docs.gradle.org/current/userguide/managing_transitive_dependencies.html. Gradle offers facilities to inspect the transitive dependency graph.
The Dependency Cache
Once a dependency is resolved as result of the dependency resolution, Gradle stores the associated artifacts in a local cache, known as the dependency cache.
The Gradle dependency cache consists of two storage types located under Gradle user home caches subdirectory: file-based storage for downloaded artifacts and raw metadata files, and a binary store of resolved module meta-data.
Example:
$HOME/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.12/8e20852d05222dc286bf1c71d78d0531e177c317/slf4j-api-1.7.12.jar