Search code examples
.net-4.0nant.net-4.5ilmerge

Nant build using .NET 4.5 (Beta) assembly references despite specifying "net-4.0"


After installing .Net 4.5 Beta, the output of my Nant build fails with:

"could not load type 'System.Runtime.CompilerServices.ExtensionAttribute' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'."

because as answered in this question ExtensionAttribute was moved to mscorlib.dll from System.Core.dll. So the nant build is incorporating .net4.5 assemblies despite me specifying the target framework in the nant build script as follows:

<property name="nant.settings.currentframework" value="net-4.0" />

Under Visual Studio the build works fine (produces a .dll that doesn't require .Net 4.5). But I need the build to work with nant because we have "old-schoolers" as well as build processes that use nant.

What do i need to add to my nant build script to make the build actually stick to 4.0?


Solution

  • Yesterday I installed VS 2012 side-by-side with VS 2010 and after recompiling and deploying web project it failed with same exception. After hour of research, I found the solution.

    First, you need to edit nant.exe.config

    Open it and find:

    <framework
       name="net-4.0" 
    

    This is approx. at line 555 (in default config for NAnt 0.92)

    You'll see a huge xml, describing net-4.0 compilation. Find three child <reference-assemblies> elements. First two looks like

    <reference-assemblies basedir="${path::combine(installRoot, 'v4.0.30319')}">
    <reference-assemblies basedir="${path::combine(installRoot, 'v4.0.30319')}/WPF">
    

    and third is

    <reference-assemblies basedir="${environment::get-folder-path('ProgramFiles')}/Reference Assemblies/Microsoft/Framework/.NETFramework/v4.0">
    

    And now - just edit first two to match third (copy from third and paste-replace 1st and 2nd). After this, NAnt will look for all .dlls in Reference Assemblies folder (instead 'broken' Windows/Microsoft .NET/...)

    Don't worry about /WPF suffix at second one - in Reference Assemblies all files are located in one folder, without /WPF subfolder.

    Second step - change your build script

    When calling csc task, add two attributes, nostdlib and noconfig:

    <csc target="..." output="..." nostdlib="true" noconfig="true" ...>
    

    This will disable automatic referencing of "bad new" mscorlib and other librares from csc's folder.

    And inside <references> element - manually add mscorlib.dll, system.core.dll and all used system libraries. NAnt will find them in Referenced Assemblies folder:

    <references>
        <include name="mscorlib.dll"/>
        <include name="Microsoft.CSharp.dll"/>
        <include name="System.dll"/>
        <include name="System.Configuration.dll"/>
        <include name="System.Core.dll"/>
        ...
    

    After that (and rebuild of course) my site successfully started on hosting machine with "original" .NET Framework 4. :)

    P.S. It looks that Microsoft re-invented DLL HELL :)