Hi. Is there any workaround how to use flavors in kotlin multiplatform modules? I know about <BuildK...
m
Hi. Is there any workaround how to use flavors in kotlin multiplatform modules? I know about BuildKonfig library but it seems usefull only for different primitive types (String, boolean etc.) for different flavors but I have module separated to flavors with its own classes and dependencies. Thanks.
đź‘€ 1
k
Use gradle modules for that
v
Could you please elaborate?
k
If you want a different logic for different applications in single monoproject then divide logic by gradle modules.
and depending on some build property select required module to include
v
So if we change (commonly) app icon, name, maybe some base API URLs, few images, we should pack all that "depend on different app" stuff into different modules
Interesting
k
yes.
v
And we can tell gradle which module to actually use via SYS env variable, so we can control that from CI/CD
Oh, I never thought about that, although I am not experienced with module development. But that doesn't sound complicated hm
k
it is much easier than android flavours and more predictable
v
It actually sounds so. But I never had this idea. I mean I am on a project when flavouring is very common (B2B app) and we have an app flavor per client if they want it. But for KMP because no 3rd party resolutions for now, we just did it as 2 native implementations and fetching in runtime some build config variables via expect/actual
Does anyone have any simple but ready example project for this?:)
m
@Konstantin Tskhovrebov I have one project for several apps. These apps have some modules only for them, some modules shared among them and some modules shared too, but "divided" by flavors (one flavor for one app). These modules I would like to convert to multiplatform. If I separate each of these modules to several (for each flavor), it would lead to a lot of new modules and that is the situation I would like to avoid.
k
I'd recommend you to avoid flavours) It depends on a scenario of using the flavours in your app. Resources? You can manage resource directories by build type. Implementations? Setup a DI. For other cases - gradle modules. A lot of modules for a complicated build is OK. Flavours are kinda a hard switch for registered source and resource directories. No one ide supports it
đź’Ż 2
p
Does anyone have any simple but ready example project for this
I have done this in Android java before. I could give you a link but the code is kind of old and the Readme is empty. But essentially you set your dependencies based on Environment variables or config files. sort of:
Copy code
sourceSets {
val commonMain by getting {
    dependencies {
        implementation(project("common-customer-api")) // Only interfaces / abstract classes here
        // or implementation("com.mycompany:common-customer-api:1.0.0")
    }
}

// Android
val androidMain by getting {
    dependencies {
        val customer = System.property[customer]
        when (customer) {
            "A" -> {
             implementation(project(":A")) // Implementations for customer A
             // or implementation("com.mycompany:customerA:1.0.0")
             }
            "B" -> {
             implementation(project(":B")) // Implementations for customer B
             // or implementation("com.mycompany:customerB:1.0.0")
             }
        }
    }
}

// Repeat the Same for iOS, JVM, JS
}
You can make it much better not repeating it for each target , perhaps creating a function to set each target
Copy code
val customerLib = when (customer) {
            "A" -> {
             "com.mycompany:customerA:1.0.0"
            "B" -> {
             "com.mycompany:customerB:1.0.0"
             }
        }

setAndroid(customerLib)
setIos(customerLib)
The problem with variant/flavor, when the number grows, you sourcesets grow in the same project, making hard to navigate. Also your build.gradle script starts growing exponentially. Perhaps you haven’t hit this problem because you just use flavors to provide icons and strings. But if you need to have code that depend on specific libraries, each different per customer. You will have to add each flavor dependency in build.gradle + build configurations per flavor. Putting the stuff in modules not only allows cleaner sourcesets + cleaner gradle script but you can have them precompiled already and maintain each flavor code in a separate project.
🙌 1
m
OK thanks. So I assume flavors support or something like that is not planned in the future?
v
@Pablichjenkov thank you. Seem easy. Seems easy and neat tho. The only theory question which is open for me is how do you tell your Android studio the value of the
customer
easily. I mean, we know system envs in settings for the projects, so if you want to build different app, you just go into those settings and change the customer from A to B manually?
p
I see, well, using a solution like this unfortunately loses the IDE integration. If you want to switch modules/customers, you would have to go to your config file, change the values, then re-run gradle. Things like that. You can have a local
appconfig.json
file in root of your project. In that json you specify the current customer/flavor. Read the json from your Gradle scripts. That is more convenient than using environment variables or gradle properties
🙌 1
k
there is
gradle.properties
v
As a person who never worked with gradle multi-module development I am getting complications with even the basics. How to create even an empty module (not android) for, for example, images/files and how to include that empty module into the common. And I can't find basic documentations/guides for KMP in particular. Any hints please where do I start?
I learned multi-module development. • Created a KMP module for a "flavor". That is not android flavor anymore. • Moved into it into src/main/res android app icon and name (resources). • added the module into shared gradle commonMain dependencies via
implementation(project(":$flavorName}"))
And that is working and seems to be easy, true, but only for android. Now I am completely stuck with - how would I connect iOS app icon/name with this module. Firstly we need to make sure that iOS app icon, which is iOS asset is in KMP and compiled by KMP. And then we get it from the complied KMP (I am not sure that already is possible). But how? There are not much info in google or github for the very topic and google search already indexed and shows this thread as first result.
@Konstantin Tskhovrebov Very sorry for pinging you. Could you elaborate just a little bit more for iOS part? 🙂
đź‘€ 1
p
I am also very interested in the iOS part, android seem to be very straight forward.
v
Well in the moko-resources page they do some interesting stuff with a cocoapods script which you can put into iOS build phase. Basically if you can access the "flavor name" gradle property in such script for xcode-copy build phase it probably will be very easy to instruct it how to copy the stuff from a "Flavored module". But I haven't finished that yet. For android I did my own KMP flavors logic, but native iOS targets still there for now
p
I started working on this, this is what I have so far, any suggestions or ideas are welcome. https://github.com/pererikbergman/multiplatform-flavors
v
@pererikbergman You can also add string resources (and other resources) in the config modules, to avoid having to add new switches in multiple places in Gradle every time you add a new config (nice for when every config is a separate app). Added a PR to your repo. =)
p
@Viktor Nyblom Nice, let me check it out, thanks.
2856 Views