6

I'm trying to test gradle 5 using kotlin DSL.

I created a lib, and built it as below:

Hasans-Air:blogiclib h_ajsf$ gradle init --type=kotlin-library

Starting a Gradle Daemon, 1 busy Daemon could not be reused, use --status for details

Select build script DSL:

1: groovy

2: kotlin

Enter selection (default: kotlin) [1..2] 2

Project name (default: blogiclib): 

Source package (default: blogiclib): 

**BUILD SUCCESSFUL** in 16s

2 actionable tasks: 2 executed

Hasans-Air:blogiclib h_ajsf$ ls

build.gradle.kts gradlew settings.gradle.kts

gradle gradlew.bat src

Hasans-Air:blogiclib h_ajsf$ code .

Hasans-Air:blogiclib h_ajsf$ gradle build

Then I got the output file generated as: build\libs\blogiclib.jar

The Library.kt file generated is:

package blogiclib

class Library {
    fun someLibraryMethod(): Boolean {
        return true
    }
}

And the build.gradle.kts generated is:

plugins {
    id("org.jetbrains.kotlin.jvm").version("1.3.10")
}

repositories {
    jcenter()
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    testImplementation("org.jetbrains.kotlin:kotlin-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

Then I generated a kotlin app and tested it as below:

Hasans-Air:gradle h_ajsf$ gradle init --type=kotlin-application

Starting a Gradle Daemon (subsequent builds will be faster)

Select build script DSL:

1: groovy

2: kotlin

Enter selection (default: kotlin) [1..2] 2

Project name (default: gradle): blogic

Source package (default: blogic): 

**BUILD SUCCESSFUL** in 25s

2 actionable tasks: 2 executed

Hasans-Air:gradle h_ajsf$ ls

build.gradle.kts gradlew settings.gradle.kts

gradle gradlew.bat src

Hasans-Air:gradle h_ajsf$ code .

Hasans-Air:gradle h_ajsf$ gradle run
**BUILD SUCCESSFUL** in 6m 4s

3 actionable tasks: 3 executed

Hasans-Air:gradle h_ajsf$ gradle run

**> Task :run**

Hello world.

Then I added the previously generated lib blogiclib.jar to the folder: main\resources

And made my App.kt file as:

package blogic

import blogiclib.LibraryKt

class App {
    val greeting: String
        get() {
            return "Hello world."
        }
}

fun main(args: Array<String>) {
    println("${App().greeting} = someLibraryMethod()")
}

And its build.gradle.kts based on my understanding from here as:

plugins {
    id("org.jetbrains.kotlin.jvm").version("1.3.10")
    application
}

repositories {
    jcenter()
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    testImplementation("org.jetbrains.kotlin:kotlin-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")

}

application {
    mainClassName = "blogic.AppKt"
}

task<JavaCompile>("compile") {
    source = fileTree(file("src/main/resources/blogiclib.jar"))
}

But at compiling I got the below error:

Hasans-Air:gradle h_ajsf$ gradle run

e: /Users/h_ajsf/Documents/gradle/src/main/kotlin/blogic/App.kt: (6, 8): Unresolved reference: blogiclib

**&gt; Task :compileKotlin** FAILED

FAILURE: Build failed with an exception.

* What went wrong:

Execution failed for task ':compileKotlin'.

&gt; Compilation error. See log for more details

* Try:

Run with **--stacktrace** option to get the stack trace. Run with **--info** or **--debug** option to get more log output. Run with **--scan** to get full insights.

* Get more help at **https://help.gradle.org**

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.

Use '--warning-mode all' to show the individual deprecation warnings.

See https://docs.gradle.org/5.0/userguide/command_line_interface.html#sec:command_line_warnings

**BUILD FAILED** in 1s

2 actionable tasks: 2 executed

UPDATE

In reference to the comments received, I did the below:

  1. Moved the library file to folder src/main/libs:
  2. Added the below code to the build.gradle.kts:

    configurations { create("externalLibs") }

    dependencies { "externalLibs"(files("src/main/libs/blogiclib.jar")) }

instead of:

task<JavaCompile>("compile") {
    source = fileTree(file("src/main/resources/blogiclib.jar"))
}

but still getting the same error :(

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
  • src/main/resources is for resources that must be bundled into your application jar, and that the application needs to read at runtime (like properties files, or images, or sounds). Not for libraries that must be in the compileclasspath of the application at build time. That's what the `implementation` configuration is for. Also, the source property of the JavaCompile task, [as documented](https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.JavaCompile.html#org.gradle.api.tasks.compile.JavaCompile:source), is read-only, and contains the file tree of the Java source files to compile – JB Nizet Nov 27 '18 at 21:55
  • You don't have any Java source file to compile, since you're using Kotlin, and a jar file is not a Java source file. The traditional way of using a library in an application is to publish the library in a repository, and to download this library from the repository. if you really want to use it from the file system, read https://docs.gradle.org/current/userguide/declaring_dependencies.html#sec:declaring_file_dependency – JB Nizet Nov 27 '18 at 21:59
  • @JBNizet kindly see my update. thanks – Hasan A Yousef Nov 28 '18 at 05:05
  • 1
    You must not create another configuration. The jar should be added to the existing implementation configuration, in order to be added to the compile classpath: `dependencies { implementation(files("src/main/libs/blogiclib.jar")) }`. – JB Nizet Nov 28 '18 at 06:47
  • Thanks @JBNizet, the librry itself is feasible now as `import blogiclib.Library` not as `import blogiclib.LibraryKt`, but getting error upon calling its function `someLibraryMethod()` as unresolved reference! – Hasan A Yousef Nov 28 '18 at 08:05
  • someLibraryMethod() is a method of the class Library. You need to create an instance of the Library class and call the method on the created object. – JB Nizet Nov 28 '18 at 09:00
  • @JBNizet how to do so, execuse me I'm new to Java and Kotlin – Hasan A Yousef Nov 28 '18 at 09:12
  • 1
    Same as what you do with App: you cal its constructor: `Library().someLibraryMethod()` – JB Nizet Nov 28 '18 at 09:37
  • Thanks alot @JBNizet, it is working now. – Hasan A Yousef Nov 28 '18 at 09:48
  • Can you advice if I've to do the same if I want to call native library `lib.so` or that is completly different, any guide/reference? – Hasan A Yousef Nov 28 '18 at 09:49
  • 1
    AFAIK, Kotlin doesn't have any specific support for using native libraries. That's the kind of thing you try to avoid in general, and Java has a hude ecosystem. My last experience of doing that was literally 20 years ago, with JNI, and I have no idea what the best way of doing that is nowadays. – JB Nizet Nov 28 '18 at 15:13

1 Answers1

14

You can include all jar files in some folders as follows:

dependencies {
    implementation(fileTree("libs/compile"))
    compileOnly(fileTree("libs/provided"))
}

Alternatively, select specific files:

repositories {
    flatDir {
        dirs("libs/compile")
        dirs("libs/provided")
    }
}

dependencies {
    implementation(":gson-2.8.5")
    compileOnly(":javaee-api-8.0")
}
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417