<kotlinc> ant task now supports <src> element and multiple source directories

This commit is contained in:
Andrey Breslav
2013-10-08 15:03:32 +04:00
parent ed006a66c5
commit bf49bc0220
10 changed files with 103 additions and 19 deletions
@@ -20,9 +20,11 @@ import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.types.Reference;
import org.jetbrains.jet.buildtools.core.BytecodeCompiler; import org.jetbrains.jet.buildtools.core.BytecodeCompiler;
import org.jetbrains.jet.buildtools.core.Util;
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentException; import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentException;
import java.io.File; import java.io.File;
import java.util.Arrays;
import static org.jetbrains.jet.buildtools.core.Util.getPath; import static org.jetbrains.jet.buildtools.core.Util.getPath;
@@ -40,7 +42,7 @@ public class BytecodeCompilerTask extends Task {
private File output; private File output;
private File jar; private File jar;
private File stdlib; private File stdlib;
private File src; private Path src;
private File module; private File module;
private Path compileClasspath; private Path compileClasspath;
private boolean includeRuntime = true; private boolean includeRuntime = true;
@@ -57,10 +59,17 @@ public class BytecodeCompilerTask extends Task {
this.stdlib = stdlib; this.stdlib = stdlib;
} }
public void setSrc(File src) { public void setSrc(Path src) {
this.src = src; this.src = src;
} }
public Path createSrc() {
if (src == null) {
src = new Path(getProject());
}
return src.createPath();
}
public void setModule(File module) { public void setModule(File module) {
this.module = module; this.module = module;
} }
@@ -121,10 +130,10 @@ public class BytecodeCompilerTask extends Task {
throw new CompileEnvironmentException("\"output\" or \"jar\" should be specified"); throw new CompileEnvironmentException("\"output\" or \"jar\" should be specified");
} }
String source = getPath(this.src); String[] source = Util.getPaths(this.src.list());
String destination = getPath(this.output != null ? this.output : this.jar); String destination = getPath(this.output != null ? this.output : this.jar);
log(String.format("Compiling [%s] => [%s]", source, destination)); log(String.format("Compiling [%s] => [%s]", Arrays.toString(source), destination));
if (this.output != null) { if (this.output != null) {
compiler.sourcesToDir(source, destination, stdlibPath, classpath); compiler.sourcesToDir(source, destination, stdlibPath, classpath);
@@ -16,13 +16,20 @@
package org.jetbrains.jet.buildtools.core; package org.jetbrains.jet.buildtools.core;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import jet.modules.Module; import jet.modules.Module;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.cli.common.CLIConfigurationKeys; import org.jetbrains.jet.cli.common.CLIConfigurationKeys;
import org.jetbrains.jet.cli.common.CompilerPlugin; import org.jetbrains.jet.cli.common.CompilerPlugin;
import org.jetbrains.jet.cli.common.messages.MessageCollectorPlainTextToStream; import org.jetbrains.jet.cli.common.messages.MessageCollectorPlainTextToStream;
import org.jetbrains.jet.cli.jvm.compiler.*; import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys;
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentException;
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.cli.jvm.compiler.KotlinToJVMBytecodeCompiler;
import org.jetbrains.jet.config.CommonConfigurationKeys; import org.jetbrains.jet.config.CommonConfigurationKeys;
import org.jetbrains.jet.config.CompilerConfiguration; import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.utils.KotlinPaths; import org.jetbrains.jet.utils.KotlinPaths;
@@ -42,6 +49,7 @@ import static org.jetbrains.jet.cli.jvm.JVMConfigurationKeys.CLASSPATH_KEY;
* Wrapper class for Kotlin bytecode compiler. * Wrapper class for Kotlin bytecode compiler.
*/ */
public class BytecodeCompiler { public class BytecodeCompiler {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private List<CompilerPlugin> compilerPlugins = new ArrayList<CompilerPlugin>(); private List<CompilerPlugin> compilerPlugins = new ArrayList<CompilerPlugin>();
@@ -87,6 +95,12 @@ public class BytecodeCompiler {
} }
configuration.addAll(CommonConfigurationKeys.SOURCE_ROOTS_KEY, Arrays.asList(sourceRoots)); configuration.addAll(CommonConfigurationKeys.SOURCE_ROOTS_KEY, Arrays.asList(sourceRoots));
for (String sourceRoot : sourceRoots) {
File file = new File(sourceRoot);
if (!file.isFile() || !"kt".equals(FileUtilRt.getExtension(file.getName()))) {
configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, file);
}
}
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollectorPlainTextToStream.PLAIN_TEXT_TO_SYSTEM_ERR); configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollectorPlainTextToStream.PLAIN_TEXT_TO_SYSTEM_ERR);
// lets register any compiler plugins // lets register any compiler plugins
@@ -101,24 +115,37 @@ public class BytecodeCompiler {
* @param exceptionThrown whether compilation failed due to exception thrown * @param exceptionThrown whether compilation failed due to exception thrown
* @return compilation error message * @return compilation error message
*/ */
private static String errorMessage(@NotNull String source, boolean exceptionThrown) { private static String errorMessage(@NotNull String[] source, boolean exceptionThrown) {
return String.format("[%s] compilation failed" + return String.format("Compilation of the following source roots failed:" + LINE_SEPARATOR +
(exceptionThrown ? "" : ", see \"ERROR:\" messages above for more details."), getAbsolutePaths(source) +
new File(source).getAbsolutePath()); (exceptionThrown ? "" : LINE_SEPARATOR + "see \"ERROR:\" messages above for more details."));
}
private static String getAbsolutePaths(String[] source) {
return StringUtil.join(
source,
new Function<String, String>() {
@Override
public String fun(String s) {
return " * " + new File(s).getAbsolutePath();
}
},
LINE_SEPARATOR
);
} }
/** /**
* {@code CompileEnvironment#compileBunchOfSources} wrapper. * {@code CompileEnvironment#compileBunchOfSources} wrapper.
* *
* @param src compilation source (directory or file) * @param src compilation source (directories or files)
* @param output compilation destination directory * @param output compilation destination directory
* @param stdlib "kotlin-runtime.jar" path * @param stdlib "kotlin-runtime.jar" path
* @param classpath compilation classpath, can be <code>null</code> or empty * @param classpath compilation classpath, can be <code>null</code> or empty
*/ */
public void sourcesToDir(@NotNull String src, @NotNull String output, @Nullable String stdlib, @Nullable String[] classpath) { public void sourcesToDir(@NotNull String[] src, @NotNull String output, @Nullable String stdlib, @Nullable String[] classpath) {
try { try {
JetCoreEnvironment environment = env(stdlib, classpath, new String[]{src}); JetCoreEnvironment environment = env(stdlib, classpath, src);
boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, null, new File(output), true); boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, null, new File(output), true);
if (!success) { if (!success) {
@@ -140,13 +167,13 @@ public class BytecodeCompiler {
* @param stdlib "kotlin-runtime.jar" path * @param stdlib "kotlin-runtime.jar" path
* @param classpath compilation classpath, can be <code>null</code> or empty * @param classpath compilation classpath, can be <code>null</code> or empty
*/ */
public void sourcesToJar(@NotNull String src, public void sourcesToJar(@NotNull String[] src,
@NotNull String jar, @NotNull String jar,
boolean includeRuntime, boolean includeRuntime,
@Nullable String stdlib, @Nullable String stdlib,
@Nullable String[] classpath) { @Nullable String[] classpath) {
try { try {
JetCoreEnvironment environment = env(stdlib, classpath, new String[]{src}); JetCoreEnvironment environment = env(stdlib, classpath, src);
boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, new File(jar), null, includeRuntime); boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, new File(jar), null, includeRuntime);
if (!success) { if (!success) {
@@ -184,11 +211,11 @@ public class BytecodeCompiler {
File directory = new File(module).getParentFile(); File directory = new File(module).getParentFile();
boolean success = KotlinToJVMBytecodeCompiler.compileModules(configuration, modules, directory, new File(jar), null, includeRuntime); boolean success = KotlinToJVMBytecodeCompiler.compileModules(configuration, modules, directory, new File(jar), null, includeRuntime);
if (!success) { if (!success) {
throw new CompileEnvironmentException(errorMessage(module, false)); throw new CompileEnvironmentException(errorMessage(new String[]{module}, false));
} }
} }
catch (Exception e) { catch (Exception e) {
throw new CompileEnvironmentException(errorMessage(module, true), e); throw new CompileEnvironmentException(errorMessage(new String[]{module}, true), e);
} }
} }
@@ -43,4 +43,13 @@ public final class Util {
throw new RuntimeException(String.format("Failed to resolve canonical file of [%s]: %s", f, e), e); throw new RuntimeException(String.format("Failed to resolve canonical file of [%s]: %s", f, e), e);
} }
} }
public static String[] getPaths(String[] paths) {
String[] result = new String[paths.length];
for (int i = 0; i < paths.length; i++) {
String path = paths[i];
result[i] = getPath(new File(path));
}
return result;
}
} }
@@ -23,8 +23,7 @@ import java.io.File;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
public class AntTaskTest extends KotlinIntegrationTestBase { public class AntTaskTest extends KotlinIntegrationTestBase {
@Test private void doAntTest() throws Exception {
public void antTaskJvm() throws Exception {
String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar"; String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar";
String runtime = new File("dist/kotlinc/lib/kotlin-runtime.jar").getAbsolutePath(); String runtime = new File("dist/kotlinc/lib/kotlin-runtime.jar").getAbsolutePath();
@@ -32,6 +31,16 @@ public class AntTaskTest extends KotlinIntegrationTestBase {
runJava("hello.run", "-cp", jar + File.pathSeparator + runtime, "Hello.HelloPackage"); runJava("hello.run", "-cp", jar + File.pathSeparator + runtime, "Hello.HelloPackage");
} }
@Test
public void antTaskJvm() throws Exception {
doAntTest();
}
@Test
public void antTaskJvmManyRoots() throws Exception {
doAntTest();
}
@Override @Override
protected String normalizeOutput(String content) { protected String normalizeOutput(String content) {
return super.normalizeOutput(content) return super.normalizeOutput(content)
@@ -1,7 +1,7 @@
OUT Buildfile: build.xml OUT Buildfile: build.xml
OUT OUT
OUT build: OUT build:
OUT [kotlinc] Compiling [[TestData]/hello.kt] => [[Temp]/hello.jar] OUT [kotlinc] Compiling [[[TestData]/hello.kt]] => [[Temp]/hello.jar]
OUT OUT
OUT BUILD SUCCESSFUL OUT BUILD SUCCESSFUL
OUT Total time: [time] OUT Total time: [time]
@@ -0,0 +1,8 @@
OUT Buildfile: build.xml
OUT
OUT build:
OUT [kotlinc] Compiling [[[TestData]/root1, [TestData]/root2]] => [[Temp]/hello.jar]
OUT
OUT BUILD SUCCESSFUL
OUT Total time: [time]
Return code: 0
@@ -0,0 +1,10 @@
<project name="Ant Task Test" default="build">
<taskdef resource="org/jetbrains/jet/buildtools/ant/antlib.xml" classpath="${kotlin.lib}/kotlin-ant.jar"/>
<target name="build">
<kotlinc output="${temp}/hello.jar">
<src path="${test.data}/root1"/>
<src path="${test.data}/root2"/>
</kotlinc>
</target>
</project>
@@ -0,0 +1,2 @@
OUT Hello, a!
Return code: 0
@@ -0,0 +1,7 @@
package Hello
fun main(args : Array<String>) {
for (s in arrayList("a"))
println("Hello, $s!")
foo()
}
@@ -0,0 +1,3 @@
package Hello
fun foo() {}