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

3

7

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?

Flannelette answered 16/8, 2012 at 16:12 Comment(0)
D
10

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 :)

Dominiquedominium answered 30/8, 2012 at 15:42 Comment(5)
Reinvented DLL HELL indeed! Thanks for taking the time to post this!Flannelette
Doesn't appear to work with VB.Net which has no "noconfig" option under nant :( I also tried to get this to work using the dlls produced via Studio, and that fails also. :(Epigraph
For the Visual Basic compiler, the noconfig/nostdlib flags behave differently, and notably they will not prevent linking with some standard libraries. Luckily MS realized this problem and added the /sdkpath argument that should be used instead. With nant, I solved it by adding this inside the vbc task: <arg line="/sdkpath:&quot;${environment::get-folder-path('ProgramFiles')}\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0&quot;"/>Santoro
What if our nant script is just calling MSBuild (target:Build) instead of calling CSC directly?Elfrieda
If your nant script call MSBuild - then all work is done by MSBuild, and it use right assemblies like when you build from visual studio.Dominiquedominium
L
1

You might have to do two things (I have not tried this at all, but I remember it helped when 4 was released). First, modify nant.exe.config and add the version to the supported framework versions in the startup section of the config file (I think that's where they go, it should be obvious once you open it). Then, upgrade to the latest and greatest NaNT version. And then, do something like this in your build file:

<property 
    name="assembly-location" value="${framework::get-assembly-directory('net-4.5')}" />
<property 
    name="dotNetReferenceAssemblyPath" value="${assembly-location}\" />

Again, it's been a while and I'm not 100% sure this will do it, but it might set you off on the right track.

Lifesaving answered 16/8, 2012 at 19:21 Comment(0)
E
1

Basically, the solution of Dmitry is correct, but I had to modify it a bit before I could compile .Net 4.0 assemblies on my Windows Server 2012. I have used the latest nant-0.93-nightly-2013-10-20 in my environment.

  1. In the Visual Studio 2013 build output it can be seen that CSC is executed with /noconfig and /nostdlib+ flags for a .Net 4.0 target. This proves that your solution is valid.

  2. basedir="${environment::get-folder-path('ProgramFiles')}..." did not work for me because NAnt.exe is a 64 bit process. Actually, most of the standard assemblies are only available under the Program Files (x86) root. I tried corflagging NAnt.exe, but this caused other problems. To ensure that the core assemblies can be located by both 32 bits and 64 bits processes, I created a directory C:\Nant\Microsoft.Net\v4.0 and copied them there. Because the directory is not below Program Files, it is always visible.

  3. Our NAnt build script is huge and I did not want to modify the references of each and every csc task manually. To reduce the required modifications to the script, I have slightly customized the NAnt 0.93 nightly. If the target framework name is "net-4.0" and the task is of type CscTask, it autmatically adds mscorlib.dll, System.dll and all System asembly references found in a csproj located in the root directory of the csc task sources. Source code and binaries of the customization can be found here: http://support.decos.nl/berend/NAnt-0.93-nightly-2013-10-20-modified.zip

The modified code logs the added references to the NAnt build output:

Inserted reference System.Data.dll
Inserted reference System.Xml.dll
Inserted reference System.configuration.dll
Inserted reference System.dll
Inserted reference mscorlib.dll
      [csc] Compiling 11 files to '...
Early answered 26/3, 2014 at 14:32 Comment(1)
Thanks for sharing! We ended up fixing nant in a nearly identical way, unfortunately as it was just for internal use, there was no interest in releasing our source patches. Similar patches for this issue with Nant exist on github as well, but main project's maintainers have not pulled or integrated them... It is sad to see nant die like this.Flannelette

© 2022 - 2024 — McMap. All rights reserved.