diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java new file mode 100644 index 00000000000..607bad3bd4e --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -0,0 +1,311 @@ +package org.jetbrains.jet.compiler; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Processor; +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; + +import java.io.*; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; +import java.util.jar.*; + +/** + * The environment for compiling a bunch of source files or + * + * @author yole + */ +public class CompileEnvironment { + private JetCoreEnvironment myEnvironment; + private final Disposable myRootDisposable; + private PrintStream myErrorStream = System.out; + + public CompileEnvironment() { + myRootDisposable = new Disposable() { + @Override + public void dispose() { + } + }; + myEnvironment = new JetCoreEnvironment(myRootDisposable); + } + + public void setMyErrorStream(PrintStream errorStream) { + myErrorStream = errorStream; + } + + public void dispose() { + Disposer.dispose(myRootDisposable); + } + + public boolean initializeKotlinRuntime() { + final File unpackedRuntimePath = getUnpackedRuntimePath(); + if (unpackedRuntimePath != null) { + myEnvironment.addToClasspath(unpackedRuntimePath); + } + else { + final File runtimeJarPath = getRuntimeJarPath(); + if (runtimeJarPath != null && runtimeJarPath.exists()) { + myEnvironment.addToClasspath(runtimeJarPath); + } + else { + return false; + } + } + return true; + } + + public static File getUnpackedRuntimePath() { + URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class"); + if (url != null && url.getProtocol().equals("file")) { + return new File(url.getPath()).getParentFile().getParentFile(); + } + return null; + } + + public static File getRuntimeJarPath() { + URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class"); + if (url != null && url.getProtocol().equals("jar")) { + String path = url.getPath(); + return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/"))); + } + return null; + } + + public void setJavaRuntime(File rtJarPath) { + myEnvironment.addToClasspath(rtJarPath); + } + + public static File findActiveRtJar() { + ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); + if (systemClassLoader instanceof URLClassLoader) { + URLClassLoader loader = (URLClassLoader) systemClassLoader; + for (URL url: loader.getURLs()) { + if("file".equals(url.getProtocol())) { + if(url.getFile().endsWith("/lib/rt.jar")) { + return new File(url.getFile()); + } + if(url.getFile().endsWith("/Classes/classes.jar")) { + return new File(url.getFile()).getAbsoluteFile(); + } + } + } + } + return null; + } + + public void compileModuleScript(String moduleFile) { + final IModuleSetBuilder moduleSetBuilder = loadModuleScript(moduleFile); + if (moduleSetBuilder == null) { + return; + } + + final String directory = new File(moduleFile).getParent(); + for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) { + ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory); + writeToJar(moduleFactory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true); + } + } + + public IModuleSetBuilder loadModuleScript(String moduleFile) { + CompileSession scriptCompileSession = new CompileSession(myEnvironment); + scriptCompileSession.addSources(moduleFile); + + URL url = CompileEnvironment.class.getClassLoader().getResource("ModuleBuilder.kt"); + if (url != null) { + String path = url.getPath(); + if (path.startsWith("file:")) { + path = path.substring(5); + } + final VirtualFile vFile = myEnvironment.getJarFileSystem().findFileByPath(path); + if (vFile == null) { + throw new CompileEnvironmentException("Couldn't load ModuleBuilder.kt from runtime jar: "+ url); + } + scriptCompileSession.addSources(vFile); + } + else { + // building from source + final String homeDirectory = getHomeDirectory(); + final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt"); + scriptCompileSession.addSources(myEnvironment.getLocalFileSystem().findFileByPath(file.getPath())); + } + + if (!scriptCompileSession.analyze(myErrorStream)) { + return null; + } + final ClassFileFactory factory = scriptCompileSession.generate(); + + return runDefineModules(moduleFile, factory); + } + + 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) { + throw new CompileEnvironmentException("Module script " + moduleFile + " must define a defineModules() method"); + } + return moduleSetBuilder; + } catch (Exception e) { + throw new CompileEnvironmentException(e); + } + } + + public ClassFileFactory compileModule(IModuleBuilder moduleBuilder, String directory) { + CompileSession moduleCompileSession = new CompileSession(myEnvironment); + for (String sourceFile : moduleBuilder.getSourceFiles()) { + moduleCompileSession.addSources(new File(directory, sourceFile).getPath()); + } + for (String classpathRoot : moduleBuilder.getClasspathRoots()) { + myEnvironment.addToClasspath(new File(classpathRoot)); + } + if (!moduleCompileSession.analyze(myErrorStream)) { + return null; + } + return moduleCompileSession.generate(); + } + + private static String getHomeDirectory() { + return new File(PathManager.getResourceRoot(CompileEnvironment.class, "/org/jetbrains/jet/compiler/CompileEnvironment.class")).getParentFile().getParentFile().getParent(); + } + + public static void writeToJar(ClassFileFactory factory, String jar, String mainClass, boolean includeRuntime) { + try { + Manifest manifest = new Manifest(); + final Attributes mainAttributes = manifest.getMainAttributes(); + mainAttributes.putValue("Manifest-Version", "1.0"); + mainAttributes.putValue("Created-By", "JetBrains Kotlin"); + if (mainClass != null) { + mainAttributes.putValue("Main-Class", mainClass); + } + FileOutputStream fos = new FileOutputStream(jar); + JarOutputStream stream = new JarOutputStream(fos, manifest); + try { + for (String file : factory.files()) { + stream.putNextEntry(new JarEntry(file)); + stream.write(factory.asBytes(file)); + } + if (includeRuntime) { + writeRuntimeToJar(stream); + } + } + finally { + stream.close(); + fos.close(); + } + + } catch (IOException e) { + throw new CompileEnvironmentException("Failed to generate jar file", e); + } + } + + private static void writeRuntimeToJar(final JarOutputStream stream) throws IOException { + final File unpackedRuntimePath = getUnpackedRuntimePath(); + if (unpackedRuntimePath != null) { + FileUtil.processFilesRecursively(unpackedRuntimePath, new Processor() { + @Override + public boolean process(File file) { + if (file.isDirectory()) return true; + final String relativePath = FileUtil.getRelativePath(unpackedRuntimePath, file); + try { + stream.putNextEntry(new JarEntry(FileUtil.toSystemIndependentName(relativePath))); + FileInputStream fis = new FileInputStream(file); + try { + FileUtil.copy(fis, stream); + } finally { + fis.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return true; + } + }); + } + else { + File runtimeJarPath = getRuntimeJarPath(); + if (runtimeJarPath != null) { + JarInputStream jis = new JarInputStream(new FileInputStream(runtimeJarPath)); + try { + while (true) { + JarEntry e = jis.getNextJarEntry(); + if (e == null) { + break; + } + if (FileUtil.getExtension(e.getName()).equals("class")) { + stream.putNextEntry(e); + FileUtil.copy(jis, stream); + } + } + } finally { + jis.close(); + } + } + else { + throw new CompileEnvironmentException("Couldn't find runtime library"); + } + } + } + + public void compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir) { + CompileSession session = new CompileSession(myEnvironment); + session.addSources(sourceFileOrDir); + + String mainClass = null; + for (JetNamespace namespace : session.getSourceFileNamespaces()) { + if (JetMainDetector.hasMain(namespace.getDeclarations())) { + mainClass = namespace.getFQName() + ".namespace"; + break; + } + } + if (!session.analyze(myErrorStream)) { + return; + } + + ClassFileFactory factory = session.generate(); + if (jar != null) { + writeToJar(factory, jar, mainClass, true); + } + else if (outputDir != null) { + writeToOutputDirectory(factory, outputDir); + } + else { + throw new CompileEnvironmentException("Output directory or jar file is not specified - no files will be saved to the disk"); + } + } + + private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) { + List files = factory.files(); + for (String file : files) { + File target = new File(outputDir, file); + try { + FileUtil.writeToFile(target, factory.asBytes(file)); + } catch (IOException e) { + throw new CompileEnvironmentException(e); + } + } + } + +} diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironmentException.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironmentException.java new file mode 100644 index 00000000000..0962b68160e --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironmentException.java @@ -0,0 +1,18 @@ +package org.jetbrains.jet.compiler; + +/** + * @author yole + */ +public class CompileEnvironmentException extends RuntimeException { + public CompileEnvironmentException(String message) { + super(message); + } + + public CompileEnvironmentException(Throwable cause) { + super(cause); + } + + public CompileEnvironmentException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/compiler/cli/src/org/jetbrains/jet/cli/CompileSession.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java similarity index 93% rename from compiler/cli/src/org/jetbrains/jet/cli/CompileSession.java rename to compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java index 120a431fe08..c166906ed87 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/CompileSession.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.cli; +package org.jetbrains.jet.compiler; import com.google.common.base.Predicates; import com.intellij.openapi.vfs.VirtualFile; @@ -15,10 +15,13 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; import org.jetbrains.jet.plugin.JetFileType; +import java.io.PrintStream; import java.util.ArrayList; import java.util.List; /** + * The session which handles analyzing and compiling a single module. + * * @author yole */ public class CompileSession { @@ -73,10 +76,10 @@ public class CompileSession { return mySourceFileNamespaces; } - public boolean analyze() { + public boolean analyze(final PrintStream out) { if (!myErrors.isEmpty()) { for (String error : myErrors) { - System.out.println(error); + out.println(error); } return false; } @@ -85,7 +88,7 @@ public class CompileSession { allNamespaces.addAll(myLibrarySourceFileNamespaces); myBindingContext = instance.analyzeNamespaces(myEnvironment.getProject(), allNamespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); ErrorCollector errorCollector = new ErrorCollector(myBindingContext); - errorCollector.report(); + errorCollector.report(out); return !errorCollector.hasErrors; } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/ErrorCollector.java b/compiler/backend/src/org/jetbrains/jet/compiler/ErrorCollector.java similarity index 84% rename from compiler/cli/src/org/jetbrains/jet/cli/ErrorCollector.java rename to compiler/backend/src/org/jetbrains/jet/compiler/ErrorCollector.java index 1da315a1b80..18573bede15 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/ErrorCollector.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/ErrorCollector.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.cli; +package org.jetbrains.jet.compiler; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; @@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange; import org.jetbrains.jet.lang.diagnostics.Severity; import org.jetbrains.jet.lang.resolve.BindingContext; +import java.io.PrintStream; import java.util.Collection; /** @@ -36,14 +37,14 @@ class ErrorCollector { } } - void report() { + void report(final PrintStream out) { if(!maps.isEmpty()) { for (PsiFile psiFile : maps.keySet()) { - System.out.println(psiFile.getVirtualFile().getPath()); + out.println(psiFile.getVirtualFile().getPath()); Collection diagnosticWithTextRanges = maps.get(psiFile); for (DiagnosticWithTextRange diagnosticWithTextRange : diagnosticWithTextRanges) { String position = DiagnosticUtils.formatPosition(diagnosticWithTextRange); - System.out.println("\t" + diagnosticWithTextRange.getSeverity().toString() + ": " + position + " " + diagnosticWithTextRange.getMessage()); + out.println("\t" + diagnosticWithTextRange.getSeverity().toString() + ": " + position + " " + diagnosticWithTextRange.getMessage()); } } } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 7f047272fe2..22a1f6bc346 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -1,29 +1,11 @@ package org.jetbrains.jet.cli; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.PathManager; -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; +import org.jetbrains.jet.compiler.CompileEnvironment; +import org.jetbrains.jet.compiler.CompileEnvironmentException; 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; -import java.util.jar.*; /** * @author yole @@ -54,273 +36,35 @@ public class KotlinCompiler { return; } - Disposable root = new Disposable() { - @Override - public void dispose() { - } - }; - JetCoreEnvironment environment = new JetCoreEnvironment(root); + CompileEnvironment environment = new CompileEnvironment(); File rtJar = initJdk(); if (rtJar == null) return; - environment.addToClasspath(rtJar); - final File unpackedRuntimePath = getUnpackedRuntimePath(); - if (unpackedRuntimePath != null) { - environment.addToClasspath(unpackedRuntimePath); - } - else { - final File runtimeJarPath = getRuntimeJarPath(); - if (runtimeJarPath != null && runtimeJarPath.exists()) { - environment.addToClasspath(runtimeJarPath); - } - else { + try { + environment.setJavaRuntime(rtJar); + if (!environment.initializeKotlinRuntime()) { System.out.println("No runtime library found"); return; } - } - if (arguments.module != null) { - compileModuleScript(environment, arguments.module); - return; - } - - CompileSession session = new CompileSession(environment); - session.addSources(arguments.src); - - String mainClass = null; - for (JetNamespace namespace : session.getSourceFileNamespaces()) { - if (JetMainDetector.hasMain(namespace.getDeclarations())) { - mainClass = namespace.getFQName() + ".namespace"; - break; - } - } - if (!session.analyze()) { - return; - } - - ClassFileFactory factory = session.generate(); - if (arguments.jar != null) { - writeToJar(factory, arguments.jar, mainClass, true); - } - else if (arguments.outputDir != null) { - writeToOutputDirectory(factory, arguments.outputDir); - } - else { - System.out.println("Output directory or jar file is not specified - no files will be saved to the disk"); - } - } - - 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) { - 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); + if (arguments.module != null) { + environment.compileModuleScript(arguments.module); return; } - scriptCompileSession.addSources(vFile); - } - else { - // building from source - final String homeDirectory = getHomeDirectory(); - final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt"); - 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; - } - ClassFileFactory factory = moduleCompileSession.generate(); - writeToJar(factory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true); - } - - private static String getHomeDirectory() { - return new File(PathManager.getResourceRoot(KotlinCompiler.class, "/org/jetbrains/jet/cli/KotlinCompiler.class")).getParentFile().getParentFile().getParent(); - } - - private static void writeToJar(ClassFileFactory factory, String jar, String mainClass, boolean includeRuntime) { - try { - Manifest manifest = new Manifest(); - final Attributes mainAttributes = manifest.getMainAttributes(); - mainAttributes.putValue("Manifest-Version", "1.0"); - mainAttributes.putValue("Created-By", "JetBrains Kotlin"); - if (mainClass != null) { - mainAttributes.putValue("Main-Class", mainClass); - } - FileOutputStream fos = new FileOutputStream(jar); - JarOutputStream stream = new JarOutputStream(fos, manifest); - try { - for (String file : factory.files()) { - stream.putNextEntry(new JarEntry(file)); - stream.write(factory.asBytes(file)); - } - if (includeRuntime) { - writeRuntimeToJar(stream); - } - } - finally { - stream.close(); - fos.close(); - } - - } catch (IOException e) { - System.out.println("Failed to generate jar file: " + e.getMessage()); - } - } - - private static File getUnpackedRuntimePath() { - URL url = KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class"); - if (url != null && url.getProtocol().equals("file")) { - return new File(url.getPath()).getParentFile().getParentFile(); - } - return null; - } - - private static File getRuntimeJarPath() { - URL url = KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class"); - if (url != null && url.getProtocol().equals("jar")) { - String path = url.getPath(); - return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/"))); - } - return null; - } - - private static void writeRuntimeToJar(final JarOutputStream stream) throws IOException { - final File unpackedRuntimePath = getUnpackedRuntimePath(); - if (unpackedRuntimePath != null) { - FileUtil.processFilesRecursively(unpackedRuntimePath, new Processor() { - @Override - public boolean process(File file) { - if (file.isDirectory()) return true; - final String relativePath = FileUtil.getRelativePath(unpackedRuntimePath, file); - try { - stream.putNextEntry(new JarEntry(FileUtil.toSystemIndependentName(relativePath))); - FileInputStream fis = new FileInputStream(file); - try { - FileUtil.copy(fis, stream); - } finally { - fis.close(); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - return true; - } - }); - } - else { - File runtimeJarPath = getRuntimeJarPath(); - if (runtimeJarPath != null) { - JarInputStream jis = new JarInputStream(new FileInputStream(runtimeJarPath)); - try { - while (true) { - JarEntry e = jis.getNextJarEntry(); - if (e == null) { - break; - } - if (FileUtil.getExtension(e.getName()).equals("class")) { - stream.putNextEntry(e); - FileUtil.copy(jis, stream); - } - } - } finally { - jis.close(); - } - } else { - System.out.println("Couldn't find runtime library"); - } - } - } - - private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) { - List files = factory.files(); - for (String file : files) { - File target = new File(outputDir, file); - try { - FileUtil.writeToFile(target, factory.asBytes(file)); - System.out.println("Generated classfile: " + target); - } catch (IOException e) { - System.out.println(e.getMessage()); + environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir); } + } catch (CompileEnvironmentException e) { + System.out.println(e.getMessage()); } } private static File initJdk() { String javaHome = System.getenv("JAVA_HOME"); - File rtJar = null; + File rtJar; if (javaHome == null) { - ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); - if(systemClassLoader instanceof URLClassLoader) { - URLClassLoader loader = (URLClassLoader) systemClassLoader; - for(URL url: loader.getURLs()) { - if("file".equals(url.getProtocol())) { - if(url.getFile().endsWith("/lib/rt.jar")) { - rtJar = new File(url.getFile()); - break; - } - if(url.getFile().endsWith("/Classes/classes.jar")) { - rtJar = new File(url.getFile()).getAbsoluteFile(); - break; - } - } - } - } + rtJar = CompileEnvironment.findActiveRtJar(); if(rtJar == null) { System.out.println("JAVA_HOME environment variable needs to be defined"); diff --git a/compiler/testData/compiler/smoke/Smoke.kt b/compiler/testData/compiler/smoke/Smoke.kt new file mode 100644 index 00000000000..6da801d1fde --- /dev/null +++ b/compiler/testData/compiler/smoke/Smoke.kt @@ -0,0 +1,4 @@ +namespace Smoke + +fun main(args: Array) { +} diff --git a/compiler/testData/compiler/smoke/Smoke.kts b/compiler/testData/compiler/smoke/Smoke.kts new file mode 100644 index 00000000000..6cdcff74a64 --- /dev/null +++ b/compiler/testData/compiler/smoke/Smoke.kts @@ -0,0 +1,8 @@ +import kotlin.modules.ModuleSetBuilder + +fun ModuleSetBuilder.defineModules() { + module("smoke") { + source files "Smoke.kt" + jar name System.getProperty("java.io.tmpdir") + "/smoke.jar" + } +} diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java new file mode 100644 index 00000000000..a7981989cdf --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileEnvironmentTest.java @@ -0,0 +1,25 @@ +package org.jetbrains.jet.compiler; + +import jet.modules.IModuleBuilder; +import jet.modules.IModuleSetBuilder; +import junit.framework.TestCase; +import org.jetbrains.jet.codegen.ClassFileFactory; +import org.jetbrains.jet.parsing.JetParsingTest; + +/** + * @author yole + */ +public class CompileEnvironmentTest extends TestCase { + public void testSmoke() { + CompileEnvironment environment = new CompileEnvironment(); + environment.setJavaRuntime(CompileEnvironment.findActiveRtJar()); + environment.initializeKotlinRuntime(); + final String testDataDir = JetParsingTest.getTestDataDir() + "/compiler/smoke/"; + final IModuleSetBuilder setBuilder = environment.loadModuleScript(testDataDir + "Smoke.kts"); + assertEquals(1, setBuilder.getModules().size()); + final IModuleBuilder moduleBuilder = setBuilder.getModules().get(0); + final ClassFileFactory factory = environment.compileModule(moduleBuilder, testDataDir); + assertNotNull(factory); + assertNotNull(factory.asBytes("Smoke/namespace.class")); + } +} diff --git a/stdlib/ktSrc/ModuleBuilder.kt b/stdlib/ktSrc/ModuleBuilder.kt index 7e2e25e8715..bee397cbb56 100644 --- a/stdlib/ktSrc/ModuleBuilder.kt +++ b/stdlib/ktSrc/ModuleBuilder.kt @@ -29,9 +29,16 @@ class ClasspathBuilder(val parent: ModuleBuilder) { } } +class JarBuilder(val parent: ModuleBuilder) { + fun name(jarName: String) { + parent.setJarName(jarName) + } +} + class ModuleBuilder(val name: String): IModuleBuilder { val sourceFiles: ArrayList = ArrayList() val classpathRoots: ArrayList = ArrayList() + var _jarName: String? = null val source: SourcesBuilder get() = SourcesBuilder(this) @@ -39,6 +46,9 @@ class ModuleBuilder(val name: String): IModuleBuilder { val classpath: ClasspathBuilder get() = ClasspathBuilder(this) + val jar: JarBuilder + get() = JarBuilder(this) + fun addSourceFiles(pattern: String) { sourceFiles.add(pattern) } @@ -47,9 +57,13 @@ class ModuleBuilder(val name: String): IModuleBuilder { classpathRoots.add(name) } + fun setJarName(name: String) { + _jarName = name + } + override fun getSourceFiles(): List? = sourceFiles override fun getClasspathRoots(): List? = classpathRoots override fun getModuleName(): String? = name -} + override fun getJarName(): String? = _jarName } \ No newline at end of file diff --git a/stdlib/src/jet/modules/IModuleBuilder.java b/stdlib/src/jet/modules/IModuleBuilder.java index c845e04a021..f455eb5fabc 100644 --- a/stdlib/src/jet/modules/IModuleBuilder.java +++ b/stdlib/src/jet/modules/IModuleBuilder.java @@ -9,4 +9,5 @@ public interface IModuleBuilder { String getModuleName(); List getSourceFiles(); List getClasspathRoots(); + String getJarName(); }