Saturday, October 2, 2010

Notes from getting Scala running on .NET

I just spend an evening getting Scala to run on .NET 4.0. Here my notes:

Scala 2.8.0

I started downloading Scala 2.8.0-final as a zip file (), and unpacking it to my scala playground directory. That gave me:
PS C:\Scala-playground\scala-2.8.0.final> tree
Folder PATH listing for volume OSDisk
Volume serial number is 00690066 6A5B:A532
C:.
+---bin
+---doc
¦   +---sbaz
¦   +---sbaz-setup
+---lib
+---meta
¦   +---cache
+---misc
¦   +---sbaz
¦   ¦   +---config
¦   ¦   +---descriptors
¦   +---sbaz-testall
¦   ¦   +---tests
¦   +---scala-devel
¦   ¦   +---plugins
¦   +---scala-tool-support
¦       +---a2ps
¦       +---bash-completion
¦       +---bluefish
¦       +---context
¦       ¦   +---Highlighters
¦       ¦   +---Template
¦       +---emacs
¦       ¦   +---contrib
¦       +---enscript
¦       +---geshi
¦       +---intellij
¦       +---jedit
¦       ¦   +---console
¦       ¦   ¦   +---commando
¦       ¦   +---modes
¦       +---latex
¦       +---notepad-plus
¦       +---scite
¦       +---subethaedit
¦       ¦   +---artwork
¦       ¦   +---Scala.mode
¦       ¦       +---Contents
¦       ¦           +---Resources
¦       ¦               +---English.lproj
¦       ¦               +---Scripts
¦       +---textmate
¦       ¦   +---Bundles
¦       +---textpad
¦       +---textwrangler
¦       +---ultraedit
¦       +---vim
¦           +---ftdetect
¦           +---indent
¦           +---plugin
¦           +---syntax
+---src

I then went on to install the Scala msil extension (i.e. the scala .NET compiler and runtime) as follows:
PS C:\Scala-playground\scala-2.8.0.final> bin/sbaz.bat install scala-msil

Then, following the "official" instructions on running scala on .NET (http://www.scala-lang.org/node/168), I copied mscorlib.dll to the scala lib folder:
PS C:\Scala-playground\scala-2.8.0.final> copy C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll .\lib

I was now ready to try to compile something. E.g. this very simple hello world program using a little bit of .NET, namely Console.WriteLine:

import System.Console object test extends Application {   Console.WriteLine("Hello world!") }

I tried to compile it like this:
PS C:\Scala-playground\hello.net> ..\scala-2.8.0.final\bin\scalac.bat -target:msil .\test.scala

but got this error:
scala.tools.nsc.MissingRequirementError: class scala.runtime.VolatileBooleanRef not found.
        at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:513)
        at scala.tools.nsc.symtab.Definitions$definitions$.getClass(Definitions.scala:471)
        at scala.tools.nsc.symtab.Definitions$definitions$.newValueClass(Definitions.scala:620)
        at scala.tools.nsc.symtab.Definitions$definitions$.BooleanClass(Definitions.scala:92)
        at scala.tools.nsc.symtab.Definitions$definitions$.initValueClasses(Definitions.scala:643)
        at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:787)
        at scala.tools.nsc.Global$Run.(Global.scala:597)
        at scala.tools.nsc.Main$.process(Main.scala:107)
        at scala.tools.nsc.Main$.main(Main.scala:122)
        at scala.tools.nsc.Main.main(Main.scala)
error: fatal error: class scala.runtime.VolatileBooleanRef not found.

I tried like this to point out where mscorlib and the scala runtime dlls are:
PS C:\Scala-playground\hello.net> ..\scala-2.8.0.final\bin\scalac.bat -target:msil -Xassem-extdirs ..\scala-2.8.0.final\lib .\test.scala
scala.tools.nsc.MissingRequirementError: class scala.runtime.VolatileBooleanRef not found.
        at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:513)
        at scala.tools.nsc.symtab.Definitions$definitions$.getClass(Definitions.scala:471)
        at scala.tools.nsc.symtab.Definitions$definitions$.newValueClass(Definitions.scala:620)
        at scala.tools.nsc.symtab.Definitions$definitions$.BooleanClass(Definitions.scala:92)
        at scala.tools.nsc.symtab.Definitions$definitions$.initValueClasses(Definitions.scala:643)
        at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:787)
        at scala.tools.nsc.Global$Run.(Global.scala:597)
        at scala.tools.nsc.Main$.process(Main.scala:107)
        at scala.tools.nsc.Main$.main(Main.scala:122)
        at scala.tools.nsc.Main.main(Main.scala)
error: fatal error: class scala.runtime.VolatileBooleanRef not found.
..same error.

