diff --git a/ant/ant.iml b/ant/ant.iml index 50e8f687d41..4548c995447 100644 --- a/ant/ant.iml +++ b/ant/ant.iml @@ -7,11 +7,7 @@ - - - - - + \ No newline at end of file diff --git a/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JsTask.kt b/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JsTask.kt index c75dbf28907..b499b089891 100644 --- a/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JsTask.kt +++ b/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JsTask.kt @@ -17,13 +17,10 @@ package org.jetbrains.jet.buildtools.ant import org.apache.tools.ant.types.Path -import org.jetbrains.jet.cli.common.arguments.K2JSCompilerArguments -import org.jetbrains.jet.cli.js.K2JSCompiler import java.io.File -public class Kotlin2JsTask : KotlinCompilerBaseTask() { - override val arguments = K2JSCompilerArguments() - override val compiler = K2JSCompiler() +public class Kotlin2JsTask : KotlinCompilerBaseTask() { + override val compilerFqName = "org.jetbrains.jet.cli.js.K2JSCompiler" public var library: Path? = null public var outputPrefix: File? = null @@ -48,19 +45,31 @@ public class Kotlin2JsTask : KotlinCompilerBaseTask() { } override fun fillSpecificArguments() { - arguments.outputFile = output!!.canonicalPath - - arguments.noStdlib = noStdlib + args.add("-output") + args.add(output!!.canonicalPath) // TODO: write test library?.let { - arguments.libraryFiles = it.list().map { File(it).canonicalPath }.copyToArray() + args.add("-library-files") + args.add(it.list().map { File(it).canonicalPath }.join(separator = ",")) } - arguments.outputPrefix = outputPrefix?.canonicalPath - arguments.outputPostfix = outputPostfix?.canonicalPath + outputPrefix?.let { + args.add("-output-prefix") + args.add(it.canonicalPath) + } - arguments.main = main - arguments.sourceMap = sourceMap + outputPostfix?.let { + args.add("-output-postfix") + args.add(it.canonicalPath) + } + + main?.let { + args.add("-main") + args.add(it) + } + + if (noStdlib) args.add("-no-stdlib") + if (sourceMap) args.add("-source-map") } } diff --git a/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JvmTask.kt b/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JvmTask.kt index 6585934c330..cdfdd5d7dad 100644 --- a/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JvmTask.kt +++ b/ant/src/org/jetbrains/jet/buildtools/ant/Kotlin2JvmTask.kt @@ -18,14 +18,11 @@ package org.jetbrains.jet.buildtools.ant import org.apache.tools.ant.types.Path import org.apache.tools.ant.types.Reference -import org.jetbrains.jet.cli.jvm.K2JVMCompiler -import org.jetbrains.jet.cli.common.arguments.K2JVMCompilerArguments import java.io.File import java.io.File.pathSeparator -public class Kotlin2JvmTask : KotlinCompilerBaseTask() { - override val arguments = K2JVMCompilerArguments() - override val compiler = K2JVMCompiler() +public class Kotlin2JvmTask : KotlinCompilerBaseTask() { + override val compilerFqName = "org.jetbrains.jet.cli.jvm.K2JVMCompiler" public var externalAnnotations: Path? = null public var includeRuntime: Boolean = true @@ -60,21 +57,27 @@ public class Kotlin2JvmTask : KotlinCompilerBaseTask() { } override fun fillSpecificArguments() { - arguments.destination = output!!.canonicalPath + args.add("-d") + args.add(output!!.canonicalPath) val classpath = arrayListOf() compileClasspath?.let { classpath.addAll(it.list()) } - arguments.freeArgs?.forEach { + src!!.list().forEach { val file = File(it) if (file.isDirectory() || file.extension != "kt") { classpath.add(it) } } - arguments.classpath = classpath.join(pathSeparator) + args.add("-classpath") + args.add(classpath.join(pathSeparator)) - arguments.annotations = externalAnnotations?.list()?.join(pathSeparator) - arguments.noStdlib = noStdlib - arguments.includeRuntime = includeRuntime + externalAnnotations?.let { + args.add("-annotations") + args.add(it.list().join(pathSeparator)) + } + + if (noStdlib) args.add("-no-stdlib") + if (includeRuntime) args.add("-include-runtime") } } diff --git a/ant/src/org/jetbrains/jet/buildtools/ant/KotlinCompilerBaseTask.kt b/ant/src/org/jetbrains/jet/buildtools/ant/KotlinCompilerBaseTask.kt index 11cd18a0061..178457c9b8d 100644 --- a/ant/src/org/jetbrains/jet/buildtools/ant/KotlinCompilerBaseTask.kt +++ b/ant/src/org/jetbrains/jet/buildtools/ant/KotlinCompilerBaseTask.kt @@ -21,22 +21,49 @@ import org.apache.tools.ant.types.Path import org.apache.tools.ant.types.Reference import java.io.File import org.apache.tools.ant.BuildException -import org.jetbrains.jet.cli.common.ExitCode -import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.jet.cli.common.CLICompiler import org.apache.tools.ant.types.Commandline -import com.sampullara.cli.Args -import org.jetbrains.jet.cli.common.messages.PrintingMessageCollector -import org.jetbrains.jet.cli.common.messages.MessageRenderer -import org.jetbrains.jet.config.Services +import java.io.PrintStream +import org.apache.tools.ant.AntClassLoader +import java.lang.ref.SoftReference +import org.apache.tools.ant.Project +import java.net.JarURLConnection + +object CompilerClassLoaderHolder { + private var classLoaderRef = SoftReference(null) + + synchronized fun getOrCreateClassLoader(project: Project?): ClassLoader { + val cached = classLoaderRef.get() + if (cached != null) return cached + + val myLoader = javaClass.getClassLoader() + if (myLoader !is AntClassLoader) return myLoader + + // Find path of kotlin-ant.jar in the filesystem and find kotlin-compiler.jar in the same directory + val resourcePath = "/" + javaClass.getName().replace('.', '/') + ".class" + val jarConnection = javaClass.getResource(resourcePath).openConnection() as? JarURLConnection + ?: throw UnsupportedOperationException("Kotlin compiler Ant task should be loaded from the JAR file") + val antTaskJarPath = File(jarConnection.getJarFileURL().toURI()) + + val compilerJarPath = File(antTaskJarPath.getParent(), "kotlin-compiler.jar") + if (!compilerJarPath.exists()) { + throw IllegalStateException("kotlin-compiler.jar is not found in the directory of Kotlin Ant task") + } + + val classLoader = AntClassLoader(myLoader, project, Path(project, compilerJarPath.path), /* parentFirst = */ false) + classLoaderRef = SoftReference(classLoader) + + return classLoader + } +} /** * Base class for Kotlin compiler Ant tasks. * http://evgeny-goldin.org/javadoc/ant/tutorial-writing-tasks.html */ -public abstract class KotlinCompilerBaseTask : Task() { - protected abstract val arguments: T - protected abstract val compiler: CLICompiler +public abstract class KotlinCompilerBaseTask : Task() { + protected abstract val compilerFqName: String + + protected val args: MutableList = arrayListOf() public var src: Path? = null public var output: File? = null @@ -73,21 +100,15 @@ public abstract class KotlinCompilerBaseTask : Task private fun fillArguments() { val sourcePaths = src ?: throw BuildException("\"src\" should be specified") - arguments.freeArgs = sourcePaths.list().map { File(it).canonicalPath } + args.addAll(sourcePaths.list().map { File(it).canonicalPath }) output ?: throw BuildException("\"output\" should be specified") - arguments.suppressWarnings = nowarn - arguments.verbose = verbose - arguments.version = printVersion + if (nowarn) args.add("-nowarn") + if (verbose) args.add("-verbose") + if (printVersion) args.add("-version") - val args = additionalArguments.flatMap { it.getParts().toList() } - try { - Args.parse(arguments, args.copyToArray()) - } - catch (e: IllegalArgumentException) { - throw BuildException(e.getMessage()) - } + args.addAll(additionalArguments.flatMap { it.getParts().toList() }) fillSpecificArguments() } @@ -95,13 +116,17 @@ public abstract class KotlinCompilerBaseTask : Task final override fun execute() { fillArguments() - log("Compiling ${arguments.freeArgs} => [${output!!.canonicalPath}]"); + val compilerClass = CompilerClassLoaderHolder.getOrCreateClassLoader(project).loadClass(compilerFqName) + val compiler = compilerClass.newInstance() + val exec = compilerClass.getMethod("execFullPathsInMessages", javaClass(), javaClass>()) - val collector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN, arguments.verbose) - val exitCode = compiler.exec(collector, Services.EMPTY, arguments) + log("Compiling ${src!!.list().toList()} => [${output!!.canonicalPath}]"); - if (exitCode != ExitCode.OK) { - throw BuildException("Compilation finished with exit code $exitCode") + val exitCode = exec(compiler, System.err, args.copyToArray()) + + // TODO: support failOnError attribute of javac + if ((exitCode as Enum<*>).ordinal() != 0) { + throw BuildException("Compile failed; see the compiler error output for details.") } } } diff --git a/build.xml b/build.xml index d8e94ade7e7..89ef5929e3f 100644 --- a/build.xml +++ b/build.xml @@ -624,7 +624,6 @@ - @@ -642,7 +641,7 @@ - + diff --git a/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java index e4c55dd9c50..5daa75868ce 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java @@ -58,6 +58,12 @@ public abstract class CLICompiler { return exec(errStream, services, MessageRenderer.TAGS, args); } + @SuppressWarnings("UnusedDeclaration") // Used via reflection in KotlinCompilerBaseTask + @NotNull + public ExitCode execFullPathsInMessages(@NotNull PrintStream errStream, @NotNull String[] args) { + return exec(errStream, Services.EMPTY, MessageRenderer.PLAIN, args); + } + @Nullable private A parseArguments(@NotNull PrintStream errStream, @NotNull MessageRenderer messageRenderer, @NotNull String[] args) { try { diff --git a/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskJvmTest.java b/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskJvmTest.java index 3f81a32889b..357f2d9338f 100644 --- a/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskJvmTest.java +++ b/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskJvmTest.java @@ -17,11 +17,13 @@ package org.jetbrains.kotlin; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.utils.UtilsPackage; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; import java.io.File; +import java.util.Arrays; public class AntTaskJvmTest extends AntTaskBaseTest { private static final String JVM_OUT_FILE = "hello.jar"; @@ -44,7 +46,11 @@ public class AntTaskJvmTest extends AntTaskBaseTest { } private static String getClassPathForAnt() { - return getCompilerLib() + File.separator + "kotlin-ant.jar" + File.pathSeparator + getKotlinRuntimePath(); + return UtilsPackage.join(Arrays.asList( + getCompilerLib() + File.separator + "kotlin-ant.jar", + getCompilerLib() + File.separator + "kotlin-compiler.jar", + getKotlinRuntimePath() + ), File.pathSeparator); } private static String getIdeaSdkHome() { @@ -61,11 +67,6 @@ public class AntTaskJvmTest extends AntTaskBaseTest { doJvmAntTest(); } - @Test - public void wrongArguments() throws Exception { - doAntTest(FAILED); - } - @Test public void jvmClasspath() throws Exception { doJvmAntTest(); diff --git a/compiler/integration-tests/testData/ant/jvm/wrongArguments/build.log.expected b/compiler/integration-tests/testData/ant/jvm/wrongArguments/build.log.expected deleted file mode 100644 index c3fabbb7cd1..00000000000 --- a/compiler/integration-tests/testData/ant/jvm/wrongArguments/build.log.expected +++ /dev/null @@ -1,13 +0,0 @@ -OUT: -Buildfile: [TestData]/build.xml - -build: - -ERR: - -BUILD FAILED -[TestData]/build.xml:5: Invalid argument: -option-never-to-be-supported - -Total time: [time] - -Return code: 1 diff --git a/compiler/integration-tests/testData/ant/jvm/wrongArguments/build.xml b/compiler/integration-tests/testData/ant/jvm/wrongArguments/build.xml deleted file mode 100644 index 33b6930c19b..00000000000 --- a/compiler/integration-tests/testData/ant/jvm/wrongArguments/build.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/compiler/integration-tests/testData/ant/jvm/wrongArguments/hello.kt b/compiler/integration-tests/testData/ant/jvm/wrongArguments/hello.kt deleted file mode 100644 index 952c9795d52..00000000000 --- a/compiler/integration-tests/testData/ant/jvm/wrongArguments/hello.kt +++ /dev/null @@ -1,4 +0,0 @@ -package hello - -fun main(args : Array) { -}