C# Installation

Um zur aktuellsten C# Mono Version zu kommen muss diese manuell installiert werden. Diese Anleitung zeigt wie und hilft einen Stolperstein für die Raspberry Pi Zero zu vermeiden.

Beschreibung

Wer C# auf dem Raspberry Pi Zero programmieren bzw. verwenden möchte ist auf das Mono Projekt angewiesen. Es unterstützt sowohl den alten ARM11-Prozessor mit ARMv6 Architektur als auch die neuen ARMv7 kompatiblen Prozessoren. Ein einfacher Aufruf von “sudo apt-get install mono-complete” reicht eigentlich zur Installation aus. Dann erhält man aber eine etwas ältere Version.

mono -V
Mono JIT compiler version 5.18.0.240 (Debian 5.18.0.240+dfsg-3 Sat Apr 20 05:16:08 UTC 2019)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           
	SIGSEGV:       normal
	Notifications: epoll
	Architecture:  armel,vfp+hard
	Disabled:      none
	Misc:          softdebug 
	Interpreter:   yes
	LLVM:          supported, not enabled.
	Suspend:       preemptive
	GC:            sgen (concurrent by default)

Möchte man die neuste Version installieren muss man manuell einige Schritte durchführen.

Installation

sudo apt-get install apt-transport-https dirmngr gnupg ca-certificates
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb https://download.mono-project.com/repo/debian stable-raspbianbuster main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
sudo apt-get update
sudo apt-get install mono-complete
mono -V
Mono JIT compiler version 6.4.0.198 (tarball Tue Sep 24 01:45:47 UTC 2019)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       normal
	Notifications: epoll
	Architecture:  armel,vfp+hard
	Disabled:      none
	Misc:          softdebug 
	Interpreter:   yes
	LLVM:          yes(610)
	Suspend:       preemptive
	GC:            sgen (concurrent by default)

Raspberry Pi Zero

Problembeschreibung

Untypisch bei der Installation des mono-complete Paketes ist, dass Bibliotheken am Zielsystem kompiliert werden. Auf den ersten Blick kann man das ja als verständlich erachten, bei näherer Betrachtung ergeben sich aber Probleme.
Ja nach System auf dem installiert wird, werden binär unterschiedliche Bibliotheken erzeugt. Wird nun mono auf einer neueren Raspberry Pi (ab Version 2) erzeugt, so kann diese SD-Karte nicht mehr in einer Raspberry Pi Zero eingesetzt werden. Offensichtlich sind die erzeugen Bibliotheken nicht kompatibel mit der alten ARMv6 Architektur. Sobald das Programm “mono” bzw. “/usr/bin/mono-sgen” ausgeführt wird, kommt es zum Absturz.
Durch den Aufruf von “dpkg-reconfigure” können die Bibliotheken am Zielsystem neu erzeugt werden. Dazu muss man aber jedes der problematischen Pakete kennen. Mir ist es bisher nicht gelungen auf diese Art mono korrekt neu zu erzeugen! Die folgende unvollständige Liste der Pakte habe ich bisher ermittelt:

sudo dpkg-reconfigure libmono-corlib4.5-cil 
Mono precompiling /usr/lib/mono/4.5/mscorlib.dll for arm (LLVM disabled due to missing SSE4.1)...
sudo dpkg-reconfigure mono-mcs
Mono precompiling /usr/lib/mono/4.5/mcs.exe for arm (LLVM disabled due to missing SSE4.1)...
sudo dpkg-reconfigure mono-roslyn
Mono precompiling /usr/lib/mono/4.5/csc.exe for arm (LLVM disabled due to missing SSE4.1)...
Mono precompiling /usr/lib/mono/4.5/vbc.exe for arm (LLVM disabled due to missing SSE4.1)...
Mono precompiling /usr/lib/mono/4.5/VBCSCompiler.exe for arm (LLVM disabled due to missing SSE4.1)...
Mono precompiling /usr/lib/mono/4.5/Microsoft.CodeAnalysis.CSharp.dll for arm (LLVM disabled due to missing SSE4.1)...
Mono precompiling /usr/lib/mono/4.5/Microsoft.CodeAnalysis.VisualBasic.dll for arm (LLVM disabled due to missing SSE4.1)...
Mono precompiling /usr/lib/mono/4.5/Microsoft.CodeAnalysis.dll for arm (LLVM disabled due to missing SSE4.1)...
Mono precompiling /usr/lib/mono/4.5/System.Collections.Immutable.dll for arm (LLVM disabled due to missing SSE4.1)...
Mono precompiling /usr/lib/mono/4.5/System.Reflection.Metadata.dll for arm (LLVM disabled due to missing SSE4.1)...

