gradle+jcdk 构建最精简applet

This commit is contained in:
zcy
2025-09-03 20:57:53 +08:00
parent 80b02f6139
commit 5122f8eade
8 changed files with 467 additions and 0 deletions

106
build.gradle Normal file
View File

@@ -0,0 +1,106 @@
plugins {
id "java"
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
/** 源码在 src/ */
sourceSets {
main { java { srcDirs = ["src"] } }
}
/** 统一编译编码 */
tasks.withType(JavaCompile).configureEach { t ->
t.options.encoding = "UTF-8"
t.sourceCompatibility = "1.5"
t.targetCompatibility = "1.5"
def jcHome = System.getenv("JC_HOME")
if (!jcHome) throw new GradleException("缺少 JC_HOME")
t.options.bootstrapClasspath = files("${jcHome}/lib/api_classic.jar")
t.options.compilerArgs += ["-g:none", "-Xlint:none", "-XDignore.symbol.file"]
}
ext.JC_HOME = System.getenv('JC_HOME')
/** 仅编译期提供 JavaCard API不打包 */
dependencies {
compileOnly files("${System.getenv("JC_HOME")}/lib/api_classic.jar")
}
/** ===== 用本地 JCDK converter 生成 CAP ===== */
def pkgName = "com.zuc.zuc256" // ← 改成你的包名
def appletClass = "${pkgName}.MyApplet" // ← 改成你的 Applet 全类名
def packageAID = "0xA0:0x00:0x00:0x03:0x33:0x01:0x01" // ← 改成你的包 AID
def appletAID = "0xA0:0x00:0x00:0x03:0x33:0x01:0x01:0x01"// ← 改成你的实例 AID
def ver = "1.0"
tasks.register("buildCap") {
group = "build"
description = "Generate CAP via JCDK converter.bat"
dependsOn("classes")
doLast {
// 仅在执行阶段读取 JC_HOME避免配置期找不到属性
def jcHome = project.JC_HOME ?: System.getenv("JC_HOME")
if (!jcHome) {
throw new GradleException("未找到 JC_HOME请设置环境变量或在 build.gradle 里 ext.JC_HOME=...")
}
file("$buildDir/javacard").mkdirs()
def logFile = file("$buildDir/javacard/converter.log")
// 必要文件检查
def apiJar = new File(jcHome, "lib/api_classic.jar")
if (!apiJar.exists()) throw new GradleException("JC_HOME 无效:缺少 ${apiJar}")
def batFile = new File(jcHome, "bin/converter.bat")
if (!batFile.exists()) throw new GradleException("未找到 converter.bat${batFile}")
// 确认 .class 存在
def cls = file("$buildDir/classes/java/main/${pkgName.replace('.','/')}/MyApplet.class")
if (!cls.exists()) throw new GradleException("未找到已编译类:${cls}")
println ">>> Running converter.bat:"
// 把整条命令拼成一个字符串,并对含空格的路径加引号
def convCmd = new StringBuilder()
convCmd << "\"${batFile.absolutePath}\""
convCmd << " -verbose"
convCmd << " -classdir \"" << file("$buildDir/classes/java/main").absolutePath << "\""
convCmd << " -exportpath \"" << new File(jcHome, "api_export_files").absolutePath << "\""
convCmd << " -applet " << appletAID << " " << appletClass
convCmd << " -out CAP"
convCmd << " -d \"" << file("$buildDir/javacard").absolutePath << "\""
convCmd << " " << pkgName << " " << packageAID << " " << ver
println convCmd.toString()
def outBytes = new ByteArrayOutputStream()
def result = project.exec {
// 注意:对 cmd.exe命令必须作为“一个”字符串放在 /c 后面
commandLine "cmd", "/c", convCmd.toString()
ignoreExitValue = true
standardOutput = new org.apache.tools.ant.util.TeeOutputStream(outBytes, new FileOutputStream(logFile))
errorOutput = standardOutput
}
// Windows 常见是 GBK便于读中文
def out = outBytes.toString("GBK")
println(out)
println ">>> Converter log: ${logFile.absolutePath}"
if (result.exitValue != 0) {
println "---- converter.log tail ----"
println logFile.readLines("GBK").takeRight(80).join(System.lineSeparator())
throw new GradleException("converter 退出码:${result.exitValue}")
} else {
println "CAP 生成成功,目录:${file("$buildDir/javacard").absolutePath}"
}
}
}