1

I'm trying to upgrade a scala library to scala3 and cannot seem to figure out how to get the scala3 language to work with jlink. It says I'm missing transitive dependencies on a jlink build. You can see the build failure here.

I can of course add these to the jlinkIgnore settings but that seems to be a poor practice. What are the transitive dependencies at play here that I am missing?

Here is a direct link to a CI failure https://github.com/bitcoin-s/bitcoin-s/actions/runs/15227451712/job/42831225145?pr=5713#step:5:23602

[error] Dependee packages not found in classpath. You can use jlinkIgnoreMissingDependency to silence these. [error] org.apache.pekko.http.scaladsl.model -> org.apache.pekko.http.javadsl.model [error] org.apache.pekko.stream.serialization -> org.apache.pekko.stream [error] scala.quoted -> scala [error] scala.quoted.runtime -> scala [error] stack trace is suppressed; run last appServer / jlinkModules for the full output [error] (appServer / jlinkModules) Missing package dependencies 
7
  • Could you try to prepare MCVE? Now your project is too big to investigate. Package scala.quoted is from "org.scala-lang" %% "scala3-library" aka "org.scala-lang" % "scala3-library_3" mvnrepository.com/artifact/org.scala-lang/scala3-library_3 Commented May 24 at 15:05
  • You can investigate transitive dependencies with sbt dependencyTree Commented May 24 at 15:15
  • Which JDK you have? For something similar I had to change it to JDK21 from 24. Commented May 29 at 10:09
  • @MateuszKubuszok welcome to sbt 1.10.11 (Eclipse Adoptium Java 21.0.4) (from OP's CI link) Commented May 29 at 12:04
  • From the code of the error message, it seems to be checking for dangling dependencies that aren't ignored so the reason for the error occurs when switching to scala3. Did adding those dependencies to jlinkIgnore fix the build without additional issues? Commented May 30 at 3:45

1 Answer 1

3
+500

Current reproduction is

git clone https://github.com/Christewart/bitcoin-s-core.git cd bitcoin-s-core git checkout 2024-05-11-scala3-crossbuild git clone https://github.com/bitcoin-s/secp256k1-zkp.git sbt appServer/universal:packageBin 

Your CI fails on sbt appServer/universal:packageBin. Locally it produces the error

[info] Running: jdeps --multi-release 21 -R /media/data/Projects2/bitcoin-s-core/app/server/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/app/server-routes/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/app-commons/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/core/.jvm/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/crypto/.jvm/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/secp256k1jni/target/classes /media/data/Projects2/bitcoin-s-core/db-commons/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/key-manager/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/node/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/async-utils/.jvm/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/chain/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/bitcoind-rpc/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/tor/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/wallet/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/fee-provider/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/dlc-wallet/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/dlc-node/target/scala-3.7.0/classes /media/data/Projects2/bitcoin-s-core/zmq/target/scala-3.7.0/classes /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.7.0/scala3-library_3-3.7.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/lihaoyi/upickle_3/4.0.2/upickle_3-4.0.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/pekko/pekko-actor_3/1.1.3/pekko-actor_3-1.1.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/pekko/pekko-http_3/1.2.0/pekko-http_3-1.2.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/pekko/pekko-stream_3/1.1.3/pekko-stream_3-1.1.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/pekko/pekko-slf4j_3/1.1.3/pekko-slf4j_3-1.1.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/codehaus/janino/janino/3.1.12/janino-3.1.12.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/google/code/gson/gson/2.13.1/gson-2.13.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/google/guava/guava/33.4.8-jre/guava-33.4.8-jre.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/io/dropwizard/metrics/metrics-healthchecks/4.2.30/metrics-healthchecks-4.2.30.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/io/dropwizard/metrics/metrics-jvm/4.2.30/metrics-jvm-4.2.30.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/io/dropwizard/metrics5/metrics-core/5.0.0/metrics-core-5.0.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/net/java/dev/jna/jna/5.17.0/jna-5.17.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/github/waffle/waffle-jna/3.5.1/waffle-jna-3.5.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/osgi/osgi.core/8.0.0/osgi.core-8.0.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/osgi/org.osgi.service.jdbc/1.1.0/org.osgi.service.jdbc-1.1.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/osgi/org.osgi.framework/1.10.0/org.osgi.framework-1.10.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/log4j/log4j/1.2.17/log4j-1.2.17.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/avalon-framework/avalon-framework/20020627/avalon-framework-20020627.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/logkit/logkit/20020529/logkit-20020529.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/tukaani/xz/1.10/xz-1.10.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/javax/servlet/javax.servlet-api/4.0.1/javax.servlet-api-4.0.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/javax/mail/mail/1.4.7/mail-1.4.7.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/javax/jms/javax.jms-api/2.0.1/javax.jms-api-2.0.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/playframework/play-json_3/3.0.4/play-json_3-3.0.4.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/typesafe/config/1.4.3/config-1.4.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/typesafe/slick/slick_3/3.6.1/slick_3-3.6.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/typesafe/slick/slick-hikaricp_3/3.6.1/slick-hikaricp_3-3.6.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/xerial/sqlite-jdbc/3.49.1.0/sqlite-jdbc-3.49.1.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/lihaoyi/ujson_3/4.0.2/ujson_3-4.0.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/zeromq/jeromq/0.5.4/jeromq-0.5.4.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/lihaoyi/upack_3/4.0.2/upack_3-4.0.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/lihaoyi/upickle-implicits_3/4.0.2/upickle-implicits_3-4.0.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/pekko/pekko-http-core_3/1.2.0/pekko-http-core_3-1.2.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/pekko/pekko-protobuf-v3_3/1.1.3/pekko-protobuf-v3_3-1.1.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/reactivestreams/reactive-streams/1.0.4/reactive-streams-1.0.4.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/typesafe/ssl-config-core_3/0.6.1/ssl-config-core_3-0.6.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/codehaus/janino/commons-compiler/3.1.12/commons-compiler-3.1.12.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations/2.38.0/error_prone_annotations-2.38.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/google/guava/failureaccess/1.0.3/failureaccess-1.0.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/google/j2objc/j2objc-annotations/3.0.0/j2objc-annotations-3.0.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/io/dropwizard/metrics/metrics-core/4.2.30/metrics-core-4.2.30.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/net/java/dev/jna/jna-platform/5.16.0/jna-platform-5.16.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/slf4j/jcl-over-slf4j/2.0.16/jcl-over-slf4j-2.0.16.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/github/ben-manes/caffeine/caffeine/3.1.8/caffeine-3.1.8.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/checkerframework/checker-qual/3.48.3/checker-qual-3.48.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/net/bytebuddy/byte-buddy/1.15.11/byte-buddy-1.15.11.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/net/bytebuddy/byte-buddy-agent/1.15.11/byte-buddy-agent-1.15.11.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/osgi/osgi.annotation/8.1.0/osgi.annotation-8.1.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/javax/activation/activation/1.1/activation-1.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/flywaydb/flyway-core/11.8.0/flyway-core-11.8.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/flywaydb/flyway-database-postgresql/11.8.0/flyway-database-postgresql-11.8.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/postgresql/postgresql/42.7.5/postgresql-42.7.5.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/bouncycastle/bcprov-jdk18on/1.80/bcprov-jdk18on-1.80.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scodec/scodec-bits_3/1.2.1/scodec-bits_3-1.2.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/playframework/play-functional_3/3.0.4/play-functional_3-3.0.4.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.15.2/jackson-core-2.15.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.15.2/jackson-annotations-2.15.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.14.3/jackson-datatype-jdk8-2.14.3.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.15.2/jackson-datatype-jsr310-2.15.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.15.2/jackson-databind-2.15.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/io/monix/monix-execution_3/3.4.1/monix-execution_3-3.4.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/zaxxer/HikariCP/6.3.0/HikariCP-6.3.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/lihaoyi/upickle-core_3/4.0.2/upickle-core_3-4.0.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/eu/neilalexander/jnacl/1.0.0/jnacl-1.0.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/apache/pekko/pekko-parsing_3/1.2.0/pekko-parsing_3-1.2.0.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/parboiled/parboiled_3/2.5.1/parboiled_3-2.5.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/fasterxml/jackson/dataformat/jackson-dataformat-toml/2.15.2/jackson-dataformat-toml-2.15.2.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/io/monix/monix-internal-jctools_3/3.4.1/monix-internal-jctools_3-3.4.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/io/monix/implicitbox_3/0.3.4/implicitbox_3-0.3.4.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/com/lihaoyi/geny_3/1.1.1/geny_3-1.1.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scijava/native-lib-loader/2.5.0/native-lib-loader-2.5.0.jar ^^^^^^^^ <------------- ... [error] Dependee packages not found in classpath. You can use jlinkIgnoreMissingDependency to silence these. [error] org.apache.pekko.http.scaladsl.model -> org.apache.pekko.http.javadsl.model [error] org.apache.pekko.stream.serialization -> org.apache.pekko.stream [error] scala.quoted -> scala [error] scala.quoted.runtime -> scala [error] stack trace is suppressed; run last appServer / jlinkModules for the full output [error] (appServer / jlinkModules) Missing package dependencies [IJ]last appServer / jlinkModules ... [error] java.lang.RuntimeException: Missing package dependencies [error] at scala.sys.package$.error(package.scala:30) [error] at com.typesafe.sbt.packager.archetypes.jlink.JlinkPlugin$.$anonfun$projectSettings$9(JlinkPlugin.scala:108) [error] at scala.Function1.$anonfun$compose$1(Function1.scala:49) [error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:63) [error] at sbt.std.Transform$$anon$4.work(Transform.scala:69) [error] at sbt.Execute.$anonfun$submit$2(Execute.scala:283) [error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:24) [error] at sbt.Execute.work(Execute.scala:292) [error] at sbt.Execute.$anonfun$submit$1(Execute.scala:283) [error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265) [error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:65) [error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) [error] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) [error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) [error] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) [error] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) [error] at java.base/java.lang.Thread.run(Thread.java:1583) [error] (appServer / jlinkModules) Missing package dependencies 

