build.gradle.kts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import org.jetbrains.compose.desktop.application.dsl.TargetFormat
  2. import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
  3. import java.io.FileOutputStream
  4. import java.io.IOException
  5. import org.apache.commons.compress.archivers.sevenz.SevenZFile
  6. import java.nio.file.Files
  7. plugins {
  8. kotlin("jvm")
  9. id("org.jetbrains.compose")
  10. kotlin("plugin.serialization") version "1.8.0"
  11. id("com.github.gmazzo.buildconfig") version "5.3.5"
  12. }
  13. group = "com.movcontext"
  14. version = "2.6.1"
  15. buildConfig {
  16. buildConfigField("APP_NAME", provider { "幕境" })
  17. buildConfigField("APP_VERSION", provider { "v${project.version}" })
  18. }
  19. repositories {
  20. google()
  21. mavenCentral()
  22. mavenLocal()
  23. maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
  24. }
  25. dependencies {
  26. implementation(compose.desktop.currentOs)
  27. implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
  28. implementation("org.jetbrains.compose.material3:material3:1.0.1")
  29. implementation ("org.jetbrains.compose.material:material-icons-extended:1.0.1")
  30. implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
  31. implementation("io.github.microutils:kotlin-logging:2.1.21")
  32. implementation("uk.co.caprica:vlcj:4.8.2")
  33. implementation("com.formdev:flatlaf:3.1")
  34. implementation("com.formdev:flatlaf-extras:2.6")
  35. implementation("org.apache.opennlp:opennlp-tools:1.9.4")
  36. implementation("org.apache.pdfbox:pdfbox:2.0.24")
  37. implementation(files("lib/ebml-reader-0.1.1.jar"))
  38. implementation(files("lib/subtitleConvert-1.0.3.jar"))
  39. implementation(files("lib/jacob-1.20.jar"))
  40. implementation("org.apache.maven:maven-artifact:3.8.6")
  41. implementation("org.burnoutcrew.composereorderable:reorderable:0.9.2")
  42. implementation("com.github.albfernandez:juniversalchardet:2.4.0")
  43. implementation("com.darkrockstudios:mpfilepicker:2.0.2")
  44. implementation("org.apache.poi:poi:5.3.0")
  45. implementation("org.apache.poi:poi-ooxml:5.3.0")
  46. implementation("org.xerial:sqlite-jdbc:3.44.1.0")
  47. implementation ("io.ktor:ktor-client-core:2.3.11")
  48. implementation ("io.ktor:ktor-client-cio:2.3.11")
  49. implementation ("net.java.dev.jna:jna:5.14.0")
  50. implementation ("net.java.dev.jna:jna-platform:5.14.0")
  51. implementation ("ch.qos.logback:logback-classic:1.4.14")
  52. implementation("net.bramp.ffmpeg:ffmpeg:0.8.0")
  53. testImplementation(compose.desktop.uiTestJUnit4)
  54. testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0")
  55. testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
  56. testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
  57. }
  58. buildscript {
  59. repositories {
  60. mavenCentral()
  61. }
  62. dependencies {
  63. classpath("org.apache.commons:commons-compress:1.26.0")
  64. classpath("org.tukaani:xz:1.10")
  65. }
  66. }
  67. tasks.withType<KotlinCompile>().configureEach {
  68. kotlinOptions {
  69. kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
  70. }
  71. }
  72. /**
  73. * `src/main/resources` 文件夹里的文件会被打包到 MovContext.jar 里面,然后通过 getResource 访问,
  74. * 只读文件可以放在 `src/main/resources` 文件夹里面,需要修改的文件不能放在这个文件夹里面
  75. */
  76. compose.desktop {
  77. application {
  78. mainClass = "MainKt"
  79. jvmArgs += listOf("-client")
  80. jvmArgs += listOf("-Dfile.encoding=UTF-8")
  81. jvmArgs += listOf("-Dstdout.encoding=UTF-8")
  82. jvmArgs += listOf("-Dstderr.encoding=UTF-8")
  83. jvmArgs += listOf("-Dsun.stdout.encoding=UTF-8")
  84. jvmArgs += listOf("-Dapple.awt.application.appearance=system")
  85. nativeDistributions {
  86. targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
  87. packageName = "幕境"
  88. packageVersion = version.toString()
  89. modules("java.compiler","java.instrument","java.management","java.prefs", "java.security.jgss","java.sql", "jdk.unsupported","java.xml.crypto","jdk.accessibility", "java.naming" )
  90. appResourcesRootDir.set(project.layout.projectDirectory.dir("resources"))
  91. copyright = "Copyright 2023 Shimin Tang. All rights reserved."
  92. vendor = "深圳市龙华区幕境网络工作室"
  93. licenseFile.set(project.file("LICENSE"))
  94. windows{
  95. // console = true
  96. dirChooser = true
  97. menuGroup = "幕境"
  98. iconFile.set(project.file("src/main/resources/logo/logo.ico"))
  99. }
  100. macOS{
  101. iconFile.set(project.file("src/main/resources/logo/logo.icns"))
  102. }
  103. linux {
  104. iconFile.set(project.file("src/main/resources/logo/logo.png"))
  105. }
  106. }
  107. }
  108. }
  109. tasks.withType(JavaCompile::class.java) {
  110. options.encoding = "UTF-8"
  111. }
  112. // 第一次编译之前要解压缩词典文件
  113. tasks.named("compileKotlin") {
  114. doFirst{
  115. val dictFile = layout.projectDirectory.dir("resources/common/dictionary/ecdict.db").asFile
  116. if (!dictFile.exists()) {
  117. println("解压缩词典文件")
  118. val input = layout.projectDirectory.dir("dict/ecdict.7z").asFile
  119. val destination = layout.projectDirectory.dir("resources/common/dictionary").asFile
  120. decompressDict(input, destination)
  121. }
  122. }
  123. }
  124. tasks.named<Test>("test") {
  125. description = "Runs unit tests."
  126. group = "verification"
  127. testClassesDirs = sourceSets["test"].output.classesDirs
  128. classpath = sourceSets["test"].runtimeClasspath
  129. exclude("**/ui/**")
  130. }
  131. tasks.register<Test>("uiTest") {
  132. description = "Runs UI tests."
  133. group = "verification"
  134. testClassesDirs = sourceSets["test"].output.classesDirs
  135. classpath = sourceSets["test"].runtimeClasspath
  136. include("**/ui/**")
  137. }
  138. project.afterEvaluate {
  139. val os = System.getProperty("os.name", "generic").lowercase()
  140. if(os.indexOf("windows") >= 0){
  141. tasks.named("prepareAppResources") {
  142. doFirst {
  143. val pluginsCache = layout.projectDirectory.dir("resources/windows/VLC/plugins/plugins.dat").asFile
  144. if(pluginsCache.exists()){
  145. println("Delete the VLC plugin cache produced after launching the program from Main.kt")
  146. pluginsCache.delete()
  147. }
  148. }
  149. }
  150. tasks.named("runDistributable") {
  151. doFirst {
  152. println("update VLC plugins cache")
  153. val plugins = project.layout.projectDirectory.dir("build/compose/binaries/main/app/幕境/app/resources/VLC/plugins").asFile.absolutePath
  154. val cacheGen = project.layout.projectDirectory.dir("build/compose/binaries/main/app/幕境/app/resources/VLC/vlc-cache-gen.exe").asFile.absolutePath
  155. val command = listOf(cacheGen, plugins)
  156. try {
  157. val process = ProcessBuilder(command).start()
  158. process.waitFor()
  159. } catch (e: Exception) {
  160. println("Error running vlc-cache-gen: ${e.message}")
  161. }
  162. }
  163. }
  164. }else if(os.indexOf("mac") >= 0 || os.indexOf("darwin") >= 0){
  165. // github 的下载地址不支持中文名称,所以需要在打包之后修改安装包的名称
  166. tasks.register("renameDmg") {
  167. doLast {
  168. val dmgFile = fileTree( project.layout.projectDirectory.dir("build/compose/binaries/main/dmg")) {
  169. include("*.dmg")
  170. }.singleFile
  171. val arch = System.getProperty("os.arch").lowercase()
  172. val newDmgFile = file("${dmgFile.parentFile}/MuJing-${project.version}-${arch}.dmg")
  173. if (newDmgFile.exists()) {
  174. newDmgFile.delete()
  175. }
  176. dmgFile.renameTo(newDmgFile)
  177. }
  178. }
  179. tasks.named("packageDmg") {
  180. finalizedBy("renameDmg")
  181. }
  182. }
  183. }
  184. apply(from = "wix.gradle.kts")
  185. /**
  186. * 解压缩 7z 文件
  187. */
  188. @Throws(IOException::class)
  189. fun decompressDict(input: File, destination: File) {
  190. SevenZFile.builder()
  191. .setSeekableByteChannel(Files.newByteChannel(input.toPath()))
  192. .get().use { sevenZFile ->
  193. val entry = sevenZFile.nextEntry
  194. if (entry != null && !entry.isDirectory) {
  195. val outFile = File(destination, entry.name)
  196. outFile.parentFile.mkdirs()
  197. FileOutputStream(outFile).use { out ->
  198. val content = ByteArray(entry.size.toInt())
  199. sevenZFile.read(content, 0, content.size)
  200. out.write(content)
  201. }
  202. }
  203. }
  204. }