第51章 依存関係の管理

51.1. はじめに Introduction

Dependency management is a critical feature of every build, and Gradle has placed an emphasis on offering first-class dependency management that is both easy-to-understand and compatible with a wide variety of approaches. If you are familiar with the approach used by either Maven or Ivy you will be delighted to learn that Gradle is fully compatible with both approaches in addition to being flexible enough to support fully-customized approaches.

依存関係の管理は、あらゆるビルドで決定的に重要になる機能です。Gradleも、理解しやすく、既存の様々な管理方法との互換性も備えるような、最高の管理機能を提供することを重視してきました。 Gradleの管理機能はとても柔軟でカスタマイズ性の高いものですが、MavenやIvyでの管理に慣れ親しんできたなら、加えてMaven、Ivy双方と完全な互換性を保っていることはとても嬉しい利点となるはずです。

Here are the major highlights of Gradle's support for dependency management:

Gradleの依存関係管理機能で特筆すべき点を挙げると、

  • Transitive dependency management: Gradle gives you full control of your project's dependency tree.

    推移的な依存関係の管理: Gradleは、プロジェクトの依存関係ツリー全体を完全にコントロールできます。

  • Support for non-managed dependencies: If your dependencies are simply files in version control or a shared drive, Gradle provides powerful functionality to support this.

    未管理の依存関係もサポート: プロジェクトの依存ファイルを単純にバージョン管理システムや共有ドライブに格納したい場合も、Gradleはそれをサポートする強力な機能を持っています。

  • Support for custom dependency definitions.: Gradle's Module Dependencies give you the ability to describe the dependency hierarchy in the build script.

    依存関係定義のカスタマイズをサポート: Gradleでは、依存関係の階層構造をビルドスクリプトで直接定義できます。

  • A fully customizable approach to Dependency Resolution: Gradle provides you with the ability to customize resolution rules making dependency substitution easy.

    非常にカスタマイズ性の高い依存関係の解決方法: Gradleでは依存関係を解決する際のルールをカスタマイズでき、簡単に依存関係を差し替えることができます。

  • Full Compatibility with Maven and Ivy: If you have defined dependencies in a Maven POM or an Ivy file, Gradle provides seamless integration with a range of popular build tools.

    Maven、Ivyとの完全な互換性: 既にMavenのPOMやIvyファイルで依存関係を定義しているかもしれません。Gradleは人気のある様々なビルドツールとシームレスに連携できます。

  • Integration with existing dependency management infrastructure: Gradle is compatible with both Maven and Ivy repositories. If you use Archiva, Nexus, or Artifactory, Gradle is 100% compatible with all repository formats.

    既存の依存関係管理インフラとの連携: Gradleは、Maven、Ivyどちらの形式のリポジトリとも互換性があります。既にArchivaやNexus、Artifactoryなどを使用されているかもしれませんが、Gradleはそれらのリポジトリと100%の互換性を持っています。

With hundreds of thousands of interdependent open source components each with a range of versions and incompatibilities, dependency management has a habit of causing problems as builds grow in complexity. When a build's dependency tree becomes unwieldy, your build tool shouldn't force you to adopt a single, inflexible approach to dependency management. A proper build system has to be designed to be flexible, and Gradle can handle any situation.

現在無数に存在するオープンソースライブラリは、それぞれ互いに依存し合っていて、さらにバージョンや互換性の有無も様々なので、ビルドが複雑さを増すにつれて依存関係が問題を引き起こすことが増えてきます。ビルドの依存関係が扱いにくくなってきたとき、ツールによって柔軟性のない一つの管理方法に縛り付けられるようなことがあってはいけません。正しいビルドシステムは柔軟にできていなければならず、Gradleにしてもあらゆるシチュエーションに自在に対応できるようになっています。

51.1.1. ビルドツール移行に必要な依存関係管理の柔軟性 Flexible dependency management for migrations

Dependency management can be particularly challenging during a migration from one build system to another. If you are migrating from a tool like Ant or Maven to Gradle, you may be faced with some difficult situations. For example, one common pattern is an Ant project with version-less jar files stored in the filesystem. Other build systems require a wholesale replacement of this approach before migrating. With Gradle, you can adapt your new build to any existing source of dependencies or dependency metadata. This makes incremental migration to Gradle much easier than the alternative. On most large projects, build migrations and any change to development process is incremental because most organizations can't afford to stop everything and migrate to a build tool's idea of dependency management.

依存関係の管理で特に問題が発生しやすいのは、あるビルドシステムから別のビルドシステムへ移行するときです。 AntやMavenからGradleへ移行する際には、難しい問題に突き当たることがあるかもしれません。 例えば、よくあるAntプロジェクトですが、バージョンのないjarファイルがファイルシステムに置かれていたりすることがあります。この場合、移行先のビルドシステムによっては、管理方法を完全に置き換える必要が出てくるかもしれません。 一方Gradleでは、依存関係をどこから、どんなメタデータで取得していたとしても、新しいビルドでそれを変更する必要はありません。これにより、段階的にビルドシステムを移行することが他のツールに比べて容易になっているのです。大規模プロジェクトでは、ビルドにしてもその他のあらゆる開発プロセスにしても、段階的に移行していく場合がほとんどです。全てを止めてビルドツール固有の考え方へ依存関係管理を移行している余裕など、ほとんどの組織にはないからです。

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. For migration purposes this is a common technique with Gradle. (But, once you've migrated, it might be a good idea to move away from a .classpath file and use Gradle's dependency management features directly.)

プロジェクトが独自の方法で依存関係を管理していたとしても、例え依存関係のマスターデータにEclipseの.classpathを使っているようなプロジェクトであったとしても、Gradleでそのデータを使うためのプラグインを書くのはとても簡単な作業です。マイグレーションのためであれば、こうしたテクニックを使うことはGradleではごく普通のことです(ただ、移行が完了した後は、.classpathを使うのは止めてGradleの依存関係管理機能を直接使うのが良いとは思いますが)。

51.1.2. Javaにおける依存関係管理 Dependency management and Java

It is ironic that in a language known for its rich library of open source components that Java has no concept of libraries or versions. In Java, there is no standard way to tell the JVM that you are using version 3.0.5 of Hibernate, and there is no standard way to say that foo-1.0.jar depends on bar-2.0.jar. This has led to external solutions often based on build tools. The most popular ones at the moment are Maven and Ivy. While Maven provides a complete build system, Ivy focuses solely on dependency management.

Javaはその豊富なオープンソースライブラリで知られる言語ですが、皮肉なことにライブラリやバージョンといった概念が存在しません。 Javaでは、JVMに、今使っているものがHibernateのバージョン3.0.5であると伝える標準的な方法はありませんし、foo-1.0.jarbar-2.0.jarに依存していると伝える方法も標準では存在しないのです。 このため、これを実現するための様々なソリューションがサードパーティにより考案されてきました。また、ビルドツールに組み込まれることもよくあります。現在もっとも有名なものがMavenであり、Ivyです。Mavenがビルドシステムの機能全体を備えているのに対し、Ivyは依存関係の管理のみに焦点を当てています。

Both tools rely on descriptor XML files, which contain information about the dependencies of a particular jar. Both also use repositories where the actual jars are placed together with their descriptor files, and both offer resolution for conflicting jar versions in one form or the other. Both have emerged as standards for solving dependency conflicts, and while Gradle originally used Ivy under the hood for its dependency management. Gradle has replaced this direct dependency on Ivy with a native Gradle dependency resolution engine which supports a range of approaches to dependency resolution including both POM and Ivy descriptor files.

どちらのツールも、ある特定のjarファイルについて、その依存関係の情報をXML形式のディスクリプタに定義して使用します。また、リポジトリに実際のjarファイルをディスクリプタファイルと一緒に配置したり、jarのバージョンが競合したときに様々な形でそれを解決する手段を備えている点も同様です。 どちらも依存関係を解決するための標準的な方法となっており、Gradleも最初は依存関係管理機能の水面下でIvyを使用していました。 Gradleは、今ではそのように直接Ivyに依存するのではなく、Gradle独自の依存関係解決エンジンを使用しています。このエンジンは、POMおよびIvyディスクリプタによる管理方法を含め様々な方法に対応しています。

51.2. 依存関係管理のベストプラクティス Dependency Management Best Practices

While Gradle has strong opinions on dependency management, the tool gives you a choice between two options: follow recommended best practices or support any kind of pattern you can think of. This section outlines the Gradle project's recommended best practices for managing dependencies.

Gradleは依存関係の管理についてとても強固な指針を持ってはいますが、ユーザーには二つのオプションを提示しています。すなわち、Gradleの推奨するベストプラクティスに従うか、自分の考えたパターン(どんなものでも構いません)をサポートするビルドを書くかです。 この節では、Gradle Projectが推奨する依存関係管理のベストプラクティスについて概要を記載します。

No matter what the language, proper dependency management is important for every project. From a complex enterprise application written in Java depending on hundreds of open source libraries to the simplest Clojure application depending on a handful of libraries, approaches to dependency management vary widely and can depend on the target technology, the method of application deployment, and the nature of the project. Projects bundled as reusable libraries may have different requirements than enterprise applications integrated into much larger systems of software and infrastructure. Despite this wide variation of requirements, the Gradle project recommends that all projects follow this set of core rules:

開発言語にかかわらず、依存関係を正しく管理することはあらゆるプロジェクトで大事なファクターです。 数百ものオープンソースライブラリに依存した複雑なエンタープライズJavaアプリケーションから、わずかなライブラリのみを使った単純なClojureのアプリケーションまで、依存関係を管理するといってもその方法はとても幅広く、対象となる技術、アプリケーションのデプロイ方法、アプリケーションの性質などによっても違ってきます。 例えば、再配布して使用されることを想定したライブラリプロジェクトの場合、巨大なソフトウェアやインフラのシステムに組み込まれるエンタープライズアプリケーションとはまた別の管理が必要になるかもしれません。しかし、要求されることは様々であっても、Gradle Projectでは全てのプロジェクトで以下の指針に従うことを推奨しています。

51.2.1. ファイル名にバージョン番号を含める(jarのバージョニング) Put the Version in the Filename (Version the jar)

The version of a library must be part of the filename. While the version of a jar is usually in the Manifest file, it isn't readily apparent when you are inspecting a project. If someone asks you to look at a collection of 20 jar files, which would you prefer? A collection of files with names like commons-beanutils-1.3.jar or a collection of files with names like spring.jar? If dependencies have file names with version numbers you can quickly identify the versions of your dependencies.

ライブラリのバージョンはファイル名で簡単に分かるようになっていなければなりません。jarのバージョンは、たいていの場合マニフェストファイルに記述されていますが、それではプロジェクトを調査しているときに手軽に見ることができません。 もし、20個のjarファイルがズラッと並べられて、これを見てほしいと言われたら、どちらがいいと思いますか? つまり、commons-beanutils-1.3.jarのようなファイル群と、spring.jarのようなファイル群と、どちらの方がわかりやすいと思いますか? ファイル名にバージョン番号が付いていれば、プロジェクトが依存しているjarのバージョンを簡単に、迅速に特定できます。

If versions are unclear you can introduce subtle bugs which are very hard to find. For example there might be a project which uses Hibernate 2.5. Think about a developer who decides to install version 3.0.5 of Hibernate on her machine to fix a critical security bug but forgets to notify others in the team of this change. She may address the security bug successfully, but she also may have introduced subtle bugs into a codebase that was using a now-deprecated feature from Hibernate. Weeks later there is an exception on the integration machine which can't be reproduced on anyone's machine. Multiple developers then spend days on this issue only finally realising that the error would have easy to uncover if they knew that Hibernate had been upgraded from 2.5 to 3.0.5.

不明瞭なバージョンは、発見するのが非常に難しい、微妙なバグに繋がります。 例えば、Hibernate2.5を使っているプロジェクトがあるとしましょう。Hibernate3.0.5にアップグレードして、致命的なセキュリティのバグを修正したと想定してください。しかし、彼女はチームメンバーにそのことを知らせるのを忘れてしまいました。彼女はセキュリティのバグを上手く修正したかもしれませんが、同時にコードベースに小さなバグを混入させてしまったかもしれません。最新版のライブラリで非推奨となった機能を使っていた場合などです。 数週間後、インテグレーションサーバーで例外が発生します。しかし他のマシンでは再現しません。結果、Hibernateが2.5から3.0.2にアップグレードされていたというだけの問題に、多くの開発者が何日もかけることになるのです。

Versions in jar names increase the expressiveness of your project and make them easier to maintain. This practice also reduces the potential for error.

jarのファイル名にバージョン付けすることは、プロジェクトの表現性を高め、メンテナンスを簡単にします。また、潜在的なエラーを減らすことにも繋がるのです。

51.2.2. 推移的な依存関係の管理 Manage transitive dependencies

Transitive dependency management is a technique that enables your project to depend on libraries which, in turn, depend on other libraries. This recursive pattern of transitive dependencies results in a tree of dependencies including your project's first-level dependencies, second-level dependencies, and so on. If you don't model your dependencies as a hierarchical tree of first-level and second-level dependencies it is very easy to quickly lose control over an assembled mess of unstructured dependencies. Consider the Gradle project itself, while Gradle only has a few direct, first-level dependencies, when Gradle is compiled it needs more than one hundred dependencies on the classpath. On a far larger scale, Enterprise projects using Spring, Hibernate, and other libraries, alongside hundreds or thousands of internal projects, can result in very large dependency trees.

推移的な依存関係の管理とは、プロジェクトがあるライブラリに依存しているとき、その依存ライブラリがさらに別のライブラリに依存することを可能にする技術のことです。 このように推移的な依存関係が再帰的に発生すると、プロジェクトが直接依存する第一層の依存、それが依存する第二層の依存、といったふうに、依存関係のツリー構造が構築されることになります。 階層的にモデリングされていない依存関係は、構造化されないまま複雑にふくれあがり、簡単に制御を失ってしまうでしょう。 Gradle自身のことを考えてみても、Gradleプロジェクト自体は直接の、つまり第一層の依存関係はそう多くはありませんが、プロジェクトのコンパイル時には100以上の依存関係をクラスパスに含める必要があります。 さらに規模が大きくなれば、例えばSpring、Hibernate、その他のライブラリを使うエンタープライズプロジェクトともなれば、それに伴い数百、数千の依存プロジェクトが非常に大きな依存関係ツリーを構築することになります。

When these large dependency trees need to change, you'll often have to solve some dependency version conflicts. Say one open source library needs one version of a logging library and a another uses an alternative version. Gradle and other build tools all have the ability to resolve this dependency tree and resolve conflicts, but what differentiates Gradle is the control it gives you over transitive dependencies and conflict resolution.

このように依存関係ツリーが巨大になってくると、それを修正する際、バージョンの競合が発生しやすくなり、その解決に追われることが増えてきます。 例えば、あるバージョンのロギングライブラリを必要としているオープンソースライブラリがあるとしましょう。この場合、そのロギングライブラリの別のバージョンを要求するライブラリを使用すると、バージョンの競合が発生します。Gradleやその他のビルドツールは全て、このようなバージョン競合を解決する手段を備えています。Gradleでは、さらにその解決方法を細かく制御することもできます。

