4

edit 3: Looks like what I'm trying to do isn't supported; it isn't actually possible to 'share' project.json files across configurations. I'm supplanting this question with How to point to a different project.json location in a .NET Core PCL?

edit 2: Yep, my suspicions were correct. ProjectJson and ProjectLockJson aren't actually special MSBuild properties, their values were being used in another imported MSBuild project to do the actual work. I'll post more on this (hopefully in the form of an answer) when I have an update.

edit: I've published the whole project to GitHub so you guys can get a repro. Just git clone the repository, open it up in VS, start building and you should hit the error.

Original Post

I'm trying to create a portable class library based on .NET Core. I'm having trouble associating multiple project.json files with my csproj. Here is my directory structure:

LibFoo
|
---- LibFoo.csproj
|
---- project.json
|
---- Platforms
     |
     ---- Net45
     |    |
     |    ---- project.json
     |
     ---- Profile32
          |
          ---- project.json

I have two MSBuild platforms (excluding AnyCPU), Net45 and Profile32. Basically, when it's set to .NET Framework 4.5, I want it to compile include the project.json in the root directory, and the project.json in Platforms/Net45. When it's set to Profile32, I want it to do that with the project.json in Platforms/Profile32.

My question is, how can I get this to work in MSBuild? Here's the relevant snippet of my csproj file:

<ItemGroup Condition=" '$(Platform)' == 'Net45' ">
  <!-- Target WPF apps -->
  <TargetPlatform Include=".NETFramework, Version=4.5" />
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'Profile32' ">
  <!-- Target Windows 8.1 Universal apps -->
  <TargetPlatform Include="Windows, Version=8.1" />
  <TargetPlatform Include="WindowsPhoneApp, Version=8.1" />
</ItemGroup>
<ItemGroup>
  <None Include="Platforms\Net45\project.json" />
  <None Include="Platforms\Profile32\project.json" />
</ItemGroup>
<PropertyGroup>
  <ProjectJsonRoot>Platforms\$(Platform)</ProjectJsonRoot>
  <ProjectJson>$(ProjectJsonRoot)\project.json</ProjectJson>
  <ProjectLockJson>$(ProjectJsonRoot)\project.lock.json</ProjectLockJson>
</PropertyGroup>
<ItemGroup>
  <!-- Include a common project.json for shared configs -->
  <None Include="project.json" />
</ItemGroup>

For some reason, the ProjectJson and ProjectLockJson parts don't seem to be working. I suspect they're the problem since I couldn't find any official docs for them on MSBuild, but CoreFX seems to be using it pretty successfully in their csproj files. Am I doing something wrong?

Community
  • 1
  • 1
James Ko
  • 32,215
  • 30
  • 128
  • 239
  • 1
    I'm just going to comment because I'm not sure on the _correct_ way to make this work, but you're supposed to have a single `project.json` file that mentions the different runtimes. There's also a common section. – moswald Feb 17 '16 at 02:57
  • @moswald I tried that at first, but I'm getting this error: 'Packages containing MSBuild targets and props files cannot be fully installed in projects targeting multiple frameworks.' And then VS just decides to ignore all of the .cs files. – James Ko Feb 17 '16 at 02:59

2 Answers2

3

The thing is that you should just move from .csprojs to .xprojs. Then each .xproj can have single project.json that can target multiple frameworks.

Great article: http://blog.marcgravell.com/2015/11/the-road-to-dnx-part-1.html

Here is my sample: https://github.com/adamsitnik/BenchmarkDotNet

Adam Sitnik
  • 1,256
  • 11
  • 15
  • Great answer! The thing is, I'm actually in the middle of transitioning from xproj to csproj, since [xproj has trouble](http://stackoverflow.com/questions/35439256/how-to-reference-windows-winmd-from-a-net-core-library) when it comes to using Windows/Windows Phone 8 APIs. So alas, using xproj is not an option. – James Ko Feb 17 '16 at 17:59
  • @JamesKo I am sorry to hear this. Have you tried with new dotnet cli toolchain? There is no integration with VS as far as I know but you could report a bug in their repo, so maybe it could be fixed with RC-2 and included in next VS release? Otherwise I have no other ideas – Adam Sitnik Feb 17 '16 at 23:33
0

For people who've stumbled across this question looking for help, follow Adam Sitnik's answer. For the vast majority of use cases, the solution is just to switch from csproj to xproj, so your project.json file can target multiple frameworks.

Alas, for my situation (which was to use Windows Runtime APIs from my library), that unfortunately wasn't possible, since project.json has no built-in ways to access the WinRT APIs even when you are compiling for their target framework. For example, if you do this:

"frameworks": {
    ".NETPortable,Version=v4.6,Profile32": {
        "frameworkAssemblies": {
            "Windows": { "type": "build" }
        }
    }
}

it won't compile, although the compiler will happily find assemblies like System.Runtime or System.Linq for you.

I ended up raising an issue about this on the CoreFX repo here. It seems that the way the CoreFX team does this (for example you will find multiple project.jsons in a project like this) is by creating a custom MSBuild task that allows them to override the project.json, which they store the code for in their buildtools repo.

I wasn't really up to creating my own MSBuild task nor using the .NET build tools to build my own repo, so I ended up just creating multiple csproj files the old-fashioned way.

Community
  • 1
  • 1
James Ko
  • 32,215
  • 30
  • 128
  • 239