blob: c1c81c560b0862825495b7ba15b7d17e31dc4f00 [file] [log] [blame]
Dependencies
============
Each gradle project can have multiple (named) "configurations"
and each configuration can have dependencies attached to it.
There are some standard conventions so, for example, the Java plugin
adds standard configurations such as "api", "implementation",
"testImplementation" and others. These configurations can also inherit
from each other; more about this typic can be found here:
https://docs.gradle.org/current/userguide/dependency_management_for_java_projects.html#dependency_management_for_java_projects
https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation
https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_plugin_and_dependency_management
Solr typically uses three configurations and attach project
dependencies to them:
api - makes a dependency available for main classes, tests and any
other modules importing the project (exportable dependency),
implementation - makes a dependency available for main classes, tests
but will *not* export the dependency for other modules (so their
compilation classpath won't contain it).
testImplementation - makes a dependency only available for test classes.
Adding a library dependency
---------------------------
Let's say we wish to add a dependency on library "foo.bar:baz" in
version 1.2 to :solr:core. Let's assume this library is only
used internally by the project. The :solr:core project is configured
by solr/core/build.gradle and we would add (or modify) the dependency
block as follows:
dependencies {
implementation "foo.bar:baz"
}
The "implementation" here is a named configuration; we don't need to declare
it because it is declared for us by the java-library plugin.
In "normal" gradle the version of the dependency would be present
directly inside the declaration but we use a plugin
(palantir-consistent-versions) to manage all dependency versions
from the top-level (so that conflicts can be resolved globally).
If this is the first time "foo.bar:baz" is added to the project, we'd have
to add its version to "versions.props" file at the top level of the
checkout:
foo.bar:baz=1.2
and then regenerate the "versions.lock" file using the following
command:
gradlew --write-locks
IMPORTANT: The versions.lock file will contain the actual version
of the dependency picked based on other project dependencies and
their transitive dependencies. This selected version may be
different from what each of these actually requires (the highest
version number will be typically selected). To see which dependencies
require which version of the library use:
gradlew why --hash=...
where the hash code comes from versions.lock file. For example, at
the time of writing, jackson-databind has the following entry:
com.fasterxml.jackson.core:jackson-databind:2.10.0 (3 constraints: 931a7796)
and "gradlew why --hash=931a7796" prints:
com.fasterxml.jackson.core:jackson-databind:2.10.0
projects -> 2.10.0
net.thisptr:jackson-jq -> 2.7.0
org.carrot2:carrot2-mini -> 2.9.9.3
Once the dependency is added it always makes sense to see the
tree of all module dependencies and maybe exclude transitive
dependencies of foo.bar:baz that we won't need.
Update Lucene prerelease
------------------------
The main branch of Apache Solr uses a prerelease of Apache Lucene that
is published by ASF Jenkins on:
https://nightlies.apache.org/solr/lucene-prereleases/
If you want to upgrade Lucene to a newer build proceed like the following:
- Go to https://ci-builds.apache.org/job/Solr/job/Lucene-prerelease-main/
- Log in with ASF account
- Press on "build now" on left side
- Wait until build is finished.... (can take long time, if other builds are
queued)
- remember the build number of Jenkins (left side, first build in list,
prefixed by '#')
- Edit ./versions.props and change Lucene's version to '9.0.0-prereleaseX',
with 'X' is the jenkins build number
- Edit ./gradle/globals.gradle and change jenkins build number, too
(this directs the repository to the one created by latest build):
def lucenePrereleaseBuild = 'X'
- Run: gradlew --write-locks (as described before)
Lucene local dependency substitution
-------------------------------
Because of the fundamental nature of Solr's dependency on Lucene, Solr
facilitates dependency substitution to support developing against a local
Lucene version (e.g., for joint Solr and Lucene development).
A local Lucene dependency substitution is resolved by evaluating the
following conditions, in priority order:
1) A "-Plucene.dev.version=[version]" property, resolving Lucene artifacts
from a local Maven repository.
2) A non-empty property "-Plucene.dev.path=[path]" pointing to a local
path. Relative paths are resolved against the Solr root project
directory.
3) An auto-wired 'lucene' subdirectory, if present. To skip auto-wiring,
pass a blank value for condition 2: "-Plucene.dev.path=".
Note: Lucene dependencies substituted via conditions 2 and 3 require the
local Lucene repository to use the same Gradle version as the Solr root
project.
Local Maven repository Lucene artifacts (for use with the
"-Plucene.dev.version" project property) may be created by running the
following command from within a local Lucene project:
gradlew mavenToLocal
As is the case with project properties generally, the relevant properties
can be invoked on the command line, or configured via the gradle.properties
file (the latter approach is particularly useful for making IDEs aware of
associated dependency substitutions).
Inspecting current dependencies
-------------------------------
The tree of dependencies of a project (in all configurations) can
be dumped by the following command (example):
gradlew -p solr/solrj dependencies
But this can be a bit overwhelming; we will most likely be interested
in just the "publicly visible" and "classpath-visible" configurations.
The publicly visible project dependencies (classes shared by other
modules importing our module) can be displayed with:
gradlew -p solr/solrj dependencies --configuration api
And the "private" set of dependencies (real classpath) can be dumped
with:
gradlew -p solr/solrj dependencies --configuration runtimeClasspath
Excluding a transitive dependency
---------------------------------
Let's say "foo.bar:baz" has a transitive dependency on project
"foo.bar:irrelevant" and we know the transitive dependency is not
crucial for the functioning of "foo.bar:baz". We can exclude it
by adding an exclusion block to the original declaration:
dependencies {
implementation("foo.bar:baz", {
exclude group: "foo.bar", module: "irrelevant"
})
}
Note the brackets - they are important and prevent accidental
mistakes of applying the exclusion to the wrong scope.
Updating dependency checksums and licenses
-----------------------------------------
The last step is to make sure the licenses, notice files and checksums
are in place for any new dependencies. This command will print what's
missing and where:
gradlew licenses
To update JAR checksums (sha1) for licenses use:
gradlew updateLicenses