While you could try to manage this problem manually, you will quickly find that this approach doesn't scale. If you want to get rid of a first level dependency you really can't be sure which other jars you should remove. A dependency of a first level dependency might also be a first level dependency itself, or it might be a transitive dependency of yet another first level dependency. If you try to manage transitive dependencies yourself, the end of the story is that your build becomes brittle: no one dares to change your dependencies because the risk of breaking the build is too high. The project classpath becomes a complete mess, and, if a classpath problem arises, hell on earth invites you for a ride.

これらの問題を、手で何とかしようと頑張ることはできるかもしれませんが、すぐにそうした方法には拡張性がないことに気づくでしょう。 例えば、第一層、直接の依存関係を取り除きたいとなったとき、関連する他のjarも削除して良いものかどうか、分からなくなってしまいます。 削除しようとする依存関係の依存ライブラリだと思っていたjarが、それ自身第一層の依存関係に含まれているかもしれませんし、別の依存関係から参照されている可能性もあります。 自分で、手で推移的な依存関係を管理しようとすれば、その行き着く先は壊れやすく脆いビルドです。 思い切ってそのプロジェクトの依存関係を変更しようなどという人はどこにもいません。ビルドを壊してしまうリスクがあまりに高すぎるからです。 プロジェクトのクラスパスはいつか完全にめちゃくちゃになって、ひとたびそのクラスパスで問題が発生すれば地獄のような状況に陥ることでしょう。

NOTE:In one project, we found a mystery, LDAP related jar in the classpath. No code referenced this jar and there was no connection to the project. No one could figure out what the jar was for, until it was removed from the build and the application suffered massive performance problems whenever it attempted to authenticate to LDAP. This mystery jar was a necessary transitive, fourth-level dependency that was easy to miss because no one had bothered to use managed transitive dependencies.ノート:あるプロジェクトで、私たちはミステリーに遭遇しました。クラスパスにあるLDAP関連のjarなのですが、このjarを参照しているコードは何処にもなく、プロジェクトと結びつくようなものは何もありませんでした。jarがビルドから取り除かれ、そしてLDAP認証を試みる度に壮大なパフォーマンス問題に悩まされるようになるまで、誰もこのjarが何のためにあるのか分からなかったのです。 この謎のjarは、推移的な、第四層の依存関係に当たるものでした。推移的な依存関係を管理してやろうという人が誰もいなければ、このようなことは簡単に分からなくなってしまいます。

Gradle offers you different ways to express first-level and transitive dependencies. With Gradle you can mix and match approaches; for example, you could store your jars in an SCM without XML descriptor files and still use transitive dependency management.

Gradleは、直接の依存関係および推移的な依存関係を表現するための手段を複数用意しています。複数のアプローチを混ぜたり、組み合わせて使うことも可能です。例えば、jarを、XMLのディスクリプタなしでソースコード管理システムに直接格納することができますし、その場合でも推移的な依存関係はそのまま管理していくことができます。

51.2.3. バージョン競合の解決 Resolve version conflicts

Conflicting versions of the same jar should be detected and either resolved or cause an exception. If you don't use transitive dependency management, version conflicts are undetected and the often accidental order of the classpath will determine what version of a dependency will win. On a large project with many developers changing dependencies, successful builds will be few and far between as the order of dependencies may directly affect whether a build succeeds or fails (or whether a bug appears or disappears in production).

同じjar間でバージョンの競合が検出された場合、それを解決するか、エラーを発生させなければなりません。ここでもし推移的な依存関係を管理していなければ、バージョン競合は検出できず、クラスパス内で偶然そうなっただけのjarの順序がどのバージョンを優先するか決定することになります。 たくさんの開発者が依存関係を変更しているような巨大プロジェクトの場合、依存関係の順序がビルドの成否(またはプロダクション環境でバグが発生するかどうか)に直接影響するような状態では、上手くいくビルドはほとんどなくなってしまうでしょう。

If you haven't had to deal with the curse of conflicting versions of jars on a classpath, here is a small anecdote of the fun that awaits you. In a large project with 30 submodules, adding a dependency to a subproject changed the order of a classpath, swapping Spring 2.5 for an older 2.4 version. While the build continued to work, developers were starting to notice all sorts of surprising (and surprisingly awful) bugs in production. Worse yet, this unintentional downgrade of Spring introduced several security vulnerabilities into the system, which now required a full security audit throughout the organization.

もしクラスパスのバージョンが競合するという不幸に苦しんだことがないようでしたら、あなたを待ち受ける愉快な逸話を一つ紹介しましょう。 30のサブモジュールからなるある巨大なプロジェクトがありました。ここにあるサブモジュールに依存関係を追加したところ、クラスパスの順序が変わり、Spring2.5が古いバージョンの2.4に置き換わってしまったのです。 ビルドはまだ正常に動き続けているのに、開発者たちは無数の驚くような、というか驚くくらいひどいバグをプロダクション環境で見つけ始めます。 さらに悪いことに、この意図しないSpringのダウングレードはいくつかのセキュリティ的な脆弱性をシステムに招き、組織全体があらゆるセキュリティ監査を受けることになりました。

In short, version conflicts are bad, and you should manage your transitive dependencies to avoid them. You might also want to learn where conflicting versions are used and consolidate on a particular version of a dependency across your organization. With a good conflict reporting tool like Gradle, that information can be used to communicate with the entire organization and standardize on a single version. If you think version conflicts don't happen to you, think again. It is very common for different first-level dependencies to rely on a range of different overlapping versions for other dependencies, and the JVM doesn't yet offer an easy way to have different versions of the same jar in the classpath (see 「Javaにおける依存関係管理 Dependency management and Java).

要するに、バージョンの競合は悪いことなので、それを避けるために推移的な依存関係は管理しなければならないのです。 また、競合したバージョンが組織全体で何処で使われているのか調べ、一つのバージョンに統一したいという場合について考えると、Gradleのような競合に関する優秀なレポートを作成できるツールがあれば、組織全体でのコミュニケーション、および一つのバージョンへの標準化などに役立つはずです。 もしバージョン競合など自分には起こるわけがないと思っているようでしたら、どうかもう一度考え直してみてください。 第一層の依存関係が、更に別のライブラリに依存していて、それが他の依存関係とバージョンが競合しているというのは非常に良くあることです。 また、JVMには同じjarの違うバージョンをクラスパスで共存させられるような簡単な方法がありません(「Javaにおける依存関係管理 Dependency management and Java参照)。

Gradle offers the following conflict resolution strategies:

Gradleでは、バージョン競合を解決するための戦略として以下のものを用意しています。

  • Newest: The newest version of the dependency is used. This is Gradle's default strategy, and is often an appropriate choice as long as versions are backwards-compatible. もっとも新しいバージョンの依存関係を使用します。これはGradleのデフォルトの戦略で、バージョン間で上位互換性が保たれている限り、この戦略を選択するのが多くの場合適切です。
  • Fail: A version conflict results in a build failure. This strategy requires all version conflicts to be resolved explicitly in the build script. See ResolutionStrategy for details on how to explicitly choose a particular version. バージョンが競合した場合、ビルドを失敗させます。この戦略は、ビルドスクリプトで全てのバージョン競合をユーザーが明示的に解決することを強制します。 特定のバージョンを明示的に選択する方法についてはResolutionStrategyを参照してください。

While the strategies introduced above are usually enough to solve most conflicts, Gradle provides more fine-grained mechanisms to resolve version conflicts:

上記の戦略で大抵の場合はほとんどの競合を解決できますが、Gradleはさらに微調整を行うためのメカニズムを備えています。

  • Configuring a first level dependency as forced. This approach is useful if the dependency in conflict is already a first level dependency. See examples in DependencyHandler. プロジェクトが直接依存する第一層の依存関係をforcedとして強制できます。 これは、競合した依存関係が第一層の依存関係だったときに便利なアプローチです。 例についてはDependencyHandlerを参照してください。
  • Configuring any dependency (transitive or not) as forced. This approach is useful if the dependency in conflict is a transitive dependency. It also can be used to force versions of first level dependencies. See examples in ResolutionStrategy 依存関係は、第一層のものか推移的なものかにかかわらずとにかくforcedとして強制することもできます。 これは、推移的な依存関係で競合が発生してしまったときに便利なアプローチです。 また、第一層の依存関係も、前述の方法でなくこちらの方法で強制させることもできます。 例についてはResolutionStrategyを参照してください。
  • Dependency resolve rules are an incubating feature introduced in Gradle 1.4 which give you fine-grained control over the version selected for a particular dependency. 依存関係解決ルールというGradle1.4で導入された試験的な機能があり、特定の依存関係において選択されるバージョンを細かく調整することができます。

To deal with problems due to version conflicts, reports with dependency graphs are also very helpful. Such reports are another feature of dependency management.

バージョン競合により発生する様々な問題に対応するときには、依存関係グラフを表示するレポートも非常に有用です。依存関係管理の機能として、Gradleはそのようなレポート機能も備えています。

51.2.4. 動的バージョンと変更性モジュールを使う Use Dynamic Versions and Changing Modules

There are many situations when you want to use the latest version of a particular dependency, or the latest in a range of versions. This can be a requirement during development, or you may be developing a library that is designed to work with a range of dependency versions. You can easily depend on these constantly changing dependencies by using a dynamic version. A dynamic version can be either a version range (e.g. 2.+) or it can be a placeholder for the latest version available (e.g. latest.integration).

あるモジュールについて、常に最新版を使いたい、またはある範囲においての最新版を使いたいといった場面がよくあります。 例えば、開発作業中や、ある範囲のバージョンのライブラリと協調して動作するよう設計されたライブラリを開発しているときなどです。 この種の、絶えず変更されるような依存関係は、動的バージョンを使うと簡単に参照することができます。 動的バージョンは、バージョンの範囲で指定すること(2.+など)も、使用できる最新版を表すプレースホルダで指定すること(latest.integrationなど)もできます。

Alternatively, sometimes the module you request can change over time, even for the same version. An example of this type of changing module is a Maven SNAPSHOT module, which always points at the latest artifact published. In other words, a standard Maven snapshot is a module that never stands still so to speak, it is a “changing module”.

また、要求しているモジュールのバージョンそのものは変わらないのに、中身だけが変更されていく場合もあります。このような変更性モジュールの典型的な例は、MavenのSNAPSHOTモジュールです。このモジュールは、公開された最新のモジュールを常にポイントし続けます。 言い換えれば、標準的なMavenのスナップショットは静的な状態にとどまっているものではありません。それがつまり、「変更性モジュール」です。

The main difference between a dynamic version and a changing module is that when you resolve a dynamic version, you'll get the real, static version as the module name. When you resolve a changing module, the artifacts are named using the version you requested, but the underlying artifacts may change over time.

動的バージョン変更性モジュールの主な違いは、モジュール名に付加されるバージョンです。動的バージョンが静的な、実際のバージョンに変換されて付加されるのに対し、変更性モジュールは要求したバージョン名がそのまま付加されます。その上で、モジュールの中身が時間が経つにつれて変わっていくのです。

By default, Gradle caches dynamic versions and changing modules for 24 hours. You can override the default cache modes using command line options. You can change the cache expiry times in your build using the resolution strategy (see 「依存関係キャッシュ制御の微調整 Fine-tuned control over dependency caching).

デフォルトでは、Gradleは動的バージョンと変更性モジュールのキャッシュを24時間保持します。デフォルトに使用される値はコマンドラインオプションで変更できます。 また、ビルド時の実際のキャッシュの有効期限は解決戦略を使って設定できます(「依存関係キャッシュ制御の微調整 Fine-tuned control over dependency caching参照)。

51.3. 依存関係のコンフィギュレーション Dependency configurations

In Gradle dependencies are grouped into configurations. Configurations have a name, a number of other properties, and they can extend each other. Many Gradle plugins add pre-defined configurations to your project. The Java plugin, for example, adds some configurations to represent the various classpaths it needs. see 「依存関係の管理Dependency management for details. Of course you can add custom configurations on top of that. There are many use cases for custom configurations. This is very handy for example for adding dependencies not needed for building or testing your software (e.g. additional JDBC drivers to be shipped with your distribution).

Gradleでは、依存関係は「コンフィギュレーション」によりグループ化されます。コンフィギュレーションは名前(name)といくつかのプロパティを持っていて、それらを別のコンフィギュレーションから継承することもできます。 Gradleプラグインの多くが、独自のコンフィグレーションを事前に定義してプロジェクトに追加します。 たとえば、Javaプラグインは、いくつかのコンフィグレーションをプロジェクトに追加して、必要とされる様々なクラスパスを表現します。詳しくは「依存関係の管理Dependency managementをご参照ください。 もちろん、定義済みのものだけでなく、自分でコンフィギュレーションを定義して追加することも可能です。このような独自コンフィギュレーションには様々な使い道があります。身近な例として、ソフトウェアのビルドやテストには必要ない依存関係を追加する場合(配布物に同梱するオプションのJDBCドライバなど)が挙げられます。

A project's configurations are managed by a configurations object. The closure you pass to the configurations object is applied against its API. To learn more about this API have a look at ConfigurationContainer.

プロジェクトのコンフィギュレーションはconfigurationsオブジェクトで管理されています。このオブジェクトに渡したクロージャは、configurationsのAPIに対して適用されます。 APIの詳細についてはConfigurationContainerをご参照ください。

To define a configuration:

コンフィギュレーションを定義するには、

例51.1 コンフィギュレーションの定義

build.gradle

configurations {
    compile
}

To access a configuration:

コンフィギュレーションにアクセスするには、

例51.2 コンフィギュレーションへのアクセス

build.gradle

println configurations.compile.name
println configurations['compile'].name

To configure a configuration:

コンフィギュレーションの設定を変更するには、

例51.3 コンフィギュレーションの設定変更

build.gradle

configurations {
    compile {
        description = 'compile classpath'
        transitive = true
    }
    runtime {
        extendsFrom compile
    }
}
configurations.compile {
    description = 'compile classpath'
}

51.4. 依存関係の定義方法 How to declare your dependencies

There are several different types of dependencies that you can declare:

定義できる依存関係にはいくつかの種類があります。

表51.1 依存関係の種類 Dependency types

Type 種類 Description 説明
External module dependency 外部モジュール依存関係 A dependency on an external module in some repository. どこかのリポジトリにある外部モジュールへの依存関係
Project dependency プロジェクト依存関係 A dependency on another project in the same build. 同じビルドに含まれる別プロジェクトへの依存関係
File dependency ファイル依存関係 A dependency on a set of files on the local filesystem. ローカルファイルシステム上のファイル群への依存関係
Client module dependency クライアントモジュール依存関係 A dependency on an external module, where the artifacts are located in some repository but the module meta-data is specified by the local build. You use this kind of dependency when you want to override the meta-data for the module. どこかのリポジトリにあるアーティファクトへ依存しているが、そのモジュールのメタデータは手元のビルドで定義する際に使用する。この依存関係を使うと、モジュールのもともとのメタデータを上書きすることができる。
Gradle API dependency Gradle APIへの依存関係 A dependency on the API of the current Gradle version. You use this kind of dependency when you are developing custom Gradle plugins and task types. 現在使用しているバージョンのGradleが持つAPIへの依存関係。Gradleのカスタムプラグインやカスタムタスクを開発するときにこの種類の依存関係を使用します。
Local Groovy dependency ローカルGroovy依存関係 A dependency on the Groovy version used by the current Gradle version. You use this kind of dependency when you are developing custom Gradle plugins and task types. 現在使用中のGradleで使われているGroovyへの依存関係。これもGradleのカスタムプラグインやカスタムタスクを作る際に使用します。

