import org.panteleyev.jpackage.ImageType buildscript { repositories { google() mavenCentral() } } plugins { id 'com.github.johnrengelman.shadow' version '8.1.1' id 'java' id 'io.franzbecker.gradle-lombok' version '3.0.0' id 'application' id 'org.openjfx.javafxplugin' version '0.1.0' // 不再使用模块插件,移除 org.javamodularity.moduleplugin // id 'org.javamodularity.moduleplugin' version '1.8.12' id("org.panteleyev.jpackageplugin") version "1.6.1" } group = project_group version = project_version repositories { mavenCentral() } ext { junitVersion = '5.10.0' } // 指定 JDK 版本 java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } sourceCompatibility = '17' targetCompatibility = '17' tasks.withType(JavaCompile).configureEach { options.release = 17 options.encoding = 'UTF-8' } // 平台判定,自动添加 JavaFX 依赖的 classifier def osName = org.gradle.internal.os.OperatingSystem.current() def javafxPlatform if (osName.isWindows()) { javafxPlatform = 'win' } else if (osName.isMacOsX()) { javafxPlatform = 'mac' } else if (osName.isLinux()) { javafxPlatform = 'linux' } else { throw new GradleException("Unsupported OS for JavaFX: $osName") } def javafxVersion = '17.0.6' dependencies { // JavaFX 必须带平台后缀,classpath 模式必须 implementation "org.openjfx:javafx-controls:$javafxVersion:$javafxPlatform" implementation "org.openjfx:javafx-fxml:$javafxVersion:$javafxPlatform" implementation 'ch.qos.logback:logback-classic:1.5.18' implementation 'ch.qos.logback:logback-core:1.5.18' implementation 'commons-cli:commons-cli:1.9.0' implementation 'com.alibaba:easyexcel:4.0.3' implementation 'org.apache.pdfbox:pdfbox:3.0.5' implementation 'com.github.albfernandez:javadbf:1.14.1' implementation 'org.apache.poi:poi-ooxml:5.4.1' implementation 'com.intellij:annotations:12.0' // ofdrw 核心库 implementation 'org.ofdrw:ofdrw-core:2.3.7' implementation 'org.ofdrw:ofdrw-pkg:2.3.7' implementation 'org.ofdrw:ofdrw-reader:2.3.7' // 第三方依赖 implementation 'dom4j:dom4j:1.6.1' implementation 'org.bouncycastle:bcpkix-jdk18on:1.77' // 注意:版本可能需要调整 implementation 'commons-io:commons-io:2.11.0' compileOnly 'org.projectlombok:lombok:1.18.38' annotationProcessor 'org.projectlombok:lombok:1.18.38' testCompileOnly 'org.projectlombok:lombok:1.18.38' testAnnotationProcessor 'org.projectlombok:lombok:1.18.38' testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" } // ... application 块 ... application { // 取消模块化,去掉 mainModule mainClass = 'top.r3944realms.docchecktoolrefactored.Main' } // 配置 Shadow-JAR 任务 第三方依赖的签名文件(.SF、.RSA)在 Fat-JAR 中冲突,导致 JVM 验证失败 shadowJar { // 设置生成的 Jar 包名称 archiveBaseName.set(project_name) archiveVersion.set(project_version) // 指定主类,这样可以直接用 java -jar 运行 manifest { attributes 'Main-Class': application.mainClass.get() } // 合并服务文件(例如 SPI 配置),对某些库很重要 mergeServiceFiles() // 核心修复:排除所有签名文件,解决 "Invalid signature file digest" 错误 exclude 'META-INF/*.SF' exclude 'META-INF/*.RSA' exclude 'META-INF/*.DSA' } // 让 build 任务依赖 shadowJar,这样执行 ./gradlew build 时也会生成 Fat-JAR build.dependsOn shadowJar javafx { version = javafxVersion // 这里的 modules 只为插件识别,实际classpath方式运行时不起作用 modules = ['javafx.controls', 'javafx.fxml'] } processResources { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } test { useJUnitPlatform() configurations.configureEach { exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl' } } // 创建日志目录任务 tasks.register('createLogDir') { doLast { mkdir "${projectDir}/logs" } } processResources.dependsOn createLogDir // 其他自定义任务按需保留或调整 tasks.register('runCli', JavaExec) { group = 'application' description = 'Run the application in CLI mode' classpath = sourceSets.main.runtimeClasspath mainClass = 'top.r3944realms.docchecktoolrefactored.Main' // 默认参数,可以覆盖 args '--cli', '-v' // 可以添加更多默认参数 if (project.hasProperty('cliArgs')) { args project.property('cliArgs').split() } } // =================== 轻便版打包 =================== tasks.register('buildPortable', Exec) { group = 'distribution' description = 'Build portable EXE (no installer)' // 依赖 shadowJar 任务,而不是 buildFatJar dependsOn shadowJar doFirst { mkdir "$buildDir/distributions" // 打印出生成的 shadow JAR 信息,方便确认 def shadowJarFile = shadowJar.archiveFile.get().asFile println "Using shadow JAR for packaging: ${shadowJarFile.name}" println "Location: ${shadowJarFile.parent}" } commandLine 'jpackage', '--name', project_name, // 使用 project_name 属性 '--input', shadowJar.archiveFile.get().asFile.parent, // shadow JAR 所在的目录 '--main-jar', shadowJar.archiveFileName.get(), // shadow JAR 的文件名 '--main-class', application.mainClass.get(), '--type', 'app-image', '--app-version', project_version, '--vendor', 'r3944realms', '--dest', "$buildDir/distributions", '--java-options', '-Dfile.encoding=UTF-8', '--java-options', '-Xmx4G', '--java-options', '-Xms256m', '--verbose', '--icon', file('src/main/resources/img/logo256x.ico').absolutePath }