From 3513a01c59ac36f8e079512bbd3fe935df6519d6 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Sat, 10 May 2014 09:27:38 -0400 Subject: [PATCH] working on launch4j builder --- app/src/processing/mode/java/JavaBuild.java | 219 +++++++++++++++++--- core/src/processing/data/XML.java | 5 + 2 files changed, 190 insertions(+), 34 deletions(-) diff --git a/app/src/processing/mode/java/JavaBuild.java b/app/src/processing/mode/java/JavaBuild.java index 338c391bc..fe3208bfc 100644 --- a/app/src/processing/mode/java/JavaBuild.java +++ b/app/src/processing/mode/java/JavaBuild.java @@ -26,8 +26,14 @@ import java.io.*; import java.util.*; import java.util.zip.*; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DefaultLogger; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectHelper; + import processing.app.*; import processing.core.*; +import processing.data.XML; import processing.mode.java.preproc.*; // Would you believe there's a java.lang.Compiler class? I wouldn't. @@ -1270,6 +1276,7 @@ public class JavaBuild { if (!jarFolder.exists()) jarFolder.mkdirs(); + /* /// on windows, copy the exe file if (exportPlatform == PConstants.WINDOWS) { @@ -1287,8 +1294,9 @@ public class JavaBuild { new File(destFolder, sketch.getName() + ".exe")); } } + */ - + /// start copying all jar files Vector jarListVector = new Vector(); @@ -1451,42 +1459,28 @@ public class JavaBuild { /// figure out run options for the VM - // this is too vague. if anyone is using it, we can bring it back -// String runOptions = Preferences.get("run.options"); List runOptions = new ArrayList(); if (Preferences.getBoolean("run.options.memory")) { runOptions.add("-Xms" + Preferences.get("run.options.memory.initial") + "m"); runOptions.add("-Xmx" + Preferences.get("run.options.memory.maximum") + "m"); } - StringBuilder jvmOptionsList = new StringBuilder(); - for (String opt : runOptions) { - jvmOptionsList.append(" "); - jvmOptionsList.append(opt); - jvmOptionsList.append(""); - jvmOptionsList.append('\n'); - } - -// if (exportPlatform == PConstants.MACOSX) { -// // If no bits specified (libs are all universal, or no native libs) -// // then exportBits will be 0, and can be controlled via "Get Info". -// // Otherwise, need to specify the bits as a VM option. -// if (exportBits == 32) { -// runOptions += " -d32"; -// } else if (exportBits == 64) { -// runOptions += " -d64"; -// } -// } /// macosx: write out Info.plist (template for classpath, etc) if (exportPlatform == PConstants.MACOSX) { - //String PLIST_TEMPLATE = "template.plist"; + StringBuilder runOptionsXML = new StringBuilder(); + for (String opt : runOptions) { + runOptionsXML.append(" "); + runOptionsXML.append(opt); + runOptionsXML.append(""); + runOptionsXML.append('\n'); + } + String PLIST_TEMPLATE = "Info.plist.tmpl"; File plistTemplate = new File(sketch.getFolder(), PLIST_TEMPLATE); if (!plistTemplate.exists()) { - //plistTemplate = mode.getContentFile("application/template.plist"); - plistTemplate = mode.getContentFile("application/Info.plist.tmpl"); + plistTemplate = mode.getContentFile("application/" + PLIST_TEMPLATE); } File plistFile = new File(dotAppFolder, "Contents/Info.plist"); PrintWriter pw = PApplet.createWriter(plistFile); @@ -1502,7 +1496,7 @@ public class JavaBuild { } while ((index = sb.indexOf("@@jvm_options_list@@")) != -1) { sb.replace(index, index + "@@jvm_options_list@@".length(), - jvmOptionsList.toString()); + runOptionsXML.toString()); } while ((index = sb.indexOf("@@sketch@@")) != -1) { sb.replace(index, index + "@@sketch@@".length(), @@ -1537,16 +1531,100 @@ public class JavaBuild { pw.close(); } else if (exportPlatform == PConstants.WINDOWS) { - File argsFile = new File(destFolder + "/lib/args.txt"); - PrintWriter pw = PApplet.createWriter(argsFile); +// File buildFile = new File(destFolder + "build.xml"); +// PrintWriter pw = PApplet.createWriter(buildFile); + +// StringBuilder runOptionsXML = new StringBuilder(); +// for (String opt : runOptions) { +// runOptionsXML.append(" "); +// runOptionsXML.append(opt); +// runOptionsXML.append(""); +// runOptionsXML.append('\n'); +// } - // Since this is only on Windows, make sure we use Windows CRLF - pw.print(PApplet.join(runOptions.toArray(new String[0]), " ") + "\r\n"); - pw.print(sketch.getName() + "\r\n"); - pw.print(exportClassPath); + XML project = new XML("project"); + //project.setString("default", "windows"); + XML target = project.addChild("target"); + target.setString("name", "windows"); + + XML taskdef = target.addChild("taskdef"); + taskdef.setString("name", "launch4j"); + taskdef.setString("classname", "net.sf.launch4j.ant.Launch4jTask"); + //pw.println(" classpath=\"${launch4j.dir}/launch4j/launch4j.jar:launch4j/lib/xstream.jar\" />"); + String launchPath = mode.getContentFile("application/launch4j").getAbsolutePath(); + taskdef.setString("classpath", launchPath + "/launch4j.jar:" + launchPath + "/lib/xstream.jar"); + +// pw.println(""); +// +// pw.println(""); - pw.flush(); - pw.close(); + // + // + + // + // + +// pw.println(""); +// pw.println(" "); + + // http://launch4j.sourceforge.net/docs.html#Ant_task +// +// +// +// +// something.jar +// something2.jar +// +// +// -Xmx512M +// +// +// +// +// +// + + XML launch4j = target.addChild("launch4j"); + XML config = launch4j.addChild("config"); + config.setString("headerType", "gui"); + File exeFile = new File(destFolder, sketch.getName() + ".exe"); + config.setString("outfile", exeFile.getAbsolutePath()); + config.setString("dontWrapJar", "true"); + config.setString("jarPath", jarList[0]); + + XML clazzPath = config.addChild("classPath"); + clazzPath.setString("mainClass", sketch.getName()); + for (int i = 1; i < jarList.length; i++) { + String jarName = jarList[i]; + clazzPath.addChild("cp").setContent(jarName); + } + XML jre = config.addChild("jre"); + jre.setString("minVersion", "1.7.0_40"); + //PApplet.join(runOptions.toArray(new String[0]), " ") + for (String opt : runOptions) { + jre.addChild("opt").setContent(opt); + } + + File buildFile = new File(destFolder + "build.xml"); + project.save(buildFile); + buildWindowsLauncher(buildFile, "windows"); +// PrintWriter pw = PApplet.createWriter(buildFile); + +// File argsFile = new File(destFolder + "/lib/args.txt"); +// PrintWriter pw = PApplet.createWriter(argsFile); +// +// // Since this is only on Windows, make sure we use Windows CRLF +// pw.print(PApplet.join(runOptions.toArray(new String[0]), " ") + "\r\n"); +// pw.print(sketch.getName() + "\r\n"); +// pw.print(exportClassPath); +// +// pw.flush(); +// pw.close(); } else { File shellScript = new File(destFolder, sketch.getName()); @@ -1619,7 +1697,80 @@ public class JavaBuild { } - protected void addManifest(ZipOutputStream zos) throws IOException { + protected boolean buildWindowsLauncher(File buildFile, String target) { + //System.setProperty("user.dir", tmpFolder.getAbsolutePath()); // oh why not { because it doesn't help } + final Project p = new Project(); + //p.setBaseDir(tmpFolder); // doesn't seem to do anything + +// System.out.println(tmpFolder.getAbsolutePath()); +// p.setUserProperty("user.dir", tmpFolder.getAbsolutePath()); + String path = buildFile.getAbsolutePath().replace('\\', '/'); + p.setUserProperty("ant.file", path); + + // deals with a problem where javac error messages weren't coming through + p.setUserProperty("build.compiler", "extJavac"); + // p.setUserProperty("build.compiler.emacs", "true"); // does nothing + + // try to spew something useful to the console + final DefaultLogger consoleLogger = new DefaultLogger(); + consoleLogger.setErrorPrintStream(System.err); + consoleLogger.setOutputPrintStream(System.out); // ? uncommented before + // WARN, INFO, VERBOSE, DEBUG + // consoleLogger.setMessageOutputLevel(Project.MSG_ERR); + consoleLogger.setMessageOutputLevel(Project.MSG_INFO); +// consoleLogger.setMessageOutputLevel(Project.MSG_DEBUG); + p.addBuildListener(consoleLogger); + + // This logger is used to pick up javac errors to be parsed into + // SketchException objects. Note that most errors seem to show up on stdout + // since that's where the [javac] prefixed lines are coming through. + final DefaultLogger errorLogger = new DefaultLogger(); + final ByteArrayOutputStream errb = new ByteArrayOutputStream(); + final PrintStream errp = new PrintStream(errb); + errorLogger.setErrorPrintStream(errp); + final ByteArrayOutputStream outb = new ByteArrayOutputStream(); + final PrintStream outp = new PrintStream(outb); + errorLogger.setOutputPrintStream(outp); + errorLogger.setMessageOutputLevel(Project.MSG_INFO); + // errorLogger.setMessageOutputLevel(Project.MSG_DEBUG); + p.addBuildListener(errorLogger); + + try { + //editor.statusNotice("Building sketch for Android..."); + p.fireBuildStarted(); + p.init(); + final ProjectHelper helper = ProjectHelper.getProjectHelper(); + p.addReference("ant.projectHelper", helper); + helper.parse(p, buildFile); + // p.executeTarget(p.getDefaultTarget()); + p.executeTarget(target); +// editor.statusNotice("Finished building sketch."); + return true; + + } catch (final BuildException e) { + // Send a "build finished" event to the build listeners for this project. + p.fireBuildFinished(e); + + // PApplet.println(new String(errb.toByteArray())); + // PApplet.println(new String(outb.toByteArray())); + + // String errorOutput = new String(errb.toByteArray()); + // String[] errorLines = + // errorOutput.split(System.getProperty("line.separator")); + // PApplet.println(errorLines); + + //final String outPile = new String(outb.toByteArray()); + //antBuildProblems(new String(outb.toByteArray()) + String out = new String(outb.toByteArray()); + String err = new String(errb.toByteArray()); + System.out.println(out); + System.err.println(err); + } + return false; + } + + + protected void addManifest(ZipOutputStream zos) throws IOException { ZipEntry entry = new ZipEntry("META-INF/MANIFEST.MF"); zos.putNextEntry(entry); diff --git a/core/src/processing/data/XML.java b/core/src/processing/data/XML.java index 5860eafc2..27ce09342 100644 --- a/core/src/processing/data/XML.java +++ b/core/src/processing/data/XML.java @@ -260,6 +260,11 @@ public class XML implements Serializable { // } + public boolean save(File file) { + return save(file, null); + } + + public boolean save(File file, String options) { PrintWriter writer = PApplet.createWriter(file); boolean result = write(writer);