From e65e111ecbe13c41af49269d6a77ece1582bd380 Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Tue, 8 Dec 2015 14:32:37 -0800 Subject: [PATCH] Use android-builder to generate resources. --- src/main/kotlin/com/beust/kobalt/Variant.kt | 5 +- .../kobalt/internal/JvmCompilerPlugin.kt | 23 +++---- .../kotlin/com/beust/kobalt/misc/KFiles.kt | 8 +++ .../kobalt/plugin/android/AndroidBuild.kt | 64 +++++++++++++++---- .../kobalt/plugin/android/AndroidFiles.kt | 9 ++- .../kobalt/plugin/android/AndroidPlugin.kt | 61 ++---------------- .../beust/kobalt/plugin/java/JavaPlugin.kt | 2 +- 7 files changed, 87 insertions(+), 85 deletions(-) diff --git a/src/main/kotlin/com/beust/kobalt/Variant.kt b/src/main/kotlin/com/beust/kobalt/Variant.kt index 235d04f8..9d903527 100644 --- a/src/main/kotlin/com/beust/kobalt/Variant.kt +++ b/src/main/kotlin/com/beust/kobalt/Variant.kt @@ -3,7 +3,6 @@ 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.AndroidFiles import com.beust.kobalt.plugin.android.AndroidPlugin import java.io.File @@ -129,8 +128,6 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null, * respect the priorities). Return the generated file if it was generated, null otherwise. */ fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? { - fun generated(project: Project) = AndroidFiles.generatedSourceDir(project) - val buildConfigs = findBuildConfigs(project, context.variant) if (buildConfigs.size > 0) { @@ -141,7 +138,7 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null, "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(generated(project)) + val result = KFiles.makeDir(KFiles.generatedSourceDir(project, context.variant, "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/internal/JvmCompilerPlugin.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index 1b7f5267..f253f02a 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -61,6 +61,7 @@ abstract class JvmCompilerPlugin @Inject constructor( super.apply(project, context) project.projectProperties.put(DEPENDENT_PROJECTS, projects()) taskContributor.addVariantTasks(this, project, context, "compile", runTask = { taskCompile(project) }) + sourceDirectories.addAll(context.variant.sourceDirectories(project)) } @Task(name = TASK_TEST, description = "Run the tests", @@ -135,8 +136,11 @@ abstract class JvmCompilerPlugin @Inject constructor( @Task(name = JvmCompilerPlugin.TASK_COMPILE, description = "Compile the project") fun taskCompile(project: Project) : TaskResult { - val generatedDir = context.variant.maybeGenerateBuildConfig(project, context) - val info = createCompilerActionInfo(project, context, generatedDir, isTest = false) + val sourceDirectory = context.variant.maybeGenerateBuildConfig(project, context) + if (sourceDirectory != null) { + sourceDirectories.add(sourceDirectory) + } + val info = createCompilerActionInfo(project, context, isTest = false) val compiler = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.compilerContributors) if (compiler != null) { return compiler.compile(project, context, info) @@ -151,7 +155,7 @@ abstract class JvmCompilerPlugin @Inject constructor( fun taskJavadoc(project: Project) : TaskResult { val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors) if (docGenerator != null) { - return docGenerator.generateDoc(project, context, createCompilerActionInfo(project, context, null, + return docGenerator.generateDoc(project, context, createCompilerActionInfo(project, context, isTest = false)) } else { warn("Couldn't find any doc contributor for project ${project.name}") @@ -163,8 +167,8 @@ abstract class JvmCompilerPlugin @Inject constructor( * Create a CompilerActionInfo (all the information that a compiler needs to know) for the given parameters. * Runs all the contributors and interceptors relevant to that task. */ - protected fun createCompilerActionInfo(project: Project, context: KobaltContext, generatedSourceDir: File?, - isTest: Boolean) : CompilerActionInfo { + protected fun createCompilerActionInfo(project: Project, context: KobaltContext, isTest: Boolean) : + CompilerActionInfo { copyResources(project, JvmCompilerPlugin.SOURCE_SET_MAIN) val classpath = if (isTest) @@ -178,11 +182,6 @@ abstract class JvmCompilerPlugin @Inject constructor( val initialSourceDirectories = arrayListOf() - // Add the generated source dir if any - generatedSourceDir?.let { - initialSourceDirectories.add(it) - } - // Source directories from the contributors initialSourceDirectories.addAll( if (isTest) { @@ -213,8 +212,10 @@ abstract class JvmCompilerPlugin @Inject constructor( return result } + val sourceDirectories = arrayListOf() + // ISourceDirectoryContributor override fun sourceDirectoriesFor(project: Project, context: KobaltContext) - = if (accept(project)) context.variant.sourceDirectories(project) else listOf() + = if (accept(project)) sourceDirectories else arrayListOf() } diff --git a/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt b/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt index 1b3bebf5..9305fed0 100644 --- a/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt +++ b/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt @@ -2,6 +2,7 @@ package com.beust.kobalt.misc import com.beust.kobalt.IFileSpec import com.beust.kobalt.SystemProperties +import com.beust.kobalt.Variant import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Project import com.beust.kobalt.homeDir @@ -58,6 +59,13 @@ class KFiles { val TEST_CLASSES_DIR : String = "test-classes" + private fun generatedDir(project: Project, variant: Variant) + = KFiles.joinDir(project.directory, project.buildDirectory, "generated", variant.toIntermediateDir()) + + fun generatedSourceDir(project: Project, variant: Variant, name: String) = + KFiles.joinDir(project.directory, project.buildDirectory, "generated", "source", name, + variant.toIntermediateDir()) + /** * Join the paths elements with the file separator. */ 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 05cfdaad..1b07e960 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidBuild.kt @@ -1,9 +1,12 @@ package com.beust.kobalt.plugin.android +import com.android.builder.core.AaptPackageProcessBuilder import com.android.builder.core.AndroidBuilder import com.android.builder.core.ErrorReporter import com.android.builder.core.LibraryRequest import com.android.builder.dependency.ManifestDependency +import com.android.builder.dependency.SymbolFileProvider +import com.android.builder.model.AaptOptions import com.android.builder.model.SyncIssue import com.android.builder.sdk.DefaultSdkLoader import com.android.builder.sdk.SdkLoader @@ -67,7 +70,8 @@ class AndroidBuild { // val annotationsJar = File("/Users/beust/adt-bundle-mac-x86_64-20140702/sdk/tools/lib/annotations.jar") // val adb = File("/Users/beust/adt-bundle-mac-x86_64-20140702/sdk/platform-tools/adb") - fun run(project: Project, variant: Variant, config: AndroidConfig, aarDependencies: List) { + fun run(project: Project, variant: Variant, config: AndroidConfig, aarDependencies: List, + rDirectory: String) { val logger = StdLogger(StdLogger.Level.VERBOSE) val processExecutor = DefaultProcessExecutor(logger) val javaProcessExecutor = KobaltJavaProcessExecutor() @@ -95,15 +99,6 @@ class AndroidBuild { sdkLoader.getTargetInfo(maxPlatformTargetHash, maxPlatformTarget.buildToolInfo.revision, logger), libraryRequests) - val writer = MergedResourceWriter(File(outputDir), - androidBuilder.getAaptCruncher(processOutputHandler), - false /* don't crunch */, - false /* don't process 9patch */, - layout.publicText, - layout.mergeBlame, - preprocessor) - val target = androidBuilder.target - val dxJar = androidBuilder.dxJar val resourceMerger = ResourceMerger() // @@ -114,7 +109,6 @@ class AndroidBuild { aarDependencies.forEach { val assetDir = File(it, "assets") if (assetDir.exists()) { - println("COPY FROM $assetDir TO $intermediates") KFiles.copyRecursively(assetDir, intermediates) } } @@ -168,7 +162,53 @@ class AndroidBuild { resourceMerger.addDataSet(set) } - + val writer = MergedResourceWriter(File(outputDir), + androidBuilder.getAaptCruncher(processOutputHandler), + false /* don't crunch */, + false /* don't process 9patch */, + layout.publicText, + layout.mergeBlame, + preprocessor) resourceMerger.mergeData(writer, true) + + // + // Process resources + // + val aaptOptions = object : AaptOptions { + override fun getAdditionalParameters() = emptyList() + override fun getFailOnMissingConfigEntry() = false + override fun getIgnoreAssets() = null + override fun getNoCompress() = null + } + + val aaptCommand = AaptPackageProcessBuilder(File(AndroidFiles.mergedManifest(project, variant)), + aaptOptions) + + fun toSymbolFileProvider(aarDirectory: File) = object: SymbolFileProvider { + override fun getManifest() = File(aarDirectory, "AndroidManifest.xml") + override fun isOptional() = false + override fun getSymbolFile() = File(aarDirectory, "R.txt") + } + + val variantDir = variant.toIntermediateDir() + val generated = KFiles.joinAndMakeDir(project.directory, project.buildDirectory, "symbols") + with(aaptCommand) { + setSourceOutputDir(rDirectory) + val libraries = aarDependencies.map { toSymbolFileProvider(it) } + setLibraries(libraries) + val r = libraries[0].symbolFile + setResFolder(File(AndroidFiles.mergedResources(project, variant))) + setAssetsFolder(File(KFiles.joinAndMakeDir(AndroidFiles.intermediates(project), "assets", variantDir))) + aaptCommand.setResPackageOutput(AndroidFiles.temporaryApk(project, variant.shortArchiveName)) + aaptCommand.setSymbolOutputDir(generated) + +// aaptCommand.setSourceOutputDir(generated) +// aaptCommand.setPackageForR(pkg) +// aaptCommand.setProguardOutput(proguardTxt) +// aaptCommand.setType(if (lib) VariantType.LIBRARY else VariantType.DEFAULT) +// aaptCommand.setDebuggable(debug) + } + + androidBuilder.processResources(aaptCommand, true, processOutputHandler) } } 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 8907ead4..3d504e6a 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidFiles.kt @@ -9,8 +9,6 @@ import java.nio.file.Paths class AndroidFiles { companion object { - fun generated(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory, "generated") - fun intermediates(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory, "intermediates") @@ -33,6 +31,12 @@ class AndroidFiles { Paths.get(intermediates(project), "exploded-aar", mavenId.groupId, mavenId.artifactId, mavenId.version, "classes.jar").toFile().path + fun classesDir(project: Project, variant: Variant): String = + KFiles.joinDir(project.directory, project.buildDirectory, variant.toIntermediateDir(), "classes") + + fun temporaryApk(project: Project, flavor: String) + = KFiles.joinFileAndMakeDir(AndroidFiles.intermediates(project), "res", "resources$flavor.ap_") + /** * Use the android home define on the project if any, otherwise use the environment variable. */ @@ -48,6 +52,5 @@ class AndroidFiles { fun androidHome(project: Project?, config: AndroidConfig) = androidHomeNoThrows(project, config) ?: throw IllegalArgumentException("Neither androidHome nor \$ANDROID_HOME were defined") - fun generatedSourceDir(project: Project) = KFiles.joinDir(AndroidFiles.generated(project), "source") } } 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 2e2c86b4..9d61a956 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt @@ -82,9 +82,6 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v private fun adb(project: Project) = "${androidHome(project)}/platform-tools/adb" - private fun temporaryApk(project: Project, flavor: String) - = KFiles.joinFileAndMakeDir(AndroidFiles.intermediates(project), "res", "resources$flavor.ap_") - private fun apk(project: Project, flavor: String) = KFiles.joinFileAndMakeDir(project.buildDirectory, "outputs", "apk", "${project.name}$flavor.apk") @@ -94,13 +91,11 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v val resDir = "temporaryBogusResDir" val aarDependencies = explodeAarFiles(project, File(resDir)) - AndroidBuild().run(project, context.variant, configurationFor(project)!!, aarDependencies) -// merger.merge(project, context) + val rDirectory = KFiles.joinAndMakeDir(KFiles.generatedSourceDir(project, context.variant, "r")) + extraSourceDirectories.add(File(rDirectory)) + AndroidBuild().run(project, context.variant, configurationFor(project)!!, aarDependencies, rDirectory) - val notUsed = "" - val generated = AndroidFiles.generated(project) - val success = generateR(project, generated, aapt(project)) - return TaskResult(success) + return TaskResult(true) } /** @@ -117,46 +112,6 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v override fun call(args: List) = super.run(arrayListOf(aaptCommand) + args) } - private fun generateR(project: Project, generated: String, aapt: String) : Boolean { - val compileSdkVersion = compileSdkVersion(project) - val androidJar = Paths.get(androidHome(project), "platforms", "android-$compileSdkVersion", "android.jar") - val applicationId = configurationFor(project)?.applicationId!! - val intermediates = AndroidFiles.intermediates(project) - -// AaptCommand(project, aapt, "crunch").call(listOf( -// "-v", -// "-C", mergedResources(project, context.variant), -// "-S", crunchedPngDir -// )) - - val variantDir = context.variant.toIntermediateDir() - - val rDirectory = KFiles.joinAndMakeDir(generated, "source", "r", variantDir).toString() - val result = AaptCommand(project, aapt, "package").call(listOf( - "-f", - "--no-crunch", - "-I", androidJar.toString(), - "-M", AndroidFiles.mergedManifest(project, context.variant), - "-S", AndroidFiles.mergedResources(project, context.variant), - // where to find more assets - "-A", KFiles.joinAndMakeDir(intermediates, "assets", variantDir), - "-m", // create directory - // where all gets generated - "-J", rDirectory, - "-F", temporaryApk(project, context.variant.shortArchiveName), - "--debug-mode", - "-0", "apk", - "--auto-add-overlay", - "--custom-package", applicationId - // "--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)) - return result == 0 - } - /** * 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. @@ -196,7 +151,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v private fun compile(project: Project, rDirectory: String): File { val sourceFiles = arrayListOf(Paths.get(rDirectory, "R.java").toFile().path) - val buildDir = File(AndroidFiles.generated(project), "classes") + val buildDir = File(AndroidFiles.classesDir(project, context.variant)) // Using a directory of "." since the project.directory is already present in buildDir val cai = CompilerActionInfo(".", listOf(), sourceFiles, buildDir, listOf( "-source", "1.6", "-target", "1.6")) @@ -257,8 +212,6 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v val classesDex = "classes.dex" val outClassesDex = KFiles.joinDir(classesDexDir, classesDex) - // 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!! val dependencies = dependencyManager.calculateDependencies(project, context, projects, @@ -292,7 +245,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v AaptCommand(project, aapt(project), "add").apply { directory = File(outClassesDex).parentFile }.call(listOf("-v", KFiles.joinDir( - File(temporaryApk(project, context.variant.shortArchiveName)).absolutePath), classesDex)) + File(AndroidFiles.temporaryApk(project, context.variant.shortArchiveName)).absolutePath), classesDex)) return TaskResult() } @@ -313,7 +266,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v runBefore = arrayOf("assemble")) fun taskSignApk(project: Project): TaskResult { val apk = apk(project, context.variant.shortArchiveName) - val temporaryApk = temporaryApk(project, context.variant.shortArchiveName) + val temporaryApk = AndroidFiles.temporaryApk(project, context.variant.shortArchiveName) val buildType = context.variant.buildType.name val config = configurationFor(project) 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 6e7d0dad..b612f18f 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/java/JavaPlugin.kt @@ -54,7 +54,7 @@ class JavaPlugin @Inject constructor( runAfter = arrayOf(JvmCompilerPlugin.TASK_COMPILE)) fun taskCompileTest(project: Project): TaskResult { copyResources(project, JvmCompilerPlugin.SOURCE_SET_TEST) - val compilerActionInfo = createCompilerActionInfo(project, context, null, isTest = true) + val compilerActionInfo = createCompilerActionInfo(project, context, isTest = true) val result = javaCompiler.compile(project, context, compilerActionInfo) return result }