51.4.1. 外部モジュール依存関係 External module dependencies

External module dependencies are the most common dependencies. They refer to a module in an external repository.

外部モジュール依存関係は、もっともポピュラーな種類の依存関係です。このタイプの依存関係は、外部リポジトリにあるモジュールを参照します。

例51.4 モジュール依存関係

build.gradle

dependencies {
    runtime group: 'org.springframework', name: 'spring-core', version: '2.5'
    runtime 'org.springframework:spring-core:2.5',
            'org.springframework:spring-aop:2.5'
    runtime(
        [group: 'org.springframework', name: 'spring-core', version: '2.5'],
        [group: 'org.springframework', name: 'spring-aop', version: '2.5']
    )
    runtime('org.hibernate:hibernate:3.0.5') {
        transitive = true
    }
    runtime group: 'org.hibernate', name: 'hibernate', version: '3.0.5', transitive: true
    runtime(group: 'org.hibernate', name: 'hibernate', version: '3.0.5') {
        transitive = true
    }
}

See the DependencyHandler class in the API documentation for more examples and a complete reference.

より多くの例と完全なリファレンスはDependencyHandlerを参照してください。

Gradle provides different notations for module dependencies. There is a string notation and a map notation. A module dependency has an API which allows for further configuration. Have a look at ExternalModuleDependency to learn all about the API. This API provides properties and configuration methods. Via the string notation you can define a subset of the properties. With the map notation you can define all properties. To have access to the complete API, either with the map or with the string notation, you can assign a single dependency to a configuration together with a closure.

Gradleはモジュール依存関係を定義するために二つの記法を用意しています。文字列記法とマップ記法です。モジュール依存関係は、実際には非常に多くの設定を可能にするAPIを持っています。ExternalModuleDependencyも併せてご覧ください。 このAPIはプロパティとメソッドを公開しており、文字列記法ではプロパティのうち一部を指定することができます。 マップ記法を使うと全てのプロパティにアクセスできます。全てのAPIにアクセスするには、文字列記法、マップ記法どちらでも構いませんが、依存するモジュールを一つだけ指定して、そこに一緒にクロージャを渡します。

If you declare a module dependency, Gradle looks for a module descriptor file (pom.xml or ivy.xml) in the repositories. If such a module descriptor file exists, it is parsed and the artifacts of this module (e.g. hibernate-3.0.5.jar) as well as its dependencies (e.g. cglib) are downloaded. If no such module descriptor file exists, Gradle looks for a file called hibernate-3.0.5.jar to retrieve. In Maven, a module can have one and only one artifact. In Gradle and Ivy, a module can have multiple artifacts. Each artifact can have a different set of dependencies.

モジュール依存関係が宣言されていると、Gradleは対応するモジュールディスクリプタファイル(pom.xmlまたはivy.xml)をリポジトリに探しに行きます。結果、ディスクリプタファイルが見つかった場合は、それをパースし、指定されているアーティファクト(hibernate-3.0.5.jarなど)および推移的依存関係(cglibなど)をダウンロードします。 ディスクリプタファイルが見つからなければ、Gradleは今度はhibernate-3.0.5.jarという名前のファイルを探して取得しようとします。 Mavenのモジュールは、アーティファクトを一つしか持つことができません。GradleとIvyは一つのモジュールが複数のアーティファクトを持つことができます。それらのアーティファクトは、それぞれ別の依存関係を持っています。

51.4.1.1. 複数のアーティファクトを持つモジュールへの依存関係 Depending on modules with multiple artifacts

As mentioned earlier, a Maven module has only one artifact. Hence, when your project depends on a Maven module, it's obvious what its artifact is. With Gradle or Ivy, the case is different. Ivy's dependency descriptor (ivy.xml) can declare multiple artifacts. For more information, see the Ivy reference for ivy.xml. In Gradle, when you declare a dependency on an Ivy module, you actually declare a dependency on the default configuration of that module. So the actual set of artifacts (typically jars) you depend on is the set of artifacts that are associated with the default configuration of that module. Here are some situations where this matters:

前述のように、Mavenのモジュールはアーティファクトを一つしか持てません。そのため、プロジェクトが依存しているモジュールがMavenのモジュールだった場合、そのアーティファクトは明らかです。 しかし、GradleやIvyの場合は違います。Ivyの依存関係モデル(ivy.xml)では、一つのモジュールに複数のアーティファクトを宣言できるからです。 詳細についてはivy.xmlのリファレンスを参照してください。 Gradleでivyモジュールへ依存していることを宣言したとき、実際にはそのモジュールのdefaultコンフィギュレーションへの依存関係を宣言しています。 つまり、プロジェクトが実際に依存しているアーティファクト(典型的にはjar)は、モジュールのdefaultコンフィギュレーションに格納された全アーティファクトです。 このことが重要になるのは、以下のような場合です。

  • The default configuration of a module contains undesired artifacts. Rather than depending on the whole configuration, a dependency on just the desired artifacts is declared.defaultコンフィグレーションに、不必要なアーティファクトが含まれている場合。この場合、defaultコンフィグレーション全てに依存するのではなく、必要なアーティファクトへの依存関係のみを宣言します。
  • The desired artifact belongs to a configuration other than default. That configuration is explicitly named as part of the dependency declaration. 必要なアーティファクトがdefaultコンフィグレーション以外のコンフィグレーションに含まれている場合。この場合、そのコンフィグレーションを依存関係の宣言で明示的に指定します。

There are other situations where it is necessary to fine-tune dependency declarations. Please see the DependencyHandler class in the API documentation for examples and a complete reference for declaring dependencies.

依存関係の宣言を微調整しなければならないようなシチュエーションはまだまだあります。 その他の例や依存関係宣言の完全なリファレンスについてはDependencyHandlerをご覧ください。

51.4.1.2. アーティファクトオンリー記法 Artifact only notation

As said above, if no module descriptor file can be found, Gradle by default downloads a jar with the name of the module. But sometimes, even if the repository contains module descriptors, you want to download only the artifact jar, without the dependencies. 上記のように、モジュールのディスクリプタファイルが見つからなかった場合、Gradleはデフォルトでモジュールの名前を基にjarファイルをダウンロードします。 しかし、リポジトリにディスクリプタファイルがあるアーティファクトでも、場合によってはjarのみをダウンロードしたいというケースもあります。 [22] And sometimes you want to download a zip from a repository, that does not have module descriptors. Gradle provides an artifact only notation for those use cases - simply prefix the extension that you want to be downloaded with '@' sign: その他にも、ディスクリプタファイルを持たないリポジトリからzipファイルをダウンロードしたいという場合などもあり、Gradleはそのようなケースのためにアーティファクトオンリー記法というものをサポートしています。書き方は簡単で、ダウンロードしたいものの拡張子を「@」で指定するだけです。

例51.5 アーティファクトオンリー記法

build.gradle

dependencies {
    runtime "org.groovy:groovy:2.2.0@jar"
    runtime group: 'org.groovy', name: 'groovy', version: '2.2.0', ext: 'jar'
}


An artifact only notation creates a module dependency which downloads only the artifact file with the specified extension. Existing module descriptors are ignored. アーティファクトオンリー記法は、指定した拡張子のファイルのみをダウンロードする、というモジュール依存関係を作成します。ディスクリプタがあっても無視されます。

51.4.1.3. 分類子(Classifiers) Classifiers

The Maven dependency management has the notion of classifiers. Mavenには分類子(classifiers)という記法があります。 [23] Gradle supports this. To retrieve classified dependencies from a Maven repository you can write: Gradleでもこの記法をサポートしています。Mavenリポジトリから分類子つきの依存関係を取得するには、次のように記述します。

例51.6 分類子付きの依存関係

build.gradle

compile "org.gradle.test.classifiers:service:1.0:jdk15@jar"
    otherConf group: 'org.gradle.test.classifiers', name: 'service', version: '1.0', classifier: 'jdk14'

As can be seen in the first line above, classifiers can be used together with the artifact only notation.

上記の一行目にあるように、分類子は明示的に拡張子を指定して(アーティファクトオンリー記法で)使うこともできます。

It is easy to iterate over the dependency artifacts of a configuration:

コンフィグレーションに含まれる依存アーティファクトの一覧は簡単に列挙できます。

例51.7 あるコンフィグレーションの内部を列挙する

build.gradle

task listJars << {
    configurations.compile.each { File file -> println file.name }
}

gradle -q listJars の出力

> gradle -q listJars
hibernate-core-3.6.7.Final.jar
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate-commons-annotations-3.2.0.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
jta-1.1.jar
slf4j-api-1.6.1.jar

51.4.2. クライアントモジュール依存関係 Client module dependencies

Client module dependencies allow you to declare transitive dependencies directly in the build script. They are a replacement for a module descriptor in an external repository.

クライアントモジュール依存関係を使うと、モジュールの推移的な依存関係をビルドスクリプトの中で直接定義できます。これは外部リポジトリにある実際のモジュールディスクリプタの代わりに使用されます。

例51.8 クライアントモジュール依存関係 - 推移的な依存関係

build.gradle

dependencies {
    runtime module("org.codehaus.groovy:groovy:2.3.6") {
        dependency("commons-cli:commons-cli:1.0") {
            transitive = false
        }
        module(group: 'org.apache.ant', name: 'ant', version: '1.9.3') {
            dependencies "org.apache.ant:ant-launcher:1.9.3@jar",
                         "org.apache.ant:ant-junit:1.9.3"
        }
    }
}

This declares a dependency on Groovy. Groovy itself has dependencies. But Gradle does not look for an XML descriptor to figure them out but gets the information from the build file. The dependencies of a client module can be normal module dependencies or artifact dependencies or another client module. Also look at the API documentation for the ClientModule class.

この例では、Groovyに依存していることが宣言されています。Groovyは、それ自身別の依存関係を持っているのですが、ここではGradleはXMLディスクリプタではなく、ビルドスクリプト内の定義を見てGroovyの推移的な依存関係を決定します。 クライアントモジュールの依存関係としては、普通のモジュール依存関係の他、アーティファクトオンリー記法、また別のクライアントモジュール依存関係も使うことができます。APIドキュメントClientModuleも参考にしてください。

In the current release client modules have one limitation. Let's say your project is a library and you want this library to be uploaded to your company's Maven or Ivy repository. Gradle uploads the jars of your project to the company repository together with the XML descriptor file of the dependencies. If you use client modules the dependency declaration in the XML descriptor file is not correct. We will improve this in a future release of Gradle.

現在、クライアントモジュールには一つの制限があります。プロジェクトがライブラリをビルドするもので、そのライブラリを社内のMavenやIvyリポジトリにアップロードしたいとします。GradleはプロジェクトのjarをXMLディスクリプタファイルと一緒に社内リポジトリにアップロードするわけですが、クライアントモジュールを使っているとそのディスクリプタの依存関係宣言が正しいものにならないのです。将来のバージョンで修正される予定です。

51.4.3. プロジェクト依存関係 Project dependencies

Gradle distinguishes between external dependencies and dependencies on projects which are part of the same multi-project build. For the latter you can declare Project Dependencies.

Gradleでは、外部モジュール依存関係と、マルチプロジェクト内で別のプロジェクトを参照する依存関係は明確に区別されます。 後者はプロジェクト依存関係として宣言します。

例51.9 プロジェクト依存関係

build.gradle

dependencies {
    compile project(':shared')
}

For more information see the API documentation for ProjectDependency.

APIドキュメントProjectDependencyに詳しい情報が記載されています。

Multi-project builds are discussed in 57章マルチプロジェクトのビルド.

また、マルチプロジェクトについては、57章マルチプロジェクトのビルドで詳述されています。

51.4.4. ファイル依存関係 File dependencies

File dependencies allow you to directly add a set of files to a configuration, without first adding them to a repository. This can be useful if you cannot, or do not want to, place certain files in a repository. Or if you do not want to use any repositories at all for storing your dependencies.

ファイル依存関係は、前もってファイルをリポジトリに格納することなく、直接コンフィギュレーションに追加することを可能にします。これは、何らかの理由であるファイルをリポジトリに置けない、または置きたくない場合に有用です。また、依存関係の保存先としてリポジトリを一切使いたくないという場合もこの依存関係が便利です。

To add some files as a dependency for a configuration, you simply pass a file collection as a dependency:

方法も簡単で、単にファイルコレクションを依存関係としてコンフィギュレーションに渡すだけです。

例51.10 ファイル依存関係

build.gradle

dependencies {
    runtime files('libs/a.jar', 'libs/b.jar')
    runtime fileTree(dir: 'libs', include: '*.jar')
}

File dependencies are not included in the published dependency descriptor for your project. However, file dependencies are included in transitive project dependencies within the same build. This means they cannot be used outside the current build, but they can be used with the same build.

ファイル依存関係は、公開されるディスクリプタファイルには含まれません。しかし、同じビルド内から参照された場合、その推移的な依存関係としては使用されます。 つまり、ファイル依存関係は、そのビルドの外部からは使用されませんが、同じビルド内のプロジェクトからは使用される、ということです。

You can declare which tasks produce the files for a file dependency. You might do this when, for example, the files are generated by the build.

ファイル依存関係では、どのタスクがファイルを生成するのか宣言することができます。依存ファイルがビルドで作成される場合などで使用されることがあります。

例51.11 生成されるファイルへの依存関係

build.gradle

dependencies {
    compile files("$buildDir/classes") {
        builtBy 'compile'
    }
}

task compile << {
    println 'compiling classes'
}

task list(dependsOn: configurations.compile) << {
    println "classpath = ${configurations.compile.collect {File file -> file.name}}"
}

gradle -q list の出力

> gradle -q list
compiling classes
classpath = [classes]

51.4.5. Gradle API依存関係 Gradle API Dependency

You can declare a dependency on the API of the current version of Gradle by using the DependencyHandler.gradleApi() method. This is useful when you are developing custom Gradle tasks or plugins.

DependencyHandler.gradleApi()メソッドを使うと、そのビルドで使用しているGradleのAPIへ依存していることを宣言できます。 Gradleのカスタムタスクやプラグインを開発しているときによく使われます。

例51.12 Gradle API依存関係

build.gradle

dependencies {
    compile gradleApi()
}

51.4.6. ローカルGroovy依存関係 Local Groovy Dependency

You can declare a dependency on the Groovy that is distributed with Gradle by using the DependencyHandler.localGroovy() method. This is useful when you are developing custom Gradle tasks or plugins in Groovy.

DependencyHandler.localGroovy()を使うと、Gradleに同梱されているGroovyへの依存関係を宣言できます。 これもGradleのカスタムタスクやプラグインを開発しているときによく使われます。

