.. index::
   triple: MapScript; .NET; Compilation

.. _dotnet_compile:

*****************************************************************************
 .NET MapScript Compilation
*****************************************************************************

:Author: Tamas Szekeres
:Contact: szekerest at gmail.com

Compilation
==============

Before compiling C# MapScript you should compile MapServer with the options 
for your requirements. For more information about the compilation of 
MapServer please see :ref:`Win32 Compilation and Installation Guide <win32>`. 
It is highly recommended to minimize the library dependency of your application, 
so when compiling MapServer enable only the features really needed. To 
compile the C# binding SWIG 1.3.31 or later is required.

.. warning::
    This document may refer to older library versions.  You may want to try
    to use more recent library versions for your build.

Win32 compilation targeting the MS.NET framework 1.1
--------------------------------------------------------
You should compile MapServer, MapScript and all of the subsequent libraries 
using Visual Studio 2003. Download and uncompress the latest SWIGWIN package 
that contains the precompiled swig.exe Open the Visual Studio .NET 2003 
Command Prompt and step into the /mapscript/csharp directory. Edit makefile.vc 
and set the SWIG variable to the location of your swig.exe

Use::

  nmake -f makefile.vc 

to compile mapscript.dll and mapscript_csharp.dll.


Win32 compilation targeting the MS.NET framework 2.0
--------------------------------------------------------
You should compile MapServer, MapScript and all of the subsequent libraries 
using Visual Studio 2005. Download and uncompress the latest SWIGWIN package 
that contains the precompiled swig.exe Open the Visual Studio 2005 Command 
Prompt and step into the /mapscript/csharp directory Edit makefile.vc and set 
the SWIG variable to the location of your swig.exe.

Use::
 
  nmake -f makefile.vc 

to compile mapscript.dll and mapscript_csharp.dll.

Win32 compilation targeting the MONO framework
--------------------------------------------------
Before the compilation you should download and install the recent mono 
Win32 setup package (eg. mono-1.1.13.2-gtksharp-2.8.1-win32-1.exe) Edit makefile.vc 
and set the CSC variable to the location of your mcs.exe. Alternatively 
you can define::

  MONO = YES

in your nmake.opt file.

You should use the same compiler for compiling MapScript as the compiler has 
been used for the MapServer compilation. To compile MapScript open the Command 
Prompt supplied with your compiler and use::

  nmake -f makefile.vc 

to compile mapscript.dll and mapscript_csharp.dll.

Alternative compilation methods on Windows
----------------------------------------------
Beginning from MapServer 4.8.3 you can invoke the C# compilation from the 
MapServer directory by uncommenting DOT_NET in nmake.opt::

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # .NET/C# MapScript
  # ----------------------------------------------------------------------
  # .NET will of course only work with MSVC 7.0 and 7.1.  Also note that
  # you will definitely want USE_THREAD defined.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #DOT_NET = YES

and invoking the compilation by::

  nmake -f makefile.vc csharp

You can also use::

  nmake -f makefile.vc install

for making the compilation an copying the targets into a common output 
directory.

Testing the compilation
---------------------------

For testing the compilation and the runtime environment you can use::

  nmake -f makefile.vc test

within the csharp directory for starting the sample applications compiled 
previously. Before making the test the location of the corresponding libraries 
should be included in the system PATH. 

Linux compilation targeting the MONO framework
--------------------------------------------------
Before the compilation you should download and install the recent mono
Linux package. Some distributions have pre-compiled binaries to install, 
but for using the latest version you might want to compile and install it 
from the source. Download and uncompress the latest SWIG release. You should 
probably compile it from the source if pre-compiled binaries are not available 
for your platform.

Before compiling MapScript, MapServer should be configured and compiled. 
Beginning from MapServer 4.8.2 during configuration the 
mapscript/csharp/Makefile will be created according to the configuration 
options. Edit this file and set the SWIG and CSC for the corresponding 
executable paths if the files could not be accessed by default. To 
compile at a console step into the /mapscript/csharp directory use::

  make
      
