Install Scala on Raspberry Pi
This article shows how to install and use Scala programming language on Raspberry Pi.
Traditionally, the programming language of choice for Raspberry Pi was Python, while JVM-based languages were set aside. That was reasonable, because JVM platform is rather resource-intensive, especially in interpreted mode, and the first version of Raspberry Pi was hardly apt for such a task.
However, things have changed: on the one hand, Raspberry Pi 2 now offers a 900MHz quad-core CPU and 1GB of RAM, on the other hand, Oracle released JDK 8 for ARM (with HardFP, JIT and server VM), which provides >10X performance boost (comparing to Zero VM from OpenJDK), so Scala runs nicely even on Raspberry Pi 1 (and, RPi 2 can run IntelliJ IDEA, if you wish).
Contents:
Some of the commands will require root privileges, so either login as root user or use sudo to start an interactive shell via sudo -i
.
Installing Java
Because Scala compiles to Java bytecode, we need to install Java virtual machine (JVM) first.
Some Linux distributives come with JVM pre-installed, however that JVM is usually provided by OpenJDK package. While I really appreciate that open-source implementation of the Java Platform, it currently offers no just-in-time compiler on ARM systems (like Raspberry Pi), so it’s too slow for our purpose.
Linux distributives often provide dedicated utilities (e. g. in Debian, in Arch Linux, etc.) to switch Java implementations, yet we’ll not rely on them and will use plain and simple approach (which is also distributive agnostic).
We can determine installed Java version by running:
java -version
If the output is “command not found” than there’s no Java installed (preferable). If the output contains “Zero VM” or “interpreted mode”, it’s better to use package manager to remove all existing Java packages (*jdk, *jre) from the system before proceeding.
First, we need to obtain JDK 8 for ARM from Oracle’s site. Open the page in a browser, accept the license and download the distributive.
Then upload the file to your Raspberry Pi via SSH (use appropriate version / host / user parts):
scp jdk-8u33-linux-arm-vfp-hflt.tar.gz user@address:/home/user
On Windows, it’s possible to use pscp
from Putty for that purpose. Alternatively, you may simply copy the file to the boot partition on the SD card (which uses Windows-friendly, FAT file system) and then access the file via /boot/...
path.
Create a directory to hold the JVM:
mkdir /usr/lib/jvm
Unpack the distributive:
tar -xf jdk-8u33-linux-arm-vfp-hflt.tar.gz -C /usr/lib/jvm
Rename the resulting directory:
mv /usr/lib/jvm/jdk1.8.0_33 /usr/lib/jvm/java-8-oracle
Delete the original archive file:
rm jdk-8u33-linux-arm-vfp-hflt.tar.gz
Create symbolic links to binaries:
ln -s /usr/lib/jvm/java-8-oracle/bin/java /bin/java
ln -s /usr/lib/jvm/java-8-oracle/bin/javac /bin/javac
Run java -version
again, the output should be like:
java version "1.8.0_33"
Java(TM) SE Runtime Environment (build 1.8.0_33-b05)
Java HotSpot(TM) Client VM (build 25.33-b05, mixed mode)
This confirms that the required version of Java is correctly installed.
Installing Scala
It’s possible to download Scala distributive directly to Raspberry Pi (consider using the latest version):
wget https://downloads.typesafe.com/scala/2.11.6/scala-2.11.6.tgz
After downloading, unpack and then delete the resulting file:
mkdir /usr/lib/scala
tar -xf scala-2.11.6.tgz -C /usr/lib/scala
rm scala-2.11.6.tgz
Create symbolic links:
ln -s /usr/lib/scala/scala-2.11.6/bin/scala /bin/scala
ln -s /usr/lib/scala/scala-2.11.6/bin/scalac /bin/scalac
Run scala -version
to verify the installation. The output should be:
Scala code runner version 2.11.6 -- Copyright 2002-2013, LAMP/EPFL
If output is OK, than everything is ready to compile and run Scala code.
Using Scala
There are multiple ways of how we can run Scala code. Let’s enumerate most common ones.
Interpreter
Scala offers an interactive interpreter (often called a REPL for Read-Evaluate-Print Loop), which can be started by simply typing scala
at the command line:
Welcome to Scala version 2.11.6.
Type in expressions to have them evaluated.
Type :help for more information.
Here’s how we can interactively define an infinite stream of Fibonacci numbers and then compute first 10 of them:
scala> val fs: Stream[Int] = 0 #:: fs.scanLeft(1)(_ + _)
fs: Stream[Int] = Stream(0, ?)
scala> fs.take(10).mkString(", ")
res0: String = 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
Type :q
to exit the interpreter.
If you want to see more cool one-liners that can easily fit into the REPL, you may check Scala for Project Euler article.
Scala scripts
Scala allows to omit all the boilerplate code (like enclosing classes or “main” methods) in scripts and to run those files directly, without explicit compilation.
Create a new Scala file:
nano ls.scala
Enter the following code and then save the file:
new java.io.File(".").listFiles.foreach(println)
Run the resulting script via:
scala ls.scala
Shell scripts
It’s possible to use Scala from shell scripts. All we need to do is to specify scala
as a desired interpreter in a script header. Arguments are accessible via args
value.
Create cat.sh
file with the following content:
#!/bin/sh
exec scala "$0" "$@"
!#
print(io.Source.fromFile(args(0)).mkString)
Mark the file as executable:
chmod +x cat.sh
Then run this file just like any other shell script:
./cat.sh /etc/fstab
Compiler
While, scripts can be handy, Scala can be explicitly compiled to Java bytecode to avoid subsequent re-compilations and improve startup performance.
Scala works like Java in this respect, just use scalac
instead of javac
for compilation, and scala
instead of java
to run the resulting bytecode. Many of the command line options are also rather similar.
Let’s compile the snippet from the REPL example to bytecode.
Create Main.scala
file with the flowing lines:
object Main extends App {
lazy val fs: Stream[Int] = 0 #:: fs.scanLeft(1)(_ + _)
println(fs.take(10).mkString(", "))
}
Invoke Scala compiler:
scalac Main.scala
Run the resulting Main.class
file:
scala Main
Notice, that this time the result appears much faster, because code is pre-compiled beforehand. We use scala
to run the class just for simplicity (to add standard Scala library to class path). In principle, the produced class file can be run via java
command as well.
Just like javac
, Scala compiler will compile all the specified files each time you run it, which may be not desirable for large code bases. That is where incremental compilation via SBT comes in handy.
Installing SBT
SBT is a build tool that (besides defining a project model) handles incremental compilation of Scala and Java files, and can be used as a compile server for continuous compilation.
Download sbt-launch.jar
file:
wget https://repo.typesafe.com/typesafe/ivy-releases\
/org.scala-sbt/sbt-launch/0.13.8/sbt-launch.jar
Place it withing the system:
mkdir /usr/lib/sbt
mv sbt-launch.jar /usr/lib/sbt
Create a shell script to run the SBT launcher:
nano /bin/sbt
Add the following lines and save the file:
#!/bin/sh
java -server -Xmx512M -jar /usr/lib/sbt/sbt-launch.jar "$@"
We’re using -server
switch here, which can slower JVM startup, yet can significantly improve performance once JVM is “warmed up”. Note that server VM requires arm7 architecture, so this switch can be applied only on Raspberry Pi 2.
Mark the script as executable:
chmod +x /bin/sbt
Verify installation by querying SBT version:
sbt --version
The output should looks like:
sbt launcher version 0.13.8
SBT relies on file modification timestamps for incremental compilation, yet Raspberry Pi boards have no real time clock (so they reset OS time on boot). Most Linux distributives rely on NTP to synchronize clock over the Internet. Make sure that the synchronization works properly by issuing date
command.
Using SBT
Run SBT interactive shell (it will take some time to download required dependencies):
sbt
Then you can invoke compile
command from the SBT command line. Type exit
to exit the tool.
You can also start compilation directly from command line:
sbt compile
SBT employs comprehensive analysis to recompile only those files which really should to be recompiled. That can significantly speed up subsequent compilations of large projects.
To speed up compilation even further, it’s possible to avoid multiple JVM and SBT startups by keeping a running SBT process for automatic, continuous compilation.
Here’s how we can run SBT compilation loop in the background:
sbt "~ compile" &
In this way SBT will monitor file changes and automatically recompile files almost instantaneously.
Use standard management command like fg
, bg
, jobs
, etc. to interact with the launched process. Alternatively, you may run the compilation loop within GNU screen, or simply from another shell session.
While Scala runs fine on Raspberry Pi out-the-box, I recommend you to check related Raspberry Pi tweaks which can help to improve performance even further.
See also: Install IntelliJ IDEA on Raspberry Pi, Scala for Project Euler
* Raspberry Pi is a trademark of the Raspberry Pi Foundation
Thank you Pavel, that works like a charm!
Check out http://www.lediouris.net/RaspberryPI to believe it… 😉
Cheers,
– Olivier
You can install the jdk now with
sudo apt-get install oracle-java8-jdk
(and I think it is later distros by default, because my new build had it already)
Where did you find the instructions on installing sbt? I was searching desperately until I found this site.