Going by the description, the MonoGame.Framework.Portable nuget package should be a bait and switch PCL, however it does not have the same API surface as the platform specific ones, and as a matter of fact is not a bait and switch PCL at all (look at MonoGame\NuGetPackages\MonoGame.Framework.Portable.nuspec and the only target is the PCL platform moniker - nuget packages targeting multiple platforms should be structured like this).
This includes the latest prerelease version as well.
To test, create a monogame project (I am using the Monogame UWP template), and a PCL project, then reference the PCL from the main project.
Add the MonoGame.Framework.Portable package to the PCL project and try to build: you'll get a conflict because both the PCL nuget package and the UWP try to copy their different versions of Monogame.Framework.dll to the same location.
Try adding the PCL nuget to both projects instead of the platform specific one and MonoGame.Framework is not present anymore.
This means the only way of sharing code in a game targeting different platforms is to use a shared project like in the template, which is not at all good practice.
@DDReaper @dellis1972 ?
Isn't the Monogame.Framework.Portable package on NuGet supposed to be a bait and switch one?
As it is now, that package does not target multiple platforms - it only has a PCL assembly and no platform specific code.
For reference, look at the definition of the package in the page I linked to before
<files>
<!-- Cross-platform reference assemblies -->
<file src="Plugin.LoggingLibrary\bin\Release\Plugin.LoggingLibrary.dll" target="lib\netstandard1.4\Plugin.LoggingLibrary.dll" />
<file src="Plugin.LoggingLibrary\bin\Release\Plugin.LoggingLibrary.xml" target="lib\netstandard1.4\Plugin.LoggingLibrary.xml" />
<file src="Plugin.LoggingLibrary.Abstractions\bin\Release\Plugin.LoggingLibrary.Abstractions.dll" target="lib\netstandard1.4\Plugin.LoggingLibrary.Abstractions.dll" />
<file src="Plugin.LoggingLibrary.Abstractions\bin\Release\Plugin.LoggingLibrary.Abstractions.xml" target="lib\netstandard1.4\Plugin.LoggingLibrary.Abstractions.xml" />
<!-- iOS reference assemblies -->
<file src="Plugin.LoggingLibrary.iOS\bin\Release\Plugin.LoggingLibrary.dll" target="lib\Xamarin.iOS10\Plugin.LoggingLibrary.dll" />
<file src="Plugin.LoggingLibrary.iOS\bin\Release\Plugin.LoggingLibrary.xml" target="lib\Xamarin.iOS10\Plugin.LoggingLibrary.xml" />
<!-- Android reference assemblies -->
<file src="Plugin.LoggingLibrary.Android\bin\Release\Plugin.LoggingLibrary.dll" target="lib\MonoAndroid10\Plugin.LoggingLibrary.dll" />
<file src="Plugin.LoggingLibrary.Android\bin\Release\Plugin.LoggingLibrary.xml" target="lib\MonoAndroid10\Plugin.LoggingLibrary.xml" />
<!-- UWP reference assemblies -->
<file src="Plugin.LoggingLibrary.UWP\bin\Release\Plugin.LoggingLibrary.dll" target="lib\UAP10\Plugin.LoggingLibrary.dll" />
<file src="Plugin.LoggingLibrary.UWP\bin\Release\Plugin.LoggingLibrary.xml" target="lib\UAP10\Plugin.LoggingLibrary.xml" />
</files>
Notice how assemblies for different platforms with the same name are packaged in subfolders of "lib" named after the platform moniker they target so that Nuget installs the correct assembly in the project on package restore.
Going by what you have in MonoGame.Framework.Portable.nuspec, the package only includes the PCL assemblies.
I'm not an expert in NuGet, but i'll tell you what I know.
Isn't the Monogame.Framework.Portable package on NuGet supposed to be a bait and switch one?
It is supposed to be.
it only has a PCL assembly and no platform specific code.
Correct... and that is the intent. The package is actually the "bait" part of "bait and switch".
For the "switch" you need to reference one of our platform specific Nuget in your final executable project.
Which is what I did, but since both the PCL and the platform specific nugget package contain Monogame.Framework.dll actually building the final project becomes impossible.
Weird... because it works for us. Since the executable is the last to process the non-PCL assembly is the one that ends up in your executable bin folder.
Ok, created a GitHub repo to demonstrate the issue.
Check it out and try to compile: you should be getting:
Error Payload contains two or more files with the same destination path 'MonoGame.Framework.dll'. Source files:
C:\Users\<yourusername>\.nuget\packages\MonoGame.Framework.Portable\3.6.0.1625\lib\portable-net45+win8+wpa81\MonoGame.Framework.dll
C:\Users\<yourusername>\.nuget\packages\MonoGame.Framework.WindowsUniversal\3.6.0.1625\lib\netcore\MonoGame.Framework.dll MonogamePCLDemo.UWP
This is on the latest/fully patched Windows 10 and Visual Studio 2017.
Ok, downloaded your project and ran it, which replicated your issue.
However, I then removed your PCL, simply created a new one, added the MG portable lib and referenced the library and it ran without issue.
SO it seems more a local issue with the project type you are using.
I've been using PCL's extensively with the upgraded MonoGame samples for the XNAGameStudio ported projects and have had no issues.
What template have you been using for PCL's and using which IDE?
Ok, I tried repeating your steps and it works now: the difference being that I did not create a project.json file for the PCL and it is using packages.config instead.
This basically means that the Monogame packages are locked to Nuget 2.x (see the article on Nuget dependency resolution for details).
While the issue can be worked around for now (although you may be relying on undefined behaviour that just happens to do the trick), it will become a problem when Microsoft drops support for Nuget 2.x or when migrating to .NET Standard, which requires 3.x
I believe you could solve the issue by either creating a true bait and switch nuget package (nicer user experience) OR by renaming the PCL Monogame.Framework.dll to something else and having the platform specific monogame packages in Nuget require the PCL package as dependency.
Hmm, I'll look in to the project.json path. However, this is being deprecated again with 2017 as it didn't take off.
For newer projects they are reverting back to a cleaner .csproj way of doing things.
btw, how did you create your pcl project using project.json for reference? @albertofustinoni
You are right project.json is deprecated, however as you say the .csproj is not the same as the od one.
Try creating a .NET standard project and add a Nuget package: you'll notice no packages.config gets created.
This means that the issue I encountered will present itself with projects using the new .csproj format as they too rely on Nuget 3.x.
As for how to create a PCL that uses project.json:
packages.config)project.json file in the project's root. For a PCL, it may look like{
"frameworks": {
".NETPortable,Version=v4.6,Profile=Profile44": {}
}
}
project.json to track installed Nuget packages.I'm having -exactly- the same issue, specially with UWP.
@albertofustinoni is right, Monogame.Framework.Portable is not a true bait'n'switch assembly, and it cannot be used on Nuget3.5+ cross platform projects
Ideally, we only need a single Monogame.Framework NuGet package for all platforms AND Net.Standard , inside the package you would have the appropiate assembly binaries for each platform/framework, and it's MSBuild the one that "magically" picks the appropiate assembly
@tomspilman Here and here you can find two great tutorials on how to write true bait'n'switch assemblies, with Net.Standard support. The tutorials are intended to use Xamarin.Forms (also a PCL) within Net.Standard 1.4 projects... but replace Xamarin.Forms with Monogame.Framework and same rules apply.
@vpenades the PCL version of MG is a "true" bait and switch dll, there does seem to be some enhancement needed for the NuGet it'self which I'm looking in to.
Personally, using the MonoGame templates and the standard PCL templates, I've had no issues with PCL projects.
There is a separate thread discussing NetStandard projects or a NetCore/NetStandard version of MonoGame but there is stil a way to go.
Only other subject is possibly the creation of a NetStandard "Bait and Switch" but from what I've read that will not work with MonoGame in it's current versioning.
Well, I've been using some other bait'n'switch packages and this is what I expect:
UrhoSharp NuSpec
SkiaSharp NuSpec
As you can see, it includes all the platforms in a single nuget package, which is not what Monogame.Framework.Portable is doing.
The advantage of placing all the platform assemblies in a single package is that it lets msbuild choose the right one for all the projects. so if you have a shared PCL code being referenced by an Android application project, MSBuild will always choose Monogame.Framework.Android from within the package. This way, it prevents the collision between the Portable and Android frameworks, because from the point of view of msbuild, they're the same package, not two different packages as it happens now.
In fact, in the "single package scenario" the PCL/Net.Standard assembly is only used as a surface definition API, it never reaches the actual platform applications, so in many cases, the methods could even be empty!
It's exactly as @vpenades says
OK, well a bit of a history lesson. Originally MonoGame was a single NuGet, a decision was then taken to split up the Nuget to make it easier to do all the platform builds and ensure everything worked as expected. No right or wrong answer, they are different paths.
However, the internal layout of the NuSpec would not change the outcome above that was originally reported (unless I'm missing something in the new .csproj references section about working with NuGet project ID's)
I'll do some testing using your steps and see if it would make any difference.
Thoughts @tomspilman @dellis1972 @KonajuGames , if there is indeed an issue / concern being raised about MG having separate NuGet's, should we go back to the single combined package (where possible) for a unified package.
Only one now that would have to remain separate would be the Content Pipeline as it's not MonoGame itself.
@DDReaper it's possible the issues being reported by users is because people are beginning to use the new, simple .csproj style, AKA "SDK Style".
Apparently, when using SDK Style csprojs, MSBuild becomes "smarter" and it's able to resolve dependencies in a way that the old csproj was not able to do.
In my case, I created several "terminal" projects with the classic .csproj, one for android, another for UWP, etc, and then I created a PCL project intended to contain the Game class, using the new SDK style .csproj (steps are described HERE), in which I referenced Monogame.Framework.Portable.
In such scenario, being the shared project a SDK style project, when compiling, MSBuild tries to retrieve compatible assemblies from the shared project, to reference them in the terminal projects. For example, when compiling the Android terminal, MSBuild will ask the shared project: "give me an assembly compatible with android".
In order to configure an SDK project to behave like that, you either create a net standard, or PCL project and reference true bait'n'switch assemblies..... or you create a SDK project targeting multiple platform, each one referencing the appropiate assemblies, so at compile time it will automatically create an assembly for every platform.
This last option is something I want to give it a try later.
Ok, been forward and back on this and using a single NuGet isn't going to work. Simply because we have several platforms which share the same Framework level that NuGet supports but have different dependencies.
For example,
NuGet just isn't capable of distinguishing between them currently.
So a better solution would be to add the Portable Class Library version to each of the current separate NuGet's, which should solve the problem in 99% of the cases.
Thoughts?
@DDReaper yes, in windows desktop platform where you have a choice of technologies, and in the future, where all platforms might eventually support Vulkan, having a single, cross platform package might not be possible.
But it cannot be denied that, in order to be able to write cross platform code seamlessly, we need some sort of cross platform "bait" package that can be references by all platforms.
Maybe the solution would be to follow SharpDx assembly split pattern, I would split like this:
Monogame.Framework.core
Monogame.Framework.desktop.dx
Monogame.Framework.desktop.gl
Monogame.Framework.droid.gl
Monogame.Framework.up.dx
Monogame.Framework.ios.gl
Etc...
The only difference between this proposal and current implementation is that all the platforms in the proposal depend on a core package that can be referenced from cross platform projects. The current implementation has a self contained framework that can only be references on each respective platform.
in the future, where all platforms might eventually support Vulkan
This won't happen. Consoles in particular use custom APIs to get the best possible performance. Also I don't think Apple plans to support anything but Metal anytime soon... especially on iOS.
This is why MonoGame has never tried to focus on a single graphics API.
True @vpenades however, from a single NuGet package model, we can't go there because NuGet cannot differentiate between the platforms that need one library over another.
SharpDX (however it's split up) has only one focus. MonoGame has multiple and Nuget just isn't designed to work that way.
Splitting MonoGame up would not solve this specific issue you are reporting.
But
Adding the Portable Lib as an installable for the platforms, would solve your specific issue with UWP and modern projects using newer .csproj or .json formats as they share the same NuGet ID.
Are you sure Nuget doesn't support different package dependencies depending on platform?
I'm out and can't provide an example right now but I remember seeing packages having multiple platforms with different dependencies listed in Visual Studio
@albertofustinoni he is referring to platforms like windows desktop (net46) where you have two graphics Api choices, opengl and directx. That case cannot be solved by simply a choice of platforms.
So far, the only approach I can see that might work, is to create a shared cross project that would switch between monogame platforms, without the bait monogame.platform. I'll give this approach a try next Monday
Shared projects can work as an alternate solution @vpenades they are just an alternate path to PCL. Although they can't support Linux and some other platforms, whereas PCL has more reach.
I believe @dellis1972 even got Content Referencing working at some point, not sure how though.
@albertofustinoni what @vpenades is correct, when you have two platforms both running on Net45 (like the desktop platforms) NuGet has no way to say install DX in one and not the other. Still investigating as NuGet is changing all the time (having build definition support would be a great help) but no luck yet.
As I said, the best solution (esp for UWP) is to simply add PCL to the UWP NuGet which would solve that problem, since it is using the newer csproj format. Then look to add it to the others as well maybe.
@vpenades I see your point now - I didn't understand what you meant at first.
@DDReaper First of all, I'd like to thank you very much your work so far on this issue.
If I understand what you said correctly your intention is to add the PCL Nuget package as a dependency of the UWP package, right? If so I agree it should work.
In my opinion, shared projects are not really an alternative to PCL: they are just a convenient way for including the same source files into multiple Visual Studio projects - they themselves produce no assembly as you compile the same source multiple times instead.
Visual Studio's tooling becomes a lot less helpful when using them too, since there's no defined API they can target the way PCLs or .NET standard asseblies do AND they of course cannot include resources of their own, which means no way of sharing localized strings between platforms, for example.
Interestingly, libraries like SkiaSharp are in the process of supporting Vulkan, and I wonder how are they going to do it, while also keeping gl support. Maybe they're keeping the platform package switch per platform, and then, if a specific platform has multiple graphics API, let the user choose the API programatically and load the neccesary DLLs dynamically?
As an FYI, Protobuild can produce Unified NuGet packages for most things, with additional metadata for platforms with the same framework information (beyond "DesktopGL", every platform currently maps to a unique NuGet framework ID).
One alternative way to support DesktopGL (which is really the only odd one out) would be with additional build targets, which redirect the DLL referenced by MSBuild if a <UseDesktopGL> property is present in the project that has the reference.
We actually already publish a unified MonoGame package here: https://www.nuget.org/packages/MonoGame.Framework.Redpoint, which we use in Protogame. This package supports Windows, macOS, Linux, Android and iOS, but obviously could have other platforms added to it as needed (we just don't currently support some of the less used platforms in Protogame since we haven't had any requests for them).
Yeah, doing the rest would be trivial and it certainly is another option. The PR sorts out the short term, which reviewing what to do for the long term.
So the best option may be to have one Generic NuGet for everything except Linux / Desktop GL and Content Pipeline, then separate packages for those including the PCL version packaged with them.
Thoughts @dellis1972 @KonajuGames ?
Had another thought over the weekend. Could simply break the MonoGame.Framework NuGets down to just two instead of all the separate platforms.
So having:
Packaging all the platforms in each that support those targets and the Portable lib.
That should solve all these packaging issues and greatly simplify our NuGet's
Thoughts @tomspilman @vpenades @albertofustinoni ?
To me, this split would make sense.
Even for platforms that currently only support OpenGL, it would make sense to add the extension, Because it might be feasible in the future monogame also supports .Vulkan
Apologies for the delayed reply.
Splitting by platform makes sense to me too. I guess the DirectX package would be Win32 and WinRT Windows, and OpenGL Win32 and everything else, right?
PR #5799 added to implement this suggestion. Tested locally but need to see what comes out of TeamCity now.
I'll give it a try tomorrow
I still see the issue in 3.7.1.189.
So what is the correct way to reference MonoGame from NuGet when using .NET Standard class library?
The way you solve this is by referencing the PCL lib, or any lib for that matter, in the following way:
<PackageReference Include="MonoGame.Framework.DesktopGL.Core" Version="3.7.0.7">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
Gonna close this as its a non issue.
@harry-cpp can you please elaborate in detail on your fix? I don't understand how to apply it. I am having the exact same issue as described above:
I have a PCL project with the MonoGame.Framework.Portable nuget installed.
I have a UWP Xaml project, and I reference the PCL project. To run you need to do, _game = MonoGame.Framework.XamlGame<MonoPCL.Game1>.Create(launchArguments, Window.Current.CoreWindow, swapChainPanel);
So I have the the MonoGame.Framework.WindowsUniversal nuget installed to it. But you can't do that because it fails with :
Error Payload contains two or more files with the same destination path 'MonoGame.Framework.dll'. Source files:
C:\Users\Paul.nuget\packages\monogame.framework.portable\3.7.1.189\lib\portable-net45+win8+wpa81\MonoGame.Framework.dll
C:\Users\Paul.nuget\packages\monogame.framework.windowsuniversal\3.7.1.189\lib\netcore\MonoGame.Framework.dll
Manually add it to your .csproj project file.
Also this might be useful to you: https://github.com/harry-cpp/MonoGame/blob/newprojdocs/Documentation/setting_up_project/setting_up_project.md
@harry-cpp thank you for the quick response, I really appreciate it. I finally got it working, a couple of things worth mentioning:
So the guide you posted works perfectly for a mgdesktopgl project, but not the UWP one (mguwpxaml). When you try to add the reference you get this error
Evaluation failed with following error: The imported project "C:\Program Files\dotnet\sdk\2.1.509\Microsoft\WindowsXaml\v15.0\Microsoft.Windows.UI.Xaml.CSharp.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
Googled a bit but couldn't find a solution.
So I took that Pong project and added a UWP project to it. First thing I noticed was the MonoGame NetStandard Library (mgnetstandard) project type does not exist under File -> new project. I was trying before with a legacy PCL project since I thought mongame was not Net Standard yet.
When I tried to compile I got
System.IO.FileNotFoundException: 'Could not load file or assembly
SharpDX, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1'.
The system cannot find the file specified.'
This is the original error I got when I just did File -> new project, which is what made me try using the nuget package instead. When I installed the nuget package I got the original error I posted about.
I then removed the nuget package and edited the UWP project .csproj file as you mentioned above:
<PackageReference Include="MonoGame.Framework.WindowsUniversal" Version="3.7.0.7">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
This finally worked. So a couple of questions:
Can that guide be updated for how to create a UWP project.
Can the MonoGame NetStandard Library please be added to the mono game templates for Visual Studio?
Can the UWP template be fixed so it works out of the box?
Can the nugget packages be fixed to work with PCL? So that the .csproj file doesn't have to be manually edited?
Thanks
Can the nugget packages be fixed to work with PCL? So that the .csproj file doesn't have to be manually edited?
No, it cannot, they changed how resolution of dependencies works so some older projects that use PCL bait and switch approach are broken. Also PCL is dead, long live .NET Standard (Also you should be able to set the flag in Visual Studio property viewer).
Can that guide be updated for how to create a UWP project.
Can the MonoGame NetStandard Library please be added to the mono game templates for Visual Studio?
Can the UWP template be fixed so it works out of the box?
I wrote the guide for VS Code, and you can just swap mgdesktopgl for any dotnet template (like mguwp) and it will work just fine.
I won't be doing any additions to the normal Visual Studio any time soon as I don't use it.
@harry-cpp how can i use directives like #if WINDOWS_UAP in .Net Standard library add by reference in desktopGl project for exemplo?