Compile Scala 2.8.x code with Apache Buildr - scala

I have been struggling to get Buildr to compile my Scala 2.8 project and I was hoping someone might have figured this out already.
Currently I have the standard HelloWorld application with a buildfile like the following:
ENV['JAVA_HOME'] = 'C:\Program Files (x86)\Java\jdk1.6.0_17'
ENV['SCALA_HOME'] = 'C:\scala-2.8.0.Beta1-RC6'
define "HelloWorld" do
#artifact_ns['Buildr::Compiler::Scalac'].library = '2.8.0'
require 'buildr/scala'
puts Scala.version
end
When I run buildr I get the following output:
(in C:/Users/Travis/eclipse_ws/HelloWorld, development)
2.7.5
Building HelloWorld
Compiling HelloWorld into C:/Users/Travis/eclipse_ws/HelloWorld/target/classes
Buildr aborted!
←[31mScala compiler crashed:
#←[0m
The first problem is the NoClassDefFoundError - it cannot find the scala compiler's main class. The second problem is that Scala.version is printing out 2.7.5. This is incorrect because the SCALA_HOME path is pointing to a 2.8 release.
Finally, using the --trace flag shows me that Buildr is generating a somewhat correct scalac command and when I run that command manually everything compiles. I say it's somewhat correct only because some cp entries are duplicated. See the following:
scalac -classpath C:/scala-2.8.0.Beta1-RC6/lib/scala-library.jar;C:/scala-2.8.0.Beta1-RC6/lib/scala-compiler.jar;C:/scala-2.8.0.Beta1-RC6/lib/scala-library.jar;C:/scala-2.8.0.Beta1-RC6/lib/scala-compiler.jar -sourcepath C:/Users/Travis/eclipse_ws/HelloWorld/src/main/scala -d C:/Users/Travis/eclipse_ws/HelloWorld/target/classes -verbose -g C:/Users/Travis/eclipse_ws/HelloWorld/src/main/scala/hw/HelloWorld.scala
One more thing I tried (but errored out builder) was setting the following (which I thought wasn't required w/ the presence of SCALA_HOME):
#artifact_ns['Buildr::Compiler::Scalac'].library = '2.8.0'
So any ideas?
Here is a quick list of my system info:
Win 7 64 bit
JDK 6 32 bit set locally for buildr but JDK 6 64 bit system-wide
Ruby 1.8.6 32 bit
Buildr 1.3.5 32 bit
Scala 2.8.0.Beta1-RC6
One more thing I'm thinking of doing is reinstalling my 32 bit JDK and getting it out the the directory with the (x86) in the name. I've found that screws with the Scala bat files although I'm not sure if this is relevant to my current problems.
Thanks in advance!

Figured it out. Silly problem. In Buildr(or maybe more generically in Ruby?), the require method call must come at the top of the file (or at least not inside the define block).
require 'buildr/scala'
So both the NoClassDefFoundError and the incorrect version displayed by puts Scala.version were corrected by this. The following is what my script should have looked like:
require 'buildr/scala'
ENV['JAVA_HOME'] = 'C:\Program Files (x86)\Java\jdk1.6.0_17'
ENV['SCALA_HOME'] = 'C:\scala-2.8.0.Beta1-RC6'
define 'HelloWorld' do
puts Scala.version
end
BTW: Buildr seems to be pretty sweet (fast, concise, convention over config, etc.) once you figure what you are doing :-)

With version 1.4, at the moment you can do
Buildr.settings.build['scala.version'] = "2.8.0"
require 'buildr/scala'
And it will use scala 2.8.

Buildr 1.4 has support for Scala 2.8 and 1.4.2 will use 2.8 by default.

Related

Scala script doesn't run on Ubuntu

I have a previously working Scala script that when I try to run it on a new PC, the compilation fails.
So I made simple script to test:
#!/bin/sh
exec scala -J-Xmx2g "$0" "$#"
!#
println("test")
And trying to run it I get:
test.scala
error: Compile server encountered fatal condition: java.nio.ByteBuffer.clear()Ljava/nio/ByteBuffer;
java.lang.NoSuchMethodError: java.nio.ByteBuffer.clear()Ljava/nio/ByteBuffer;
at scala.tools.nsc.io.SourceReader.read(SourceReader.scala:61)
at scala.tools.nsc.io.SourceReader.read(SourceReader.scala:40)
at scala.tools.nsc.io.SourceReader.read(SourceReader.scala:49)
at scala.tools.nsc.Global.getSourceFile(Global.scala:395)
at scala.tools.nsc.Global.getSourceFile(Global.scala:401)
at scala.tools.nsc.Global$Run$$anonfun$30.apply(Global.scala:1607)
at scala.tools.nsc.Global$Run$$anonfun$30.apply(Global.scala:1607)
at scala.collection.immutable.List.map(List.scala:284)
at scala.tools.nsc.Global$Run.compile(Global.scala:1607)
at scala.tools.nsc.StandardCompileServer.session(CompileServer.scala:151)
at scala.tools.util.SocketServer$$anonfun$doSession$1$$anonfun$apply$1.apply(SocketServer.scala:74)
at scala.tools.util.SocketServer$$anonfun$doSession$1$$anonfun$apply$1.apply(SocketServer.scala:74)
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
at scala.Console$.withOut(Console.scala:65)
at scala.tools.util.SocketServer$$anonfun$doSession$1.apply(SocketServer.scala:74)
at scala.tools.util.SocketServer$$anonfun$doSession$1.apply(SocketServer.scala:69)
at scala.tools.nsc.io.Socket.applyReaderAndWriter(Socket.scala:49)
at scala.tools.util.SocketServer.doSession(SocketServer.scala:69)
at scala.tools.util.SocketServer.loop$1(SocketServer.scala:85)
at scala.tools.util.SocketServer.run(SocketServer.scala:97)
at scala.tools.nsc.CompileServer$$anonfun$execute$2$$anonfun$apply$mcZ$sp$1.apply$mcZ$sp(CompileServer.scala:218)
at scala.tools.nsc.CompileServer$$anonfun$execute$2$$anonfun$apply$mcZ$sp$1.apply(CompileServer.scala:213)
at scala.tools.nsc.CompileServer$$anonfun$execute$2$$anonfun$apply$mcZ$sp$1.apply(CompileServer.scala:213)
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
at scala.Console$.withOut(Console.scala:53)
at scala.tools.nsc.CompileServer$$anonfun$execute$2.apply$mcZ$sp(CompileServer.scala:213)
at scala.tools.nsc.CompileServer$$anonfun$execute$2.apply(CompileServer.scala:213)
at scala.tools.nsc.CompileServer$$anonfun$execute$2.apply(CompileServer.scala:213)
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
at scala.Console$.withErr(Console.scala:80)
at scala.tools.nsc.CompileServer$.execute(CompileServer.scala:212)
at scala.tools.nsc.CompileServer$.main(CompileServer.scala:180)
at scala.tools.nsc.CompileServer.main(CompileServer.scala)
It seems like Scala is compiling something near my script, but I don't quite know how to debug it and fix it.
TL;DR
Ubuntu's Scala package used to be incompatible with Java 8 (this has been fixed in 2.11.12-4). The solution was to uninstall Ubuntu's Scala package and install one of the official Scala packages. You might still want to do that, this time around, not due to incompatibility with Java, but because Ubuntu's latest packaged Scala version is still 2.11, while Scala's latest version is currently 2.13.
sudo apt remove scala-library scala
wget https://downloads.lightbend.com/scala/2.13.4/scala-2.13.4.deb
sudo dpkg -i scala-2.13.4.deb
Since many people were asking for the reason behind this issue and I was also curious about what caused it, I did some digging...
The root of the problem
In Java 9, Buffer subclasses (including ByteBuffer) were changed to override methods that in the superclass return Buffer to return the respective subtype.
Bug: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-4774077
Commit: https://github.com/AdoptOpenJDK/openjdk-jdk9/commit/d9d7e875470bf478110b849315b4fff55b4c35cf
This change is not binary backward compatible. If some Java code which calls one these methods directly in one of Buffer's subclasses is compiled with JDK9+, the generated bytecode will not run in JRE8 (even if the returned value is not used at all). This happens because the signature of the method when called will be compiled as java.nio.ByteBuffer.clear()Ljava/nio/ByteBuffer which doesn't exist in JRE8. However, if compiled with JDK8, the signature compiled into bytecode would be java/nio/ByteBuffer.clear:()Ljava/nio/Buffer which exists in the Buffer calss in both JRE8 and JRE9+.
Where did Scala go wrong? (Or did it?)
Scala compiler does use some of the methods affected by the changes above. Particularly, in the SourceReader class where the error in OP's question happened.
Looking at Scala's compatibility matrix, it says that we need at least Scala 2.11.12 to use JDK11, but it doesn't say much explicitly about the opposite direction of compatibility. It does say though that "Scala 2.12+ definitely doesn't work at all on JDK 6 or 7", so we could expect that 2.12+ is still compatible with JDK8, and even more so Scala 2.11.
Why did they break the compatibility then? Couldn't they just compile Scala's source code with an older JDK version? They didn't and they could, so much, that they still do it.
If we download one of the official Scala packages and check the manifest file for scala-compiler.jar, this is what we find:
Scala 2.11.12:
Bundle-Name: Scala Compiler
Bundle-RequiredExecutionEnvironment: JavaSE-1.6, JavaSE-1.7
Bundle-SymbolicName: org.scala-lang.scala-compiler
Bundle-Version: 2.11.12.v20171031-225310-b8155a5502
Created-By: 1.6.0_45 (Sun Microsystems Inc.)
Scala 2.13.4:
Bundle-Name: Scala Compiler
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-SymbolicName: org.scala-lang.scala-compiler
Bundle-Version: 2.13.4.v20201117-181115-VFINAL-39148e4
Created-By: 1.8.0_275 (AdoptOpenJDK)
So it seems Scala 2.11 is still being compiled with JDK6 and Scala 2.13 is still being compiled with JDK8. Shouldn't that mean that they are both compatible with JRE8? Yes and indeed they are. Where's the error coming from then?
Where did Ubuntu go wrong?
Ubuntu, as most other Linux distributions do, likes to build its own packages that are made available through its package manager. This is done to ensure that everything works properly within the OS ecosystem, and that often means patching the source code of upstream projects.
Regarding the Scala package in particular, Ubuntu decided to ditch the upstream choices of JDK versions used to compile the Scala source code and has been using newer JDK versions to compile Ubuntu's Scala package for a while.
If we check the manifest file for scala-compiler.jar in Ubuntu's Scala 2.11.12-4, we can see that is was compiled with JDK11:
Created-By: 11.0.2+9-Ubuntu-3ubuntu1 (Oracle Corporation)
Bundle-Name: Scala Distribution
Bundle-SymbolicName: org.scala-ide.scala.compiler;singleton:=true
Bundle-Version: 2.11.12
Didn't you say the issue was resolved in 2.11.12-4? Yes, I did.
Ubuntu's solution for this problem was not to compile Scala with JDK8, but rather to patch Scala's source code to avoid calling the problematic methods directly in the subclasses. This was achieved by casting ByteBuffer (and CharBuffer) to its superclass Buffer before calling these methods. In practice, that meant changing Scala's source code from bytes.clear() to bytes.asInstanceOf[Buffer].clear().asInstanceOf[ByteBuffer] (not sure why they cast it back to ByteBuffer when the result from clear() doesn't seem to be used at all). Here is Ubuntu's patch.
Ubuntu's approach seems a bit dangerous, because other sources of incompatibility could have gone unnoticed and still be there waiting to happen in some very specific situation. Also having their own setup different from the official Scala releases means not having the whole Scala community testing these changes in real-case scenarios.
It works for me by disabling fsc with version 2.11.12:
#!/usr/bin/env -S scala -nc

