Add ability to create runnable jar file from lua script with sample build file build-app.xml

This commit is contained in:
James Roseborough
2012-10-02 07:00:17 +00:00
parent 497a9f2346
commit 7b6381c352
13 changed files with 182 additions and 22 deletions

View File

@@ -62,14 +62,6 @@ public class LuaFunction extends LuaValue {
return s_metatable;
}
/** Hook for implementations such as LuaJC to load the environment of the main chunk
* into the first upvalue location. If the function has no upvalues or is not a main chunk,
* calling this will be no effect.
* @param env The environment to load into the first upvalue, if there is one.
*/
public void initupvalue1(LuaValue env) {
}
public String tojstring() {
return "function: " + classnamestub();
}

View File

@@ -3524,6 +3524,13 @@ public class LuaValue extends Varargs {
return invoke(args);
}
/** Hook for implementations such as LuaJC to load the environment of the main chunk
* into the first upvalue location. If the function has no upvalues or is not a main chunk,
* calling this will be no effect.
* @param env The environment to load into the first upvalue, if there is one.
*/
public void initupvalue1(LuaValue env) {}
/** Varargs implemenation with no values.
* <p>
* This is an internal class not intended to be used directly.

View File

@@ -24,6 +24,7 @@ package org.luaj.vm2.lib;
import java.io.InputStream;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
@@ -306,6 +307,8 @@ public class PackageLib extends OneArgFunction {
try {
c = Class.forName(classname);
v = (LuaValue) c.newInstance();
if (v.isfunction())
((LuaFunction)v).initupvalue1(globals);
return v;
} catch ( ClassNotFoundException cnfe ) {
return valueOf("\n\tno class '"+classname+"'" );

View File

@@ -46,6 +46,7 @@ import org.luaj.vm2.Varargs;
* @see ThreeArgFunction
*/
abstract public class VarArgFunction extends LibFunction {
public VarArgFunction() {
}

View File

@@ -37,7 +37,7 @@ import org.luaj.vm2.luajc.LuaJC;
* Compiler for lua files to compile lua sources or lua binaries into java classes.
*/
public class luajc {
private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org";
private static final String version = Lua._VERSION + " Copyright (C) 2012 luaj.org";
private static final String usage =
"usage: java -cp luaj-jse.jar,bcel-5.2.jar luajc [options] fileordir [, fileordir ...]\n" +
@@ -46,6 +46,7 @@ public class luajc {
" -s src source directory\n" +
" -d dir destination directory\n" +
" -p pkg package prefix to apply to all classes\n" +
" -m generate main(String[]) function for JSE\n" +
" -r recursively compile all\n" +
" -l load classes to verify generated bytecode\n" +
" -v verbose\n";
@@ -57,6 +58,7 @@ public class luajc {
private String srcdir = null;
private String destdir = null;
private boolean genmain = false;
private boolean recurse = false;
private boolean verbose = false;
private boolean loadclasses = false;
@@ -96,6 +98,9 @@ public class luajc {
usageExit();
pkgprefix = args[i];
break;
case 'm':
genmain = true;
break;
case 'r':
recurse = true;
break;
@@ -113,7 +118,7 @@ public class luajc {
if ( verbose ) {
System.out.println(version);
System.out.println("srcdir: "+srcdir);
System.out.println("destdir: "+srcdir);
System.out.println("destdir: "+destdir);
System.out.println("files: "+seeds);
System.out.println("recurse: "+recurse);
}
@@ -192,7 +197,7 @@ public class luajc {
// create the chunk
FileInputStream fis = new FileInputStream( inf.infile );
final Hashtable t = LuaJC.getInstance().compileAll(fis, inf.luachunkname, inf.srcfilename);
final Hashtable t = LuaJC.getInstance().compileAll(fis, inf.luachunkname, inf.srcfilename, genmain);
fis.close();
// write out the chunk

View File

@@ -25,6 +25,7 @@ import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.Bit32Lib;
import org.luaj.vm2.lib.CoroutineLib;
@@ -120,4 +121,22 @@ public class JsePlatform {
_G.load(new DebugLib());
return _G;
}
/** Simple wrapper for invoking a lua function with command line arguments.
* The supplied function is first given a new Globals object,
* then the program is run with arguments.
*/
public static void luaMain(LuaValue mainChunk, String[] args) {
Globals g = standardGlobals();
int n = args.length;
LuaValue[] vargs = new LuaValue[args.length];
for (int i = 0; i < n; ++i)
vargs[i] = LuaValue.valueOf(args[i]);
LuaTable arg = LuaValue.listOf(vargs);
arg.set("n", n);
g.set("arg", arg);
mainChunk.initupvalue1(g);
mainChunk.invoke(LuaValue.varargsOf(vargs));
}
}

View File

@@ -77,6 +77,7 @@ public class JavaBuilder {
private static final String STR_LUATABLE = LuaTable.class.getName();
private static final String STR_BUFFER = Buffer.class.getName();
private static final String STR_STRING = String.class.getName();
private static final String STR_JSEPLATFORM = "org.luaj.vm2.lib.jse.JsePlatform";
private static final ObjectType TYPE_VARARGS = new ObjectType(STR_VARARGS);
private static final ObjectType TYPE_LUAVALUE = new ObjectType(STR_LUAVALUE);
@@ -86,10 +87,11 @@ public class JavaBuilder {
private static final ObjectType TYPE_LUABOOLEAN = new ObjectType(STR_LUABOOLEAN);
private static final ObjectType TYPE_LUATABLE = new ObjectType(STR_LUATABLE);
private static final ObjectType TYPE_BUFFER = new ObjectType(STR_BUFFER);
private static final ObjectType TYPE_STRING = new ObjectType(STR_STRING);
private static final ArrayType TYPE_LOCALUPVALUE = new ArrayType( TYPE_LUAVALUE, 1 );
private static final ArrayType TYPE_CHARARRAY = new ArrayType( Type.CHAR, 1 );
private static final ArrayType TYPE_LUAVALUEARRAY = new ArrayType( TYPE_LUAVALUE, 1 );
private static final ArrayType TYPE_STRINGARRAY = new ArrayType( TYPE_STRING, 1 );
private static final String STR_FUNCV = VarArgFunction.class.getName();
@@ -116,6 +118,8 @@ public class JavaBuilder {
private static final Type[] ARG_TYPES_INT_INT = { Type.INT, Type.INT };
private static final Type[] ARG_TYPES_LUAVALUE = { TYPE_LUAVALUE };
private static final Type[] ARG_TYPES_BUFFER = { TYPE_BUFFER };
private static final Type[] ARG_TYPES_STRINGARRAY = { TYPE_STRINGARRAY };
private static final Type[] ARG_TYPES_LUAVALUE_STRINGARRAY = { TYPE_LUAVALUE, TYPE_STRINGARRAY };
// names, arg types for main prototype classes
private static final String[] SUPER_NAME_N = { STR_FUNC0, STR_FUNC1, STR_FUNC2, STR_FUNC3, STR_FUNCV, };
@@ -257,7 +261,7 @@ public class JavaBuilder {
}
}
public byte[] completeClass() {
public byte[] completeClass(boolean genmain) {
// add class initializer
if ( ! init.isEmpty() ) {
@@ -303,6 +307,26 @@ public class JavaBuilder {
main.dispose();
}
// add main function so class is invokable from the java command line
if (genmain) {
MethodGen mg = new MethodGen( Constants.ACC_PUBLIC | Constants.ACC_STATIC, // access flags
Type.VOID, // return type
ARG_TYPES_STRINGARRAY, // argument types
new String[] { "arg" }, // arg names
"main",
classname, // method, defining class
main, cp);
append(factory.createNew(classname));
append(InstructionConstants.DUP);
append(factory.createInvoke(classname, Constants.CONSTRUCTOR_NAME, Type.VOID, ARG_TYPES_NONE, Constants.INVOKESPECIAL));
append(new ALOAD(0));
append(factory.createInvoke(STR_JSEPLATFORM, "luaMain", Type.VOID, ARG_TYPES_LUAVALUE_STRINGARRAY, Constants.INVOKESTATIC));
append(InstructionConstants.RETURN);
mg.setMaxStack();
cg.addMethod(mg.getMethod());
main.dispose();
}
// convert to class bytes
try {

View File

@@ -37,11 +37,11 @@ public class JavaGen {
public final byte[] bytecode;
public final JavaGen[] inners;
public JavaGen( Prototype p, String classname, String filename ) {
this( new ProtoInfo(p,classname), classname, filename );
public JavaGen( Prototype p, String classname, String filename, boolean genmain ) {
this( new ProtoInfo(p,classname), classname, filename, genmain );
}
private JavaGen( ProtoInfo pi, String classname, String filename ) {
private JavaGen( ProtoInfo pi, String classname, String filename, boolean genmain ) {
this.classname = classname;
// build this class
@@ -51,14 +51,14 @@ public class JavaGen {
LocVars l = pi.prototype.locvars[i];
builder.setVarStartEnd(i, l.startpc, l.endpc, l.varname.tojstring());
}
this.bytecode = builder.completeClass();
this.bytecode = builder.completeClass(genmain);
// build sub-prototypes
if ( pi.subprotos != null ) {
int n = pi.subprotos.length;
inners = new JavaGen[n];
for ( int i=0; i<n; i++ )
inners[i] = new JavaGen(pi.subprotos[i], closureName(classname,i), filename);
inners[i] = new JavaGen(pi.subprotos[i], closureName(classname,i), filename, false);
} else {
inners = null;
}

View File

@@ -36,7 +36,7 @@ public class JavaLoader extends ClassLoader {
}
public LuaFunction load( Prototype p, String classname, String filename, LuaValue env ) {
JavaGen jg = new JavaGen( p, classname, filename );
JavaGen jg = new JavaGen( p, classname, filename, false );
return load( jg, env );
}

View File

@@ -79,12 +79,12 @@ public class LuaJC implements LuaCompiler {
public LuaJC() {
}
public Hashtable compileAll(InputStream script, String chunkname, String filename) throws IOException {
public Hashtable compileAll(InputStream script, String chunkname, String filename, boolean genmain) throws IOException {
String classname = toStandardJavaClassName( chunkname );
String luaname = toStandardLuaFileName( filename );
Hashtable h = new Hashtable();
Prototype p = LuaC.instance.compile(script, classname);
JavaGen gen = new JavaGen(p, classname, luaname);
JavaGen gen = new JavaGen(p, classname, luaname, genmain);
insert( h, gen );
return h;
}