From 9094b807cc8f3cd884531a2054d1f7601410442c Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Fri, 30 Oct 2015 01:00:11 -0700 Subject: [PATCH 1/2] Warnings. --- .../com/beust/kobalt/internal/JvmCompilerPlugin.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index 828ba2dd..97f49020 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -43,7 +43,7 @@ abstract class JvmCompilerPlugin @Inject constructor( * Log with a project. */ protected fun lp(project: Project, s: String) { - log(2, "${project.name}: ${s}") + log(2, "${project.name}: $s") } fun calculateClasspath(vararg allDependencies : List): List { @@ -105,18 +105,18 @@ abstract class JvmCompilerPlugin @Inject constructor( sourceDirs.addAll(project.sourceDirectoriesTest.filter { it.contains("resources") }) outputDir = KFiles.TEST_CLASSES_DIR } else { - throw IllegalArgumentException("Custom source sets not supported yet: ${sourceSet}") + throw IllegalArgumentException("Custom source sets not supported yet: $sourceSet") } if (sourceDirs.size > 0) { - lp(project, "Copying ${sourceSet} resources") + lp(project, "Copying $sourceSet resources") val absOutputDir = File(KFiles.joinDir(project.directory, project.buildDirectory!!, outputDir)) sourceDirs.map { File(it) }.filter { it.exists() } .forEach { - log(2, "Copying from ${sourceDirs} to ${absOutputDir}") + log(2, "Copying from $sourceDirs to $absOutputDir") KFiles.copyRecursively(it, absOutputDir) } } else { - lp(project, "No resources to copy for ${sourceSet}") + lp(project, "No resources to copy for $sourceSet") } } } From 4614ea725309c72a1a2b08e1fc2250fa55331ec5 Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Fri, 30 Oct 2015 01:34:27 -0700 Subject: [PATCH 2/2] IClasspathContributor. --- .../beust/kobalt/api/IClasspathContributor.kt | 11 +++++ .../com/beust/kobalt/api/KobaltContext.kt | 2 + .../kobalt/internal/JvmCompilerPlugin.kt | 28 ++++++++++- .../kobalt/plugin/android/AndroidPlugin.kt | 46 +++++++++++++++---- .../beust/kobalt/plugin/java/JavaPlugin.kt | 4 +- .../kobalt/plugin/kotlin/KotlinCompiler.kt | 2 +- .../kobalt/plugin/kotlin/KotlinPlugin.kt | 2 +- .../beust/kobalt/plugin/packaging/JarUtils.kt | 28 ++++++++++- 8 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 src/main/kotlin/com/beust/kobalt/api/IClasspathContributor.kt diff --git a/src/main/kotlin/com/beust/kobalt/api/IClasspathContributor.kt b/src/main/kotlin/com/beust/kobalt/api/IClasspathContributor.kt new file mode 100644 index 00000000..47720e7e --- /dev/null +++ b/src/main/kotlin/com/beust/kobalt/api/IClasspathContributor.kt @@ -0,0 +1,11 @@ +package com.beust.kobalt.api + +import com.beust.kobalt.maven.IClasspathDependency + +/** + * Implement this interface in order to add your own entries to the classpath. A list of contributors + * can be found on the `KobaltContext`. + */ +interface IClasspathContributor { + fun entriesFor(project: Project) : Collection +} diff --git a/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt b/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt index 59d9682a..39509a55 100644 --- a/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt +++ b/src/main/kotlin/com/beust/kobalt/api/KobaltContext.kt @@ -2,8 +2,10 @@ package com.beust.kobalt.api import com.beust.kobalt.Args import com.beust.kobalt.Plugins +import java.util.* public class KobaltContext(val args: Args) { fun findPlugin(name: String) = Plugins.findPlugin(name) + val classpathContributors: ArrayList = arrayListOf() } diff --git a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index 97f49020..d8d3f24f 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -1,6 +1,7 @@ package com.beust.kobalt.internal import com.beust.kobalt.api.BasePlugin +import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Task @@ -37,6 +38,15 @@ abstract class JvmCompilerPlugin @Inject constructor( } } + + private fun runClasspathContributors(context: KobaltContext?, project: Project) : + Collection { + val result = arrayListOf() + context!!.classpathContributors.forEach { + result.addAll(it.entriesFor(project)) + } + return result + } } /** @@ -46,11 +56,25 @@ abstract class JvmCompilerPlugin @Inject constructor( log(2, "${project.name}: $s") } - fun calculateClasspath(vararg allDependencies : List): List { + var context: KobaltContext? = null + + override fun apply(project: Project, context: KobaltContext) { + this.context = context + } + + /** + * @return the classpath for this project, including the IClasspathContributors. + */ + fun calculateClasspath(project: Project?, vararg allDependencies: List): + List { var result = arrayListOf() allDependencies.forEach { dependencies -> result.addAll(dependencyManager.transitiveClosure(dependencies)) } + if (project != null) { + result.addAll(runClasspathContributors(context, project)) + } + return result } @@ -61,7 +85,7 @@ abstract class JvmCompilerPlugin @Inject constructor( with(project) { arrayListOf(compileDependencies, compileProvidedDependencies, testDependencies, testProvidedDependencies).forEach { - result.addAll(calculateClasspath(it)) + result.addAll(calculateClasspath(project, it)) } } return dependencyManager.reorderDependencies(result) diff --git a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt index d4fe56cd..b5305e39 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt @@ -1,18 +1,19 @@ package com.beust.kobalt.plugin.android -import com.beust.kobalt.api.BasePlugin -import com.beust.kobalt.api.Kobalt -import com.beust.kobalt.api.KobaltContext -import com.beust.kobalt.api.Project +import com.beust.kobalt.api.* import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.internal.TaskResult import com.beust.kobalt.maven.FileDependency import com.beust.kobalt.maven.IClasspathDependency +import com.beust.kobalt.maven.MavenId import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.RunCommand import com.beust.kobalt.misc.log import com.beust.kobalt.plugin.java.JavaCompiler +import com.beust.kobalt.plugin.packaging.JarUtils +import com.google.common.collect.ArrayListMultimap +import com.google.common.collect.HashMultimap import com.google.inject.Inject import com.google.inject.Singleton import java.io.File @@ -32,7 +33,7 @@ fun Project.android(init: AndroidConfiguration.() -> Unit) : AndroidConfiguratio } @Singleton -public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : BasePlugin() { +public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : BasePlugin(), IClasspathContributor { val ANDROID_HOME = "/Users/beust/android/adt-bundle-mac-x86_64-20140702/sdk" override val name = "android" @@ -41,6 +42,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : if (accept(project)) { project.compileDependencies.add(FileDependency(androidJar(project).toString())) } + context.classpathContributors.add(this) } val configurations = hashMapOf() @@ -49,7 +51,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : configurations.put(p.name!!, configuration) } - override fun accept(p: Project) = configurations.containsKeyRaw(p.name) + override fun accept(project: Project) = configurations.containsKey(project.name!!) fun dirGet(dir: Path, vararg others: String) : String { val result = Paths.get(dir.toString(), *others) @@ -60,8 +62,8 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : return result.toString() } - fun compileSdkVersion(project: Project) = configurations.get(project.name!!)?.compileSdkVersion - fun buildToolsVersion(project: Project) = configurations.get(project.name!!)?.buildToolsVersion + fun compileSdkVersion(project: Project) = configurations[project.name!!]?.compileSdkVersion + fun buildToolsVersion(project: Project) = configurations[project.name!!]?.buildToolsVersion fun androidJar(project: Project) : Path = Paths.get(ANDROID_HOME, "platforms", "android-${compileSdkVersion(project)}", "android.jar") @@ -76,12 +78,14 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : val applicationId = configurations[project.name!!]?.applicationId!! val intermediates = Paths.get(project.directory, "app", "build", "intermediates") val manifestDir = Paths.get(project.directory, "app", "src", "main").toString() - val manifestIntermediateDir = dirGet(intermediates, "manifests", "full", flavor) +// val manifestIntermediateDir = dirGet(intermediates, "manifests", "full", flavor) val manifest = Paths.get(manifestDir, "AndroidManifest.xml") val generated = Paths.get(project.directory, "app", "build", "generated") val aapt = "$ANDROID_HOME/build-tools/$buildToolsVersion/aapt" val outputDir = dirGet(intermediates, "resources", "resources-$flavor") + explodeAarFiles(project, generated) + val crunchedPngDir = dirGet(intermediates, "res", flavor) RunCommand(aapt).apply { directory = File(project.directory) @@ -119,6 +123,23 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : return TaskResult() } + /** + * Extract all the .aar files found in the dependencies and add the android.jar to classpathEntries, + * which will be added to the classpath at compile time + */ + private fun explodeAarFiles(project: Project, outputDir: Path) { + project.compileDependencies.filter { + it.jarFile.get().name.endsWith(".aar") + }.forEach { + log(2, "Exploding ${it.jarFile.get()}") + val mavenId = MavenId(it.id) + val destDir = Paths.get(outputDir.toFile().absolutePath, mavenId.artifactId, mavenId.version).toFile() + JarUtils.extractJarFile(it.jarFile.get(), destDir) + val classesJar = Paths.get(destDir.absolutePath, "classes.jar") + classpathEntries.put(project.name, FileDependency(classesJar.toFile().absolutePath)) + } + } + private fun compile(project: Project, rDirectory: String) : File { val sourceFiles = arrayListOf(Paths.get(rDirectory, "R.java").toFile().path) val buildDir = Paths.get(project.buildDirectory, "generated", "classes").toFile() @@ -127,6 +148,13 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) : sourceFiles, buildDir) return buildDir } + + val classpathEntries = HashMultimap.create() + + override fun entriesFor(project: Project): Collection { + return classpathEntries.get(project.name!!) ?: listOf() + } + } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt index 51089a02..00277eac 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt @@ -77,7 +77,7 @@ public class JavaPlugin @Inject constructor( val sourceFiles = files.findRecursively(projectDir, project.sourceDirectories.map { File(it) }) { it: String -> it.endsWith(".java") } .map { File(projectDir, it).absolutePath } - val classpath = calculateClasspath(project.compileDependencies) + val classpath = calculateClasspath(project, project.compileDependencies) val args = arrayListOf( javadoc!!.absolutePath, "-classpath", classpath.map { it.jarFile.get().absolutePath }.joinToString(File.pathSeparator), @@ -105,7 +105,7 @@ public class JavaPlugin @Inject constructor( val sourceFiles = files.findRecursively(projectDir, project.sourceDirectories.map { File(it) }) { it: String -> it.endsWith(".java") } .map { File(projectDir, it).absolutePath } - val classpath = calculateClasspath(project.compileDependencies) + val classpath = calculateClasspath(project, project.compileDependencies) return compilePrivate(project, classpath, sourceFiles, buildDir) } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt index 8aab82fa..4ebbe6b9 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinCompiler.kt @@ -48,7 +48,7 @@ class KotlinCompiler @Inject constructor(override val localRepo : LocalRepo, getKotlinCompilerJar("kotlin-compiler-embeddable")) classpathList.addAll(otherClasspath) - classpathList.addAll(calculateClasspath(compileDependencies).map { it.id }) + classpathList.addAll(calculateClasspath(null, compileDependencies).map { it.id }) validateClasspath(classpathList) diff --git a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt index ac713dbb..ac040d2b 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/kotlin/KotlinPlugin.kt @@ -41,7 +41,7 @@ class KotlinPlugin @Inject constructor( @Task(name = TASK_COMPILE, description = "Compile the project") fun taskCompile(project: Project): TaskResult { copyResources(project, JvmCompilerPlugin.SOURCE_SET_MAIN) - val classpath = calculateClasspath(project.compileDependencies, project.compileProvidedDependencies) + val classpath = calculateClasspath(project, project.compileDependencies, project.compileProvidedDependencies) val projectDirectory = java.io.File(project.directory) val buildDirectory = File(projectDirectory, project.buildDirectory + File.separator + "classes") diff --git a/src/main/kotlin/com/beust/kobalt/plugin/packaging/JarUtils.kt b/src/main/kotlin/com/beust/kobalt/plugin/packaging/JarUtils.kt index a3dac07e..35bd0d96 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/packaging/JarUtils.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/packaging/JarUtils.kt @@ -1,6 +1,7 @@ package com.beust.kobalt.plugin.packaging import com.beust.kobalt.IFileSpec +import com.beust.kobalt.file import com.beust.kobalt.misc.log import java.io.* import java.util.jar.JarEntry @@ -44,7 +45,7 @@ public class JarUtils { // // var len = zis.read(buf) // while (len >= 0) { -// outStream.write(buf, 0, len); +// outStream.write(buf, 0, len) // len = zis.read(buf) // } // } @@ -154,5 +155,30 @@ public class JarUtils { log(1, "Deduplicated $fromFile.name") } + fun extractJarFile(jarFile: File, destDir: File) { + val jar = java.util.jar.JarFile(jarFile) + val enumEntries = jar.entries() + while (enumEntries.hasMoreElements()) { + val file = enumEntries.nextElement() as JarEntry + val f = File(destDir.path + java.io.File.separator + file.name) + if (file.isDirectory) { + f.mkdir() + continue + } + var ins: InputStream? = null + var fos: OutputStream? = null + try { + ins = jar.getInputStream(file) + f.parentFile.mkdirs() + fos = FileOutputStream(f) + while (ins.available() > 0) { + fos.write(ins.read()) + } + } finally { + fos?.close() + ins?.close() + } + } + } } }