Correct references.
[SquirrelJME.git] / emulators / standalone / build.gradle
blob2a1ad9858ae59a9cd34d3d59bd662a9870fc5d48
1 import cc.squirreljme.plugin.multivm.ident.SourceTargetClassifier
2 import cc.squirreljme.plugin.multivm.BangletVariant
3 import cc.squirreljme.plugin.multivm.ClutterLevel
4 import cc.squirreljme.plugin.multivm.VMFullSuiteDepends
5 import cc.squirreljme.plugin.multivm.VMHelpers
6 import cc.squirreljme.plugin.multivm.VMRunUpToDateWhen
7 import cc.squirreljme.plugin.multivm.VMType
9 import java.nio.file.Files
10 import java.nio.file.Paths
11 import java.nio.file.StandardOpenOption
12 import java.util.regex.Pattern
13 import java.util.zip.ZipEntry
14 import java.util.zip.ZipInputStream
16 plugins
18         id "application"
19         id "java"
20         id "com.github.johnrengelman.shadow" version "7.1.2"
23 description = "Standalone SquirrelJME virtual machine on Java."
24 mainClassName = "cc.squirreljme.vm.standalone.main.Main"
26 dependencies {
27         implementation project(":emulators:springcoat-vm")
30 java {
31         // Use a fixed version of the JVM
32         compileJava
33         {
34                 sourceCompatibility = JavaVersion.VERSION_1_8
35                 targetCompatibility = JavaVersion.VERSION_1_8
36                 
37                 // Use the default bootstrap classpath
38                 options.bootstrapClasspath = null
39                 
40         }
41         
42         // Maximize debugging
43         compileJava.options.debug = true
44         compileJava.options.debugOptions.setDebugLevel("source,lines,vars")
45         
46         // Copy settings
47         compileTestJava.options.debug = compileJava.options.debug
48         compileTestJava.options.debugOptions = compileJava.options.debugOptions
51 // Mapper for Jar names on files to straight file names
52 static Iterable<java.nio.file.Path> mapBaseNameP(Iterable<Path> input) {
53         List<java.nio.file.Path> result = new ArrayList<>()
54         
55         input.forEach({path -> result.add(path.getFileName())})
56         
57         return result;
60 // Mapper for Jar names on files to straight file names
61 static Iterable<java.nio.file.Path> mapBaseNameF(Iterable<File> input) {
62         List<java.nio.file.Path> mapped = new ArrayList<>()
63         
64         input.forEach({file -> mapped.add(file.toPath())})
65         
66         return mapBaseNameP(mapped as Iterable<Path>)
69 static String flatClasspath(Project project) {
70         return VMHelpers.classpathAsString(mapBaseNameP(VMHelpers
71                 .runClassPath(project, new SourceTargetClassifier(
72                         SourceSet.MAIN_SOURCE_SET_NAME,
73                         VMType.SPRINGCOAT, BangletVariant.NONE,
74                         ClutterLevel.DEBUG)) as List<Path>))
77 static java.nio.file.Path nameToDiskFile(java.nio.file.Path jarOut,
78         String name) {
79         java.nio.file.Path diskFile = jarOut
80         for (String splice : name.split("[\\\\/]"))
81                 diskFile = diskFile.resolve(splice)
82                 
83         return diskFile
86 // Prefix for included JAR resources
87 String MERGED_PREFIX = "SQUIRRELJME.SQC"
89 task collateResourceJars {
90         dependsOn new VMFullSuiteDepends(collateResourceJars,
91                 new SourceTargetClassifier(SourceSet.MAIN_SOURCE_SET_NAME,
92                         VMType.SPRINGCOAT, BangletVariant.NONE, ClutterLevel.DEBUG))
93         mustRunAfter processResources
94         
95         // About this task
96         group "squirreljme"
97         description "Collates all files for standalone JARs."
98         
99         // Inputs for this, it is just all of the input JARs and such
100         inputs.files(project.provider({ -> VMHelpers.fullSuiteLibraries(
101                 rootProject.tasks.getByName("fullSpringCoatRelease")) as Iterable<Path>}))
102         outputs.files(project.provider({ ->
103                         java.nio.file.Path outBase = processResources.getOutputs().
104                                 files.getSingleFile().toPath().resolve(MERGED_PREFIX)
105                                 
106                         Set<java.nio.file.Path> result = new LinkedHashSet<>()
107                         
108                         // Suites list
109                         result.add(outBase.resolve("suites.list"))
110                         
111                         // Process each JAR
112                         for (File jarFile : collateResourceJars.getInputs()
113                                 .files.asList()) {
114                                 java.nio.file.Path jarPath = jarFile.toPath()
115                                 java.nio.file.Path jarName = jarPath.getFileName()
116                                 java.nio.file.Path jarOut = outBase.resolve(jarName)
117                                 
118                                 // JAR contents
119                                 result.add(jarOut.resolve("META-INF")
120                                         .resolve("squirreljme").resolve("resources.list"))
121                                 
122                                 // Contents of the JAR
123                                 try (InputStream jarIn = Files.newInputStream(jarPath,
124                                                 StandardOpenOption.READ);
125                                         ZipInputStream jar = new ZipInputStream(jarIn)) {
126                                         for (;;) {
127                                                 ZipEntry entry = jar.getNextEntry()
128                                                 if (entry == null)
129                                                         break
130                                                 
131                                                 if (entry.isDirectory())
132                                                         continue
133                                                 
134                                                 // Where is this file going?
135                                                 result.add(nameToDiskFile(jarOut, name))
136                                         }
137                                 }
138                         }
139                         
140                         return result
141                 }))
142         
143         // Up to date when dependencies are updated
144         outputs.upToDateWhen(new VMRunUpToDateWhen(new SourceTargetClassifier(
145                 SourceSet.MAIN_SOURCE_SET_NAME, VMType.SPRINGCOAT,
146                 BangletVariant.NONE, ClutterLevel.DEBUG)))
147                 
148         // Explode the JARs into the resource root
149         doFirst {
150                 java.nio.file.Path outBase = processResources.getOutputs().
151                         files.getSingleFile().toPath().resolve(MERGED_PREFIX)
152                 
153                 // Delete old directory set first since it will have a bunch of
154                 // old files in it and such...
155                 if (Files.isDirectory(outBase)) {
156                         Set<java.nio.file.Path> deleteFiles = new LinkedHashSet<>()
157                         Set<java.nio.file.Path> deleteDirs = new LinkedHashSet<>()
158                         Files.walk(outBase).forEach({
159                                         if (Files.isDirectory(it))
160                                                 deleteDirs.add(it)
161                                         else
162                                                 deleteFiles.add(it)
163                                 })
164                         for (Set<java.nio.file.Path> rawByes : [deleteFiles, deleteDirs]) {
165                                 List<java.nio.file.Path> byes = new ArrayList<>(rawByes)
166                                 Collections.reverse(byes)
167                                 
168                                 for (java.nio.file.Path bye : byes) {
169                                         logger.lifecycle(String.format("Cleaning %s...", bye))
170                                         
171                                         try {
172                                                 Files.deleteIfExists(bye)
173                                         } catch (IOException e) {
174                                                 e.printStackTrace()
175                                         }
176                                 }
177                         }
178                 }
179                 
180                 // Make sure it exists
181                 Files.createDirectories(outBase)
182                 
183                 // JAR suite list
184                 List<String> suiteList = new ArrayList<>()
185                 
186                 // Go through all of the files
187                 byte[] buf = new byte[524288];
188                 for (File jarFile : collateResourceJars.getInputs().files.asList()) {
189                         // Where is everything?
190                         java.nio.file.Path jarPath = jarFile.toPath()
191                         java.nio.file.Path jarName = jarPath.getFileName()
192                         
193                         // Add to the suite list for later
194                         suiteList.add(jarName.toString())
195                         
196                         // Where does the exploded JAR content go?
197                         java.nio.file.Path jarOut = outBase.resolve(jarName)
198                         
199                         // Setup base dir
200                         Files.createDirectories(jarOut)
201                         
202                         // Read the ZIP and process
203                         List<String> jarContent = new ArrayList<>()
204                         try (InputStream jarIn = Files.newInputStream(jarPath,
205                                         StandardOpenOption.READ);
206                                 ZipInputStream jar = new ZipInputStream(jarIn)) {
207                                 for (;;) {
208                                         ZipEntry entry = jar.getNextEntry()
209                                         if (entry == null)
210                                                 break
211                                         
212                                         if (entry.isDirectory())
213                                                 continue
214                                         
215                                         // Record for later
216                                         String name = entry.getName()
217                                         jarContent.add(name)
218                                         
219                                         // Find where it goes
220                                         java.nio.file.Path diskFile = nameToDiskFile(jarOut, name)
221                                         
222                                         // Setup parent
223                                         Files.createDirectories(diskFile.getParent())
224                                         
225                                         // Note it
226                                         logger.lifecycle(String.format("Adding %s...",
227                                                 outBase.relativize(diskFile)))
228                                         
229                                         // Copy down file
230                                         try (OutputStream out = Files.newOutputStream(diskFile,
231                                                         StandardOpenOption.WRITE,
232                                                         StandardOpenOption.TRUNCATE_EXISTING,
233                                                         StandardOpenOption.CREATE)) {
234                                                 for (;;) {
235                                                         int rc = jar.read(buf)
236                                                         
237                                                         if (rc < 0)
238                                                                 break
239                                                         
240                                                         out.write(buf, 0, rc)
241                                                 }
242                                         }
243                                 }
244                         }
245                         
246                         // Write resource list
247                         java.nio.file.Path rcListBase =
248                                 jarOut.resolve("META-INF").resolve("squirreljme")
249                         java.nio.file.Path rcListPath =
250                                 rcListBase.resolve("resources.list")
251                         Files.createDirectories(rcListBase)
252                         Files.write(rcListPath, jarContent,
253                                 StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING,
254                                 StandardOpenOption.CREATE)
255                 }
256                 
257                 // Write the suite list
258                 Files.write(outBase.resolve("suites.list"), suiteList,
259                         StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING,
260                         StandardOpenOption.CREATE)
261         }
264 // Jar Configuration
265 jar {
266         dependsOn processResources, collateResourceJars
267         mustRunAfter collateResourceJars
268         
269         // We need to set specific manifest properties
270         manifest {
271                 attributes \
272                         "X-SquirrelJME-Standalone-Main-Class":
273                                 "javax.microedition.midlet.__MainHandler__",
274                         "X-SquirrelJME-Standalone-Parameter":
275                                 "cc.squirreljme.runtime.launcher.ui.MidletMain",
276                         "X-SquirrelJME-Standalone-Classpath": project.provider({ ->
277                                         return flatClasspath(project(":modules:launcher"))
278                                 }),
279                         "X-SquirrelJME-Standalone-Library": project.provider({ ->
280                                         return VMHelpers.classpathAsString(
281                                                 mapBaseNameP(VMHelpers.fullSuiteLibraries(
282                                                         rootProject.tasks.getByName("fullSpringCoatRelease"))
283                                                         as Iterable<Path>))
284                                 }),
285                         "X-SquirrelJME-Standalone-Internal-Jar-Root": project.provider({ ->
286                                 "/" + MERGED_PREFIX + "/"})
287         }
290 // Configuration for ShadowJar
291 shadowJar {
292         dependsOn collateResourceJars
293         mustRunAfter collateResourceJars
294         
295         // Always SquirrelJME
296         archiveBaseName.set("squirreljme-standalone")
297         
298         // Set the suffix of the JAR to be the OS name and arch, since there is
299         // a dynamic library within for it
300         archiveClassifier.set(project.provider({ ->
301                         String osName = System.getProperty("os.name").toLowerCase()
302                         String osArch = System.getProperty("os.arch").toLowerCase()
303                         
304                         // Normalize OS names
305                         if (osName.contains("windows"))
306                                 osName = "windows"
307                         else if (osName.contains("mac os") || osName.contains("macos"))
308                                 osName = "macos"
309                         
310                         // Make sure there are no spaces or weird characters such as for
311                         // Windows
312                         return (osName + "-" + osArch).replaceAll(
313                                 Pattern.compile("[\\s<>:\"/\\\\|?*]"), "") 
314                 }))