Использование тени Gradle с мультиплатформой Kotlin - PullRequest
0 голосов
/ 04 ноября 2018

Есть ли способ настроить Gradle Shadow с мультиплатформенным проектом Kotlin? Я использую «новую» версию многоплатформенного проекта, где у меня есть все определения / зависимости набора исходных текстов в одном файле. Вот мой файл сборки:

buildscript {
    ext.ktor_version = "1.0.0-beta-3"

    repositories {
       maven { url "https://plugins.gradle.org/m2/"}
    }

    dependencies {
        classpath "com.github.jengelman.gradle.plugins:shadow:4.0.2"
    }
}


plugins {
    id 'kotlin-multiplatform' version '1.3.0'
    id 'com.github.johnrengelman.shadow' version '4.0.2'
    id 'application'
}

version = '1.0'
group = '[redacted]'
mainClassName = '[redacted]'

repositories {
    maven { url "https://dl.bintray.com/kotlin/exposed" }
    maven { url "https://dl.bintray.com/kotlin/ktor" }
    mavenCentral()
    jcenter()
}
kotlin {
    targets {
        fromPreset(presets.jvm, 'jvm')
        fromPreset(presets.js, 'js')
    }
    sourceSets {
        commonMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
            }
        }
        commonTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-common'
                implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
            }
        }
        jvmMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
                implementation 'org.jetbrains.exposed:exposed:0.11.2'
                implementation "org.mindrot:jbcrypt:0.4"
                implementation "org.slf4j:slf4j-simple:1.8.0-beta2"
                implementation "io.ktor:ktor-server-netty:$ktor_version"
                implementation "io.ktor:ktor-jackson:$ktor_version"
                implementation "mysql:mysql-connector-java:8.0.13"
            }
        }
        jvmTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test'
                implementation 'org.jetbrains.kotlin:kotlin-test-junit'
            }
        }
        jsMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-js'
            }
        }
        jsTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-js'
            }
        }
    }
}

shadowJar {
    baseName = '[redacted]'
    version = 1.0
}

Пытаясь использовать это, я получаю печальный результат файла JAR, содержащего только META-INF (304 байта). Честно говоря, я не знаю, с чего начать, и это заставило меня задуматься и запутаться часами. Любая помощь будет оценена.

Скелет моего проекта:

├── build.gradle
├── gradle.properties
├── settings.gradle
└── src
    ├── commonMain
    │   └── kotlin
    │       ├── PasswordValidator.kt
    │       └── Responses.kt
    └── jvmMain
        └── kotlin
            └── XXX
                └── XXXXXX
                    └── ticketing
                        ├── Auth.kt
                        ├── Registration.kt
                        ├── Server.kt
                        ├── requests
                        │   ├── Auth.kt
                        │   ├── Register.kt
                        │   └── account
                        │       ├── Close.kt
                        │       ├── List.kt
                        │       ├── ModifyPassword.kt
                        │       ├── New.kt
                        │       └── SetAdmin.kt
                        └── services
                            ├── AsyncHandler.kt
                            ├── Exception.kt
                            ├── RateLimiter.kt
                            └── Token.kt

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

У меня есть решение, которое работает с kotlin-multiplatform версией плагина 1.3.31 и проектом, созданным с помощью опции IntelliJ New Project/Kotlin/JS Client and JVM Server | Gradle.

buildscript {
  repositories {
    jcenter()
  }
}

plugins {
  id 'com.github.johnrengelman.shadow' version '5.0.0'
  id 'kotlin-multiplatform' version '1.3.31'
}

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

repositories {
  jcenter()
  maven { url "https://dl.bintray.com/kotlin/ktor" }
  mavenCentral()
}
def ktor_version = '1.2.1'
def logback_version = '1.2.3'

