SMAPI proper check for libgdiplus existence on Linux
Patronos opened this issue ยท 4 comments
Different Linux distributions handle packaging and distributing of files and packages in different ways.
Today I ran into the problem, that one Mod (that I really liked testing) instantly hit an Exception and thus ended up being not usable. After some further investigations it came to my attention, that Fedora is one of these distributions who packaged a library in a way, that caused the SDV provided Mono libraries to not find libgdiplus.so
(please pay attention to the proper naming here). Fedora's libgdiplus rpm package provided two files that also added version numbering after the .so and thus System.Graphics.dll wasn't able to find that mandatory library and ended up crashing the Mod.
This issue of not finding libgdiplus.so
may also lead into other Mods - that rely on GDI graphics - to crash. To solve the issue I'm offering a more or less compatible solution to ensure that the libgdiplus.so file is being found AND if needed CREATED as symlink.
The patch can be found here:
LeonBlade/TreeTransplant#1 (comment)
... and applied via patch -p0 < filename.patch
. The patch has been tested on Fedora 26 but should also work on all modern Linux distributions that cover more or less new GNU toolchain.
What does the patch do (covering the lib64 subset) ?
+ if [ ! -h "/usr/lib64/libgdiplus.so" ] ; then
+ libgdiplus=`find "/usr/lib64" -maxdepth "1" -name "libgdiplus*" -type f -print | sort | tail -n "1"`
+
+ if [ "${libgdiplus}" == "" ] ; then
+ echo "please install libgdiplus package from your distro!"
+ exit
+ else
+ ln -sf "${libgdiplus}" "libgdiplus.so"
+ fi
+ fi
Line1: The if clause checks for a symlink called /usr/lib64/libgdiplus.so. If this is found then the entire clause is being skipped and the game proceeds normal loading. I test for symlink (-h) here, because I assume that libgdiplus.so is a symlink... Please note that this can also be a file - which is not covered by that if clause... It then won't find a symlink and proceeds with the inner execution.
Line2: We assume that we weren't able to find the symlink in Line1 (or maybe it was just a file) - anyways, we can continue and use a crude way to determine, whether we have libgdiplus.so.0[.0.0.0.x.x.x] etc. installed. Depending on the packging guidelines and rules of said distributions. We intend finding a library called libgdiplus*
(asterix) in the top /usr/lib64 directory (-maxdir "1") have it a type file (-type f) and print the results. The sort afterwards ensures sorting multiple finds (which most likely won't be the case) and have the last element in the list found (tail -n "1"). This is most likely the real file and not a subset of symlinks to the real file.
Line 3: empty
Line 4: We test whether the variable libdiplus received some finds... (the find before returns its finds in that variable). If it finds something, then proceed with Line 8. Otherwise continues with Line 5.
Line 5: We didn't find any variation of the name libgdiplus*
and therefore assume that libgdiplus is missing entirely. We inform the user (in case the StardeValley script is launched through a terminal) that he/she is missing the mandatory library, which may affect in nonfunctional (or malfunctional) Mods. If the user won't see a terminal (which is most likely, if started through an icon), then he/she won't see anything.
Line 6: We enforce an explicit exit
and disallow further execution of SDV... It may be required to re-think the exit line and have it removed optionally.
Line 7: Else statement
Line 8: Enforce creation of a symlink inside the game directory based on the returned finds of the find command. This will create the correct named libgdiplus.so
symlink.
Further thoughts:
It might be interesting to investigate into Mono itself, whether Mono itself requires a strict naming convention of the *.so file. If this is the case then it may be interesting to file a bugreport in https://bugzilla.redhat.com to inform the package maintainer of libgdiplus or Mono to correct the issue. But this can also be a strict issue inside SDV depending how the Mono interpreter was compiled (and how the rules of said distribution it was created with are).
The script is working but can of course be optimized for strict or better testing.
@Patronos Is this only an issue with Fedora? I'm a bit wary of heuristically detecting libgdiplus.so
. One option is to add libgdiplus-devel as a requirement on Fedora, and have the SMAPI installer warn if it can't find libgdiplus.so
. That keeps the launcher simpler, but also makes it clearer to players how to fix the issue.
I thought about this for quite some time now, but had other things to do in the meanwhile...
Well... It's not just an issue with Fedora but also with SuSE. I ten'd to say that this is related to all *.rpm based distros.
What I figured out was this: *.deb (debian) based distros do have the symbolic link inside the main package (libgdiplus) but on *.rpm (red hat) based distros the link is separated into the libgdiplus-devel package. We are lucky that this particular libgdiplus-devel package doesn't trigger a rats tail of other dependencies.
I would vote that the installation document may extend the requirements part as described above. But I can't say how Arch or Gentoo handles this. Most likely they install all requirements automagically after compiling or how they handle it in their package managers...
So basicly: Forget about my patch, because I wasn't aware of the particular requirements of the *-devel package (and it wasn't mentioned anywhere either) and extend the documentation that *.deb based distros such as debian or ubuntu only requires the package libgdiplus.so to be installed (or mono as a metapackage) and that *.rpm based distros such as fedora, rhel, centos, suse needs aditional libgdiplus-devel to be installed (for that plain silly symlink).
Looks like this issue has been reported a 2016 already but they decided a different approach in "fixing" it. But it looks like this only works if they offer their own Mono subset. If Mono related games come with their own dll libraries then these libraries of course expect the strict naming and end up in exception throwing. I just commented to the bug below. If more Mono based games show up on Steam (and most likely compiled on other distributions) then we may get more of these exception throwing... Just a guess though...
I have no current plans to change SMAPI for this, so I'll close it as won't do. Might be useful to document the issue on the player troubleshooting page though, and pull requests are still welcome if needed.