Notice the command jdeps ... above.

https://docs.oracle.com/en/java/javase/11/tools/jdeps.html

Simpler reproduction is the following.

  • For Scala 2:

myscalaproject/src/main/scala/module-info.java

module myscalaproject { exports com.example; } 

myscalaproject/src/main/scala/com/example/App.scala

package com.example object App { def main(args: Array[String]): Unit = { println("hi") } } 

myscalaproject/project/build.properties

sbt.version = 1.11.0 

myscalaproject/project/plugins.sbt

addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.11.1") 

myscalaproject/build.sbt

Global / onChangedBuildSource := ReloadOnSourceChanges ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / scalaVersion := "2.13.16" lazy val root = (project in file(".")) .settings( name := "myscalaproject", compileOrder := CompileOrder.ScalaThenJava, packageOptions += Package.ManifestAttributes( "Class-Path" -> "/home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar" ), Compile / mainClass := Some("com.example.App"), //https://stackoverflow.com/questions/21461798/how-to-disable-scaladoc-generation-in-dist-task-in-play-2-2-x-using-project-bui Compile / packageDoc / publishArtifact := false, packageDoc / publishArtifact := false, Compile / doc / sources := Seq.empty ) .enablePlugins( JavaAppPackaging, JlinkPlugin, ) 

sbt package produces myscalaproject_2.13-0.1.0-SNAPSHOT.jar.

Then jdeps works properly:

jdeps -s -R mydir/myscalaproject_2.13-0.1.0-SNAPSHOT.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar myscalaproject -> java.base myscalaproject -> /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar scala-library-2.13.16.jar -> java.base 
  • But for Scala 3:

myscala3project/src/main/scala/module-info.java

myscala3project/src/main/scala/com/example/App.scala

myscalaproject/project/build.properties

myscala3project/project/plugins.sbt

The same.

myscala3project/build.sbt

Global / onChangedBuildSource := ReloadOnSourceChanges ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / scalaVersion := "3.7.0" lazy val root = (project in file(".")) .settings( name := "myscala3project", compileOrder := CompileOrder.ScalaThenJava, packageOptions += Package.ManifestAttributes( "Class-Path" -> Seq( "/home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar", "/home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.7.0/scala3-library_3-3.7.0.jar", ).mkString(" ") ), Compile / mainClass := Some("com.example.App"), //https://stackoverflow.com/questions/21461798/how-to-disable-scaladoc-generation-in-dist-task-in-play-2-2-x-using-project-bui Compile / packageDoc / publishArtifact := false, packageDoc / publishArtifact := false, Compile / doc / sources := Seq.empty ) .enablePlugins( JavaAppPackaging, JlinkPlugin, ) 

jdeps fails:

jdeps -s -R mydir/myscala3project_3-0.1.0-SNAPSHOT.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.7.0/scala3-library_3-3.7.0.jar myscala3project -> java.base myscala3project -> /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar myscala3project -> /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.7.0/scala3-library_3-3.7.0.jar scala-library-2.13.16.jar -> java.base scala3-library_3-3.7.0.jar -> java.base scala3-library_3-3.7.0.jar -> jdk.unsupported scala3-library_3-3.7.0.jar -> not found <------------- !!! scala3-library_3-3.7.0.jar -> /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar 

You will see more details if you remove the summary flag -s

... scala.quoted -> scala scala-library-2.13.16.jar scala.quoted -> scala not found <------------- ??? ... scala.quoted.runtime -> scala scala-library-2.13.16.jar scala.quoted.runtime -> scala not found <------------- ??? ... 

It seems there is a bug in jdeps:

A: https://stackoverflow.com/a/75430512/5249621 (Q: jdeps returns "not found")

You can see the actual Path parser checks if the -cp/-classpath argument list contains dir/.* format and not dir/* format as advertised by the docs, examples and the API's javadoc.

// wildcard to parse all JAR files e.g. -classpath dir/* int i = p.lastIndexOf(".*"); 

JDK 11 Adoptium JDK 17 Adoptium JDK 21 Adoptium JDK 24 Adoptium JDK 24 Corretto OpenJDK

So if you don't want to patch jdk and jdeps then it seems you should add those lines to jlinkIgnore, indeed.


Update. Actually, the situation is a little more complicated. I patched OpenJDK 25 fixing jdeps. On contrary to .split, .lastIndexOf doesn't support regex. So I replaced

int i = p.lastIndexOf(".*"); if (i > 0) { Path dir = Paths.get(p.substring(0, i)); ... 

with

int i = lastIndex(p, ".\\*"); if (i > 0) { Path dir = Paths.get(p.substring(0, i)); ... private int lastIndex(String str, String regex) { String splitted[] = (str + " ").split(regex); if (splitted.length == 0 || splitted.length == 1) { return -1; } return str.length() - 1 - splitted[splitted.length - 1].length(); } 

https://github.com/DmytroMitin/jdk/commit/9e601728961170940aee1356855f075557bae613

https://stackoverflow.com/a/10619920/5249621 ( Find Last Index Of by Regex in Java )

or just

int i = p.lastIndexOf("*"); if (i > 0) { Path dir = Paths.get(p.substring(0, i - 1)); ... 

https://github.com/DmytroMitin/jdk/commit/381ea799460e959eec5a8000d837934fcd29946f

But still jdeps -s -R ... (-s stands for "summary", -R for "recursively" i.e. transitive dependencies) produces not found in some places:

https://github.com/DmytroMitin/so79636833_jdeps_bug_demo/actions/runs/15419307905/job/43389831125

(https://github.com/DmytroMitin/so79636833_jdeps_bug_demo - creating a module via module-info.java seems not significant

https://github.com/DmytroMitin/setup-java

https://github.com/DmytroMitin/jdk25

https://github.com/DmytroMitin/jdk/tree/so79636833_jdeps_bug)

Run JDK 25 jdeps jdeps -s -R /home/runner/work/so79636833_jdeps_bug_demo/so79636833_jdeps_bug_demo/target/scala-3.7.1/so79636833_jdeps_bug_demo_3-0.1.0-SNAPSHOT.jar /home/runner/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.7.1/scala3-library_3-3.7.1.jar /home/runner/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar scala-library-2.13.16.jar -> java.base scala3-library_3-3.7.1.jar -> java.base scala3-library_3-3.7.1.jar -> jdk.unsupported scala3-library_3-3.7.1.jar -> not found <------------ scala3-library_3-3.7.1.jar -> /home/runner/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar so79636833_jdeps_bug_demo_3-0.1.0-SNAPSHOT.jar -> java.base so79636833_jdeps_bug_demo_3-0.1.0-SNAPSHOT.jar -> /home/runner/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar 

I found better flags -v ("verbose" i.e. even more verbose than if just to remove -s) and especially --missing-deps

jdeps --missing-deps -R target/scala-3.7.1/so79636833_jdeps_bug_demo_3-0.1.0-SNAPSHOT.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.7.1/scala3-library_3-3.7.1.jar /home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar scala3-library_3-3.7.1.jar -> not found scala.quoted.Quotes$reflectModule$TypeReprModule -> scala.AnyKind not found scala.quoted.Quotes$reflectModule$TypeTreeModule -> scala.AnyKind not found scala.quoted.Type -> scala.AnyKind not found scala.quoted.Type$ -> scala.AnyKind not found scala.quoted.runtime.QuoteUnpickler -> scala.AnyKind not found 

So what confuses jdeps in Scala 3 is scala.AnyKind. And this makes sense. In Scala there are types present in sources but not in bytecode, or even some types/classes not present either in sources or bytecode (e.g. trait ContextFunctionN Can't create an anonymous implementation of ContextFunction1 in Scala 3). But scala.AnyKind is a class present in sources but not in bytecode

https://www.scala-lang.org/api/current/scala/AnyKind.html

https://github.com/scala/scala3/blob/main/library-aux/src/scala/AnyKind.scala

Scala 3. Kind polymorphism and AnyKind type - any code example?

package scala final abstract class AnyKind 
Class.forName("scala.AnyKind") //java.lang.ClassNotFoundException 

So the answer to your question

Either this bug is in the jlink tool itself or is something weird about the new scala3 system that didn't exist with scala2

is that it's both a bug in jlink (actually, jdeps) and something specific to Scala 3.

Here is the output of jdeps --missing-deps -R ... for https://github.com/bitcoin-s/bitcoin-s

https://gist.github.com/DmytroMitin/6b6d9338dc8abe38bd15113f1cd0d915

Sign up to request clarification or add additional context in comments.

7 Comments

First off, thank you! This is awesome. Second off, would you be interested in publishing your minimal reproducible repo and then filing a jdk issue? I've done this before with jlink and had success getting bugs fixed for scala builds (bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8282351)
@ChrisStewart You can ask at contributors.scala-lang.org. I mean for your original question it was not the best place. But now when we know that the thing is in scala.AnyKind and jdeps, language design questions relate there. Honestly I suspect that no one cared. I can't see any reason why originally not to make AnyKind a type rather than class. In Scala people often make OOP-ish choices making something classes when types would be enough. Classes are needed only if we're going to instantiate or extend them.
@ChrisStewart For example in Shapeless it would be better not to have trait HNil, just type HNil = HNil.type: github.com/milessabin/shapeless/blob/v2.3.13/core/shared/src/… Then issues with two different types HNil and HNil.type <: HNil could be avoided: stackoverflow.com/questions/59186443 stackoverflow.com/questions/54412106 In Scala 3 this is fixed: github.com/scala/scala3/blob/3.7.1/library/src/scala/…
@ChrisStewart Also KeyTag could be a type rather than trait: github.com/milessabin/shapeless/issues/1285 etc.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.