Return-Path: Mailing-List: contact ant-dev-help@jakarta.apache.org; run by ezmlm Delivered-To: mailing list ant-dev@jakarta.apache.org Received: (qmail 47713 invoked from network); 17 Feb 2000 19:49:12 -0000 Received: from ux4.sp.cs.cmu.edu (128.2.198.104) by locus.apache.org with SMTP; 17 Feb 2000 19:49:12 -0000 Received: from TURTLE.CORAL.CS.CMU.EDU by ux4.sp.cs.cmu.edu id aa28030; 17 Feb 2000 14:48 EST Date: Thu, 17 Feb 2000 14:48:21 -0500 From: William Uther To: ant-dev@jakarta.apache.org Subject: MakeExectuable task definition Message-ID: <8432322.3159787701@turtle.coral.cs.cmu.edu> Originator-Info: login-id=will; server=postoffice.srv.cs.cmu.edu X-Mailer: Mulberry (MacOS) [1.4.4, s/n S-100002] MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="==========08449242==========" --==========08449242========== Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline Hi all, I've attached an ant task definition that people might find useful. It creates simple execuables for java programs. At the moment it only handles mac and unix. The Mac executable is a double-clickable app (requires MRJ 2.2 or later). The Unix executable is a simple shell-script. Here is how I build my ant executable (yeah, I use a Mac entry-point. Using org.apache.tools.ant.Main would be fine on a command-line system.): later, \x/ill :-} Here is a description of the options. It can handle most of the command-line options of the 'java' command: System: Tells the task what type of executable to build. Currently accepts either "mac" or "unix". Defaults to the current system. Output: The path of the executable to be generated. Main: The main class of the executable. Parameters: A string containing command line parameters to be passed to the main class. Classpath: The argument for the -classpath option. Currently this is parsed and the paths are made absolute. Might want to change this behaviour in future. Stdout: A filename to direct stdout to. Stdoutappend: A boolean. Should stdout append or replace. Only has meaning if stdout is defined. Stderr and Stderrappend: As for Stdout and Stdoutappend but for stderr :). Stdin: A file to read input from. Verificationall: a boolean. If true sets bytecode verification to all. If false sets bytcode verification to the VM default. Verificationnone: a boolean. If true sets bytecode verification to none. If false sets bytcode verification to the VM default. Verificationremote: a boolean. If true sets bytecode verification to remote classes only. If false sets bytcode verification to the VM default. Jitc: a boolean. Should the jit be enabled? This allows control of the -nojit option. Useful for debugging. Gcmin: Specify an argument for the -ms option. Gcmax: Specify an agrument for the -mx option. Asyncgc: a boolean. Controls Asynchronous garbage collection. Like the -noasyncgc option. Classgc: a boolean. Controls GC of Class instances. Like the -noclassgc option. Verbose: a boolean. Controls verbose class loading. Like the -verbose option. Properties: A comma separated list of properties. Each property in this list is read from the current property list and its definition is added to executable. Like the -D option. Mergeresourcefile: This is a Mac specific option that allows Mac resource files to be merged with the App. --==========08449242========== Content-Type: text/plain; charset=us-ascii; name="MakeExecutable.java" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="MakeExecutable.java"; size=18186 /* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.*; import java.io.*; import java.util.*; import java.lang.reflect.*; /** * Creates an executable script. This is platform dependant. It might be nice to * put Install Anywhere support in at some point. * * At the moment this will generate a Mac executable on a Mac (with MRJ 2.2 or * higher installed). It will generate a Unix shell on a non-mac system. * Someone want to put in a windows .bat file generator? * * @author William Uther will+ant@cs.cmu.edu */ public class MakeExecutable extends Task { static final int VERIFICATION_DEFAULT = 0; static final int VERIFICATION_NONE = 1; static final int VERIFICATION_REMOTE = 2; static final int VERIFICATION_ALL = 3; static final int JITC_DEFAULT = 0; static final int JITC_ENABLED = 1; static final int JITC_DISABLED = 2; static final int ASYNCGC_DEFAULT = 0; static final int ASYNCGC_ENABLED = 1; static final int ASYNCGC_DISABLED = 2; static final int CLASSGC_DEFAULT = 0; static final int CLASSGC_ENABLED = 1; static final int CLASSGC_DISABLED = 2; static final int VERBOSE_DEFAULT = 0; static final int VERBOSE_ENABLED = 1; static final int VERBOSE_DISABLED = 2; static final int SYSTEM_DEFAULT = 0; static final int SYSTEM_MAC = 1; static final int SYSTEM_UNIX = 2; int system = SYSTEM_DEFAULT; String output; String mainClass = "Main"; String classpath = null; String parameters = null; String stdout = null; boolean stdOutAppend = false; String stderr = null; boolean stdErrAppend = false; String stdin = null; int verificationLevel = VERIFICATION_DEFAULT; int jitc = JITC_DEFAULT; String GCMin = null; String GCMax = null; int ASyncGC = ASYNCGC_DEFAULT; int classGC = CLASSGC_DEFAULT; int verbose = VERBOSE_DEFAULT; String propertyNameList = null; File resourceFile = null; public void setSystem(String systemName) { if ("mac".equalsIgnoreCase(systemName)) { system = SYSTEM_MAC; } else if ("unix".equalsIgnoreCase(systemName)) { system = SYSTEM_UNIX; } } public void setOutput(String fileName) { output = project.translatePath(fileName); } public void setMain(String className) { mainClass = className; } public void setParameters(String parameters) { this.parameters = parameters; } public void setClasspath(String classpath) { StringTokenizer st = new StringTokenizer(classpath, ":"); StringBuffer newClassPath = new StringBuffer(classpath.length()); while (st.hasMoreTokens()) { String thisPath = st.nextToken(); File thisFile = project.resolveFile(project.translatePath(thisPath)); newClassPath.append(thisFile.getAbsolutePath()); if (st.hasMoreTokens()) { newClassPath.append(thisFile.pathSeparator); } } this.classpath = newClassPath.toString(); } public void setStdout(String filename) { stdout = project.translatePath(filename); } public void setStdoutappend(String appendString) { stdOutAppend = Project.toBoolean(appendString); } public void setStderr(String filename) { stderr = project.translatePath(filename); } public void setStderrappend(String appendString) { stdErrAppend = Project.toBoolean(appendString); } public void setStdin(String filename) { stdin = project.translatePath(filename); } public void setVerificationall(String verificationString) { if (verificationString == null || verificationString == "" || Project.toBoolean(verificationString)) verificationLevel = VERIFICATION_ALL; else verificationLevel = VERIFICATION_DEFAULT; } public void setVerificationnone(String verificationString) { if (verificationString == null || verificationString == "" || Project.toBoolean(verificationString)) verificationLevel = VERIFICATION_NONE; else verificationLevel = VERIFICATION_DEFAULT; } public void setVerificationremote(String verificationString) { if (verificationString == null || verificationString == "" || Project.toBoolean(verificationString)) verificationLevel = VERIFICATION_REMOTE; else verificationLevel = VERIFICATION_DEFAULT; } public void setJitc(String jitcString) { if (jitcString == null || jitcString == "" || Project.toBoolean(jitcString)) jitc = JITC_ENABLED; else jitc = JITC_DISABLED; } public void setGcmin(String GCMin) { this.GCMin = GCMin; } public void setGcmax(String GCMax) { this.GCMax = GCMax; } public void setAsyncgc(String ayncGCString) { if (ayncGCString == null || ayncGCString == "" || Project.toBoolean(ayncGCString)) ASyncGC = ASYNCGC_ENABLED; else ASyncGC = ASYNCGC_DISABLED; } public void setClassgc(String classGCString) { if (classGCString == null || classGCString == "" || Project.toBoolean(classGCString)) classGC = CLASSGC_ENABLED; else classGC = CLASSGC_DISABLED; } public void setVerbose(String verboseString) { if (verboseString == null || verboseString == "" || Project.toBoolean(verboseString)) verbose = VERBOSE_ENABLED; else verbose = VERBOSE_DISABLED; } public void setProperties(String propertyNameList) { this.propertyNameList = propertyNameList; } public void setMergeresourcefile(String resourceFile) { this.resourceFile = project.resolveFile(project.translatePath(resourceFile)); } /** * Does the work. * * @exception BuildException if someting goes wrong with the build */ public void execute() throws BuildException { File outFile = project.resolveFile(output); if (system == SYSTEM_DEFAULT) { if (System.getProperty("os.name").startsWith("Mac")) system = SYSTEM_MAC; else system = SYSTEM_UNIX; } switch (system) { case SYSTEM_MAC: { if (!System.getProperty("os.name").startsWith("Mac")) throw new BuildException("Unable to make Mac executable on non-Mac system. Sorry."); String MRJversion = System.getProperty("mrj.version"); float version = 0; if (MRJversion != null) { try { version = Float.valueOf(MRJversion).floatValue(); } catch (NumberFormatException ignore) { } } if (version < 2.2) { throw new BuildException("Unable to make Mac executable with MRJ version < 2.2."); } project.log("Creating Mac executable: " + outFile.getPath()); Properties p = new Properties(); p.put("com.apple.mrj.application.main",mainClass); if (classpath != null) p.put("com.apple.mrj.application.classpath",classpath); if (parameters != null) p.put("com.apple.mrj.application.parameters",parameters); if (stdout != null) { p.put("com.apple.mrj.application.stdout",stdout); if (stdOutAppend) p.put("com.apple.mrj.application.stdout.append","true"); } if (stderr != null) { p.put("com.apple.mrj.application.stderr",stderr); if (stdErrAppend) p.put("com.apple.mrj.application.stderr.append","true"); } if (stdin != null) { p.put("com.apple.mrj.application.stdin",stdin); } switch (verificationLevel) { case VERIFICATION_DEFAULT: break; case VERIFICATION_NONE: p.put("com.apple.mrj.application.verify","none"); break; case VERIFICATION_REMOTE: p.put("com.apple.mrj.application.verify","remote"); break; case VERIFICATION_ALL: p.put("com.apple.mrj.application.verify","all"); break; } switch (jitc) { case JITC_DEFAULT: break; case JITC_ENABLED: p.put("com.apple.mrj.application.jitc.disable","false"); break; case JITC_DISABLED: p.put("com.apple.mrj.application.jitc.disable","true"); break; } if (GCMin != null) p.put("com.apple.mrj.application.gc.min",GCMin); if (GCMax != null) p.put("com.apple.mrj.application.gc.max",GCMax); switch (ASyncGC) { case ASYNCGC_DEFAULT: break; case ASYNCGC_ENABLED: p.put("com.apple.mrj.application.gc.async","true"); break; case ASYNCGC_DISABLED: p.put("com.apple.mrj.application.gc.async","false"); break; } switch (classGC) { case CLASSGC_DEFAULT: break; case CLASSGC_ENABLED: p.put("com.apple.mrj.application.gc.classes","true"); break; case CLASSGC_DISABLED: p.put("com.apple.mrj.application.gc.classes","false"); break; } switch (verbose) { case VERBOSE_DEFAULT: break; case VERBOSE_ENABLED: p.put("com.apple.mrj.application.classloading.verbose","true"); break; case VERBOSE_DISABLED: p.put("com.apple.mrj.application.classloading.verbose","false"); break; } if (propertyNameList != null) { StringTokenizer st = new StringTokenizer(propertyNameList,","); while (st.hasMoreTokens()) { String name = st.nextToken(); String property = project.getProperty(name); if (property != null) { p.put(name, property); } } } // I'm doing all the Mac calls dynamically so this will compile on non-Mac systems /* com.apple.mrj.tools.MRJAppBuilder builder = new com.apple.mrj.tools.MRJAppBuilder(); builder.reset(); builder.setConfigProperties(p); if (resourceFile != null) builder.addResourceFileToVFS(resourceFile); try { builder.createApplication(outFile); } catch (IOException e) { throw new BuildException("I/O Error creating executable: " + e.getMessage()); } */ try { Class builderClass = Class.forName("com.apple.mrj.tools.MRJAppBuilder"); Object builder = builderClass.newInstance(); Method resetMethod = builderClass.getMethod("reset", new Class[0]); Method setConfigPropertiesMethod = builderClass.getMethod("setConfigProperties", new Class[] {p.getClass()}); Method addResourceMethod = builderClass.getMethod("addResourceFileToVFS", new Class[] {resourceFile.getClass()}); Method CreateAppMethod = builderClass.getMethod("createApplication", new Class[] {outFile.getClass()}); resetMethod.invoke(builder, new Object[0]); setConfigPropertiesMethod.invoke(builder, new Object[] {p}); if (resourceFile != null) addResourceMethod.invoke(builder, new Object[] {resourceFile}); CreateAppMethod.invoke(builder, new Object[] {outFile}); } catch (ClassNotFoundException e) { throw new BuildException("ClassNotFoundException: " + e.getMessage()); } catch (InstantiationException e) { throw new BuildException("InstantiationException: " + e.getMessage()); } catch (IllegalAccessException e) { throw new BuildException("IllegalAccessException: " + e.getMessage()); } catch (NoSuchMethodException e) { throw new BuildException("NoSuchMethodException: " + e.getMessage()); } catch (SecurityException e) { throw new BuildException("SecurityException: " + e.getMessage()); } catch (IllegalArgumentException e) { throw new BuildException("IllegalArgumentException: " + e.getMessage()); } catch (InvocationTargetException e) { Throwable ex = e.getTargetException(); throw new BuildException("InvocationTargetException: " + ex.getMessage()); } } break; case SYSTEM_UNIX: { project.log("Creating UNIX shell script: " + outFile.getAbsolutePath()); StringBuffer commandLine = new StringBuffer(); String cmd = project.getProperty("java.command"); if (cmd == null) cmd = "java"; commandLine.append(cmd); if (classpath != null) { commandLine.append(" "); commandLine.append("-classpath"); commandLine.append(" "); commandLine.append(classpath); } switch (verificationLevel) { case VERIFICATION_DEFAULT: break; case VERIFICATION_NONE: commandLine.append(" -noverify"); break; case VERIFICATION_REMOTE: commandLine.append(" -verifyremote"); break; case VERIFICATION_ALL: commandLine.append(" -verify"); break; } switch (jitc) { case JITC_DEFAULT: break; case JITC_ENABLED: break; case JITC_DISABLED: commandLine.append(" -nojit"); break; } if (GCMin != null) { commandLine.append(" -ms"); commandLine.append(GCMin); } if (GCMax != null) { commandLine.append(" -mx"); commandLine.append(GCMax); } switch (ASyncGC) { case ASYNCGC_DEFAULT: break; case ASYNCGC_ENABLED: break; case ASYNCGC_DISABLED: commandLine.append(" -noasyncgc"); break; } switch (classGC) { case CLASSGC_DEFAULT: break; case CLASSGC_ENABLED: break; case CLASSGC_DISABLED: commandLine.append(" -noclassgc"); break; } switch (verbose) { case VERBOSE_DEFAULT: break; case VERBOSE_ENABLED: commandLine.append(" -verbose"); break; case VERBOSE_DISABLED: break; } if (propertyNameList != null) { StringTokenizer st = new StringTokenizer(propertyNameList,","); while (st.hasMoreTokens()) { String name = st.nextToken(); String property = project.getProperty(name); if (property != null) { commandLine.append(" -D"); commandLine.append(name); commandLine.append("="); commandLine.append(property); } } } commandLine.append(" "); commandLine.append(mainClass); if (parameters != null) { commandLine.append(" "); commandLine.append(parameters); } commandLine.append(" $@"); // allow the user to append their own parameters if (stdout != null) { if (stdOutAppend) commandLine.append(" >>"); else commandLine.append(" >"); commandLine.append(stdout); } if (stderr != null) { if (stdErrAppend) commandLine.append(" 2>>"); else commandLine.append(" 2>"); commandLine.append(stderr); } if (stdin != null) { commandLine.append(" <"); commandLine.append(stdin); } PrintWriter out = null; try { out = new PrintWriter(new FileWriter(outFile)); out.println("#!/bin/sh"); out.println(); out.println(commandLine.toString()); } catch (IOException e) { throw new BuildException("I/O Error creating executable " + output); } finally { if (out != null) out.close(); } try { Runtime.getRuntime().exec("chmod +x " + output); } catch (IOException e) { // log, but don't fail project.log("I/O Error in: chmod +x " + output); } } break; default: throw new BuildException("Unknown system type."); } } } --==========08449242==========--