Skip to content

Commit

Permalink
Merge pull request #64 from code-disaster/osx-app-store
Browse files Browse the repository at this point in the history
MacOS: Updated bundle structure to meet Mac App Store requirements
  • Loading branch information
code-disaster authored Jun 18, 2016
2 parents 9394e94 + 157352d commit 08a74d4
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 35 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ outdir/
Info.plist
MacOS/
executable
Resources/
yourjar.jar
config.json
jre/
Resources/
icons.icns [if config.icon is set]
```

Expand Down
53 changes: 28 additions & 25 deletions src/main/java/com/badlogicgames/packr/Packr.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void pack(PackrConfig config) throws IOException {
config.validate();
this.config = config;

File output = config.outDir;
PackrOutput output = new PackrOutput(config.outDir, config.outDir);

cleanOrCreateOutputFolder(output);

Expand All @@ -67,16 +67,17 @@ public void pack(PackrConfig config) throws IOException {
System.out.println("Done!");
}

private void cleanOrCreateOutputFolder(File output) throws IOException {
if (output.exists()) {
System.out.println("Cleaning output directory '" + output.getAbsolutePath() + "' ...");
FileUtils.deleteDirectory(output);
private void cleanOrCreateOutputFolder(PackrOutput output) throws IOException {
File folder = output.executableFolder;
if (folder.exists()) {
System.out.println("Cleaning output directory '" + folder.getAbsolutePath() + "' ...");
FileUtils.deleteDirectory(folder);
} else {
PackrFileUtils.mkdirs(output);
PackrFileUtils.mkdirs(folder);
}
}

private File buildMacBundle(File output) throws IOException {
private PackrOutput buildMacBundle(PackrOutput output) throws IOException {

if (config.platform != PackrConfig.Platform.MacOS) {
return output;
Expand All @@ -95,13 +96,15 @@ private File buildMacBundle(File output) throws IOException {

// create folder structure

PackrFileUtils.mkdirs(new File(output, "Contents"));
FileUtils.writeStringToFile(new File(output, "Contents/Info.plist"), readResourceAsString("/Info.plist", values));
File root = output.executableFolder;

File target = new File(output, "Contents/MacOS");
PackrFileUtils.mkdirs(new File(root, "Contents"));
FileUtils.writeStringToFile(new File(root, "Contents/Info.plist"), readResourceAsString("/Info.plist", values));

File target = new File(root, "Contents/MacOS");
PackrFileUtils.mkdirs(target);

File resources = new File(output, "Contents/Resources");
File resources = new File(root, "Contents/Resources");
PackrFileUtils.mkdirs(resources);

if (config.iconResource != null) {
Expand All @@ -111,10 +114,10 @@ private File buildMacBundle(File output) throws IOException {
}
}

return target;
return new PackrOutput(target, resources);
}

private void copyExecutableAndClasspath(File output) throws IOException {
private void copyExecutableAndClasspath(PackrOutput output) throws IOException {
byte[] exe = null;
String extension = "";

Expand All @@ -139,13 +142,13 @@ private void copyExecutableAndClasspath(File output) throws IOException {
}

System.out.println("Copying executable ...");
FileUtils.writeByteArrayToFile(new File(output, config.executable + extension), exe);
PackrFileUtils.chmodX(new File(output, config.executable + extension));
FileUtils.writeByteArrayToFile(new File(output.executableFolder, config.executable + extension), exe);
PackrFileUtils.chmodX(new File(output.executableFolder, config.executable + extension));

System.out.println("Copying classpath(s) ...");
for (String file : config.classpath) {
File cpSrc = new File(file);
File cpDst = new File(output, new File(file).getName());
File cpDst = new File(output.resourcesFolder, new File(file).getName());

if (cpSrc.isFile()) {
FileUtils.copyFile(cpSrc, cpDst);
Expand All @@ -157,7 +160,7 @@ private void copyExecutableAndClasspath(File output) throws IOException {
}
}

private void writeConfig(File output) throws IOException {
private void writeConfig(PackrOutput output) throws IOException {

StringBuilder builder = new StringBuilder();
builder.append("{\n");
Expand Down Expand Up @@ -188,18 +191,18 @@ private void writeConfig(File output) throws IOException {
builder.append(" ]\n");
builder.append("}");

FileUtils.writeStringToFile(new File(output, "config.json"), builder.toString());
FileUtils.writeStringToFile(new File(output.resourcesFolder, "config.json"), builder.toString());
}

private void copyJRE(File output) throws IOException {
private void copyJRE(PackrOutput output) throws IOException {

File jdkFile;
boolean fetchFromRemote = config.jdk.startsWith("http://") || config.jdk.startsWith("https://");

// add JRE from local or remote zip file
if (fetchFromRemote) {
System.out.println("Downloading JDK from '" + config.jdk + "' ...");
jdkFile = new File(output, "jdk.zip");
jdkFile = new File(output.resourcesFolder, "jdk.zip");
InputStream in = new URL(config.jdk).openStream();
OutputStream outJdk = FileUtils.openOutputStream(jdkFile);
IOUtils.copy(in, outJdk);
Expand All @@ -210,7 +213,7 @@ private void copyJRE(File output) throws IOException {
}

System.out.println("Unpacking JRE ...");
File tmp = new File(output, "tmp");
File tmp = new File(output.resourcesFolder, "tmp");
PackrFileUtils.mkdirs(tmp);
ZipUtil.unpack(jdkFile, tmp);

Expand All @@ -219,7 +222,7 @@ private void copyJRE(File output) throws IOException {
throw new IOException("Couldn't find JRE in JDK, see '" + tmp.getAbsolutePath() + "'");
}

FileUtils.copyDirectory(jre, new File(output, "jre"));
FileUtils.copyDirectory(jre, new File(output.resourcesFolder, "jre"));
FileUtils.deleteDirectory(tmp);

if (fetchFromRemote) {
Expand Down Expand Up @@ -248,7 +251,7 @@ private File searchJre(File tmp) {
return null;
}

private void copyResources(File output) throws IOException {
private void copyResources(PackrOutput output) throws IOException {
if (config.resources != null) {
System.out.println("Copying resources ...");

Expand All @@ -258,11 +261,11 @@ private void copyResources(File output) throws IOException {
}

if (file.isFile()) {
FileUtils.copyFile(file, new File(output, file.getName()));
FileUtils.copyFile(file, new File(output.resourcesFolder, file.getName()));
}

if (file.isDirectory()) {
File target = new File(output, file.getName());
File target = new File(output.resourcesFolder, file.getName());
PackrFileUtils.mkdirs(target);
FileUtils.copyDirectory(file, target);
}
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/badlogicgames/packr/PackrOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright 2014 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/

package com.badlogicgames.packr;

import java.io.File;

/**
* Data structure to describe output folders.
*/
class PackrOutput {

final File executableFolder;
final File resourcesFolder;

PackrOutput(File executableFolder, File resourcesFolder) {
this.executableFolder = executableFolder;
this.resourcesFolder = resourcesFolder;
}

}
14 changes: 7 additions & 7 deletions src/main/java/com/badlogicgames/packr/PackrReduce.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
*/
class PackrReduce {

static void minimizeJre(File output, PackrConfig config) throws IOException {
static void minimizeJre(PackrOutput output, PackrConfig config) throws IOException {
if (config.minimizeJre == null) {
return;
}
Expand All @@ -46,7 +46,7 @@ static void minimizeJre(File output, PackrConfig config) throws IOException {
JsonArray reduceArray = minimizeJson.get("reduce").asArray();
for (JsonValue reduce : reduceArray) {
String path = reduce.asObject().get("archive").asString();
File file = new File(output, path);
File file = new File(output.resourcesFolder, path);

if (!file.exists()) {
if (config.verbose) {
Expand All @@ -58,7 +58,7 @@ static void minimizeJre(File output, PackrConfig config) throws IOException {
boolean needsUnpack = !file.isDirectory();

File fileNoExt = needsUnpack
? new File(output, path.contains(".") ? path.substring(0, path.lastIndexOf('.')) : path)
? new File(output.resourcesFolder, path.contains(".") ? path.substring(0, path.lastIndexOf('.')) : path)
: file;

if (needsUnpack) {
Expand Down Expand Up @@ -113,7 +113,7 @@ static void minimizeJre(File output, PackrConfig config) throws IOException {

JsonArray removeFilesArray = remove.asObject().get("paths").asArray();
for (JsonValue removeFile : removeFilesArray) {
removeFileWildcard(output, removeFile.asString(), config);
removeFileWildcard(output.resourcesFolder, removeFile.asString(), config);
}
}
}
Expand Down Expand Up @@ -184,13 +184,13 @@ private static JsonObject readMinimizeProfile(PackrConfig config) throws IOExcep
return json;
}

static void removePlatformLibs(File output, PackrConfig config) throws IOException {
static void removePlatformLibs(PackrOutput output, PackrConfig config) throws IOException {
System.out.println("Removing foreign platform libs ...");

// let's remove any shared libs not used on the platform, e.g. libGDX/LWJGL natives
for (String classpath : config.classpath) {
File jar = new File(output, new File(classpath).getName());
File jarDir = new File(output, jar.getName() + ".tmp");
File jar = new File(output.resourcesFolder, new File(classpath).getName());
File jarDir = new File(output.resourcesFolder, jar.getName() + ".tmp");

if (config.verbose) {
if (jar.isDirectory()) {
Expand Down
39 changes: 37 additions & 2 deletions src/main/native/packr/src/macos/packr_macos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,43 @@ const char* getExecutablePath(const char* argv0) {
static char buf[MAXPATHLEN];
uint32_t size = sizeof(buf);

if (_NSGetExecutablePath(buf, &size) == -1) {
return argv0;
// first, try to obtain the MacOS bundle resources folder

char resourcesDir[MAXPATHLEN];
bool foundResources = false;

CFBundleRef bundle = CFBundleGetMainBundle();
if (bundle != NULL) {
CFURLRef resources = CFBundleCopyResourcesDirectoryURL(bundle);
if (resources != NULL) {
foundResources = CFURLGetFileSystemRepresentation(resources, true, (UInt8*) resourcesDir, size);
CFRelease(resources);
}
}

// as a fallback, default to the executable path

char executablePath[MAXPATHLEN];
bool foundPath = _NSGetExecutablePath(executablePath, &size) != -1;

// mangle path and executable name; the main application divides them again

if (foundResources && foundPath) {
const char* executableName = strrchr(executablePath, '/') + 1;
strcpy(buf, resourcesDir);
strcat(buf, "/");
strcat(buf, executableName);
cout << "Using bundle resource folder [1]: " << resourcesDir << "/[" << executableName << "]" << endl;
} else if (foundResources) {
strcpy(buf, resourcesDir);
strcat(buf, "/packr");
cout << "Using bundle resource folder [2]: " << resourcesDir << endl;
} else if (foundPath) {
strcpy(buf, executablePath);
cout << "Using executable path: " << executablePath << endl;
} else {
strcpy(buf, argv0);
cout << "Using [argv0] path: " << argv0 << endl;
}

return buf;
Expand Down
Binary file modified src/main/resources/packr-mac
Binary file not shown.

0 comments on commit 08a74d4

Please sign in to comment.