https://kotlinlang.org logo
#getting-started
Title
# getting-started
r

Ray Rahke

03/13/2024, 7:21 AM
My project is split up into multiple packages that I import into main. Pressing play in intellij runs my project, but when I manually do
kotlinc Main.kt -include-runtime -d out.jar && java -jar out.jar
, I get unresolved errors about my package imports.
h

hfhbd

03/13/2024, 7:24 AM
Well, it depends on the error message you didn’t mention. If you get ClassNotFoundExceptions during runtime it’s because you didn’t add the classpath to the java call.
r

Ray Rahke

03/13/2024, 7:25 AM
error: unresolved reference: mysubmodule import mysubmodule
h

hfhbd

03/13/2024, 7:26 AM
And IMHO you should not fight against the main conventions of the ecosystem. This makes everything harder.
r

Ray Rahke

03/13/2024, 7:27 AM
that is hard when the conventions extend to being forced into a specific IDE that I dislike
h

hfhbd

03/13/2024, 7:27 AM
Then you might need to add the jars/files to kotlinc.
r

Ray Rahke

03/13/2024, 7:27 AM
and currently, all we're trying to do is run code, from the command line
is the convention in JVM/Kotlin to be so dependent on GUI tooling that running code without clicking big shiny icons is tricky to get working?
h

hfhbd

03/13/2024, 7:28 AM
Gradle isn’t forced to a specific IDE, build servers don’t need an IDE ;)
r

Ray Rahke

03/13/2024, 7:29 AM
But just having a normal development workflow, where I write code, execute it, test it, repeat, etc.
most of the guides I find online say "click this button in intellij"
h

hfhbd

03/13/2024, 7:31 AM
I never use IntelliJs buttons but Gradle 🤷🏻‍♂️ and properly almost many users here too.
r

Ray Rahke

03/13/2024, 7:32 AM
Then you might need to add the jars/files to kotlinc. (edited)
could you clarify what you mean by this. I have this structure src/ main.kt foo/ A.kt B.kt
in main, i do
Copy code
import foo.A

fun main() {
  A()
}
(omitting the
package
declarations)
r

Ray Rahke

03/13/2024, 7:34 AM
what would I put there
I obviously cannot explicitly enumerate my packages
my codebase is a pyramid of dozens of packages
i assume it can just recursively resolve imports
like all other languages
Copy code
sudo kotlinc src -include-runtime -d out.jar && java -jar outjar
Error: Unable to access jarfile outjar
this is my problem
both answers look equally useless though
one of the answers just says to do
-cp main.jar:package_a
...but that is for a single package.
why does the big play button in intellij not require this
it intelligently resolves imports recursively.
j

Joffrey

03/13/2024, 7:41 AM
> I obviously cannot explicitly enumerate my packages In the JVM world you pass all your sources to the compiler, yes. Imports are not used for dependency resolution, they are used as a convenient syntax to avoid using qualified names
r

Ray Rahke

03/13/2024, 7:41 AM
but the play button doesn't do that..
j

Joffrey

03/13/2024, 7:42 AM
but the play button doesn't do that..
What do you mean?
h

hfhbd

03/13/2024, 7:42 AM
It does under the hood
r

Ray Rahke

03/13/2024, 7:42 AM
so why isn't there a command line utility that does that under the hood
h

hfhbd

03/13/2024, 7:43 AM
You just invented a build tool like Maven or Gradle.
j

Joffrey

03/13/2024, 7:43 AM
IntelliJ calls the Kotlin compiler with all your source files depending on how you configured it. If you use Gradle, then IntelliJ will know the source directories from the Gradle source sets configuration
r

Ray Rahke

03/13/2024, 7:43 AM
i am using gradle right now
is there a gradle command i need to do
h

hfhbd

03/13/2024, 7:43 AM
./gradlew :compileKotlin
or just
./gradlew assemble
👍 1
r

Ray Rahke

03/13/2024, 7:47 AM
after doing ./gradlew assemble, where does the jar go
trying to run it now
j

Joffrey

03/13/2024, 7:47 AM
i assume it can just recursively resolve imports like all other languages
That's not how most JVM languages work, btw
1
h

hfhbd

03/13/2024, 7:48 AM
build/libs/name.jar
r

Ray Rahke

03/13/2024, 7:48 AM
just, in software, you modularize your code into sub folders with sub folders etc. that are all eventually imported back up into main where you run your code
i go python main.py, and it triggers that cascade of imports
or npm run dev
or rust run (i forget)
h

hfhbd

03/13/2024, 7:49 AM
npm is also a build tool.
😆 1
1
r

Ray Rahke

03/13/2024, 7:49 AM
all i'm conveying is that when you execute a top-level file like main.whatever, and main.whatever references other files, some mechanism resolves those
npm run dev just triggers node runtime typically
image.png
Copy code
java -jar build/libs/kts.jar                                                                                    
no main manifest attribute, in build/libs/kts.jar
(sorry for naming the project kts. it is not a .kts project)
j

Joffrey

