Importing a source dependency with Gradle (Kotlin DSL) - kotlin

I want to import version 1.0.0 of this project https://github.com/whichdigital/ksv
as a source dependency in a Kotlin project using Gradle 6.3 with Kotlin DSL.
As the page tells me I added this into the settings.gradle.kts of my project
sourceControl {
gitRepository(java.net.URI.create("https://github.com/whichdigital/ksv.git")) {
producesModule("uk.co.whichdigital:ksv")
}
}
and using this dependency in my build.gradle.kts file:
implementation("uk.co.whichdigital:ksv:1.0.0")
trying to import tagged version/release 1.0.0 of the KSV repo. But building my project (importing the KSV repo) fails with following expection:
TaskDependencyResolveException: Could not determine the dependencies of task ':bootJar'.
...
Caused by: DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all task dependencies for configuration ':runtimeClasspath'.
....
Caused by: ModuleVersionResolveException: Git repository at https://github.com/whichdigital/ksv.git did not contain a project publishing the specified dependency.
Required by:
project :
I'm actually also the person who wrote/published the KSV-repository, so if there's some configuration that I missed, I can add it in the imported or importing project.

"uk.co.whichdigital:ksv:1.0.0" group id is wrong.
Can you please try
sourceControl {
gitRepository(java.net.URI.create("https://github.com/whichdigital/ksv.git")) {
producesModule("uk.co.whichdigital.ksv:ksv")
}
}
implementation("uk.co.whichdigital.ksv:ksv:1.0.0")

Related

Cocoapod dependency in iosMain of a Kotlin Multiplatform project, cocoapod unresolved reference

I am trying to create a wrapper around AWS Amplify to use for my project. I have a module inside my shared ( common ) module called Amplify. Here I integrated cocoapods as instructed in the official docs. But when I try to import anything from the iosMain I keep getting Unresolved reference: cocoapods.
My project structure is as follows
Common module (shared)
|- root module
|- other features
|- amplify wrapper module
In the root module I have the
kotlin {
ios {
binaries {
framework {
baseName = "Framework"
linkerOpts.add("-lsqlite3")
export(project(":common:main"))
}
}
}
And the setup for the cocoapods in the amplify module
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
id("multiplatform-setup") // this is from buildSrc, it adds the multiplatform plugin
id("android-setup")
id("org.jetbrains.kotlin.native.cocoapods")
kotlin("plugin.serialization") version "1.5.10"
}
version = "1.0"
kotlin {
sourceSets {
named("commonMain") {
dependencies {
}
}
}
cocoapods {
summary = "Amplify wrapper for KMP project"
homepage = "Link to a Kotlin/Native module homepage"
frameworkName = "AmplifyKMP"
pod("Amplify")
pod("AmplifyPlugins/AWSCognitoAuthPlugin")
pod("AmplifyPlugins/AWSPinpointAnalyticsPlugin")
}
}
My idea is that I'd be able to expose my wrapper from the commonMain code, that would call actual implementations from the Amplify Android and Amplify IOS libraries. My first problem is the cocoapods being unresolved and secondly all of the examples from the official docs and github all have cocoapods in the main module (root module in my case) from where they export the framework, I am not sure my approach is even feasible.
The first problem is easy. You need to add kotlin("native.cocoapods") to your plugins section.
On the second, can a sub-module import pods with cinterop and make them available to a module that depends on them? I haven't tried it. In theory the cocoapods plugin should be able to just import pods definitions to kotlin. However, the cocoapods Kotlin gradle plugin (aka kotlin("native.cocoapods")) will configure ios targets to create a framework. That might create issues with the dependency config.
In the amplify module I don't see that you're defining any iOS targets, so you'll probably need to do that, but that config will be altered by kotlin("native.cocoapods"). You'll likely need to step in and modify that yourself. You can step in and do that in gradle, but I would prepare to spend some time tweaking that.
https://github.com/touchlab/KaMPKit/blob/main/shared/build.gradle.kts#L114

Kotlin - Import Jar and Use Class