to compile libmapscript.so and mapscript_csharp.dll.

For testing the compilation and the runtime environment you can use::

  make test

for starting the sample applications compiled previously.

OSX compilation targeting the MONO framework
------------------------------------------------

Beginning from 4.10.0 the csharp/Makefile supports the OSX builds. Before
making the build the recent MONO package should be installed on the system.

Before compiling MapScript, MapServer should be configured and compiled. 
Beginning from MapServer 4.8.2 during configuration the 
mapscript/csharp/Makefile will be created according to the configuration 
options. Edit this file and set the SWIG and CSC for the corresponding 
executable paths if the files could not be accessed by default. To compile 
at a console step into the /mapscript/csharp directory use::

  make
      
to compile libmapscript.dylib and mapscript_csharp.dll.

For testing the compilation and the runtime environment you can use::

  make test

for starting the sample applications compiled previously.

To run the applications mapscript_csharp.dll.config is needed along with the 
mapscript_csharp.dll file. This file is created during the make process

Installation
===============
The files required for your application should be manually installed. It is 
highly recommended to copy the files into the same folder as the executable 
resides.

Known issues
===============

Visual Studio 2005 requires a manifest file to load the CRT native assembly wrapper
---------------------------------------------------------------------------------------

If you have compiled MapServer for using the CRT libraries and you are using 
the MS.NET framework 2.0 as the execution runtime you should supply a proper 
manifest file along with your executable, like::

  <?xml version="1.0" encoding="utf-8"?>
  <assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1
   assembly.adaptive.xsd" manifestVersion="1.0"
   xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
   xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
   xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
   xmlns="urn:schemas-microsoft-com:asm.v1"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity name="drawmap.exe" version="1.0.0.0" type="win32" />
  <dependency>
  <dependentAssembly asmv2:dependencyType="install"
   asmv2:codebase="Microsoft.VC80.CRT.manifest" asmv2:size="522">
  <assemblyIdentity name="Microsoft.VC80.CRT" version="8.0.50608.0"
   publicKeyToken="1fc8b3b9a1e18e3b" processorArchitecture="x86"
   type="win32" />
  <hash xmlns="urn:schemas-microsoft-com:asm.v2">
  <dsig:Transforms>
  <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
  </dsig:Transforms>
  <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
  <dsig:DigestValue>UMOlhUBGeKRrrg9DaaPNgyhRjyM=</dsig:DigestValue>
  </hash>
  </dependentAssembly>
  </dependency>
  </assembly>

This will inform the CLR that your exe depends on the CRT and the proper 
assembly wrapper is to be used. If you are using the IDE the manifest file 
could be pregenerated by adding a reference to Microsoft.VC80.CRT.manifest 
within the /Microsoft Visual Studio 8/VC/redist/x86/Microsoft.VC80.CRT
directory.

Manifests for the dll-s must be embedded as a resource
----------------------------------------------------------

According to the windows makefile the MapScript compilation target 
(mapscript.dll) is linked with the /MD option. In this case the VS2005 
linker will generate a manifest file containing the unmanaged assembly 
dependency. The sample contents of the manifest file are::

  <?xml version='1.0' encoding='UTF-8' standalone='yes'?>
  <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
  <dependentAssembly>
  <assemblyIdentity type='win32' name='Microsoft.VC80.CRT'
   version='8.0.50608.0' processorArchitecture='x86'
   publicKeyToken='1fc8b3b9a1e18e3b' />
  </dependentAssembly>
  </dependency>
  </assembly>

Like previously mentioned if you are creating a windows application
the common language runtime will search for a manifest file for the
application.  The name of the manifest file should be the same as the
executable append and end with the .manifest extension. However if the
host process is not controlled by you (like web mapping applications
using aspnet_wp.exe as the host process) you will not be certain if
the host process (.exe) will have a manifest containing a reference to
the CRT wrapper. In this case you may have to embed the manifest into
the dll as a resource using the mt tool like::

  mt /manifest mapscript.dll.manifest /outputresource:mapscript.dll;#2

