I have a multiplatform kotlin library project that publishes to maven and have been updating to the kotlin 1.3 multiplatform model and kotlin-dsl
The previous groovy gradle script has a modifyPom block, and i found an example here. However as soon as I add
val modifyPom : Closure<*> by ext
modifyPom(closureOf<MavenPom> {
// pom code in here
})
I get the same result no matter what is in the pom data, which is that the call of the modifyPom groovy closure breaks the build with a very vague error:
Build file '<path>\build.gradle.kts' line: 47
Open File
In other words the line number of the call of modifyPom groovy Closure, but nothing about the actual error.
I am using Gradle 5.0. Any help appreciated.
So - in Groovy I had this block for configuring POMs, and it worked just fine:
project.publishing.publications.forEach { publication ->
publication.pom.withXml {
def root = asNode()
root.appendNode("name", "libui")
root.appendNode("description", "Kotlin/Native interop to libui: a portable GUI library")
root.appendNode("url", POM_SCM_URL)
root.children().last() + {
licenses {
license {
name "MIT License"
url POM_SCM_URL
distribution "repo"
}
}
developers {
developer {
id "msink"
name "Mike Sinkovsky"
email "msink#permonline.ru"
}
}
scm {
url POM_SCM_URL
connection POM_SCM_CONNECTION
developerConnection POM_SCM_DEV_CONNECTION
}
}
}
}
And how to convert it to Kotlin DSL?
Edit:
Well, was answered in https://github.com/JetBrains/kotlin-native/issues/2372
In Gradle Kotlin DSL it becomes:
project.publishing.publications.withType<MavenPublication>().forEach { publication ->
with(publication.pom) {
withXml {
val root = asNode()
root.appendNode("name", "libui")
root.appendNode("description", "Kotlin/Native interop to libui: a portable GUI library")
root.appendNode("url", POM_SCM_URL)
}
licenses {
license {
name.set("MIT License")
url.set(POM_SCM_URL)
distribution.set("repo")
}
}
developers {
developer {
id.set("msink")
name.set("Mike Sinkovsky")
email.set("msink#permonline.ru")
}
}
scm {
url.set(POM_SCM_URL)
connection.set(POM_SCM_CONNECTION)
developerConnection.set(POM_SCM_DEV_CONNECTION)
}
}
}
This problem was fixed by changing the definition of modifyPom to
val modifyPom : Closure<MavenPom> by ext
That fixed the original problem as posted, and the pom is now being modified. If anyone needs help, add a comment and hopefully I will notice
Related
I'm trying to figure out why dependent projects for my Kotlin MPP library don't see any provided modules in their common modules even though the targets (jvm, android) can see them.
Published via maven-publish.
The /build directory for the library contains nothing I can identify as an intermediate representation of my common modules, leading me to think that I need to explicitly tell Gradle to produce the files to be included as common in the published package.
As it is, the .aar and .jar files produced in the android and desktop (jvm) modules each look normal, but the published common module is empty.
I need that common module to be populated before I can code against it inside the common module of dependent projects.
Here is the relevant section of my build.gradle.kts. I omit the repository config as it appears to work.
I basically followed the instructions from kotlinlang.org.
I've looked at the maven-publish plugin configuration, the settings for the kotlin-multiplatformm plugin, and the configured project structure.
kotlin version is 1.6.10, unable to update due to Jetbrains Compose dependency.
plugins {
kotlin("multiplatform")
id("com.android.library")
id("maven-publish")
}
kotlin {
android {
publishLibraryVariants = listOf("release", "debug")
}
jvm("desktop") {
compilations.all {
kotlinOptions {
jvmTarget = "11"
}
}
}
val publicationsFromMainHost = listOf(jvm("desktop").name, "kotlinMultiplatform")
publishing {
publications {
matching { it.name in publicationsFromMainHost }.all {
val targetPublication = this#all
tasks.withType<AbstractPublishToMaven>()
.matching { it.publication == targetPublication }
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("androidx.startup:startup-runtime:1.1.1")
}
}
val androidTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
implementation("androidx.test:core:1.4.0")
implementation("androidx.test:runner:1.4.0")
implementation("androidx.test:rules:1.4.0")
implementation("org.robolectric:robolectric:4.6.1")
}
}
val desktopMain by getting
val desktopTest by getting {
dependencies {
implementation("junit:junit:4.13.2")
}
}
}
}
The answer is to manually supply the Kotlin stdlib dependency, rather than relying on the gradle plugin to add it.
When there are only jvm-based builds present, commonMain will be built with platform type of jdk8 rather than common. By making an explicit dependency on stdlib-common, it will be coerced back to the common platform, and then the correct metadata will be created and published.
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
}
}
I've a java project that is built using gradle kotlin dsl.
Now I want to use gradle-avro-plugin like this https://github.com/davidmc24/gradle-avro-plugin#alternate-usage
In kotlin dsl I have written the same logic as below -
plugins {
java
id( "com.github.davidmc24.gradle.plugin.avro") version "1.0.0"
}
dependencies {
implementation ("org.apache.avro", "avro", "1.10.1")
}
val generateAvro = tasks.register<com.github.davidmc24.gradle.plugin.avro.GenerateAvroJavaTask>("generateAvro") {
source("src/avro")
this.setOutputDir(file("dest/avro"))
}
configure<org.gradle.api.tasks.compile.JavaCompile> {
this.source = fileTree(generateAvro)
}
The above code is returning below error when I run grade compileJava-
> * What went wrong:
Extension of type 'JavaCompile' does not exist. Currently registered extension types: [ExtraPropertiesExtension, DefaultArtifactPublicationSet, SourceSetContainer, ReportingExtension, JavaPluginExtension, JavaInstallationRegistry, JavaToolchainService, DistributionContainer, JavaApplication, DefaultAvroExtension]
How can I fix this error?
I had similar issues, what worked for me was:
plugins {
id("com.github.davidmc24.gradle.plugin.avro") version "1.2.0"
}
dependencies {
implementation("org.apache.avro:avro:1.10.1")
}
tasks.withType<com.github.davidmc24.gradle.plugin.avro.GenerateAvroJavaTask> {
setOutputDir(file("src/dest/dir/"))
}
The important thing is I did not registered a new task, just specified a new destination directory for each task with the type GenerateAvroJavaTask
I have the following build.gradle configuration:
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.41'
}
repositories {
mavenCentral()
}
kotlin {
linuxX64("linux") {
binaries {
executable {
entryPoint = 'sample.main'
runTask?.args('')
}
}
}
sourceSets {
linuxMain {
dependencies {
api("org.http4k:http4k-core:3.183.0")
}
}
linuxTest {
}
}
}
And the following source file src/linuxMain/kotlin/sample/SampleLinux.kt :
package sample
fun hello(): String = "Hello, Kotlin/Native!"
fun main() {
println(hello())
}
How to add a external library in order to be able to use autocomplete in imports for the library org.http4k:http4k-core:3.183.0?
As you can see, I tried to add the line api("org.http4k:http4k-core:3.183.0") in linuxMain dependencies, but although intellij show the library in External Libraries section, I cannot work with the packages neither classes of http4k in SampleLinux.kt file: any org.http4k..... import attempt is not recognized and generates compilation error.
After a quick look, I am almost sure that http4k is JVM-only library, at least for now. According to this issue, they are still waiting for Native to grow. If you are interested, it would be nice if one can ask the library maintainers again. As far as K/N has grown a lot by the last year, maybe they change their mind.
My gradle project generates some java code inside gen/main/java using annotation processor. When I import this project into Eclipse, Eclipse will not automatically add gen/main/java as source folder to buildpath. I can do it manually. But is there a way to automate this?
Thanks.
You can easily add the generated folder manually to the classpath by
eclipse {
classpath {
file.whenMerged { cp ->
cp.entries.add( new org.gradle.plugins.ide.eclipse.model.SourceFolder('gen/main/java', null) )
}
}
}
whereby null as a second constructor arg means that Eclipse should put the compiled "class" files within the default output folder. If you want to change this, just provide a String instead, e.g. 'bin-gen'.
I think it's a little bit cleaner just to add a second source directory to the main source set.
Add this to your build.gradle:
sourceSets {
main {
java {
srcDirs += ["src/gen/java"]
}
}
}
This results in the following line generated in your .classpath:
<classpathentry kind="src" path="src/gen/java"/>
I've tested this with Gradle 4.1, but I suspect it'd work with older versions as well.
Andreas' answer works if you generate Eclipse project from command line using gradle cleanEclipse eclipse. If you use STS Eclipse Gradle plugin, then you have to implement afterEclipseImport task. Below is my full working snippet:
project.ext {
genSrcDir = projectDir.absolutePath + '/gen/main/java'
}
compileJava {
options.compilerArgs += ['-s', project.genSrcDir]
}
compileJava.doFirst {
task createGenDir << {
ant.mkdir(dir: project.genSrcDir)
}
createGenDir.execute()
println 'createGenDir DONE'
}
eclipse.classpath.file.whenMerged {
classpath - >
def genSrc = new org.gradle.plugins.ide.eclipse.model.SourceFolder('gen/main/java', null)
classpath.entries.add(genSrc)
}
task afterEclipseImport(description: "Post processing after project generation", group: "IDE") {
doLast {
compileJava.execute()
def classpath = new XmlParser().parse(file(".classpath"))
new Node(classpath, "classpathentry", [kind: 'src', path: 'gen/main/java']);
def writer = new FileWriter(file(".classpath"))
def printer = new XmlNodePrinter(new PrintWriter(writer))
printer.setPreserveWhitespace(true)
printer.print(classpath)
}
}
In resolving a dependency from a Maven-repository, Gradle has to download the corresponding pom-file. I would like to access this file from within the Gradle-script and save it somewhere. How can I do this?
Take a look at Artifact Query API. Here is the sample code (Groovy):
def componentIds = configurations.compileClasspath.incoming.resolutionResult.allDependencies.collect { it.selected.id }
def result = project.dependencies.createArtifactResolutionQuery()
.forComponents(componentIds)
.withArtifacts(MavenModule, MavenPomArtifact)
.execute()
for (component in result.resolvedComponents) {
component.getArtifacts(MavenPomArtifact).each { println "POM file for ${component.id}: ${it.file}" }
}
I'm using the same API in my plugin in Kotlin.
You could simply declare a dependency on the POM itself.
configurations {
pom
}
dependencies {
pom 'org.foo:some-lib:1.0.0#pom'
}
task copyPom(type: Copy) {
into "${buildDir}/poms"
from configurations.pom
}