例51.13 Gradleに同梱されているGroovyへの依存関係

build.gradle

dependencies {
    compile localGroovy()
}

51.4.7. 推移的な依存関係の除外 Excluding transitive dependencies

You can exclude a transitive dependency either by configuration or by dependency:

コンフィギュレーション単位、または依存関係単位で、特定の推移的な依存関係を除外することができます。

例51.14 推移的な依存関係の除外

build.gradle

configurations {
    compile.exclude module: 'commons'
    all*.exclude group: 'org.gradle.test.excludes', module: 'reports'
}

dependencies {
    compile("org.gradle.test.excludes:api:1.0") {
        exclude module: 'shared'
    }
}

If you define an exclude for a particular configuration, the excluded transitive dependency will be filtered for all dependencies when resolving this configuration or any inheriting configuration. If you want to exclude a transitive dependency from all your configurations you can use the Groovy spread-dot operator to express this in a concise way, as shown in the example. When defining an exclude, you can specify either only the organization or only the module name or both. Also look at the API documentation of the Dependency and Configuration classes.

コンフィギュレーションに対してある依存関係を除外すると、そのコンフィギュレーション、および全ての継承コンフィギュレーションに含まれる全依存関係に対して推移的依存関係がフィルターされます。 また、全てのコンフィギュレーションにまとめて除外設定を適用したい場合は、例にあるようにGroovyの展開ドット演算子を使うと簡潔に記述できます。 除外設定は、organizationのみを指定することもできますし、モジュール名やその両方で指定しても構いません。 APIドキュメントのDependencyConfigurationを参照してみてください。

Not every transitive dependency can be excluded - some transitive dependencies might be essential for correct runtime behavior of the application. Generally, one can exclude transitive dependencies that are either not required by runtime or that are guaranteed to be available on the target environment/platform.

全ての推移的な依存関係が除外できるとは限りません。アプリケーションの動作に必須な依存関係もあります。 一般的には、実行時に使われることがないものや、対象環境やプラットフォームでそれが使えると保証できているような場合には、その依存関係を除外することができます。

Should you exclude per-dependency or per-configuration? It turns out that in the majority of cases you want to use the per-configuration exclusion. Here are some typical reasons why one might want to exclude a transitive dependency. Bear in mind that for some of these use cases there are better solutions than exclusions! 除外設定は、依存関係単位かコンフィギュレーション単位、どちらで設定するべきでしょうか? ほとんどの場合は、コンフィギュレーション単位で設定することになるでしょう。 推移的な依存関係を除外したいと考える、代表的な理由を挙げてみます。 なお、これらの中には、依存関係を除外してしまうよりも優れた解決手段があるものもあります。頭に留めておいてください!

  • The dependency is undesired due to licensing reasons. ライセンス上の理由により、その依存関係を除外したい
  • The dependency is not available in any of remote repositories. いずれかのリモートリポジトリで、その依存関係が使用できない
  • The dependency is not needed for runtime. 実行時にその依存関係が不要
  • The dependency has a version that conflicts with a desired version. For that use case please refer to 「バージョン競合の解決 Resolve version conflicts and the documentation on ResolutionStrategy for a potentially better solution to the problem. その依存関係のバージョンが競合していて欲しいバージョンの依存関係が取得できない。この場合、除外設定よりも優れた方法があるかもしれません。「バージョン競合の解決 Resolve version conflictsResolutionStrategyを参照してみてください。

Basically, in most of the cases excluding the transitive dependency should be done per configuration. This way the dependency declaration is more explicit. It is also more accurate because a per-dependency exclude rule does not guarantee the given transitive dependency does not show up in the configuration. For example, some other dependency, which does not have any exclude rules, might pull in that unwanted transitive dependency. 基本的には、ほとんどのケースでコンフィギュレーション単位の除外設定を使うべきです。これにより、依存関係の宣言がより明示的で正確なものになります。依存関係単位で除外ルールを設定しても、その依存関係が必ずしもコンフィギュレーションから取り除かれるとは限らないからです。 例えば、除外ルールを適用していない別の依存関係が、除外したはずの依存関係を引っ張ってきてしまうかもしれません。

Other examples of dependency exclusions can be found in the reference for the ModuleDependency or DependencyHandler classes.

リファレンスには、除外設定の他の例も記載されています。ModuleDependencyDependencyHandlerを見てみてください。

51.4.8. オプション属性 Optional attributes

All attributes for a dependency are optional, except the name. Which attributes are required for actually finding dependencies in the repository will depend on the repository type. See 「リポジトリ Repositories. For example, if you work with Maven repositories, you need to define the group, name and version. If you work with filesystem repositories you might only need the name or the name and the version.

依存関係宣言の属性は、nameを除いて全てオプションです。ただ、実際にリポジトリから依存関係を見つけてくる際にどんな情報が必要になるのかは、リポジトリの種類により異なります。「リポジトリ Repositoriesを参照してください。 例えば、Mavenリポジトリを使うときは、組織名、モジュール名、およびバージョンを指定する必要があります。一方、ただのファイルシステムをリポジトリにしている場合は、必要なのはモジュール名だけかもしれません。

例51.15 依存関係のオプション属性

build.gradle

dependencies {
    runtime ":junit:4.10", ":testng"
    runtime name: 'testng' 
}

You can also assign collections or arrays of dependency notations to a configuration:

また、依存関係定義のコレクションや属性をコンフィギュレーションに割り当てることもできます。

例51.16 依存関係定義のコレクション、配列

build.gradle

List groovy = ["org.codehaus.groovy:groovy-all:2.3.6@jar",
               "commons-cli:commons-cli:1.0@jar",
               "org.apache.ant:ant:1.9.3@jar"]
List hibernate = ['org.hibernate:hibernate:3.0.5@jar',
                  'somegroup:someorg:1.0@jar']
dependencies {
    runtime groovy, hibernate
}

51.4.9. 依存するコンフィギュレーションの指定 Dependency configurations

In Gradle a dependency can have different configurations (as your project can have different configurations). If you don't specify anything explicitly, Gradle uses the default configuration of the dependency. For dependencies from a Maven repository, the default configuration is the only possibility anyway. If you work with Ivy repositories and want to declare a non-default configuration for your dependency you have to use the map notation and declare:

Gradleでは、依存先のモジュールが複数のコンフィギュレーションを公開していることがあります(自分のプロジェクトでも様々なコンフィギュレーションを定義できたことを思い出してください)。 特に明示しないかぎり、Gradleはその依存関係のdefaultコンフィギュレーションを使用します。 Mavenリポジトリではdefaultコンフィギュレーションが使用できる唯一のコンフィギュレーションなのでいいのですが、Ivyリポジトリを使う場合、default以外のコンフィギュレーションを参照するときはマップ記法で次のように指定しなければなりません。

例51.17 依存するコンフィギュレーションの指定

build.gradle

dependencies {
    runtime group: 'org.somegroup', name: 'somedependency', version: '1.0', configuration: 'someConfiguration'
}

To do the same for project dependencies you need to declare:

プロジェクト依存関係で同じことをするには、次のように定義する必要があります。

例51.18 依存するプロジェクトのコンフィギュレーション

build.gradle

dependencies {
    compile project(path: ':api', configuration: 'spi')
}

51.4.10. 依存関係のレポート Dependency reports

You can generate dependency reports from the command line (see 「プロジェクトの依存関係一覧Listing project dependencies). With the help of the Project report plugin (see 41章プロジェクトレポートプラグイン) such a report can be created by your build.

Gradleには、依存関係に関するレポートを生成できるコマンドが用意されています(「プロジェクトの依存関係一覧Listing project dependencies参照)。 また、プロジェクトレポートプラグイン(41章プロジェクトレポートプラグイン)を使えば、ビルドのタスクでそのレポートを作成することもできます。

Since Gradle 1.2 there is also a new programmatic API to access the resolved dependency information. The dependency reports (see the previous paragraph) are using this API under the covers. The API lets you walk the resolved dependency graph and provides information about the dependencies. In future releases the API will grow to provide more information about the resolution result. For more information about the API please refer to the Javadocs on ResolvableDependencies.getResolutionResult(). Potential usages of the ResolutionResult API: Gradle1.2からは、解決した依存関係に関する情報に、プログラム的にアクセスできるAPIもあります。 先ほど述べた依存関係のレポートを作成するときも、水面下でこのAPIが使用されています。 このAPIを使えば、解決した依存関係グラフを走査したり、情報を取得したりすることが可能です。 また、近くこのAPIを更に拡張し、解決結果についてもっと情報を取得できるようにする予定です。 APIについての詳細はJavadoc(ResolvableDependencies.getResolutionResult())を参照してください。 API(ResolutionResult)の使い道として考えられるのは、

  • Creation of advanced dependency reports tailored to your use case. 自分のユースケースに適した、もっと踏み込んだレポートを作成するため
  • Enabling the build logic to make decisions based on the content of the dependency graph. 依存関係グラフの中身に応じて処理を切り替えるようなビルドロジックを実装するため

51.5. 依存関係を使った作業 Working with dependencies

For the examples below we have the following dependencies setup:

例えば、次のような依存関係をセットアップしたとします。

例51.19 Configuration.copy

build.gradle

configurations {
    sealife
    alllife
}

dependencies {
    sealife "sea.mammals:orca:1.0", "sea.fish:shark:1.0", "sea.fish:tuna:1.0"
    alllife configurations.sealife
    alllife "air.birds:albatross:1.0"
}

The dependencies have the following transitive dependencies:

このセットアップにおける推移的な依存関係は、以下の通りです。

shark-1.0 -> seal-2.0, tuna-1.0

orca-1.0 -> seal-1.0

tuna-1.0 -> herring-1.0

You can use the configuration to access the declared dependencies or a subset of those:

このコンフィギュレーションを使って、宣言された依存関係やその一部にアクセスできます。

例51.20 宣言した依存関係にアクセスする

build.gradle

task dependencies << {
    configurations.alllife.dependencies.each { dep -> println dep.name }
    println()
    configurations.alllife.allDependencies.each { dep -> println dep.name }
    println()
    configurations.alllife.allDependencies.findAll { dep -> dep.name != 'orca' }
        .each { dep -> println dep.name }
}

gradle -q dependencies の出力

> gradle -q dependencies
albatross

albatross
orca
shark
tuna

albatross
shark
tuna

The dependencies task returns only the dependencies belonging explicitly to the configuration. The allDependencies task includes the dependencies from extended configurations.

dependenciesはコンフィギュレーションに明示的に属しているもののみを返します。allDependenciesは継承したコンフィギュレーションに含まれるものも返します。

To get the library files of the configuration dependencies you can do:

コンフィギュレーションの依存関係として設定されているライブラリファイルを取得するには、次のようにします。

例51.21 Configuration.files

build.gradle

task allFiles << {
    configurations.sealife.files.each { file ->
        println file.name
    }
}

gradle -q allFiles の出力

> gradle -q allFiles
orca-1.0.jar
shark-1.0.jar
tuna-1.0.jar
herring-1.0.jar
seal-2.0.jar

Sometimes you want the library files of a subset of the configuration dependencies (e.g. of a single dependency).

コンフィギュレーションに属する依存関係のうち、一部の依存関係のみ、例えば一つの依存関係のみライブラリファイルを取得したいときもあります。

例51.22 フィルター付きConfiguration.files

build.gradle

task files << {
    configurations.sealife.files { dep -> dep.name == 'orca' }.each { file ->
        println file.name
    }
}

gradle -q files の出力

> gradle -q files
orca-1.0.jar
seal-2.0.jar

The Configuration.files method always retrieves all artifacts of the whole configuration. It then filters the retrieved files by specified dependencies. As you can see in the example, transitive dependencies are included.

Configuration.filesメソッドは、常にそのコンフィギュレーション全体から全てのアーティファクトを返すので、ここでは依存関係を指定してフィルターしました。例にあるように、推移的な依存関係も対象に含まれます。

You can also copy a configuration. You can optionally specify that only a subset of dependencies from the original configuration should be copied. The copying methods come in two flavors. The copy method copies only the dependencies belonging explicitly to the configuration. The copyRecursive method copies all the dependencies, including the dependencies from extended configurations.

コンフィギュレーションはコピーすることもできます。さらに、元のコンフィギュレーションから一部の依存関係のみコピーすることもできます。 コピー用のメソッドは二つ用意されており、copyメソッドは明示的にコンフィギュレーションに属している依存関係のみコピーします。もう一つのcopyRecursiveメソッドは継承元のコンフィギュレーションに含まれる依存関係もすべてコピーします。

例51.23 Configuration.copy

build.gradle

task copy << {
    configurations.alllife.copyRecursive { dep -> dep.name != 'orca' }
        .allDependencies.each { dep -> println dep.name }
    println()
    configurations.alllife.copy().allDependencies
        .each { dep -> println dep.name }
}

gradle -q copy の出力

> gradle -q copy
albatross
shark
tuna

albatross

It is important to note that the returned files of the copied configuration are often but not always the same than the returned files of the dependency subset of the original configuration. In case of version conflicts between dependencies of the subset and dependencies not belonging to the subset the resolve result might be different.

注意するべきなのは、コピーされたコンフィギュレーションから返される依存関係が、常にオリジナルのコンフィギュレーションのサブセットになるとは限らないという点です。 「コピーされたサブセット」と、「コピーされなかった残りのサブセット」の間でバージョンの競合がある場合、依存関係の解決結果が異なることがあります。

例51.24 Configuration.copy vs. Configuration.files

build.gradle

task copyVsFiles << {
    configurations.sealife.copyRecursive { dep -> dep.name == 'orca' }
        .each { file -> println file.name }
    println()
    configurations.sealife.files { dep -> dep.name == 'orca' }
        .each { file -> println file.name }
}

gradle -q copyVsFiles の出力

> gradle -q copyVsFiles
orca-1.0.jar
seal-1.0.jar

orca-1.0.jar
seal-2.0.jar

In the example above, orca has a dependency on seal-1.0 whereas shark has a dependency onseal-2.0. The original configuration has therefore a version conflict which is resolved to the newer seal-2.0 version. The files method therefore returns seal-2.0 as a transitive dependency oforca. The copied configuration only has orca as a dependency and therefore there is no version conflict and seal-1.0 is returned as a transitive dependency.

上の例では、orcaseal-1.0に依存しており、sharkseal-2.0に依存しています。なので、オリジナルのコンフィギュレーションではバージョンの競合が発生しているわけです。 そのため、この依存関係はより新しいバージョンであるseal-2.0に解決され、推移的な依存関係としてseal-2.0が表示されています。 一方、コピー先のコンフィギュレーションにはorcaしか含まれていません。そのためバージョンの競合は発生しておらず、推移的な依存関係としてseal-1.0が表示されているのです。

Once a configuration is resolved it is immutable. Changing its state or the state of one of its dependencies will cause an exception. You can always copy a resolved configuration. The copied configuration is in the unresolved state and can be freshly resolved.

一度解決されたコンフィギュレーションは不変(immutable)です。 その状態を変更したり、コンフィギュレーション内の依存関係の状態を変更したりすると例外が発生します。一方でコンフィギュレーションのコピーはいつでも可能です。コピーされたコンフィギュレーションは未解決状態であり、解決処理を新規に行うことができます。

