Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSFML NuGet Package not Compatible with .NET Framework Apps #174

Closed
eXpl0it3r opened this issue Nov 22, 2019 · 13 comments
Closed

CSFML NuGet Package not Compatible with .NET Framework Apps #174

eXpl0it3r opened this issue Nov 22, 2019 · 13 comments
Labels

Comments

@eXpl0it3r
Copy link
Member

eXpl0it3r commented Nov 22, 2019

Steps to Reproduce

  • Create a new Console App project with .Net Framework 4.6.1 or newer (.Netstandard 2.0 compatible)
  • Install the SFML.Net NuGet package
  • Write some SFML code (e.g. the example from the docs)
  • Build & Run the application

Actual Behavior

The application is throwing a DllNotFoundException because the CSFML DLLs were not installed.

Expected Behavior

The application launches without any DllNotFoundExceptions.

Workarounds

Copy the needed DLLs from the local package directory next to your executable

Next Steps

  • Analyze why the CSFML DLLs are not installed at all when using a .NET Framework project
  • Fix the issue
@eXpl0it3r eXpl0it3r added the Bug label Nov 22, 2019
@DemoXinMC
Copy link
Contributor

I will start attempting to devise the why and the solution to this, as we've had quite a few people come to us with this problem.

But I do have to be a conscientious object here, also... I think that we should really be moving people away from working against Framework. At this point, it is considered by the .NET Foundation to be legacy. While I don't think that we're directly shooting people in the foot by simplifying .NET Framework app creation, we are sort of handing them the gun, so to speak.

@charleyah
Copy link
Contributor

charleyah commented Nov 23, 2019

Regards to the issue, I'm pretty sure it's because .NET Framework projects have no recognition of native runtime targets given it originally designed for Windows. But i'm no Nuget expert so this is mostly a hunch.

With .NET Framework 4.8 being the last major update, I think it will be on life support by Microsoft once .NET 5 is released next year. So I think it makes sense to consider moving away from .NET Framework.

Maybe a new version of SFML.NET that targets .NET Standard 2.1 that explicitly no longer supports Framework.

@DemoXinMC
Copy link
Contributor

There's no reason to actively prevent people from using SFML.NET with Framework. The code is compatible with netstandard2.0, but I wonder if we're really making the best decision by spending time enabling it out of the box. I sort of feel that people who really want to work on .NET Framework should at least be able to manage setting their SFML.NET up for it, considering that it's really just moving a few files around.

@charleyah
Copy link
Contributor

charleyah commented Nov 23, 2019

My suggestion on .NET Standard 2.1 is mostly because keeping SFML.NET on Standard 2.0 does restrict the library from potentially benefitting or supporting some of the newer things available like Span in the future. Wasn’t with intention to lock out Framework users and more suggesting of maintaining an older version in future, but I understand thats a whole different subject for another time.

I would agree. From personal experience .NET Framework projects with native dependencies have had them added as project files in the simplest cases and used a MSBuild script for most complex cases. In this case its no more than what might of been done before Nuget, I guess it was more expecting the package manager to just work. If desired I can sort out a beginner proof bullet point guide on the workaround if a fix isn't sorted out.

@eXpl0it3r
Copy link
Member Author

.NET Standard 2.0 is not something set in stone, but as long as we're not using any .NET Standard 2.1 features, there's no point in making it incompatible. Either way, this discussion is kind of unrelated to the issue at hand.

There's no point in trying to play "tech stack police". If people want to (or have to) stick with .NET Framework, it's not our place to judge them and actively make it harder to use SFML.Net.
Of course that doesn't mean we should move heaven and earth just to get this usability improvement in.

If there's no easy solution, I'm also fine with providing some instruction either through NuGet or within the package, so those installing it on .NET Framework will at least know how to workaround it.

@Balnian
Copy link

Balnian commented Dec 2, 2019

Hey, I was part of the migration from .net framework to .net standard 2.0 . We never intended to lock out anyone from using sfml.net by doing that move. The reason for that move was to have a native support of mac/linux without requiring Mono. And the fact that people could still use .net framework was an argument to allow the change to go through. Like @eXpl0it3r said as long as we don't need 2.1 feature we should stay as stable as possible (if we start becoming a moving target people might not want to start a project with us, because it will mean having to constantly update their projects to keep up with the new release).
Also the fact that we did deprecate some support of .net framework with that move should be considered an exception and not a precedent to allow further deprecation

@charleyah
Copy link
Contributor

charleyah commented Dec 2, 2019

I don’t want to perpetuate the incorrect subject I accidentally brought up here but I just want to clarify.

I totally understand why SFML is sticking with .NET Standard 2.0 to support an existing user base as frictionless as possible. I’m a Framework user myself and I will be jumping to Core in the near future, but would like to benefit from what Core can offer in places for the API that are available under 2.1 which when I get around to, I intend to add to a folk.

