50

私は次のプロジェクト構造を持っています

-->Starnderd Location
        -->Project1 
           -->settings.gradle 
           -->build.gradle
           -->Subproject11
              -->build.gradle
           -->Subproject12
              -->build.gradle
        -->Project2 
           -->settings.gradle 
           -->build.gradle
           -->Subproject21
              -->build.gradle
           -->Subproject22
              -->build.gradle
        -->build.gradle
        -->settings.gradle

上記のプロジェクト構造の考え方は、サブプロジェクトを含む複数のプロジェクトがあり、各プロジェクトが他のプロジェクトに依存する可能性があるということです。また、プロジェクト内のサブプロジェクトは、同じプロジェクト内の他のサブプロジェクトへの依存関係を持つことができます。プロジェクトは、ルートのsettings.gradleで指定されます。また、各プロジェクト内のsettings.gradleは、その特定のプロジェクトのサブプロジェクトを示します。

ルートのsettings.gradleは次のようになります

include 'Project1',
         'Project2'

Project1のsettings.gradleは次のようになります

include 'SubProject11'
         'SubProject12'

他の依存関係の順序は、それぞれのbuild.gradleファイルで定義されています。ルートの場所(Standarの場所)内でgradle clean build installを実行すると、プロジェクトレベルのsettings.gradleファイルの構成が使用されないようです。

私がここで間違っていることは何ですか?

4

6 に答える 6

26

この問題を比較的きれいな方法で解決できました。改善は大歓迎です!

Gradle はそのままでは複数のスクリプトをサポートしていませんsettings.gradleが、個別のサブプロジェクトをそれぞれ独自のsettings.gradleファイルで作成することは可能です。マルチプロジェクト B に依存するマルチプロジェクト A があり、それぞれに独自のサブプロジェクトがあるとします。ディレクトリ構造は次のようになります。

A
- settings.gradle
- foo
- faz
\ B
  - settings.gradle
  - bar
  - bap

箱から出してすぐに、Gradle はA/settings.gradle次のようになることを期待しています。

include ':foo', ':faz', 'B:bar', 'B:bap'

これに関する問題は、B が新しいプロジェクトを追加するたびにA/settings.gradle、新しいプロジェクトが B だけで使用されている場合でも、変更する必要があることです。この状況を回避するには、冗長な宣言を追加する代わりにapply B/settings.gradle、次のようにすることができます。A/settings.gradle

apply from: 'B/settings.gradle'
include ':foo', ':faz'

projectDirこれを試すと、間違った:barとを生成するため、Gradle が失敗することがわかります:bap。B のインクルードは、そのプロジェクト ルートから Gradle が呼び出されたときにsettingsDirたまたま相対的であると誤って想定しています。A/これを修正するには、次のような別のスクリプトを追加できますB/settings-parent.gradle(正確な名前は重要ではありません)。

apply from: 'settings.gradle'

def updateProjectPaths(Set<ProjectDescriptor> projects) {
    projects.each { ProjectDescriptor project ->
        String relativeProjectPath = project.projectDir.path.replace(settingsDir.path, "")
        project.projectDir = new File("B/$relativeProjectPath")
        // Recursively update paths for all children
        updateProjectPaths(project.children)
    }
}

updateProjectPaths(rootProject.children)

これによりsettingsDir.path、パスが取り除かれ、接頭辞が付けられB/ます。settings[-parent].gradleこれは、各レイヤー自体をパスに追加することで、ファイルの複数のレイヤーに拡張できます。次に、このスクリプトを に適用しますA/settings.gradle

apply from: 'B/settings-parent.gradle'
include ':foo', ':faz'

このスキームでは、新しい B プロジェクトが不必要に壊れることはA/settings.gradleなく、B サブプロジェクトを明示的に参照しなくてもすべてのプロジェクトを使用できます。たとえば、':foo'を使用する場合は'B:bap'、次のように宣言するだけです。

compile project(':bap')
于 2015-04-16T02:57:47.973 に答える
11

現在、Gradle はsettings.gradleビルドごとに 1 つのファイルのみをサポートしています。これは将来変更される可能性があります。

于 2012-08-28T12:28:36.247 に答える
5

私もこれを調べましたが、あなたはそれを行うことができますが、それは非常に醜いです! これがうまくいく理由は、ほとんどの場合、最上位レベルから構築したいだけだからです。

それがまったく役立つ場合は、最上位の settings.gradle ファイルがすべてのプロジェクトサブプロジェクトを直接適切に参照するようにする必要があります。これを最初に機能させます。

次に、Project1 と Project2 (など) を互いに独立してビルドできる場合は、そのプロジェクトのローカル settings.gradle ファイルを作成できます。上で述べたように、これは通常行うことではないため、このファイルを settings.project1 と呼びます。このファイルを使用する場合は、settings.gradle にコピーします。私は醜いことを知っています。

しかし、実際にはさらに悪化します:) このsettings.gradleファイルを配置すると、Project1からビルドすると、おそらく定義が必要なトップレベルのbuild.gradleファイルが表示されなくなります。これを呼び出すには、すべてのプロジェクト レベルの build.gradle ファイルに次のようなものを追加する必要があります。

if (project.hasProperty('local')) {
    apply from: '../build.gradle'
}

その後、次のようにビルドを実行できます: gradle -Plocal build

醜いですが、必要な場合は、少なくとも機能します。そして、完全な開示のために、数週間前にこれを導入しましたが、開発者は誰もそれを必要としたり、使用したりしていません. 使用しない場合は、おそらくあと 2 週間で削除されます。

サブプロジェクト自体からビルドする場合、そのサブプロジェクト (およびすべての依存プロジェクト) のみがビルドされることに注意してください (ただし、すべての gradle スクリプトはコンパイル/評価されます)。

于 2012-08-28T13:45:33.270 に答える
2

以前の回答に基づいて、これが私が思いついたものです。

interface Includer {
  def include(String... args)
}

def applyFrom(String folder) {
  apply from: folder + '/settings.gradle'
  def includer = [
    include: { args ->
          args.each {
            project(it.startsWith(':') ? it : ':' + it).projectDir =
                new File(rootDir, folder + "/" + (it.startsWith(':') ? it.substring(1) : it).replace(':', '/'))
          }
    }] as Includer

  apply from: folder + '/settings.gradle', to: includer
}

applyFrom('A')
applyFrom('B')

利点は、重複しないことです。

于 2015-10-28T16:52:16.883 に答える