03/13/2024, 7:54 AM
all i'm conveying is that when you execute a top-level file like main.whatever, and main.whatever references other files, some mechanism resolves those
You don't execute a source file. You compile a set of source files, then you execute compiled files/classes/jars. In the JVM world, you can compile multiple parts independently. So you need to tell the compiler which files you're compiling together, and which dependencies need to be available to them. Your examples are about running the app, which is different. And actually Python and JS are not compiled, so you can't really compare that to a compilation. Rust uses cargo as a build tool, so if you're comparing with this you should compare with Gradle commands, and you get pretty much the same convenience
r

Ray Rahke

03/13/2024, 7:54 AM
im fine using a gradle command to compile and run the code
👌 1
h

hfhbd

03/13/2024, 7:54 AM
Yes, you need to specify the entry point. When running with the IntelliJ button, IntelliJ
sets
it for you.
r

Ray Rahke

03/13/2024, 7:55 AM
so then something like
Copy code
manifest {
    attributes["Main-Class"] = "MainKt"
}
?
j

Joffrey

03/13/2024, 7:55 AM
To do that, use the
application
plugin in Gradle, so it knows it's not a library but an application you can run. You don't need to manually set manifest entries, Gradle will do it for you. https://kotlinlang.org/docs/get-started-with-jvm-gradle-project.html#explore-the-build-script
Copy code
plugins {
    kotlin("jvm") version "1.9.23"
    application
}

application {
    mainClass.set("MainKt") // The main class of the application
}
👍 1
h

hfhbd

03/13/2024, 7:57 AM
application.mainClass.set("MainKt")
j

Joffrey

03/13/2024, 7:58 AM
I agree that it's annoying that the tutorial goes through IntelliJ, it gives a false sense that IntelliJ is necessary. I think it was made in an attempt to simplify the project initialization for beginners, but for users like you it seems counter productive
h

hfhbd

03/13/2024, 7:58 AM
and if you want to run the jar without calling java, use
./gradlew run
and for tests
./gradlew test
j

Joffrey

03/13/2024, 8:01 AM
Yep, all you really need for a JVM CLI application is a
build.gradle.kts
with:
Copy code
plugins {
    kotlin("jvm") version "1.9.23"
    application
}

repositories {
    mavenCentral()
}

application {
    mainClass.set("MainKt")
}
Then place your source files in
src/main/kotlin
, with one of them called
Main.kt
with the main function. Then you can compile and run your app using
./gradlew run
. If you just want compilation or test you can run other Gradle tasks.
r

Ray Rahke

03/13/2024, 8:02 AM
How can I change the folder structure target. I have
src/main.kt
, not
src/main/kotllin/Main.kt
Copy code
plugins {
    kotlin("jvm") version "1.9.23"
    application
}
repositories {
    mavenCentral()
}
application {
    mainClass.set("MainKt")
}
dependencies {
    testImplementation(kotlin("test"))
}
sourceSets {
    main {
        kotlin.srcDirs("src/")
    }
    test {
        kotlin.srcDirs("test/")
    }
}
j

Joffrey

03/13/2024, 8:08 AM
Yeah if you want to stray away from conventions, you're going to have to add more config in your Gradle build script. And I think you got it right, here
r

Ray Rahke

03/13/2024, 8:08 AM
Copy code
/gradlew run                                                                                                    3.66s
> Task :run FAILED
Error: Could not find or load main class MainKt
Caused by: java.lang.ClassNotFoundException: MainKt

FAILURE: Build failed with an exception.
main.kt
Copy code
package <http://org.me|org.me>

import mod.Foo

fun main() {
    Foo()
}
j

Joffrey

03/13/2024, 8:09 AM
You have a
package <http://org.me|org.me>
at the top, so your main class is not just
MainKt
but
org.me.MainKt
r

Ray Rahke

03/13/2024, 8:10 AM
great, all working now. thanks a lot
🙏 1
is it good practice to do package org.me at the top of main.kt?
j

Joffrey

03/13/2024, 8:11 AM
Yeah it's often the case to have all your sources under at least some top level package name (usually a reverse domain name that you own). But it's not mandatory.
r

Ray Rahke

03/13/2024, 8:12 AM
gotcha. I apologies for my posts recently coming off abrasive. just not used to this setup / run process all being so difficult coming from primarily scripting languages, and have been struggling with actually getting to do anything with this language for days now so feeling exhausted. thanks for helping
👍 1
h

hfhbd

03/13/2024, 8:14 AM
You are welcome. BTW do you need a trailing slash in
srcDirs
?
r

Ray Rahke

03/13/2024, 8:14 AM
I assumed it was necessary to indicate a folder vs file
j

Joffrey

03/13/2024, 8:15 AM
Thanks for saying this, really appreciated. I'm happy to help. Note that you can avoid a part of this frustration if you try to follow more the conventions of the tools rather than tweak them to match the conventions you're used to from other ecosystems.
That said, I have to admit that Gradle can be intimidating when you're starting. We're trying to address that with Amper.