diff --git a/src/main/kotlin/com/beust/kobalt/Variant.kt b/src/main/kotlin/com/beust/kobalt/Variant.kt index 33016478..60fe759e 100644 --- a/src/main/kotlin/com/beust/kobalt/Variant.kt +++ b/src/main/kotlin/com/beust/kobalt/Variant.kt @@ -3,6 +3,7 @@ package com.beust.kobalt import com.beust.kobalt.api.* import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.log +import com.beust.kobalt.misc.warn import java.io.File /** @@ -131,7 +132,8 @@ class Variant(val initialProductFlavor: ProductFlavorConfig? = null, fun toIntermediateDir() : String { if (isDefault) { - throw AssertionError("DEFAULT VARIANT NOT IMPLEMENTED") + warn("DEFAULT VARIANT NOT IMPLEMENTED") + return "" } else { return KFiles.joinDir(productFlavor.name, buildType.name) } diff --git a/src/main/kotlin/com/beust/kobalt/api/IBuildDirectoryInterceptor.kt b/src/main/kotlin/com/beust/kobalt/api/IBuildDirectoryInterceptor.kt new file mode 100644 index 00000000..4d722f12 --- /dev/null +++ b/src/main/kotlin/com/beust/kobalt/api/IBuildDirectoryInterceptor.kt @@ -0,0 +1,9 @@ +package com.beust.kobalt.api + +/** + * Plug-ins can alter the build directory by implementing this interface. + */ +interface IBuildDirectoryIncerceptor : IPluginActor { + fun intercept(project: Project, context: KobaltContext, buildDirectory: String) : String +} + diff --git a/src/main/kotlin/com/beust/kobalt/api/ICompilerInterceptor.kt b/src/main/kotlin/com/beust/kobalt/api/ICompilerInterceptor.kt new file mode 100644 index 00000000..f057a3a9 --- /dev/null +++ b/src/main/kotlin/com/beust/kobalt/api/ICompilerInterceptor.kt @@ -0,0 +1,10 @@ +package com.beust.kobalt.api + +import com.beust.kobalt.internal.CompilerActionInfo + +/** + * Plug-ins can alter what is passed to the compiler by implementing this interface. + */ +interface ICompilerInterceptor : IPluginActor { + fun intercept(project: Project, context: KobaltContext, actionInfo: CompilerActionInfo) : CompilerActionInfo +} diff --git a/src/main/kotlin/com/beust/kobalt/api/IContributor.kt b/src/main/kotlin/com/beust/kobalt/api/IContributor.kt index a2f25ef9..d85e51a5 100644 --- a/src/main/kotlin/com/beust/kobalt/api/IContributor.kt +++ b/src/main/kotlin/com/beust/kobalt/api/IContributor.kt @@ -1,4 +1,7 @@ package com.beust.kobalt.api -interface IContributor +interface IPluginActor + +interface IContributor : IPluginActor + diff --git a/src/main/kotlin/com/beust/kobalt/api/ISourceDirectoriesInterceptor.kt b/src/main/kotlin/com/beust/kobalt/api/ISourceDirectoriesInterceptor.kt new file mode 100644 index 00000000..6e8af5eb --- /dev/null +++ b/src/main/kotlin/com/beust/kobalt/api/ISourceDirectoriesInterceptor.kt @@ -0,0 +1,11 @@ +package com.beust.kobalt.api + +import java.io.File + +/** + * Plug-ins can alter the source directories by implementing this interface. + */ +interface ISourceDirectoriesIncerceptor : IPluginActor { + fun intercept(project: Project, context: KobaltContext, sourceDirectories: List) : List +} + diff --git a/src/main/kotlin/com/beust/kobalt/api/Project.kt b/src/main/kotlin/com/beust/kobalt/api/Project.kt index 263ae1fb..7a9b80a3 100644 --- a/src/main/kotlin/com/beust/kobalt/api/Project.kt +++ b/src/main/kotlin/com/beust/kobalt/api/Project.kt @@ -112,6 +112,14 @@ open public class Project( fun addBuildType(name: String, bt: BuildTypeConfig) { buildTypes.put(name, bt) } + + fun classesDir(context: KobaltContext): String { + val initial = KFiles.joinDir(buildDirectory, "classes") + val result = context.pluginInfo.buildDirectoryInterceptors.fold(initial, { dir, intercept -> + intercept.intercept(this, context, dir) + }) + return result + } } public class Sources(val project: Project, val sources: HashSet) { diff --git a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index ee1f96aa..732ad3b7 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -28,9 +28,6 @@ abstract class JvmCompilerPlugin @Inject constructor( open val jvmCompiler: JvmCompiler) : BasePlugin(), IProjectContributor { companion object { - @ExportedProjectProperty(doc = "The location of the build directory", type = "String") - const val BUILD_DIR = "buildDir" - @ExportedProjectProperty(doc = "Projects this project depends on", type = "List") const val DEPENDENT_PROJECTS = "dependentProjects" @@ -54,7 +51,6 @@ abstract class JvmCompilerPlugin @Inject constructor( override fun apply(project: Project, context: KobaltContext) { super.apply(project, context) - project.projectProperties.put(BUILD_DIR, project.buildDirectory + File.separator + "classes") project.projectProperties.put(DEPENDENT_PROJECTS, projects()) addVariantTasks(project, "compile", runTask = { taskCompile(project) }) } @@ -176,17 +172,23 @@ abstract class JvmCompilerPlugin @Inject constructor( project.compileDependencies) val projectDirectory = File(project.directory) - val buildDirectory = File(project.projectProperties.getString(BUILD_DIR)) + val buildDirectory = File(project.classesDir(context)) buildDirectory.mkdirs() - val sourceDirectories = context.variant.sourceDirectories(project) + val initialSourceDirectories = context.variant.sourceDirectories(project) + val sourceDirectories = context.pluginInfo.sourceDirectoriesInterceptors.fold(initialSourceDirectories, + { sd, interceptor -> interceptor.intercept(project, context, sd) }) + val sourceFiles = files.findRecursively(projectDirectory, sourceDirectories, { it .endsWith(project.sourceSuffix) }) - .map { File(projectDirectory, it).absolutePath } + .map { File(projectDirectory, it).path } - val cai = CompilerActionInfo(projectDirectory.path, classpath, sourceFiles, buildDirectory, + val initialActionInfo = CompilerActionInfo(projectDirectory.path, classpath, sourceFiles, buildDirectory, emptyList()) - return cai + val result = context.pluginInfo.compilerInterceptors.fold(initialActionInfo, { ai, interceptor -> + interceptor.intercept(project, context, ai) + }) + return result } abstract fun doCompile(project: Project, cai: CompilerActionInfo) : TaskResult diff --git a/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt b/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt index ebfdc03a..ee38fa46 100644 --- a/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt +++ b/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt @@ -52,6 +52,15 @@ class KobaltPluginXml { @XmlElement(name = "compiler-flag-contributors") @JvmField var compilerFlagContributors: ClassNameXml? = null + + @XmlElement(name = "compiler-interceptors") @JvmField + var compilerInterceptors: ClassNameXml? = null + + @XmlElement(name = "source-directories-interceptors") @JvmField + var sourceDirectoriesInterceptors: ClassNameXml? = null + + @XmlElement(name = "build-directory-interceptors") @JvmField + var buildDirectoryInterceptors: ClassNameXml? = null } class ContributorXml { @@ -76,6 +85,9 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) { val initContributors = arrayListOf() val repoContributors = arrayListOf() val compilerFlagContributors = arrayListOf() + val compilerInterceptors = arrayListOf() + val sourceDirectoriesInterceptors = arrayListOf() + val buildDirectoryInterceptors = arrayListOf() // Future contributors: // source files @@ -140,6 +152,15 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) { xml.compilerFlagContributors?.className?.forEach { compilerFlagContributors.add(factory.instanceOf(forName(it)) as ICompilerFlagContributor) } + xml.compilerInterceptors?.className?.forEach { + compilerInterceptors.add(factory.instanceOf(forName(it)) as ICompilerInterceptor) + } + xml.sourceDirectoriesInterceptors?.className?.forEach { + sourceDirectoriesInterceptors.add(factory.instanceOf(forName(it)) as ISourceDirectoriesIncerceptor) + } + xml.buildDirectoryInterceptors?.className?.forEach { + buildDirectoryInterceptors.add(factory.instanceOf(forName(it)) as IBuildDirectoryIncerceptor) + } } fun addPluginInfo(pluginInfo: PluginInfo) { diff --git a/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt b/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt index 197369e1..c3a9dbac 100644 --- a/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt +++ b/src/main/kotlin/com/beust/kobalt/maven/DependencyManager.kt @@ -4,7 +4,6 @@ import com.beust.kobalt.api.IClasspathContributor import com.beust.kobalt.api.KobaltContext import com.beust.kobalt.api.Project import com.beust.kobalt.api.ProjectDescription -import com.beust.kobalt.internal.JvmCompilerPlugin import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.warn @@ -101,7 +100,7 @@ public class DependencyManager @Inject constructor(val executors: KobaltExecutor it.project.name == project?.name }.forEach { pd -> pd.dependsOn.forEach { p -> - val classesDir = p.projectProperties.getString(JvmCompilerPlugin.BUILD_DIR) + val classesDir = p.classesDir(context) if (classesDir != null) { result.add(FileDependency(KFiles.joinDir(p.directory, classesDir))) } else { 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 abfe235e..014b3c13 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/android/AndroidPlugin.kt @@ -1,12 +1,9 @@ package com.beust.kobalt.plugin.android -import com.beust.kobalt.OperatingSystem -import com.beust.kobalt.TaskResult -import com.beust.kobalt.Variant +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.homeDir import com.beust.kobalt.internal.CompilerActionInfo import com.beust.kobalt.internal.JvmCompilerPlugin import com.beust.kobalt.maven.FileDependency @@ -41,12 +38,13 @@ fun Project.android(init: AndroidConfig.() -> Unit) : AndroidConfig { return pd } -val Project.isAndroid : Boolean - get() = (Kobalt.findPlugin("android") as AndroidPlugin).isAndroid(this) +//val Project.isAndroid : Boolean +// get() = (Kobalt.findPlugin("android") as AndroidPlugin).isAndroid(this) @Singleton public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) - : ConfigPlugin(), IClasspathContributor, IRepoContributor, ICompilerFlagContributor { + : ConfigPlugin(), IClasspathContributor, IRepoContributor, ICompilerFlagContributor, + ICompilerInterceptor, ISourceDirectoriesIncerceptor, IBuildDirectoryIncerceptor { override val name = "android" fun isAndroid(project: Project) = configurationFor(project) != null @@ -305,19 +303,30 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) val buildToolsDir = buildToolsVersion(project) val dx = "${androidHome(project)}/build-tools/$buildToolsDir/dx" + if (OperatingSystem.current().isWindows()) ".bat" else "" - val classesDexDir = KFiles.joinDir(intermediates(project), "dex", context.variant.shortArchiveName) + val classesDexDir = KFiles.joinDir(intermediates(project), "dex", context.variant.toIntermediateDir()) File(classesDexDir).mkdirs() val classesDex = "classes.dex" val outClassesDex = KFiles.joinDir(classesDexDir, classesDex) - val args = listOf("--dex", "--output", outClassesDex) - val otherArgs = - project.dependencies?.let { - it.dependencies.map { - it.jarFile.get().path - }.filter { ! it.endsWith(".aar") && ! it.endsWith("android.jar") } - } ?: emptyList() - RunCommand(dx).run(args + otherArgs) + // 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( + "-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()), + project.classesDir(context) + )) +// val args = listOf("--dex", "--output", outClassesDex) +// val otherArgs = +// project.dependencies?.let { +// it.dependencies.map { +// it.jarFile.get().path +// }.filter { ! it.endsWith(".aar") && ! it.endsWith("android.jar") } +// } ?: emptyList() +// RunCommand(dx).run(args + otherArgs) // // Add classes.dex to existing .ap_ @@ -376,4 +385,25 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler) emptyList() } } + + // IBuildDirectoryInterceptor + override fun intercept(project: Project, context: KobaltContext, buildDirectory: String): String { + val result = KFiles.joinDir(intermediates(project), "classes", context.variant.toIntermediateDir()) + return result + } + + // ISourceDirectoriesInterceptor + override fun intercept(project: Project, context: KobaltContext, sourceDirectories: List): List { + return sourceDirectories.map { File("app", it.path)} + } + + // ICompilerInterceptor + override fun intercept(project: Project, context: KobaltContext, actionInfo: CompilerActionInfo) + : CompilerActionInfo { + val newOutputDir = KFiles.joinDir("kobaltBuild", "intermediates", "classes", + context.variant.toIntermediateDir()) + return actionInfo.copy(outputDir = File(newOutputDir)) + } + + } diff --git a/src/main/resources/META-INF/kobalt-plugin.xml b/src/main/resources/META-INF/kobalt-plugin.xml index 17a241ff..5e873e56 100644 --- a/src/main/resources/META-INF/kobalt-plugin.xml +++ b/src/main/resources/META-INF/kobalt-plugin.xml @@ -31,4 +31,13 @@ com.beust.kobalt.plugin.android.AndroidPlugin com.beust.kobalt.plugin.apt.AptPlugin + + com.beust.kobalt.plugin.android.AndroidPlugin + + + com.beust.kobalt.plugin.android.AndroidPlugin + + + com.beust.kobalt.plugin.android.AndroidPlugin + \ No newline at end of file