module compiler: initial working version
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
<target name="jarRT" depends="compileRT">
|
||||
<jar destfile="${output}/kotlin-runtime.jar">
|
||||
<fileset dir="${output}/classes/runtime"/>
|
||||
<fileset dir="${basedir}/stdlib/ktSrc"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class GeneratedClassLoader extends ClassLoader {
|
||||
private final ClassFileFactory state;
|
||||
|
||||
public GeneratedClassLoader(ClassFileFactory state) {
|
||||
super(GeneratedClassLoader.class.getClassLoader());
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String file = name.replace('.', '/') + ".class";
|
||||
if (state.files().contains(file)) {
|
||||
byte[] bytes = state.asBytes(file);
|
||||
return defineClass(name, bytes, 0, bytes.length);
|
||||
}
|
||||
return super.findClass(name);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
<orderEntry type="module" module-name="backend" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="stdlib" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -2,14 +2,16 @@ package org.jetbrains.jet.cli;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Processor;
|
||||
import com.sampullara.cli.Args;
|
||||
import com.sampullara.cli.Argument;
|
||||
import jet.modules.IModuleBuilder;
|
||||
import jet.modules.IModuleSetBuilder;
|
||||
import org.jetbrains.jet.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.GeneratedClassLoader;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.plugin.JetMainDetector;
|
||||
|
||||
@@ -17,6 +19,7 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.List;
|
||||
@@ -66,9 +69,19 @@ public class KotlinCompiler {
|
||||
if (unpackedRuntimePath != null) {
|
||||
environment.addToClasspath(unpackedRuntimePath);
|
||||
}
|
||||
else {
|
||||
final File runtimeJarPath = getRuntimeJarPath();
|
||||
if (runtimeJarPath != null && runtimeJarPath.exists()) {
|
||||
environment.addToClasspath(runtimeJarPath);
|
||||
}
|
||||
else {
|
||||
System.out.println("No runtime library found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.module != null) {
|
||||
compileModule(environment, arguments.module);
|
||||
compileModuleScript(environment, arguments.module);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -98,30 +111,82 @@ public class KotlinCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
private static void compileModule(JetCoreEnvironment environment, String moduleFile) {
|
||||
final FileIndexFacade instance = FileIndexFacade.getInstance(environment.getProject());
|
||||
VirtualFile jetObject = environment.getLocalFileSystem().findFileByPath(KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class").getPath());
|
||||
instance.isInLibraryClasses(jetObject);
|
||||
|
||||
CompileSession moduleCompileSession = new CompileSession(environment);
|
||||
moduleCompileSession.addSources(moduleFile);
|
||||
private static void compileModuleScript(JetCoreEnvironment environment, String moduleFile) {
|
||||
CompileSession scriptCompileSession = new CompileSession(environment);
|
||||
scriptCompileSession.addSources(moduleFile);
|
||||
|
||||
URL url = KotlinCompiler.class.getClassLoader().getResource("ModuleBuilder.kt");
|
||||
if (url != null) {
|
||||
// TODO
|
||||
String path = url.getPath();
|
||||
if (path.startsWith("file:")) {
|
||||
path = path.substring(5);
|
||||
}
|
||||
final VirtualFile vFile = environment.getJarFileSystem().findFileByPath(path);
|
||||
if (vFile == null) {
|
||||
System.out.println("Couldn't load ModuleBuilder.kt from runtime jar: "+ url);
|
||||
return;
|
||||
}
|
||||
scriptCompileSession.addSources(vFile);
|
||||
}
|
||||
else {
|
||||
// building from source
|
||||
final String homeDirectory = getHomeDirectory();
|
||||
final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt");
|
||||
moduleCompileSession.addSources(environment.getLocalFileSystem().findFileByPath(file.getPath()));
|
||||
|
||||
scriptCompileSession.addSources(environment.getLocalFileSystem().findFileByPath(file.getPath()));
|
||||
}
|
||||
|
||||
if (!scriptCompileSession.analyze()) {
|
||||
return;
|
||||
}
|
||||
final ClassFileFactory factory = scriptCompileSession.generate();
|
||||
|
||||
final IModuleSetBuilder moduleSetBuilder = runDefineModules(moduleFile, factory);
|
||||
|
||||
for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) {
|
||||
compileModule(environment, moduleBuilder, new File(moduleFile).getParent());
|
||||
}
|
||||
}
|
||||
|
||||
private static IModuleSetBuilder runDefineModules(String moduleFile, ClassFileFactory factory) {
|
||||
GeneratedClassLoader loader = new GeneratedClassLoader(factory);
|
||||
try {
|
||||
Class moduleSetBuilderClass = loader.loadClass("kotlin.modules.ModuleSetBuilder");
|
||||
final IModuleSetBuilder moduleSetBuilder = (IModuleSetBuilder) moduleSetBuilderClass.newInstance();
|
||||
|
||||
Class namespaceClass = loader.loadClass("namespace");
|
||||
final Method[] methods = namespaceClass.getMethods();
|
||||
boolean modulesDefined = false;
|
||||
for (Method method : methods) {
|
||||
if (method.getName().equals("defineModules")) {
|
||||
method.invoke(null, moduleSetBuilder);
|
||||
modulesDefined = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!modulesDefined) {
|
||||
System.out.println("Module script " + moduleFile + " must define a defineModules() method");
|
||||
return null;
|
||||
}
|
||||
return moduleSetBuilder;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void compileModule(JetCoreEnvironment environment, IModuleBuilder moduleBuilder, String directory) {
|
||||
CompileSession moduleCompileSession = new CompileSession(environment);
|
||||
for (String sourceFile : moduleBuilder.getSourceFiles()) {
|
||||
moduleCompileSession.addSources(new File(directory, sourceFile).getPath());
|
||||
}
|
||||
for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
|
||||
environment.addToClasspath(new File(classpathRoot));
|
||||
}
|
||||
if (!moduleCompileSession.analyze()) {
|
||||
return;
|
||||
}
|
||||
final ClassFileFactory factory = moduleCompileSession.generate();
|
||||
ClassFileFactory factory = moduleCompileSession.generate();
|
||||
writeToJar(factory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true);
|
||||
}
|
||||
|
||||
private static String getHomeDirectory() {
|
||||
|
||||
@@ -88,7 +88,7 @@ public abstract class CodegenTestCase extends JetLiteFixture {
|
||||
|
||||
protected String blackBox() throws Exception {
|
||||
ClassFileFactory codegens = generateClassesInFile();
|
||||
CodegensClassLoader loader = new CodegensClassLoader(codegens);
|
||||
GeneratedClassLoader loader = new GeneratedClassLoader(codegens);
|
||||
|
||||
final JetNamespace namespace = myFile.getRootNamespace();
|
||||
String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", ".");
|
||||
@@ -215,23 +215,4 @@ public abstract class CodegenTestCase extends JetLiteFixture {
|
||||
return super.loadClass(name);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CodegensClassLoader extends ClassLoader {
|
||||
private final ClassFileFactory state;
|
||||
|
||||
public CodegensClassLoader(ClassFileFactory state) {
|
||||
super(CodegenTestCase.class.getClassLoader());
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String file = name.replace('.', '/') + ".class";
|
||||
if (state.files().contains(file)) {
|
||||
byte[] bytes = state.asBytes(file);
|
||||
return defineClass(name, bytes, 0, bytes.length);
|
||||
}
|
||||
return super.findClass(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,16 @@ namespace modules {
|
||||
import java.util.*
|
||||
import jet.modules.*
|
||||
|
||||
class ModuleSetBuilder() {
|
||||
val modules: ArrayList<ModuleBuilder> = ArrayList<ModuleBuilder>()
|
||||
class ModuleSetBuilder(): IModuleSetBuilder {
|
||||
val modules: ArrayList<IModuleBuilder?> = ArrayList<IModuleBuilder?>()
|
||||
|
||||
fun module(name: String, callback: fun ModuleBuilder.()) {
|
||||
val builder = ModuleBuilder(name)
|
||||
builder.callback()
|
||||
modules.add(builder)
|
||||
}
|
||||
|
||||
override fun getModules(): List<IModuleBuilder?>? = modules
|
||||
}
|
||||
|
||||
class SourcesBuilder(val parent: ModuleBuilder) {
|
||||
@@ -46,6 +49,7 @@ class ModuleBuilder(val name: String): IModuleBuilder {
|
||||
|
||||
override fun getSourceFiles(): List<String?>? = sourceFiles
|
||||
override fun getClasspathRoots(): List<String?>? = classpathRoots
|
||||
override fun getModuleName(): String? = name
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public interface IModuleBuilder {
|
||||
String getModuleName();
|
||||
List<String> getSourceFiles();
|
||||
List<String> getClasspathRoots();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package jet.modules;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public interface IModuleSetBuilder {
|
||||
List<IModuleBuilder> getModules();
|
||||
}
|
||||
Reference in New Issue
Block a user