Search code examples
scalasbtgraalvmpicocli

Sbt task for picocli graalvm reflection generation?


In picocli they give examples on how to generate GraalVM reflection configurations during the build for Maven and Gradle.

Gradle example

configurations {
    generateConfig
}
dependencies {
    compile 'info.picocli:picocli:3.9.3'
    generateConfig 'info.picocli:picocli-codegen:3.9.3'
}

task

task(generateGraalReflectionConfig, dependsOn: 'classes', type: JavaExec) {
    main = 'picocli.codegen.aot.graalvm.ReflectionConfigGenerator'
    classpath = configurations.generateConfig + sourceSets.main.runtimeClasspath
    def outputFile = new File(project.buildDir, 'cli-reflect.json')
    args = ["--output=$outputFile", 'com.your.package.YourCommand1', 'com.your.package.YourCommand2']
}
assemble.dependsOn generateGraalReflectionConfig

How could I write something equivalent for sbt ?

This is what I got so far but I don't know if I'm going in the right direction.

import Dependencies._

ThisBuild / scalaVersion := "2.12.8"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / organization := "com.example"
ThisBuild / organizationName := "example"

lazy val root = (project in file("."))
  .settings(
    name := "poc-cli",
    libraryDependencies += scalaTest % Test,
    libraryDependencies += "info.picocli" % "picocli" % "3.9.3",
    libraryDependencies += "info.picocli" % "picocli-codegen" % "3.9.3",
  )

lazy val graalConfig = inputKey[Unit]("gen-graal-config") 

graalConfig:= {
    val conf = (runMain in Compile).fullInput(" picocli.codegen.aot.graalvm.ReflectionConfigGenerator --output=cli-reflect.json example.Hello").evaluated
}

enablePlugins(GraalVMNativeImagePlugin)

Edit

in my initial question, I had the code below, with my current code the problem is solved

lazy val graalConfig = taskKey[Unit]("graal-config") := {
    Process("java" :: "-jar" :: "picocli.codegen.aot.graalvm.ReflectionConfigGenerator" :: "--output" :: "cli-reflect.json" :: "???" :: Nil,
        baseDirectory.value / "lib").!
}

Solution

  • The solution was

    import Dependencies._
    
    
    ThisBuild / scalaVersion := "2.12.8"
    ThisBuild / version := "0.1.0-SNAPSHOT"
    ThisBuild / organization := "com.example"
    ThisBuild / organizationName := "example"
    
    lazy val root = (project in file("."))
      .settings(
        name := "poc-cli",
        libraryDependencies += scalaTest % Test,
        libraryDependencies += "info.picocli" % "picocli" % "3.9.3",
        libraryDependencies += "info.picocli" % "picocli-codegen" % "3.9.3",
      )
    
    lazy val graalConfig = inputKey[Unit]("gen-graal-config")
    
    graalVMNativeImageOptions += "-H:ReflectionConfigurationFiles=../cli-reflect.json"
    
    graalConfig:= {
        (runMain in Compile).fullInput(" picocli.codegen.aot.graalvm.ReflectionConfigGenerator -o=target/cli-reflect.json example.Hello").evaluated
    }
    
    enablePlugins(GraalVMNativeImagePlugin)
    

    then I can run:

    $ sbt graalConfig
    $ sbt graalvm-native-image:packageBin