1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-27 00:38:11 -07:00

Use android-builder to generate resources.

This commit is contained in:
Cedric Beust 2015-12-08 14:32:37 -08:00
parent 114a2b7a3a
commit e65e111ecb
7 changed files with 87 additions and 85 deletions

View file

@ -3,7 +3,6 @@ package com.beust.kobalt
import com.beust.kobalt.api.* import com.beust.kobalt.api.*
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.log import com.beust.kobalt.misc.log
import com.beust.kobalt.plugin.android.AndroidFiles
import com.beust.kobalt.plugin.android.AndroidPlugin import com.beust.kobalt.plugin.android.AndroidPlugin
import java.io.File 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. * respect the priorities). Return the generated file if it was generated, null otherwise.
*/ */
fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? { fun maybeGenerateBuildConfig(project: Project, context: KobaltContext) : File? {
fun generated(project: Project) = AndroidFiles.generatedSourceDir(project)
val buildConfigs = findBuildConfigs(project, context.variant) val buildConfigs = findBuildConfigs(project, context.variant)
if (buildConfigs.size > 0) { 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") "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 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 // 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 // that directory will be added when trying to find recursively all the sources in it
generatedSourceDirectory = File(result.relativeTo(File(project.directory))) generatedSourceDirectory = File(result.relativeTo(File(project.directory)))

View file

@ -61,6 +61,7 @@ abstract class JvmCompilerPlugin @Inject constructor(
super.apply(project, context) super.apply(project, context)
project.projectProperties.put(DEPENDENT_PROJECTS, projects()) project.projectProperties.put(DEPENDENT_PROJECTS, projects())
taskContributor.addVariantTasks(this, project, context, "compile", runTask = { taskCompile(project) }) taskContributor.addVariantTasks(this, project, context, "compile", runTask = { taskCompile(project) })
sourceDirectories.addAll(context.variant.sourceDirectories(project))
} }
@Task(name = TASK_TEST, description = "Run the tests", @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") @Task(name = JvmCompilerPlugin.TASK_COMPILE, description = "Compile the project")
fun taskCompile(project: Project) : TaskResult { fun taskCompile(project: Project) : TaskResult {
val generatedDir = context.variant.maybeGenerateBuildConfig(project, context) val sourceDirectory = context.variant.maybeGenerateBuildConfig(project, context)
val info = createCompilerActionInfo(project, context, generatedDir, isTest = false) if (sourceDirectory != null) {
sourceDirectories.add(sourceDirectory)
}
val info = createCompilerActionInfo(project, context, isTest = false)
val compiler = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.compilerContributors) val compiler = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.compilerContributors)
if (compiler != null) { if (compiler != null) {
return compiler.compile(project, context, info) return compiler.compile(project, context, info)
@ -151,7 +155,7 @@ abstract class JvmCompilerPlugin @Inject constructor(
fun taskJavadoc(project: Project) : TaskResult { fun taskJavadoc(project: Project) : TaskResult {
val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors) val docGenerator = ActorUtils.selectAffinityActor(project, context, context.pluginInfo.docContributors)
if (docGenerator != null) { if (docGenerator != null) {
return docGenerator.generateDoc(project, context, createCompilerActionInfo(project, context, null, return docGenerator.generateDoc(project, context, createCompilerActionInfo(project, context,
isTest = false)) isTest = false))
} else { } else {
warn("Couldn't find any doc contributor for project ${project.name}") 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. * 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. * Runs all the contributors and interceptors relevant to that task.
*/ */
protected fun createCompilerActionInfo(project: Project, context: KobaltContext, generatedSourceDir: File?, protected fun createCompilerActionInfo(project: Project, context: KobaltContext, isTest: Boolean) :
isTest: Boolean) : CompilerActionInfo { CompilerActionInfo {
copyResources(project, JvmCompilerPlugin.SOURCE_SET_MAIN) copyResources(project, JvmCompilerPlugin.SOURCE_SET_MAIN)
val classpath = if (isTest) val classpath = if (isTest)
@ -178,11 +182,6 @@ abstract class JvmCompilerPlugin @Inject constructor(
val initialSourceDirectories = arrayListOf<File>() val initialSourceDirectories = arrayListOf<File>()
// Add the generated source dir if any
generatedSourceDir?.let {
initialSourceDirectories.add(it)
}
// Source directories from the contributors // Source directories from the contributors
initialSourceDirectories.addAll( initialSourceDirectories.addAll(
if (isTest) { if (isTest) {
@ -213,8 +212,10 @@ abstract class JvmCompilerPlugin @Inject constructor(
return result return result
} }
val sourceDirectories = arrayListOf<File>()
// ISourceDirectoryContributor // ISourceDirectoryContributor
override fun sourceDirectoriesFor(project: Project, context: KobaltContext) override fun sourceDirectoriesFor(project: Project, context: KobaltContext)
= if (accept(project)) context.variant.sourceDirectories(project) else listOf() = if (accept(project)) sourceDirectories else arrayListOf()
} }

View file

@ -2,6 +2,7 @@ package com.beust.kobalt.misc
import com.beust.kobalt.IFileSpec import com.beust.kobalt.IFileSpec
import com.beust.kobalt.SystemProperties import com.beust.kobalt.SystemProperties
import com.beust.kobalt.Variant
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.homeDir import com.beust.kobalt.homeDir
@ -58,6 +59,13 @@ class KFiles {
val TEST_CLASSES_DIR : String = "test-classes" 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. * Join the paths elements with the file separator.
*/ */

View file

@ -1,9 +1,12 @@
package com.beust.kobalt.plugin.android package com.beust.kobalt.plugin.android
import com.android.builder.core.AaptPackageProcessBuilder
import com.android.builder.core.AndroidBuilder import com.android.builder.core.AndroidBuilder
import com.android.builder.core.ErrorReporter import com.android.builder.core.ErrorReporter
import com.android.builder.core.LibraryRequest import com.android.builder.core.LibraryRequest
import com.android.builder.dependency.ManifestDependency 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.model.SyncIssue
import com.android.builder.sdk.DefaultSdkLoader import com.android.builder.sdk.DefaultSdkLoader
import com.android.builder.sdk.SdkLoader 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 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") // 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<File>) { fun run(project: Project, variant: Variant, config: AndroidConfig, aarDependencies: List<File>,
rDirectory: String) {
val logger = StdLogger(StdLogger.Level.VERBOSE) val logger = StdLogger(StdLogger.Level.VERBOSE)
val processExecutor = DefaultProcessExecutor(logger) val processExecutor = DefaultProcessExecutor(logger)
val javaProcessExecutor = KobaltJavaProcessExecutor() val javaProcessExecutor = KobaltJavaProcessExecutor()
@ -95,15 +99,6 @@ class AndroidBuild {
sdkLoader.getTargetInfo(maxPlatformTargetHash, maxPlatformTarget.buildToolInfo.revision, logger), sdkLoader.getTargetInfo(maxPlatformTargetHash, maxPlatformTarget.buildToolInfo.revision, logger),
libraryRequests) 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() val resourceMerger = ResourceMerger()
// //
@ -114,7 +109,6 @@ class AndroidBuild {
aarDependencies.forEach { aarDependencies.forEach {
val assetDir = File(it, "assets") val assetDir = File(it, "assets")
if (assetDir.exists()) { if (assetDir.exists()) {
println("COPY FROM $assetDir TO $intermediates")
KFiles.copyRecursively(assetDir, intermediates) KFiles.copyRecursively(assetDir, intermediates)
} }
} }
@ -168,7 +162,53 @@ class AndroidBuild {
resourceMerger.addDataSet(set) 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) resourceMerger.mergeData(writer, true)
//
// Process resources
//
val aaptOptions = object : AaptOptions {
override fun getAdditionalParameters() = emptyList<String>()
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)
} }
} }

View file

@ -9,8 +9,6 @@ import java.nio.file.Paths
class AndroidFiles { class AndroidFiles {
companion object { companion object {
fun generated(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory, "generated")
fun intermediates(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory, fun intermediates(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory,
"intermediates") "intermediates")
@ -33,6 +31,12 @@ class AndroidFiles {
Paths.get(intermediates(project), "exploded-aar", mavenId.groupId, mavenId.artifactId, mavenId.version, Paths.get(intermediates(project), "exploded-aar", mavenId.groupId, mavenId.artifactId, mavenId.version,
"classes.jar").toFile().path "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. * 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) ?: fun androidHome(project: Project?, config: AndroidConfig) = androidHomeNoThrows(project, config) ?:
throw IllegalArgumentException("Neither androidHome nor \$ANDROID_HOME were defined") throw IllegalArgumentException("Neither androidHome nor \$ANDROID_HOME were defined")
fun generatedSourceDir(project: Project) = KFiles.joinDir(AndroidFiles.generated(project), "source")
} }
} }

View file

@ -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 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) private fun apk(project: Project, flavor: String)
= KFiles.joinFileAndMakeDir(project.buildDirectory, "outputs", "apk", "${project.name}$flavor.apk") = 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 resDir = "temporaryBogusResDir"
val aarDependencies = explodeAarFiles(project, File(resDir)) val aarDependencies = explodeAarFiles(project, File(resDir))
AndroidBuild().run(project, context.variant, configurationFor(project)!!, aarDependencies) val rDirectory = KFiles.joinAndMakeDir(KFiles.generatedSourceDir(project, context.variant, "r"))
// merger.merge(project, context) extraSourceDirectories.add(File(rDirectory))
AndroidBuild().run(project, context.variant, configurationFor(project)!!, aarDependencies, rDirectory)
val notUsed = "" return TaskResult(true)
val generated = AndroidFiles.generated(project)
val success = generateR(project, generated, aapt(project))
return TaskResult(success)
} }
/** /**
@ -117,46 +112,6 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
override fun call(args: List<String>) = super.run(arrayListOf(aaptCommand) + args) override fun call(args: List<String>) = 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, * 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. * 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 { private fun compile(project: Project, rDirectory: String): File {
val sourceFiles = arrayListOf(Paths.get(rDirectory, "R.java").toFile().path) 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 // Using a directory of "." since the project.directory is already present in buildDir
val cai = CompilerActionInfo(".", listOf(), sourceFiles, buildDir, listOf( val cai = CompilerActionInfo(".", listOf(), sourceFiles, buildDir, listOf(
"-source", "1.6", "-target", "1.6")) "-source", "1.6", "-target", "1.6"))
@ -257,8 +212,6 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
val classesDex = "classes.dex" val classesDex = "classes.dex"
val outClassesDex = KFiles.joinDir(classesDexDir, classesDex) 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 javaExecutable = JavaInfo.create(File(SystemProperties.javaBase)).javaExecutable!!
val dependencies = dependencyManager.calculateDependencies(project, context, projects, 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 { AaptCommand(project, aapt(project), "add").apply {
directory = File(outClassesDex).parentFile directory = File(outClassesDex).parentFile
}.call(listOf("-v", KFiles.joinDir( }.call(listOf("-v", KFiles.joinDir(
File(temporaryApk(project, context.variant.shortArchiveName)).absolutePath), classesDex)) File(AndroidFiles.temporaryApk(project, context.variant.shortArchiveName)).absolutePath), classesDex))
return TaskResult() return TaskResult()
} }
@ -313,7 +266,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
runBefore = arrayOf("assemble")) runBefore = arrayOf("assemble"))
fun taskSignApk(project: Project): TaskResult { fun taskSignApk(project: Project): TaskResult {
val apk = apk(project, context.variant.shortArchiveName) 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 buildType = context.variant.buildType.name
val config = configurationFor(project) val config = configurationFor(project)

View file

@ -54,7 +54,7 @@ class JavaPlugin @Inject constructor(
runAfter = arrayOf(JvmCompilerPlugin.TASK_COMPILE)) runAfter = arrayOf(JvmCompilerPlugin.TASK_COMPILE))
fun taskCompileTest(project: Project): TaskResult { fun taskCompileTest(project: Project): TaskResult {
copyResources(project, JvmCompilerPlugin.SOURCE_SET_TEST) 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) val result = javaCompiler.compile(project, context, compilerActionInfo)
return result return result
} }