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

Assets for Android.

This commit is contained in:
Cedric Beust 2015-12-08 07:09:11 -08:00
parent 4354d37ecf
commit 896102dedf
12 changed files with 107 additions and 87 deletions

View file

@ -227,25 +227,26 @@ private class Main @Inject constructor(
private fun runClasspathInterceptors(allProjects: List<Project>) {
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<IClasspathDependency>) = with(dependencies) {
val deps = interceptDependencies(pluginInfo, this)
clear()
addAll(deps)
}
private fun runClasspathInterceptors(project: Project, dependencies: ArrayList<IClasspathDependency>)
= with(dependencies) {
val deps = interceptDependencies(project, pluginInfo, this)
clear()
addAll(deps)
}
private fun interceptDependencies(pluginInfo: PluginInfo, dependencies: ArrayList<IClasspathDependency>)
: ArrayList<IClasspathDependency> {
private fun interceptDependencies(project: Project, pluginInfo: PluginInfo,
dependencies: ArrayList<IClasspathDependency>) : ArrayList<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
pluginInfo.classpathInterceptors.forEach {
result.addAll(it.intercept(dependencies))
result.addAll(it.intercept(project, dependencies))
}
return result
}

View file

@ -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<IClasspathDependency>) : List<IClasspathDependency>
fun intercept(project: Project, dependencies: List<IClasspathDependency>) : List<IClasspathDependency>
}

View file

@ -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))

View file

@ -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")

View file

@ -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))

View file

@ -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

View file

@ -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")
}
}

View file

@ -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("")
}
}

View file

@ -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.
*/

View file

@ -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<AndroidConfig>(), 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<File> {
private fun explodeAarFiles(project: Project, resDir: File) : List<File> {
val result = arrayListOf<File>()
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<String>) : List<String> {
if (isAndroid(project)) {
val result = arrayListOf<String>()
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<String>().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<String>, error: List<String>) =
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<IClasspathDependency>): List<IClasspathDependency> {
override fun intercept(project: Project, dependencies: List<IClasspathDependency>): List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
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)
}

View file

@ -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()

View file

@ -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)