https://kotlinlang.org logo
#gradle
Title
# gradle
j

Jeff Lockhart

07/20/2022, 12:23 AM
I'm looking for a way to modify a build task, but only when running tests. Specifically, I need to add some additional header definitions in a Kotlin/Native .def file. I have this working, but I only want those definitions to be added when running tests, as they're not needed in production code and I don't want them to leak into the public API. Is there a good way to accomplish this with gradle? Given my gradle task dependency trees, I want to modify (or insert a task after)
generateDefCocoaPodsLib
when it's executed from the
iosX64Test
task:
Copy code
iosX64Test
+--- ...
     +--- generateDefCocoaPodsLib
     |    +--- ...
     +--- ...
But I don't want to modify this task, or append the additional definitions when it's executed from any other task tree:
Copy code
assemble
+--- ...
|    +--- generateDefCocoaPodsLib
|    |    +--- ...
|    +--- ...
+--- ...
v

Vampire

07/20/2022, 8:42 AM
The problem is you don't "execute from" a task. Tasks depend on other tasks.
iosX64Test
depends on
generateDefCocoaPodsLib
and
assemble
depends on
generateDefCocoaPodsLib
. If you do
./gradlew iosX64Test assemble
, the
generateDefCocoaPodsLib
is executed just once. If you need it with different results, you should probably create a second task with a different configuration, so that test and production use different tasks, but the question is, whether the right thing is tested then. But I'm not familiar with native development, so I might not get something right.
j

Jeff Lockhart

07/20/2022, 1:11 PM
I see that dilemma. So there's no way for a task to see any sort of state as to why it was run, like the depends-on tree that triggered it? The other direction I'm considering would be to rebuild the dependency tree from
iosX64Test
..
generateDefCocoaPodsLib
as
iosX64Test
..
generateDefCocoaPodsLibTest
. There are two tasks between these two, which would also need to be copied as
*Test
to create a separate dependency tree. They also have other dependencies as well that they'd need to maintain. Is there a way to duplicate an existing task with a new name and then remove/add dependencies to other tasks?
v

Vampire

07/20/2022, 1:12 PM
No
😞 1
What you could of course also consider is to enforce that test and prod runs cannot happen in the same build. You could for example define a Gradle property "runTestsThisTime". If it is set, you add the headers, if it is not set, you don't. And then you add
doFirst
actions to the right tasks that need those where it makes a difference that throws an error if the property is set to the other value. Something like that.
But maybe you should just refactor your code to be testable without polluting the public API. 🙂
j

Jeff Lockhart

07/20/2022, 1:25 PM
Unfortunately the CocoaPods library API isn't my own. I'm building KMM bindings into the existing Android and ObjC SDKs of the library. Some of the tests rely on internal classes and methods, which are not part of the public API and I don't want to introduce them as such in my KMM library. Unfortunately Kotlin/Native C interop doesn't provide a way to import certain headers as internal and not part of the public API. This would be the ideal solution. The native ObjC tests import the internal headers this way, without publishing them as part of the framework. The underlying Java SDK does this with package private methods and classes.
I suppose I can live with how it is, since the API is obfuscated enough. It's only really accessible in iOS platform-specific Kotlin code, using the native library classes, rather than the KMM API, which isn't the intended use.