2016-11-10 72 views
1

我想讓Gradle根據我是爲桌面還是爲Android構建,在我的多項目構建中選擇不同的依賴關係。我有一個共同的子項目(一個庫),我試圖重用。但是,我無法讓Gradle正確切換依賴配置。根據平臺切換Gradle中的依賴關係

我的主要settings.gradle簡單地包括所有的依賴:

// /settings.gradle 
rootProject.name = 'myProject' 

include 'androidUI' 
include 'reusableLibrary' 
include 'desktopUI' 

現在無論androidUIdesktopUI指定reusableLibrary作爲一個依賴:

// /androidUI/build.gradle and /desktopUI/build.gradle 
apply plugin: 'java' 
dependencies { 
    compile project(path: ':reusableLibrary', configuration: 'desktop') 
} 

reusableLibrary本身規定了兩種配置,因爲它的依賴是不同的是否它建立在桌面或Android上:

// /reusableLibrary/build.gradle 
apply plugin: 'java' 
configurations { 
    desktop { 
     extendsFrom compile 
    } 
    android { 
     extendsFrom compile 
    } 
} 

dependencies { 
    // Just examples, the real list is longer. 
    // The point is that h2database is only included on desktop, 
    // and ormlite is only included on Android. 
    android 'com.j256.ormlite:ormlite-jdbc:5.0' 
    desktop 'com.h2database:h2:1.4.192' 
} 

This looks對我而言很好。但是,當我編譯要麼desktopUIandroidUI,我可以看到,雖然依賴性被包含在我想要的方式classpath中的reusableLibrary,實際JAR 通過reusableLibrary本身提供的是包括在內。這當然會導致構建失敗。我懷疑我沒有正確設置reusableLibrary;我不清楚configurations {}塊的功能。

爲什麼reusableLibrary中的編譯項目不包含在UI項目的類路徑中?以這種方式包含特定於平臺的依賴關係的規範方法是什麼?

回答

1

原始配置非常接近正確。關鍵是要了解從Gradle Java plugin's documentation這個依賴圖:「依賴關係列表」

Java dependency configurations

這是Java插件的各種依賴關係配置的可視化,這是搖籃,爲ESE當您將compile行添加到dependencies {...}塊時,即將Dependency元素添加到compile相關性列表。

default依賴配置是特殊的;它是包含在compile project("path")行中的一個,除非選擇與configuration:參數不同的一個。這意味着當您構建庫時,runtime依賴關係列表(其中包含來自庫本身的編譯的jar本身)被添加到客戶端項目的類路徑中。

原始配置會在此圖中創建兩個新節點desktopandroid,並使用extendsFrom將它們耦合到compile。他們沒有以其他方式連接到圖表!現在原始配置的問題是顯而易見的:通過將上游項目切換到其中任一個,它是缺少來自runtime的編譯代碼。這解釋了類路徑的省略。

該解決方案比僅針對desktopandroidruntime稍微微妙一些。爲了確保在添加測試時所有內容都能正確解耦,我們需要一個額外的依賴配置層來間接保留testCompile,具體取決於runtime。此外,圖書館的源代碼本身可能需要在其類路徑上進行類型檢查;我們可以使用compileOnly。最終解決方案如下所示:

configurations { 
    desktopCompile 
    androidCompile 

    compileOnly.extendsFrom desktopCompile 
    testCompile.extendsFrom desktopCompile // Assuming tests run on the desktop 

    desktop { 
     extendsFrom desktopCompile 
     extendsFrom runtime 
    } 
    android { 
     extendsFrom androidCompile 
     extendsFrom runtime 
    } 
} 

dependencies { 
    androidCompile "some.android:dependency" 
    desktopCompile "other.desktop:dependency" 
}