2021年6月22日 星期二

使用 gradle 管理並編譯 kotlin 程式碼

1. 首先上 gradle  官網: https://gradle.org/releases 只要下載 binary-only 壓縮檔就可以了

2. 打開終端機, 把下載回來的檔案(gradle-7.1-bin.zip)解壓縮, 再將執行檔所在目錄加進 PATH 內, gradle 就安裝完成:

     cd Downloads  &&  unzip gradle-7.1-bin.zip

     PATH=$PATH:/home/mint/Downloads/gradle-7.1/bin

3.建個目錄儲存各種專案, 主程式目錄名稱, 同時也會被當成是專案名稱, 例如下述 example 次專案, 進入目錄內執行 gradle init 將會再當地目錄初始化成新專案, 接著跳出選項, 要依照畫面適當選取, 最後執行 gradle run 就能啟動樣版程式

     mkdir  Project  &&  cd Project

     mkdir  example  &&  cd example

     gradle init

     gradle run

觀察它所產生的檔案, 我打算利用 make 語法, 編寫一個簡短的 Makefile 方便以後初始化新專案,而不用每次初始化都要用選的:
# /home/mint/Project/Makefile
shellpwd  = $(shell pwd)
project  = `basename $(shellpwd)`
gradlebin  = /home/mint/Downloads/gradle-7.1/bin/gradle
templateKts  = /home/mint/Project/template.gradle.kts
templateApp  = /home/mint/Project/template.kt
appDir  = app
kotlinDir  = src/main/kotlin
targetDir  = $(appDir)/$(kotlinDir)
AppKt  = $(targetDir)/App.kt
settingsKts  = settings.gradle.kts
setProject  = "rootProject.name=(\"$(project)\")"
setInclude = "include(\"$(appDir)\")"
buildKts = $(appDir)/build.gradle.kts
ktsSetApp  = "application { mainClass.set(\"$(project).AppKt\") }"
ktsSetSrc = "sourceSets.main { java.srcDirs(\"$(kotlinDir)\") }"

name:
    @echo this is a kotlin project: $(project)

$(targetDir): $(appDir)/src/main
    @[ -d $@ ]|| mkdir $@

$(appDir)/src/main: $(appDir)/src
    @[ -d $@ ] || mkdir $@

$(appDir)/src: $(appDir)
    @[ -d $@ ] || mkdir $@

$(appDir):
    @[ -d $@ ] || mkdir $@

init: $(settingsKts) $(AppKt)
    @echo ... $(project) is ready

$(settingsKts):
    @if [ -f $@ ]; then echo .; else echo $(setProject)      > $@ && echo $(setInclude) >> $@; fi

$(AppKt): $(targetDir) $(buildKts)
    @if [ -f $@ ]; then echo .; else echo package $(project) > $@ && cat $(templateApp) >> $@; fi

$(buildKts):
    @if [ -f $@ ]; then echo .; else cp $(templateKts) $@ && echo $(ktsSetSrc) >> $@ && echo $(ktsSetApp) >> $@ ;fi
   
run:
    $(gradlebin)  run  -q  --args='arg1 arg2 arg3 ...'

build:
    $(gradlebin) build --offline

clean:
    rm -rf  build  $(appDir)/build  .gradle

再寫一個 /home/mint/Project/template.gradle.kts 樣版檔案, 用來產生 build.gradle.kts:

// template.gradle.kts
plugins {
    kotlin("jvm") version "1.5.10"
    application
}
repositories { mavenCentral() }
dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0") }

以及另一個  /home/mint/Project/template.kt 樣版範例, 用來產生 kotline 的程式碼:

// template.kt
import kotlinx.coroutines.*
import kotlin.coroutines.*
fun main() {
    runBlocking{
        launch {
            println("Hello")
        }
        launch {
            println("world")
        }
        launch {
            println("you are welcome")
        }
    }
}

將上述 3 個檔案各自存檔後, 在 Makefile 所在目錄內執行 make init, 或是使用參數 -f 指定 Makefile 位置, 上述 make init 用來先產生 settings.grtadle.kts, app/build.gradle.kts, 及 app/src/main/kotlin/App.kt 等範例代碼, 這樣 gradle run 就能編譯並且執行程式:

       make   init   -f   /home/mint/Project/Makefile

      gradle  run

不用寫程式, 就能讓上面的樣版程式跑起來, 夠神奇吧! 實際上是 gradle 先根據 build.gradle.kts 內容,先上網路倉庫(repositories), 找尋插件(plugins)將 kotlin 編譯程式  kotlin("jvm") version "1.5.10" 以及各種需要的相關(dependencies)程式庫,下載後存入硬碟, 再呼叫 kotlin 去編譯成 Java 代碼(byte code), 最後在 J(ava)V(irtual)M(achine 內執行程式. 一切全自動完成, 這就是 gradle 厲害的地方.

ps.

1. gradle 缺點是網路一定要通暢才能運作, 主要是 gradle daemon 要先跑起來.雖然可以用 gradle --offline build 離線編譯程式, 但沒了網路, 例如用 iptables 先把網路的輸出通道關閉:

    sudo  iptables  -A  OUTPUT  -m  owner  --gid-owner  mint  -j  REJECT

    gradle  --offline  build

他就無法編譯了?  這參數 --offline 目的就真的有點奇怪, 似乎名不正言不順.

 2. 如果用複製/貼上面的 Makefile 內容, 無法讓 make 運作, 可能是縮排(tab)的問題, 可以用文字編輯程式稍微修改, 因為 make 規定所有標的物的執行代碼(冒號: 下一行)必須要先縮排(tab)才能運作, 否則會出現錯誤訊息.

沒有留言:

張貼留言

使用 pcie 轉接器連接 nvme SSD

之前 AM4 主機板使用 pcie ssd, 但主機板故障了沒辦法上網, 只好翻出以前買的 FM2 舊主機板, 想辦法讓老主機復活, 但舊主機板沒有 nvme 的界面, 因此上網買了 pcie 轉接器用來連接 nvme ssd, 遺憾的是 grub2 bootloader 無法識...