diff --git a/build.xml b/build.xml
index c5a74ee9208..bc0ee63e9f7 100644
--- a/build.xml
+++ b/build.xml
@@ -29,6 +29,7 @@
+
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedClassLoader.java b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedClassLoader.java
new file mode 100644
index 00000000000..b851b21a8a0
--- /dev/null
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedClassLoader.java
@@ -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);
+ }
+}
diff --git a/compiler/cli/cli.iml b/compiler/cli/cli.iml
index de82ce75e19..ed2341d3d46 100644
--- a/compiler/cli/cli.iml
+++ b/compiler/cli/cli.iml
@@ -10,6 +10,7 @@
+
diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java
index e391db30564..7f047272fe2 100644
--- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java
+++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java
@@ -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() {
diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java
index 8b0bb54a270..e6ec1009270 100644
--- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java
+++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java
@@ -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);
- }
- }
}
diff --git a/stdlib/ktSrc/ModuleBuilder.kt b/stdlib/ktSrc/ModuleBuilder.kt
index 2f90dcb1158..7e2e25e8715 100644
--- a/stdlib/ktSrc/ModuleBuilder.kt
+++ b/stdlib/ktSrc/ModuleBuilder.kt
@@ -5,13 +5,16 @@ namespace modules {
import java.util.*
import jet.modules.*
-class ModuleSetBuilder() {
- val modules: ArrayList = ArrayList()
+class ModuleSetBuilder(): IModuleSetBuilder {
+ val modules: ArrayList = ArrayList()
fun module(name: String, callback: fun ModuleBuilder.()) {
val builder = ModuleBuilder(name)
builder.callback()
+ modules.add(builder)
}
+
+ override fun getModules(): List? = modules
}
class SourcesBuilder(val parent: ModuleBuilder) {
@@ -46,6 +49,7 @@ class ModuleBuilder(val name: String): IModuleBuilder {
override fun getSourceFiles(): List? = sourceFiles
override fun getClasspathRoots(): List? = classpathRoots
+ override fun getModuleName(): String? = name
}
}
\ No newline at end of file
diff --git a/stdlib/src/jet/modules/IModuleBuilder.java b/stdlib/src/jet/modules/IModuleBuilder.java
index 53ac51123c6..c845e04a021 100644
--- a/stdlib/src/jet/modules/IModuleBuilder.java
+++ b/stdlib/src/jet/modules/IModuleBuilder.java
@@ -6,6 +6,7 @@ import java.util.List;
* @author yole
*/
public interface IModuleBuilder {
+ String getModuleName();
List getSourceFiles();
List getClasspathRoots();
}
diff --git a/stdlib/src/jet/modules/IModuleSetBuilder.java b/stdlib/src/jet/modules/IModuleSetBuilder.java
new file mode 100644
index 00000000000..7f5f03dc3d2
--- /dev/null
+++ b/stdlib/src/jet/modules/IModuleSetBuilder.java
@@ -0,0 +1,10 @@
+package jet.modules;
+
+import java.util.List;
+
+/**
+ * @author yole
+ */
+public interface IModuleSetBuilder {
+ List getModules();
+}