Wednesday, November 18, 2020

AltCover -- the road to .net 5, F# 5, and GitHub actions

A for the record listing of what was needed to make the transition for a project that's over a decade old -- the current GitHub repo is only 3 years old, but that was formed by grafting the relevant contents of the original 2010-vintage SVN history onto a 2H17 git bootstrap.

In the original 10Q2-11Q1 development, the build system was a PowerShell script that called msbuild on the .net3.5 solution, then did an automated copy and edit to also build against .net4; taking up the reins again in 17Q3, the latter were used as the basis for going forwards. Over time, parallel .net core projects were added, which eventually subsumed the originals.

Thus, on the eve of the .net5 release, we had

  • A main solution targeting net472 (debug only) and netstandard2.0 for libraries; net472, netcoreapp2.0 and netcoreapp2.1 for tooling with netcoreapp3.0 for unit tests
  • A separate solution building a net20 library (the run-anywhere recorder) plus tests at net20/net472/netcoreapp3.0
  • A separate solution for the GUI tool, targeting net472 (debug only) and netstandard2.0 for libraries, net472 with a reference to the GTK2# assemblies in the GAC, and netcoreapp2.1 for tooling and netcoreapp3.0 for unit tests
  • Finally a solution for building a front end to the Mono C# compiler library, used to provide test data, still in the old project style

So, all very good and mostly modern -- the transition should have been trivial then...

Not so fast...

Once I had the F#5 compiler installed, that broke the net20 build (looking for a System.Numerics.dll which was still part of FSharp.Core in net20). Applying an earlier F# compiler via NuGet package fixed that in Visual Studio, but then dotnet build failed, so I had to resort to msbuild-ing the recorder solution. But then on the travis-ci build, that meant that the net5.0 (upgraded from netcoreapp3.0) unit test target got interpreted as .net Framework 5.0, and the build failed for lack of approprate referenced assemblies. So, as you were before with the unit tests, at least for the moment.

At this point, one obvious result of maintaining backwards compatibility by building deliverable executables (and unit tests) against older netcoreapp* targets, but with "rollForwardOnNoCandidateFx": 2 in runtimeconfig.template.json was a profusion of NETSDK1138 obsolescence warnings; silenced by building with /p:CheckEolTargetFramework="false" all around.

Where I'd been running ahead of AppVeyor's current installed .net SDKs, I'd been using Chocolatey to bring down the version I wanted; time to be aware that the package has been renamed from dotnetcore-sdk to dotnet-sdk instead.

That got things building on the "traditional" CI servers, so, a good time to make a first try of GitHub Actions for CI as well.

With the at-time-of-writing latest windows and linux platforms, that meant that I didn't have a "modern enough" msbuild.exe on the PATH for the recorder and the GUI tool. To resolve that, I resorted to finding the path of the MSBuild.dll from the current .net5 SDK (via parsing the output of dotnet --info for the Base Path: value), and lashing up a way to use it with Fake's MSBuild command line construction support.

Fall-out from this was needing to compile string resources ahead of time for the recorder -- no ResGen.exe support in the new regime -- and use the same (earlier) compiler for all the test platforms; also creating a set of reference assemblies for GTK#2, so I could avoid having any reference to the GAC (meaning that the GUI tool solution would now dotnet build, even if I still have to MSBuild the recorder solution). The Mono C# compiler project -- also using MSBuild -- which still made references out to .targets files out in Visual Studio or Windows SDK parts of MSBuildExtensionsPath32-land also needed attention; as a retro project, I simply added the earlier F# compiler package here, too, to make it build.

On the plus side, now the net20 project is using the MSBuild executable from the net5 SDK, switching the unit tests all round to target net5.0 works as one would hope it to work.

No comments :