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

CLOVIS

10/01/2023, 2:12 PM
I'm trying to create a Gradle task that creates a configuration file for Kotlin/JS. That file should be created in NPM package, so I wrote a task that creates the file in
build/js/packages/<module-name>/
. However, Gradle refuses to execute it, because:
Copy code
- Gradle detected a problem with the following location: '[…]/build/js/packages/example-simple'.
    
    Reason: Task ':[…]' uses this output of task ':jsBrowserProductionWebpack' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
The task I'm creating does not do anything other than create a configuration file in that directory. In fact, it could just create the directory itself even if it didn't exist. There's no reason for that task to depend on
:jsBrowserProductionWebpack
. I guess if the Kotlin plugin exposed a task that creates the directory without doing anything else, I should depend on that one, but it doesn't seem so. How can I tell Gradle that these are truly unrelated?
a

Alexander.Likhachev

10/01/2023, 10:55 PM
In general, there should be no other tasks writing to the same directory marked as
OutputDirectory
as of a given task. That may break caching, up-to-date checks and the result depends on the execution order. That’s why you’re getting that message. Please describe your use case. Perhaps you could use some built-in ways to customise the result either you should consume the result of other tasks as input and create a modified copy that you will then use in your pipeline
c

CLOVIS

10/02/2023, 7:53 AM
I'm creating JS configuration files (e.g.
vite.config.js
,
tailwindcss.config.js
…). They need to be in the JS project's directory to be found by the build, which would be
/build/js/packages/<project>
if I'm not mistaken.
Honestly, I'm starting to think it's a bug in the Kotlin plugin. The Gradle error messages make no sense. Following your advice, I attempted to copy the contents of the build directory after the compilation tasks end to another directory that I control. So I have a task
:copyCompiledFiles
that depends on
:jsProductionExecutableCompileSync
. So far, so good, these are in fact the files I want to get. Except, Gradle considers that directory as belonging to
:jsBrowserProductionWebpack
:
Copy code
A problem was found with the configuration of task ':[…]' (type 'Copy').
  - Gradle detected a problem with the following location: '[…]/build/js/packages/example-simple'.
    
    Reason: Task ':[…]' uses this output of task ':jsBrowserProductionWebpack' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':jsBrowserProductionWebpack' as an input of ':[…]'.
      2. Declare an explicit dependency on ':jsBrowserProductionWebpack' from ':[…]' using Task#dependsOn.
      3. Declare an explicit dependency on ':jsBrowserProductionWebpack' from ':[…]' using Task#mustRunAfter.
But none of these are what I want. My tasks do work on the output of the Kotlin compiler, without any Webpack involvement. I do not want to involve Webpack in this, as it will massively slow down what I'm doing, especially for the production build.
i

Ilya Goncharov [JB]

10/03/2023, 2:57 PM
Hm, it is interesting,
KotlinWebpack
has only one
@OutputDirectory
, which targeting not into this directory
c

CLOVIS

10/03/2023, 3:04 PM
If you need to reproduce this, the repository is public: • clone https://gitlab.com/opensavvy/kotlin-vite.git • branch:
2-vite-build
(if it is deleted, see commit
ace9d7785a99dd0404e036929680aa3abcce3936
) • in
examples/simple/build.gradle.kts
, remove the
onlyIf { false }
for
:jsBrowserProductionWebpack
• run
./gradlew -p examples/simple --include-build ../.. build
Keep in mind I'm a Gradle newbie, so maybe I'm doing something dumb… I don't see what it could be, though
i

Ilya Goncharov [JB]

10/03/2023, 5:58 PM
I have taken a look. You have copy task which has input
build/js/packages/<package>
Usually it is okay, but webpack task has output file
webpack.config.js
. That’s why Gradle detect that copy task wants to use webpack output (because webpack output is inside input folder) What I recommend - to use in your Copy task,
sourceTask
as input, not specific folder Something like this
Copy code
from(project.tasks.named(sourceTask))
		into(destination)
		exclude("node_modules")
But I can propose more. In fact you can reuse
build/js/packages/<package>
, with just producing
vite.config.js
inside it (like KotlinWebpack does) It helps to reuse
node_modules
(without symlinks) and reuse content of
kotlin
folder I understand that you likely want to distinguish outputs of dev and prod task, but you can distinguish not directories (because you don’t have
@OutputDirectory
) but just
configs
Something like
vite.prod.config.js
and
<http://vite.dev|vite.dev>.config.js
, and run them via
--config
- https://vitejs.dev/config/ BTW, good work with adopting vite, I think that it is good way of integrating, and thinking about separating webpack tool integration into separate plugin.
c

CLOVIS

10/03/2023, 6:04 PM
Now, I'm really confused… what you're describing is what I was originally trying to do, but I hit the same output conflict. Someone (not sure if it was here or in the Gradle slack) told me it would be safer to have everything happen in another folder to avoid the conflict, but the result seems to be the same. Indeed, having two configuration files in the same directory sounds more efficient than copying to two different directories. It will probably help with compatibility with other plugins that generate configuration files (e.g. the Tailwind plugin). I'll try your suggestion with depending on the task directly, but I'm not really expecting much from it since this is more or less my starting point. With regards to Vite, I've had it configured in my projects for years now by manually copying tasks, so I thought I'd finally learn how to make a Gradle plugin so other people can use it 🙂
i

Ilya Goncharov [JB]

10/03/2023, 6:07 PM
Thank you for your effort! So in fact I may miss something with overlapping outputs (in fact we have problem here because we just reuse directory
kotlin
and one file
webpack.config.js
among prod and dev variants, but I hope I’ll fix it) So if there will be problem, please ping me, I’ll try to help
c

CLOVIS

10/03/2023, 6:32 PM
Thanks a lot, I will 🙂
Now, this is not the result I expected at all 🤔 • I open the project (same version as mentioned earlier) • I edit the copy task as shown in the screenshot below • If I run the Vite build now, it works • If I comment out the
onlyIf { false }
for the Webpack task, then the build starts to fail:
Copy code
Could not resolve entry module "kotlin/index.html".
error during build:
RollupError: Could not resolve entry module "kotlin/index.html".
    at error (file:///home/ivan/Projects/opensavvy/kotlin-vite/examples/simple/build/js/node_modules/rollup/dist/es/shared/node-entry.js:2287:30)
    at ModuleLoader.loadEntryModule (file:///home/ivan/Projects/opensavvy/kotlin-vite/examples/simple/build/js/node_modules/rollup/dist/es/shared/node-entry.js:24881:20)
    at async Promise.all (index 0)
And, most surprising: the build continues to fail, even if I re-comment the Webpack task, even if I clean the project, disable the build cache and the configuration cache. To get it back to working, I have to revert the changes, re-comment the Webpack task, clean everything, then rebuild once without the build cache. My only guess is that Webpack somehow modifies the Kotlin files in that directory, and somehow that gets remembered by the Gradle daemon in a way that survives cleaning and the build cache? It's strange
i

Ilya Goncharov [JB]

10/05/2023, 9:35 AM
Copy code
RollupError: Could not resolve entry module "kotlin/index.html".
Yes, now we are copying compileSync output, and it is collection of files. So you can either change
vite.config.js
onto just entering
index.html
or change destination of copying
compileSync
onto
destination/kotlin
c

CLOVIS

10/05/2023, 8:12 PM
Indeed, it now works pretty well 🙂 I'll probably continue cleaning up a few things before making an announcement
4 Views