I have created a library in kotlin using gradle init and following the prompts. It compiles and produces a jar file in lib/build/libs. I then have another project that needs to access functions in the library. through intelliJ, I add the dependency by going to Project Settings > Modules > Dependencies and adding the jar file. I then attempt to import the package defined in the library with import DemoLib where DemoLib is the name of the package (and the name of the library). This does not compile as it does not recognize the package name. I have also tried importing as a library rather than a jar, with the same results. How can I achieve the desired result?
EDIT: In case it helps here is the code:
Library:
package DemoLib
class Library {
fun someLibraryMethod(): Boolean {
return true
}
}
Client Code:
package DemoClientAppOne
import DemoLib.*
class App {
val greeting: String
get() {
return "Hello World!"
}
}
fun main() {
println(App().greeting)
}
Not terribly interesting, but the point is that DemoLib is an unresolved reference even after adding the jar as a dependency
You have three options
Combine two projects under same IDE project and use Gradle dependencies on project:
settings.gradle:
include 'project-lib'
build.gradle:
implementation project(':project-lib')
See https://docs.gradle.org/current/userguide/declaring_dependencies.html#sub:project_dependencies
Install the library into local repository and add it as a Gradle dependency:
apply plugin: 'maven'
then run gradle publishToMavenLocal
and add mavenLocal() repository in gradle.build file.
See How to install a compiled by Gradle jar into the local Gradle Repository files-2.1 instead of the Maven repository?
Use this jar as a flat library Gradle dependency (assuming this jar is located in the libs directory:
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
implementation name: 'lib-jar-name'
}
If DemoLib is a package,
you need to
import DemoLib.*
to import all its names into scope. Just import DemoLib wouldn't do anything. Or better,
import DemoLib.SomeClass
to import only one specific name. Actually, if you start typing SomeClass (assuming that's a name in your DemoLib package), IDEA should suggest adding the import.
Also, it's better to follow naming conventions from the beginning, and DemoLib is not a good package name:
Names of packages are always lower case and do not use underscores (org.example.project). Using multi-word names is generally discouraged, but if you do need to use multiple words, you can either simply concatenate them together or use camel case (org.example.myProject).

Can't add kotlinx to a fresh Kotlin/JS project

Trying to figure out what I'm doing wrong. I created a small video of exactly what I'm doing in IntelliJ on Windows.
https://www.youtube.com/watch?v=nIH_55Zbxus&feature=youtu.be
And I'll describe it here in text.
Create a new project
Tick the Gradle > Kotlin/JS for browser template and untick everything else
Add implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8' to the dependencies block in the build.gradle.
Sync the gradle files
Attempt to use something from the kotlinx.coroutines namespace
Hopefully its just a silly thing I'm missing. I expected to just have to add the coroutines library to be able to actually import it. It looks like the library is listed in the project structure for the main module so I'm not sure what else might be wrong. Here is a repo of the project too.
plugins {
id 'org.jetbrains.kotlin.js' version '1.3.72'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-js"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
testImplementation "org.jetbrains.kotlin:kotlin-test-js"
}
kotlin.target.browser { }
You should add kotlinx-coroutines-core-js dependency. See the documentation: https://github.com/Kotlin/kotlinx.coroutines#js

"No main manifest attribute" when creating Kotlin jar using IntelliJ IDEA

When creating a jar from my Kotlin code and running it, it says "No main manifest attribute".
When looking at the manifest.mf, it has this content:
Manifest-Version: 1.0
When looking at the file in the source, it has this content:
Manifest-Version: 1.0
Main-Class: MyMainClass
When manually copying the source manifest to the jar, it runs perfectly.
Screenshot of my artifact settings
I got this error with Gradle and Kotlin.
I had to add in my build.gradle.kts an explicit manifest attribute:
tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = "com.example.MainKt"
}
}
From the gradle documentation, it's better to create a fatJar task to englobe all of the runtime dependencies in case you encounter java.lang.NoClassDefFoundError errors
If any of the dependent jars has a MANIFEST.MF file, it will override your custom one which defines the Main-Class.
In order to address this problem you should do the following:
Disable the alphabetical ordering
Change items ordering so that item which has META-INF/MANIFEST.MF file is the first in the list
Your custom MANIFEST.MF will be picked up by IntelliJ IDEA and displayed for the jar artifact.
See the related issue for more details.
You can also use Gradle or Maven to generate the fat jar instead.
1.Add the following task definition in the build script
tasks.jar {
manifest {
attributes["Main-Class"] = "MainKt"
}
configurations["compileClasspath"].forEach { file: File ->
from(zipTree(file.absoluteFile))
}
}
Then the jar tasks (Tasks | build | jar) again from the right hand sidebar.
For Spring boot apps:
What worked for me (gradle kotlin) in build.gradle.kts
add spring boots plugin &. apply dependency management
plugins {
id("org.springframework.boot") version "2.6.7"
}
apply(plugin = "io.spring.dependency-management")
set your main class
springBoot {
mainClass.set("com.example.Application")
}
Found this all by reading up on spring-boot docs found here

