Warren  P Warren P - 4 months ago 78
C# Question

Create a single source project with full .net, PCL and dotnet core assemblies build from same C# source?

Using Visual Studio 2015, update 3, I am trying to find out the current limitations that exist that would prevent me from doing the following:


  1. For a single C# codebase, compile a full .net framework version and a PCL version, and a .net core class library from the same sources.

  2. Solution dir
    solutiondir\
    will contain a
    src\
    dir which contains a
    projectdir\
    (
    Solutiondir\src\projectdir
    ).

  3. Projectdir
    will contain a HelloWorldPCL class library which is built as a
    classic .net PCL
    project, and with other framework targets as well.

  4. From the same
    Projectdir
    the same HelloWorldPCL will also be compiled for
    .net 4.6
    project.

  5. From the same
    Projectdir
    the same HelloWorldPCL will also be compiled for
    .net core
    .

  6. All of the output assemblies above will share access to a single set of C# code which may have some
    #if DOTNET
    and
    #if NET46
    and
    #if PCL
    conditional defines to handle things which are not available in various frameworks/environments.



So far I can do most of the above, but when I try to have the
Projectdir
contain a
.net core
artifact like
project.json
or
HelloWorldCore.xproj
, the IDE gives me many errors if I try to create separate
.csproj
and
.xproj
projects in the same folder, so that appears not to be the right way to go.

With a working
.csproj
project when I introduce an
.xproj
and a
project.json
on disk, but we have not added these to the solution itself, they are just sitting there on the disk beside the Real Project Sources, I get a Nuget package restore error, which can only be made to go away by deleting the
project.json
file, so clearly it is not possible to have a
.csproj
in a project directory and also have a
project.json
folder. One must choose between
project.json
mode (
.net core
project style) and
.csproj
mode (classic C# project style).

I have built a "broken" codebase that demonstrates the impossibility of using a folder containing both a
.csproj
and a
project.json
and then trying to build the
csproj
and
project.json
project without them interfering:

https://bitbucket.org/wpostma/helloworldcoreandpcl

Question: is there ANY way to build a project from a single set of C# source files, and have as your targets, a full
.net 4.6
assembly, and also a native
.net core
class library, and also a PCL assembly which might target any particular .net profile?

Objection: You may rightly ask "shouldn't you just use one PCL and have done with it, and forget targeting full .net or creating a separate
.net core
class library dll?". Maybe if the code could be built once, from a single source, without any conditional defines, and without any differences in functionality and if the limitations imposed by a lowest-common-denominator PCL "netstandard" profile approach were sufficient, you could. But what about the cases where that's not even possible?

Do we have to have some elaborate build process where we either copy project files or move source code around, in order to achieve single
.cs
source file target multiple .net profile nerdvana? Or am I overlooking alternative solutions?

Update: It appears there is a problem with the Visual Studio IDE that prevents you from directly adding a reference to a class library in your solution, when you build it with a
project.json
instead of using a
.csproj
. However the solution below specified by Jon indicates that you should build your project, then build a nuget package with
dotnet pack
. If you look at my modified demo here you can the pack.cmd file contains the steps I used to pack up a nuget package, and then locally "publish" it to a file (local directory) nuget feed for my own personal use.

Answer

I would try to go for a pure project.json approach. For example, here's a project.json file which will build a single package which supports netstandard1.0, PCL profile 328, and .NET 4.6 - with each configuration defining its own symbols so you can have conditional code.

{
  "version": "1.0.0",

  "frameworks": {
    "net46": {
      "buildOptions": {
        "define": [ "NET46" ]
      }
    },

    "netstandard1.0": {
      "buildOptions": {
        "define": [ "CORE" ]
      },
      "dependencies": {
        "NETStandard.Library": "1.6.0"
      }
    },

    ".NETPortable,Version=v4.0,Profile=Profile328": {
      "buildOptions": {
        "define": [ "PCL" ]
      },
      "frameworkAssemblies": {
         "mscorlib": "",
         "System": "",
       }
    }
  }
}

Then just use dotnet pack to create the nuget package. (After adding in all the other metadata etc.)