How to skip compilation for some KMM targets?

Hello! I’m trying to speed up CI compiling for my KMM library project and noticed that I compile targets that won’t be published. I tried skipping it with this code that was provided by Kotlin docs

fun PublicationContainer.onlyHostCanPublishTheseTargets(
    machine: Machine,
    targets: List<String>,
    tasks: TaskContainer
) {
    matching { it.name in targets }.all {
        val targetPublication = this@all

        tasks.withType<AbstractPublishToMaven>()
            .matching { (it.publication == targetPublication) }
            .configureEach {
                onlyIf {
                    val canPublish = currentMachine == machine
                    when(canPublish) {
                        true ->
                            println("Current host ($machine) can publish ${targetPublication.name} target")
                        false ->
                            println("Only $machine can publish ${targetPublication.name} target")
                    }
                    canPublish
                }
            }
    }
}

But it just skips publishing, unnecessary targets will still keep compiling

Sure, you just disabled that specific task.
Using onlyIf { ... } is like enabled = false, just dynamically calculated right before the task is executed.
Alone that would be reason enough that dependency tasks are not “skipped along”.
If you want to skip a task and also its dependencies (unless needed by some other task) you need to use the -x <taskName> commandline argument. Afair for this it would also work if you do it on gradle.startParameters during configuration time, but that is a bit unclean if you can give it from outside.

1 Like

Afair for this it would also work if you do it on gradle.startParameters during configuration time, but that is a bit unclean if you can give it from outside.

I decided to try with gradle.startParamets.excludedTaskNames and it works! I managed to provide info from outside by using system properties of running machine (alternatively I could use env variables)

I created function in buildSrc

fun Project.onlyHostCanPublishTheseTargets(
    publishingMachine: Machine,
    target: List<String>
) {
    val excludedTasks = target.map(::getPublishTaskName)

    // Machine is just data class with two system properties (OS and Architecture)
    if (publishingMachine != currentMachine) {
        val excludedTaskStringList = "- ${excludedTasks.joinToString("\n- ")}"

        println("[Publishing] These tasks are excluded because $currentMachine can't publish these targets:")
        println(excludedTaskStringList)
        gradle.startParameter.excludedTaskNames.addAll(excludedTasks)
    }
}

private fun getPublishTaskName(target: String): String
    = "publish${target.uppercaseFirstChar()}ToMavenLocal"

Called it in build.gradle.kts

}

onlyHostCanPublishTheseTargets(
    publishingMachine = Machine(OS.Linux, Arch.X86),
    target = listOf("androidDebug", "androidRelease", "kotlinMultiplatform", "jvm", "js")
)

singing { ...

It works! It skips task with its dependencies

> Configure project :
[Publishing] These tasks are excluded because Machine(system=Windows, arch=X86) can't publish these targets:
- publishAndroidDebugToMavenLocal
- publishAndroidReleaseToMavenLocal
- publishKotlinMultiplatformToMavenLocal
- publishJvmToMavenLocal
- publishJsToMavenLocal

> Task :compileKotlinMingwX64

> Task :mingwX64SourcesJar UP-TO-DATE
> Task :generateMetadataFileForMingwX64Publication
> Task :generatePomFileForMingwX64Publication
> Task :signMingwX64Publication UP-TO-DATE
> Task :publishMingwX64PublicationToMavenLocal
> Task :publishToMavenLocal

BUILD SUCCESSFUL in 23s

Thanks for help! Now it builds 2-2.5 times faster!:blush:

1 Like