Open s5bug opened 3 years ago
Thanks for your report. Since I did not know the feature to pass arguments as a file, this plugin does not support it. I'll try the feature later.
A temporary workaround for problem with many dependencies is to use an uber-jar of them, and to use it as runtime classpath for nativeImage task.
configurations {
uberJar
}
dependencies {
// some your dependencies here
// ...
// add uberJar task outputs to uberJar configuration
uberJar(provider { project.tasks.makeUberJar.outputs.files })
}
task makeUberJar(type: Jar) {
from(provider { configurations.runtimeClasspath.collect { zipTree(it) } })
destinationDirectory = file("$buildDir/uberjar")
archiveBaseName = 'runtime-all'
}
nativeImage {
dependsOn 'makeUberJar'
runtimeClasspath = configurations.uberJar
// your native image configurations here
// ...
}
If I already have the assembly plugin enabled, is it easy to use that? Or would that be a bad idea?
You can use a third-party task that provides the ability to combine multiple jar files into one, whereas it's not clear to me what you're calling an 'assembly plugin'.
For example you can use uber-jar created by com.github.johnrengelman.shadow
plugin(https://plugins.gradle.org/plugin/com.github.johnrengelman.shadow).
The point of this workaround is to reduce the number of jar files that cause command lengthening to one, by creating uber-jar from them.
current trouble
native-image -cp /path/to/lib1.jar:/path/to/lib2.jar:...many many jar files...:/path/to/libN.jar
workaround
native-image -cp /project/path/build/uber-jar/uber-jar
Ah yeah, I have shadow. In SBT it's called sbt-assembly and I keep forgetting that it's not called the same thing in Gradle because I'm so used to Scala development.
I'll give this a shot.
It seems native-image does not support argfile feature.
Huh. Should a relevant issue be opened in Graal? Because it seems like it could be useful to have...
I detected a temporary workaround.
You can pass dependencies path to native-image command via jar's manifest file using Class-Path
attribute.
configurations {
// to remove too long jar path, prepare empty configuration
emptyConfiguration
}
// copies jar files for manifest can refer to dependencies
task copyDependencies(type: Copy, group: 'build') {
from configurations.runtimeClasspath
destinationDir = file("$buildDir/libs")
}
jar {
dependsOn 'copyDependencies'
manifest {
// entry jar files via Class-Path attribute
def classpathString = configurations.runtimeClasspath.collect { File f -> f.name }.join(' ')
attributes 'Class-Path': classpathString
}
}
nativeImage {
// remove jar's paths from command
runtimeClasspath = configurations.emptyConfiguration
}
I have one more workaround.
The main idea is:
build/lib
build/lib/*
as the -cp argument value.I.E.
tasks {
register("buildNativeImage") {
dependsOn(named("build"))
doLast {
val libs = File(buildDir, "libs").apply { mkdir() }
val nativeImage = File(buildDir, "native-image").apply { mkdir() }
copy {
from(configurations.runtimeClasspath)
into(libs)
}
copy {
from(configurations.compileClasspath)
into(libs)
}
val args = listOf(
"--shared",
"-cp",
"${libs.toString().replace("\\", "/").trimEnd { it == '/' }}/*",
"-H:Path=$nativeImage"
)
logger.info("============================")
logger.info("")
logger.info("Native-Image args are:")
logger.info("$args")
logger.info("")
logger.info("============================")
val windows = DefaultNativePlatform.getCurrentOperatingSystem().isWindows
exec {
this.executable = "native-image".let { if (windows) "$it.cmd" else it }
this.args = args
}
}
}
}
This example was tested on Windows and macOS.
@mike-neck as for me, it more similar to the logic of your plugin.
@s5bug, I've tried your repo, using the master branch, and I have no such 'The command line is too long' error. Did your upgrade to version 1.4.1
of this plugin (in the master branch) fix the error?
(I eventually hit some errors during the native-image building, but they have nothing to do with this issue.)
I haven't manually compiled my project in a long long time. If @dependabot updated the plugin then it's updated. I'll set a reminder to go off in a bit to attempt manual compilation.
I still have this bug on 1.4.1. It's true. I have a huge cp in my build, much more than 8k allowed in windows. It would be nice to implement some of the mentioned workarounds right into the plugin.
I can also confirm I still experience this issue.
Now GraalVM CE Java16 21.2.0.
Describe What happened
Running
.\gradlew.bat nativeImage
generates aThe command line is too long.
error if enough arguments are added to it.How To Reproduce
Steps to reproduce the behavior:
Compile my project with a lot of dependencies to a native image.
build.gradle
file(or othergradle
build files).permalink to build.gradle that causes this issue
.\gradlew.bat nativeImage
Expected behavior
I expected
native-image
to be called properly.StackTraces or Console logs
Environment
Additional Context
I've read that
native-image
supports passing arguments as a file for this reason, although I don't know how to enable that or how to use it.