To learn more about the API of the configuration class see the API documentation: Configuration.

ConfigurationクラスのAPIをさらに詳しく知りたいときは、APIドキュメント(Configuration)をご参照ください。

51.6. リポジトリ Repositories

Gradle repository management, based on Apache Ivy, gives you a lot of freedom regarding repository layout and retrieval policies. Additionally Gradle provides various convenience method to add pre-configured repositories.

Gradleのリポジトリ管理機能は、Apache Ivyをベースにしたもので、リポジトリのレイアウトや参照方法を自在に定義できます。さらに、Gradleにはあらかじめ様々なリポジトリが定義されており、それらを簡単にプロジェクトに設定することができます。

You may configure any number of repositories, each of which is treated independently by Gradle. If Gradle finds a module descriptor in a particular repository, it will attempt to download all of the artifacts for that module from the same repository. Although module meta-data and module artifacts must be located in the same repository, it is possible to compose a single repository of multiple URLs, giving multiple locations to search for meta-data files and jar files.

リポジトリはいくつでも定義できますが、Gradleからはそれぞれが独立して取り扱われます。 あるリポジトリでモジュールのディスクリプタが見つかれば、Gradleはそのモジュールのアーティファクトを全て同じリポジトリからダウンロードしようとします。 つまり、モジュールのメタデータと全てのアーティファクトは同じリポジトリになければなりません。しかし、一つのリポジトリを複数のURLから構成し、メタデータとjarファイルを様々な場所から探してこれるようにすることは可能です。

There are several different types of repositories you can declare:

宣言できるリポジトリには、以下のものがあります。

表51.2 リポジトリの種類 Repository types

Type 種類 Description 説明
Maven central repository Mavenセントラルリポジトリ A pre-configured repository that looks for dependencies in Maven Central. Mavenセントラルにある依存関係を探すための定義済みリポジトリ
Maven JCenter repository Maven JCenterリポジトリ A pre-configured repository that looks for dependencies in Bintray's JCenter. BintrayのJCenterにある依存関係を探すための定義済みリポジトリ
Maven local repository Mavenローカルリポジトリ A pre-configured repository that looks for dependencies in the local Maven repository. Mavenのローカルリポジトリにある依存関係を探すための定義済みリポジトリ
Maven repository Mavenリポジトリ A Maven repository. Can be located on the local filesystem or at some remote location. Mavenリポジトリ。ローカルファイルシステムまたはリモートに配置できる。
Ivy repository Ivyリポジトリ An Ivy repository. Can be located on the local filesystem or at some remote location. Ivyリポジトリ。ローカルファイルシステムまたはリモートに配置できる。
Flat directory repository フラットディレクトリリポジトリ A simple repository on the local filesystem. Does not support any meta-data formats. ローカルファイルシステム上のシンプルなリポジトリ。メタデータは一切サポートされない。

51.6.1. Supported repository transport protocols

Maven and Ivy repositories support the use of various transport protocols. At the moment the following protocols are supported:

表51.3 Repository transport protocols

Type Authentication schemes
file none
http username/password
https username/password
sftp username/password

To define a repository use the repositories configuration block. Within the repositories closure, a Maven repository is declared with maven. An Ivy repository is declared with ivy. The transport protocol is part of the URL definition for a repository. The following build script demonstrates how to create a HTTP-based Maven and Ivy repository:

例51.25 Declaring a Maven and Ivy repository

build.gradle

repositories {
    maven {
        url "http://repo.mycompany.com/maven2"
    }

    ivy {
        url "http://repo.mycompany.com/repo"
    }
}

If authentication is required for a repository, the relevant credentials can be provided. The following example shows how to provide username/password-based authentication for SFTP repositories:

例51.26 Providing credentials to a Maven and Ivy repository

build.gradle

repositories {
    maven {
        url "sftp://repo.mycompany.com:22/maven2"
        credentials {
            username 'user'
            password 'password'
        }
    }

    ivy {
        url "sftp://repo.mycompany.com:22/repo"
        credentials {
            username 'user'
            password 'password'
        }
    }
}

51.6.2. Mavenセントラルリポジトリ Maven central repository

To add the central Maven 2 repository (http://repo1.maven.org/maven2) simply add this to your build script: Maven2のセントラルリポジトリ(http://repo1.maven.org/maven2)は、次のように簡単に追加できます。

例51.27 Mavenセントラルリポジトリを追加する

build.gradle

repositories {
    mavenCentral()
}

Now Gradle will look for your dependencies in this repository.

Warning: Be aware that the central Maven 2 repository is HTTP only and HTTPS is not supported. If you need a public HTTPS enabled central repository, you can use the JCenter public repository (see 「Maven JCenterリポジトリ Maven JCenter repository).

これで、Gradleはこのリポジトリから依存関係を探すようになります。

51.6.3. Maven JCenterリポジトリ Maven JCenter repository

Bintray's JCenter is an up-to-date collection of all popular Maven OSS artifacts, including artifacts published directly to Bintray.

BintrayのJCenterには、Bintrayに直接公開されたアーティファクトだけでなく、ポピュラーなMaven上のOSSライブラリが全て集められ、随時更新されています。

To add the JCenter Maven repository (https://jcenter.bintray.com) simply add this to your build script: JCenter Mavenリポジトリ(https://jcenter.bintray.com)は、次のように簡単に追加できます。

例51.28 BintrayのJCenter Mavenリポジトリを追加する

build.gradle

repositories {
    jcenter()
}

Now Gradle will look for your dependencies in the JCenter repository. jcenter() uses HTTPS to connect to the repository. If you want to use HTTP you can configure jcenter():

これで、GradleはJCenterリポジトリから依存関係を探すようになります。 jcenter() uses HTTPS to connect to the repository. If you want to use HTTP you can configure jcenter():

例51.29 Using Bintrays's JCenter with HTTP

build.gradle

repositories {
    jcenter {
        url "http://jcenter.bintray.com/"
    }
}

51.6.4. ローカルMavenリポジトリ Local Maven repository

To use the local Maven cache as a repository you can do:

Mavenのローカルキャッシュをリポジトリとして使うには、次のようにします。

例51.30 Mavenのローカルキャッシュをリポジトリとして追加する

build.gradle

repositories {
    mavenLocal()
}

Gradle uses the same logic as Maven to identify the location of your local Maven cache. If a local repository location is defined in a settings.xml, this location will be used. The settings.xml in USER_HOME/.m2 takes precedence over the settings.xml in M2_HOME/conf. If no settings.xml is available, Gradle uses the default location USER_HOME/.m2/repository.

Gradleは、Mavenが使っているのと同じロジックでローカルキャッシュの場所を決定します。 もしローカルリポジトリの場所がsettings.xmlで定義されていれば、そこが使用されます。 USER_HOME/.m2settings.xmlは、M2_HOME/confsettings.xmlよりも優先されます。 使用できるsettings.xmlがなければ、デフォルトのUSER_HOME/.m2/repositoryがローカルキャッシュの場所になります。

51.6.5. Mavenリポジトリ Maven repositories

For adding a custom Maven repository you can do:

カスタムのMavenリポジトリを追加するには、次のようにします。

例51.31 カスタムMavenリポジトリを追加する

build.gradle

repositories {
    maven {
        url "http://repo.mycompany.com/maven2"
    }
}

Sometimes a repository will have the POMs published to one location, and the JARs and other artifacts published at another location. To define such a repository, you can do:

POMとJARなどのアーティファクトを別々の場所に配置するようなリポジトリもあります。このようなリポジトリを設定するには、次のようにします

例51.32 JARファイル用の追加リポジトリを設定する

build.gradle

repositories {
    maven {
        // Look for POMs and artifacts, such as JARs, here
        url "http://repo2.mycompany.com/maven2"
        // Look for artifacts here if not found at the above location
        artifactUrls "http://repo.mycompany.com/jars"
        artifactUrls "http://repo.mycompany.com/jars2"
    }
}

Gradle will look at the first URL for the POM and the JAR. If the JAR can't be found there, the artifact URLs are used to look for JARs.

Gradleは、最初のURLを、POMとJARを探すために使用します。JARがそこで見つからなかった場合は、アーティファクトURLを使ってJARを探しに行きます。

51.6.5.1. パスワードで保護されたMavenリポジトリへのアクセス Accessing password protected Maven repositories

To access a Maven repository which uses basic authentication, you specify the username and password to use when you define the repository:

BASIC認証で保護されたMavenリポジトリにアクセスするには、リポジトリ定義でユーザー名とパスワードを指定します。

例51.33 パスワード保護されたMavenリポジトリへのアクセス

build.gradle

repositories {
    maven {
        credentials {
            username 'user'
            password 'password'
        }
        url "http://repo.mycompany.com/maven2"
    }
}

It is advisable to keep your username and password in gradle.properties rather than directly in the build file.

ユーザー名、パスワードは、ビルドファイルに直接指定するのではなく、gradle.propertiesに外出しすることを推奨します。

51.6.6. フラットディレクトリリポジトリ Flat directory repository

If you want to use a (flat) filesystem directory as a repository, simply type:

ファイルシステム上の(フラットな)ディレクトリをリポジトリとして使用したい場合は、単に次のようにタイプしてください。

例51.34 フラットディレクトリ・リゾルバ

build.gradle

repositories {
    flatDir {
        dirs 'lib'
    }
    flatDir {
        dirs 'lib1', 'lib2'
    }
}

This adds repositories which look into one or more directories for finding dependencies. If you only work with flat directory resolvers you don't need to set all attributes of a dependency. See 「オプション属性 Optional attributes

これで、依存関係を取得するリポジトリとして複数のディレクトリが追加されました。 このフラットディレクトリ・リゾルバのみ使うのであれば、依存関係定義ですべての属性を定義する必要はありません。「オプション属性 Optional attributesをご参照ください。

51.6.7. Ivyリポジトリ Ivy repositories

51.6.7.1. Defining an Ivy repository with a standard layout

例51.35 Ivyリポジトリ

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
    }
}

51.6.7.2. Defining a named layout for an Ivy repository

You can specify that your repository conforms to the Ivy or Maven default layout by using a named layout.

例51.36 Ivy repository with named layout

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
        layout "maven"
    }
}

Valid named layout values are 'gradle' (the default), 'maven' and 'ivy'. See IvyArtifactRepository.layout() in the API documentation for details of these named layouts.

51.6.7.3. Ivyリポジトリのカスタムパターンを定義する Defining custom patterns for an Ivy repository

To define an Ivy repository with a non-standard layout, you can define a pattern layout for the repository:

標準的でないレイアウトのIvyリポジトリを使うには、リポジトリのパターンレイアウトを定義します。

例51.37 パターンレイアウトを指定したIvyリポジトリ

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
        layout "pattern", {
            artifact "[module]/[revision]/[type]/[artifact].[ext]"
        }
    }
}

51.6.7.4. Maven互換レイアウトのIvyリポジトリ Ivy repository with Maven compatible layout

Optionally, a repository with pattern layout can have its 'organisation' part laid out in Maven style, with forward slashes replacing dots as separators. For example, the organisation my.company would then be represented as my/company.

オプションとして、パターンレイアウトを定義する際、「organisation」部分をMavenスタイルに展開し、ドットの代わりにスラッシュを用いるようにできます。 例えば、my.companyという組織名はmy/companyと表現されます。

例51.38 Maven互換レイアウトのIvyリポジトリ

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
        layout "pattern", {
            artifact "[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
            m2compatible = true
        }
    }
}

Valid named layout values are 'gradle' (the default), 'maven' and 'ivy'. See IvyArtifactRepository.layout() in the API documentation for details of these named layouts.

51.6.7.5. アーティファクトとivyファイルの場所が異なるIvyリポジトリの設定 Defining different artifact and Ivy file locations for an Ivy repository

To define an Ivy repository which fetches Ivy files and artifacts from different locations, you can use the pattern layout with separate patterns to use to locate the Ivy files and artifacts:

例51.39 Ivy repository with pattern layout

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
        layout "pattern", {
            artifact "[module]/[revision]/[type]/[artifact].[ext]"
        }
    }
}

To define an Ivy repository which fetches Ivy files and artifacts from different locations, you can define separate patterns to use to locate the Ivy files and artifacts:

Each artifact or ivy specified for a repository adds an additional pattern to use. The patterns are used in the order that they are defined.

例51.40 Ivy repository with multiple custom patterns

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
        layout "pattern", {
            artifact "3rd-party-artifacts/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
            artifact "company-artifacts/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
            ivy "ivy-files/[organisation]/[module]/[revision]/ivy.xml"
        }
    }
}

Optionally, a repository with pattern layout can have its 'organisation' part laid out in Maven style, with forward slashes replacing dots as separators. For example, the organisation my.company would then be represented as my/company.

例51.41 Ivy repository with Maven compatible layout

build.gradle

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
        layout "pattern", {
            artifact "[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
            m2compatible = true
        }
    }
}

51.6.7.6. パスワードで保護されたIvyリポジトリへのアクセス Accessing password protected Ivy repositories

To access an Ivy repository which uses basic authentication, you specify the username and password to use when you define the repository:

BASIC認証で保護されたIvyリポジトリへアクセスするには、リポジトリ定義の際にユーザー名とパスワードを指定します。

例51.42 パスワードで保護されたIvyリポジトリ

build.gradle

repositories {
    ivy {
        url 'http://repo.mycompany.com'
        credentials {
            username 'user'
            password 'password'
        }
    }
}

51.6.8. リポジトリを使った作業 Working with repositories

To access a repository:

リポジトリ定義にアクセスするには、

例51.43 リポジトリ定義へのアクセス

build.gradle

println repositories.localRepository.name
    println repositories['localRepository'].name

To configure a repository:

リポジトリの設定を変更するには、

例51.44 リポジトリの設定変更

build.gradle

repositories {
    flatDir {
        name 'localRepository'
    }
}
repositories {
    localRepository {
        dirs 'lib'
    }
}
repositories.localRepository {
    dirs 'lib'
}

51.6.9. Ivyリゾルバについて More about Ivy resolvers

Gradle, thanks to Ivy under its hood, is extremely flexible regarding repositories:

Gradleは、水面下でIvyを使っているおかげで、リポジトリに関しては非常に高い柔軟性を持っています。たとえば、

  • There are many options for the protocol to communicate with the repository (e.g. filesystem, http, ssh, sftp ...)

    リポジトリとの通信プロトコル(ファイルシステム、http、ssh、等々)がたくさん用意されている

  • The protocol sftp currently only supports username/password-based authentication.

  • Each repository can have its own layout.

    一つ一つのリポジトリが、それぞれ独自のレイアウトを持つことができる

Let's say, you declare a dependency on the junit:junit:3.8.2 library. Now how does Gradle find it in the repositories? Somehow the dependency information has to be mapped to a path. In contrast to Maven, where this path is fixed, with Gradle you can define a pattern that defines what the path will look like. Here are some examples: junit:junit:3.8.2へ依存していることを定義したとしましょう。このとき、Gradleはどのようにしてリポジトリからjunitを探すのでしょうか。そのためには、なんとかしてこの依存関係情報をファイルパスに変換する必要があります。Mavenではその変換方法は変更できませんが、Gradleではパスをどのように決定するか、そのパターンを自分で定義できます。たとえば、 [24]

