Serve kotlin multiplatform javascript from ktor - gradle

I have set up a multi-module gradle project with a common module and a ktor module.
The common module is a kotlin multiplatform library.
I would like to be able to serve the javascript files generated from the common library from the ktor server, when I run it from Intellij.
Currently ktor is set up to serve resources as static content:
static("/static") {
resources()
}
The ktor module has a dependency on the common module:
dependencies {
compile project(':common')
...
}
I would assume when running in Intellij to be able to browse to http://localhost:8080/static/common.js to retrieve the outputs of the common module JS build (written to common\build\classes\kotlin\js\main) but this does not work.

Fixed this by including a copy task. Note that the kotlin full stack mpp here (https://github.com/ktorio/ktor-samples/tree/master/mpp/fullstack-mpp) has an example that uses webpack outputs.
kotlin {
jvm() {
task copyJsToJvm(type: Copy) {
from("$buildDir/classes/kotlin/js/main")
include '*.*'
into "$buildDir/classes/kotlin/jvm/main"
}
compilations.main {
tasks.getByName(processResourcesTaskName) {
dependsOn(copyJsToJvm)
}
}
}
...
}

Related

Publishing test fixtures with submodules, gradle

I have been looking around for a way to include test fixtures in my gradle publications.
https://developer.android.com/studio/publish-library/configure-test-fixtures#kts suggests that it should work automatically so long as the project name is set correctly, which I have done in the settings.gradle file. This seems to solve the issue in the case of https://github.com/slackhq/EitherNet/issues/44.
For context, my project is built with several sub modules and I have defined a custom publication for each (I suspect this is the clue to the issue) as shown here:
subprojects {
// ... some repos and unimportant plugin applications
tasks {
register("prepareKotlinBuildScriptModel") {}
withType<BootJar> {
enabled = false // this is enabled in the jar I wish to be bootable
}
withType<Test> {
useJUnitPlatform()
}
getByName<Jar>("jar") {
enabled = true
archiveClassifier.set("")
}
}
publishing {
publications {
create<MavenPublication>(project.name) {
version = projectVersion
artifactId = tasks.jar.get().archiveBaseName.get()
groupId = "${projectGroup}.${rootProject.name}"
from(components["kotlin"])
}
}
}
For ref, this is currently what my module structure and build.gradle looks like for the module in question:
module structure
plugins {
id("java-test-fixtures")
id("java-library")
}
dependencies {
testFixturesApi(project(":model"))
... unrelated stuff
The test fixtures work fine as internal dependencies in the project itself, but they do not get published so that they can be used in external projects.
So my question is if there is a way to bake the test fixtures into my submodule jars so they can be used in external projects?
Any input would be highly appreciated.
Tried, expected, result:
Publishing to local repo, expected the test fixtures to be bundled, they were not.

Multi module gradle: how to run module A before compiling modules B in a multi module project

We have a multi-module project in gradle. We have a "data" module that needs to be compiled (simple java 11 app) then run.
When we run java -jar data.jar after compiling the data module source is generated into the "webapp" module. With this generated source code we are now able to build the webapp module.
I am new to Gradle and struggling to figure out how do achieve this properly. I am especially concerned if I do it wrong I will make build caching fail.
Note: I am using Kotlin with Gradle 7.5.
The answer appears to be to create a custom configuration which produces a different artifact than the default.
task(taskJarGenerated, Jar::class) {
group = groupJooq
dependsOn(taskCompileGeneratedSource)
inputs.dir("$projectDir/build/classes/java/main")
outputs.file("${projectDir}/build/libs/data-1.0.jar")
from("$projectDir/build/classes/java/main")
}
artifacts {
add("generatedDbDataJar", tasks[taskJarGenerated])
}
Then you can reference this custom configuration "generatedDbDataJar" in other projects like this:
dependencies {
implementation(project(":data","generatedDbDataJar"))
}

how to regenerate missing source paths in in a Gradle project?

how to regenerate missing source paths in in a Gradle project? I need to generate all those missing folders like src/java, src/clojure and so on. depends on project plugins. So if I add say Java plugin then src/java/ will be generated.
I just saw that some IDE has an option to create al source paths of the plugins when it imports the project - so I assume it is possible to do from the command line.
You can do that in build.gradle by changing the sourceSets.
sourceSets {
main {
java { srcDirs 'src/java' }
clojure { srcDirs 'src/clojure' }
}
}
If you also need to do the same for the test folders, this should work too:
sourceSets {
test {
java { srcDirs 'test/java' }
clojure { srcDirs 'test/clojure' }
}
}
Java plugin will not create folders for you, it instead assumes a project layout, and you are free to change this structure by doing something similar to what I have above. I have not used the clojure plugin, but I assume it behaves in a similar way.
If you want to list all the folders that the java plugin is making use of, you can do this:
println sourceSets.main.allJava.asPath
Displays all the files being watched by the java plugin.

Depend on Kotlin Multiplatfrom JS Module from JVM

I have a Kotlin Multiplatform project with a common, a JS and a JVM module. The JVM module uses a JavaFX WebView to display a GUI. This GUI however shall be implemented as the JS module. How do I add the JS module as a dependency correctly? I tried
dependencies {
compile project(":myproject-js")
}
however, this does not include the resulting JS files anywhere in the classpath. The JS module does indeed create a JAR file with the required dependencies, but I could not find a way to access them.
I also tried simply copying the JS files into my build output, but they are still ignored:
configurations {
js
}
dependencies {
js project(":myproject-js")
}
project.afterEvaluate {
build.dependsOn copyResources
}
task copyResources(type: Copy) {
dependsOn configurations.js
into file("${project.buildDir}/resources")
from {
configurations.js.asFileTree.each {
from (zipTree(it))
}
null
}
}
Is there a way to achieve this?
Here's what should work:
Create a configuration for the myproject-js dependency:
configurations {
js
}
Add the project dependency to that configuration:
dependencies {
js project(":myproject-js")
}
Add the configuration files to the processResources task with .from(...), and the corresponding build dependency:
processResources {
dependsOn configurations.js
from(configurations.js.collect { zipTree(it) })
}
Then, whenever you build the JVM project, the JS module's files get unpacked into the resources output directory and then packed into the JAR.

Building a project with Groovy extension methods in it

I'm trying to build a simple Groovy project which contains a package with a Groovy extension method.
When I try to compile the project the classes using the extension method can't find it. The descriptor and the class are picked up correctly by the IDE.
I guess the problem is that the extension method is needed at compile time by which it probably hasn't been compiled yet.
I've tried creating different sourceSets but with no success.
dependencies {
compile 'org.codehaus.groovy:groovy:2.4.7'
compile 'org.membrane-soa:service-proxy-core:4.2.2'
testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
extensionCompile 'org.codehaus.groovy:groovy:2.4.7'
}
sourceSets {
extension {
groovy {
include '**/ClosureExtension.groovy'
}
}
main {
groovy {
compileClasspath += extension.output
}
}
}
The extension method lives in src/main/groovy/com/predic8/membrane/dsl/extension and the rest of the project in src/main/groovy/com/predic8/membrane/dsl/.
P.S.: The project classes are all annotated with #CompileStatic.
One approach: separate the extension code into its own project, and produce a jar from that project. Then, in another project, the DSL code can use that jar and specify the extension jar as a dependency.
This would make a huge answer, so I mocked it up and placed it on GitHub here (with all due credit to mrhaki's post). There are two projects: extension and dsl. Assuming you understand multi-project builds in Gradle, the essence is this line from dsl/build.gradle:
compileGroovy.dependsOn tasks.getByPath(':extension:jar')

Resources