Skip to content
This repository was archived by the owner on Jan 2, 2022. It is now read-only.

Commit f5304dc

Browse files
Added some documentation
1 parent 3bba363 commit f5304dc

File tree

2 files changed

+202
-1
lines changed

2 files changed

+202
-1
lines changed

.github/assets/magicmodules-demo.gif

5.78 MB
Loading

README.md

Lines changed: 202 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,209 @@
11
# Magic Modules
2+
![Main workflow](https://github.com/dotanuki-labs/magic-modules/workflows/Main%20workflow/badge.svg)
3+
4+
![](.github/assets/magicmodules-demo.gif)
25

36
## What is this?
47

5-
WIP
8+
> // Blog post with the full motivation to come! Stay tunned
9+
10+
For large Android projects hosted in mono repos, management for module names might be a real pain, specially when we have lots of moving parts under a structure driven by nested Gradle subprojects.
11+
12+
This experimental plugin attemps to solve that. It parses a project tree like this
13+
14+
```
15+
.
16+
├── app
17+
│   └── src
18+
│   └── main
19+
│   ├── AndroidManifest.xml
20+
│   ├── java
21+
│   └── res
22+
├── build.gradle
23+
├── buildSrc
24+
│   ├── build.gradle.kts
25+
│   └── src
26+
│   └── main
27+
│   └── kotlin
28+
├── common
29+
│   ├── core
30+
│   │   ├── build.gradle
31+
│   │   └── src
32+
│   │   └── main
33+
│   └── utils
34+
│   ├── build.gradle.kts
35+
│   └── src
36+
│   └── main
37+
├── features
38+
│   ├── home
39+
│   │   ├── build.gradle
40+
│   │   └── src
41+
│   │   └── main
42+
│   └── login
43+
│   ├── build.gradle
44+
│   └── src
45+
│   └── main
46+
|
47+
|
48+
└── settings.gradle
49+
50+
```
51+
52+
and
53+
54+
- it automatically includes all founded modules in `settings.gradle`
55+
- it writes 2 Kotlin files under your `buildSrc/src/main/kotlin` :
56+
57+
```kotlin
58+
// Generated by MagicModules plugin. Mind your Linters!
59+
import kotlin.String
60+
import kotlin.collections.List
61+
62+
object Libraries {
63+
const val FEATURES_HOME: String = ":features:home"
64+
65+
const val FEATURES_LOGIN: String = ":features:login"
66+
67+
const val COMMON_CORE: String = ":common:core"
68+
69+
const val COMMON_UTILS: String = ":common:utils"
70+
71+
val allAvailable: List<String> =
72+
listOf(
73+
FEATURES_HOME,
74+
FEATURES_LOGIN,
75+
COMMON_CORE,
76+
COMMON_UTILS
77+
)
78+
}
79+
```
80+
81+
and
82+
83+
```kotlin
84+
// Generated by MagicModules plugin. Mind your Linters!
85+
import kotlin.String
86+
import kotlin.collections.List
87+
88+
object Applications {
89+
const val APP: String = ":app"
90+
91+
val allAvailable: List<String> =
92+
listOf(
93+
APP
94+
)
95+
}
96+
```
97+
In this way, refactors around the project structure will become a bit easier, since `build.gradle` configuration
98+
99+
```groovy
100+
dependencies {
101+
implementation project(Libraries.COMMON_UTILS)
102+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
103+
implementation ...
104+
}
105+
```
106+
107+
will break if `common/utils` moves around. The new constant under `buildSrc` will be mapped and will be ready to use.
108+
109+
We can also add all the libraries to one monotlithic app easily
110+
111+
```groovy
112+
dependencies {
113+
Libraries.allAvailable.each { implementation project(it) }
114+
}
115+
```
116+
117+
## Setup
118+
119+
Add this snippet in your `settings.gradle` file
120+
121+
```groovy
122+
buildscript {
123+
repositories {
124+
maven { url 'https://jitpack.io' }
125+
}
126+
127+
dependencies {
128+
classpath 'io.labs.dotanuki:magic-modules-plugin:<plugin_version>'
129+
}
130+
}
131+
132+
apply plugin: "io.labs.dotanuki.magicmodules"
133+
134+
```
135+
136+
and remove all `include` statements
137+
138+
```groovy
139+
include 'app'
140+
include 'featureA'
141+
include 'featureB'
142+
include 'featureC'
143+
include ...
144+
145+
```
146+
They are not needed anymore.
147+
148+
If your project uses a multi-application layout, with standalone apps for your features/screens, you can opt-in to not include all `com.android.application` modules in order to reduce configuration times locally and eventually build times on CI.
149+
150+
```groovy
151+
rootProject.name='awesome-project'
152+
153+
apply plugin: "io.labs.dotanuki.magicmodules"
154+
155+
magicModules {
156+
includeApps = false
157+
}
158+
159+
include ':app'
160+
161+
```
162+
163+
## Matching Gradle build files
164+
165+
This plugin walks your project tree and inspect all the `build.gradle` and `build.gradle.kts` files in order to learn if the related module matches an Android/JVM library or an Android application. This means that this plugin is sensitive on how you apply plugins in your `build.gradle` files
166+
167+
```groovy
168+
apply plugin: 'com.android.library'
169+
```
170+
171+
or
172+
173+
```kotlin
174+
plugins {
175+
kotlin("jvm")
176+
}
177+
```
178+
179+
This plugin does a best-effort attempt in order to catch all the common cases, but it might not work at all if you (1) have some strategy to share build logic accross Gradle modules and (2) define the applied plugin using such shared build logic
180+
181+
## Building and testing
182+
183+
To build this plugin and publish it locally for testing
184+
185+
```shell
186+
./gradlew publishToMavenLocal
187+
```
188+
189+
To run all the checks, including integration tests
190+
191+
```shell
192+
./gradlew ktlintCheck test
193+
```
194+
195+
## Limitations
196+
197+
The main limitation I've found with this approach is that - right now - the plugin generates the `Libraries.kt` and `Applications.kt` under the main source set of `buildSrc`, which means that eventually issues with Git and/or linters that run for `buildSrc` files.
198+
199+
I needed more work in order to figure out if we can have such generated files under `buildSrc/build` somehow.
200+
201+
## Further work
202+
203+
I realised that
204+
205+
- It might be useful to configure the output folder/package for `Libraries.kt` and `Applications.kt`
206+
- It might be useful to grab more Gradle build script matchers using the plugin configuration
6207

7208
## Author
8209

0 commit comments

Comments
 (0)