2016-05-10 30 views
2

我想建立一個大型的項目,我被告知gradle是做到這一點的方法。規範設置的Gradle構建

我對Gradle很困惑,整個系統看起來像是很多魔術,揮手和知識,我不想閱讀gradle指南的所有60章。

我會用以下組件來結束:

  • protobuf的文件定義了一堆的消息
  • Java庫1和測試(取決於ProtoBufs)
  • Java庫2測試(依賴於Java庫1)
  • Java應用程序(取決於Java庫2)
  • Android應用程序(取決於Java庫2)
  • 的iOS應用
  • 複製所有的Java的東西,但爲Python,C++和Objective-C)

我希望能夠建立和測試於一體的大型鏡頭的一切。所以通常我會建立這樣的樹:

project/ proto/ 
     lib1/ java/ src/ 
         test/ 
       python/ src/ 
         test/ 
       ... 
     lib2/ java/ src/ 
         test/ 
       python/ src/ 
         test/ 
       ... 
     app1/ java/ src/ 
         test/ 
       python/ src/ 
         test/ 
       ... 
     app2/ java/ src/ 
         test/ 
       python/ src/ 
         test/ 
       ... 
     android/ src/ 
        test/ 
     iOS/ src/ 
       test/ 

我得到修建從gradle這個的iOS可能是不可能的,所以我很高興能忽略它。

這是一個合適的結構使用?我如何構建和放置我的gradle.build文件,以便其他團隊可以正確使用這些庫?我如何確保我的依賴關係緊密,以便庫僅包含他們需要包含的最小集合?

Gradle構建文件似乎留下了一堆可能未被使用的任務。我只是試圖忽略這些?

回答

0

我住的結構是基於將類似的項目分成子項目結構。

project/client/core/common-android 
project/client/core/features-android 
project/client/core/ui-android 
project/client/app/client-android 
project/server/admin 
project/server/base 
project/server/util 
project/server/api-deployment 
project/bundles/bundle1 
project/bundles/bundle2 
project/bundles/bundle3 
project/bundles/bundle4 

該結構使得使用子項目更直觀,然後平面目錄結構。現在我們可以將配置應用到類似的子項目。我的最後一個項目結構看起來像這樣

------------------------------------------------------------ 
Root project 
------------------------------------------------------------ 

Root project 'platform' 
+--- Project ':client' - Client: Android core projects 
| +--- Project ':client:common-android' - Client: Common library for Android aar 
| +--- Project ':client:features-android' - Client: Features library for Android aar 
| +--- Project ':client:ui-android' - Client: UI library for Android aar 
| +--- Project ':client:app-android' - Client: Apk client Android apk 
+--- Project ':bundles' - bundles: OSGi bundles container project 
| +--- Project ':bundles:bundle1' - bundles: OSGi bundle jar 
| +--- Project ':bundles:bundle2' - bundles: OSGi bundle jar 
| +--- Project ':bundles:bundle3' - bundles: OSGi bundle jar 
| +--- Project ':bundles:bundle4' - bundles: OSGi bundle jar 
\--- Project ':server' - Server: Coriolis root project 
    +--- Project ':server:admin' - Server: admin jar 
    +--- Project ':server:base' - Server: jar base 
    +--- Project ':server:apiDeployment' - Server: platform deployment war 
    \--- Project ':server:util' - Server: utils jar 

因爲我們不希望父項目,儘量少對自己的孩子,我們可以讓通過settings.gradle

配置過程中的每個項目組配置本身知道settings.gradle:

rootProject.name = 'platform' 

Map<String, String> projectProperties = startParameter.getProjectProperties() 
projectProperties.put('platform', true.toString()) 

// TODO: Make project imports smarter by removing hardcoding of paths 

def subprojects = settingsDir.listFiles(new FileFilter() { 
    @Override 
    boolean accept(File file) { 
     return file.isDirectory() && (file.name == 'client' || file.name == 'server') 
    } 
}) 