Then I resorted to frantic googling, but ended up deciding to downgrade the mscorlib.dll to 2.0, and to 1.1. But in both cases I got same depressing result.
Finally I decided to downgrade to scala 2.7.7.

Scala 2.7.7

I downloaded scala 2.7.7 unzipped it and got:
PS C:\Scala-playground\scala-2.7.7.final> tree
Folder PATH listing for volume OSDisk
Volume serial number is 00690066 6A5B:A532
C:.
+---bin
+---doc
¦   +---sbaz
¦   +---sbaz-setup
+---lib
+---meta
¦   +---cache
+---misc
¦   +---sbaz
¦   ¦   +---descriptors
¦   +---sbaz-testall
¦   ¦   +---tests
¦   +---scala-tool-support
¦       +---a2ps
¦       +---bluefish
¦       +---context
¦       ¦   +---Highlighters
¦       ¦   +---Template
¦       +---emacs
¦       ¦   +---contrib
¦       +---enscript
¦       +---geshi
¦       +---intellij
¦       +---jedit
¦       ¦   +---console
¦       ¦   ¦   +---commando
¦       ¦   +---modes
¦       +---latex
¦       +---notepad-plus
¦       +---scite
¦       +---subethaedit
¦       ¦   +---artwork
¦       ¦   +---Scala.mode
¦       ¦       +---Contents
¦       ¦           +---Resources
¦       ¦               +---English.lproj
¦       ¦               +---Scripts
¦       +---textmate
¦       ¦   +---Bundles
¦       +---textpad
¦       +---textwrangler
¦       +---ultraedit
¦       +---vim
¦           +---ftdetect
¦           +---indent
¦           +---plugin
¦           +---syntax
+---src
The I went through copying mscorlib and installing scala-msil again:
PS C:\Scala-playground\scala-2.7.7.final> copy C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll .\lib
PS C:\Scala-playground\scala-2.7.7.final> .\bin\sbaz.bat install scala-msil
planning to install: scala-msil/2.7.7.final
Installing...

Then I tried compilling again:
PS C:\Scala-playground\hello.net> ..\scala-2.7.7.final\bin\scalac-net.bat .\test.scala
PS C:\Scala-playground\hello.net> ls


    Directory: C:\Scala-playground\hello.net


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        30-09-2010     21:59            target
-a---        30-09-2010     22:33       3863 test.msil
-a---        30-09-2010     21:52        100 test.scala

which went well. The scala compiler made a .msil file. Yeah.

Next step was turning that .msil into an .exe:
PS C:\Scala-playground\hello.net> C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe .\test.msil

Microsoft (R) .NET Framework IL Assembler.  Version 4.0.30319.1
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling '.\test.msil'  to EXE --> '.\test.exe'
Source file is ANSI

Assembled method test::$tag
Assembled method test::main
Assembled method test$::.ctor
Assembled method test$::.cctor
Assembled method test$::$tag
Assembled method test$::main
Assembled global method Main
Creating PE file

Emitting classes:
Class 1:        test
Class 2:        test$

Emitting fields and methods:
Global  Methods: 1;
Class 1 Methods: 2;
Class 2 Fields: 1;      Methods: 4;
Resolving local member refs: 8 -> 8 defs, 0 refs, 0 unresolved

Emitting events and properties:
Global
Class 1
Class 2
Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Operation completed successfully

Which gave:
PS C:\Scala-playground\hello.net> ls


    Directory: C:\Scala-playground\hello.net


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        30-09-2010     21:59            target
-a---        30-09-2010     22:35       2560 test.exe
-a---        30-09-2010     22:33       3863 test.msil
-a---        30-09-2010     21:52        100 test.scala

So I tried running the program:
PS C:\Scala-playground\hello.net> .\test.exe

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'predef, Version=0.0.0.0, Culture=
neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
   at Main(String[] args)

but missed the predef assembly which is part of the scala-msil extension. To get passed that I simply copied all dlls from the Scala lib folder and ran again:
PS C:\Scala-playground\hello.net> mv .\test.exe .\target
PS C:\Scala-playground\hello.net> cp ..\scala-2.7.7.final\lib/*.dll .\target
PS C:\Scala-playground\hello.net> cd .\target
PS C:\Scala-playground\hello.net\target> ls

    Directory: C:\Scala-playground\hello.net\target


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        30-09-2010     22:30    2070528 mscorlib.dll
-a---        30-09-2010     22:30    1180160 predef.dll
-a---        30-09-2010     22:30       5632 scalaruntime.dll
-a---        30-09-2010     22:35       2560 test.exe
PS C:\Scala-playground\hello.net\target> .\test.exe
Hello world!

Success! but only on the next to newest Scala version. Either way I had fun :-)