```kotlin { js { compilerOptions { ...
# gradle
c
Copy code
kotlin {
    js {
        compilerOptions {
            target.set("es2015")
        }
    }
}
How can I get which target is set from within a Gradle plugin? The only thing I see is
project.kotlinExtension.sourceSets
but that doesn't seem to have that option.
m
If you cast your
kotlinExtension
to a
KotlinMultiplatformExtension
or something similar, you should get the targets
c
I see, thanks
m
Copy code
extensions.getByType(KotlinMultiplatformExtension::class.java).targets
Use together with
.configureEach {}
to “react” to targets being added
c
Got it;
Copy code
val targets = project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets

	targets.named { it == "js" }.configureEach {
		this as KotlinJsIrTarget
		val target = this.compilerOptions.target
		println("Target ${target.get()}")
	}
👍 1
m
named
may fail depending the order of when your plugin gets called (
.gradle.kts
is imperative)
I would do this instead:
Copy code
targets.configureEach {
        if (name != "js") return@configureEach
		this as KotlinJsIrTarget
		val target = this.compilerOptions.target
		println("Target ${target.get()}")
	}
c
The lambda-version of
.named
should be lazy, no? 🤔 It returns a
NamedDomainObjectCollection
👍🏾 1
m
If it’s like for tasks, it’s not
🎉 2
🤦‍♂️ 1
🤦🏾‍♂️ 1
Looks like it’s not like for tasks though
tasks.named("foo")
returns a
TaskProvider
So feel free to ignore me and try it out
I have just built brain muscle to avoid “named” because of that tasks thing 🤷
👎🏾 1
h
BTW you can rename a Kotlin target, what about using
targets.withType<KotlinJsIrTarget>().configureEach {
?
c
Yeah, that's a thing… What about when a user creates multiple?
h
In this case
configureEach
should be called twice, it is lazy
c
…Gradle lazy configuration is such a mess. So: • If the user is using
target.set("es2015")
, I need to add an additional dependency • but by the time the Kotlin plugin has initialized itself, it's forbidden to touch dependencies
I love the configuration cache
Copy code
Exception in thread "DefaultSharedObjectDecoder reader thread" org.gradle.api.GradleException: Could not load the value of field `collection` of `kotlin.collections.builders.SerializedCollection` bean found in field `_byTask` of `org.jetbrains.kotlin.gradle.targets.js.nodejs.TasksRequirements` bean found in field `tasksRequirements` of `org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolution` bean found in field `byCompilation` of `org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution` bean found in field `v` of `java.util.Collections$SingletonMap` bean found in field `projects` of `org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution` bean found in field `__resolution__` of `org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager$Parameters_Decorated` bean found in Gradle runtime.
🫘 1
e
untested but
Copy code
kotlin.targets.withType<KotlinJsIrTarget>().configureEach {
    configurations.getByName("${name}Implementation").withDependencies {
        if (compilerOptions.target.get() == "es2015") {
            add(dependencies.create("group:module:version"))
        }
    }
}
does that work?
👀 2
c
@ephemient there is no
KotlinJsIrTarget.configurations
Anyway this is moot, that property isn't set at the time tasks are configured. This one is, however:
Copy code
project.tasks.withType<org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink> {
	println(compilerOptions.moduleKind.get())
}
h
Yeah, KGP has different phases so it might set the values later. It is really annoying because it does not work well with Gradle lazy approach and causes bugs like these https://github.com/google/ksp/pull/2562
e
I meant
project.configurations
, etc.
and
withDependencies
is the last opportunity to add dependencies so if it isn't ready by then, it's hopeless
v
> I have just built brain muscle to avoid “named” because of that tasks thing 🤷 > @mbonnin you are talking about orthogonal things.
tasks
and all others have
named("...")
, tasks and all others have
named { ... }
, and it is the same whether it is about
tasks
or not.
named("...")
requires the thing to be registered already and failed if it is not there.
named { ... }
is reactive and will not fail if it is never added.
m
@Vampire I realized that and find this very confusing.
v
I agree, I also find it quite confusing that both have the same name but do significantly behave different. Actually
named { ... }
should even behave more different. It effectively is currently just a shorthand for
matching { it.name... }
, but was intended to be even more configuration avoiding, only realizing the name-matching elements, that just was not implemented correctly.
1
c
Personally I find much worse that NamedDomainObjectCollection is a non-lazy Iterable. So many useful functions in the auto-complete and they're virtually all forbidden to use, very frustrating
💯 2
v
They are not forbidden, it depends on the context. At execution time for example the non-lazy stuff should be fine, just not at configuration time. Those types are simply older than the lazy API, so the eager methods were already there. 🤷‍♂️
h
Yeah that’s true, it is historical but it is still very easy to make mistakes like using map/flatMap on a filecollection during configuration time because you already use map correctly for a property one line above.
☝️ 1
v
Yes, undoubtly 😞