

위와 같이 Kotlin 프로젝트 생성

그리고 다음과 같이 테스트로 args를 받아와 실행해보았다.
개발 중에는 다음과 같이 Intellij IDEA의 도움을 받아서 args를 받아오려고 한다.

Progran arguments에 위와 같이 args에 담고자 하는 것들을 넣어줄 수 있음

코드 실행 결과 위처럼 args에 [”geet”, “init”]과 같은 배열이 담김
실제 사용시에는 빌드 후 jar 파일이 생기면 zsh 설정 파일에 alias를 “geet”으로 설정하여 jar를 실행시키고, 명령어를 보낼 생각이다.
즉 “geet init”이라고 치면 “geet”은 jar파일을 실행하는 용도, “init”이 실제 전해지는 명령어(args)인 것
예시로 진행해보았다.
일단 빌드

./gradlew build 명령어로 빌드 → 그러면 build/libs 폴더 안에 jar 파일이 생성되어있다.
그 후 zshrc에 아래와 같이 alias를 넣어준다.
vi ~/.zshrc

그리고 “geet” 명령어를 입력했더니 다음과 같은 에러가 발생했다.
/Users/songjs/projects/myproject/intellij/kotlin/Geet/build/libs/Geet-1.0-SNAPSHOT.jar에 기본 Manifest 속성이 없습니다.
“기본 Manifest 속성이 없습니다.” 에러를 해결하고자 GPT를 참고하였다.
tasks.jar {
manifest {
attributes["Main-Class"] = "MainKt"
}
}
위와 같이 tasks.jar의 manifest 관련 설정을 build.gradle에 추가해 주었다.
Main-Class는 실행하고자 하는 메인 클래스를 지정하는데, 이 클래스를 실행하기 위해 필요
만약 이러한 설정이 되어 있지 않다면, Manifest 속성을 명시적으로 추가하여 JAR 파일을 생성해야 한다.
위 예시처럼 tasks.jar 블록 안에 manifest 속성을 추가하여 Manifest를 설정할 수 있다.
그 후 빌드하고 다시 실행을 하려고 하니 다시 아래와 같은 에러가 발생하였다.
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at MainKt.main(Main.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
... 1 more
해결 참고
Gradle Project: java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = "MainKt"
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from(sourceSets.main.get().output)
dependsOn(configurations.runtimeClasspath)
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
}
tasks.jar 부분을 위와 같이 수정해주었다.
manifest 설정:
manifest 설정은 JAR 파일의 메인 클래스를 지정하는 데 사용됩니다.attributes["Main-Class"] = "MainKt"는 JAR 파일에서 실행될 메인 클래스를 MainKt로 지정합니다. Kotlin 스크립트의 메인 클래스 이름은 MainKt입니다.duplicatesStrategy 설정:
duplicatesStrategy = DuplicatesStrategy.EXCLUDE는 중복 파일이 있을 때 어떻게 처리할지를 지정합니다. 여기서는 중복을 제외하는 설정을 사용하고 있습니다.from 설정:
from(sourceSets.main.get().output)은 소스 세트의 출력을 JAR에 포함시키도록 지정합니다. 이 부분은 소스 코드 및 리소스 파일을 JAR에 포함시킵니다.dependsOn 설정:
dependsOn(configurations.runtimeClasspath)는 런타임 클래스패스에 있는 파일들을 JAR에 포함시키도록 지정합니다. 이는 빌드된 JAR 파일이 실행될 때 필요한 라이브러리와 종속성을 포함하게 합니다.from 및 map 설정:
from과 map을 조합하여 런타임 클래스패스의 JAR 파일을 필터링하고, 필요한 파일들을 JAR에 추가합니다. configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) } 부분은 런타임 클래스패스에 있는 JAR 파일들을 필터링하여 JAR에 포함시키도록 구성합니다.이제 드디어 빌드 후 실행하면 잘 된다!!
