Monday, November 25, 2013

Mono 3.2.3 on Synology DS210

This is my guide to building Mono on the Synology DS box with the ARM chipset. If you just want the binaries, they are here: Mono 3.2.3 binaries for Synology DS210.

To use it run (installs in /opt/mono3.2.3):

wget "https://dl.dropboxusercontent.com/u/15251537/mono-3.2.3-bin.tar.bz2"
tar -C / xf mono-3.2.3-bin.tar.bz2

Then sprinkle a few symlinks:
ln -s /opt/mono-3.2.3/bin/mono /opt/bin/mono
ln -s /opt/mono-3.2.3/bin/mcs /opt/bin/mcs
ln -s /opt/mono-3.2.3/bin/gmcs /opt/bin/gmcs

If you want to compile Mono 3.2.3 yourself, the guide follows here. 


First step is to grab and extract the Mono source:
wget "http://download.mono-project.com/sources/mono/mono-3.2.3.tar.bz2"
tar xf mono-3.2.3.tar.bz2
cd mono-3.2.3

Then simply run the configure script:
./configure --prefix=/opt/mono-3.2.3

And you should be able to compile, but if you try, you get errors like:
undefined reference to `__sync_add_and_fetch_4'
undefined reference to `__sync_val_compare_and_swap_8'

This is because Mono uses a newer GCC and the methods are not in the old GCC found on Synology, and the cross compile tools version is also too old. Fortunately there is a trick which I adopted from here. I use a newer version of GCC, and the relevant file has moved, so these are the steps:
wget "http://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2"
tar xf gcc-4.8.2.tar.bz2 gcc-4.8.2/libgcc/config/arm/
cd gcc-4.8.2/libgcc/config/arm/
sed -i -e 's/define HIDDEN.*/define HIDDEN/' linux-atomic.c
gcc -g -O2 -MT linux-atomic.lo -MD -MP -MF linux-atomic.Tpo -c linux-atomic.c  -fPIC -DPIC -o linux-atomic.o
cd ../../../../
mv gcc-4.8.2/libgcc/config/arm/*.o .

Now you have the missing methods in the object files so they can be linked into the binaries, except the __sync_val_compare_and_swap_8 method. This method can be obtained from the linux-atomic-64bit.c file in libgcc as well. But it depends on the kernel function call "__kernel_cmpxchg64", which is not included in the kernel running on Synology. Fortunately there is a fallback method, which we can activate by editing mono/utils/atomic.h. Somewhere around the top, just insert this line:
#define BROKEN_64BIT_ATOMICS_INTRINSIC 1

This will make the compilation fall back to a mutex based method instead of using the missing kernel method. To make sure we can compile the libraries that need the atomic methods, export these:
export pedump_LDFLAGS=`pwd`/linux-atomic.o
export mono_boehm_LDFLAGS=`pwd`/linux-atomic.o
export mono_sgen_LDFLAGS=`pwd`/linux-atomic.o
export monodis_LDFLAGS=`pwd`/linux-atomic.o
export monograph_LDFLAGS=`pwd`/linux-atomic.o

The mono_sgen and mono_boehm LDFLAGS are overwritten in the Makefile, so:
nano mono/mini/Makefile

Look for mono_boehm_LDFLAGS and mono_sgen_LDFLAGS and change the "LDFLAGS=" to "LDFLAGS+=".

 And finally the __clear_cache call is also missing, so edit mono/mini/mini-arm.c, line 1032, and comment out the call, so we use the fallback instead:

#ifdef MONO_CROSS_COMPILE
#elif __APPLE__
        sys_icache_invalidate (code, size);
//#elif __GNUC_PREREQ(4, 1)
//      __clear_cache (code, code + size);
#elif defined(PLATFORM_ANDROID)
        const int syscall = 0xf0002;
        __asm __volatile (
                "mov     r0, %0\n"
                "mov     r1, %1\n"
                "mov     r7, %2\n"
                "mov     r2, #0x0\n"
                "svc     0x00000000\n"
                :
                :       "r" (code), "r" (code + size), "r" (syscall)
                :       "r0", "r1", "r7", "r2"
                );
#else
        __asm __volatile ("mov r0, %0\n"
                        "mov r1, %1\n"
                        "mov r2, %2\n"
                        "swi 0x9f0002       @ sys_cacheflush"
                        : /* no outputs */
                        : "r" (code), "r" (code + size), "r" (0)
                        : "r0", "r1", "r3" );
#endif

This should get you almost through, but there seems to be an install file missing, or perhaps just using the wrong path:
ln -s install-sh docs/install-sh

And now run "make" and wait.... If it fails with something about pthreads, you may need this hack:
mkdir /opt/arm-none-linux-gnueabi/lib_disabled
mv /opt/arm-none-linux-gnueabi/lib/libpthread* /opt/arm-none-linux-gnueabi/lib_disabled
cp /lib/libpthread.so.0 /opt/arm-none-linux-gnueabi/lib/
ln -s /opt/arm-none-linux-gnueabi/lib/libpthread.so.0 /opt/arm-none-linux-gnueabi/lib/libpthread.so
ln -s /opt/arm-none-linux-gnueabi/lib/libpthread.so.0 /opt/arm-none-linux-gnueabi/lib/libpthread-2.5.so

