4

I have a MonoGame application built using the Linux Game template in Visual Studio. It runs on Windows using either .NET or Mono, but it fails on Linux.

The error is a DllNotFoundException concerning SDL.dll but the SDL.dll is always in the binary's directory. The file is not a CLR assembly, so it's not in the References. Instead, I have it copied during build from MonoGame's Assemblies/Linux directory (and all related CLR assemblies are copied from that folder as well). The error appears regardless of whether I've built the project under Windows in Visual Studio or Xamarin Studio or under Linux in MonoDevelop. There are no build errors.

Here's the relevant stack trace:

System.DllNotFoundException: SDL.dll
  at (wrapper managed-to-native) Tao.Sdl.Sdl:__SDL_InitSubSystem (int)
  at Tao.Sdl.Sdl.SDL_InitSubSystem (Int32 flags) [0x00000] in <filename unknown>:0 
  at Microsoft.Xna.Framework.OpenTKGamePlatform..ctor (Microsoft.Xna.Framework.Game game) [0x00000] in <filename unknown>:0 
  at Microsoft.Xna.Framework.GamePlatform.Create (Microsoft.Xna.Framework.Game game) [0x00000] in <filename unknown>:0 
  at Microsoft.Xna.Framework.Game..ctor () [0x00000] in <filename unknown>:0 

(I haven't included code because this doesn't have to do with my code - it happens even if I build a fresh project from the template. I've already been googling for hours about this and have tried all combinations of what's proposed in various forums, but I haven't found a solution yet.)

What can I do to fix this?


Addendum: With MONO_LOG_LEVEL=debug, I can see the runtime's attempts to locate the DLL and they all say that the file was not found. When I try to "help" the runtime by renaming the file to libSDL.dll (or anything else it's looking for) it says "invalid ELF header" and ignores it. Which is probably to be expected, since it looks like a Win32 binary (not a CLR assembly).

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
  • 2
    If it's not a CLR assembly (and I agree, it probably isn't), then it's a Windows-format PE executable. Linux doesn't recognize that natively, you'll need to configure Wine integration to let Mono load it. And even then it may or may not run correctly. Perhaps you can get a libSDL.so file that exports the same functions? – Ben Voigt Aug 07 '14 at 00:05
  • @BenVoigt I just found out what the problem was, making an answer now. – Theodoros Chatzigiannakis Aug 07 '14 at 00:08

2 Answers2

4

Context:

Indeed, SDL.dll (from Assemblies/Linux) is a Win32 binary. The reason it's included in the "MonoGame for Linux" template is so that the game can run under Windows too. Under Linux, the DLL is not touched. Instead, Mono searches for a native Linux version of the SDL library. For some reason, however, it fails to map.

Solution:

  1. Make sure you have the libSDL library installed on your Linux system.
  2. Go to your project and add a file called Tao.Sdl.dll.config. This is because we want to write an application configuration file for the Tao.Sdl.dll assembly (because the call to SDL happens from inside Tao.Sdl.dll).
  3. Make sure the build action for this new file is Content and that it is copied to the output directory.
  4. Write the following in the new file (applicable for libSDL 1.2 - other versions may require different names):

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <dllmap dll="SDL.dll" target="libSDL-1.2.so.0" />
      <dllmap dll="SDL_image.dll" target="libSDL_image-1.2.so.0" />
      <dllmap dll="SDL_mixer.dll" target="libSDL_mixer-1.2.so.0" />
      <dllmap dll="SDL_ttf.dll" target="libSDL_ttf-2.0.so.0" />
      <dllmap dll="SDL_net.dll" target="libSDL_net-1.2.so.0" />
      <dllmap dll="smpeg.dll" target="libsmpeg-0.4.so.0" />
      <dllmap dll="SDL_gfx.dll" target="libSDL_gfx.so.4" />
    </configuration>
    
  5. Clean and build.

Now Mono should have enough information to find libSDL on your system.

Timo Salomäki
  • 7,099
  • 3
  • 25
  • 40
Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
1

Indeed the solution you found solves the problem you faced, there is however an easier way to do it now.

  1. In your project install the Linux Nuget (https://www.nuget.org/profiles/MonoGame). This will automatically generate the necessary mappings.
  2. (possibly not necessary) The new Nugets should already remove any references that got added by default if you started a project from the Linux Template, but if not, remove those as instructed in the readme of the Nuget
  3. When running in the Linux OS you might then need to install some SDL related libraries that can depend on your system. For example, in my case (debian) I already had the libsdl1.2debian (supplying the "libSDL-1.2.so.0") but when I started the game it identified "libSDL_mixer-1.2.so.0" as missing and therefore I looked it up in an aptcache search and found the libsdl-mixer1.2 package. After installing it the game executed without a problem.