module lang::java::Compiler
rascal-Not specified
Provides access to the JDK javac compiler, to compile (generated) Java code.
Usage
import lang::java::Compiler;
Dependencies
extend Message;
import IO;
import Location;
import String;
import util::FileSystem;
import util::PathConfig;
import util::Reflective;
import util::UUID;
Benefits
- Compile any Java code, stored anywhere reachable through a
locand using any library reachable through aloc, to JVM bytecode using the standard JDK compiler.
Pitfalls
- If you are looking for Java analysis and transformation support in Rascal please go find the java-air package. The current module only provides a Java to bytecode compilation API.
function compileJava
Compile all the .java files in source folders in PathConfig
list[Message] compileJava(PathConfig pcfg)
See Compile Java Source Folders for more information.
function compileJavaSourceFile
Compile a single Java source file
list[Message] compileJavaSourceFile(loc file, loc bin, list[loc] srcs, list[loc] libs=[])
Pitfalls
filehas to be reachable fromsrcs, because a fully qualified class name is computing by relativizing the source filelocagainst thesrcsfolders.- The source files is read using Read File.
- All classfiles, which could be many in the case of anonymous or nested classes, are written directly to the
binfolder. libsis typically a list ofjar+file:///ormvn:///locations, one for each (transitive) compile-time dependency. Without these the compiler will complain about missing symbols and return error messages.
function compileJavaSourceFolders
Compile all java source files from a list of source folders.
list[Message] compileJavaSourceFolders(list[loc] srcFolders, loc bin, list[loc] libs=[])
- Qualified class names are obtained by relativizing against the source folders.
- Source code is read in using Read File.
- Bytecode files are written directly into the
binfolder
function compileJava
Call the Java compiler on a list of files, reading in their contents first and computing their qualified names
list[Message] compileJava(list[loc] sources, loc bin, list[loc] srcs=[], list[loc] libs=[])
function compileJava
Main workhorse for compiling Java source code
list[Message] compileJava(rel[loc fileName, str qualifiedName, str sourceCode] sources, loc bin, list[loc] libs=[])
Benefits
- Use in memory cache to optimize compiling a lot of files at once
- Can work with any kind of source loc or target loc
Pitfalls
- The sources relation must match the right file name to the right source code, for accurate error messages.
- The sources relation must give the right qualified name to the right source code, otherwise the compilation fails.
- While
compileJavais running all source code and all generated bytecode will be in memory; this can be significant. if you need to use less memory then callcompileJavaseveral times with a smaller relation.
function qualifiedName
computes the packageName.className fully qualified class name from a source filename /.../src/packageName/className.java
str qualifiedName(loc path, list[loc] srcs)
Tests
test compilerInputOutputFileTest
test bool compilerInputOutputFileTest() {
root = uuid()[scheme="memory"];
target = root + "target";
writeFile(root + "A.java", "class A { }");
writeFile(root + "B.java", "class B extends A { }");
writeFile(root + "pack/C.java", "package pack; \npublic class C { }");
writeFile(root + "pack/pack/D.java", "package pack.pack; \nclass D extends pack.C { }");
errors = compileJavaSourceFolders([root], target);
assert errors == [] : "unexpected errors: <errors>";
return find(target, "class")
== {
target + "pack/C.class",
target + "pack/pack/D.class",
target + "B.class",
target + "A.class"
};
}
test compilerClasspathTest
test bool compilerClasspathTest() {
root = uuid()[scheme="memory"];
target = root + "target";
writeFile(root + "A.java", "class A { org.rascalmpl.uri.URIResolverRegistry reg = org.rascalmpl.uri.URIResolverRegistry.getInstance(); }");
rascalLib = resolvedCurrentRascalJar();
errors = compileJavaSourceFolders([root], target, libs=[rascalLib]);
assert errors == [] : "no errors expected: <errors>";
return find(target,"class") == {target + "A.class"};
}