plugins { id 'application' } mainClassName = 'com.cbe.gui.Main' dependencies { implementation project(':modules:core') implementation project(':modules:loader') implementation project(':modules:cbecc') compileOnly 'com.google.code.findbugs:jsr305:3.0.2' } application { applicationName = 'cbe-emu' mainModule = 'com.cbe.gui' } jar { manifest { attributes 'Main-Class': 'com.cbe.gui.Main' } } // Build a fat-jar with all dependencies for packaging with jpackage // Also embeds example .cbeplugin files so the jar can run with no arguments tasks.register('fatJar', Jar) { archiveClassifier.set('all') duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes 'Main-Class': 'com.cbe.gui.Main' } from sourceSets.main.output dependsOn configurations.runtimeClasspath from { configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) } } exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class' // Embed pre-compiled .cbeplugin files so the jar runs standalone doFirst { def buildDir = file("$rootDir/build") buildDir.mkdirs() def cbeccCp = configurations.runtimeClasspath.asPath // Map: plugin basename -> source folder suffix def plugins = [ 'tiny-cpu' : 'cpu', 'basic-ram' : 'ram', 'vga-display' : 'gpu', 'basic-kbd' : 'kbd', 'basic-snd' : 'snd', 'tiny-bios' : 'bios', ] plugins.each { name, ext -> def src = file("$rootDir/examples/${name}.${ext}") def dst = new File(buildDir, "${name}.cbeplugin") if (src.exists()) { exec { commandLine 'java', '-cp', cbeccCp, 'com.cbe.cbecc.Main', 'build', src.absolutePath, '-o', dst.absolutePath } } } } from("$rootDir/build") { include 'tiny-cpu.cbeplugin' include 'basic-ram.cbeplugin' include 'vga-display.cbeplugin' include 'basic-kbd.cbeplugin' include 'basic-snd.cbeplugin' include 'tiny-bios.cbeplugin' into 'embedded/' } } // Stage the fat-jar and required runtime jars in a single directory for jpackage tasks.register('stage', Copy) { dependsOn fatJar from("$buildDir/libs") { include 'gui-0.1.0-all.jar' rename 'gui-0.1.0-all.jar', 'cbe-emu.jar' } into "$buildDir/stage" doLast { println "" println "==> Staged: $buildDir/stage" file("$buildDir/stage").eachFileMatch(~/.*\.jar/) { println " " + it.name } } } // Build a native installer using JDK jpackage // Usage: ./gradlew :modules:gui:packageImage -PjpackageType=app-image // ./gradlew :modules:gui:packageImage -PjpackageType=msi // ./gradlew :modules:gui:packageImage -PjpackageType=exe // (requires JDK 14+ on the host running the build) tasks.register('packageImage', Exec) { dependsOn stage def stageDir = file("$buildDir/stage") def outDir = file("$buildDir/installer") def type = hasProperty('jpackageType') ? property('jpackageType') : 'app-image' doFirst { outDir.deleteDir() outDir.mkdirs() } // 'app-image' = folder with launcher inside (no JRE bundled) - works on any host // 'msi' = Windows MSI installer (with bundled JRE) - requires WiX // 'exe' = Windows EXE installer (with bundled JRE) - requires Inno Setup // 'deb'/'rpm' = Linux installer // 'dmg'/'pkg' = macOS installer commandLine 'jpackage', '--input', stageDir.absolutePath, '--dest', outDir.absolutePath, '--name', 'CBE-Emulator', '--main-jar', 'cbe-emu.jar', '--main-class', 'com.cbe.gui.Main', '--app-version', '0.1.0', '--vendor', 'CBE Project', '--description', 'CBE Platform - Emulator', '--type', type, '--java-options', '-Xmx256m' } // Build a portable Windows package: fat-jar + bundled JRE + .bat launcher // Usage: ./gradlew :modules:gui:portableWindowsZip -PwinJre=/mnt/e/ZernMC/lib/jre21 // Property: -PwinJre= - REQUIRED: path to a Windows JRE (must contain bin/java.exe) tasks.register('portableWindows', Exec) { group = 'distribution' description = 'Builds dist/windows-portable/ - .bat launcher + bundled JRE + fat-jar + plugins' dependsOn stage def winJre = findProperty('winJre') if (winJre == null) { throw new GradleException("portableWindows requires -PwinJre=") } def winJreFile = file(winJre) if (!new File(winJreFile, 'bin/java.exe').exists()) { throw new GradleException("-PwinJre=$winJre does not contain bin/java.exe (not a Windows JRE?)") } def outDir = file("$rootDir/dist/windows-portable") commandLine 'bash', '-c', """ set -e rm -rf '${outDir.absolutePath}' mkdir -p '${outDir.absolutePath}/runtime' mkdir -p '${outDir.absolutePath}/app' mkdir -p '${outDir.absolutePath}/app/examples' # Copy Windows JRE cp -rL '${winJreFile.absolutePath}/.' '${outDir.absolutePath}/runtime/' # Copy fat jar (with embedded plugins) cp '${rootDir}/modules/gui/build/stage/cbe-emu.jar' '${outDir.absolutePath}/app/' # Copy launchers cp '${rootDir}/modules/gui/src/launcher/CBE-Emulator.bat' '${outDir.absolutePath}/' cp '${rootDir}/modules/gui/src/launcher/CBE-Emulator.vbs' '${outDir.absolutePath}/' # Create CBE-Emulator.exe as a copy of javaw.exe (real Windows PE binary) # Use the bundled runtime's javaw.exe cp '${outDir.absolutePath}/runtime/bin/javaw.exe' '${outDir.absolutePath}/CBE-Emulator.exe' # Compile example plugins (strip source type extension: foo.ram -> foo) CBECC_CP='${rootDir}/modules/cbecc/build/libs/cbecc-0.1.0.jar:${rootDir}/modules/loader/build/libs/loader-0.1.0.jar:${rootDir}/modules/core/build/libs/core-0.1.0.jar' for src in '${rootDir}/examples'/*/; do fullname=\$(basename "\$src") shortname=\${fullname%.*} # remove .ram / .gpu / .cpu suffix java -cp "\$CBECC_CP" com.cbe.cbecc.Main build "\$src" -o "${outDir.absolutePath}/app/examples/\$shortname.cbeplugin" 2>/dev/null || true done echo '' echo '==> Built portable package: ${outDir.absolutePath}' du -sh '${outDir.absolutePath}' ls -la '${outDir.absolutePath}/' | head -10 """ } tasks.register('portableWindowsZip', Exec) { group = 'distribution' description = 'Builds dist/CBE-Emulator-windows-portable.zip' dependsOn portableWindows commandLine 'bash', '-c', """ set -e cd '${rootDir}/dist' rm -f CBE-Emulator-windows-portable.zip python3 -c " import zipfile, os with zipfile.ZipFile('CBE-Emulator-windows-portable.zip', 'w', zipfile.ZIP_DEFLATED, compresslevel=6) as z: for root, dirs, files in os.walk('windows-portable'): for f in files: full = os.path.join(root, f) rel = os.path.relpath(full, 'windows-portable') z.write(full, rel) " ls -la CBE-Emulator-windows-portable.zip """ }