diff --git a/TODO.md b/TODO.md index 25d795b2..2bd27c88 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,18 @@ To do: +Android: + +- [ ] Dex dependencies into kobaltBuild/intermediates/pre-dexed and preserve those across builds +- [ ] Move the calculated applicationId back into the merged AndroidManifest.xml +- [ ] Dex from android builder +- [ ] Keep exploded aars between runs +- [ ] aars keep being refetched +- [ ] See if there is an android manifest file in builder + +General + +- [ ] Apt should run from serviceloader +- [ ] Auto add variant - [ ] The test runner only selects classes with a parameterless constructor, which works for JUnit but not for TestNG factories - [ ] Add a "Auto complete Build.kt" menu in the plug-in @@ -31,6 +44,7 @@ To do: Done: +- [x] Compile with javax.tool - [x] Android: multiple -source/-target flags - [x] Dokka: allow multiple format outputs e.g `outputFormat("html", "javadoc")` - [x] Finish abstracting everything in `JvmCompilerPlugin` diff --git a/kobalt/wrapper/kobalt-wrapper.properties b/kobalt/wrapper/kobalt-wrapper.properties index 89d1cc76..55d79852 100644 --- a/kobalt/wrapper/kobalt-wrapper.properties +++ b/kobalt/wrapper/kobalt-wrapper.properties @@ -1 +1 @@ -kobalt.version=0.318 \ No newline at end of file +kobalt.version=0.320 \ No newline at end of file diff --git a/src/main/kotlin/com/beust/kobalt/Variant.kt b/src/main/kotlin/com/beust/kobalt/Variant.kt index fe5a5442..6c0ffff7 100644 --- a/src/main/kotlin/com/beust/kobalt/Variant.kt +++ b/src/main/kotlin/com/beust/kobalt/Variant.kt @@ -3,6 +3,7 @@ package com.beust.kobalt import com.beust.kobalt.api.* import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.log +import com.beust.kobalt.plugin.android.AndroidConfig import com.beust.kobalt.plugin.android.AndroidPlugin import java.io.File @@ -122,23 +123,35 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null, return result } + fun applicationId(androidConfig: AndroidConfig?): String? { + val mainId = productFlavor.applicationId ?: androidConfig?.applicationId + val result = + if (mainId != null) { + mainId + (buildType.applicationIdSuffix ?: "") + } else { + null + } + + return result + } + /** * Generate BuildConfig.java if requested. Also look up if any BuildConfig is defined on the current build type, * product flavor or main project, and use them to generate any additional field (in that order to * respect the priorities). Return the generated file if it was generated, null otherwise. */ fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? { - val buildConfigs = findBuildConfigs(project, context.variant) + val buildConfigs = findBuildConfigs(project, this) if (buildConfigs.size > 0) { val androidConfig = (Kobalt.findPlugin(AndroidPlugin.PLUGIN_NAME) as AndroidPlugin) .configurationFor(project) - val pkg = androidConfig?.applicationId ?: project.packageName ?: project.group + val pkg = applicationId(androidConfig) ?: project.packageName ?: project.group ?: throw KobaltException( "packageName needs to be defined on the project in order to generate BuildConfig") - val code = project.projectInfo.generateBuildConfig(project, context, pkg, context.variant, buildConfigs) - val result = KFiles.makeDir(KFiles.generatedSourceDir(project, context.variant, "buildConfig")) + val code = project.projectInfo.generateBuildConfig(project, context, pkg, this, buildConfigs) + val result = KFiles.makeDir(KFiles.generatedSourceDir(project, this, "buildConfig")) // Make sure the generatedSourceDirectory doesn't contain the project.directory since // that directory will be added when trying to find recursively all the sources in it generatedSourceDirectory = File(result.relativeTo(File(project.directory))) diff --git a/src/main/kotlin/com/beust/kobalt/api/ICompilerFlagContributor.kt b/src/main/kotlin/com/beust/kobalt/api/ICompilerFlagContributor.kt index 87757868..13396d0e 100644 --- a/src/main/kotlin/com/beust/kobalt/api/ICompilerFlagContributor.kt +++ b/src/main/kotlin/com/beust/kobalt/api/ICompilerFlagContributor.kt @@ -4,5 +4,5 @@ package com.beust.kobalt.api * Plugins that add compiler flags. */ interface ICompilerFlagContributor : IContributor { - fun flagsFor(project: Project, currentFlags: List): List + fun flagsFor(project: Project, context: KobaltContext, currentFlags: List): List } diff --git a/src/main/kotlin/com/beust/kobalt/api/Project.kt b/src/main/kotlin/com/beust/kobalt/api/Project.kt index 1cf16a00..43996ed3 100644 --- a/src/main/kotlin/com/beust/kobalt/api/Project.kt +++ b/src/main/kotlin/com/beust/kobalt/api/Project.kt @@ -181,6 +181,7 @@ interface IBuildConfig { } class ProductFlavorConfig(val name: String) : IBuildConfig { + var applicationId: String? = null override var buildConfig : BuildConfig? = BuildConfig() } @@ -192,6 +193,7 @@ fun Project.productFlavor(name: String, init: ProductFlavorConfig.() -> Unit) = class BuildTypeConfig(val project: Project?, val name: String) : IBuildConfig { var minifyEnabled = false + var applicationIdSuffix: String? = null var proguardFile: String? = null fun getDefaultProguardFile(name: String) : String { diff --git a/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt index b6c3d1ff..a770ffc5 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompiler.kt @@ -31,7 +31,7 @@ class JvmCompiler @Inject constructor(val dependencyManager: DependencyManager) // Plugins that add flags to the compiler val contributorFlags = if (project != null) { context.pluginInfo.compilerFlagContributors.flatMap { - it.flagsFor(project, info.compilerArgs) + it.flagsFor(project, context, info.compilerArgs) } } else { emptyList() diff --git a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index 70880215..cd4d5ae4 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -179,7 +179,8 @@ abstract class JvmCompilerPlugin @Inject constructor( dependencyManager.dependencies(project, context, projects) val projectDirectory = File(project.directory) - val buildDirectory = File(project.classesDir(context)) + val buildDirectory = if (isTest) KFiles.makeOutputTestDir(project) + else File(project.classesDir(context)) buildDirectory.mkdirs() val initialSourceDirectories = arrayListOf() @@ -199,7 +200,7 @@ abstract class JvmCompilerPlugin @Inject constructor( context.pluginInfo.sourceDirectoriesInterceptors.fold(initialSourceDirectories.toList(), { sd, interceptor -> interceptor.intercept(project, context, sd) }) }.filter { - it.exists() + File(project.directory, it.path).exists() } // Now that we have the final list of source dirs, find source files in them diff --git a/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt b/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt index 666c2f9e..5c3e81f9 100644 --- a/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt +++ b/src/main/kotlin/com/beust/kobalt/maven/RepoFinder.kt @@ -49,7 +49,7 @@ public class RepoFinder @Inject constructor(val executors: KobaltExecutors) { for (i in 0..Kobalt.repos.size - 1) { try { val result = cs.take().get(2000, TimeUnit.MILLISECONDS) - log(2, "Result for repo #$i: $result") + log(2, " Result for repo #$i: $result") if (result.found) { log(2, "Located $id in ${result.hostConfig.url}") return result @@ -70,7 +70,7 @@ public class RepoFinder @Inject constructor(val executors: KobaltExecutors) { inner class RepoFinderCallable(val id: String, val repo: HostConfig) : Callable { override fun call(): RepoResult { val repoUrl = repo.url - log(2, "Checking $repoUrl for $id") + log(2, " Checking $repoUrl for $id") val mavenId = MavenId(id) val groupId = mavenId.groupId 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 1b07e960..a591613c 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt @@ -116,18 +116,17 @@ class AndroidBuild { // // Manifest // - val mainManifest = File("src/main/AndroidManifest.xml") - - val appInfo = AppInfo(mainManifest, config) - val manifestOverlays = listOf( - File("src/${variant.productFlavor.name}/AndroidManifest.xml"), - File("src/${variant.buildType.name}/AndroidManifest.xml")).filter { - it.exists() - } + val manifestOverlays = variant.allDirectories(project).map { + File("src/$it/AndroidManifest.xml") + }.filter { + it.exists() + } val libraries = listOf() val outManifest = AndroidFiles.mergedManifest(project, variant) val outAaptSafeManifestLocation = KFiles.joinDir(project.directory, project.buildDirectory, "generatedSafeAapt") val reportFile = File(KFiles.joinDir(project.directory, project.buildDirectory, "manifest-merger-report.txt")) + val mainManifest = File("src/main/AndroidManifest.xml") + val appInfo = AppInfo(mainManifest, config) androidBuilder.mergeManifests(mainManifest, manifestOverlays, libraries, null /* package override */, appInfo.versionCode, 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 3d504e6a..11e864f3 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt @@ -12,9 +12,8 @@ class AndroidFiles { fun intermediates(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory, "intermediates") - fun manifest(project: Project, context: KobaltContext) : String { - return KFiles.joinDir(project.directory, "src/main", "AndroidManifest.xml") - } + fun manifest(project: Project, context: KobaltContext) = + KFiles.joinDir(project.directory, "src", "main", "AndroidManifest.xml") fun mergedManifest(project: Project, variant: Variant) : String { val dir = KFiles.joinAndMakeDir(intermediates(project), "manifests", "full", variant.toIntermediateDir()) 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 9d61a956..92ccda09 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt @@ -164,7 +164,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v * Make sure we compile and generate 1.6 sources unless the build file defined those (which can * happen if the developer is using RetroLambda for example). */ - override fun flagsFor(project: Project, currentFlags: List) : List { + override fun flagsFor(project: Project, context: KobaltContext, currentFlags: List) : List { if (isAndroid(project)) { var found = currentFlags.any { it == "-source" || it == "-target" } val result = arrayListOf().apply { addAll(currentFlags) } @@ -218,7 +218,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v project.compileDependencies).map { it.jarFile.get().path }.filterNot { - it.contains("android.jar") || it.endsWith(".aar") || it.contains("com.android.support") + it.contains("android.jar") || it.endsWith(".aar") || it.contains("retrolambda") }.toHashSet().toTypedArray() @@ -367,13 +367,14 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v } override fun run(project: Project, context: KobaltContext, classpath: List): TaskResult { - val manifest = AndroidFiles.manifest(project, context) - FileInputStream(File(manifest)).use { ins -> - // adb shell am start -n com.package.name/com.package.name.ActivityName - val manifest = AndroidManifest(ins) - RunCommand(adb(project)).useErrorStreamAsErrorIndicator(false).run(args = listOf( - "shell", "am", "start", "-n", manifest.pkg + "/" + manifest.mainActivity)) - return TaskResult() + AndroidFiles.mergedManifest(project, context.variant).let { manifestPath -> + FileInputStream(File(manifestPath)).use { ins -> + // adb shell am start -n com.package.name/com.package.name.ActivityName + val manifest = AndroidManifest(ins) + RunCommand(adb(project)).useErrorStreamAsErrorIndicator(false).run(args = listOf( + "shell", "am", "start", "-n", manifest.pkg + "/" + manifest.mainActivity)) + return TaskResult() + } } } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt index 27558895..7cf40947 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/apt/AptPlugin.kt @@ -19,14 +19,19 @@ import javax.inject.Singleton @Singleton public class AptPlugin @Inject constructor(val depFactory: DepFactory) : ConfigPlugin(), ICompilerFlagContributor { + companion object { const val PLUGIN_NAME = "Apt" } override val name = PLUGIN_NAME + private fun generated(project: Project, context: KobaltContext, outputDir: String) = + KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir, + context.variant.toIntermediateDir()) + // ICompilerFlagContributor - override fun flagsFor(project: Project, currentFlags: List) : List { + override fun flagsFor(project: Project, context: KobaltContext, currentFlags: List) : List { val result = arrayListOf() configurationFor(project)?.let { config -> aptDependencies[project.name]?.let { aptDependencies -> @@ -44,9 +49,8 @@ public class AptPlugin @Inject constructor(val depFactory: DepFactory) result.add("-processorpath") result.add((dependencyJarFiles + dependencies).joinToString(":")) - val generated = KFiles.joinAndMakeDir(project.directory, project.buildDirectory, config.outputDir) result.add("-s") - result.add(generated) + result.add(generated(project, context, config.outputDir)) } log(2, "New flags from apt: " + result.joinToString(" ")) } diff --git a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt index e71c3cbe..42d8c3cf 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaCompiler.kt @@ -9,12 +9,14 @@ import com.beust.kobalt.api.Project import com.beust.kobalt.internal.ICompilerAction import com.beust.kobalt.internal.JvmCompiler import com.beust.kobalt.misc.KFiles -import com.beust.kobalt.misc.log import com.beust.kobalt.misc.warn -import com.beust.kobalt.plugin.android.forward import com.google.inject.Inject import com.google.inject.Singleton import java.io.File +import java.io.PrintWriter +import javax.tools.DiagnosticCollector +import javax.tools.JavaFileObject +import javax.tools.ToolProvider @Singleton class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler) { @@ -25,31 +27,25 @@ class JavaCompiler @Inject constructor(val jvmCompiler: JvmCompiler) { return TaskResult() } - info.outputDir.mkdirs() - val allArgs = arrayListOf( - executable.absolutePath, "-d", KFiles.makeDir(info.directory!!, info.outputDir.path).path) if (info.dependencies.size > 0) { allArgs.add("-classpath") - allArgs.add(info.dependencies.map {it.jarFile.get()}.joinToString(File.pathSeparator)) + allArgs.add(info.dependencies.map { it.jarFile.get() }.joinToString(File.pathSeparator)) } allArgs.addAll(info.compilerArgs) - allArgs.addAll(info.sourceFiles) - val pb = ProcessBuilder(allArgs) -// info.directory?.let { -// pb.directory(File(it)) -// } - pb.inheritIO() - val line = allArgs.joinToString(" ") - log(1, " Compiling ${info.sourceFiles.size} files") - log(2, " Compiling ${line.forward()}") - val process = pb.start() - val errorCode = process.waitFor() + val compiler = ToolProvider.getSystemJavaCompiler() + val fileManager = compiler.getStandardFileManager(null, null, null) + val fileObjects = fileManager.getJavaFileObjectsFromFiles(info.sourceFiles.map { File(it) }) + val dc = DiagnosticCollector() + val classes = arrayListOf() + val task = compiler.getTask(PrintWriter(System.out), fileManager, dc, allArgs, classes, fileObjects) + val result = task.call() - return if (errorCode == 0) TaskResult(true, "Compilation succeeded") + return if (result) TaskResult(true, "Compilation succeeded") else TaskResult(false, "There were errors") + } } diff --git a/src/main/resources/kobalt.properties b/src/main/resources/kobalt.properties index 58905964..ea6bd2cf 100644 --- a/src/main/resources/kobalt.properties +++ b/src/main/resources/kobalt.properties @@ -1 +1 @@ -kobalt.version=0.318 +kobalt.version=0.320