This message was deleted.
# community-support
s
This message was deleted.
e
there isn't a public way to react to registration without also realizing the object
v
The only way currently is to react to the same source that registers those tasks instead of reacting to the actual tasks.
Btw. if that tasks copies into the output directory of another task, it is a bad idea to do so anyway.
☝️ 1
j
The task is to copy test resources to the runtime path of the test binary, so it can read the resources during tests. It is the output path of the task that produces the binary, but also needs to be the location of the resources for common API consistency. Other examples of similar need would be copying the resources to a framework directory that is also the output path for the compilation's binary.
The task that produces the binary and the task that copies the resources to the same directory would always be run together, as the one depends on the other.
e
that's not true: on re-run, depending on inputs, one or both or neither may be run. Gradle isn't able to track where files are going when you do this.
v
Don't do that. It disturbs up to date checks, it disturbs cache entries of cacheable tasks, Gradle will detect it if you use the task output of one of these tasks and use it in another task and then complain that you miss a task dependency on the other task, when using the output of the one task, your will eventually get the output of both tasks or not depending on situation, ... Just don't do it, but find a better way during your use-case. Well, if it works for you, fine. But don't wonder if anything starts to behave strange. :-)
e
if you really had to,
Copy code
abstract class CopyToTestWorkingDir @Inject constructor(private val files: Any) : Action<Task> {
    @get:Inject
    abstract val fileSystemOperations: FileSystemOperations

    override fun execute(task: Task) {
        fileSystemOperations.copy {
            from(files)
            into((task as KotlinNativeTest).workingDir)
        }
    }
}

kotlin.targets.withType<KotlinNativeTargetWithTests<*>> {
    testRuns.all {
        tasks.named("${target.name}${name.capitalized()}") {
            val files = files("src/commonTest/resources")
            inputs.files(files.asFileTree)
            doFirst(objects.newInstance(CopyToTestWorkingDir::class, files))
        }
    }
}
would avoid the issues mentioned above, but you'd still have no way to get rid of stale resources in the destination
basically if you want to have resources in that directory properly, it needs support upstream
for my K/N binaries and tests, I use an environment variable for to pass along the data directory. easy and no interference with any other infrastructure
j
I've definitely run across where this can be an issue. I had to hack together this workaround to get Dokka working with Gradle 8. What would you suggest as an alternative for these cases? There seems to be a gap between ideal Gradle methodology and some real world requirements. For the framework use case, I could see creating a downstream task
assembleFrameworkWithResources
that depends on the framework build task, but then copies both the binary compilation and the resources to yet another path. But then that could easily be confused and another user expect the framework build task to have created a complete useable framework. For the test task, the task dependency has to be upstream from the task that eventually runs the tests from the location the binary was built in and those tests expect the resources to be present there at runtime.
Also, creating these new tasks, whether upstream or downstream that depend on existing tasks of the same type always end up with the initial problem of not being able to be configured lazily. There are several framework build tasks for example for different architecture combinations. Whether the copy resources task is a dependency or depends on these existing tasks, they all need to be named uniquely and associated with the existing tasks.
e
for the Java ecosystem, you simply add to the test sourceset's resources and you don't need to care about anything else. no clobbering since there's multiple directories, all consumers use the same sources, etc.
Kotlin/Native needs to grow support and then none of this hackery is needed
j
Yes, JVM resources work great. Android mostly works, at least outside of KMP common resources. But all other Kotlin multiplatform targets don't have good support for resources currently. So it seems like solutions just aren't ideal, in one way or another, when you need to add features to an existing plugin's tasks.
v
when you need to add features to an existing plugin's tasks
For that you just add
doFirst
or
doLast
actions to those tasks
j
That's a good point. I could use those APIs instead of creating new task dependencies. Thanks for the ideas and feedback.