Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REPL: load transitive dependencies of JARs on classpath #6660

Closed
scabug opened this issue Nov 13, 2012 · 10 comments
Closed

REPL: load transitive dependencies of JARs on classpath #6660

scabug opened this issue Nov 13, 2012 · 10 comments

Comments

@scabug
Copy link

scabug commented Nov 13, 2012

The Scala REPL should load dependencies referenced in MANIFEST.MF files of other JARs on the classpath.

As described in https://support.typesafe.com/tickets/1585:

We have JAR files that contain standard META-INF/MANIFEST.MF files with the Class-Path: entry. This entry points to a number of other JARs that should be loaded transitively by the ClassLoader. Unfortunately the REPL does not load these transitive dependencies, instead dependency JARs need to be placed on the classpath explicitly one by one.

As an example let's say I have A.jar and B.jar. I also have a C.jar that has nothing else in it than a MANIFEST.MF with 'Class-Path: A.jar B.jar'. If I use

> scala -classpath A.jar;B.jar

everything is ok. I can e.g import A and import B. However, if I use

> scala -classpath C.jar

I couldn't import or use any classes from A.jar or B.jar.
@scabug
Copy link
Author

scabug commented Nov 13, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6660?orig=1
Reporter: @szeiger
Affected Versions: 2.10.0

@scabug
Copy link
Author

scabug commented Apr 19, 2015

Li Haoyi (lihaoyi) said:
This works in the Ammonite REPL, not with raw jar files, but you can specify any coordinate on maven central and the REPL will pull down any transitive dependencies necessary. e.g. here I am asking for upickle and getting jawn-parser for free:

@ load.ivy("com.lihaoyi" %% "upickle" % "0.2.6")
:: resolving dependencies :: com.lihaoyi#upickle_2.11-caller;working
	confs: [default]
	found com.lihaoyi#upickle_2.11;0.2.6 in central
	found org.scala-lang#scala-library;2.11.4 in central
	[2.11.4] org.scala-lang#scala-library;2.11.4
	found org.spire-math#jawn-parser_2.11;0.7.0 in central
	found com.lihaoyi#acyclic_2.11;0.1.2 in central
	found org.scala-lang#scala-compiler;2.11.0 in central
	found org.scala-lang.modules#scala-xml_2.11;1.0.1 in central
	found org.scala-lang.modules#scala-parser-combinators_2.11;1.0.1 in central
	found org.scala-lang#scala-reflect;2.11.4 in central
	[2.11.4] org.scala-lang#scala-reflect;2.11.4
res17: Unit = ()
@ import upickle._
import upickle._
@ upickle.write(Seq(1, 2, 3))
res19: String = "[1,2,3]"
@

@SethTisue
Copy link
Member

I wonder how the Dotty REPL does on this

@lrytz
Copy link
Member

lrytz commented Nov 22, 2019

From outside the repl, it can be done with coursier (dwijnand/scala-runners#3), so there's some overlap here with the work discussed at scala/scala-dev#326.

@som-snytt
Copy link

I thought this is what --use-manifest-class-path was for, but I guess not?

➜  t6660-run.obj git:(issue/6660-manifest-cp) ✗ scala --class-path y.jar:x.jar
Welcome to Scala 2.13.10 (OpenJDK 64-Bit Server VM, Java 19).
Type in expressions for evaluation. Or try :help.

scala> class C extends Y
class C

scala>
:quit
➜  t6660-run.obj git:(issue/6660-manifest-cp) ✗ scala --class-path y.jar --use-manifest-class-path
Welcome to Scala 2.13.10 (OpenJDK 64-Bit Server VM, Java 19).
Type in expressions for evaluation. Or try :help.

scala> class C extends Y
       ^
       error: Symbol 'type <empty>.X' is missing from the classpath.
       This symbol is required by 'method Y.x'.
       Make sure that type X is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
       A full rebuild may help if 'Y.class' was compiled against an incompatible version of <empty>.

scala>
:quit

Same result with scalac.

@som-snytt som-snytt self-assigned this Apr 6, 2023
@som-snytt
Copy link

-nobootcp -toolcp y.jar --use-manifest-class-path
shows

  ZipArchiveClassPath(/home/amarki/projects/scala/build/pack/lib/scala-repl-frontend.jar,None)
  ZipArchiveClassPath(y.jar,None)
  DirectoryClassPath(.)
[snip]
  ManifestResourcesClassPath(file:/home/amarki/projects/scala/build/pack/lib/scala-repl-frontend.jar)
  ManifestResourcesClassPath(file:/home/amarki/projects/scala/test/files/run/t6660-run.obj/y.jar)
  ManifestResourcesClassPath(file:/home/amarki/projects/scala/test/files/run/t6660-run.obj/x.jar)

and both jars at end of [search path for class files:. (But not a successful compile yet.)

@som-snytt
Copy link

oh there is a fat comment

   * with a particularly prepared scala-library.jar. It should have all classes listed in the manifest like e.g. this entry:
   * Name: scala/Function2$mcFJD$sp.class

I'm not entirely sure why that is useful, as opposed to exposing the contents of the jar file. Who has a home chef to specially prepare anything?

@SethTisue
Copy link
Member

this is now scala-cli's job

@SethTisue SethTisue closed this as not planned Won't fix, can't repro, duplicate, stale Apr 7, 2023
@SethTisue SethTisue removed this from the Backlog milestone Apr 7, 2023
@SethTisue
Copy link
Member

@som-snytt if you're planning something, I think Scala 3 is the appropriate first venue — though we could discuss...

@som-snytt
Copy link

@SethTisue this is why I looking at that class path stuff! The tweak to expandManifestPath showed the JarRunner only uses the class-path from the first ("main") jar, but not recursively and not for other jars on the class path. Too bad the 10-year statute of limitations has already run out on this ticket.

The use case, per the OP, is that it simplifies running local jars. scala foo.jar without a script to set the class path, etc. That can be nice on servers, where there is no desire to download anything from anywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants