mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 16:28:12 -07:00
Remove the Android plug-in from the core.
It's now in its own project.
This commit is contained in:
parent
05d4571a9a
commit
643c85f1a4
9 changed files with 1 additions and 1035 deletions
|
@ -115,8 +115,7 @@ val kobaltApp = kotlinProject(kobaltPluginApi, wrapper) {
|
|||
|
||||
dependencies {
|
||||
// Used by the plugins
|
||||
compile("com.android.tools.build:builder:2.0.0-alpha3",
|
||||
"org.jetbrains.kotlin:kotlin-compiler-embeddable:1.0.0-beta-3595",
|
||||
compile("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.0.0-beta-3595",
|
||||
"org.jetbrains.dokka:dokka-fatjar:0.9.3")
|
||||
|
||||
// Used by the main app
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
package com.beust.kobalt.plugin.android
|
||||
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.misc.RunCommand
|
||||
import com.beust.kobalt.misc.log
|
||||
import java.io.File
|
||||
|
||||
open class AndroidCommand(project: Project, androidHome: String, command: String, cwd: File = File(project.directory))
|
||||
: RunCommand(command) {
|
||||
init {
|
||||
env.put("ANDROID_HOME", androidHome)
|
||||
directory = cwd
|
||||
}
|
||||
|
||||
open fun call(args: List<String>) = run(args,
|
||||
successCallback = { output ->
|
||||
log(1, "$command succeeded:")
|
||||
output.forEach {
|
||||
log(1, " $it")
|
||||
}
|
||||
},
|
||||
errorCallback = { output ->
|
||||
with(StringBuilder()) {
|
||||
append("Error running $command:")
|
||||
output.forEach {
|
||||
append(" $it")
|
||||
}
|
||||
error(this.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
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
|
||||
|
||||
class AndroidFiles {
|
||||
companion object {
|
||||
fun intermediates(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory,
|
||||
"intermediates")
|
||||
|
||||
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())
|
||||
return KFiles.joinDir(dir, "AndroidManifest.xml")
|
||||
}
|
||||
|
||||
fun mergedResourcesNoVariant(project: Project) =
|
||||
KFiles.joinAndMakeDir(AndroidFiles.intermediates(project), "res", "merged")
|
||||
|
||||
fun mergedResources(project: Project, variant: Variant) =
|
||||
KFiles.joinAndMakeDir(mergedResourcesNoVariant(project), variant.toIntermediateDir())
|
||||
|
||||
fun exploded(project: Project, mavenId: MavenId) = KFiles.joinAndMakeDir(
|
||||
intermediates(project), "exploded-aar", mavenId.groupId, mavenId.artifactId, mavenId.version!!)
|
||||
|
||||
fun explodedManifest(project: Project, mavenId: MavenId) =
|
||||
KFiles.joinDir(exploded(project, mavenId), "AndroidManifest.xml")
|
||||
|
||||
fun aarClassesJar(dir: String) = KFiles.joinDir(dir, "classes.jar")
|
||||
|
||||
fun explodedClassesJar(project: Project, mavenId: MavenId) = aarClassesJar(
|
||||
KFiles.joinDir(exploded(project, mavenId)))
|
||||
|
||||
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.
|
||||
*/
|
||||
fun androidHomeNoThrows(project: Project?, config: AndroidConfig?): String? {
|
||||
var result = System.getenv("ANDROID_HOME")
|
||||
if (project != null && config?.androidHome != null) {
|
||||
result = config?.androidHome
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun androidHome(project: Project?, config: AndroidConfig) = androidHomeNoThrows(project, config) ?:
|
||||
throw IllegalArgumentException("Neither androidHome nor \$ANDROID_HOME were defined")
|
||||
|
||||
fun preDexed(project: Project, variant: Variant) =
|
||||
KFiles.joinAndMakeDir(intermediates(project), "pre-dexed", variant.toIntermediateDir())
|
||||
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
package com.beust.kobalt.plugin.android
|
||||
|
||||
import java.io.InputStream
|
||||
import javax.xml.bind.JAXBContext
|
||||
import javax.xml.bind.annotation.XmlAttribute
|
||||
import javax.xml.bind.annotation.XmlElement
|
||||
import javax.xml.bind.annotation.XmlRootElement
|
||||
|
||||
/**
|
||||
* Parse AndroidManifest.xml and expose its content.
|
||||
*/
|
||||
class AndroidManifest(val ins: InputStream) {
|
||||
companion object {
|
||||
const val NAMESPACE = "http://schemas.android.com/apk/res/android"
|
||||
}
|
||||
|
||||
val manifest: AndroidManifestXml by lazy {
|
||||
val jaxbContext = JAXBContext.newInstance(AndroidManifestXml::class.java)
|
||||
jaxbContext.createUnmarshaller().unmarshal(ins) as AndroidManifestXml
|
||||
}
|
||||
|
||||
val pkg by lazy {
|
||||
manifest.pkg
|
||||
}
|
||||
|
||||
val mainActivity: String? by lazy {
|
||||
fun isLaunch(act: ActivityXml) : Boolean {
|
||||
val r = act.intentFilters.filter { inf: IntentFilter ->
|
||||
inf.action?.name == "android.intent.action.MAIN" &&
|
||||
inf.category?.name == "android.intent.category.LAUNCHER"
|
||||
}
|
||||
return r.size > 0
|
||||
}
|
||||
val act = manifest.application?.activities?.filter { isLaunch(it) }
|
||||
if (act != null && act.size > 0) {
|
||||
act.get(0).name?.let { n ->
|
||||
if (n.startsWith(".")) pkg + "." + n.substring(1) else n
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@XmlRootElement(name = "manifest")
|
||||
class AndroidManifestXml {
|
||||
@XmlAttribute(name = "package") @JvmField
|
||||
val pkg: String? = null
|
||||
var application: ApplicationXml? = null
|
||||
}
|
||||
|
||||
class ApplicationXml {
|
||||
@XmlElement(name = "activity") @JvmField
|
||||
var activities: List<ActivityXml> = arrayListOf()
|
||||
}
|
||||
|
||||
class ActivityXml {
|
||||
@XmlAttribute(namespace = AndroidManifest.NAMESPACE, name = "name") @JvmField
|
||||
var name: String? = null
|
||||
|
||||
@XmlElement(name = "intent-filter") @JvmField
|
||||
var intentFilters: List<IntentFilter> = arrayListOf()
|
||||
}
|
||||
|
||||
class IntentFilter {
|
||||
var action: ActionXml? = null
|
||||
var category: CategoryXml? = null
|
||||
}
|
||||
|
||||
class ActionXml {
|
||||
@XmlAttribute(namespace = AndroidManifest.NAMESPACE, name = "name") @JvmField
|
||||
var name: String? = null
|
||||
}
|
||||
|
||||
class CategoryXml {
|
||||
@XmlAttribute(namespace = AndroidManifest.NAMESPACE, name = "name") @JvmField
|
||||
var name: String? = null
|
||||
}
|
|
@ -1,535 +0,0 @@
|
|||
package com.beust.kobalt.plugin.android
|
||||
|
||||
import com.beust.kobalt.*
|
||||
import com.beust.kobalt.api.*
|
||||
import com.beust.kobalt.api.annotation.Directive
|
||||
import com.beust.kobalt.api.annotation.IncrementalTask
|
||||
import com.beust.kobalt.api.annotation.Task
|
||||
import com.beust.kobalt.maven.DependencyManager
|
||||
import com.beust.kobalt.maven.MavenId
|
||||
import com.beust.kobalt.maven.Md5
|
||||
import com.beust.kobalt.maven.dependency.FileDependency
|
||||
import com.beust.kobalt.maven.dependency.MavenDependency
|
||||
import com.beust.kobalt.misc.*
|
||||
import com.beust.kobalt.plugin.java.JavaCompiler
|
||||
import com.google.common.collect.HashMultimap
|
||||
import com.google.inject.Inject
|
||||
import com.google.inject.Singleton
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* The Android plug-in which executes:
|
||||
* library dependencies (android.library.reference.N)
|
||||
* ndk
|
||||
* aidl
|
||||
* renderscript
|
||||
* BuildConfig.java
|
||||
* aapt
|
||||
* compile
|
||||
* obfuscate
|
||||
* dex
|
||||
* png crunch
|
||||
* package resources
|
||||
* package apk
|
||||
* sign
|
||||
* zipalign
|
||||
*/
|
||||
@Singleton
|
||||
public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler,
|
||||
val executors: KobaltExecutors, val dependencyManager: DependencyManager, val taskContributor : TaskContributor)
|
||||
: ConfigPlugin<AndroidConfig>(), IClasspathContributor, IRepoContributor, ICompilerFlagContributor,
|
||||
ICompilerInterceptor, IBuildDirectoryIncerceptor, IRunnerContributor, IClasspathInterceptor,
|
||||
ISourceDirectoryContributor, IBuildConfigFieldContributor, ITaskContributor, IMavenIdInterceptor {
|
||||
companion object {
|
||||
const val PLUGIN_NAME = "Android"
|
||||
const val TASK_GENERATE_DEX = "generateDex"
|
||||
const val TASK_SIGN_APK = "signApk"
|
||||
const val TASK_INSTALL= "install"
|
||||
}
|
||||
|
||||
override val name = PLUGIN_NAME
|
||||
|
||||
fun isAndroid(project: Project) = configurationFor(project) != null
|
||||
|
||||
override fun apply(project: Project, context: KobaltContext) {
|
||||
super.apply(project, context)
|
||||
if (accept(project)) {
|
||||
project.compileDependencies.add(FileDependency(androidJar(project).toString()))
|
||||
|
||||
taskContributor.addVariantTasks(this, project, context, "generateR", runBefore = listOf("compile"),
|
||||
runTask = { taskGenerateRFile(project) })
|
||||
taskContributor.addIncrementalVariantTasks(this, project, context, "generateDex",
|
||||
runAfter = listOf ("compile"),
|
||||
runBefore = listOf("assemble"),
|
||||
runTask = { taskGenerateDex(project) })
|
||||
taskContributor.addVariantTasks(this, project, context, "signApk", runAfter = listOf("generateDex"),
|
||||
runBefore = listOf("assemble"),
|
||||
runTask = { taskSignApk(project) })
|
||||
taskContributor.addVariantTasks(this, project, context, "install", runAfter = listOf("signApk"),
|
||||
runTask = { taskInstall(project) })
|
||||
taskContributor.addVariantTasks(this, project, context, "proguard", runBefore = listOf("install"),
|
||||
runAfter = listOf("compile"),
|
||||
runTask = { taskProguard(project) })
|
||||
}
|
||||
context.pluginInfo.classpathContributors.add(this)
|
||||
}
|
||||
|
||||
|
||||
override fun accept(project: Project) = isAndroid(project)
|
||||
|
||||
fun compileSdkVersion(project: Project) = configurationFor(project)?.compileSdkVersion
|
||||
|
||||
fun buildToolsVersion(project: Project): String {
|
||||
val version = configurationFor(project)?.buildToolsVersion
|
||||
if (OperatingSystem.current().isWindows() && version == "21.1.2")
|
||||
return "build-tools-$version"
|
||||
else
|
||||
return version as String
|
||||
}
|
||||
|
||||
fun androidHome(project: Project?) = AndroidFiles.androidHome(project, configurationFor(project)!!)
|
||||
|
||||
fun androidJar(project: Project): Path =
|
||||
Paths.get(androidHome(project), "platforms", "android-${compileSdkVersion(project)}", "android.jar")
|
||||
|
||||
private fun aapt(project: Project) = "${androidHome(project)}/build-tools/${buildToolsVersion(project)}/aapt"
|
||||
|
||||
private fun adb(project: Project) = "${androidHome(project)}/platform-tools/adb"
|
||||
|
||||
private fun apk(project: Project, flavor: String)
|
||||
= KFiles.joinFileAndMakeDir(project.buildDirectory, "outputs", "apk", "${project.name}$flavor.apk")
|
||||
|
||||
private val preDexFiles = arrayListOf<String>()
|
||||
|
||||
@Task(name = "generateR", description = "Generate the R.java file",
|
||||
runBefore = arrayOf("compile"), runAfter = arrayOf("clean"))
|
||||
fun taskGenerateRFile(project: Project): TaskResult {
|
||||
|
||||
val aarDependencies = explodeAarFiles(project)
|
||||
preDexFiles.addAll(preDex(project, context.variant, aarDependencies))
|
||||
val rDirectory = KFiles.joinAndMakeDir(KFiles.generatedSourceDir(project, context.variant, "r"))
|
||||
extraSourceDirectories.add(File(rDirectory))
|
||||
KobaltResourceMerger().run(project, context.variant, configurationFor(project)!!, aarDependencies, rDirectory)
|
||||
|
||||
return TaskResult(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Predex all the libraries that need to be predexed then return a list of them.
|
||||
*/
|
||||
private fun preDex(project: Project, variant: Variant, aarDependencies: List<File>) : List<String> {
|
||||
log(2, "Predexing")
|
||||
val result = arrayListOf<String>()
|
||||
val aarFiles = aarDependencies.map { File(AndroidFiles.aarClassesJar(it.path))}
|
||||
val jarFiles = dependencies(project).map { File(it) }
|
||||
val allDependencies = (aarFiles + jarFiles).toHashSet().filter { it.exists() }
|
||||
|
||||
allDependencies.forEach { dep ->
|
||||
val versionFile = File(dep.path).parentFile
|
||||
val artifactFile = versionFile.parentFile
|
||||
val name = artifactFile.name + "-" + versionFile.name
|
||||
val outputDir = AndroidFiles.preDexed(project, variant)
|
||||
val outputFile = File(outputDir, name + ".jar")
|
||||
if (! outputFile.exists()) {
|
||||
log(2, " Predexing $dep")
|
||||
runDex(project, outputFile.path, dep.path)
|
||||
} else {
|
||||
log(2, " $dep already predexed")
|
||||
}
|
||||
result.add(outputFile.path)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* aapt returns 0 even if it fails, so in order to detect whether it failed, we are checking
|
||||
* if its error stream contains anything.
|
||||
*/
|
||||
inner class AaptCommand(project: Project, aapt: String, val aaptCommand: String,
|
||||
cwd: File = File(".")) : AndroidCommand(project, androidHome(project), aapt) {
|
||||
init {
|
||||
directory = cwd
|
||||
useErrorStreamAsErrorIndicator = true
|
||||
}
|
||||
|
||||
override fun call(args: List<String>) = super.run(arrayListOf(aaptCommand) + args)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) : List<File> {
|
||||
log(2, "Exploding aars")
|
||||
val result = arrayListOf<File>()
|
||||
project.compileDependencies.filter {
|
||||
it.jarFile.get().name.endsWith(".aar")
|
||||
}.forEach {
|
||||
val mavenId = MavenId.create(it.id)
|
||||
val destDir = File(AndroidFiles.exploded(project, mavenId))
|
||||
if (!File(AndroidFiles.explodedManifest(project, mavenId)).exists()) {
|
||||
log(2, " Exploding ${it.jarFile.get()} to $destDir")
|
||||
JarUtils.extractJarFile(it.jarFile.get(), destDir)
|
||||
} else {
|
||||
log(2, " $destDir already exists, not extracting again")
|
||||
}
|
||||
val classesJar = AndroidFiles.explodedClassesJar(project, mavenId)
|
||||
|
||||
// Add the classses.jar of this .aar to the classpath entries (which are returned via IClasspathContributor)
|
||||
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()) {
|
||||
libsDir.listFiles().filter { it.name.endsWith(".jar") }.forEach {
|
||||
classpathEntries.put(project.name, FileDependency(it.absolutePath))
|
||||
}
|
||||
}
|
||||
}
|
||||
result.add(destDir)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ICompilerFlagContributor
|
||||
* 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, context: KobaltContext, currentFlags: List<String>) : List<String> {
|
||||
if (isAndroid(project)) {
|
||||
var found = currentFlags.any { it == "-source" || it == "-target" }
|
||||
val result = arrayListOf<String>().apply { addAll(currentFlags) }
|
||||
if (! found) {
|
||||
result.add("-source")
|
||||
result.add("1.6")
|
||||
result.add("-target")
|
||||
result.add("1.6")
|
||||
result.add("-nowarn")
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
@Task(name = "proguard", description = "Run Proguard, if enabled", runBefore = arrayOf(TASK_GENERATE_DEX),
|
||||
runAfter = arrayOf("compile"))
|
||||
fun taskProguard(project: Project): TaskResult {
|
||||
val config = configurationFor(project)
|
||||
if (config != null) {
|
||||
val buildType = context.variant.buildType
|
||||
if (buildType.minifyEnabled) {
|
||||
log(1, "minifyEnabled is true, running Proguard")
|
||||
val classesDir = project.classesDir(context)
|
||||
val proguardHome = KFiles.joinDir(androidHome(project), "tools", "proguard")
|
||||
val proguardCommand = KFiles.joinDir(proguardHome, "bin", "proguard.sh")
|
||||
}
|
||||
}
|
||||
return TaskResult()
|
||||
}
|
||||
|
||||
private fun dependencies(project: Project) = dependencyManager.calculateDependencies(project, context, projects,
|
||||
project.compileDependencies).map {
|
||||
it.jarFile.get().path
|
||||
}.filterNot {
|
||||
it.contains("android.jar") || it.endsWith(".aar") || it.contains("retrolambda")
|
||||
}.toHashSet().toTypedArray()
|
||||
|
||||
class DexCommand : RunCommand("java") {
|
||||
override fun isSuccess(callSucceeded: Boolean, input: List<String>, error: List<String>) =
|
||||
error.size == 0
|
||||
}
|
||||
|
||||
private fun inputChecksum(classDirectory: String) = Md5.toMd5Directories(listOf(File(classDirectory)))
|
||||
|
||||
private fun runDex(project: Project, outputJarFile: String, target: String) {
|
||||
// DexProcessBuilder(File(jarFile)).
|
||||
DexCommand().run(listOf(
|
||||
"-cp", KFiles.joinDir(androidHome(project), "build-tools", buildToolsVersion(project), "lib", "dx.jar"),
|
||||
"com.android.dx.command.Main",
|
||||
"--dex",
|
||||
if (KobaltLogger.LOG_LEVEL == 3) "--verbose" else "",
|
||||
"--num-threads=4",
|
||||
"--output", outputJarFile,
|
||||
*(preDexFiles.toTypedArray()),
|
||||
target
|
||||
).filter { it != "" })
|
||||
}
|
||||
|
||||
@IncrementalTask(name = TASK_GENERATE_DEX, description = "Generate the dex file", runBefore = arrayOf("assemble"),
|
||||
runAfter = arrayOf("compile"))
|
||||
fun taskGenerateDex(project: Project): IncrementalTaskInfo {
|
||||
File(project.classesDir(context)).mkdirs()
|
||||
return IncrementalTaskInfo(
|
||||
inputChecksum = inputChecksum(project.classesDir(context)),
|
||||
outputChecksum = "1",
|
||||
task = { project -> doTaskGenerateDex(project) }
|
||||
)
|
||||
}
|
||||
|
||||
fun doTaskGenerateDex(project: Project): TaskResult {
|
||||
//
|
||||
// Call dx to generate classes.dex
|
||||
//
|
||||
val buildToolsDir = buildToolsVersion(project)
|
||||
val dx = "${androidHome(project)}/build-tools/$buildToolsDir/dx" +
|
||||
if (OperatingSystem.current().isWindows()) ".bat" else ""
|
||||
val classesDexDir = KFiles.joinDir(AndroidFiles.intermediates(project), "dex",
|
||||
context.variant.toIntermediateDir())
|
||||
File(classesDexDir).mkdirs()
|
||||
val classesDex = "classes.dex"
|
||||
val outClassesDex = KFiles.joinDir(classesDexDir, classesDex)
|
||||
|
||||
runDex(project, outClassesDex, project.classesDir(context))
|
||||
|
||||
//
|
||||
// Add classes.dex to existing .ap_
|
||||
// Because aapt doesn't handle directory moving, we need to cd to classes.dex's directory so
|
||||
// that classes.dex ends up in the root directory of the .ap_.
|
||||
//
|
||||
AaptCommand(project, aapt(project), "add").apply {
|
||||
directory = File(outClassesDex).parentFile
|
||||
}.call(listOf("-v", KFiles.joinDir(
|
||||
File(AndroidFiles.temporaryApk(project, context.variant.shortArchiveName)).absolutePath), classesDex))
|
||||
|
||||
return TaskResult()
|
||||
}
|
||||
|
||||
private val DEFAULT_DEBUG_SIGNING_CONFIG = SigningConfig(
|
||||
SigningConfig.DEFAULT_STORE_FILE,
|
||||
SigningConfig.DEFAULT_STORE_PASSWORD,
|
||||
SigningConfig.DEFAULT_KEY_ALIAS,
|
||||
SigningConfig.DEFAULT_KEY_PASSWORD)
|
||||
|
||||
/**
|
||||
* Sign the apk
|
||||
* Mac:
|
||||
* jarsigner -keystore ~/.android/debug.keystore -storepass android -keypass android -signedjar a.apk a.ap_
|
||||
* androiddebugkey
|
||||
*/
|
||||
@Task(name = TASK_SIGN_APK, description = "Sign the apk file", runAfter = arrayOf(TASK_GENERATE_DEX),
|
||||
runBefore = arrayOf("assemble"))
|
||||
fun taskSignApk(project: Project): TaskResult {
|
||||
val apk = apk(project, context.variant.shortArchiveName)
|
||||
val temporaryApk = AndroidFiles.temporaryApk(project, context.variant.shortArchiveName)
|
||||
val buildType = context.variant.buildType.name
|
||||
|
||||
val config = configurationFor(project)
|
||||
var signingConfig = config!!.signingConfigs[buildType]
|
||||
|
||||
if (signingConfig == null && buildType != "debug") {
|
||||
warn("No signingConfig found for product type \"$buildType\", using the \"debug\" signConfig")
|
||||
}
|
||||
|
||||
signingConfig = DEFAULT_DEBUG_SIGNING_CONFIG
|
||||
|
||||
val success = RunCommand("jarsigner").apply {
|
||||
// useInputStreamAsErrorIndicator = true
|
||||
}.run(listOf(
|
||||
"-keystore", signingConfig.storeFile,
|
||||
"-storepass", signingConfig.storePassword,
|
||||
"-keypass", signingConfig.keyPassword,
|
||||
"-signedjar", apk,
|
||||
temporaryApk,
|
||||
signingConfig.keyAlias
|
||||
))
|
||||
log(1, "Created $apk")
|
||||
|
||||
return TaskResult(success == 0)
|
||||
}
|
||||
|
||||
@Task(name = TASK_INSTALL, description = "Install the apk file", runAfter = arrayOf(TASK_GENERATE_DEX, "assemble"))
|
||||
fun taskInstall(project: Project): TaskResult {
|
||||
|
||||
/**
|
||||
* adb has weird ways of signaling errors, that's the best I've found so far.
|
||||
*/
|
||||
class AdbInstall : RunCommand(adb(project)) {
|
||||
override fun isSuccess(callSucceeded: Boolean, input: List<String>, error: List<String>)
|
||||
= input.filter { it.contains("Success")}.size > 0
|
||||
}
|
||||
|
||||
val apk = apk(project, context.variant.shortArchiveName)
|
||||
val result = AdbInstall().useErrorStreamAsErrorIndicator(true).run(
|
||||
args = listOf("install", "-r", apk))
|
||||
log(1, "Installed $apk")
|
||||
return TaskResult(result == 0)
|
||||
}
|
||||
|
||||
private val classpathEntries = HashMultimap.create<String, IClasspathDependency>()
|
||||
|
||||
// IClasspathContributor
|
||||
override fun entriesFor(project: Project?): Collection<IClasspathDependency> {
|
||||
return if (project != null) {
|
||||
classpathEntries.get(project.name) ?: emptyList()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
// IRepoContributor
|
||||
override fun reposFor(project: Project?): List<HostConfig> {
|
||||
val config = configurationFor(project)
|
||||
var home = AndroidFiles.androidHomeNoThrows(project, config)
|
||||
|
||||
return if (home != null) {
|
||||
val path = Paths.get(KFiles.joinDir(home, "extras", "android", "m2repository"))
|
||||
listOf(HostConfig(path.toUri().toString()))
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
// IBuildDirectoryInterceptor
|
||||
override fun intercept(project: Project, context: KobaltContext, buildDirectory: String): String {
|
||||
if (isAndroid(project)) {
|
||||
val result = KFiles.joinDir(AndroidFiles.intermediates(project), "classes",
|
||||
context.variant.toIntermediateDir())
|
||||
return result
|
||||
} else {
|
||||
return buildDirectory
|
||||
}
|
||||
}
|
||||
|
||||
// ICompilerInterceptor
|
||||
override fun intercept(project: Project, context: KobaltContext, actionInfo: CompilerActionInfo)
|
||||
: CompilerActionInfo {
|
||||
val result: CompilerActionInfo =
|
||||
if (isAndroid(project)) {
|
||||
val newOutputDir = KFiles.joinDir("kobaltBuild", "intermediates", "classes",
|
||||
context.variant.toIntermediateDir())
|
||||
actionInfo.copy(outputDir = File(newOutputDir))
|
||||
} else {
|
||||
actionInfo
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// IRunContributor
|
||||
override fun affinity(project: Project, context: KobaltContext): Int {
|
||||
val manifest = AndroidFiles.manifest(project, context)
|
||||
return if (File(manifest).exists()) IAffinity.DEFAULT_POSITIVE_AFFINITY else 0
|
||||
}
|
||||
|
||||
override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>): 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAar(id: MavenId) = id.groupId == "com.android.support" && id.artifactId != "support-annotations"
|
||||
|
||||
/**
|
||||
* For each com.android.support dependency or aar packaging, add a classpath dependency that points to the
|
||||
* classes.jar inside that (exploded) aar.
|
||||
*/
|
||||
// IClasspathInterceptor
|
||||
override fun intercept(project: Project, dependencies: List<IClasspathDependency>): List<IClasspathDependency> {
|
||||
val result = arrayListOf<IClasspathDependency>()
|
||||
dependencies.forEach {
|
||||
if (it is MavenDependency && (isAar(it.mavenId) || it.mavenId.packaging == "aar")) {
|
||||
val newDep = FileDependency(AndroidFiles.explodedClassesJar(project, it.mavenId))
|
||||
result.add(newDep)
|
||||
val id = MavenId.create(it.groupId, it.artifactId, "aar", it.version)
|
||||
result.add(MavenDependency.create(id))
|
||||
} else {
|
||||
result.add(it)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// IMavenIdInterceptor
|
||||
override fun intercept(mavenId: MavenId) : MavenId =
|
||||
if (isAar(mavenId)) {
|
||||
val version = mavenId.version ?: ""
|
||||
MavenId.createNoInterceptors("${mavenId.groupId}:${mavenId.artifactId}:$version@aar")
|
||||
} else {
|
||||
mavenId
|
||||
}
|
||||
|
||||
private val extraSourceDirectories = arrayListOf<File>()
|
||||
|
||||
// ISourceDirectoryContributor
|
||||
override fun sourceDirectoriesFor(project: Project, context: KobaltContext): List<File> = extraSourceDirectories
|
||||
|
||||
// IBuildConfigFieldContributor
|
||||
override fun fieldsFor(project: Project, context: KobaltContext): List<BuildConfigField> {
|
||||
val result = arrayListOf<BuildConfigField>()
|
||||
configurationFor(project)?.let { config ->
|
||||
result.add(BuildConfigField("String", "VERSION_NAME", "\"${config.defaultConfig.versionName}\""))
|
||||
result.add(BuildConfigField("int", "VERSION_CODE", "${config.defaultConfig.versionCode}"))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
//ITaskContributor
|
||||
override fun tasksFor(context: KobaltContext): List<DynamicTask> = taskContributor.dynamicTasks
|
||||
}
|
||||
|
||||
class DefaultConfig(var minSdkVersion: Int? = null,
|
||||
val maxSdkVersion: String? = null,
|
||||
var targetSdkVersion: String? = null,
|
||||
var versionCode: Int? = null,
|
||||
var versionName: String? = null) {
|
||||
var buildConfig : BuildConfig? = BuildConfig()
|
||||
}
|
||||
|
||||
class AndroidConfig(val project: Project,
|
||||
var compileSdkVersion : String? = null,
|
||||
var buildToolsVersion: String? = null,
|
||||
var applicationId: String? = null,
|
||||
val androidHome: String? = null) {
|
||||
|
||||
val signingConfigs = hashMapOf<String, SigningConfig>()
|
||||
|
||||
fun addSigningConfig(name: String, project: Project, signingConfig: SigningConfig) {
|
||||
signingConfigs.put(name, signingConfig)
|
||||
}
|
||||
|
||||
var defaultConfig: DefaultConfig = DefaultConfig()
|
||||
|
||||
fun defaultConfig(init: DefaultConfig.() -> Unit) {
|
||||
defaultConfig = DefaultConfig().apply { init() }
|
||||
}
|
||||
}
|
||||
|
||||
@Directive
|
||||
fun Project.android(init: AndroidConfig.() -> Unit) : AndroidConfig = let { project ->
|
||||
return AndroidConfig(project).apply {
|
||||
init()
|
||||
(Kobalt.findPlugin(AndroidPlugin.PLUGIN_NAME) as AndroidPlugin).addConfiguration(project, this)
|
||||
}
|
||||
}
|
||||
|
||||
class SigningConfig(var storeFile: String = SigningConfig.DEFAULT_STORE_FILE,
|
||||
var storePassword: String = SigningConfig.DEFAULT_STORE_PASSWORD,
|
||||
var keyAlias: String = SigningConfig.DEFAULT_KEY_ALIAS,
|
||||
var keyPassword: String = SigningConfig.DEFAULT_KEY_ALIAS) {
|
||||
|
||||
companion object {
|
||||
val DEFAULT_STORE_FILE = homeDir(".android", "debug.keystore")
|
||||
val DEFAULT_STORE_PASSWORD = "android"
|
||||
val DEFAULT_KEY_ALIAS = "androiddebugkey"
|
||||
val DEFAULT_KEY_PASSWORD = "android"
|
||||
}
|
||||
}
|
||||
|
||||
@Directive
|
||||
fun AndroidConfig.signingConfig(name: String, init: SigningConfig.() -> Unit) : SigningConfig = let { androidConfig ->
|
||||
SigningConfig().apply {
|
||||
init()
|
||||
androidConfig.addSigningConfig(name, project, this)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package com.beust.kobalt.plugin.android
|
||||
|
||||
import com.android.io.FileWrapper
|
||||
import com.android.xml.AndroidManifest
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Manage the main application id for the app: values from androidConfig{} have precedence over values
|
||||
* found in the manifest.
|
||||
*/
|
||||
class AppInfo(val androidManifest: File, val config: AndroidConfig) {
|
||||
val abstractManifest = FileWrapper(androidManifest)
|
||||
|
||||
val versionCode : Int
|
||||
get() = config.defaultConfig.versionCode ?: AndroidManifest.getVersionCode(abstractManifest)
|
||||
|
||||
val versionName : String
|
||||
get() = config.defaultConfig.versionName ?: versionCode.toString()
|
||||
|
||||
val minSdkVersion: Int
|
||||
get() = config.defaultConfig.minSdkVersion ?: (AndroidManifest.getMinSdkVersion(abstractManifest) as Int)
|
||||
|
||||
val maxSdkVersion: Int?
|
||||
get() = config.defaultConfig.maxSdkVersion?.toInt()
|
||||
|
||||
val targetSdkVersion: String?
|
||||
get() = config.defaultConfig.targetSdkVersion
|
||||
?: AndroidManifest.getTargetSdkVersion(abstractManifest)?.toString()
|
||||
}
|
|
@ -1,283 +0,0 @@
|
|||
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
|
||||
import com.android.ide.common.blame.Message
|
||||
import com.android.ide.common.internal.ExecutorSingleton
|
||||
import com.android.ide.common.process.*
|
||||
import com.android.ide.common.res2.*
|
||||
import com.android.manifmerger.ManifestMerger2
|
||||
import com.android.sdklib.AndroidTargetHash
|
||||
import com.android.sdklib.SdkManager
|
||||
import com.android.utils.ILogger
|
||||
import com.android.utils.StdLogger
|
||||
import com.beust.kobalt.Variant
|
||||
import com.beust.kobalt.api.IClasspathDependency
|
||||
import com.beust.kobalt.api.Project
|
||||
import com.beust.kobalt.maven.dependency.MavenDependency
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.KobaltLogger
|
||||
import com.beust.kobalt.misc.log
|
||||
import com.beust.kobalt.misc.logWrap
|
||||
import java.io.File
|
||||
|
||||
class KobaltProcessResult : ProcessResult {
|
||||
override fun getExitValue(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun assertNormalExitValue(): ProcessResult? {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun rethrowFailure(): ProcessResult? {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
class KobaltJavaProcessExecutor : JavaProcessExecutor {
|
||||
override fun execute(javaProcessInfo: JavaProcessInfo?, processOutputHandler: ProcessOutputHandler?)
|
||||
: ProcessResult? {
|
||||
log(1, "Executing " + javaProcessInfo!!)
|
||||
return KobaltProcessResult()
|
||||
}
|
||||
}
|
||||
|
||||
class KobaltProcessOutputHandler : BaseProcessOutputHandler() {
|
||||
override fun handleOutput(processOutput: ProcessOutput) =
|
||||
log(3, "AndroidBuild output" + processOutput.standardOutput)
|
||||
}
|
||||
|
||||
class KobaltErrorReporter : ErrorReporter(ErrorReporter.EvaluationMode.STANDARD) {
|
||||
override fun handleSyncError(data: String?, type: Int, msg: String?): SyncIssue? {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun receiveMessage(message: Message?) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
class ProjectLayout {
|
||||
val mergeBlame: File? = null
|
||||
val publicText: File? = null
|
||||
|
||||
}
|
||||
|
||||
class KobaltResourceMerger {
|
||||
fun run(project: Project, variant: Variant, config: AndroidConfig, aarDependencies: List<File>,
|
||||
rDirectory: String) {
|
||||
val level = when(KobaltLogger.LOG_LEVEL) {
|
||||
3 -> StdLogger.Level.VERBOSE
|
||||
2 -> StdLogger.Level.WARNING
|
||||
else -> StdLogger.Level.ERROR
|
||||
}
|
||||
val logger = StdLogger(level)
|
||||
val androidBuilder = createAndroidBuilder(project, config, logger)
|
||||
|
||||
log(2, "Merging resources")
|
||||
|
||||
//
|
||||
// Assets
|
||||
//
|
||||
processAssets(project, variant, androidBuilder, aarDependencies)
|
||||
|
||||
//
|
||||
// Manifests
|
||||
//
|
||||
val appInfo = processManifests(project, variant, androidBuilder, config)
|
||||
|
||||
//
|
||||
// Resources
|
||||
//
|
||||
KobaltProcessOutputHandler().let {
|
||||
processResources(project, variant, androidBuilder, aarDependencies, logger, it, appInfo.minSdkVersion)
|
||||
mergeResources(project, variant, androidBuilder, aarDependencies, rDirectory, it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAndroidBuilder(project: Project, config: AndroidConfig, logger: ILogger): AndroidBuilder {
|
||||
val processExecutor = DefaultProcessExecutor(logger)
|
||||
val javaProcessExecutor = KobaltJavaProcessExecutor()
|
||||
val androidHome = File(AndroidFiles.androidHome(project, config))
|
||||
val sdkLoader : SdkLoader = DefaultSdkLoader.getLoader(androidHome)
|
||||
val result = AndroidBuilder(project.name, "kobalt-android-plugin",
|
||||
processExecutor,
|
||||
javaProcessExecutor,
|
||||
KobaltErrorReporter(),
|
||||
logger,
|
||||
false /* verbose */)
|
||||
|
||||
val libraryRequests = arrayListOf<LibraryRequest>()
|
||||
val sdk = sdkLoader.getSdkInfo(logger)
|
||||
val sdkManager = SdkManager.createManager(androidHome.absolutePath, logger)
|
||||
val maxPlatformTarget = sdkManager.targets.filter { it.isPlatform }.last()
|
||||
val maxPlatformTargetHash = AndroidTargetHash.getPlatformHashString(maxPlatformTarget.version)
|
||||
|
||||
result.setTargetInfo(sdk,
|
||||
sdkLoader.getTargetInfo(maxPlatformTargetHash, maxPlatformTarget.buildToolInfo.revision, logger),
|
||||
libraryRequests)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun createLibraryDependencies(project: Project, dependencies: List<IClasspathDependency>)
|
||||
: List<ManifestDependency> {
|
||||
val result = arrayListOf<ManifestDependency>()
|
||||
dependencies.filter {
|
||||
it is MavenDependency && it.jarFile.get().path.endsWith(".aar")
|
||||
}.forEach {
|
||||
val dep = it as MavenDependency
|
||||
result.add(object: ManifestDependency {
|
||||
override fun getManifest(): File? {
|
||||
return File(AndroidFiles.explodedManifest(project, dep.mavenId))
|
||||
}
|
||||
|
||||
override fun getName() = it.jarFile.get().path
|
||||
|
||||
override fun getManifestDependencies(): List<ManifestDependency> {
|
||||
return createLibraryDependencies(project, it.directDependencies())
|
||||
}
|
||||
|
||||
})
|
||||
it.directDependencies()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun processAssets(project: Project, variant: Variant, androidBuilder: AndroidBuilder,
|
||||
aarDependencies: List<File>) {
|
||||
logWrap(2, " Processing assets...", "done") {
|
||||
val intermediates = File(
|
||||
KFiles.joinDir(AndroidFiles.intermediates(project), "assets", variant.toIntermediateDir()))
|
||||
aarDependencies.forEach {
|
||||
val assetDir = File(it, "assets")
|
||||
if (assetDir.exists()) {
|
||||
KFiles.copyRecursively(assetDir, intermediates)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processManifests(project: Project, variant: Variant, androidBuilder: AndroidBuilder,
|
||||
config: AndroidConfig): AppInfo {
|
||||
val mainManifest = File("src/main/AndroidManifest.xml")
|
||||
val appInfo = AppInfo(mainManifest, config)
|
||||
logWrap(2, " Processing manifests...", "done") {
|
||||
val manifestOverlays = variant.allDirectories(project).map {
|
||||
File("src/$it/AndroidManifest.xml")
|
||||
}.filter {
|
||||
it.exists()
|
||||
}
|
||||
val libraries = createLibraryDependencies(project, project.compileDependencies)
|
||||
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"))
|
||||
androidBuilder.mergeManifests(mainManifest, manifestOverlays, libraries,
|
||||
null /* package override */,
|
||||
appInfo.versionCode,
|
||||
appInfo.versionName,
|
||||
appInfo.minSdkVersion.toString(),
|
||||
appInfo.targetSdkVersion,
|
||||
appInfo.maxSdkVersion,
|
||||
outManifest,
|
||||
outAaptSafeManifestLocation,
|
||||
// TODO: support aar too
|
||||
ManifestMerger2.MergeType.APPLICATION,
|
||||
emptyMap() /* placeHolders */,
|
||||
reportFile)
|
||||
}
|
||||
return appInfo
|
||||
}
|
||||
|
||||
private fun processResources(project: Project, variant: Variant, androidBuilder: AndroidBuilder,
|
||||
aarDependencies: List<File>, logger: ILogger, processOutputHandler: KobaltProcessOutputHandler,
|
||||
minSdk: Int) {
|
||||
logWrap(2, " Processing resources...", "done") {
|
||||
val layout = ProjectLayout()
|
||||
val preprocessor = NoOpResourcePreprocessor()
|
||||
val outputDir = AndroidFiles.mergedResources(project, variant)
|
||||
val resourceMerger = ResourceMerger(minSdk)
|
||||
val fullVariantDir = File(variant.toCamelcaseDir())
|
||||
val srcList = listOf("main", variant.productFlavor.name, variant.buildType.name, fullVariantDir.path)
|
||||
.map { "src" + File.separator + it }
|
||||
|
||||
// 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 goodAarList = aarDependencies.map { it.path + File.separator }
|
||||
(goodAarList + srcList).map { it + File.separator + "res" }.forEach { path ->
|
||||
with(ResourceSet(path)) {
|
||||
addSource(File(path))
|
||||
loadFromFiles(logger)
|
||||
setGeneratedSet(GeneratedResourceSet(this))
|
||||
resourceMerger.addDataSet(this)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
ExecutorSingleton.getExecutor().shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
private fun mergeResources(project: Project, variant: Variant, androidBuilder: AndroidBuilder,
|
||||
aarDependencies: List<File>, rDirectory: String,
|
||||
processOutputHandler: KobaltProcessOutputHandler) {
|
||||
logWrap(2, " Merging resources...", "done") {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
fun dex(project: Project) {
|
||||
// androidBuilder.createMainDexList()
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package com.beust.kobalt.plugin.android
|
||||
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
|
||||
class Proguard(val androidHome: String) {
|
||||
val proguardHome = KFiles.joinDir(androidHome, "tools", "proguard")
|
||||
val proguardCommand = KFiles.joinDir(proguardHome, "bin", "proguard.sh")
|
||||
|
||||
fun getDefaultProguardFile(name: String) = KFiles.joinDir(proguardHome, name)
|
||||
}
|
|
@ -5,7 +5,6 @@
|
|||
<!-- Classes within this tag are instantiated and the introspected by Kobalt. Whenever they -->
|
||||
<!-- are found to implement one of IPluginActor's interfaces, they are added as such -->
|
||||
<class-name>com.beust.kobalt.plugin.java.JavaPlugin</class-name>
|
||||
<class-name>com.beust.kobalt.plugin.android.AndroidPlugin</class-name>
|
||||
<class-name>com.beust.kobalt.plugin.application.ApplicationPlugin</class-name>
|
||||
<class-name>com.beust.kobalt.plugin.KobaltPlugin</class-name>
|
||||
<class-name>com.beust.kobalt.plugin.kotlin.KotlinPlugin</class-name>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue