• Tidak ada hasil yang ditemukan

Managing dependencies

Dalam dokumen Gradle User Manual Version 5.4.1 (Halaman 79-83)

Example 15. Declaring dependencies served from the filesystem

build.gradle repositories {   flatDir {

  name = 'libs dir'   dir file('libs') ①   }

}

dependencies {

  implementation files('libs/our-custom.jar') ②   implementation ':log4j:1.2.8', ':commons-io:2.1' ③ }

build.gradle.kts repositories {   flatDir {

  name = "libs dir"

  dir(file("libs")) ①   }

}

dependencies {

  implementation(files("libs/our-custom.jar")) ②   implementation(":log4j:1.2.8") ③

  implementation(":commons-io:2.1") ③ }

①Specifies the path to the directory containing the JAR files

②Declares a file dependency for the unversioned JAR

③Declares dependencies using standard dependency coordinates — note that no group is specified, but each identifier has a leading :, implying an empty group

The above sample will add our-custom.jar, log4j-1.2.8.jar and commons-io-2.1.jar to the implementation configuration, which is used to compile the project’s code.

NOTE

You can also specify a group in these module dependencies, even though they don’t actually have a group. That’s because the flat-directory repository simply ignores the information.

If you then add a normal Maven- or Ivy-compatible repository at a later date, Gradle will preferentially download the module dependencies that are declared with a group from that repository rather than the flat-directory one.

Migrating Ivy dependencies

Apache Ivy is a standalone dependency management tool that is widely used with Ant. It works in a similar fashion to Gradle. In fact, they both allow you to

• Define your own configurations

• Extend configurations from one another

• Attach dependencies to configurations

• Resolve dependencies from Ivy-compatible repositories

• Publish artifacts to Ivy-compatible repositories

The most notable difference is that Gradle has standard configurations for specific types of projects.

For example, the Java Plugin defines configurations like implementation, testImplementation and runtimeOnly. You can still define your own dependency configurations, though.

This similarity means that it’s usually quite straightforward to migrate from Ivy to Gradle:

• Transcribe the dependency declarations from your module descriptors into the dependencies {}

block of your Gradle build script, ideally using the standard configurations provided by any plugins you apply.

• Transcribe any configuration declarations from your module descriptors into the configurations {} block of the build script for any custom configurations that can’t be replaced by Gradle’s standard ones.

• Transcribe the resolvers from your Ivy settings file into the repositories {} block of the build script.

See the chapters on Declaring Dependencies, Managing Dependency Configurations and Declaring Repositories for more information.

Ivy provides several Ant tasks that handle Ivy’s process for fetching dependencies. The basic steps of that process consist of:

1. Configure — applies the configuration defined in the Ivy settings file

2. Resolve — locates the declared dependencies and downloads them to the cache if necessary 3. Retrieve — copies the cached dependencies to another directory

Gradle’s process is similar, but you don’t have to explicitly invoke the first two steps as it performs them automatically. The third step doesn’t happen at all — unless you create a task to do it — because Gradle typically uses the files in the dependency cache directly in classpaths and as the

source for assembling application packages.

Let’s look in more detail at how Ivy’s steps map to Gradle:

Configuration

Most of Gradle’s dependency-related configuration is baked into the build script, as you’ve seen with elements like the dependencies {} block. Another particularly important configuration element is resolutionStrategy, which can be accessed from dependency configurations. This provides many of the features you might get from Ivy’s conflict managers and is a powerful way to control transitive dependencies and caching.

Some Ivy configuration options have no equivalent in Gradle. For example, there are no lock strategies because Gradle ensures that its dependency cache is concurrency safe, period. Nor are there "latest strategies" because it’s simpler to have a reliable, single strategy for conflict resolution. If the "wrong" version is picked, you can easily override it using forced versions or other resolution strategy options.

See the chapters on Managing Transitive Dependencies and Customizing Dependency Resolution Behavior for more information on this aspect of Gradle.

Resolution

At the beginning of the build, Gradle will automatically resolve any dependencies that you have declared and download them to its cache. It searches the repositories for those dependencies, with the search order defined by the order in which the repositories are declared.

It’s worth noting that Gradle supports the same dynamic version syntax as Ivy, so you can still use versions like 1.0.+. You can also use the special latest.integration and latest.release labels if you wish. If you decide to use such dynamic and changing dependencies, you can configure the caching behavior for them via resolutionStrategy.

You might also want to consider dependency locking if you’re using dynamic and/or changing dependencies. It’s a way to make the build more reliable and allows for reproducible builds.

Retrieval

As mentioned, Gradle does not automatically copy files from the dependency cache. Its standard tasks typically use the files directly. If you want to copy the dependencies to a local directory, you can use a Copy task like this in your build script:

Example 16. Copying dependencies to a local directory

build.gradle

task retrieveRuntimeDependencies(type: Copy) {   into "$buildDir/libs"

  from configurations.runtimeClasspath }

build.gradle.kts tasks {

  register<Copy>("retrieveRuntimeDependencies") {   into("$buildDir/libs")

  from(configurations.runtimeClasspath)   }

}

A configuration is also a file collection, hence why it can be used in the from() configuration. You can use a similar technique to attach a configuration to a compilation task or one that produces documentation. See the chapter on Working with Files for more examples and information on Gradle’s file API.

Dalam dokumen Gradle User Manual Version 5.4.1 (Halaman 79-83)

Dokumen terkait