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}" } } }