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

2

5

Update: This refers to an obsolete set of .net core tools built around project.json, this question and its answers are of very limited utility in current .net core toolsets like Visual Studio 2017+.

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.

Cronyism answered 5/7, 2016 at 14:36 Comment(9)
For a more concrete example consider this codebase where I am trying to create native .net core class library targets, on a codebase which currently has dual PCL and full-net solutions doing two thirds of what I wanted to do in the question above... github.com/wpostma/fhir-net-apiCronyism
Why have three different project files? I think you can do all of this with a single project.json which supports the three different frameworks. (And you can have different build options for the different frameworks, too...)Schaab
See stackoverflow.com/questions/36148363 for some help with targeting PCL from project.jsonSchaab
Yes, I believe it should all work. It's a bit of a "road less travelled" though.Schaab
Will see if I can come up with a complete example. Which PCL profile are you targeting?Schaab
I'm not sure what you mean by "the profile selected above" - but that solution seems to be needlessly complicated with lots of folders etc. Will still try to add an answer...Schaab
25k and an image of your errors. There should be a ceremony where we rip the rep off your uniform and send you out into the desert on a donkey.Fungicide
The screenshot is in the end not relevant, deleted.Cronyism
Interesting blog post: stackify.com/using-both-xproj-and-csproj-with-net-coreCronyism
S
6

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

Schaab answered 5/7, 2016 at 15:34 Comment(5)
@WarrenP: Will try to reproduce. Although note that within the same solution, I typically use a "target": "project" dependency, to avoid having to specify the version number.Schaab
@WarrenP: Why do you have four different projects in your sample? It would make it easier to understand what's going on if you just had two: a class library with a project.json as per my answer, then a console app trying to consume it... (In particular, which project is failing? It sounds like this may be an issue with csproj projects failing to consume project.json projects. You should try either making everything project.json-based, or pack the class library into a nuget package, put it in a local package source, and depend on that.)Schaab
@WarrenP: Well, I'd check that the resulting project.json is what you'd want it to be. A bit of diligence early in can pay dividends in maintainability later on.Schaab
@WarrenP: From what kind of project? Maybe it's worth asking a second question where you give the specifics. I'm sure we can make this work :)Schaab
Okay. Full source code of my example, fixed as per Jon's instructions above, is working fine... Code is found here: bitbucket.org/wpostma/helloworldcoreandpclv2Cronyism
C
1

You can use xproj and csproj together with different project.json files. I did a blog post on the topic you should check out: http://stackify.com/using-both-xproj-and-csproj-with-net-core/

Essentially, you create a projectname.project.json that csproj picks up and then project.json that xproj uses. Seems to work!

Chemotaxis answered 11/7, 2016 at 16:37 Comment(1)
Thanks. That's a useful technique!Cronyism

© 2022 - 2024 — McMap. All rights reserved.