看板 java 關於我們 聯絡資訊
※ 引述《Neisseria (Neisseria)》之銘言: : 小弟用 gradle 想包一些 groovy 命令稿和靜態檔案 : build.gradle 如網址:https://pastebin.com/EUGbHCmg : 目前可以順利產生 JAR,該 JAR 也可以順利執行 : 不過 靜態檔案會跑到其他的資料夾 : 結構大致如下: : ├── classes : │ └── main : │ └── SomeClass.class : ├── libs : │ └── SomeClass-1.0.jar : ├── resources : │ └── main : │ └── static-file : └── tmp : ├── compileGroovy : │ └── groovy-java-stubs : └── uberjar : └── MANIFEST.MF : 我覺得我可能是誤會了 : static-file 不會跑進 JAR 裡 : 不過我不確定 所以 po 上來請各位大大解惑 : 感恩 我建了一些 sample class 與靜態檔: qty:t qrtt1$ tree . ├── build │ ├── classes │ │ └── main │ │ └── Hello.class │ ├── libs │ │ └── t-1.0.jar │ ├── resources │ │ └── main │ │ └── foo.txt │ └── tmp │ ├── compileGroovy │ │ └── groovy-java-stubs │ ├── jar │ │ └── MANIFEST.MF │ └── uberjar │ └── MANIFEST.MF ├── build.gradle └── src ├── groovy │ └── Hello.groovy └── resources └── foo.txt 14 directories, 8 files 摘錄會用到的部分如下: sourceSets { main { groovy { srcDir 'src/groovy' } resources { srcDir 'src/resources' } } } task uberjar(type: Jar, dependsOn:[':compileJava', ':compileGroovy', ':processResources']) { from files(sourceSets.main.output.classesDir) from configurations.runtime.asFileTree.files.collect { zipTree(it) } manifest { attributes 'Main-Class': 'SomeClass' } } 若是懷疑檔案沒進去,那就檢查一下源頭吧! 很明顯地黃字部分是源頭,綠字部分是其它 library 檔 那麼就來研究黃子部分的 code 吧。 沒頭緒!沒關係!gradle script 就是 groovy script 把它的類別印出來研究一下,在 build.gradle 最後面加上: println sourceSets.main.output.class println sourceSets.main.output.classesDir.class 執行一下: # gradle -q class org.gradle.api.internal.tasks.DefaultSourceSetOutput_Decorated class java.io.File classesDir 是個 File 物件,依它的命名猜是個錄目 DefaultSourceSetOutput 就是某個 gradle 的物件,先不知道它做什用的。 先不理它,來研究一下 classesDir 目錄內有什麼: 再加印一下它的內容: println "files in classesDir" sourceSets.main.output.classesDir.eachFile { println it } /Users/qrtt1/t/build/classes/main/Hello.class 你發會現它沒有 靜態檔 只有 .class。 看來得換一條路來查了,如果在 sourceSets.main.output.classesDir 沒有我們期待的檔,那在它的上一層會不會有呢? 不確定要怎麼查但它是個 groovy object 先用 each 看看運氣: sourceSets.main.output.each { println it } /Users/qrtt1/t/build/classes/main /Users/qrtt1/t/build/resources/main 你會發現它印出了二個目錄,依剛剛變數的名字來看 sourceSets.main.output.classesDir 就會是 /Users/qrtt1/t/build/classes/main 那麼代表目錄 /Users/qrtt1/t/build/resources/main 的變數叫什麼? 沒頭緒沒關係,找一下 property 有 Dir 的看看。 加 build.gradle 印一下: println sourceSets.main.output.properties.grep { it.key.contains("Dir") } 只要沒有被 MOP 動手腳,groovy object 都有 properties 只要是 groovy object 就有基 grep 能用囉 qty:t qrtt1$ gradle [classesDir=/Users/qrtt1/t/build/classes/main, resourcesDir=/Users/qrtt1/t/build/resources/main] ======================================================== 以上是簡單的野外求生過程, 不過先前其實有查到是哪個類別了,直接看 source code 比較快 https://github.com/gradle/gradle/blob/master/subprojects/ plugins/src/main/groovy/ org/gradle/api/internal/tasks/DefaultSourceSetOutput.java 縮:http://bit.ly/1SPm1Ke 所以,由上述的歷程可以知道你根本缺少了 resources 檔的位置。 依直覺可以這麼寫: task uberjar(type: Jar, dependsOn:[':compileJava', ':compileGroovy', ':processResources']) { from files(sourceSets.main.output.classesDir) from files(sourceSets.main.output.resourcesDir) from configurations.runtime.asFileTree.files.collect { zipTree(it) } manifest { attributes 'Main-Class': 'SomeClass' } } 你就得到了有 resources file 的 uberjar qty:t qrtt1$ unzip -l build/libs/t-1.0.jar |grep foo 0 04-15-16 18:01 foo.txt 不過依手冊與 source code 的明示、暗示, 它是一個 Composite Pattern public class DefaultSourceSetOutput extends CompositeFileCollection implements SourceSetOutput { } 通俗一點的叫『樹』,簡單地說應該要有獲得 parent 就得到它包含物的效果 你可以改寫成: from files(sourceSets.main.output) 再加上 CopySpec 手冊說明 http://bit.ly/1VtZKbl , from (...) 它會自動呼叫 project.files,所以又能再簡化成: from sourceSets.main.output 於是開心地打完收工,謝謝收看。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 211.21.157.223 ※ 文章網址: https://www.ptt.cc/bbs/java/M.1460717223.A.650.html
Neisseria: 感謝大大回得那麼認真,我會再試試看 04/15 22:32