diff --git a/app/Editor.java b/app/Editor.java index 63d6834f0..dfc8741e2 100644 --- a/app/Editor.java +++ b/app/Editor.java @@ -26,6 +26,7 @@ package processing.app; import processing.app.syntax.*; import processing.app.tools.*; +import processing.core.PConstants; import java.awt.*; import java.awt.datatransfer.*; @@ -1637,10 +1638,10 @@ public class Editor extends JFrame message("Exporting application..."); try { - boolean success = sketch.exportApplication(); - if (success) { - File destFolder = new File(sketch.folder, "application"); - Base.openFolder(destFolder); + if (sketch.exportApplication(PConstants.WINDOWS) && + sketch.exportApplication(PConstants.MACOSX) && + sketch.exportApplication(PConstants.LINUX)) { + Base.openFolder(sketch.folder); message("Done exporting."); } else { // error message will already be visible diff --git a/app/Sketch.java b/app/Sketch.java index f0c7f273f..1cc708c91 100644 --- a/app/Sketch.java +++ b/app/Sketch.java @@ -1777,16 +1777,11 @@ public class Sketch { // library sketch's "library" folder File libraryFolder = (File)en.nextElement(); File exportSettings = new File(libraryFolder, "export.txt"); + Hashtable exportTable = readSettings(exportSettings); + String appletList = (String) exportTable.get("applet"); String exportList[] = null; - if (exportSettings.exists()) { - String info[] = PApplet.loadStrings(exportSettings); - for (int i = 0; i < info.length; i++) { - if (info[i].startsWith("applet")) { - int idx = info[i].indexOf('='); // get applet= or applet = - String commas = info[i].substring(idx+1).trim(); - exportList = PApplet.split(commas, ", "); - } - } + if (appletList != null) { + exportList = PApplet.split(appletList, ", "); } else { exportList = libraryFolder.list(); } @@ -1938,15 +1933,29 @@ public class Sketch { * +-------------------------------------------------------+ * */ - public boolean exportApplication() throws Exception { + public boolean exportApplication(int exportPlatform) throws Exception { // make sure the user didn't hide the sketch folder ensureExistence(); //int exportPlatform = PApplet.platform; //PConstants.MACOSX; - int exportPlatform = PConstants.LINUX; + String exportPlatformStr = null; + if (exportPlatform == PConstants.WINDOWS) { + exportPlatformStr = "windows"; + } else if (exportPlatform == PConstants.MACOSX) { + exportPlatformStr = "macosx"; + } else if (exportPlatform == PConstants.LINUX) { + exportPlatformStr = "linux"; + } else { + exportPlatform = -1; + } + + String folderName = "application"; + if (exportPlatform != -1) { + folderName += "." + exportPlatformStr; + } // nuke the old folder because it can cause trouble - File destFolder = new File(folder, "application"); + File destFolder = new File(folder, folderName); Base.removeDir(destFolder); destFolder.mkdirs(); @@ -1981,12 +1990,28 @@ public class Sketch { File dotAppSkeleton = new File("lib/export/" + APP_SKELETON); Base.copyDir(dotAppSkeleton, dotAppFolder); + String stubName = "Contents/MacOS/JavaApplicationStub"; // need to set the stub to executable - File stubFile = - new File(dotAppFolder, "Contents/MacOS/JavaApplicationStub"); - String stubPath = stubFile.getAbsolutePath(); // will work on osx or *nix, but just dies on windows, oh well.. - Runtime.getRuntime().exec(new String[] { "chmod", "+x", stubPath }); + if (PApplet.platform == PConstants.WINDOWS) { + File warningFile = new File(destFolder, "readme.txt"); + PrintStream ps = new PrintStream(new FileOutputStream(warningFile)); + ps.println("This application was created on Windows, which doesn't"); + ps.println("properly support setting files as \"executable\","); + ps.println("a necessity for applications on Mac OS X."); + ps.println(); + ps.println("To fix this, use the Terminal on Mac OS X, and from this"); + ps.println("directory, type the following:"); + ps.println(); + ps.println("chmod +x " + dotAppFolder.getName() + "/" + stubName); + ps.flush(); + ps.close(); + + } else { + File stubFile = new File(dotAppFolder, stubName); + String stubPath = stubFile.getAbsolutePath(); + Runtime.getRuntime().exec(new String[] { "chmod", "+x", stubPath }); + } // set the jar folder to a different location than windows/linux jarFolder = new File(dotAppFolder, "Contents/Resources/Java"); @@ -2091,17 +2116,21 @@ public class Sketch { // in the list is a File object that points the // library sketch's "library" folder File exportSettings = new File(libraryFolder, "export.txt"); + Hashtable exportTable = readSettings(exportSettings); + String commaList = null; String exportList[] = null; - if (exportSettings.exists()) { - String info[] = PApplet.loadStrings(exportSettings); - for (int i = 0; i < info.length; i++) { - if (info[i].startsWith("application")) { - int idx = info[i].indexOf('='); - String commas = info[i].substring(idx+1).trim(); - exportList = PApplet.split(commas, ", "); - } - } - } else { + + if (exportPlatform != -1) { + // first check to see if there's something like application.macosx + commaList = (String) + exportTable.get("application." + exportPlatformStr); + } + if (commaList == null) { + // next check to see if something for 'application' is specified + commaList = (String) exportTable.get("application"); + } + if (commaList == null) { + // otherwise just dump the whole folder exportList = libraryFolder.list(); } @@ -2278,16 +2307,35 @@ public class Sketch { "Main-Class: " + name + "\n"; // TODO not package friendly zos.write(contents.getBytes()); zos.closeEntry(); + } - /* - for (int i = 0; i < bagelClasses.length; i++) { - if (!bagelClasses[i].endsWith(".class")) continue; - entry = new ZipEntry(bagelClasses[i]); - zos.putNextEntry(entry); - zos.write(Base.grabFile(new File(exportDir + bagelClasses[i]))); - zos.closeEntry(); + + /** + * Read from a file with a bunch of attribute/value pairs + * that are separated by = and ignore comments with #. + */ + protected Hashtable readSettings(File inputFile) { + Hashtable outgoing = new Hashtable(); + if (!inputFile.exists()) return outgoing; // return empty hash + + String lines[] = PApplet.loadStrings(inputFile); + for (int i = 0; i < lines.length; i++) { + int hash = lines[i].indexOf('#'); + String line = (hash == -1) ? + lines[i].trim() : lines[i].substring(hash).trim(); + if (line.length() == 0) continue; + + int equals = line.indexOf('='); + if (equals == -1) { + System.err.println("ignoring illegal line in " + inputFile); + System.err.println(" " + line); + continue; } - */ + String attr = line.substring(0, equals).trim(); + String valu = line.substring(equals + 1).trim(); + outgoing.put(attr, valu); + } + return outgoing; } diff --git a/opengl/library/export.txt b/opengl/library/export.txt new file mode 100755 index 000000000..aa5495070 --- /dev/null +++ b/opengl/library/export.txt @@ -0,0 +1,3 @@ +application.macosx = opengl.jar, jogl.jar, libjogl.jnilib, libjogl_cg.jnilib +application.windows = opengl.jar, jogl.jar, jogl.dll, jogl_cg.dll +application.linux = opengl.jar, jogl.jar, libjogl.so, libjogl_cg.so \ No newline at end of file diff --git a/serial/library/export.txt b/serial/library/export.txt new file mode 100755 index 000000000..7b4cacba8 --- /dev/null +++ b/serial/library/export.txt @@ -0,0 +1,3 @@ +application.macosx = serial.jar, RXTXcomm.jar, librxtxSerial.jnilib +application.windows = serial.jar, RXTXcomm.jar, rxtxSerial.dll +application.linux = serial.jar, RXTXcomm.jar, librxtxSerial.so \ No newline at end of file diff --git a/todo.txt b/todo.txt index d7e339126..b2122c162 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,8 @@ 0097 pde export-to-application -_ http://dev.processing.org/bugs/show_bug.cgi?id=60 +X http://dev.processing.org/bugs/show_bug.cgi?id=60 +_ make a note in the faq that it's implemented X add manifest.mf to exported applets so that applications will work X include main class info for executable jar file with jdk > 1.2 X was already done before @@ -24,18 +25,18 @@ X http://dev.processing.org/bugs/show_bug.cgi?id=157 X can macosx jnilib files be placed in the resources dir? X shift-export should export as application X write support for linux export - -_ need per-platform settings for exports -_ opengl needs to export .jnilib for macosx, but no dll and so files -_ if nothing available for that platform, uses "application" setting -_ if no application setting or export.txt file, then export everything +X need per-platform settings for exports +X opengl needs to export .jnilib for macosx, but no dll and so files +X if nothing available for that platform, uses "application" setting +X if no application setting or export.txt file, then export everything +o write code for selecting the output platform +X just export for all platforms _ documentation _ people using "java" mode must create their own main _ another function named main() is a no-no.. it'll confuse the preproc _ how to handle qtjava in exports? _ problem because on export, the qtjava import happens before the lib import _ why is this different between compiling and exporting? -_ write code for selecting the output platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .