torutkのブログ

ソフトウェア・エンジニアのブログ

Gradleでビルドする際に使用するライブラリをローカルに置く際の問題

2020-04-12追記あり

Android Studioで、外部のライブラリを使用するアプリケーションのプロジェクトを作成しようとしています。Android StuidoはビルドにデフォルトでGradleを使っており、外部のライブラリを使う場合はその設定をGradleの設定ファイルに記述します。

外部のライブラリの参照は、デフォルトではインターネット上のmavenリポジトリ(BintrayのJCenter Mavenリポジトリ)を使用します。また、定義を追加すれば他のmavenリポジトリやIvyリポジトリも使用できます。

Android Studioで新規作成したプロジェクトのbuild.gradleにデフォルトで記述されている外部リポジトリ参照(抜粋)

    repositories {
        jcenter()
    }

これは、http://jcenter.bintray.com を参照する設定

これらリポジトリは、単に外部のライブラリ(バイナリ)が置かれているだけではなく、バージョン情報やそのライブラリが依存している他のライブラリの情報を保持しているので、Gradleがライブラリの依存関係を解析してバージョンの整合性をチェックしたり必要とするライブラリを取得するといった作業の自動化が実現できます。

つまり、ソースコードの構成管理だけでなく、バイナリの構成管理が可能になります。

しかし、インターネット接続を規制*1している開発環境や、独自に作成したライブラリを使用したいときは、インターネット上のリポジトリを利用できないので別な手段でライブラリの定義をする必要があります。
また、Gradleはリポジトリをちょくちょくなめる傾向がmavenよりも大きく、必要なファイルをキャッシュにダウンロードしたからといってインターネット接続が不要になるわけではないようです。モバイル環境で開発作業をオフラインで実施する頻度が高いと制約を受けることになります。

開発環境(PC)に、あらかじめダウンロードしておいた外部のライブラリを配置し、それを参照するのが従来のやり方ですが、Gradleでその方法を調べるのに少し苦労しました。

まず、調べるとすぐに出てくる配置方法は、アプリケーション個々のプロジェクトのディレクトリ内に'libs'ディレクトリなどを設け、そこに外部ライブラリのjarファイルを置く方法です。
Android Studioでは、プロジェクトディレクトリ下のapp/build.gradle*2に次の記述があります。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    :
}

これは、ビルド(コンパイル)時に、プロジェクトディレクトリ下のapp/libsディレクトリの中にある*.jarにマッチするファイルをクラスライブラリとして使用する定義となります。なので、このディレクトリに外部ライブラリのjarファイルを配置するのがもっとも簡単な方法となります。ただし、プロジェクト毎に外部ライブラリのjarを置く必要があるので、複数プロジェクトを開発するときに重複が発生します。

次は、フラットディレクトリです。ローカルファイルシステム上のディレクトリをリポジトリとして使用するものです。

repositories {
    flatDir {
        dirs "libs", "alfa-libs"
    }
}

ただし、指定するパスはプロジェクトディレクトリからの相対パスとなります。
相対パスだけでなく、絶対パスの指定も可能です(2020-04-12追記)。ただし、絶対パスは開発者・環境によって異なるため(例:WindowsLinuxと開発者が異なるOS~異なるパス表記~のマシンを使用する場合などは特に)、プロパティを介在し、絶対パスを外部から与える(コマンドラインオプションや、ユーザーホームに置くgradle.propertiesなどにより)といった工夫が必要になります。

ここまでの調査結果では、Gradleを使ってPC上に外部ライブラリを一元的に配置し、それを使うプロジェクトから参照させる、という方法が見出せませんでした。
NetBeans(Ant)ではPC上に一元的に外部ライブラリを配置し、それをライブラリ設定で定義してアプリケーションのプロジェクトから参照することができましたが、Gradleではそれが難しいようです。

最後は、開発環境の中にインターネット上のリポジトリのミラーを立ててしまう方法です。
mavenリポジトリのミラーサーバーを開発環境内に用意すれば、外部ライブラリを使用する構成管理が可能になります。最近では、オープンソースリポジトリミラー機能を持つソフトウェアとしてSonatype NexusArtifactoryなどが登場しています。これらを使って開発環境の中にmavenリポジトリを作ってしまえば、インターネット接続の制約を気にせずに外部ライブラリを構成管理しつつ使用することが容易になります。

Sonatype Nexusは、2014年のJavaOne SFでセッションを聴講しました。
http://d.hatena.ne.jp/torutk/20140928/p1

Artifactoryは、2015年のJJUG CCC SpringでAndroid開発セッションの開発環境の構成に登場していました(Artifactory自体の解説はなかった)。
http://www.slideshare.net/s_kozake/android-android-sierjava

まとめ

昨今のアプリケーションプログラムは、オープンソースをはじめとするさまざまな外部ライブラリを利用して作成することが多くなりました。オープンソースの外部ライブラリは、独自のライフサイクルを持つので、どのバージョンを使用しているかを管理しておくことが重要です。それには、ライブラリをリポジトリ管理するのが望ましいです。

しかし、開発の状況によってはインターネット上のリポジトリを常用することができません。

そのときは、開発環境内に、Sonatype NexusArtifactoryなどのツールを使ってリポジトリを用意するのがよさそうです。

*1:インターネットへの接続が禁止されている環境だけではなく、ファイアウォールを介してインターネットへ接続し、そのファイアウォールでさまざまな検閲をしている環境ではGradleからリポジトリへの通信が遅延されたり、阻害されてその原因の調査と対策が難しいことがあります。

*2:プロジェクトディレクトリ直下にもbuild.gradleがあるので最初かなり戸惑いました