// Maven2 レイアウト (Maven2と互換性があるとマークすれば、組織(グループ)フォルダは組織名のドットに従ってサブフォルダに分割される)
someroot/[organisation]/[module]/[revision]/[module]-[revision].[ext]

// 典型的なIvyリポジトリレイアウト(組織フォルダがサブフォルダに分割されない)
someroot/[organisation]/[module]/[revision]/[type]s/[artifact].[ext]

// シンプルなレイアウト(組織名は使用せず、フォルダをネストしない)
someroot/[artifact]-[revision].[ext]

To add any kind of repository (you can pretty easy write your own ones) you can do:

上記のどのリポジトリも、以下のようにして参照できます。

例51.45 カスタムリポジトリの定義

build.gradle

repositories {
    ivy {
        ivyPattern "$projectDir/repo/[organisation]/[module]-ivy-[revision].xml"
        artifactPattern "$projectDir/repo/[organisation]/[module]-[revision](-[classifier]).[ext]"
    }
}

An overview of which Resolvers are offered by Ivy and thus also by Gradle can be found here. With Gradle you just don't configure them via XML but directly via their API.

Ivyで(つまりGradleで)どんなリゾルバを使えるかはここで見ることができます。Gradleでは、XMLを経由することなく直接これらのAPIを操作できます。

51.7. 依存関係解決の仕組み How dependency resolution works

Gradle takes your dependency declarations and repository definitions and attempts to download all of your dependencies by a process called dependency resolution. Below is a brief outline of how this process works.

Gradleは、ビルドスクリプトの依存関係宣言とリポジトリ定義を読み込み、依存関係解決と呼ばれる処理によって依存関係を全てダウンロードしようと試みます。以下に、その処理がどのように進むか、概要を記載しました。

  • Given a required dependency, Gradle first attempts to resolve the module for that dependency. Each repository is inspected in order, searching first for a module descriptor file (POM or Ivy file) that indicates the presence of that module. If no module descriptor is found, Gradle will search for the presence of the primary module artifact file indicating that the module exists in the repository.

    必要な依存関係が指示されると、Gradleはまず、リポジトリを順に検査して、その依存関係のモジュールを解決しようとします。 モジュールディスクリプタファイル(POMまたはIvyファイル)が見つかれば、リポジトリにモジュールがあると判断します。ディスクリプタファイルが見つからない場合は、デフォルトのモジュールアーティファクトファイルがあるかどうかでモジュールの有無を判断します。

    • If the dependency is declared as a dynamic version (like 1.+), Gradle will resolve this to the newest available static version (like 1.2) in the repository. For Maven repositories, this is done using the maven-metadata.xml file, while for Ivy repositories this is done by directory listing.

      もし、依存関係が動的バージョン(1.+のような)で指定されていれば、Gradleは動的バージョンを、リポジトリ内の最新の静的バージョン(1.2など)に解決します。この処理は、Mavenリポジトリに対してはmaven-metadata.xmlファイルを使って行われ、Ivyリポジトリの場合はディレクトリ内の一覧表示が使用されます。

    • If the module descriptor is a POM file that has a parent POM declared, Gradle will recursively attempt to resolve each of the parent modules for the POM.

      モジュールディスクリプタが、親POMの宣言を含むPOMファイルだった場合、GradleはPOMの親モジュールを再帰的に解決しようとします。

  • Once each repository has been inspected for the module, Gradle will choose the 'best' one to use. This is done using the following criteria: 全てのリポジトリでモジュールの調査が終わると、Gradleはそれらのリポジトリの中から、使うのに「最も良い」リポジトリを選択します。どれが最良かは以下の基準で決定されます。

    • For a dynamic version, a 'higher' static version is preferred over a 'lower' version. 動的バージョンに関しては、なるべく新しい静的バージョンが使用できるリポジトリが好ましい。
    • Modules declared by a module descriptor file (Ivy or POM file) are preferred over modules that have an artifact file only. モジュールディスクリプタ(ivyやpomファイル)で宣言されているモジュールは、アーティファクトファイルしかないモジュールよりも好ましい。
    • Modules from earlier repositories are preferred over modules in later repositories. 早く見に行ったリポジトリのほうが、後のリポジトリよりも優先される。

    When the dependency is declared by a static version and a module descriptor file is found in a repository, there is no need to continue searching later repositories and the remainder of the process is short-circuited.

    依存関係が静的バージョンで宣言されており、かつモジュールディスクリプタがリポジトリにあれば、後続のリポジトリを探索する必要はないので、処理を飛ばすことができます。

  • All of the artifacts for the module are then requested from the same repository that was chosen in the process above.

    モジュール内の全アーティファクトを、上記処理で選択したリポジトリと同じリポジトリに取得しに行きます。

51.8. 依存関係解決処理の微調整 Fine-tuning the dependency resolution process

In most cases, Gradle's default dependency management will resolve the dependencies that you want in your build. In some cases, however, it can be necessary to tweak dependency resolution to ensure that your build receives exactly the right dependencies.

Gradleの依存関係管理は、ほとんどの場合、デフォルトのままでビルドに必要な依存関係を解決できます。しかし、正しい依存関係を確実に受け取るために、解決処理を調整する必要がある場合もあります。

There are a number of ways that you can influence how Gradle resolves dependencies.

Gradleの依存関係解決処理は、様々な部分で調整可能です。

51.8.1. モジュールのバージョンを強制する Forcing certain module versions

Forcing a module version tells Gradle to always use a specific version for given dependency (transitive or not), overriding any version specified in a published module descriptor. This can be very useful when tackling version conflicts - for more information see 「バージョン競合の解決 Resolve version conflicts.

指定した依存関係について、(推移的かどうかにかかわらず)指定したバージョンを使うよう解決処理を設定できます。 依存関係は、グループ名と名前で指定します。この機能は、バージョンの競合に四苦八苦している際にとても便利です。詳細については、「バージョン競合の解決 Resolve version conflictsを参照してください。

Force versions can also be used to deal with rogue metadata of transitive dependencies. If a transitive dependency has poor quality metadata that leads to problems at dependency resolution time, you can force Gradle to use a newer, fixed version of this dependency. For an example, see the ResolutionStrategy class in the API documentation. Note that 'dependency resolve rules' (outlined below) provide a more powerful mechanism for replacing a broken module dependency. See 「バージョンのブラックリストと差し替え Blacklisting a version with a replacement.

また、推移的な依存関係のメタデータが壊れている場合もこれで対処できることがあります。推移的な依存関係のメタデータがあまりに低品質で、依存関係を解決する際に問題が発生している場合、モジュールのバージョンを修正された新バージョンに強制できます。ResolutionStrategyの例を参照してください。また、「依存関係解決ルール」は壊れたモジュールを置き換える更に強力な機構を提供します。「バージョンのブラックリストと差し替え Blacklisting a version with a replacementを参照してください。

51.8.2. 依存関係解決ルールを使う Using dependency resolve rules

A dependency resolve rule is executed for each resolved dependency, and offers a powerful api for manipulating a requested dependency prior to that dependency being resolved. This feature is incubating, but currently offers the ability to change the group, name and/or version of a requested dependency, allowing a dependency to be substituted with a completely different module during resolution.

依存関係解決ルールは、全ての依存関係に対して実行され、要求された依存関係を解決前に操作する強力なAPIを提供します。 この機能は試験的なものですが、要求した依存関係のグループ名や名前、バージョンを変更し、解決処理中に依存関係を完全に別のモジュールに差し替えてしまうことが可能です。

Dependency resolve rules provide a very powerful way to control the dependency resolution process, and can be used to implement all sorts of advanced patterns in dependency management. Some of these patterns are outlined below. For more information and code samples see the ResolutionStrategy class in the API documentation.

依存関係解決ルールは依存関係をコントロールする非常に強力な手段で、依存関係管理における先進的なパターンを全て実装できます。 いくつかのパターンの概要を以下に紹介します。詳細な情報やコードサンプル等はResolutionStrategyをご参照ください。

51.8.2.1. リリース可能単位を表現する Modelling releaseable units

Often an organisation publishes a set of libraries with a single version; where the libraries are built, tested and published together. These libraries form a 'releasable unit', designed and intended to be used as a whole. It does not make sense to use libraries from different releasable units together.

組織によっては、いくつかのライブラリをまとめて一つのバージョンでリリースすることがあります。それらのライブラリは、一緒にビルド、テストされ、公開されます。 そのようなライブラリ群は、「リリース可能単位」として構成され、一緒に使用されることが想定されています。一般的に、別々のリリース可能単位を混ぜて使うことは意味がありません。

But it is easy for transitive dependency resolution to violate this contract. For example: しかし、この制限は、推移的な依存関係の中で簡単に破られてしまいます。以下の例をご覧ください。

  • module-a depends on releasable-unit:part-one:1.0
  • module-b depends on releasable-unit:part-two:1.1

A build depending on both module-a and module-b will obtain different versions of libraries within the releasable unit. module-amodule-bの両方に依存しているビルドがあれば、それぞれのモジュールがリリース可能単位を構成するライブラリの別々のバージョンを取得してしまうでしょう。

Dependency resolve rules give you the power to enforce releasable units in your build. Imagine a releasable unit defined by all libraries that have 'org.gradle' group. We can force all of these libraries to use a consistent version: 依存関係解決ルールを使うと、ビルドで使用するリリース可能単位を強制できます。 'org.gradle'グループに属する全てのライブラリが、あるリリース可能単位を構成していると想像してください。これらのライブラリについては一貫したバージョンを使うよう強制することができます。

例51.46 あるグループのライブラリ全てで一貫したバージョンを使用するよう強制する

build.gradle

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == 'org.gradle') {
            details.useVersion '1.4'
        }
    }
}


51.8.2.2. 独自のバージョニング体制を実装する Implement a custom versioning scheme

In some corporate environments, the list of module versions that can be declared in gradle builds is maintained and audited externally. Dependency resolve rules provide a neat implementation of this pattern: 社内環境によっては、gradleのビルドで使用できるモジュールのバージョンリストを外部的に監視、維持していることがあります。 依存関係解決ルールはこのようなパターンを簡潔に実装できます。

  • In the build script, the developer declares dependencies with the module group and name, but uses a placeholder version, for example: 'default'. ビルドスクリプトでは、使用するモジュールのグループと名前を開発者が記述しますが、バージョンだけは「default」などのプレースホルダで宣言します。
  • The 'default' version is resolved to a specific version via a dependency resolve rule, which looks up the version in a corporate catalog of approved modules.default」バージョンは、依存関係解決ルールがある特定のバージョンに置換します。その際、承認されたモジュールの一覧が記載された社内カタログなどを参照します。

This rule implementation can be neatly encapsulated in a corporate plugin, and shared across all builds within the organisation. このルールの実装は、整理して社内プラグインにカプセル化し、組織内の全てのビルドで共有することもできます。

例51.47 独自のバージョニング体制を実装する

build.gradle

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.version == 'default') {
            def version = findDefaultVersionInCatalog(details.requested.group, details.requested.name)
            details.useVersion version
        }
    }
}

def findDefaultVersionInCatalog(String group, String name) {
    //some custom logic that resolves the default version into a specific version
    "1.0"
}


51.8.2.3. バージョンのブラックリストと差し替え Blacklisting a version with a replacement

Dependency resolve rules provide a mechanism for blacklisting a particular version of a dependency and providing a replacement version. This can be useful if a certain dependency version is broken and should not be used, where a dependency resolve rule causes this version to be replaced with a known good version. One example of a broken module is one that declares a dependency on a library that cannot be found in any of the public repositories, but there are many other reasons why a particular module version is unwanted and a different version is preferred.

依存関係解決ルールを使って、あるモジュールの特定のバージョンをブラックリストに指定し、バージョンを差し替えるような機構を実装できます。 これは、あるモジュールにおいて特定のバージョンが壊れていて使いたくないという場合に有用で、そのバージョンを依存関係解決処理が引っ張ってきてしまったときにそれを感知し、優良だと分かっている別のバージョンに差し替えることができます。 一例を挙げると、どこの公開リポジトリにも存在しないライブラリに依存しているようなモジュールは「壊れたモジュール」だと言えます。しかし、その他にもあるバージョンは使いたくない、別のバージョンを使いたいという理由はたくさんあるでしょう。

In example below, imagine that version 1.2.1 contains important fixes and should always be used in preference to 1.2. The rule provided will enforce just this: any time version 1.2 is encountered it will be replaced with 1.2.1. Note that this is different from a forced version as described above, in that any other versions of this module would not be affected. This means that the 'newest' conflict resolution strategy would still select version 1.3 if this version was also pulled transitively. 以下の例では、バージョン1.2.1に重要な修正が含まれていて、1.2ではなく必ずそちらを使いたい、という状況を想定しています。 例のルールは、単にバージョン1.2を見つけたら必ず1.2.1に差し替えられるということを保証しているだけですが、注目すべき点は、これが上の方で述べたバージョンの強制とは異なるということです。ここでは、1.2以外の全てのバージョンはそのまま受け入れられます。 例えばバージョン1.3もどこかで推移的に引っ張られている場合、競合解決戦略「newest」によりバージョン1.3が選択されるでしょう。

例51.48 バージョンのブラックリスト指定と差し替

build.gradle

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.group == 'org.software' && details.requested.name == 'some-library' && details.requested.version == '1.2') {
            //prefer different version which contains some necessary fixes
            details.useVersion '1.2.1'
        }
    }
}


51.8.2.4. 依存モジュールを互換性のあるモジュールに差し替える Substituting a dependency module with a compatible replacement

At times a completely different module can serve as a replacement for a requested module dependency. Examples include using 'groovy' in place of 'groovy-all', or using 'log4j-over-slf4j' instead of 'log4j'. Starting with Gradle 1.5 you can make these substitutions using dependency resolve rules: 要求されたモジュールを、全く異なる別モジュールに差し替えることができる場合もあります。 例にあるのは、「groovy-all」から「groovy」への差し替えと「log4j」から「log4j-over-slf4j」への差し替えです。 Gradle1.5から、このような置き換えも依存関係解決ルールで可能になりました。

例51.49 解決時に依存関係のグループ名や名前を変更する

build.gradle

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.name == 'groovy-all') {
            //prefer 'groovy' over 'groovy-all':
            details.useTarget group: details.requested.group, name: 'groovy', version: details.requested.version
        }
        if (details.requested.name == 'log4j') {
            //prefer 'log4j-over-slf4j' over 'log4j', with fixed version:
            details.useTarget "org.slf4j:log4j-over-slf4j:1.7.7"
        }
    }
}


51.8.2.5. Declaring that a legacy library is replaced by a new one

A good example when a new library replaced a legacy one is the "google-collections" -> "guava" migration. The team that created google-collections decided to change the module name from "com.google.collections:google-collections" into "com.google.guava:guava". This a legal scenario in the industry: teams need to be able to change the names of products they maintain, including the module coordinates. Renaming of the module coordinates has impact on conflict resolution.

