xref: /Lucene/help/dependencies.txt (revision 1679076bdef9142ba21000227115533b7517791b)
1Dependencies
2============
3
4Each gradle project can have multiple (named) "configurations"
5and each configuration can have dependencies attached to it.
6
7There are some standard conventions so, for example, the Java plugin
8adds standard configurations such as "api", "implementation",
9"testImplementation" and others. These configurations can also inherit
10from each other; more about this typic can be found here:
11
12https://docs.gradle.org/current/userguide/dependency_management_for_java_projects.html#dependency_management_for_java_projects
13https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation
14https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_plugin_and_dependency_management
15
16Lucene typically uses three configurations and attach project
17dependencies to them:
18
19api  - makes a dependency available for main classes, tests and any
20  other modules importing the project (exportable dependency),
21
22implementation - makes a dependency available for main classes, tests
23  but will *not* export the dependency for other modules (so their
24  compilation classpath won't contain it).
25
26testImplementation - makes a dependency only available for test  classes.
27
28
29Adding a library dependency
30---------------------------
31
32Let's say we wish to add a dependency on library "foo.bar:baz" in
33version 1.2 to :lucene:core. Let's assume this library is only
34used internally by the project. The :lucene:core project is configured
35by lucene/core/build.gradle and we would add (or modify) the dependency
36block as follows:
37
38dependencies {
39  implementation "foo.bar:baz"
40}
41
42The "implementation" here is a named configuration; we don't need to declare
43it because it is declared for us by the java-library plugin.
44
45In "normal" gradle the version of the dependency would be present
46directly inside the declaration but we use a plugin
47(palantir-consistent-versions) to manage all dependency versions
48from the top-level (so that conflicts can be resolved globally).
49
50If this is the first time "foo.bar:baz" is added to the project, we'd have
51to add its version to "versions.props" file at the top level of the
52checkout:
53
54foo.bar:baz=1.2
55
56and then regenerate the "versions.lock" file using the following
57command:
58
59gradlew --write-locks
60
61IMPORTANT: The versions.lock file will contain the actual version
62of the dependency picked based on other project dependencies and
63their transitive dependencies. This selected version may be
64different from what each of these actually requires (the highest
65version number will be typically selected). To see which dependencies
66require which version of the library use:
67
68gradlew why --hash=...
69
70where the hash code comes from versions.lock file. For example, at
71the time of writing, jackson-databind has the following entry:
72
73com.fasterxml.jackson.core:jackson-databind:2.10.0 (3 constraints: 931a7796)
74
75and "gradlew why --hash=931a7796" prints:
76
77com.fasterxml.jackson.core:jackson-databind:2.10.0
78        projects -> 2.10.0
79        net.thisptr:jackson-jq -> 2.7.0
80        org.carrot2:carrot2-mini -> 2.9.9.3
81
82Once the dependency is added it always makes sense to see the
83tree of all module dependencies and maybe exclude transitive
84dependencies of foo.bar:baz that we won't need.
85
86
87Inspecting current dependencies
88-------------------------------
89
90The tree of dependencies of a project (in all configurations) can
91be dumped by the following command (example):
92
93gradlew -p lucene\analysis\icu dependencies
94
95But this can be a bit overwhelming; we will most likely be interested
96in just the "publicly visible" and "classpath-visible" configurations.
97
98The publicly visible project dependencies (classes shared by other
99modules importing our module) can be displayed with:
100
101gradlew -p lucene\analysis\icu dependencies --configuration api
102
103And the "private" set of dependencies (real classpath) can be dumped
104with:
105
106gradlew -p lucene\analysis\icu dependencies --configuration runtimeClasspath
107
108
109Excluding a transitive dependency
110---------------------------------
111
112Let's say "foo.bar:baz" has a transitive dependency on project
113"foo.bar:irrelevant" and we know the transitive dependency is not
114crucial for the functioning of "foo.bar:baz". We can exclude it
115by adding an exclusion block to the original declaration:
116
117dependencies {
118  implementation("foo.bar:baz", {
119    exclude group: "foo.bar", module: "irrelevant"
120  })
121}
122
123Note the brackets - they are important and prevent accidental
124mistakes of applying the exclusion to the wrong scope.
125
126
127Updating dependency checksum and licenses
128-----------------------------------------
129
130The last step is to make sure the licenses, notice files and checksums
131are in place for any new dependencies. This command will print what's
132missing and where:
133
134gradlew licenses
135
136To update JAR checksums for licenses use:
137
138gradlew updateLicenses
139