the common language runtime will search for the embedded resource and load 
the CRT assembly properly.

Normally it is enough to load the CRT with the root dll
(mapscript.dll), but it is not harmful embedding the manifest into the
dependent libraries as well.


Issue with regex and Visual Studio 2005
-------------------------------------------

When compiling with Microsoft Visual Studio 2005 variable name collision 
may occur between regex.c
and crtdefs.h. For more details see:

https://github.com/mapserver/mapserver/issues/1651

C# MapScript library name mapping with MONO
-------------------------------------------

Using the MapScript interface created by the SWIG interface generator the 
communication between the C# wrapper classes (mapscript_csharp.dll) and the 
C code (mapscript.dll) takes place using platform invoke like::

  [DllImport("mapscript", EntryPoint="CSharp_new_mapObj")]
  public static extern IntPtr new_mapObj(string jarg1); 

The DllImport declaration contains the library name, however to transform 
the library name into a file name is platform dependent. On Windows the library 
name is simply appended with the .dll extension (mapscript.dll). On the Unix 
systems the library file name normally starts with the lib prefix and appended 
with the .so extension (libmapscript.so).

Mapping of the library name may be manually controlled using a dll.config 
file. This simply maps the library file the DllImport is looking for to its 
unix equivalent. The file normally contains the following information 
(mapscript_csharp.dll.config)::

  <configuration>
    <dllmap dll="mapscript" target="libmapscript.so" />
  </configuration>

and with the OSX builds::

  <configuration>
    <dllmap dll="mapscript" target="libmapscript.dylib" />
  </configuration>
 
The file should be placed along with the corresponding mapscript_csharp.dll 
file, and created by default during the make process. For more information see:

https://github.com/mapserver/mapserver/issues/1596
http://www.mono-project.com/Interop_with_Native_Libraries

Localization issues with MONO/Linux
---------------------------------------

According to https://github.com/mapserver/mapserver/issues/1762 MapServer 
may not operate equally well on different locale settings. Especially when the 
decimal separator is other than "." inside the locale of the process may cause 
parse errors when the mapfile contains float numbers. Since the MONO process 
takes over the locale settings of the environment it is worth considering to 
set the default locale to "C" of the host process, like::

  LC_ALL=C mono ./drawmap.exe ../../tests/test.map test_csharp.png

Most frequent errors
=======================

This chapter will summarize the most frequent problems the user can run into. 
The issues were collected mainly from the -users list and the IRC.

Unable to load dll (MapScript)
----------------------------------

You can get this problem on Windows and in most cases it can be
dedicated to a missing or an unloadable shared library. The error
message talks about mapscript.dll but surely one or more of the dll-s
are missing that libmap.dll depends on. So firstly you might want to
check for the dependencies of your libmap.dll in your application
directory. You can use the Visual Studio Dependency Walker to
accomplish this task. You can also use a file monitoring tool (like
SysInternal's filemon) to detect the dll-s that could not be loaded.
I propose to store all of the dll-s required by your application in
the application folder. If you can run the drawmap C# sample
application with your mapfile your compilation might be correct and
all of the dlls are available.

You may find that the MapScript C# interface behaves differently for the 
desktop and the ASP.NET applications. Although you can run the drawmap sample 
correctly you may encounter the dll loading problem with the ASP.NET 
applications. When creating an ASP.NET project your application folder will 
be '\Inetpub\wwwroot\[YourApp]\bin' by default. The host process of the 
application will aspnet_wp.exe or w3wp.exe depending on your system. The 
application will run under a different security context than the interactive 
user (under the context of the ASPNET user by default). When placing the 
dll-s outside of your application directory you should consider that the PATH 
environment variable may differ between the interactive and the ASPNET user 
and/or you may not have enough permission to access a dll outside of your 
application folder.

Bug reports
==============
If you find a problem dedicated to the MapScript C# interface feel free to 
file a bug report to the `Issue Tracker <https://github.com/mapserver/mapserver/issues>`__.