I understand what’s being said and accept I was abit brash and ahead of myself to make the suggestion. Apologies for the derailing.

@Balnian
Copy link

Balnian commented Dec 3, 2019

So apparently the fix is to add a \build\net462\ path to csfml nuget containing a .props and .targets that will add the right dlls (copy them) to the output path.
I don't have enough time to do the fix right now, so anyone feel free to experiment and implement the fix.
Source:
https://stackoverflow.com/questions/56154884/nuget-package-not-copying-native-dlls-on-build
that will lead you to:
https://docs.microsoft.com/en-au/nuget/create-packages/creating-a-package#include-msbuild-props-and-targets-in-a-package

@CoolDadTx
Copy link

The MS team has specified that NetFx does not work properly with NuGet packages that contain native/runtime assets. The issue is a bug in the core SDK that handles this. NuGet has to evaluate the runtime graph to determine what folder(s) to copy. NetFx projects do not have the runtime graph logic and therefore, currently as of 3.1, will not work properly.

The current workaround for projects that target NetFx and require that runtime/native DLLs be copied is to add the Microsoft.NetCore.Platforms package to the NetFx project. This package is just a file that contains the necessary runtime graph logic needed to get NuGet working. Adding this to your project, ensuring that you set the RID in your project file (might be optional) and then rebuilding will get the native DLLs copied. However I don't know if this follows through to dependent projects. I ended up adding CSFML to my NetFx console app with the RID in the project file and it copies the binaries just fine now.

@Davipb
Copy link
Contributor

Davipb commented Dec 31, 2019

I don't think this is an issue with the .NET Framework itself, but rather with the "Any CPU" Platform.
If you change the Platform to x64 or x86, the (correct) CSFML DLLs will be copied to the output directory as expected.

When creating a framework-dependent .NET Core application (which would be the closest equivalent of 'Any CPU' for .NET Core), all the native DLLs are copied to a runtimes folder and referenced in the .deps.json file.
The .NET Core host then reads that JSON and loads the appropriate DLL based on the current platform (OS and CPU Architecture) at runtime, automatically.

I don't think the .NET Framework host has anything similar (I couldn't find anything online, at least), so that would have to be done manually: Before calling any native methods, locate the correct CSFML DLL and load it with a P/Invoke to kernel32::LoadLibrary.

Given that the .NET Framework is being superseeded by .NET 5, however, it would be easier to add a .props/.targets that generates an informative error message when "Any CPU" is used. Something like "CSFML doesn't support 'Any CPU'. Consider using .NET Core instead, or switch to x86/x64".

@bobasaurus
Copy link

There are many of us still using .NET framework (4.8 will be here to stay for a long time), and having the nuget package silently fail and having to delve deep into old forums like this is frustrating. I even tried copy pasting the csfml dlls myself from a downloaded zip and it didn't work, but changing the build from any cpu to x86 or x64 made the cfsml dlls copy and work just fine.

@hawkerm
Copy link

hawkerm commented Dec 26, 2022

Mentioned on the other issue here:

It's fairly straight-forward to multi-target for .NET 6 and .NET Standard 2.1 to get those benefits, but then keep support for .NET Standard 2.0 by including the System.Memory package when running there, see this example: https://github.com/CommunityToolkit/dotnet/blob/main/src/CommunityToolkit.Diagnostics/CommunityToolkit.Diagnostics.csproj

There's also projects like https://github.com/Sergio0694/PolySharp to help as well.

i.e. it's still possible to write with many modern language features and use Span while maintaining support for .NET Standard 2.0 still.

@eXpl0it3r
Copy link
Member Author

With the changes done in SFML/CSFML#159 and SFML.Net 2.5.1 having been released, I gave this another try.

After adding SFML.Net to a .NET Framework 4.8.1 project, I get as expected the following error:

CSFML.targets(5, 9): CSFML doesn't support 'Any CPU' on the .NET Framework. Consider switching to .NET Core. If this is not possible, change your platform to x64 or x86, or set the MSBuild property 'CSFMLIgnoreAnyCPU' to true and manually load the appropriate native library at runtime.

Switching to x64 fixes the issue and the test application builds.

But then as expected, running the application fails with the error:

Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'csfml-graphics': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

As the CSFML DLLs aren't being copied.


Maybe there's a way one could package the CSFML DLLs in the right spot of have some target file copy them, but in my opinion the time has passed for .NET Framework and I personally don't want to invest more of my time into such edge cases. SFML still works with .NET Framework, but you just have to copy the CSFML DLLs manually to your output directory. That seems to me like a good enough workaround.

Having said that, I'll close the issue. If you have an (easy) solution to the problem, I'm more than willing to re-open it and accept it. I just don't want to spend my time figuring this one out.

@eXpl0it3r eXpl0it3r closed this as not planned Won't fix, can't repro, duplicate, stale Jun 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants