ngld / old-knossos

A mod launcher/installer for FSO
https://fsnebula.org/knossos/
Apache License 2.0
58 stars 23 forks source link

SDL2 MacOS loading issue #197

Open chief1983 opened 4 years ago

chief1983 commented 4 years ago

Even though the Mac builds now build and run again, there may be an issue with the SDL2 integration now. When opening the settings, this is in the log:

Traceback (most recent call last):
  File "/Users/travis/build/ngld/knossos/knossos/clibs.py", line 129, in init_sdl
  File "/Users/travis/build/ngld/knossos/knossos/clibs.py", line 92, in load_lib
Exception: ../Frameworks/SDL2.framework/SDL2 could not be found! (Failed to load dynlib/dll '../Frameworks/SDL2.framework/SDL2'. Most probably this dynlib/dll was not found when the application was frozen.)
DEBUG:Thread-12:base.send_remote: Sending message of length 824 to https://sentry.gruenprint.de/api/9/store/
DEBUG:raven.AsyncWorker:connectionpool._new_conn: Starting new HTTPS connection (1): sentry.gruenprint.de:443
DEBUG:raven.AsyncWorker:connectionpool._make_request: https://sentry.gruenprint.de:443 "POST /api/9/store/ HTTP/1.1" 200 None

MacOS 10.15.5 Knossos 0.14.1

chief1983 commented 4 years ago

I double checked, and the 0.13.3 build does not have this error when loading the settings, however the SDL2.framework is in the same place inside the .app bundle. The SDL2 version is different but I don't think that should keep it from loading as it should match what was present when the app was built.

ngld commented 4 years ago

It actually doesn't matter against which SDL2 version the app is built since it's not really compiled. The PyInstaller script just copies the SDL2 framework inside the app bundle and that's loaded during runtime with Python's ctypes module which is just a wrapper around dlopen() and dlsym().

If you open the SDL2 framework, do you see the SDL2 symlink? Does it point to a file that exists?

EDIT: I just looked at the Knossos DMG. Looks like all the symlinks inside SDL2.framework have been resolved which would explain the issue. The actual SDL2 file (which should be in SDL2.framework/Versions/A/SDL2) depends on hidapi.framework. It's probably linked with a relative path which doesn't work if SDL2 is moved outside the A folder. Loading SDL2 fails with a file not found error so ctypes assumes that SDL2 could not be found while in reality the hidapi framework is the issue.

Angairi commented 4 years ago

Hello chief1983,

I contacted you about this issue on discord some weeks ago. I also happen to be a software developer, and I noticed that even though Knossos 0.14.3 came out, the issue of broken Knossos on macOS is still present for new installs and reinstalls.

I did some of my own debugging work and I have found the cause of the game not running, and it IS due to SDL2 pathing issues. I have 3 comments:

Comment 1: In $HOME/Library/Preferences/knossos/settings.json, FS2 opens correctly when key/value pair "sdl2" = "/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/Versions/Current/SDL2"

The Knossos install/reinstall function is not figuring out this relative pathname, or is not writing it to the settings.json file.

In fact, variable "sdl2" was empty in the settings file when I opened it. Obviously, this causes a problem when loading SDL2.

The Knossos installer needs to write the correct value (above) to the settings.json file in order for the game to launch, and that is assuming that the user has placed Knossos.app in /Applications.

FYI, my library path is "/Users/Shared/Applications/FS2Open".

Comment 2: The SDL2 framework should be installed in "/Library/Frameworks" on macOS. I would tend to avoid bundling it with the executable unless the developers have absolutely no other option.

It should be OK to include a zip file with the framework that unpacks to this location, but this is something you should ask the user for permission to do.

Comment 3:

For Mac users with scaled display resolutions, the Knossos UI is heavily pixelated. Just as FS2 allows a selection of Video resolution settings, I would allow a selection of settings for Knossos.


These suggestions are all informal.

Thank you for reading, and happy coding! Angairi

chief1983 commented 4 years ago

Sorry I missed the mention. Sounds like useful info, although we have tried to make these bundles as monolithic as possible so users don't need to install their own dependencies. The previous release, 0.13.x, was working fine with this method as well, so something seems to be getting done differently now, I would think.

ngld commented 4 years ago

In $HOME/Library/Preferences/knossos/settings.json, FS2 opens correctly when key/value pair "sdl2" = "/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/Versions/Current/SDL2"

Do you mean sdl2_path? The sdl2 key isn't used. What happens when you set sdl2_path to /Applications/Knossos.app/Contents/Frameworks/SDL2.framework/SDL2?

The Knossos install/reinstall function is not figuring out this relative pathname, or is not writing it to the settings.json file.

In fact, variable "sdl2" was empty in the settings file when I opened it. Obviously, this causes a problem when loading SDL2.

This is expected behavior. There is no installation process. You simply copy the .app folder from the .dmg to your /Applications folder (you can actually put it pretty much anywhere and it'll still work). The setting can be used to disable Knossos' SDL2 auto-detection and override it with an explicit path. If the key is empty, Knossos tries to load the bundled SDL2 framework. Apparently, the path it uses for that doesn't work anymore. See my earlier comment for a guess as to why.

The Knossos installer needs to write the correct value (above) to the settings.json file in order for the game to launch, and that is assuming that the user has placed Knossos.app in /Applications.

The game actually doesn't care about this setting at all. FSO doesn't launch when Knossos can't load SDL2 due to issues with Knossos' handling of joysticks.

Comment 2: The SDL2 framework should be installed in "/Library/Frameworks" on macOS. I would tend to avoid bundling it with the executable unless the developers have absolutely no other option.

This is not an option. The various SDL2 releases are incompatible with each other and all are versioned as A in the framework. Bundling SDL2 with Knossos ensures that we use a version that works as expected. Note that FSO itself also bundles SDL2 as such it's more consistent to bundle SDL2 with Knossos as well. Bundling SDL2 with FSO is once again necessary since different FSO versions are built against different SDL2 releases and thus can't use Knossos' SDL2 copy.

For Mac users with scaled display resolutions, the Knossos UI is heavily pixelated. Just as FS2 allows a selection of Video resolution settings, I would allow a selection of settings for Knossos.

This is a known issue (on Windows as well). Adding video resolution settings is not an option due to the way the UI is rendered. We need to properly implement Qt's support for HiDPI / retina to fix this. However, I don't have a retina (or HiDPI) display and thus can't test it.

Angairi commented 4 years ago

From Comment 1:

Do you mean sdl2_path? The sdl2 key isn't used.

Sorry, you are correct. I meant the sdl2_path variable.

What happens when you set sdl2_path to /Applications/Knossos.app/Contents/Frameworks/SDL2.framework/SDL2?

If this sdl2_path is provided, Knossos' error log reports:

ERROR:Thread-13:clibs.init_sdl: Failed to load user-supplied SDL2! Traceback (most recent call last): File "/Users/travis/build/ngld/knossos/knossos/clibs.py", line 121, in init_sdl File "/Users/travis/build/ngld/knossos/knossos/clibs.py", line 92, in load_lib Exception: /Applications/Knossos.app/Contents/Frameworks/SDL2.framework/SDL2 could not be found! (Failed to load dynlib/dll '/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/SDL2'. Most probably this dynlib/dll was not found when the application was frozen.)

Freespace does not start. Further, the "Save" button in the settings (gear) page gets stuck on "Loading..." when the app is opened.

I downloaded the source code and located the line in clibs.py that is responsible for loading the library. The error messages are coming from (roughly) line 119 onward.

The try block starting on line 120 throws an exception if sdl2_path is empty. ctypes.py attempts another strategy to load SDL2 on line 127. This is the exception I saw when I originally mentioned this problem to chief1983 on Discord. The applicable code is:

sdl = load_lib('../Frameworks/SDL2.framework/SDL2')

This path is hard-coded into the Knossos binary. Freespace does not start if this line is executed.

Thus, the only way I can get the binary to run is by setting the sdl2_path in settings.json to

/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/Versions/Current/SDL2

Thereby avoiding the execution of the code on line 127.

The required version of the SDL2.framework links via the "Current" branch of that framework. For example, various versions can be incorporated into a framework, but they have a structure of "A", "B", "C", etc. The "Current" branch is a symbolic link to the default version of the framework for an application, or "A" for Knossos.

This means that "/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/Versions/Current/SDL2" is the organizationally correct path for the active SDL2.framework. That said, there is only one version of the framework ("A"), so "/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/Versions/A/SDL2" loads exactly the same library as does the "Current" version.

From Comment 2: Duly noted.

From Comment 3: That's OK. When you are able to upgrade to a new monitor, the community can revisit this issue.

Angairi commented 4 years ago

I will add one more tidbit:

If the "../Frameworks/SDL2.framework/SDL2" path is working for you, there is very likely a linking error occurring after compilation. The correct path for the SDL2 library should be:

"/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/Versions/Current/SDL2"

This is probably why you see one set of responses and people not involved in the development see another.

If you change ctypes.py's relative path on line 127 to:

"../Frameworks/SDL2.framework/Versions/Current/SDL2"

Knossos might function as expected. I don't have all the dependencies installed, so I can't test this with my own build. In any case, you definitely won't break the program by changing that line to point to the SDL2 binary at the conventional location.

To clear up some confusion, here is what a Framework structure should look like:

Correct Framework Structure

and here is the SDL2 Framework packaged with Knossos.

Packaged SDL2 Framework

This structure explains why the sdl2_path "Frameworks/SDL2.framework/SDL2" isn't working as expected. In this case, go with the full path name for any library calls, i.e.

"/Applications/Knossos.app/Contents/Frameworks/SDL2.framework/Versions/Current/SDL2"

chief1983 commented 4 years ago

That structure also makes me wonder if the copy somehow turned the symlinks into duplicate files, unnecessarily inflating the size, instead of leaving them as relative symlinks. The folders in the second image are not displayed indicating they are symlinks, but they should be.

chief1983 commented 4 years ago

Just confirmed, the SDL2.framework in the app bundle is 10MB but the one in my user's Frameworks folder that uses symlinks is only 1.4MB. However, I don't think that's the cause of the problem because 0.13.3 had the same problem, and didn't have any SDL2 issues.

spacecowgoesmoo commented 3 years ago

Just wanted to call some extra attention to this issue. Unless I misinterpreted something when trying to getting this to work a couple months ago, it's making the game unplayable on Mac OS.

Angairi commented 3 years ago

Thank you for checking up on this issue.

The game can still be played, but the settings.json file needs to be edited manually before the game will run.

I have also needed to edit the path to the FSO executable in "Knossos > [Campaign] > Details > Options > FSOSettings > FSO build " to reference (note: short-hand path notation follows) “$FS2OPEN_DIR/bin/FSO-version/macosx/FSO-version.app/Contents/MacOS/FSO-version"

I am an engineer, so I know how how to tinker with all types of software—for normal users, the game is unplayable.

I have also noticed that my settings.json file is about half a megabyte after downloading a few campaigns, so text editing this file eventually becomes impractical.

Let me know if you need more information.

On Sep 23, 2020, at 9:06 PM, Taylor Calderone notifications@github.com wrote:

Just wanted to call some extra attention to this issue. Unless I misinterpreted something when trying to getting this to work a few weeks ago, it's making the game unplayable on Mac OS.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ngld/knossos/issues/197#issuecomment-698098624, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLDD5VDSJ6AJAYBNBKOKRDSHLASVANCNFSM4NONISEA.

spacecowgoesmoo commented 3 years ago

Progress made, documented for others:

It's now logging this in the Console whenever I hit the play button. Still doesn't launch anything.

default 19:58:00.427777-0700    mDNSResponder   [R8239] DNSServiceQueryRecord(1D000, 0, <private>, Addr) START PID[8584](Knossos)
default 19:58:00.618097-0700    mDNSResponder   [R8239] DNSServiceQueryRecord(1D000, 0, <private>, Addr) STOP PID[8584](Knossos)
default 19:58:00.619556-0700    mDNSResponder   [R8240] DNSServiceQueryRecord(1D000, 0, <private>, Addr) START PID[8584](Knossos)
default 19:58:00.620018-0700    mDNSResponder   [R8241] DNSServiceQueryRecord(1D000, 0, <private>, AAAA) START PID[8584](Knossos)
default 19:58:00.620383-0700    mDNSResponder   [R8240] DNSServiceQueryRecord(1D000, 0, <private>, Addr) STOP PID[8584](Knossos)
default 19:58:00.620424-0700    mDNSResponder   [R8241] DNSServiceQueryRecord(1D000, 0, <private>, AAAA) STOP PID[8584](Knossos)
Angairi commented 3 years ago

FYI: You should not edit the json file while Knossos is running. Knossos must be closed or it will overwrite any custom configuration on exiting.

On Sep 24, 2020, at 8:12 PM, Taylor Calderone notifications@github.com wrote:

Progress made, documented for others:

Edited the JSON as directed. This resets itself back to null anytime I close the Knossos app. Changed the FSO executable as directed. The OS fights this a little, you have to navigate into the package using another Finder window and then drag it into the file selector. Installed Freetype with Brew, because it was giving me missing library crash errors. Some previously blank menus in Knossos now have text in them. It's now logging this in the Console whenever I hit the play button. Still doesn't launch anything.

default 19:58:00.427777-0700 mDNSResponder [R8239] DNSServiceQueryRecord(1D000, 0, , Addr) START PID8584 default 19:58:00.618097-0700 mDNSResponder [R8239] DNSServiceQueryRecord(1D000, 0, , Addr) STOP PID8584 default 19:58:00.619556-0700 mDNSResponder [R8240] DNSServiceQueryRecord(1D000, 0, , Addr) START PID8584 default 19:58:00.620018-0700 mDNSResponder [R8241] DNSServiceQueryRecord(1D000, 0, , AAAA) START PID8584 default 19:58:00.620383-0700 mDNSResponder [R8240] DNSServiceQueryRecord(1D000, 0, , Addr) STOP PID8584 default 19:58:00.620424-0700 mDNSResponder [R8241] DNSServiceQueryRecord(1D000, 0, , AAAA) STOP PID8584 — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ngld/knossos/issues/197#issuecomment-698696118, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFLDD5TXBOIUY2WPF7UE3OTSHQDCRANCNFSM4NONISEA.

spacecowgoesmoo commented 3 years ago

That got it! I edited the JSON again with the app closed, the settings persisted and the game launched <3

chief1983 commented 3 years ago

I have no idea what you guys are talking about. The game runs fine for me without any extra work, the only issue is that the joystick detection in Knossos isn't working because that relies on SDL2. Everything else is working fine for me. I did have to install freetype with Homebrew as mentioned, but other than that, it's been stable. I just ran the latest nightly that just got added to Knossos (not listed on forums yet, didn't post, still working out kinks on the new HLP server).