diff --git a/build.sbt b/build.sbt index 16be7f13d..40b4d2218 100644 --- a/build.sbt +++ b/build.sbt @@ -18,6 +18,8 @@ libraryDependencies ++= Seq( "org.apache.commons" % "commons-compress" % "1.18", // for jdkpackager "org.apache.ant" % "ant" % "1.10.5", + // workaround for the command line size limit + "com.github.eldis" % "tool-launcher" % "0.2.1", "org.scalatest" %% "scalatest" % "3.0.5" % Test ) diff --git a/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala index ec923a5f8..2d33ae526 100644 --- a/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/archetypes/jlink/JlinkPlugin.scala @@ -71,7 +71,7 @@ object JlinkPlugin extends AutoPlugin { // Jdeps has a few convenient options (like --print-module-deps), but those // are not flexible enough - we need to parse the full output. - val jdepsOutput = runForOutput(run("jdeps", "--multi-release" +: javaVersion +: "-R" +: paths), log) + val jdepsOutput = run("jdeps", "--multi-release" +: javaVersion +: "-R" +: paths) val deps = jdepsOutput.linesIterator // There are headers in some of the lines - ignore those. @@ -146,7 +146,7 @@ object JlinkPlugin extends AutoPlugin { IO.delete(outDir) - runForOutput(run("jlink", jlinkOptions.value), log) + run("jlink", jlinkOptions.value) outDir }, @@ -176,12 +176,26 @@ object JlinkPlugin extends AutoPlugin { private lazy val defaultJavaHome: File = file(sys.props.getOrElse("java.home", sys.error("no java.home"))) - private def runJavaTool(jvm: File, log: Logger)(exeName: String, args: Seq[String]): ProcessBuilder = { - val exe = (jvm / "bin" / exeName).getAbsolutePath + private def runJavaTool(jvm: File, log: Logger)(toolName: String, args: Seq[String]): String = { + log.info("Running: " + (toolName +: args).mkString(" ")) - log.info("Running: " + (exe +: args).mkString(" ")) + val toolLauncherClass = classOf[ru.eldis.toollauncher.ToolLauncher] + val toolLauncherJar = file( + // This assumes that the code source is a file or a directory (as opposed + // to a remote URL) - but that should hold. + toolLauncherClass.getProtectionDomain.getCodeSource.getLocation.getPath + ).getAbsolutePath - Process(exe, args) + val javaExe = (jvm / "bin" / "java").getAbsolutePath + + IO.withTemporaryFile(s"snp-$toolName-", "args") { argFile => + IO.writeLines(argFile, args) + + val argFileArg = "@" + argFile.getAbsolutePath + val builder = Process(Vector(javaExe, "-jar", toolLauncherJar, "-tool", toolName, argFileArg)) + + runForOutput(builder, log) + } } // Like `ProcessBuilder.!!`, but this logs the output in case of a non-zero diff --git a/src/sbt-test/jlink/test-jlink-misc/build.sbt b/src/sbt-test/jlink/test-jlink-misc/build.sbt index 9f08b27c6..2e8deae19 100644 --- a/src/sbt-test/jlink/test-jlink-misc/build.sbt +++ b/src/sbt-test/jlink/test-jlink-misc/build.sbt @@ -62,3 +62,21 @@ val issue1247JakartaJavaModules = project ), runChecks := jlinkBuildImage.value ) + +// Should succeed for large classpaths. +val issue1266 = project + .enablePlugins(JlinkPlugin) + .settings( + // An arbitrary JAR with a non-platform module. + libraryDependencies += "com.sun.xml.fastinfoset" % "FastInfoset" % "1.2.16", + // A lot of "dummy" dependencies, so that the resulting classpath is over + // the command line limit (2MB on my machine) + unmanagedJars in Compile ++= { + def mkPath(ix: Int) = target.value / s"there-is-no-such-file-$ix.jar" + + 1.to(300000).map(mkPath) + }, + logLevel in jlinkModules := Level.Error, + + runChecks := jlinkBuildImage.value + ) diff --git a/src/sbt-test/jlink/test-jlink-misc/test b/src/sbt-test/jlink/test-jlink-misc/test index 2ae30732c..0d327a3ac 100644 --- a/src/sbt-test/jlink/test-jlink-misc/test +++ b/src/sbt-test/jlink/test-jlink-misc/test @@ -3,4 +3,5 @@ > issue1243/runChecks > issue1247BadAutoModuleName/runChecks > issue1247ExternalModule/runChecks -> issue1247JakartaJavaModules/runChecks \ No newline at end of file +> issue1247JakartaJavaModules/runChecks +> issue1266/runChecks \ No newline at end of file