0

To build our application, we have a structure of several MSBuild proj files, which currently compile libraries on .NET Framework.

Now we want to move the solution to .Net 6.0, however the task we use ("Csc") give us many errors when using the same parameters. Looks that is not made to make Net6.0 assemblies from MSBuild.

To clarify, this is not just one project, but a hierarchy of projects:

  1. Project1 has a Build Target that DependsOn on Project2.

  2. Project2 has a Build Target that DependsOn Project3.

  3. Project3 executes some custom task which generates CS files, and compiles them into a Library, that is then used by Project2.

Everything is done vie msbuild proj files, like:

Project1.proj:

<Project DefaultTargets = "Build">
   <Target Name = "BusinessRuless">
    <MSBuild Projects=".\Project2.proj" Targets="Build" />
  </Target>   
  <Target Name = "Build" DependsOn ="BusinessRuless">
    <CSC Sources = "@(CSFile)"
            References="$(dlls);"
            DebugType="full"
            DefineConstants="TRACE"
            TargetType="library"
            EmitDebugInformation="true"
            TreatWarningsAsErrors="true"
            OutputAssembly = "$(dllFileName).dll">
        </CSC>
  </Target>
...

When the CSC task starts, it invokes the correct csc compiler:

C:\Program Files\Microsoft Visual Studio\2022<version>\MSBuild\Current\Bin\Roslyn\csc.exe

However, it throws errors as if the basic system assemblies are not referenced:

CSC : error CS0518: Predefined type 'System.Void' is not defined or imported [....proj]

So in summary the question is : Is there any recipe to use MSBuild to build projects targeting Net6.0?

Do i need to explicity reference all the foundational dlls from Nuget?

BTW: I tried adding one of them, like "C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.9\ref\net6.0\System.Runtime.dll", but the same error shows up : Predefined type 'System.Void' is not defined or imported

We dont use Visual Studio for the building of our libraries, just MSBuild.

Thanks a Lot!

D.Firka
  • 59
  • 5
  • Are you using Visual Studio generated .csproj files and a Visual Studio generated .sln file? Or are all the MSBuild project files custom written? – Jonathan Dodds Dec 17 '22 at 00:07
  • Does this help: https://stackoverflow.com/questions/36737642/how-to-make-csc-exe-c-sharp-6-aware? – Kit Dec 17 '22 at 02:10
  • How did you "move the solution" to .NET 6? Please create new solution/projects for .NET 6 and then cut/paste your code over. That can easily show you the incompatibilities and solutions for specific errors can be then found via search engines. – Lex Li Dec 17 '22 at 08:36
  • Jonathan: i am using proj files, not csproj. – D.Firka Dec 18 '22 at 13:24
  • Kit: the CSC task is using the correct csc.exe compiler. – D.Firka Dec 18 '22 at 13:24
  • Lex Li: our code compiles OK in a new .NET 6 solution/csproj, however we want to have a minimal structure and build from the ground up, not using Sdk="Microsoft.NET.Sdk" which adds requirements we dont need for a simple class library, like a specific obj directory for the nuget projects, which we actually do in a more efficient way, cascading properties with the nuget locations, from the top MSBuild project, instead of restoring at each project. – D.Firka Dec 18 '22 at 13:28

1 Answers1

0

Finally i was a able to do it, here is what i found:

1- Get the dotnet location of the assemblies. I use the following fragment to get the dotnet folder:

<Choose>
    <When Condition=" '$(DOTNET_ROOT)'=='' ">
      <PropertyGroup>
        <DotNetRoot>$(ProgramFiles)\dotnet</DotNetRoot>
      </PropertyGroup>
    </When>
    <Otherwise>
      <PropertyGroup>
        <DotNetRoot>$(DOTNET_ROOT)</DotNetRoot>
      </PropertyGroup>
    </Otherwise>
  </Choose>

Then creating a property to the location of the assemblies (dont know still where to get the version number, so it is hardcoded)

<PropertyGroup>
    <TargetFrameworkMoniker>.NETCoreApp,Version=v6.0</TargetFrameworkMoniker>
    <TargetFramework>net6.0</TargetFramework>
    <DotNetAssemblies>$(DotNetRoot)\packs\Microsoft.NETCore.App.Ref\6.0.9\ref\net6.0</DotNetAssemblies>
</PropertyGroup>

2- Prevent CSC task from using the standard libraries, using NoStandardLib="true"

3- Allow nullable by using Nullable="enable"

4- Adding specific references to the standard libraries used by the CS files.

In summary, the CSC Task looks like:

<CSC Sources="@(CSFile)" References="...$(dotNetAssemblies)\System.Runtime.dll;$(dotNetAssemblies)\System.dll;$(dotNetAssemblies)\System.Threading.Tasks.dll;"  
         DebugType="full" TargetType="library" EmitDebugInformation="true" TreatWarningsAsErrors="true" OutputAssembly="$(dllFileName).dll"
         NoStandardLib="true" Nullable="enable">
</CSC>
D.Firka
  • 59
  • 5
  • 1
    This seems like an incredibly, unnecessarily complicated exercise in hoop-jumping just because you have a misguided belief that having references to libraries your code doesn't need, somehow makes it less efficient (it doesn't). It's also going to break every time an update to VS is released which updates the reference assembly versions (i.e. the `\6.0.9` directory could go away). Basically, you're fighting the project system in every possible way it's possible to do so, for no apparent reason. As part of your .NET 6 migration, consider getting rid of all this. – Ian Kemp Dec 20 '22 at 14:15
  • Thanks for your feedback, my question is: How would you suggest to orchestrate the automatic code generation (which we do by xslt now), and the serial compilation of dependencies (first the Protobuf contracts, then DataCentric tier, then Business rules, then UI/Asp.Net) that currently we have all solved via MSBuild... – D.Firka Dec 21 '22 at 15:08