Die besagten problematischen Bibliotheken befinden sich alle im Verzeichnis “/usr/lib/mono/aot-cache/arm”. Mit dem Tool “md5sum” kann man einen Hash der binären Dateien errechnen und erkennt dann, dass auf unterschiedlichen Systemen andere Bibliotheken erzeugt wurden.

Raspberry Pi 3+:

5a171770d300363e3ec2eb60a854c481  csc.exe.so
df8506376fdf137d863e3bba99716b07  mcs.exe.so
4015357bc969c8a9be7193d59555debc  Microsoft.CodeAnalysis.CSharp.dll.so
4c55c6475790d96c7a245df5afa22358  Microsoft.CodeAnalysis.dll.so
c3c739f4753d6fa2770be8704f6f61a6  Microsoft.CodeAnalysis.VisualBasic.dll.so
405641746541bb05ea82ac45f20f5696  mscorlib.dll.so
8a32754f92db9671bd3beacc0bc3689d  System.Collections.Immutable.dll.so
1a4ec59a04636afaa39112fef86e7229  System.Reflection.Metadata.dll.so
32fcdc11684481eb72f638b3dce0cf8e  vbc.exe.so
ce4d8efa2c3ddac3b42b8e8ffa6407f6  VBCSCompiler.exe.so

Raspberry Pi Zero:

85ad88c49857e8ca89ba4ae00e8c1fd3  csc.exe.so
3bef36c9fe11d7e99367cf9b23c32853  mcs.exe.so
322fdde542e899c12479c71f3d7b1dec  Microsoft.CodeAnalysis.CSharp.dll.so
28666816903d4a5d16312cf21320833e  Microsoft.CodeAnalysis.dll.so
d146515c05c29292c401789f0bb4fdf2  Microsoft.CodeAnalysis.VisualBasic.dll.so
b0f1c0f302c96d49ec699152445fa96d  mscorlib.dll.so
33bb1dcc310d5db62bcf4f06df475976  System.Collections.Immutable.dll.so
be3df82bb795a9224f916113f5bbeeab  System.Reflection.Metadata.dll.so
5dc11adaa95f1e942f1fb98ca4673b1f  vbc.exe.so
bd646f0b1c23b90cf0ea90f15231e439  VBCSCompiler.exe.so

Der genaue Grund warum die Bibliotheken am Raspberry Pi Zero nicht funktionieren ist mir nicht bekannt. Die Dateien werden möglicherweise mit dem Assembler “as” erzeugt. Hier wird der Optimierungsparameter “-mfpu=vfp3” verwendet. Als Beschreibung findet man “Enable the ARMv7 VFPv3 floating-point extension. Disable the Advanced SIMD extension”. Dieser Optimierung sollte eigentlich auf dem ARM11 nicht funktionieren, ob dies aber zum Absturz führt, ist nicht bekannt.
Aktualisierung 1.11.2020: Auch bei Update/Installation auf einem Raspberry Pi 1 wird beim Kompilieren der Parameter “-mfpu=vfp3” angewendet.

Lösung (GC2 Raspjamming)

Das Problem trifft vor allem bei unserem Raspjamming Image auf, wenn das Image auf einem ARMv7 System erzeugt wird. Auf einem x86_64-System bei dem eine Emulation (qemu) Verwendung findet, tritt das Problem nicht auf.
Als Lösung wird von uns nach der Installation von mono, die Library-Dateien überschrieben. Sie wurden einmalig von einem Raspberry Pi Zero System gesichert. Diese sind dann auch für neue Raspberry Pi Einplatinencomputer geeignet.

Martin Strohmayer Geschrieben von:

Softwareentwickler und Raspberry Pi Enthusiast.