To explain the impact on conflict resolution, let's consider the "google-collections" -> "guava" scenario. It may happen that both libraries are pulled into the same dependency graph. For example, "our" project depends on guava but some of our dependencies pull in a legacy version of google-collections. This can cause runtime errors, for example during test or application execution. Gradle does not automatically resolve the google-collections VS guava conflict because it is not considered as a "version conflict". It's because the module coordinates for both libraries are completely different and conflict resolution is activated when "group" and "name" coordinates are the same but there are different versions available in the dependency graph (for more info, please refer to the section on conflict resolution). Traditional remedies to this problem are:

  • Declare exclusion rule to avoid pulling in "google-collections" to graph. It is probably the most popular approach.
  • Avoid dependencies that pull in legacy libraries.
  • Upgrade the dependency version if the new version no longer pulls in a legacy library.
  • Downgrade to "google-collections". It's not recommended, just mentioned for completeness.

Traditional approaches work but they are not general enough. For example, an organisation wants to resolve the google-collections VS guava conflict resolution problem in all projects. Starting from Gradle 2.2 it is possible to declare that certain module was replaced by other. This enables organisations to include the information about module replacement in the corporate plugin suite and resolve the problem holistically for all Gradle-powered projects in the enterprise.

例51.50 Declaring module replacement

build.gradle

dependencies {
    components {
        module("com.google.collections:google-collections").replacedBy("com.google.guava:guava")
    }
}


For more examples and detailed API, please refer to the DSL reference for ComponentMetadataHandler.

What happens when we declare that "google-collections" are replaced by "guava"? Gradle can use this information for conflict resolution. Gradle will consider every version of "guava" newer/better than any version of "google-collections". Also, Gradle will ensure that only guava jar is present in the classpath / resolved file list. Please note that if only "google-collections" appears in the dependency graph (e.g. no "guava") Gradle will not eagerly replace it with "guava". Module replacement is an information that Gradle uses for resolving conflicts. If there is no conflict (e.g. only "google-collections" or only "guava" in the graph) the replacement information is not used.

Currently it is not possible to declare that certain modules is replaced by a set of modules. However, it is possible to declare that multiple modules are replaced by a single module.

51.8.3. Ivyの動的解決モードを有効にする Enabling Ivy dynamic resolve mode

Gradle's Ivy repository implementations support the equivalent to Ivy's dynamic resolve mode. Normally, Gradle will use the rev attribute for each dependency definition included in an ivy.xml file. In dynamic resolve mode, Gradle will instead prefer the revConstraint attribute over the rev attribute for a given dependency definition. If the revConstraint attribute is not present, the rev attribute is used instead.

GradleのIvyレポジトリ実装は、Ivyの動的解決モードと同等のものをサポートしています。通常、Gradleは依存関係についてivy.xmlファイルで定義されているrev属性を使用しますが、動的解決モードでは、Gradleはrev属性の代わりにrevConstraint属性を優先して使用します。revConstraintが未定義の時はrev属性を使用します。

To enable dynamic resolve mode, you need to set the appropriate option on the repository definition. A couple of examples are shown below. Note that dynamic resolve mode is only available for Gradle's Ivy repositories. It is not available for Maven repositories, or custom Ivy DependencyResolver implementations.

動的解決モードを有効にするには、リポジトリ定義に適切なオプションを設定する必要があります。いくつかの例を以下に挙げます。動的解決モードは、Gradle組み込みのIvyリポジトリ定義でしか使用できないことに注意してください。Mavenリポジトリや独自DependencyResolver実装のIvyリポジトリでは使用できません。

例51.51 動的解決モードを有効にする

build.gradle

// Can enable dynamic resolve mode when you define the repository
repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
        resolve.dynamicMode = true
    }
}

// Can use a rule instead to enable (or disable) dynamic resolve mode for all repositories
repositories.withType(IvyArtifactRepository) {
    resolve.dynamicMode = true
}

51.8.4. Component metadata rules

Each module (also called component) has metadata associated with it, such as its group, name, version, dependencies, and so on. This metadata typically originates in the module's descriptor. Metadata rules allow certain parts of a module's metadata to be manipulated from within the build script. They take effect after a module's descriptor has been downloaded, but before it has been selected among all candidate versions. This makes metadata rules another instrument for customizing dependency resolution.

One piece of module metadata that Gradle understands is a module's status scheme. This concept, also known from Ivy, models the different levels of maturity that a module transitions through over time. The default status scheme, ordered from least to most mature status, is integration, milestone, release. Apart from a status scheme, a module also has a (current) status, which must be one of the values in its status scheme. If not specified in the (Ivy) descriptor, the status defaults to integration for Ivy modules and Maven snapshot modules, and release for Maven modules that aren't snapshots.

A module's status and status scheme are taken into consideration when a latest version selector is resolved. Specifically, latest.someStatus will resolve to the highest module version that has status someStatus or a more mature status. For example, with the default status scheme in place, latest.integration will select the highest module version regardless of its status (because integration is the least mature status), whereas latest.release will select the highest module version with status release. Here is what this looks like in code:

例51.52 'Latest' version selector

build.gradle

dependencies {
    config1 "sea.fish:tuna:latest.integration"
    config2 "sea.fish:tuna:latest.release"
}

task listFish << {
    configurations.config1.each { println it.name }
    println()
    configurations.config2.each { println it.name}
}

gradle -q listFish の出力

> gradle -q listFish
tuna-1.5.jar

tuna-1.4.jar

The next example demonstrates latest selectors based on a custom status scheme declared in a module metadata rule:

例51.53 Custom status scheme

build.gradle

dependencies {
    config3 "air.birds:albatross:latest.silver"
    components {
        eachComponent { ComponentMetadataDetails details ->
            if (details.id.group == "air.birds") {
                details.statusScheme = ["bronze", "silver", "gold", "platinum"]
            }
        }
    }
}

task listBirds << {
    configurations.config3.each { println it.name }
}

gradle -q listBirds の出力

> gradle -q listBirds
albatross-2.0.jar

Gradle can also create component metadata rules utilizing Ivy-specific metadata for modules resolved from an Ivy repository. Values from the Ivy descriptor are made available via the IvyModuleDescriptor interface.

例51.54 Ivy component metadata rule

build.gradle

dependencies {
    components {
        eachComponent { ComponentMetadataDetails details, IvyModuleDescriptor ivyModule ->
            if (details.id.group == 'my.org' && ivyModule.branch == 'testing') {
                details.changing = true
            }
        }
    }
}

51.8.5. Component Selection Rules

Component selection rules define how versions should be selected when multiple versions are available that match a given set of coordinates. Rules are applied against every available version and allow the version to be explicitly rejected by rule. This allows Gradle to select alternate versions when the alternate version is not known in advance.

Rules are configured via the ComponentSelectionRules object. Each rule configured will be called with a ComponentSelection object as an argument which contains information about the version being requested and the candidate version being considered. Calling ComponentSelection.reject() causes the given candidate version to be explicitly rejected, in which case the candidate will not be considered for the selector.

The following example shows a rule that disallows a particular version of a module but allows the default version selection rules to choose the next best candidate. If the version requested was 1.+, and versions 1.1, 1.0.1 and 1.0 were available, it would reject 1.1 and select the next newest version available (1.0.1).

例51.55 Component selection rule

build.gradle

configurations {
    rejectConfig {
        resolutionStrategy {
            componentSelection {
                // Accept the highest version matching the requested version that isn't '1.1'
                all { ComponentSelection selection ->
                    if (selection.candidate.group == 'org.sample' && selection.candidate.module == 'api' && selection.candidate.version == '1.1') {
                        selection.reject("version 1.1 is broken for 'org.sample:api'")
                    }
                }
            }
        }
    }
}

Note that version selection is applied starting with the highest version first. The version selected will be the first version found that all component selection rules accept. A version is considered accepted if a rule does not explicitly reject it.

Similarly, rules can be targeted at specific modules. Modules must be specified in the form of "group:module".

例51.56 Component selection rule with module target

build.gradle

configurations {
    targetConfig {
        resolutionStrategy {
            componentSelection {
                module("org.sample:api") { ComponentSelection selection ->
                    if (selection.candidate.version == "1.1") {
                        selection.reject("known bad version")
                    }
                }
            }
        }
    }
}

Component selection rules can also consider component metadata when selecting a version. Possible metadata arguments that can be considered are ComponentMetadata and IvyModuleDescriptor.

例51.57 Component selection rule with metadata

build.gradle

configurations {
    rejectConfig {
        resolutionStrategy {
            componentSelection {
                // Reject any versions with a status of 'experimental'
                all { ComponentSelection selection, ComponentMetadata metadata ->
                    if (selection.candidate.group == 'org.sample' && selection.candidate.module == 'api') {
                        if (metadata.status == 'experimental') {
                            selection.reject("don't use experimental candidates of 'org.sample:api'")
                        }
                    }
                }
                // Accept the highest version with a branch of 'testing' or a status of 'milestone'
                all { ComponentSelection selection, IvyModuleDescriptor descriptor, ComponentMetadata metadata ->
                    if (selection.candidate.group == 'org.sample' && selection.candidate.module == 'api') {
                        if (descriptor.branch != 'testing' && metadata.status != 'milestone') {
                            selection.reject("'org.sample:api' must have testing branch or milestone status")
                        }
                    }
                }
            }
        }
    }
}

Note that a ComponentSelection argument is always required when declaring a component selection rule but the metadata arguments are optional.

51.9. 依存関係のキャッシュ The dependency cache

Gradle contains a highly sophisticated dependency caching mechanism, which seeks to minimise the number of remote requests made in dependency resolution, while striving to guarantee that the results of dependency resolution are correct and reproducible.

Gradleは、非常に洗練された依存関係のキャッシング機構を持っており、依存関係の解決の際、リモートまでリクエストを飛ばす回数を最小限に抑えるようにしています。 また、その際、依存関係解決の正確性、再現性を最大限保証できるような仕組みを備えています。

The Gradle dependency cache consists of 2 key types of storage:

Gradleの依存関係キャッシュは、二種類のストレージで構成されています。

  • A file-based store of downloaded artifacts, including binaries like jars as well as raw downloaded meta-data like POM files and Ivy files. The storage path for a downloaded artifact includes the SHA1 checksum, meaning that 2 artifacts with the same name but different content can easily be cached.

    ダウンロードされたアーティファクトを保存する、ファイルベースのストレージ。pomファイルやivyファイルのようなダウンロード済みの生メタデータだけでなく、jarなどのバイナリも格納される。 ダウンロード済みのアーティファクトを保存するストレージパスには、SHA1のチェックサムが含まれているので、同名の別アーティファクトも簡単にキャッシュできる。

  • A binary store of resolved module meta-data, including the results of resolving dynamic versions, module descriptors, and artifacts.

    解決済みのメタデータを保存するバイナリストレージ。動的バージョン、モジュールのディスクリプタやアーティファクトなどの解決結果が格納される。

Separating the storage of downloaded artifacts from the cache metadata permits us to do some very powerful things with our cache that would be difficult with a transparent, file-only cache layout.

メタデータのキャッシュとダウンロードしたアーティファクトを別のストレージに分けることで、ファイルのみの透過的なキャッシュレイアウトでは困難な、強力な機能を実現できます。

The Gradle cache does not allow the local cache to hide problems and create other mysterious and difficult to debug behavior that has been a challenge with many build tools. This new behavior is implemented in a bandwidth and storage efficient way. In doing so, Gradle enables reliable and reproducible enterprise builds.

Gradleのキャッシュでは、ローカルキャッシュによって問題が隠蔽されるようなことはありませんし、多くのビルドツールで直面してきたような不可解でデバッグ困難な動作をすることもありません。 また、その実装は帯域、ストレージ双方において効率的なものです。それにより、Gradleはエンタープライズでのビルドに必要な信頼性、再現性を達成しているのです。

51.9.1. Gradleにおける依存関係キャッシュの重要な機能 Key features of the Gradle dependency cache

51.9.1.1. 分離されたメタデータ・キャッシュ Separate metadata cache

Gradle keeps a record of various aspects of dependency resolution in binary format in the metadata cache. The information stored in the metadata cache includes: Gradleは、依存関係を解決した結果を様々な観点から記録し、バイナリ形式でメタデータ・キャッシュに保存します。 メタデータ・キャッシュに保存される情報には以下のようなものがあります。

  • The result of resolving a dynamic version (e.g. 1.+) to a concrete version (e.g. 1.2). (1.+のような)動的バージョンを具体的なバージョン(1.2など)に解決したその結果。
  • The resolved module metadata for a particular module, including module artifacts and module dependencies. それぞれのモジュールの解決済みメタデータ。モジュールのアーティファクトや依存関係など。
  • The resolved artifact metadata for a particular artifact, including a pointer to the downloaded artifact file. それぞれのアーティファクトの、解決済みメタデータ。ダウンロードしたファイルへのポインタを含む。
  • The absence of a particular module or artifact in a particular repository, eliminating repeated attempts to access a resource that does not exist. あるモジュールやアーティファクトがリポジトリに無いことを記録し、存在しないリソースに繰り返しアクセスしに行くことを防ぐ。

Every entry in the metadata cache includes a record of the repository that provided the information as well as a timestamp that can be used for cache expiry. メタデータ・キャッシュの全てのエントリには、リポジトリに関する記録が含まれていて、キャッシュの有効期限を制御したりするのに使われるタイムスタンプなどの情報を取得できるようになっています。

51.9.1.2. リポジトリキャッシュの独立性 Repository caches are independent

As described above, for each repository there is a separate metadata cache. A repository is identified by its URL, type and layout. If a module or artifact has not been previously resolved from this repository, Gradle will attempt to resolve the module against the repository. This will always involve a remote lookup on the repository, however in many cases no download will be required (see「アーティファクトの再利用 Artifact reuse, below).

前述の通り、リポジトリにはそれぞれ独立したメタデータ・キャッシュが存在します。リポジトリはURL、種別、レイアウトにより別のリポジトリと区別されます。 もしそのリポジトリから、あるモジュールやアーティファクトをまだ解決したことがない場合、Gradleはリポジトリに対してモジュールを解決しに行きます。これは常にリポジトリに対するリモート・ルックアップを伴うわけですが、ほとんどのケースではダウンロードまでは要求されません(後述の「「アーティファクトの再利用 Artifact reuse」を参照してください)。

Dependency resolution will fail if the required artifacts are not available in any repository specified by the build, even if the local cache has a copy of this artifact which was retrieved from a different repository. Repository independence allows builds to be isolated from each other in an advanced way that no build tool has done before. This is a key feature to create builds that are reliable and reproducible in any environment.

ビルドで指定されたどのリポジトリにも要求されたアーティファクトがない場合、たとえ別のリポジトリのキャッシュにそのアーティファクトがあったとしても、依存関係の解決は失敗します。 リポジトリの独立性を保つことで、それぞれのビルドも高度に独立したものにしているのです。これは、従来のビルドツールにはない特徴で、あらゆる環境で高い信頼性と再現性を持つビルドを構築するためのキーとなります。

51.9.1.3. アーティファクトの再利用 Artifact reuse