for (File file : subprojects) { 
    println "Found subproject directory: $file.absolutePath" 
    switch (file.name) { 
     case 'client': 
      def androidHome = 'ANDROID_HOME' 
      // any non-null value will add android modules to the build. 
      // Assumption is only a valid SDK location will be set. 
      if (System.getenv(androidHome)) { 
       def clientFile = new File("$file.absolutePath/core/childProjectSettings.gradle") 
       if (clientFile.exists()) { 
        println "Adding android client" 
        include ':client' 
        project(":client").projectDir = clientFile.parentFile 
        apply from: clientFile.absolutePath 
       } 
      } else { 
       println "WARNING: Environment variable {$androidHome} not set. Not adding Android modules as they are " + 
         "impossible to build without the Android SDK being installed. To install the Android SDK " + 
         "please see: http://developer.android.com/sdk/installing/index.html" 
      } 
      break 
     case 'server': 
      def serverFile = new File("$file.absolutePath/server/childProjectSettings.gradle") 
      if (serverFile.exists()) { 
       println "Adding server" 
       include ':server' 
       project(':server').projectDir = serverFile.parentFile 
       apply from: serverFile.absolutePath 
      } 

      def bundlesFile = new File("$file.absolutePath/bundles/childProjectSettings.gradle") 
      if (bundlesFile.exists() && !projectProperties.containsKey('noBundles')) { 
       println "Adding osgi bundles" 
       include ':bundles' 
       project(':bundles').projectDir = bundlesFile.parentFile 
       apply from: bundlesFile.absolutePath 
      } 
      break 
     default: 
      println "Unknown subproject found: $file.absolutePath" 
    } 
} 

磁盤上存在的現在只有子項目將包括在內,我們可以去除剩餘的硬編碼更加動態的例子,但這個更簡單。然後我們爲每個項目分組(客戶端,服務器,軟件包)創建一個文件(在本例中)childProjectSettings.gradle。您的childProjectSettings.gradle應該以每次添加新子項目時不需要更新的方式來指定它的子項目。

childProjectSettings。gradle這個:

File moduleSettingsDir = new File("$settingsDir.absolutePath/server", "bundles") 

println "Bundles sees settings dir as: $moduleSettingsDir.absolutePath" 

def bundleDirectories = moduleSettingsDir.listFiles(new FileFilter() { 
    @Override 
    boolean accept(File pathname) { 
     return pathname.isDirectory() 
    } 
}) 

// get a reference to this project's descriptor so we can add subprojects 
ProjectDescriptor bundles = project(':bundles') 

bundleDirectories.each { File bundleDir -> 
    if (new File(bundleDir, "build.gradle").exists()) { 
     // normalize project names (blah-blah -> blahBlah) 
     def bundleName = bundleDir.name 
     if (bundleName.contains("-")) { 
      def names = bundleDir.name.split("-") 
      bundleName = names[0] + names[1].capitalize() 
     } 

     // include a subproject in the build 
     include ":bundles:$bundleName" 
     // default location will be wrong lets update the project's directory 
     project(":bundles:$bundleName").projectDir = bundleDir 
     // add the project as a subproject giving us better grouping 
     bundles.children.add(project(":bundles:$bundleName")) 
    } 
} 

project(':bundles').children.each { 
    println "Parent {$it.parent} found child {$it} in path {$it.path} using buildScript {$it.buildFile $it.path}" 
} 

搖籃建立文件似乎留下了一堆散落周圍可能未使用的任務。我只是試圖忽略這些?

這不是創建任務的構建文件,它是在build.gradle文件中應用的插件。爲儘可能保證任務的緊湊性,只能在build.gradle中聲明它實際使用的插件。任務不是從依賴項目繼承的,但聲明的依賴項是從依賴項目繼承的。

*有一個重要的注意這裏所有的依賴是transitive默認情況下,因此,如果ui取決於core其聲明gson依賴然後ui將默認有gson在它的類路徑中。

對於你關於源文件夾的問題,更多的gradle結構可能看起來更像下面。如果您的應用程序組爲lib1:java|lib1:python|lib2:java|lib2:python|app1:java|app1:python|app2:java|app2:python,每個論壇都將是其包含組的子項目。

然後lib1項目包含兩個子項目lib1:javalib1:python,每個子項都使用自己的build.gradle文件中的插件進行編譯。如果需要,通用代碼可以放在buildSrc的自定義插件中。

project/ proto/ 
     lib1/ java/ src/main/java/ 
         src/main/javaTest/ 
       python/ src/main/python/ 
         src/main/pythonTest/ 
       ... 
     lib2/ java/ src/main/java/ 
         src/main/javaTest/ 
       python/ src/main/python/ 
         src/main/pythonTest/ 
       ... 
     app1/ java/ src/main/java/ 
         src/main/javaTest/ 
       python/ src/main/python/ 
         src/main/pythonTest/ 
       ... 
     app2/ java/ src/main/java/ 
         src/main/javaTest/ 
       python/ src/main/python/ 
         src/main/pythonTest/ 
       ... 
     android/ src/ 
        test/ 
     iOS/ src/ 
       test/