diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt index bff3c6b8..364d74bd 100644 --- a/src/main/kotlin/com/beust/kobalt/Main.kt +++ b/src/main/kotlin/com/beust/kobalt/Main.kt @@ -227,25 +227,26 @@ private class Main @Inject constructor( private fun runClasspathInterceptors(allProjects: List) { allProjects.forEach { - runClasspathInterceptors(it.compileDependencies) - runClasspathInterceptors(it.compileProvidedDependencies) - runClasspathInterceptors(it.compileRuntimeDependencies) - runClasspathInterceptors(it.testProvidedDependencies) - runClasspathInterceptors(it.testDependencies) + runClasspathInterceptors(it, it.compileDependencies) + runClasspathInterceptors(it, it.compileProvidedDependencies) + runClasspathInterceptors(it, it.compileRuntimeDependencies) + runClasspathInterceptors(it, it.testProvidedDependencies) + runClasspathInterceptors(it, it.testDependencies) } } - private fun runClasspathInterceptors(dependencies: ArrayList) = with(dependencies) { - val deps = interceptDependencies(pluginInfo, this) - clear() - addAll(deps) - } + private fun runClasspathInterceptors(project: Project, dependencies: ArrayList) + = with(dependencies) { + val deps = interceptDependencies(project, pluginInfo, this) + clear() + addAll(deps) + } - private fun interceptDependencies(pluginInfo: PluginInfo, dependencies: ArrayList) - : ArrayList { + private fun interceptDependencies(project: Project, pluginInfo: PluginInfo, + dependencies: ArrayList) : ArrayList { val result = arrayListOf() pluginInfo.classpathInterceptors.forEach { - result.addAll(it.intercept(dependencies)) + result.addAll(it.intercept(project, dependencies)) } return result } diff --git a/src/main/kotlin/com/beust/kobalt/api/IClasspathInterceptor.kt b/src/main/kotlin/com/beust/kobalt/api/IClasspathInterceptor.kt index b105928b..906dee86 100644 --- a/src/main/kotlin/com/beust/kobalt/api/IClasspathInterceptor.kt +++ b/src/main/kotlin/com/beust/kobalt/api/IClasspathInterceptor.kt @@ -1,10 +1,8 @@ package com.beust.kobalt.api -import com.beust.kobalt.api.IClasspathDependency - /** * Modify a list of dependencies before Kobalt starts using them. */ interface IClasspathInterceptor : IInterceptor { - fun intercept(dependencies: List) : List + fun intercept(project: Project, dependencies: List) : List } diff --git a/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt index 3e0bddc0..b6c3d1ff 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt @@ -29,14 +29,15 @@ class JvmCompiler @Inject constructor(val dependencyManager: DependencyManager) .distinct() // Plugins that add flags to the compiler - val addedFlags = ArrayList(info.compilerArgs) + - if (project != null) { - context.pluginInfo.compilerFlagContributors.flatMap { - it.flagsFor(project, info.compilerArgs) - } - } else { - emptyList() + val contributorFlags = if (project != null) { + context.pluginInfo.compilerFlagContributors.flatMap { + it.flagsFor(project, info.compilerArgs) } + } else { + emptyList() + } + + val addedFlags = contributorFlags + ArrayList(info.compilerArgs) validateClasspath(allDependencies.map { it.jarFile.get().absolutePath }) return action.compile(info.copy(dependencies = allDependencies, compilerArgs = addedFlags)) diff --git a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index 2d620580..1b7f5267 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -112,7 +112,7 @@ abstract class JvmCompilerPlugin @Inject constructor( it.exists() } .forEach { log(2, "Copying from $sourceDirs to $absOutputDir") - KFiles.copyRecursively(it, absOutputDir) + KFiles.copyRecursively(it, absOutputDir, deleteFirst = true) } } else { lp(project, "No resources to copy for $sourceSet") diff --git a/src/main/kotlin/com/beust/kobalt/maven/DepFactory.kt b/src/main/kotlin/com/beust/kobalt/maven/DepFactory.kt index 210e08db..9c49bc91 100644 --- a/src/main/kotlin/com/beust/kobalt/maven/DepFactory.kt +++ b/src/main/kotlin/com/beust/kobalt/maven/DepFactory.kt @@ -2,9 +2,12 @@ package com.beust.kobalt.maven import com.beust.kobalt.KobaltException import com.beust.kobalt.api.IClasspathDependency +import com.beust.kobalt.api.Kobalt import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.maven.dependency.MavenDependency +import com.beust.kobalt.misc.DependencyExecutor import com.beust.kobalt.misc.KobaltExecutors +import com.google.inject.Key import java.util.concurrent.ExecutorService import javax.inject.Inject @@ -14,10 +17,15 @@ public class DepFactory @Inject constructor(val localRepo: LocalRepo, val downloadManager: DownloadManager, val pomFactory: Pom.IFactory) { + companion object { + val defExecutor = + Kobalt.INJECTOR.getInstance(Key.get(ExecutorService::class.java, DependencyExecutor::class.java)) + } + /** * Parse the id and return the correct IClasspathDependency */ - public fun create(id: String, executor: ExecutorService, + public fun create(id: String, executor: ExecutorService = defExecutor, localFirst : Boolean = true) : IClasspathDependency { if (id.startsWith(FileDependency.PREFIX_FILE)) { return FileDependency(id.substring(FileDependency.PREFIX_FILE.length)) diff --git a/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt b/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt index 0cdad327..1b3bebf5 100644 --- a/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt +++ b/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt @@ -137,7 +137,7 @@ class KFiles { return result } - fun copyRecursively(from: File, to: File, replaceExisting: Boolean = true, deleteFirst: Boolean = true, + fun copyRecursively(from: File, to: File, replaceExisting: Boolean = true, deleteFirst: Boolean = false, onError: (File, IOException) -> OnErrorAction = { file, exception -> throw exception }) { // Need to wait until copyRecursively supports an overwrite: Boolean = false parameter // Until then, wipe everything first diff --git a/src/main/kotlin/com/beust/kobalt/misc/RunCommand.kt b/src/main/kotlin/com/beust/kobalt/misc/RunCommand.kt index 05b00116..7d6646d4 100644 --- a/src/main/kotlin/com/beust/kobalt/misc/RunCommand.kt +++ b/src/main/kotlin/com/beust/kobalt/misc/RunCommand.kt @@ -48,10 +48,8 @@ open class RunCommand(val command: String) { } } val callSucceeded = process.waitFor(30, TimeUnit.SECONDS) - val input = if (process.inputStream.available() > 0) fromStream(process.inputStream) - else listOf() - val error = if (process.errorStream.available() > 0) fromStream(process.errorStream) - else listOf() + val input = if (process.inputStream.available() > 0) fromStream(process.inputStream) else emptyList() + val error = if (process.errorStream.available() > 0) fromStream(process.errorStream) else emptyList() val isSuccess = isSuccess(callSucceeded, input, error) if (isSuccess) { @@ -85,5 +83,8 @@ open class RunCommand(val command: String) { line = br.readLine() } return result + +// val result = CharStreams.toString(InputStreamReader(ins, Charset.defaultCharset())) +// return result.split("\n") } } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt index a4418153..05cfdaad 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt @@ -106,6 +106,19 @@ class AndroidBuild { val dxJar = androidBuilder.dxJar val resourceMerger = ResourceMerger() + // + // Assets + // + val intermediates = File( + KFiles.joinDir(AndroidFiles.intermediates(project), "assets", variant.toIntermediateDir())) + aarDependencies.forEach { + val assetDir = File(it, "assets") + if (assetDir.exists()) { + println("COPY FROM $assetDir TO $intermediates") + KFiles.copyRecursively(assetDir, intermediates) + } + } + // // Manifest // @@ -143,8 +156,8 @@ class AndroidBuild { // TODO: figure out why the badSrcList is bad. All this information should be coming from the Variant val badSrcList = variant.resDirectories(project).map { it.path } - val aarList = aarDependencies.map { it.path + File.separator} - (aarList + srcList).map { it + File.separator + "res" }.forEach { path -> + val goodAarList = aarDependencies.map { it.path + File.separator} + (goodAarList + srcList).map { it + File.separator + "res" }.forEach { path -> val set = ResourceSet(path) set.addSource(File(path)) set.loadFromFiles(logger) @@ -157,7 +170,5 @@ class AndroidBuild { resourceMerger.mergeData(writer, true) - - println("") } } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt index 75c82b63..8907ead4 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt @@ -3,7 +3,9 @@ package com.beust.kobalt.plugin.android import com.beust.kobalt.Variant import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project +import com.beust.kobalt.maven.MavenId import com.beust.kobalt.misc.KFiles +import java.nio.file.Paths class AndroidFiles { companion object { @@ -27,6 +29,10 @@ class AndroidFiles { fun mergedResources(project: Project, variant: Variant) = KFiles.joinAndMakeDir(mergedResourcesNoVariant(project), variant.toIntermediateDir()) + fun classesJar(project: Project, mavenId: MavenId) = + Paths.get(intermediates(project), "exploded-aar", mavenId.groupId, mavenId.artifactId, mavenId.version, + "classes.jar").toFile().path + /** * Use the android home define on the project if any, otherwise use the environment variable. */ 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 8e860c24..2e2c86b4 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt @@ -4,6 +4,7 @@ import com.beust.kobalt.* import com.beust.kobalt.api.* import com.beust.kobalt.api.annotation.Directive import com.beust.kobalt.api.annotation.Task +import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.MavenId import com.beust.kobalt.maven.dependency.FileDependency import com.beust.kobalt.maven.dependency.MavenDependency @@ -20,7 +21,7 @@ import java.nio.file.Paths @Singleton public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, val merger: Merger, - val executors: KobaltExecutors) + val executors: KobaltExecutors, val dependencyManager: DependencyManager) : ConfigPlugin(), IClasspathContributor, IRepoContributor, ICompilerFlagContributor, ICompilerInterceptor, IBuildDirectoryIncerceptor, IRunnerContributor, IClasspathInterceptor, ISourceDirectoryContributor, IBuildConfigFieldContributor, ITaskContributor { @@ -72,7 +73,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v return version as String } - inline fun androidHome(project: Project?) = AndroidFiles.androidHome(project, configurationFor(project)!!) + fun androidHome(project: Project?) = AndroidFiles.androidHome(project, configurationFor(project)!!) fun androidJar(project: Project): Path = Paths.get(androidHome(project), "platforms", "android-${compileSdkVersion(project)}", "android.jar") @@ -91,9 +92,8 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v runBefore = arrayOf("compile"), runAfter = arrayOf("clean")) fun taskGenerateRFile(project: Project): TaskResult { - val intermediates = AndroidFiles.intermediates(project) val resDir = "temporaryBogusResDir" - val aarDependencies= explodeAarFiles(project, intermediates, File(resDir)) + val aarDependencies = explodeAarFiles(project, File(resDir)) AndroidBuild().run(project, context.variant, configurationFor(project)!!, aarDependencies) // merger.merge(project, context) @@ -151,31 +151,32 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v // "--output-text-symbols", KFiles.joinAndMakeDir(intermediates(project).toString(), "symbol", flavor) )) - val rOutputDirectory = KFiles.joinDir(rDirectory, applicationId.replace(".", File.separator)) - val generatedBuildDir = compile(project, rOutputDirectory) - project.compileDependencies.add(FileDependency(generatedBuildDir.path)) +// val rOutputDirectory = KFiles.joinDir(rDirectory, applicationId.replace(".", File.separator)) +// val generatedBuildDir = compile(project, rOutputDirectory) +// project.compileDependencies.add(FileDependency(generatedBuildDir.path)) return result == 0 } /** - * 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 + * Extract all the .aar files found in the dependencies and add their android.jar to classpathEntries, + * which will be added to the classpath at compile time via the classpath interceptor. */ - private fun explodeAarFiles(project: Project, outputDir: String, resDir: File) : List { + private fun explodeAarFiles(project: Project, resDir: File) : List { val result = arrayListOf() project.compileDependencies.filter { it.jarFile.get().name.endsWith(".aar") }.forEach { val mavenId = MavenId(it.id) + val outputDir = AndroidFiles.intermediates(project) val destDir = Paths.get(outputDir, "exploded-aar", mavenId.groupId, mavenId.artifactId, mavenId.version) .toFile() log(2, "Exploding ${it.jarFile.get()} to $destDir") JarUtils.extractJarFile(it.jarFile.get(), destDir) - val classesJar = Paths.get(destDir.absolutePath, "classes.jar") + val classesJar = AndroidFiles.classesJar(project, mavenId) // Add the classses.jar of this .aar to the classpath entries (which are returned via IClasspathContributor) - classpathEntries.put(project.name, FileDependency(classesJar.toFile().absolutePath)) + classpathEntries.put(project.name, FileDependency(classesJar)) // Also add all the jar files found in the libs/ directory File(destDir, "libs").let { libsDir -> if (libsDir.exists()) { @@ -188,7 +189,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v // Copy all the resources from this aar into the same intermediate directory log(2, "Copying the resources to $resDir") result.add(destDir) - KFiles.copyRecursively(destDir.resolve("res"), resDir, deleteFirst = false) + KFiles.copyRecursively(destDir.resolve("res"), resDir) } return result } @@ -210,40 +211,13 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v */ override fun flagsFor(project: Project, currentFlags: List) : List { if (isAndroid(project)) { - val result = arrayListOf() - var foundSource = false - var foundTarget = false - var noWarn = false - var i = 0 - while (i < currentFlags.size) { - with(currentFlags[i]) { - if (this == "-source") { - result.add(this) - result.add(currentFlags[i + 1]) - i++ - foundSource = true - } else if (this == "-target") { - result.add(this) - result.add(currentFlags[i + 1]) - i++ - foundTarget = true - } else { - result.add(this) - } - } - i++ - } - if (! foundSource) { + var found = currentFlags.any { it == "-source" || it == "-target" } + val result = arrayListOf().apply { addAll(currentFlags) } + if (! found) { result.add("-source") result.add("1.6") - noWarn = true - } - if (! foundTarget) { result.add("-target") result.add("1.6") - noWarn = true - } - if (noWarn) { result.add("-nowarn") } return result @@ -286,12 +260,27 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v // java.exe -Xmx1024M -Dfile.encoding=windows-1252 -Duser.country=US -Duser.language=en -Duser.variant -cp D:\android\adt-bundle-windows-x86_64-20140321\sdk\build-tools\23.0.1\lib\dx.jar com.android.dx.command.Main --dex --verbose --num-threads=4 --output C:\Users\cbeust\android\android_hello_world\app\build\intermediates\dex\pro\debug C:\Users\cbeust\android\android_hello_world\app\build\intermediates\classes\pro\debug val javaExecutable = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable!! - RunCommand(javaExecutable.absolutePath).run(listOf( + + val dependencies = dependencyManager.calculateDependencies(project, context, projects, + project.compileDependencies).map { + it.jarFile.get().path + }.filterNot { + it.contains("android.jar") || it.endsWith(".aar") || it.contains("com.android.support") + || it.contains("retrolambda") + }.toHashSet().toTypedArray() + + class DexCommand : RunCommand(javaExecutable.absolutePath) { + override fun isSuccess(callSucceeded: Boolean, input: List, error: List) = + error.size == 0 + } + + DexCommand().run(listOf( "-cp", KFiles.joinDir(androidHome(project), "build-tools", buildToolsVersion(project), "lib", "dx.jar"), "com.android.dx.command.Main", "--dex", "--verbose", "--num-threads=4", "--output", outClassesDex, - //KFiles.joinDir(intermediates(project), "dex", context.variant.toIntermediateDir()), + *dependencies, +// KFiles.joinDir(AndroidFiles.intermediates(project), "dex", context.variant.toIntermediateDir()), project.classesDir(context) )) @@ -439,12 +428,14 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v * Automatically add the "aar" packaging for support libraries. */ // IClasspathInterceptor - override fun intercept(dependencies: List): List { + override fun intercept(project: Project, dependencies: List): List { val result = arrayListOf() dependencies.forEach { - if (it is MavenDependency && it.groupId == "com.android.support") { + if (it is MavenDependency && (it.groupId == "com.android.support" || it.mavenId.packaging == "aar")) { + val newDep = FileDependency(AndroidFiles.classesJar(project, it.mavenId)) + result.add(newDep) val id = MavenId.create(it.groupId, it.artifactId, "aar", it.version) - result.add(MavenDependency.create(id, executors.miscExecutor)) + result.add(MavenDependency.create(id)) } else { result.add(it) } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt index d0ebbb43..a6b159d4 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/packaging/PackagingPlugin.kt @@ -91,7 +91,8 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana // The transitive closure of libraries goes into WEB-INF/libs. // Copy them all in kobaltBuild/war/WEB-INF/libs and create one IncludedFile out of that directory // - val allDependencies = dependencyManager.transitiveClosure(project.compileDependencies) + val allDependencies = dependencyManager.calculateDependencies(project, context, projects, + project.compileDependencies) val WEB_INF = "WEB-INF/lib" val outDir = project.buildDirectory + "/war" @@ -268,7 +269,7 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana log(1, "Installing from $buildDir to ${config.libDir}") val toDir = KFiles.makeDir(config.libDir) - KFiles.copyRecursively(buildDirFile, toDir) + KFiles.copyRecursively(buildDirFile, toDir, deleteFirst = true) } return TaskResult() diff --git a/src/main/kotlin/com/beust/kobalt/plugin/retrolambda/RetrolambdaPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/retrolambda/RetrolambdaPlugin.kt index 80aee6e2..037d44a2 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/retrolambda/RetrolambdaPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/retrolambda/RetrolambdaPlugin.kt @@ -34,7 +34,7 @@ class RetrolambdaPlugin @Inject constructor(val dependencyManager: DependencyMan override fun apply(project: Project, context: KobaltContext) { super.apply(project, context) taskContributor.addVariantTasks(this, project, context, "retrolambda", runTask = { taskRetrolambda(project) }, - alwaysRunAfter = listOf("compile")) + runBefore = listOf("generateDex"), alwaysRunAfter = listOf("compile")) } // IClasspathContributor @@ -43,14 +43,16 @@ class RetrolambdaPlugin @Inject constructor(val dependencyManager: DependencyMan if (project != null && configurationFor(project) != null) listOf(JAR) else emptyList() - @Task(name = "retrolambda", description = "Run Retrolambda", + @Task(name = "retrolambda", description = "Run Retrolambda", runBefore = arrayOf("generateDex"), alwaysRunAfter = arrayOf(JvmCompilerPlugin.TASK_COMPILE)) fun taskRetrolambda(project: Project): TaskResult { val config = configurationFor(project) val result = if (config != null) { val classesDir = project.classesDir(context) - val classpath = (dependencyManager.transitiveClosure(project.compileDependencies).map { + val classpath = (dependencyManager.calculateDependencies(project, context, projects, + project.compileDependencies) + .map { it.jarFile.get() } + classesDir).joinToString(File.pathSeparator)