error: ';' expected but double literal found

I am learning Scala and I am using typesafe activator to run the programs. I have my first program in the below path <downloads>\typesafe-activator-1.3.7\activator-dist-1.3.7\simple scala project\scala-2.11\Simple_scala_project.scala
Below is the program content
object Simple_scala_project {
def main (args:String): Unit =
{ println("My first scala program") }
}
when I am running the below command in the command line I am getting the error
scala -cp <downloads>\typesafe-activator-1.3.7\activator-dist-1.3.7\simple scala project\scala-2.11 Simple_scala_project
:1: error: ';' expected but double literal found.
Please help me in this.
I noted a similar error when I inadvertently placed a line including "sbt.version=1.3.13" (in my case) in the wrong file. I realize now that it should have gone into a folder insider my overall project folder called "project", inside a file called "build.properties" (instead of in "build.sbt").
The take-away from this is that I don't think you experienced a compiler error at all, but an error owing to some files in the project setup. Better SBT documentation may be found here.
It's absolutely true that SBT isn't needed for very simple examples, and indeed offends the sensibilities of ones volunteering to learn a new language (soon to be improved, Scala 3.x, not a hundred other extraneous technologies. I find IntelliJ Idea Community to be a boost, here, since its Scala support is first-rate, and will create simple example projects for you in a variety of ways Installing Scala / Installing Scala plugin for Idea.

Compiling Scala^Z3 on Windows

I tried to compile Scala^Z3 on Win XP using Cygwin and JDK 1.7.0 but it didn't work out as expected.
I did the following:
- Use SBT 0.7.4
- Use current Scala^Z3 revision from github
- Use Cygwin and its gcc
- Use JDK 1.7.0 (javac)
"sbt update" was successfull.
"sbt package" end up in several errors stating undefined references like the following:
\psuter-ScalaZ3-35cb691\src\c/z3_Z3Wrapper.c:10: undefined reference to `_Z3_mk_config'
In order to make it work at all I changed ....\PSuterScalaZ3\psuter-ScalaZ3-35cb691\project\build\scalaz3.scala line 74 to:
lazy val gcc : ManagedTask = if(isUnix || is32bit) {
On the homepage it is stated that it should work for Windows, too. Does it at all?
Is there a precompiled jar available?
I saw a z3.jar here: http://lara.epfl.ch/~psuter/jniz3/z3.jar
This is a Linux Version too, I guess? Because it didn't work for me either...
Scala^Z3 is a really good piece of code (if i can get it to work ;))
Sorry about that, the sbt script indeed currently only works for Linux (and as you can tell by the absolute path, we're not quite used to having external users yet).
Here are the steps I use to compile it under Windows:
compile all Java sources with javac (there are no dependencies)
generate the header files using javah
compile all the Scala sources with scalac (using only the Java .class files as dependencies)
compile the .c + .h files with Visual Studio
manually create a jar file with everything
We also hope to release a precompiled .jar file with the shared library for Linux and Windows once we adapted Scala^Z3 to the new changes in Z3 3.1.
EDIT The GitHub repository now contains a precompiled .jar file prepared for Scala 2.9.1 and Z3 3.2. It works under Windows and Linux (32bit). The repository also contains more detailed instructions on how to compile the shared library in Windows, using MinGW instead of Visual Studio (hence removing the need for VS runtime libraries).
I had a similar problem some months back and here is what it I had to do in order to compile it with Visual Studio 2010. I am not sure if it is still relevant since Scala^Z3 and Z3 itself changed a lot, but I hope it nevertheless is helpful.
Created a new Visual C++ Win32 project (.NET Framework 4) for
creating DLLs.
Added all .h and .c files in the src/c/ directory. VC somehow
complained about the "inline" modifier and a work mate suggested to
remove them, which I did.
Added z3.h from Z3 2.19, Z3 2.16 wasn't accepted. Also added the
corresponding z3.lib (x86, haven't tried x64 yet). VC wouldn't accept
z3.dll and complaint about the file being corrupt. No clue why, Z3
itself works fine for me.
The project compiles with 13 warnings and a dll is created which
apparently MUST be named scalaz3.dll.
sbt compile, adding scalaz3.dll to lib-bin, jar the whole thing
together to scalaz3.jar
'scala -classpath scalaz3.jar test.scala' with scalaz3.jar and z3.dll
in the current folder works

Scala : trying to get log4j working

Scala newb here (it's my 2nd day of using it). I want to get log4j logging working in my Scala script. The script and the results are below, any ideas as to what's going wrong?
[sean#ibmp2 pybackup]$ cat backup.scala
import org.apache.log4j._
val log = LogFactory.getLog()
log.info("started backup")
[sean#ibmp2 pybackup]$ scala -cp log4j-1.2.16.jar:. backup.scala
/home/sean/projects/personal/pybackup/backup.scala:1: error: value apache is not a member of package org
import org.apache.log4j._
^
one error found
I reproduce it under Windows: delimiter of '-classpath' must be ';' there (not ':'). Are you use cygwin or some sort of unix emulator?
But Scala script works anywhere without current dir in classpath. Try to use:
$ scala -cp log4j-1.2.16.jar backup.scala
JFI: LogFactory is a class of slf4j library (not log4j).
UPDATE
Another possible case: broken jar in classpath, maybe during download or something else. Scala interpreter does report only about unavailable member of the package.
$ echo "qwerty" > example.jar
$ scala -cp example.jar backup.scala
backup.scala:1: error: value apache is not a member of package org
...
Need to inspect content of the jar-file:
$ jar -tf log4j-1.2.16.jar
...
org/apache/log4j/Appender.class
...
Did you remember to put log4j.jar in your classpath?
Had Similar issue when started doing Scala Development using Eclipse, doing a clean build solved the problem.
Guess the Scala tools are not matured et.
Instead of using log4j directly, you might try using Configgy. It's the Scala Way™ to work with log4j, as well as configuration files. It also plays nicely with SBT and Maven.
I asked and answered this question myself, have a look:
Put it under src/main/resources/logback.xml. It will be copied to the right location when SBT is doing the artifact assembly.

scala compilation problem - with java libs

Im trying to put together a simple ant build file for compiling a scala project (scala 2.7.6)...
I have everything working correctly except that its bringing up the
"fatal error: class java.lang.Object not found." both the scalac and scala libs are all in the project folder, so Im refering to them relativelly to the project root.
Im hoping that someone could help with which command line scalac option I can use to point the compiler towards the java core lib (if thats what it needs). Im hoping not to use any environemnt variables, and instead have the needed java libs in my project root folder...
that way I can have everything needed to compile movable with the project, and not need any setup for others to be able to compile
thank you
Scala 2.7.6 is a broken release.
Please upgrade to 2.7.7
Also, do you have javac on PATH and JAVA_HOME set?