Search code examples
javawindowsscalamsys2

Scala under MSys2 - failure to initialize terminal


My environment is Windows 10 x64/Scala 2.11.7/Msys2 latest.

When running Scala from MSys2 console, I see the following:

$ scala
[ERROR] Terminal initialization failed; falling back to unsupported
java.lang.NoClassDefFoundError: Could not initialize class org.fusesource.jansi.internal.Kernel32
    at org.fusesource.jansi.internal.WindowsSupport.getConsoleMode(WindowsSupport.java:50)
    at jline.WindowsTerminal.getConsoleMode(WindowsTerminal.java:204)
    at jline.WindowsTerminal.init(WindowsTerminal.java:82)
    at jline.TerminalFactory.create(TerminalFactory.java:101)
    at jline.TerminalFactory.get(TerminalFactory.java:158)
    at jline.console.ConsoleReader.<init>(ConsoleReader.java:229)
    at jline.console.ConsoleReader.<init>(ConsoleReader.java:221)
    at jline.console.ConsoleReader.<init>(ConsoleReader.java:209)
    at scala.tools.nsc.interpreter.jline.JLineConsoleReader.<init>(JLineReader.scala:61)
    at scala.tools.nsc.interpreter.jline.InteractiveReader.<init>(JLineReader.scala:33)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$scala$tools$nsc$interpreter$ILoop$$instantiate$1$1.apply(ILoop.scala:865)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$scala$tools$nsc$interpreter$ILoop$$instantiate$1$1.apply(ILoop.scala:862)
    at scala.tools.nsc.interpreter.ILoop.scala$tools$nsc$interpreter$ILoop$$mkReader$1(ILoop.scala:871)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$15$$anonfun$apply$8.apply(ILoop.scala:875)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$15$$anonfun$apply$8.apply(ILoop.scala:875)
    at scala.util.Try$.apply(Try.scala:192)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$15.apply(ILoop.scala:875)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$15.apply(ILoop.scala:875)
    at scala.collection.immutable.Stream.map(Stream.scala:418)
    at scala.tools.nsc.interpreter.ILoop.chooseReader(ILoop.scala:875)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1$$anonfun$apply$mcZ$sp$2.apply(ILoop.scala:916)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:916)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:911)
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:911)
    at scala.reflect.internal.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:97)
    at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:911)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:74)
    at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_79).
Type in expressions to have them evaluated.
Type :help for more information.

scala>

When running it from cmd.exe, it works as expected. To debug the issue, I tried the following Scala program:

object Test extends App {
    println(org.fusesource.jansi.internal.WindowsSupport.getConsoleMode)
}

When run from Msys2, it produces the following error:

java.lang.UnsatisfiedLinkError: Could not load library. Reasons: [no jansi in java.library.path]
    at org.fusesource.hawtjni.runtime.Library.doLoad(Library.java:182)
    at org.fusesource.hawtjni.runtime.Library.load(Library.java:140)
    at org.fusesource.jansi.internal.Kernel32.<clinit>(Kernel32.java:37)
    at org.fusesource.jansi.internal.WindowsSupport.getConsoleMode(WindowsSupport.java:50)
    at Test$.delayedEndpoint$Test$1(Test.scala:5)
    at Test$delayedInit$body.apply(Test.scala:1)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at Test$.main(Test.scala:1)
    at Test.main(Test.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70)
    at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101)
    at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
    at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
    at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65)
    at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

What I tried and it didn't work:

  • Some threads on the internet mention that it might be caused by missing VC2008 runtime, so I made sure that I have it both for x64 and x86.
  • Extracting jansi.dll from scala/lib/jline-2.12.1.jar and putting it in my working directory (with "." included in java.library.path).
  • Starting with a fresh MSys2 home directory.
  • running bash --login -i from cmd.exe (same error when running scala)
  • trying 32-bit and 64-bit JREs

One more thing: the issue doesn't affect sbt; for example, running "sbt console" gives me a working Scala command line, albeit of version 2.10.4.


Solution

  • The problem is caused by the name clash between the scala shell script in scala/bin directory and scala.bat in the same directory. Msys2 runs the shell script, while cmd.exe runs the batch file. Apparently, the shell script is not suited for Msys2, which causes the error that I witnessed. Issuing cmd //c scala.bat from MSys2 results in a functional Scala command line.

    It is also trivial to edit the scala shell script to support MSys2: https://gist.github.com/kirillkh/a9ba2e00ef2e901f13bf

    I have opened a pull request with this change on the GitHub: https://github.com/scala/scala/pull/4674