Then build again. And that should now build all the way, so you can install: make install If this gives you an error about the EntityFramework.dll no being signed: "Failure adding assembly ./../../class/lib/net_4_5/EntityFramework.dll to the cache: Strong name cannot be verified for delay-signed assembly"

Then you need to manually sign the assembly:
mono/mini/mono mcs/class/lib/build/sn.exe -R mcs/class/lib/net_4_5/EntityFramework.dll mcs/class/mono.snk

Run "make install" again, and finally test:

> /opt/mono-3.2.3/bin/mono --version
Mono JIT compiler version 3.2.3 (tarball Thr Nov 21 10:05:16 CET 2013)
Copyright (C) 2002-2012 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       normal
        Notifications: epoll
        Architecture:  armel,vfp+fallback
        Disabled:      none
        Misc:          softdebug
        LLVM:          supported, not enabled.
        GC:            sgen

Happy building :)

20 comments:

Anonymous said...

Hi,

thanks for sharing your knowledge!

I'm currently trying to run a MVC4 application on my DS213j, therefore I need mono.

I just tried to run a simple console application with your binaries but it crashed with a SIGSEGV. I guess the binaries are not compatible with the processor my synology has.

Now I will try to compile mono myself with your guide :)

Anonymous said...

Hello me again!

I managed to run the console application with your binaries!

By default mono 3 uses sgen.

I called my application with ./mono --gc=boehm and suddenly it worked! Did you have a similar problem?

I also tried to compile mono my self on my synology but it said I need a newer version of automake when running autogen.sh (I had no configure.sh in my mono directory)

Is there anyway I can contact you?

Thanks in advance :)

Kenneth said...

Ok, I can run with sgen fine on my DS210+

You can email me at opensource@hexad.dk.

CHOCOBOBOY said...

Hi, thanks for you binary, it can run on my iomega NAS. and could you give me some help on build xsp, i got these error when running the autogen.sh.

