Skip to content

Commit c18ceae

Browse files
committed
Added option to cache results of JRE extract & minimize, to speedup build times.
1 parent 7f783e4 commit c18ceae

File tree

5 files changed

+84
-38
lines changed

5 files changed

+84
-38
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@ java -jar packr.jar \
3030
| Parameter | Meaning |
3131
| --- | --- |
3232
| platform | one of "windows32", "windows64", "linux32", "linux64", "mac" |
33-
| jdk | ZIP file location or URL to ZIP file of an OpenJDK or Oracle JDK build containing a JRE. Prebuild OpenJDK packages can be found at https://github.com/alexkasko/openjdk-unofficial-builds. You can also specify a directory to an unpacked JDK distribution. E.g. using ${java.home} in a build script|
33+
| jdk | directory, ZIP file, or URL to ZIP file of an OpenJDK or Oracle JDK build containing a JRE. Prebuild OpenJDK packages can be found at https://github.com/alexkasko/openjdk-unofficial-builds. You can also specify a directory to an unpacked JDK distribution. E.g. using ${java.home} in a build script|
3434
| executable | name of the native executable, without extension such as ".exe" |
3535
| classpath | file locations of the JAR files to package |
3636
| mainclass | the fully qualified name of the main class, using dots to delimit package names |
3737
| vmargs | list of arguments for the JVM, without leading dashes, e.g. "Xmx1G" |
3838
| resources (optional) | list of files and directories to be packaged next to the native executable |
3939
| minimizejre | minimize the JRE by removing directories and files as specified by an additional config file. Comes with a few config files out of the box. See below for details on the minimization config file. |
4040
| output | the output directory |
41+
| cachejre (optional) | An optional directory to cache the result of JRE extraction and minimization. See below for details. |
4142
| icon (optional, OS X) | location of an AppBundle icon resource (.icns file) |
4243
| bundleidentifier (optional, OS X) | the bundle identifier of your Java application, e.g. "com.my.app" |
4344
| verbose | prints more status information during processing, which can be useful for debugging |
@@ -159,6 +160,12 @@ Packr comes with two such configurations out of the box, [`soft`](https://github
159160

160161
There's also a new, *experimental* configuration, [`oraclejre8`](https://github.com/libgdx/packr/blob/master/src/main/resources/minimize/oraclejre8), which reduces size of an Oracle 8 JRE following Oracle's redistribution rules described [here](http://www.oracle.com/technetwork/java/javase/jre-8-readme-2095710.html). It also repacks JAR files, reducing (unpacked) JRE size from about 180 mb to 70 mb. **This version is pretty much untested, so please use with care!**
161162

163+
### Cache
164+
165+
Extracting and minimizing a JRE can take quite some time. If the `cachejre` option is used, the result of these operations is cached in the given folder, and can be reused in subsequent runs of packr.
166+
167+
As of now, packr doesn't do any elaborate checks to validate the content of this cache folder. So if you update the JDK, or change the minimize profile, you need to empty or remove this folder manually to force a change.
168+
162169
### Classpath
163170

164171
Minimization aside, packr also removes all dynamic libraries which do not match the target platform from your project JAR file(s):

src/main/java/com/badlogicgames/packr/Packr.java

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,10 @@ public void pack(PackrConfig config) throws IOException {
5151

5252
writeConfig(output);
5353

54-
copyJRE(output);
54+
copyAndMinimizeJRE(output, config);
5555

5656
copyResources(output);
5757

58-
PackrReduce.minimizeJre(output, config);
59-
6058
PackrReduce.removePlatformLibs(output, config);
6159

6260
System.out.println("Done!");
@@ -197,44 +195,74 @@ private void writeConfig(PackrOutput output) throws IOException {
197195
}
198196
}
199197

200-
private void copyJRE(PackrOutput output) throws IOException {
198+
private void copyAndMinimizeJRE(PackrOutput output, PackrConfig config) throws IOException {
201199

202-
File jdkFile;
203-
boolean fetchFromRemote = config.jdk.startsWith("http://") || config.jdk.startsWith("https://");
200+
boolean extractToCache = config.cacheJre != null;
201+
boolean skipExtractToCache = false;
204202

205-
// add JRE from local or remote zip file
206-
if (fetchFromRemote) {
207-
System.out.println("Downloading JDK from '" + config.jdk + "' ...");
208-
jdkFile = new File(output.resourcesFolder, "jdk.zip");
209-
InputStream in = new URL(config.jdk).openStream();
210-
OutputStream outJdk = new FileOutputStream(jdkFile);
211-
IOUtils.copy(in, outJdk);
212-
in.close();
213-
outJdk.close();
214-
} else {
215-
jdkFile = new File(config.jdk);
203+
// check if JRE extraction (and minimize) can be skipped
204+
if (extractToCache && config.cacheJre.exists()) {
205+
if (config.cacheJre.isDirectory()) {
206+
// check if the cache directory is empty
207+
String[] files = config.cacheJre.list();
208+
skipExtractToCache = files != null && files.length > 0;
209+
} else {
210+
throw new IOException(config.cacheJre + " must be a directory");
211+
}
216212
}
217213

218-
System.out.println("Unpacking JRE ...");
219-
File tmp = new File(output.resourcesFolder, "tmp");
220-
PackrFileUtils.mkdirs(tmp);
214+
// path to extract JRE to (cache, or target folder)
215+
File jreStoragePath = extractToCache ? config.cacheJre : output.resourcesFolder;
221216

222-
if (jdkFile.isDirectory()) {
223-
PackrFileUtils.copyDirectory(jdkFile, tmp);
217+
if (skipExtractToCache) {
218+
System.out.println("Using cached JRE in '" + config.cacheJre + "' ...");
224219
} else {
225-
ZipUtil.unpack(jdkFile, tmp);
226-
}
220+
// path to extract JRE from (folder, zip or remote)
221+
boolean fetchFromRemote = config.jdk.startsWith("http://") || config.jdk.startsWith("https://");
222+
File jdkFile = fetchFromRemote ? new File(jreStoragePath, "jdk.zip") : new File(config.jdk);
223+
224+
// download from remote
225+
if (fetchFromRemote) {
226+
System.out.println("Downloading JDK from '" + config.jdk + "' ...");
227+
try (InputStream remote = new URL(config.jdk).openStream()) {
228+
try (OutputStream outJdk = new FileOutputStream(jdkFile)) {
229+
IOUtils.copy(remote, outJdk);
230+
}
231+
}
232+
}
227233

228-
File jre = searchJre(tmp);
229-
if (jre == null) {
230-
throw new IOException("Couldn't find JRE in JDK, see '" + tmp.getAbsolutePath() + "'");
231-
}
234+
// unpack JDK zip (or copy if it's a folder)
235+
System.out.println("Unpacking JRE ...");
236+
File tmp = new File(jreStoragePath, "tmp");
237+
PackrFileUtils.mkdirs(tmp);
232238

233-
PackrFileUtils.copyDirectory(jre, new File(output.resourcesFolder, "jre"));
234-
PackrFileUtils.deleteDirectory(tmp);
239+
if (jdkFile.isDirectory()) {
240+
PackrFileUtils.copyDirectory(jdkFile, tmp);
241+
} else {
242+
ZipUtil.unpack(jdkFile, tmp);
243+
}
244+
245+
// copy the JRE sub folder
246+
File jre = searchJre(tmp);
247+
if (jre == null) {
248+
throw new IOException("Couldn't find JRE in JDK, see '" + tmp.getAbsolutePath() + "'");
249+
}
250+
251+
PackrFileUtils.copyDirectory(jre, new File(jreStoragePath, "jre"));
252+
PackrFileUtils.deleteDirectory(tmp);
253+
254+
if (fetchFromRemote) {
255+
PackrFileUtils.delete(jdkFile);
256+
}
257+
258+
// run minimize
259+
PackrReduce.minimizeJre(jreStoragePath, config);
260+
}
235261

236-
if (fetchFromRemote) {
237-
PackrFileUtils.delete(jdkFile);
262+
if (extractToCache) {
263+
// if cache is used, copy again here; if the JRE is cached already,
264+
// this is the only copy done (and everything above is skipped)
265+
PackrFileUtils.copyDirectory(jreStoragePath, output.resourcesFolder);
238266
}
239267
}
240268

src/main/java/com/badlogicgames/packr/PackrCommandLine.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ public interface PackrCommandLine {
6161
@Option(description = "minimize JRE by removing folders and files specified in config file", longName = "minimizejre", defaultToNull = true)
6262
String minimizeJre();
6363

64+
@Option(description = "folder to cache bundled JRE, to speedup builds", longName = "cachejre", defaultToNull = true)
65+
File cacheJre();
66+
6467
@Option(description = "additional files and folders to be packed next to the executable", longName = "resources", defaultToNull = true)
6568
List<File> resources();
6669

src/main/java/com/badlogicgames/packr/PackrConfig.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static Platform byDesc(String desc) throws IOException {
6666
public String mainClass;
6767
public List<String> vmArgs;
6868
public String minimizeJre;
69+
public File cacheJre;
6970
public List<File> resources;
7071
public File outDir;
7172
public File iconResource;
@@ -125,6 +126,10 @@ public PackrConfig(PackrCommandLine commandLine) throws IOException {
125126
minimizeJre = commandLine.minimizeJre();
126127
}
127128

129+
if (commandLine.cacheJre() != null) {
130+
cacheJre = commandLine.cacheJre();
131+
}
132+
128133
resources = appendTo(resources, commandLine.resources());
129134

130135
if (commandLine.outDir() != null) {
@@ -163,6 +168,9 @@ private void readConfigJson(File configJson) throws IOException {
163168
if (json.get("minimizejre") != null) {
164169
minimizeJre = json.get("minimizejre").asString();
165170
}
171+
if (json.get("cachejre") != null) {
172+
cacheJre = new File(json.get("cachejre").asString());
173+
}
166174
if (json.get("resources") != null) {
167175
resources = toFileArray(json.get("resources").asArray());
168176
}
@@ -177,7 +185,7 @@ private void readConfigJson(File configJson) throws IOException {
177185

178186
private <T> List<T> appendTo(List<T> list, List<T> append) {
179187
if (list == null) {
180-
return append != null ? append : new ArrayList<T>();
188+
return append != null ? append : new ArrayList<>();
181189
}
182190

183191
if (append != null) {

src/main/java/com/badlogicgames/packr/PackrReduce.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
*/
3030
class PackrReduce {
3131

32-
static void minimizeJre(PackrOutput output, PackrConfig config) throws IOException {
32+
static void minimizeJre(File output, PackrConfig config) throws IOException {
3333
if (config.minimizeJre == null) {
3434
return;
3535
}
@@ -45,7 +45,7 @@ static void minimizeJre(PackrOutput output, PackrConfig config) throws IOExcepti
4545
JsonArray reduceArray = minimizeJson.get("reduce").asArray();
4646
for (JsonValue reduce : reduceArray) {
4747
String path = reduce.asObject().get("archive").asString();
48-
File file = new File(output.resourcesFolder, path);
48+
File file = new File(output, path);
4949

5050
if (!file.exists()) {
5151
if (config.verbose) {
@@ -57,7 +57,7 @@ static void minimizeJre(PackrOutput output, PackrConfig config) throws IOExcepti
5757
boolean needsUnpack = !file.isDirectory();
5858

5959
File fileNoExt = needsUnpack
60-
? new File(output.resourcesFolder, path.contains(".") ? path.substring(0, path.lastIndexOf('.')) : path)
60+
? new File(output, path.contains(".") ? path.substring(0, path.lastIndexOf('.')) : path)
6161
: file;
6262

6363
if (needsUnpack) {
@@ -112,7 +112,7 @@ static void minimizeJre(PackrOutput output, PackrConfig config) throws IOExcepti
112112

113113
JsonArray removeFilesArray = remove.asObject().get("paths").asArray();
114114
for (JsonValue removeFile : removeFilesArray) {
115-
removeFileWildcard(output.resourcesFolder, removeFile.asString(), config);
115+
removeFileWildcard(output, removeFile.asString(), config);
116116
}
117117
}
118118
}

0 commit comments

Comments
 (0)