Before downloading an artifact, Gradle tries to determine the checksum of the required artifact by downloading the sha file associated with that artifact. If the checksum can be retrieved, an artifact is not downloaded if an artifact already exists with the same id and checksum. If the checksum cannot be retrieved from the remote server, the artifact will be downloaded (and ignored if it matches an existing artifact).

アーティファクトをダウンロードする前に、Gradleは、そのアーティファクトに結びついたshaファイルをダウンロードして、アーティファクトのチェックサムを決定しようとします。 チェックサムをダウンロードできれば、そして既に同じIDとチェックサムを持つアーティファクトが存在すれば、ダウンロードは行われません。 チェックサムをリモートサーバーから取得できない場合、アーティファクトは常にダウンロードされます(既知のアーティファクトとマッチするかどうかは無視されます)。

As well as considering artifacts downloaded from a different repository, Gradle will also attempt to reuse artifacts found in the local Maven Repository. If a candidate artifact has been downloaded by Maven, Gradle will use this artifact if it can be verified to match the checksum declared by the remote server.

Gradleは、別のリポジトリからダウンロードされたアーティファクトだけでなく、Mavenのローカルリポジトリにあるアーティファクトも再利用しようとします。候補のアーティファクトが既にMavenによりダウンロードされたことがあれば、リモートサーバーで宣言されたチェックサムで検証してからそれらを再利用します。

51.9.1.4. チェックサムベースのストレージ Checksum based storage

It is possible for different repositories to provide a different binary artifact in response to the same artifact identifier. This is often the case with Maven SNAPSHOT artifacts, but can also be true for any artifact which is republished without changing it's identifier. By caching artifacts based on their SHA1 checksum, Gradle is able to maintain multiple versions of the same artifact. This means that when resolving against one repository Gradle will never overwrite the cached artifact file from a different repository. This is done without requiring a separate artifact file store per repository.

同じ識別子でアーティファクトを要求したのに、それぞれのリポジトリが別のバイナリを返すことがあります。良くあるケースがMavenのスナップショットですが、名称を変更せずにアーティファクトを再公開した場合にも同じことが起こります。 Gradleは、SHA1チェックサムに基づいてアーティファクトをキャッシングするので、同じアーティファクトの様々なバージョンを保持することができます。 これはつまり、あるリポジトリからアーティファクトを解決した際、別のリポジトリのファイルキャッシュが上書きされることは決してない、ということでもあります。 これを、それぞれのリポジトリごとに別個にアーティファクトファイルのキャッシュを持つことなく実現できるのです。

51.9.1.5. キャッシュのロック Cache Locking

The Gradle dependency cache uses file-based locking to ensure that it can safely be used by multiple Gradle processes concurrently. The lock is held whenever the binary meta-data store is being read or written, but is released for slow operations such as downloading remote artifacts.

Gradleの依存関係キャッシュは、並列に実行される複数のGradleプロセスから安全に使用できるよう、ファイルベースのロックを使用します。 このロックは、メタデータバイナリストレージの読み込みや書き込みの際には常に取得されますが、リモートからアーティファクトをダウンロードするときのような、時間のかかる操作の際には解放されます。

51.9.2. キャッシングに関するコマンドラインオプション Command line options to override caching

51.9.2.1. オフライン Offline

The --offline command line switch tells Gradle to always use dependency modules from the cache, regardless if they are due to be checked again. When running with offline, Gradle will never attempt to access the network to perform dependency resolution. If required modules are not present in the dependency cache, build execution will fail.

--offlineオプションを使うと、常にキャッシュされた依存モジュールを使用するようGradleに指示できます。依存モジュールが再検証されることになっていても無視されます。 オフラインで実行されると、Gradleは依存関係を解決するときにネットワークにアクセスしに行くことはありません。 要求されたモジュールが依存関係のキャッシュにない場合は、ビルドは失敗します。

51.9.2.2. リフレッシュ Refresh

At times, the Gradle Dependency Cache can be out of sync with the actual state of the configured repositories. Perhaps a repository was initially misconfigured, or perhaps a "non-changing" module was published incorrectly. To refresh all dependencies in the dependency cache, use the --refresh-dependencies option on the command line.

Gradleの依存関係キャッシュが、設定されたリポジトリの実際の状態と同期が取れていないこともあります。 おそらくは最初のリポジトリ設定が間違っていたか、未変更のモジュールが間違って公開されたのでしょう。キャッシュにある全ての依存関係をリフレッシュするには、コマンドラインで--refresh-dependenciesオプションを使用してください。

The --refresh-dependencies option tells Gradle to ignore all cached entries for resolved modules and artifacts. A fresh resolve will be performed against all configured repositories, with dynamic versions recalculated, modules refreshed, and artifacts downloaded. However, where possible Gradle will check if the previously downloaded artifacts are valid before downloading again. This is done by comparing published SHA1 values in the repository with the SHA1 values for existing downloaded artifacts.

--refresh-dependenciesオプションは、解決済みのモジュールとアーティファクトに対する全てのキャッシュエントリを無視するようGradleに指示します。 対象のリポジトリ全てに対して、新規に解決処理が実行されます。動的バージョンは再取得され、モジュールは再解決され、アーティファクトも再度ダウンロードされます。 ただ、実際にアーティファクトをダウンロードする前に、Gradleは以前ダウンロードしたものが使用できないか確認します。 これは、リポジトリで公開されているSHA1と、ダウンロード済みのアーティファクトのSHA1を比較することで行われます。

51.9.3. 依存関係キャッシュ制御の微調整 Fine-tuned control over dependency caching

You can fine-tune certain aspects of caching using the ResolutionStrategy for a configuration.

キャッシングについて、いくつかの動作は設定でResolutionStrategyを使うことで微調整することができます。

By default, Gradle caches dynamic versions for 24 hours. To change how long Gradle will cache the resolved version for a dynamic version, use:

デフォルトでは、Gradleは動的バージョンを24時間キャッシュします。動的バージョンを具体的なバージョンに解決したとき、それをどれだけの長さキャッシュするか制御するには、以下のようにします。

例51.58 動的バージョンのキャッシュ制御

build.gradle

configurations.all {
    resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes'
}

By default, Gradle caches changing modules for 24 hours. To change how long Gradle will cache the meta-data and artifacts for a changing module, use:

デフォルトでは、Gradleは変更性モジュールを24時間キャッシュします。変更性モジュールのメタデータとアーティファクトをどれだけの長さキャッシュするか制御するには、以下のようにします。

例51.59 変更性モジュールのキャッシュ制御

build.gradle

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 4, 'hours'
}

For more details, take a look at the API documentation for ResolutionStrategy.

詳しくはAPIドキュメントでResolutionStrategyを参照してください。

51.10. 推移的依存関係を管理するための戦略 Strategies for transitive dependency management

Many projects rely on the Maven Central repository. This is not without problems.

多くのプロジェクトがMavenセントラルリポジトリに依存していますが、これが時に問題になることもあります。

  • The Maven Central repository can be down or can be slow to respond.

    Mavenセントラルリポジトリはダウンする可能性もあり、またレスポンスが返るまで長い時間がかかります。

  • The POM files of many popular projects specify dependencies or other configuration that are just plain wrong (for instance, the POM file of the “commons-httpclient-3.0” module declares JUnit as a runtime dependency).

    POMファイルに間違った情報を入れているプロジェクトがたくさんあります(たとえば、commons-httpclient-3.0はJUnitをruntime依存関係に設定しています)。

  • For many projects there is not one right set of dependencies (as more or less imposed by the POM format).

    「ただ一つの正当な依存関係」というものが決められないようなプロジェクトもたくさんあります(つまり、POMのフォーマットのせいで、押しつけられる依存関係が多すぎたり少なすぎたりすることがあります)。

If your project relies on the Maven Central repository you are likely to need an additional custom repository, because:

もしプロジェクトがMavenセントラルリポジトリに依存しているのであれば、カスタムリポジトリを追加する必要があるかもしれません。以下のような場合も考えられるからです。

  • You might need dependencies that are not uploaded to Maven Central yet.

    まだMavenセントラルにアップロードされていない依存関係が必要になった。

  • You want to deal properly with invalid metadata in a Maven Central POM file.

    MavenセントラルのPOMファイルに誤ったメタデータが含まれていた。

  • You don't want to expose people to the downtimes or slow response of Maven Central, if they just want to build your project.

    プロジェクトをビルドしたいと思う人々がいて、彼らをMavenセントラルのダウンタイムや、時折発生する長時間のレスポンスタイムで煩わせたくない。

It is not a big deal to set-up a custom repository, [25] but it can be tedious to keep it up to date. For a new version, you always have to create the new XML descriptor and the directories. Your custom repository is another infrastructure element which might have downtimes and needs to be updated. To enable historical builds, you need to keep all the past libraries, not to mention a backup of these. It is another layer of indirection. Another source of information you have to lookup. All this is not really a big deal but in its sum it has an impact. Repository managers like Artifactory or Nexus make this easier, but most open source projects don't usually have a host for those products. This is changing with new services like Bintray that let developers host and distribute their release binaries using a self-service repository platform. Bintray also supports sharing approved artifacts though the JCenter public repository to provide a single resolution address for all popular OSS Java artifacts (see 「Maven JCenterリポジトリ Maven JCenter repository). そのリポジトリを最新に保つ作業は単調で退屈なものになりがちです。新しいバージョンが出るたびに、新しいXML設定ファイルとディレクトリを作成しなければなりません。それに、そのカスタムリポジトリもまたダウンしたり、保守する必要があったりするインフラのひとつです。過去のビルドを再現できるようにするには、過去使用したすべてのライブラリをバックアップしておく必要があります。 それは冗長な層が一つ増えるということでもあります。調査しなければならない情報元が増えるということです。一つ一つは本当に大したことではないかもしれませんが、積み重なっていけばやはり問題です。 ArtifactoryやNexusのようなリポジトリマネージャーを使えば、こういった作業も簡単になります。しかし、たとえばオープンソースプロジェクトなどは、普通このようなソフトウェアのホスティング先を持っていません。 ただ、この状況は、Bintrayのような、開発者が自分のバイナリをホストして配布できる新しいサービスのおかげで変わってきています。 Bintrayでは、承認されたアーティファクトをJCenterという公開リポジトリを通じて共有しており、Javaの全てのポピュラーなOSSライブラリを一つのアドレスで取得できるようになっています(「Maven JCenterリポジトリ Maven JCenter repository参照)。

This is a common reason why many projects prefer to store their libraries in their version control system. This approach is fully supported by Gradle. The libraries can be stored in a flat directory without any XML module descriptor files. Yet Gradle offers complete transitive dependency management. You can use either client module dependencies to express the dependency relations, or artifact dependencies in case a first level dependency has no transitive dependencies. People can check out such a project from your source code control system and have everything necessary to build it.

使用しているライブラリをバージョン管理システムに入れているプロジェクトがありますが、それはこのあたりが理由です。Gradleはこの方法も完全にサポートしています。ライブラリを、XML設定ファイルを一切使用せず、ただローカルディレクトリに入れておくことができるのです。また、その場合でも、Gradleは推移的な依存関係を完全に管理できます。クライアントモジュール依存関係を使って依存関係のグラフを表現したり、推移的な依存関係がない場合は、アーティファクトオンリー記法を使ったりできます。こうしたプロジェクトは、SVNからチェックアウトされた段階で、ビルドに必要なすべてのものがそろっていることになります。

If you are working with a distributed version control system like Git you probably don't want to use the version control system to store libraries as people check out the whole history. But even here the flexibility of Gradle can make your life easier. For example, you can use a shared flat directory without XML descriptors and yet you can have full transitive dependency management, as described above.

Gitのような分散バージョン管理システムを使っている場合は、リポジトリにライブラリを格納したくないかもしれません。ユーザーがリポジトリの履歴をすべてチェックアウトする必要があるからです。しかし、たとえこのような場合でも、Gradleの柔軟性は生活を楽にしてくれます。たとえば、XMLリポジトリなしの共有ディレクトリを使うこともできます。そして、この場合でも上記の方法で推移的な依存関係は完全に管理できるのです。

You could also have a mixed strategy. If your main concern is bad metadata in the POM file and maintaining custom XML descriptors, then Client Modules offer an alternative. However, you can still use Maven2 repo or your custom repository as a repository for jars only and still enjoy transitive dependency management. Or you can only provide client modules for POMs with bad metadata. For the jars and the correct POMs you still use the remote repository.

これらを複合させた戦略をとることもあります。POMファイルの不良メタデータをなんとかしたい、カスタムPOMを使いたいということであれば、クライアントモジュールが一つの選択肢になります。 もちろんjarの取得だけをMaven2リポジトリやカスタムリポジトリから行うこともできますし、推移的な依存関係もそのまま問題なく管理できます。また、不良メタデータを含むPOMのみをクライアントモジュールで置き換えることも可能です。その場合、jarと正しいPOM情報については、今まで通りリモートリポジトリから取得することになります。

51.10.1. 暗黙的な推移的依存関係 Implicit transitive dependencies

There is another way to deal with transitive dependencies without XML descriptor files. You can do this with Gradle, but we don't recommend it. We mention it for the sake of completeness and comparison with other build tools.

The trick is to use only artifact dependencies and group them in lists. This will directly express your first level dependencies and your transitive dependencies (see 「オプション属性 Optional attributes). The problem with this is that Gradle dependency management will see this as specifying all dependencies as first level dependencies. The dependency reports won't show your real dependency graph and the compile task uses all dependencies, not just the first level dependencies. All in all, your build is less maintainable and reliable than it could be when using client modules, and you don't gain anything.

そのトリックは、アーティファクトオンリー記法を使い、それらをリストでグループ化するというものです。 この方法でも、なにが直接の依存関係で、何が推移的な依存関係なのか、なんとか表現することはできました(「オプション属性 Optional attributesを参照してください)。 しかし、この方法の欠点は、Gradleの依存関係管理システムが、すべての依存関係を直接の依存関係として取り扱ってしまうことです。依存関係のレポートを出力させても正しい依存関係グラフは出てきませんし、compileタスクでも、直接的な依存関係だけでなく、すべての依存関係が使われてしまうことになります。クライアントモジュールを使った場合に比べると、大抵は保守性も信頼性も落ちてしまいますし、特にその分なにか利点があるわけでもありません。



[22] Gradle supports partial multiproject builds (see57章マルチプロジェクトのビルド). Gradleはマルチプロジェクトの部分ビルドをサポートしています(57章マルチプロジェクトのビルド参照)。

[24] At http://ant.apache.org/ivy/history/latest-milestone/concept.html you can learn more about ivy patterns. ivyパターンについてはhttp://ant.apache.org/ivy/history/latest-milestone/concept.htmlで詳細な情報を知ることができます。

[25] If you want to shield your project from the downtimes of Maven Central things get more complicated. You probably want to set-up a repository proxy for this. In an enterprise environment this is rather common. For an open source project it looks like overkill. Mavenセントラルのダウンからプロジェクトを防御したい場合は、もう少し複雑になります。 おそらく、そのためにリポジトリのプロキシをセットアップしたくなると思います。 エンタープライズ環境では珍しくないシチュエーションと言えますが、オープンソースプロジェクトの場合は、やりすぎのように思います。