./autogen.sh --prefix=/opt/mono-3.2.3
root@NAS:/opt/root/xsp# ./autogen.sh --prefix=/opt/mono-3.2.3
This Perl not built to support threads
Compilation failed in require at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 23.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 26.
Compilation failed in require at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
Compilation failed in require at /opt/bin/aclocal line 38.
BEGIN failed--compilation aborted at /opt/bin/aclocal line 38.
./autogen.sh: line 23: [: -lt: unary operator expected
This Perl not built to support threads
Compilation failed in require at /opt/bin/automake line 137.
BEGIN failed--compilation aborted at /opt/bin/automake line 142.
./autogen.sh: line 23: [: -lt: unary operator expected
Running aclocal -I build/m4/shamrock -I build/m4/shave ...
This Perl not built to support threads
Compilation failed in require at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 23.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 26.
Compilation failed in require at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
Compilation failed in require at /opt/bin/aclocal line 38.
BEGIN failed--compilation aborted at /opt/bin/aclocal line 38.
Error: Could not run aclocal, which is required to configure xsp
root@NAS:/opt/root/xsp#

CHOCOBOBOY said...

Hi, thank u for the binary, it run on my iomega nas without error. and i try to compile xsp got these error, could you give me some help.

root@NAS:/opt/root/xsp# ./autogen.sh --prefix=/opt/mono-3.2.3
This Perl not built to support threads
Compilation failed in require at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 23.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 26.
Compilation failed in require at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
Compilation failed in require at /opt/bin/aclocal line 38.
BEGIN failed--compilation aborted at /opt/bin/aclocal line 38.
./autogen.sh: line 23: [: -lt: unary operator expected
This Perl not built to support threads
Compilation failed in require at /opt/bin/automake line 137.
BEGIN failed--compilation aborted at /opt/bin/automake line 142.
./autogen.sh: line 23: [: -lt: unary operator expected
Running aclocal -I build/m4/shamrock -I build/m4/shave ...
This Perl not built to support threads
Compilation failed in require at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 23.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/ChannelDefs.pm line 26.
Compilation failed in require at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
BEGIN failed--compilation aborted at /opt/share/automake-1.12/Automake/Configure_ac.pm line 27.
Compilation failed in require at /opt/bin/aclocal line 38.
BEGIN failed--compilation aborted at /opt/bin/aclocal line 38.
Error: Could not run aclocal, which is required to configure xsp
root@NAS:/opt/root/xsp#

Kenneth said...

It looks like aclocal does not work on your machine.
Also, the line:

[: -lt: unary operator expected

Seems to indicate that your shell bash/ash/csh/etc does not correctly parse the input. But it may be caused by a previous error that mangles the input on that line.

Try enabling more output and examine the output, most likely the real cause is related to the very first line.

Michel Beld said...

I tried the configure command to compile the latest Mono but I failed sadly.

I'm on a cedarview dualcore atom Synology 412+

configure: creating ./config.status
config.status: creating Makefile
config.status: creating m4/Makefile
config.status: creating include/Makefile
config.status: creating include/private/Makefile
config.status: creating doc/Makefile
config.status: executing depfiles commands
config.status: executing libtool commands
config.status: executing default commands
awk: cmd. line:3: Unexpected token

mcs source: mcs

Engine:
GC: sgen and bundled Boehm GC with typed GC and parallel mark
TLS: pthread
SIGALTSTACK: yes
Engine: Building and using the JIT
oprofile: no
BigArrays: no
DTrace: no
LLVM Back End: no (dynamically loaded: no)

Libraries:
.NET 2.0/3.5: yes
.NET 4.0: yes
.NET 4.5: yes
MonoDroid: no
MonoTouch: no
JNI support: IKVM Native
libgdiplus: assumed to be installed
zlib: system zlib

Michel Beld said...

I tried to compile it on my cedarview dualcore atom Synology 412+ but sadly it failed.

configure: creating ./config.status
config.status: creating Makefile
config.status: creating m4/Makefile
config.status: creating include/Makefile
config.status: creating include/private/Makefile
config.status: creating doc/Makefile
config.status: executing depfiles commands
config.status: executing libtool commands
config.status: executing default commands
awk: cmd. line:3: Unexpected token

mcs source: mcs

Engine:
GC: sgen and bundled Boehm GC with typed GC and parallel mark
TLS: pthread
SIGALTSTACK: yes
Engine: Building and using the JIT
oprofile: no
BigArrays: no
DTrace: no
LLVM Back End: no (dynamically loaded: no)

Libraries:
.NET 2.0/3.5: yes
.NET 4.0: yes
.NET 4.5: yes
MonoDroid: no
MonoTouch: no
JNI support: IKVM Native
libgdiplus: assumed to be installed
zlib: system zlib

Kenneth said...

Hi Michel.

If you can get more info that would help in diagnosing. It seems that AWK gets some input it does not like, which can happen for many reasons.

I do not have an atom based Synology so you are mostly on your own when trying to build there.

Sebastian Betzin said...

Great work! Do you have any plans to compile 3.2.4 as well?

Kenneth said...

No, I do not have plans for trying that currently.

Kevinmce said...

Has anyone had any success compiling MONO 3.2 for the DS412+?

Many users need to move to a later version to support the latest .NET apps.

@Kenneth, another solution for some of us would be to re-compile SQlite with SQLITE_ENABLE_COLUMN_METADATA C-preprocessor symbol

Since this is needed for the NZB drone applicatio.

Do you know how id go about this
?

Kenneth said...

@Kevinmce

I guess you can just write:

make CFLAGS="-D SQLITE_ENABLE_COLUMN_METADATA"

Kevinmce said...

Hi Kenneth,

Ive goten as far as the Michel Beld in compiling MONO.

What sort of information could i provide to help diagnose the AWK problem?

Thanks for the help!

config.status: executing default commands
awk: cmd. line:3: Unexpected token

mcs source: mcs

Engine:
GC: sgen and bundled Boehm GC with typed GC and parallel mark
TLS: pthread
SIGALTSTACK: no
Engine: Building and using the JIT
oprofile: no
BigArrays: no
DTrace: no
LLVM Back End: no (dynamically loaded: no)

Libraries:
.NET 2.0/3.5: yes
.NET 4.0: yes
.NET 4.5: yes
MonoDroid: no
MonoTouch: no
JNI support: IKVM Native
libgdiplus: assumed to be installed
zlib:

Kenneth said...

I would need at least the command that AWK is choking on, but since I have no context I cannot tell you how to find it.

Anonymous said...

Hi all, I'm trying to get Mono 3.2.3 on my DS110j, I managed to download it but the tar command gives a "You must specify one of the `-Acdtrux' or `--test-label' options". As you can see I'm a complete linux rookie, pls help me out here. Beer for thought, thanks a lot!

Marco Mansi said...

Hi Kenneth,

googling on how to install mono on a synology i came to your blog. Really nice that you're sharing your knowledge!
I was trying like the other to install mono 3.4 on my DS211 and i encountered the same error:

awk: cmd. line:3: Unexpected token

Can you help us please?
If u need more information please let me know!

Kenneth said...

Re the tar command: try "tar -xvf mono-3.2.3-bin.tar.bz2" instead.

Kenneth said...

Re the awk problem:

The error message is not enough.
It just says "The awk command is invoked but the input was not recognized".

However, without further information, I dont know anything else.

To further debug, you need to figure out where the awk command is called. Once you figure this out, you need to figure out what arguments it is called with.

also, try:

> awk --version

awk: unrecognized option '--version'
BusyBox v1.16.1 (2014-03-06 14:34:06 CST) multi-call binary.

Usage: awk [OPTIONS] [AWK_PROGRAM] [FILE]...

Options:
-v VAR=VAL Set variable
-F SEP Use SEP as field separator
-f FILE Read program from FILE

Carsten Poulsen said...

I get an error in make install with gmodule-unix.c where I get undefined reference to dlclose, dlerror, dlsym, and dlopen