Provided dependencies using Gradle (JetGradle) and Intellij Idea 13

I have a multiproject build with multiple war modules that depends on one jar module.
Both war and jar modules have dependencies over libraries like Spring, Hibernate and so on, those dependencies are defined as providedCompile on the war modules and as compile on the jar.
The problem is that when JetGradle updates the dependencies all artifacts have errors, as the dependencies from the jar module are required on the artifacts.
I would like to use any of this solutions:
Include the libraries on the lib folder of the server and have Intellij treat them as provided.
Include the libraries as project wide libraries somehow, so intellij puts them on all artifacts even after the gradle dependencies are updated.
On the other hand my approach could be completely wrong from the beginning.
The dependencies in the war modules are defined as:
providedCompile 'org.slf4j:slf4j-log4j12:1.7.5'
providedCompile 'org.slf4j:jcl-over-slf4j:1.7.5'
...
compile(project(':jarModule')) {transitive = false}
...
The dependencies in the jar module are defined as:
...
compile 'org.slf4j:slf4j-log4j12:1.7.5'
compile 'org.slf4j:jcl-over-slf4j:1.7.5'
...
The best solution I found was to set the transitive "compile" dependencies from the jar module as provided using the following code in the Gradle configuration file:
apply plugin: 'idea'
configurations {
provided
provided.extendsFrom(compile)
}
idea {
module {
scopes.PROVIDED.plus += configurations.provided
}
}
For Gradle 2.0+ modify the last bit to be like this:
idea {
module {
scopes.PROVIDED.plus += [configurations.provided]
}
}
This solution works using the Intellij Gradle plugin and also the idea task in Gradle
I got this solution working based on the info on this urls:
https://github.com/Netflix/RxJava/pull/145
http://www.gradle.org/docs/current/dsl/org.gradle.plugins.ide.idea.model.IdeaModule.html
I hope this helps someone else
I tried the above solution but found a problem. In my scenario I had a sub-project that had the above configuration. The problem was that the transitive dependencies of the sub-project were not being exported in the IntelliJ configuration, which caused the base project to stop compiling.
I did some digging around and stumbled upon this little gem which fixed the problem.
https://github.com/gradle/gradle/blob/ccddc438ce09293d84030ebe31668d739c8a228a/gradle/providedConfiguration.gradle
/**
* Adds a configuration named 'provided'. 'Provided' dependencies
* are incoming compile dependencies that aren't outgoing
* dependencies. In other words, they have no effect on transitive
* dependency management.
*/
configurations {
provided
providedPlusCompile.extendsFrom(compile, provided)
testCompile.extendsFrom(providedPlusCompile)
}
sourceSets.main {
compileClasspath = configurations.providedPlusCompile
}
plugins.withType(IdeaPlugin) {
idea.module.scopes.PROVIDED.plus = [ configurations.provided ]
}
Adding to the answer from Adrijardi, for Gadle 2.0 + not only did I have to change
scopes.PROVIDED.plus += configurations.provided
to
scopes.PROVIDED.plus += [configurations.provided]
I also had to change
provided project(":module-name") {
transitive = false
}
to
provided (project(":module-name")) {
transitive = false
}
Note the extra set of brackets on the second code sample