kotlin {
  jvm()
  js() {
    compilations.all {
      kotlinOptions {
        languageVersion = "1.3"
        moduleKind = "umd"
        sourceMap = true
        metaInfo = true
      }
    }
  }
  sourceSets {
    commonMain {
      dependencies {
        implementation kotlin('stdlib-common')
      }
    }
    commonTest {
      dependencies {
        implementation kotlin('test-common')
        implementation kotlin('test-annotations-common')
      }
    }
    jvmMain {
      dependencies {
        implementation kotlin('stdlib-jdk8')
        implementation "io.ktor:ktor-server-netty:$ktor_version"
        implementation "io.ktor:ktor-html-builder:$ktor_version"
        implementation "io.ktor:ktor-jackson:$ktor_version"
        implementation "ch.qos.logback:logback-classic:$logback_version"
      }
    }
    jvmTest {
      dependencies {
        implementation kotlin('test')
        implementation kotlin('test-junit')
        implementation "io.ktor:ktor-server-test-host:$ktor_version"
      }
    }
    jsMain {
      dependencies {
        implementation kotlin('stdlib-js')
      }
    }
    jsTest {
      dependencies {
        implementation kotlin('test-js')
      }
    }
  }
}

def webFolder = new File(project.buildDir, "web")
def jsCompilations = kotlin.targets.js.compilations

task populateWebFolder(dependsOn: [jsMainClasses]) {
  doLast {
    copy {
      from jsCompilations.main.output
      from kotlin.sourceSets.jsMain.resources.srcDirs
      jsCompilations.test.runtimeDependencyFiles.each {
        if (it.exists() && !it.isDirectory()) {
          from zipTree(it.absolutePath).matching { include '*.js' }
        }
      }
      into webFolder
    }
  }
}

jsJar.dependsOn(populateWebFolder)

def mainServerClassName = "org.pongasoft.jamba.quickstart.server.be.ServerKt"

task run(type: JavaExec, dependsOn: [jvmMainClasses, jsJar]) {
  main = mainServerClassName
  ignoreExitValue = true
  classpath {
    [
        kotlin.targets.jvm.compilations.main.output.allOutputs.files,
        configurations.jvmRuntimeClasspath,
    ]
  }
  args = ["-P:org.pongasoft.jamba.quickstart.server.staticWebDir=${webFolder.canonicalPath}"]
}

task shadowJar(type: ShadowJar, dependsOn: [jvmJar]) {
  from jvmJar.archiveFile
  configurations = [project.configurations.jvmRuntimeClasspath]
  manifest {
      attributes 'Main-Class': mainServerClassName
  }
}

Я считаю, что основной вопрос, почему он не работает, заключается в том, что, согласно документации:

От: Документация Shadow , Shadow - реактивный плагин. Это означает, что применение Shadow само по себе не будет выполнять настройку вашего проекта. Вместо этого Shadow реагирует. Это означает, что для большинства пользователей должны быть явно применены плагины java или groovy, чтобы получить желаемый эффект.

, и в результате он не работает из коробки с мультиплатформенным плагином kotlin, который имеет нетрадиционную настройку. Таким образом, хитрость заключается в том, чтобы определить задачу ShadowJar, которая зависит от jvmJar и использует артефакт в качестве его from (jvmJar.archiveFile) и конфигурации project.configurations.jvmRuntimeClasspath для включения всех зависимостей времени выполнения. И это также место для определения записи Main-Class для манифеста.

Обратите внимание, что эта версия не объединяет статические ресурсы, сгенерированные для части компиляции javascript.

0 голосов
/ 08 января 2019

На самом деле, вам не нужна тень. Просто добавьте следующий код в блок kotlin> target (build.gradle)

configure([jvmJar]) {
    manifest{
        attributes 'Main-Class':'main.class.path.MainKt'
    }
}

Сгенерированный файл Jar в build/libs будет содержать указанный Main-Class в манифесте. Все необходимые классы также уже есть. Сгенерированный jar готов к использованию (не забудьте указать внешние зависимости в проекте, где вы используете jar - мне удалось заставить его работать на проекте gradle java).

...