Skip to content
This repository has been archived by the owner on Dec 18, 2023. It is now read-only.

Provide a way to attach a mount of library as module deps #160

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Create a real life complexity Android project that mimics your own and observe t
* Configurable version of Gradle, Kotlin, the Android Gradle Plugin
* Experimental Bazel support
* [Compose](https://developer.android.com/jetpack/compose) and [DataBinding](https://developer.android.com/topic/libraries/data-binding) support
* Configurable number of local jar library dependencies

## Download & Run
### IntelliJ IDEA/Android Studio
Expand Down Expand Up @@ -56,6 +57,10 @@ will crawl the folder recursively and execute each config in turn.
* Specify `viewBinding` for View Binding.
* Specify `composeConfig` for Compose.
* It has a property `actionCount` to indicate the number of clickable actions.
* Sepcify `localJarLibsDependency` for local jar depencencies.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specify

* It's a list of items that indicate creating local jar depencencies for specific module. For each item,
* It has a property `moduleName` to indicate the module name that depencies are attached to.
* It has a properoty `count` to indicate the number of depencies are attached.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a link to a sample config with Jars

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dependencies

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A typo "property" instead of "properoty"

* If nothing above is specified, the UI layer code will be traditional XML-based layout.
* Errors will be thrown when two of the above config is specified.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ package com.google.androidstudiopoet.input
sealed class DependencyConfig {
data class ModuleDependencyConfig(val moduleName: String, val method: String? = null) : DependencyConfig()
data class LibraryDependencyConfig(val library: String, val method: String? = null) : DependencyConfig()
}
data class LocalJarLibsDependencyConfig(val moduleName: String, val count: Int, val method: String? = null) : DependencyConfig()
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ object ModuleBlueprintFactory {
}
}
is DependencyConfig.LibraryDependencyConfig -> LibraryDependency(dependencyConfig.method.toDependencyMethod(), dependencyConfig.library)
is DependencyConfig.LocalJarLibsDependencyConfig -> FileTreeDependency(dependencyConfig.method.toDependencyMethod(), "libs", "*.jar", dependencyConfig.count)
}
} ?: listOf()
return moduleDependencies.toHashSet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class ConfigPojoToAndroidModuleConfigConverter {

val resolvedDependencies = config.resolvedDependencies[moduleName]?.sortedBy { it.to }
?.map { dependency -> DependencyConfig.ModuleDependencyConfig(dependency.to, dependency.method) } ?: emptyList()
dependencies = config.libraries?.let { resolvedDependencies + it } ?: resolvedDependencies
val resolvedLocalJarLibsDependency = config.resolvedLocalJarLibsDependencies[moduleName]?.let { listOf(it) } ?: emptyList()
dependencies = (config.libraries?: emptyList()) + resolvedDependencies + resolvedLocalJarLibsDependency

this.buildTypes = buildTypes
this.productFlavorConfigs = productFlavorConfigs
Expand All @@ -57,4 +58,4 @@ class ConfigPojoToAndroidModuleConfigConverter {
viewBinding = config.viewBinding
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class ConfigPojoToModuleConfigConverter {
generateTests = config.generateTests

moduleName = config.getModuleName(index)
dependencies = config.resolvedDependencies[moduleName]?.map { DependencyConfig.ModuleDependencyConfig(it.to, it.method) } ?: listOf()

val resolvedFileTreeDependency = config.resolvedLocalJarLibsDependencies[moduleName]?.let { listOf(it) } ?: emptyList()
dependencies = (config.resolvedDependencies[moduleName]?.map { DependencyConfig.ModuleDependencyConfig(it.to, it.method) } ?: listOf()) + resolvedFileTreeDependency
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ import com.google.androidstudiopoet.gradle.Expression
import com.google.androidstudiopoet.gradle.StringStatement
import com.google.androidstudiopoet.models.Dependency
import com.google.androidstudiopoet.models.LibraryDependency
import com.google.androidstudiopoet.models.FileTreeDependency
import com.google.androidstudiopoet.models.ModuleDependency
import com.google.androidstudiopoet.models.Repository

fun ModuleDependency.toExpression() = Expression(this.method, "project(':${this.name}')")

fun LibraryDependency.toExpression() = Expression(this.method, "\"${this.name}\"")

fun FileTreeDependency.toExpression() = Expression(this.method, "fileTree(dir: '${this.dir}', include: ['${this.include}'])")

fun String.toApplyPluginExpression() = Expression("apply plugin:", "'$this'")

fun String.toClasspathExpression() = Expression("classpath", "\"$this\"")
Expand All @@ -44,5 +47,6 @@ fun Repository.Remote.toExpression() = Closure("maven", listOf(Expression("url",
fun Dependency.toExpression() = when (this) {
is ModuleDependency -> this.toExpression()
is LibraryDependency -> this.toExpression()
is FileTreeDependency -> this.toExpression()
else -> null
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ limitations under the License.

package com.google.androidstudiopoet.generators

import com.google.androidstudiopoet.models.FileTreeDependency
import com.google.androidstudiopoet.models.ModuleBuildBazelBlueprint
import com.google.androidstudiopoet.models.ModuleDependency
import com.google.androidstudiopoet.writers.FileWriter
Expand All @@ -25,9 +26,20 @@ class ModuleBuildBazelGenerator(private val fileWriter: FileWriter) {
val deps: Set<String> = blueprint.dependencies.map {
when (it) {
is ModuleDependency -> "\"//${it.name}\""
is FileTreeDependency -> "\":imported\""
else -> ""
}
}.toSet()
var imported = blueprint.dependencies.firstOrNull() {
it is FileTreeDependency
}?.let { it ->
val dep = it as FileTreeDependency
"""java_import(
name = "imported",
constraints = ["android"],
jars = glob(["${dep.dir}/${dep.include}}"]),
)"""
} ?: ""
val depsString = """
deps = [
${deps.joinToString(separator = ",\n ") { it }}
Expand All @@ -38,7 +50,8 @@ class ModuleBuildBazelGenerator(private val fileWriter: FileWriter) {
name = "$targetName",
srcs = glob(["src/main/java/**/*.java"]),
visibility = ["//visibility:public"],${if (deps.isNotEmpty()) depsString else ""}
)"""
)
$imported"""

fileWriter.writeToFile(ruleDefinition, blueprint.path)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ import com.google.androidstudiopoet.generators.project.GradlePropertiesGenerator
import com.google.androidstudiopoet.generators.project.GradleSettingsGenerator
import com.google.androidstudiopoet.generators.project.GradlewGenerator
import com.google.androidstudiopoet.generators.project.ProjectBuildGradleGenerator
import com.google.androidstudiopoet.models.FileTreeDependency
import com.google.androidstudiopoet.models.ModuleBlueprint
import com.google.androidstudiopoet.models.ProjectBlueprint
import com.google.androidstudiopoet.utils.joinPath
import com.google.androidstudiopoet.writers.FileWriter
import java.io.BufferedOutputStream
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File
import java.io.FileOutputStream
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.system.measureTimeMillis

class SourceModuleGenerator(private val moduleBuildGradleGenerator: ModuleBuildGradleGenerator,
Expand Down Expand Up @@ -105,11 +111,38 @@ class SourceModuleGenerator(private val moduleBuildGradleGenerator: ModuleBuildG
}

packagesGenerator.writePackages(moduleBlueprint.packagesBlueprint)
}
moduleBlueprint.dependencies?.mapNotNull { denpendency ->
when (denpendency) {
is FileTreeDependency -> {
// generate the local jar file that can be accessed
for (count in 0 until denpendency.count) {
val index = denpendency.include.lastIndexOf(".")
val suffix = if (index == -1) "" else denpendency.include.substring(index)
val uuid = UUID.randomUUID()
val jarFileName = "$uuid$suffix"
writeLibFile("${
moduleBlueprint.moduleRoot.joinPath(denpendency.dir).joinPath(jarFileName)
}")
}
}
}
}
}

private fun writeLibsFolder(moduleRootFile: File) {
// write libs
val libRoot = moduleRootFile.toString() + "/libs/"
File(libRoot).mkdir()
}

private fun writeLibFile(path: String, entryName: String="foo.java") {
val file = File(path)
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
}
ZipOutputStream(BufferedOutputStream(FileOutputStream(file))).use { out ->
val entry = ZipEntry(entryName)
out.putNextEntry(entry)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class AndroidModuleBuildBazelGenerator(val fileWriter: FileWriter) {
val deps: Set<String> = bazelBlueprint.dependencies.map {
when (it) {
is ModuleDependency -> "\"//${it.name}\""
is FileTreeDependency -> "\":imported\""
is GmavenBazelDependency -> "gmaven_artifact(\"${it.name}\")"
else -> ""
}
Expand All @@ -33,6 +34,16 @@ class AndroidModuleBuildBazelGenerator(val fileWriter: FileWriter) {
deps = [
${deps.joinToString(separator = ",\n ") { it }}
],"""
var imported = bazelBlueprint.dependencies.firstOrNull() {
it is FileTreeDependency
}?.let { it ->
val dep = it as FileTreeDependency
"""java_import(
name = "imported",
constraints = ["android"],
jars = glob(["${dep.dir}/${dep.include}}"]),
)"""
} ?: ""
val multidexString = """
multidex = "native","""

Expand All @@ -47,7 +58,8 @@ $ruleClass(
manifest = "src/main/AndroidManifest.xml",
custom_package = "${bazelBlueprint.packageName}",
visibility = ["//visibility:public"],${if (deps.isNotEmpty()) depsString else ""}
)"""
)
$imported"""

fileWriter.writeToFile(ruleDefinition, bazelBlueprint.path)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class ConfigPOJO {

var libraries: List<DependencyConfig.LibraryDependencyConfig>? = null

var localJarLibsDependency: List<DependencyConfig.LocalJarLibsDependencyConfig>? = null

var extraBuildFileLines: List<String>? = null

var extraAndroidBuildFileLines: List<String>? = null
Expand Down Expand Up @@ -135,6 +137,10 @@ class ConfigPOJO {
allDependencies
}

val resolvedLocalJarLibsDependencies: Map<String, DependencyConfig.LocalJarLibsDependencyConfig> by lazy {
val givenDependency = localJarLibsDependency
givenDependency?.associateBy({it.moduleName}, {it}) ?: emptyMap()
}
private val allModuleNames: List<String> by lazy {
val moduleNames = mutableListOf<String>()
(0 until androidModules).mapTo(moduleNames) {getAndroidModuleName(it)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class AndroidModuleDependency(name: String, methodToCall: MethodToCall, method:

data class LibraryDependency(val method: String, val name: String) : Dependency

data class FileTreeDependency(val method: String, val dir: String, val include: String, val count: Int) : Dependency

data class GmavenBazelDependency(val name: String) : Dependency

interface Dependency
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class ConfigPojoToAndroidModuleConfigConverterTest {

generateTests.assertEquals(GENERATE_TESTS)
hasLaunchActivity.assertFalse()
dependencies!!.assertEquals(PURE_MODULE_DEPENDENCY_LIST + LIBRARY_LIST)
dependencies!!.sortedBy { it.toString() }.assertEquals((PURE_MODULE_DEPENDENCY_LIST + LIBRARY_LIST).sortedBy { it.toString() })
}
}

Expand All @@ -115,7 +115,7 @@ class ConfigPojoToAndroidModuleConfigConverterTest {
val androidModuleConfig = converter.convert(configPOJO, 0, productFlavorConfigs, buildTypes)
assertOn(androidModuleConfig) {
hasLaunchActivity.assertTrue()
dependencies!!.assertEquals(listOf(DependencyConfig.ModuleDependencyConfig(ANDROID_MODULE_NAME_1, DEPENDENCY_METHOD)) + PURE_MODULE_DEPENDENCY_LIST + LIBRARY_LIST)
dependencies!!.sortedBy { it.toString() }.assertEquals((listOf(DependencyConfig.ModuleDependencyConfig(ANDROID_MODULE_NAME_1, DEPENDENCY_METHOD)) + PURE_MODULE_DEPENDENCY_LIST + LIBRARY_LIST).sortedBy { it.toString() })
resourcesConfig!!.assertEquals(ResourcesConfig(ACTIVITY_COUNT + 2, ACTIVITY_COUNT + 5, ACTIVITY_COUNT))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,29 @@ class ModuleBuildBazelGeneratorTest {
"//library1",
"//library2"
],
)
"""
verify(fileWriter).writeToFile(expected, "BUILD.bazel")
}

@Test
fun `generator applies local dependencies from the blueprint`() {
val blueprint = getModuleBuildBazelBlueprint(dependencies = setOf(
FileTreeDependency("implementation", "libs", "*.jar", 1)
))
buildBazelGenerator.generate(blueprint)
val expected = """java_library(
name = "target_name",
srcs = glob(["src/main/java/**/*.java"]),
visibility = ["//visibility:public"],
deps = [
":imported"
],
)
java_import(
name = "imported",
constraints = ["android"],
jars = glob(["libs/*.jar}"]),
)"""
verify(fileWriter).writeToFile(expected, "BUILD.bazel")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package com.google.androidstudiopoet.generators

import com.google.androidstudiopoet.models.Dependency
import com.google.androidstudiopoet.models.FileTreeDependency
import com.google.androidstudiopoet.models.ModuleBuildGradleBlueprint
import com.google.androidstudiopoet.models.LibraryDependency
import com.google.androidstudiopoet.models.ModuleDependency
Expand Down Expand Up @@ -60,6 +61,20 @@ targetCompatibility = "1.8""""
verify(fileWriter).writeToFile(expected, "path")
}

@Test
fun `generator applies local libraries from the blueprint`() {
val blueprint = getModuleBuildGradleBlueprint(dependencies = setOf(
FileTreeDependency("implementation", "libs", "*.jar", 1)
))
buildGradleGenerator.generate(blueprint)
val expected = """dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8""""
verify(fileWriter).writeToFile(expected, "path")
}

@Test
fun `generator applies dependencies from the blueprint`() {
val blueprint = getModuleBuildGradleBlueprint(dependencies = setOf(
Expand Down Expand Up @@ -105,4 +120,4 @@ line2"""
whenever(this.path).thenReturn("path")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ android_binary(
"//library1",
gmaven_artifact("external:aar:1")
],
)"""
)
"""
verify(fileWriter).writeToFile(expected, "BUILD.bazel")
}

Expand Down Expand Up @@ -61,6 +62,34 @@ android_library(
gmaven_artifact("external:aar:1"),
gmaven_artifact("external:aar:2")
],
)
"""
verify(fileWriter).writeToFile(expected, "BUILD.bazel")
}

@Test
fun `generator applies local libraries from the blueprint`() {
val blueprint = getAndroidBuildBazelBlueprint(dependencies = setOf(
FileTreeDependency("implementation","libs", "*.jar", 1),
))
androidModuleBuildBazelGenerator.generate(blueprint)
val expected = """load("@gmaven_rules//:defs.bzl", "gmaven_artifact")

android_library(
name = "example",
srcs = glob(["src/main/java/**/*.java"]),
resource_files = glob(["src/main/res/**/*"]),
manifest = "src/main/AndroidManifest.xml",
custom_package = "com.example",
visibility = ["//visibility:public"],
deps = [
":imported"
],
)
java_import(
name = "imported",
constraints = ["android"],
jars = glob(["libs/*.jar}"]),
)"""
verify(fileWriter).writeToFile(expected, "BUILD.bazel")
}
Expand All @@ -78,7 +107,8 @@ android_library(
manifest = "src/main/AndroidManifest.xml",
custom_package = "com.foo",
visibility = ["//visibility:public"],
)"""
)
"""
verify(fileWriter).writeToFile(expected, "BUILD.bazel")
}

Expand Down
Loading