net Core RC2 came out on 2 days ago (May 16 2016). I tried upgrading a simple class library so that it can support .net Core RC2 plus older .net frameworks.
It was relatively straightforward, unlike RC1. Here's what I did.
The library I used was very simple (my public holidays project). There is just one project. We're not doing tests for now- we're using vanilla MsTest. RC2 still only supports XUnit, but we should get MsTest for RTM. For now, we want to be able to use the "classic" solution, with tests, and add a parallel "Core" solution that sits alongside it.
Installing RC2
- If upgrading from RC1, clear the nuget cache: nuget locals all -clear
- If you upgrade projects, there are numerous low-level changes (project.json structure, package names)
- If you installed older versions of RC2/dotnet CLI, uninstall them via Programs + Features ("Microsoft Dotnet CLI for Windows". You can also get rid of "Microsoft ASP.Net 5 RC1 Update 1" which seemed to work but didn't disappear from the list)
- If you forget (as I did!), VS shows the error "The project is configured to use .NET Core SDK version 1.0.0-preview1-002702 which is not installed or cannot be found."
- Use the "Microsoft .Net Core 1.0.0 RC2 VS 2015 Tooling Preview 1"
Project.json
I added a project.json, but I added it alongside the .csproj. There was a bug in RC1 that Visual Studio/ nuget didn't like csproj and project.json together (https://github.com/dotnet/corefx/issues/4544, last updated April, see also Marc Gravell's instructions at http://blog.marcgravell.com/2015/11/the-road-to-dnx-part-1.html, November 2015 so RC1). Let's find out if it's fixed.
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.5.0-rc2-24027"
},
"frameworks": {
"netstandard1.3": {
"imports": "dnxcore50"
}
}
}
- We're just using the standard library (we could depend on loads of individually specified packages, but this is very concise).
- The package/dll name is the folder name.
- Not sure why we're importing dnxcore50, when dnx is supposed to be gone- from the discussion on github it looks like another transitional thing. Maybe it will be gone for RTM in June.
- You can use framework netstandard1.5 or roll back to netstandard1.0. For 1.0 - 1.2, it red-lined on [assembly: Guid( attribute in AssemblyInfo.cs. So netstandard1.3 it is.
I opened up the old solution. Building in Visual Studio broke: "Your project is not referencing the ".NETFramework,Version=v4.0" framework. Add a reference to ".NETFramework,Version=v4.0" in the "frameworks" section of your project.json, and then re-run NuGet restore."
The workaround (from the github issue) is to add <ResolveNuGetPackages>false</ResolveNuGetPackages> to the .csproj. If you have packages, tough.
First dotnet build
There's documentation on the "dotnet build" command here: http://dotnet.github.io/docs/core-concepts/core-sdk/cli/dotnet-build.html
>dotnet build
Project x does not have a lock file
Project x does not have a lock file
Saying it twice doesn't make it any more helpful. The lock file is something to do with a package restore.
>dotnet restore
log : Restoring packages for C:\...\project.json...
info : Committing restore...
log : Writing lock file to disk. Path: C:\...\project.lock.json
log : Restore completed in 950ms.
>dotnet build
It builds!
We now have a dll and pdb in bin/Debug/netstandard1.3
We also have a json file, (x.deps.json), which shows you everything in .NETStandard,Version=v1.3
Parallel solutions
I created a second solution alongside the current solution (essentially the same, minus the test project).
Next, alongside the current project, I added an xproj file (a cut-down csproj). To get this file, I created a new Core library in Visual Studio in a different folder, and stole the xproj. I had to change the <RootNamespace>x</RootNamespace>.
I also changed the <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> ( to .\bin\core\ ) so building the current and new projects put things in different places. Note this only works in Visual Studio- "dotnet build" doesn't look at the .xproj. Instead you have to >dotnet build -c Release -o .\bin\core\ -f netstandard1.3 (note you have to specify the framework when you use --output).
Multi-targeting
Adding older frameworks to project.json is as simple as adding the targets (which are the same as used in nuget).
"frameworks": {
"netstandard1.3": {
"imports": "dnxcore50"
},
"net35": { },
"net40": { }
This works, but in Visual Studio it has a deep output folder structure. Using the dotnet command line, it's exactly what you'd expect.
Not sure why Visual Studio adds more levels.
Packing up
Nuspec is now in project.json. Add json like this:
"packOptions": {
"summary": "Wonderful library",
"tags": [ "Wonderful" ],
"owners": [ "me ],
"projectUrl": "https://github.com/xxx",
"licenseUrl": "http://opensource.org/licenses/MIT",
"repository": {
"type": "git",
"url": "https://github.com/xxx"
}
},
We now use "dotnet pack" instead of "nuget pack": http://dotnet.github.io/docs/core-concepts/core-sdk/cli/dotnet-pack.html
>dotnet pack -c Release -o .\artifacts
- Pack builds the project, but you can pass --no-build.
- Note the version number is taken from the project.json (not the AssemblyInfo.cs).
ToDo
Hopefully appveyor will roll out RC2 support soon (maybe this week?), and we can have easy CI builds. Once that is in-place, I will use it to publish the pre-release package to nuget.
More complex dependencies, particularly on older parts of .net like ADO, will be more challenging. It would be easy to find yourself with heavy compiler directives all over your code.
Sometime after RTM, project.json will be phased out, and we move back to csproj (hopefully improved). I suspect this will come with the release of the next version of Visual Studio (2017?).