Skip to main content

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 loc and using any library reachable through a loc, 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

  • file has to be reachable from srcs, because a fully qualified class name is computing by relativizing the source file loc against the srcs folders.
  • 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 bin folder.
  • libs is typically a list of jar+file:/// or mvn:/// 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 bin folder

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 compileJava is running all source code and all generated bytecode will be in memory; this can be significant. if you need to use less memory then call compileJava several 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"};
}