Slackbot
07/05/2022, 7:05 PMSatyarth Sampath
07/06/2022, 11:02 AMadd("fooImplementation",project(":login",configuration="release"))
work.Satyarth Sampath
07/06/2022, 11:04 AMSatyarth Sampath
07/06/2022, 11:05 AM<https://developer.android.com/studio/build/build-variants#variant_aware>
That's the one...providing fallbacks could be another approach for this?Alexander Gherschon
07/06/2022, 11:06 AMadd("fooImplementation",project(":login",configuration="release"))
works that's much better!
Testing right nowAlexander Gherschon
07/06/2022, 11:08 AMThe Hilt Android Gradle plugin is applied but no com.google.dagger:hilt-android dependency was found.
So weird, I don't understand how that plugin being applied is an issue when using add()
or the other way of writing itSatyarth Sampath
07/06/2022, 11:10 AM--stacktrace
. You could probably be hitting an issue with configuration in the other project.Satyarth Sampath
07/06/2022, 11:12 AMAlexander Gherschon
07/06/2022, 11:13 AMbuildVariantImplementation
doesn't existAlexander Gherschon
07/06/2022, 11:13 AMproductFlavorImplementation
exists I guessAlexander Gherschon
07/06/2022, 11:14 AMSatyarth Sampath
07/06/2022, 11:18 AMSatyarth Sampath
07/06/2022, 11:20 AMAlexander Gherschon
07/06/2022, 11:20 AMAlexander Gherschon
07/06/2022, 11:21 AMAlexander Gherschon
07/06/2022, 11:21 AMsitDebug
I get the following error:
org.gradle.api.artifacts.UnknownConfigurationException: Configuration with name 'sitDebugImplementation' not found.
Satyarth Sampath
07/06/2022, 11:25 AMsitDebug
build variant would lead to the following configurations being created.
You can also print configurations as a part of running any gradle task.Alexander Gherschon
07/06/2022, 11:26 AMSatyarth Sampath
07/06/2022, 11:27 AMAlexander Gherschon
07/06/2022, 11:28 AMAlexander Gherschon
07/06/2022, 11:28 AMconfigurations.forEach {
println(it.name)
}
Satyarth Sampath
07/06/2022, 11:30 AMAlexander Gherschon
07/06/2022, 11:31 AMAlexander Gherschon
07/06/2022, 12:21 PMXavier Ducrohet
07/06/2022, 5:11 PM<buildVariant>Implementation
exist but only in afterEvaluate
because that's where the variants are computed by AGP. So if you want to use this you need to wrap your dependencies {}
section in afterEvaluate {}
Xavier Ducrohet
07/06/2022, 5:13 PMimplementation(project("...", configuration = "...")
This is Gradle's old way of targeting a specific configuration in a producer module that predates the whole variant-aware publication introduced several years ago.Xavier Ducrohet
07/06/2022, 5:14 PMAlexander Gherschon
07/08/2022, 12:45 PMlogin
module, we created a special AutoLogin
class (to help us when we develop) but we want to have it on the classpath and run that special code only in sitDebug
and uatDebug
build variants (for security reasons)
The solution:
⢠In that login
module, I've created a dev
and prod
variants
⢠The autoLogin
class is placed into the devDebug
productFlavor/source folder
⢠In prodDebug
and release
productFlavor/source folders, there's a no-op empty AutoLogin
class (copied twice for now*)
⢠matchingFallbacks += listOf(<http://Flavor.DEV|Flavor.DEV>)
set in the app
module, on product flavors sit
and uat
does the magic!
Overall I like this solution a lot, as a good infra for automating things while developping, besides having to copy twice the no-op version of the class.
* I hope to be able to use sourceSets {}
to avoid the no-op class duplication but I'm not sure yet how to do that, because I need it in 3 specific build variants our of the 4. I'll look into afterEvaluate
for that šAlexander Gherschon
07/08/2022, 2:18 PMafterEvaluate
, I got this:
afterEvaluate {
val extra = "extra"
val extraNoop = "extra-noop"
fun newSrcDirs(sourceSetName: String, op: Boolean) = setOf(
File("./src/${sourceSetName}/java"),
File("./src/${sourceSetName}/kotlin"),
File("./src/${if (op) extra else extraNoop}/java"),
File("./src/${if (op) extra else extraNoop}/kotlin")
)
android.sourceSets.forEach { sourceSet ->
if (sourceSet.name == "devDebug") {
sourceSet.kotlin.srcDirs(newSrcDirs(sourceSet.name, true))
} else if (sourceSet.name in listOf("devRelease", "prodDebug", "prodRelease")) {
sourceSet.kotlin.srcDirs(newSrcDirs(sourceSet.name, false))
}
}
}
The IDE picks the right sourceSet correctly, but I get the following errors while building:
> Task login:compileDevReleaseKotlin FAILED
e: LoginMainFragment.kt: (12, 37): Unresolved reference: AutoLogin
e: LoginMainFragment.kt: (27, 29): Unresolved reference: AutoLogin
What am I missing?
Probably something related to the configurations... š¤Alexander Gherschon
07/08/2022, 3:37 PMsourceSets
at https://developer.android.com/studio/build/extend-agp šXavier Ducrohet
07/08/2022, 3:43 PMXavier Ducrohet
07/08/2022, 3:44 PMXavier Ducrohet
07/08/2022, 3:45 PMXavier Ducrohet
07/08/2022, 3:46 PMapp-type
) would consume the prod flavor in the dimension login-type
, while sit/uat would consume dev
in that same login-type dimension (replace with your own dimension names š )Xavier Ducrohet
07/08/2022, 3:47 PMmissingDimensionStrategy
. see https://developer.android.com/studio/build/build-variantsAlexander Gherschon
07/08/2022, 6:19 PMapp
module has a version
dimension with 3 values (aka product flavors): sit
/ uat
/ prod
⢠The login
module
⦠has a login-type
dimension 2 values: automatic
, manual
⦠The special code doing the automatic login sits at /login/src/automatic/java/<package>/AutoLogin.kt
⦠The no-op version, that doesn't login automatically sits at /login/src/manual/java/<package>/AutoLogin.kt
What I would need to make happen then would be the following:
⢠:app:sitDebug
consumes :login:automaticDebug
<- automatic login here
⢠:app:sitRelease
consumes :login:manualRelease
⢠:app:uatDebug
consumes :login:automaticDebug
<- automatic login here
⢠:app:uatRelease
consumes :login:manualRelease
⢠:app:prodDebug
consumes :login:manualDebug
⢠:app:prodRelease
consumes :login:manualRelease
Can I really just do that with missingDimensionStrategy
?
I feel like I miss the point of how to differentiate between debug
/ release
š¤Alexander Gherschon
07/08/2022, 6:25 PMmissingDimensionStrategy
and matchingFallbacks
?Xavier Ducrohet
07/08/2022, 6:26 PMXavier Ducrohet
07/08/2022, 6:27 PMAlexander Gherschon
07/08/2022, 6:28 PMXavier Ducrohet
07/08/2022, 6:28 PMmissingDimensionStrategy
ultimately just sets up attributes on Configuration
objects.Xavier Ducrohet
07/08/2022, 6:28 PMXavier Ducrohet
07/08/2022, 6:30 PMandroid {
productFlavors {
sit {
missingDimensionStrategy 'login-type', 'automatic'
}
uat {
missingDimensionStrategy 'login-type', 'automatic'
}
prod {
missingDimensionStrategy 'login-type', 'manual'
}
}
}
Xavier Ducrohet
07/08/2022, 6:30 PMXavier Ducrohet
07/08/2022, 6:30 PMuatRelease
and change things.Alexander Gherschon
07/08/2022, 6:31 PMXavier Ducrohet
07/08/2022, 6:32 PMConfiguration
object in the variant API: https://developer.android.com/reference/tools/gradle-api/7.3/com/android/build/api/variant/ComponentXavier Ducrohet
07/08/2022, 6:33 PMuatReleaseCompileClasspath
and uatReleaseRuntimeClasspath
Xavier Ducrohet
07/08/2022, 6:35 PMandroidComponents {
onVariant(selector().withName('uatRelease')) { v ->
v.compileConfiguration...
v.runtimeConfiguration...
}
}
Xavier Ducrohet
07/08/2022, 6:36 PMselector().withName('uatRelease')
is a shortcut and less future proof than something like selector().withBuildType('release').withFlavor('login-type' to 'uat')
Alexander Gherschon
07/08/2022, 6:36 PMXavier Ducrohet
07/08/2022, 6:37 PMlogin-type
and this is where you need low level APIs in Gradle, and some knowledge of AGP internalsXavier Ducrohet
07/08/2022, 6:37 PMmissingDimensionStrategy
on variant so that you don't have to deal with thisAlexander Gherschon
07/08/2022, 6:38 PMXavier Ducrohet
07/08/2022, 6:40 PMXavier Ducrohet
07/08/2022, 6:42 PMConfiguration.getAttributes().attributes(Attribute<T>, T)
is the API you want to use to set an attributesXavier Ducrohet
07/08/2022, 6:42 PMXavier Ducrohet
07/08/2022, 6:42 PMXavier Ducrohet
07/08/2022, 6:44 PMAttribute<ProductFlavorAttr>
and you can get this with ProductFlavorAttr.Companion.of("name of dimension")
Xavier Ducrohet
07/08/2022, 6:44 PMXavier Ducrohet
07/08/2022, 6:44 PMAlexander Gherschon
07/08/2022, 6:45 PM7.3.0-beta05
and will try those APIs right awayXavier Ducrohet
07/08/2022, 6:46 PMandroidComponents {
onVariant(selector().withName('uatRelease')) { v ->
v.compileConfiguration.getAttributes().attribute(
ProductFlavorAttr.Companion.of("login-type"),
"manual"
)
v.runtimeConfiguration.getAttributes().attribute(
ProductFlavorAttr.Companion.of("login-type"),
"manual"
)
}
}
Xavier Ducrohet
07/08/2022, 6:54 PMmissingDimensionStrategy
on a per-variant basis. š¤¦Xavier Ducrohet
07/08/2022, 6:54 PMAlexander Gherschon
07/08/2022, 6:55 PMXavier Ducrohet
07/08/2022, 6:55 PMandroid {
applicationVariants.all {
if (name == "uatRelease") {
missingDimensionStrategy("login-type", "manual")
}
}
}
Xavier Ducrohet
07/08/2022, 6:56 PMmissingDimensionStrategy
to it (filing the bug now)Xavier Ducrohet
07/08/2022, 7:00 PMAlexander Gherschon
07/08/2022, 7:06 PMAlexander Gherschon
07/08/2022, 7:07 PMXavier Ducrohet
07/08/2022, 7:08 PMXavier Ducrohet
07/08/2022, 7:08 PMXavier Ducrohet
07/08/2022, 7:09 PMXavier Ducrohet
07/08/2022, 7:09 PMAlexander Gherschon
07/08/2022, 7:10 PMAlexander Gherschon
07/08/2022, 7:32 PMXavier Ducrohet
07/08/2022, 7:32 PMAlexander Gherschon
07/14/2022, 7:18 AM2022-07-14 10:00:36.993 9097-9097/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: il.co.firstdigitalbank.uat, PID: 9097
java.lang.NoClassDefFoundError: Failed resolution of: Lil/co/firstdigitalbank/login/ui/add_email/AddEmailViewModel_HiltModules_KeyModule_ProvideFactory;
at aj.c.h(DaggerDigitalBankApp_HiltComponents_SingletonC.java:2)
at aj.c.a(DaggerDigitalBankApp_HiltComponents_SingletonC.java:4)
at wi.a.a(DefaultViewModelFactories.java:2)
at gy.b.getDefaultViewModelProviderFactory(Unknown Source:4)
at il.co.firstdigitalbank.ui.launcher.LauncherActivity$c.m(Unknown Source:2)
at androidx.lifecycle.s0.getValue(ViewModelProvider.kt:2)
at il.co.firstdigitalbank.ui.launcher.LauncherActivity.onCreate(LauncherActivity.kt:3)
Only when isMinifyEnabled = true
(which was our default in release obviously), because when isMinifyEnabled = false
the app runs, no issues.
Any idea why R8 is having an issue with using missingDimensionStrategy
?Alexander Gherschon
07/14/2022, 7:45 AMgoogle()
aka com.android.tools:r8:3.3.28
doesn't helpXavier Ducrohet
07/14/2022, 5:30 PMAlexander Gherschon
07/15/2022, 3:47 AM