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

Prioritize system libraries on linux SDL backend (fix build-related issues on linux) #160

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Arastais
Copy link

@Arastais Arastais commented Jan 8, 2024

This PR reworks the build system for Arc on Linux to essentially only use system libraries and no longer use pre-bundled library files. Along with the many advantages of using the system libraries on Linux, this PR generally improves the overall experience on arc-based games on Linux (i.e. mindustry) and fixes some build issues (more on that later).

Specifically, in this PR:

  • The pre-bundled libSDL2.so (i.e. the SDL library) has been removed. Arc links to the system's SDL instead. When included in the mindustry jar, the included libSDL2.so is specifically used instead of the system SDL. Without any library file in the jar, mindustry uses the system SDL, which is definitely better suited. The most obvious advantage is that now the user/system has control over how SDL is configured.
  • The system glew library is linked to, instead of downloading and building a separate instance of glew in the gradle build from source without any extra compile flags. The glew source files have many different possible compilation flags (mainly macros), so it's preferable to use the system's glew. Much like with SDL, the system/user now controls the compilation flags and configuration, not arc itself.
  • The pre-bundled libsdl-arc64.so is removed. Instead, it is generated using the system libraries (namely SDL and glew as mentioned before). The generation task is also now a dependency for the Arc jar; This forces the Arc library file to be generated using the system's libraries on Linux during the build process for Arc. This makes sure the sdl backend is generated before being bundled and thus prevents a pre-bundled version of Arc to be included.

Using the system's libraries is preferred (at least on Linux). I personally think this is especially true on linux since different users and distros/package managers may have a differently configured version (or a different version altogether) of the same library.

As an example, this PR inherently adds wayland support to Arc and thus fixes Anuken/Mindustry#1393/Anuken/Mindustry#8705 with no actual changes to mindustry's source code, simply because Arc is no longer using pre-bundled libraries with a fixed configuration. (wayland support in mindustry had become broken again with the regression in 3928486, since it removed the option of dynamic natives in the backend-sdl build.gradle); Similarly, this also fixes #131, which is an issue I was personally having before this PR - Arc wasn't using my system's specific version of glew with patches/configuration from my distro's package manager. Since arc now links to the systems libraries, users with a glew compiled with SYSTEM=linux-egl and a properly configured SDL can now just run mindustry under native wayland with no other configuration and no changes to mindustry itself. This PR may solve many other current and future runtime and build related issues on Linux, although it may not be immediately obvious as all issues on the mindustry repository are marked as resolved.

In general, it is a very good idea to use the system's libraries when building arc on linux, and to simultaneously make sure that no pre-bundled library files are used.

@Anuken
Copy link
Owner

Anuken commented Jan 8, 2024

This forces the Arc library file to be generated using the system's libraries on Linux during the build process for Arc.

This is not a good idea. Anyone using Arc on Linux - most notably, me - will now be forced to sit through a (mostly irrelevant) native compilation phase every time they clone or clean the project. I don't know how good Gradle is at detecting whether the natives task is up to date, either; it's highly unlikely to happen only once, based on my experience.

What's more, if someone wants to make a PR for Arc - and very few involve touching the SDL backend - they'll now need to install various packages needed for compiling these native libraries every time they wish to do so.

The pre-bundled libSDL2.so (i.e. the SDL library) has been removed. Arc links to the system's SDL instead.

This is an even worse idea. Many systems don't have SDL2 installed, which is why it's bundled. It is not reasonable to expect people to install packages to play a game.

@Arastais
Copy link
Author

Arastais commented Jan 8, 2024

Anyone using Arc on Linux - most notably, me - will now be forced to sit through a (mostly irrelevant) native compilation phase every time they clone or clean the project.

I assume that by "mostly irrelevant", you mean that compiling the natives is an irrelevant and thus not worth it. Regardless, i would strongly argue that compiling at build time and per-system is not irrelevant at all. In fact, personally, mindustry wasn't running at all for me until this PR, neither on X11/Xwayland nor native wayland, regardless of what version of mindustry I used; I would get some variant of a GLEW failed to initialize error (similar to #131, but even on X11/Xwayland) due to incompatibilities between the pre-bundled glew Arc uses (which isn't configured properly for my system) and my proprietary nvidia drivers. This was immediately resolved by linking to the glew on my system (which is maintained by my distro's package manager and thus configured properly, e.g. with egl) instead of using a glew built from source and pre-bundled within the Arc library.

The benefits you gain from using system libraries and compiling the library per-system (e.g. using native compilation flags) definitely outweighs any extra compilation time (which is most likely less than 30 seconds on any modern system anyway). Not to mention, it's only compiled if the library file doesn't exist in the first place, so you only have to do it per clone or clean like you said.


I don't know how good Gradle is at detecting whether the natives task is up to date, either; it's highly unlikely to happen only once, based on my experience.

Like I just mentioned, it seems gradle will only compile Arc if the libsdl-arc64.so file is missing and the :jar task is run (e.g. when mindustry calls the backend-sdl Arc module), since the jar task now calls the jni generation task for linux. So, like you mentioned, it will get compiled once Arc is cloned when building mindustry, or if the :jar task after a clean.


What's more, if someone wants to make a PR for Arc - and very few involve touching the SDL backend - they'll now need to install various packages needed for compiling these native libraries every time they wish to do so.

This was actually an issue I greatly considered when writing this PR. This is why specifically the :jar task has the jni generation task on Linux as a dependency and not the :compileJava task for example. My intention with this was so that someone who is just compiling or testing Arc (i.e. runs the :compileJava task or ./gradlew test) doesn't need to compile the sdl backend file itself; only when the backends:backend-sdl Arc module is called (e.g. in mindustry's :desktop task) or if the task is run explicitly does the sdl backend library file get compiled. You can even see this in action in this PR's very own CI - ./gradlew test even calls :backends:backend-sdl:compileJava, but the jni generation task is never called and thus the library file isn't compiled.

Regardless, the only packages a developer would theoretically need is glew and sdl. I believe it is extremely likely that a developer on linux would especially have both glew and sdl on their system.


Many systems don't have SDL2 installed, which is why it's bundled. It is not reasonable to expect people to install packages to play a game.

I would think this isn't the case; Linux's library ecosystem isn't like that of Windows in where all third part library files need to be bundled separately and with the application itself. SDL and glew are a common dependency of many packages regardless of the package manager, so I feel it is quite likely that the average linux user would already have SDL and glew installed.

It's important to note that this only concerns users who directly download binary versions of linux mindustry (e.g. from github releases or itch.io) The versions of mindustry from a package manager (e.g. AUR or flathub) could just have SDL and glew listed as a dependency (and it would be very easy to do so) so that anyone installing mindustry from a package manager will automatically have SDL and glew installed. Steam on linux (or more specifically, the steam runtime) comes with SDL, so anyone running mindustry through steam couldn't have this issue either. Thus, this issue can only even happen in the first place to users who use pre-compiled binary versions of mindustry.

I personally think that this isn't really much of an issue, and I believe it's fine to just always use the system libraries on linux. However, I can understand if you're still concerned about users not having the required libraries on their system to run the game, and although I think it's probably unnecessary and causes more hassle, there are a few solutions for said users who download binary distributions of mindustry.

The easiest solution would be to leave package manager versions of mindustry (i.e. when mindustry is compiled from source) to be unchanged after this PR, but in binary distributions of mindustry (i.e. distributions that come with Mindustry.jar pre-compiled; e.g. the github releases or itch.io versions) add a libSDL2.so and a libGLEW.so (most likely the ones from the host system, i.e. the Ci/system mindustry is being compiled on) to Mindustry.jar. This way, someone who downloads mindustry from, itch.io for example, won't have to worry about missing libraries (but will lose out on the benefits of linking to system libraries) since it's bundled. Everyone else however will have SDL and glew on their system and thus can link their system's versions of the libraries. This could easily be done with a simple GitHub Actions step that adds the library files to Mindustry.jar after the gradle tasks have been finished, or even a separate gradle task to Arc that does this and is only called after :desktop:dist in the GitHub Actions workflow. Another solution would be to add an explicit flag (which mindustry's Actions workflow would use) to Arc's gradle build which adds said library files to the libs/linux64 folder after compilation (this would essentially be the opposite of 3a72937 - using system libraries is the default and the flag is to include pre-compiled libraries instead)

My point is that there are many solutions to this concern, but in my opinion are not worth the extra hassle. It may be better to just always use the system libraries on linux, since I think it's unlikely that a linux user will even meet the conditions to run into this issue specifically.


Overall, this isn't really a matter of debate; Using the system libraries is objectively better overall than using bundled library files and a pre-compiled version of glew, especially in terms of mindustry. I believe the benefits of using system libraries greatly outweighs any drawbacks such as having to deal with linux users maybe not having sdl or glew on their systems or any extra compilation.

@Anuken
Copy link
Owner

Anuken commented Jan 9, 2024

Using the system libraries is objectively better overall than using bundled library files

You can't simply call something "objectively" better when it has pros and cons. Saying "it's not a matter of debate" is also a bit presumptuous when there is, in fact, quite a bit to debate here.


I believe it is extremely likely that a developer on linux would especially have both glew and sdl on their system.

Strangely enough, I don't have glew installed on my current PC, despite using it for many months for game development. There simply has been no reason for me to install it, since the only application that would need it is Mindustry, and the native builds run through CI.

However, I can understand if you're still concerned about users not having the required libraries on their system to run the game, and although I think it's probably unnecessary and causes more hassle, there are a few solutions for said users who download binary distributions of mindustry.

Okay, just for the sake of argument, let's say we go your route, and skip the "unnecessary" step of bundling libraries. Let's suppose a typical user (like me!) without GLEW or SDL installed downloads the itch version of the game, and tries to run it.

What happens? Probably nothing. The game crashes, because it can't find the libraries, and the crash dialog probably won't even show up, because that's part of SDL. What do you expect the user to do in this (common) situation? Check the program output by running it through the terminal? Try to figure out what the error means? File a Github issue?

since I think it's unlikely that a linux user will even meet the conditions to run into this issue specifically.

But how is this unlikely? I have no reason to install SDL2 (and especially) GLEW unless I am specifically building the Mindustry natives. Is it really reasonable to expect every Mindustry player on Linux to have these?


Let me lay out the pros and cons, as I see them.

Pros:

  • Fixes your issue with misconfigured GLEW - which, I may note, in the many years of Mindustry's existence, has never been reported as a problem by anyone else, as far as I'm aware. Yes, you mention glewInit() called too early, fails with "Missing GL version" when used with EGL on Wayland #131, but unless the issue title is completely wrong (and was not related to method call order), that's unrelated to what you're experiencing.
  • Might fix wayland support... in some Linux packages? I'm not involved in those packages at all, so I can't say much about them. However, as far as the ones I maintain are concerned, nothing will change - it'll still bundle the same GLEW/SDL versions as used in this CI, so any issues with them will remain the same, unless I'm missing something.
  • May fix some other issues, but I have no idea if they exist or are relevant.

Cons:

  • Slower initial build times for Arc upon cleaning the project/cloning a fresh project
  • Building Arc at all now requires installing certain packages, even if you're not touching native code (I've never seen any Java project require this - and as mentioned above, even as a developer myself, I do not have all the libraries installed for it!)
    • An immediate swarm of issues of the "can't build mindustry" kind will ensue for anyone who happened to pull the latest Arc/Mindustry after this change
  • Potential regressions with loading the correct libraries (any changes in the library loading code have been notoriously flaky in my experience)
  • More code needed to load GLEW/SDL for the bundled platforms (which is not part of this PR, and will have to be written and tested separately)
  • More code needed in various CI scripts to bundle SDL/GLEW
  • Potential issues caused by differing versions of SDL/GLEW across systems due to dynamic linking
    • There have been times when I needed to downgrade SDL because of version-specific regressions
    • Reporting bugs is now more complicated, as the SDL version can be the source of problems and can differ across reports

Factoring in the time, effort, and potential issues it could cause, this doesn't seem like the "objectively better" solution to me at all.


To be clear, I'm not necessarily against loading system libraries as the first-tried option when the game runs. But I am against removing the current libraries from the repo, and making them build implicitly in any way.

@Arastais
Copy link
Author

Arastais commented Jan 10, 2024

You can't simply call something "objectively" better when it has pros and cons. Saying "it's not a matter of debate" is also a bit presumptuous when there is, in fact, quite a bit to debate here.

I apologize if I sounded rude. I probably should've worded that better.

What I mean is that in principal, it is better to use system libraries on Linux overall - remember that the native library ecosystem on Linux is quite different from that on Windows. It's just a matter of principal and practice, not just my own opinion - there are numerous benefits to using system libraries in general - hence why I said that in isolation, this doesn't have much of a debate as it's outside of the scope of this issue. What I think should be discussed is how to go about implementing this within mindustry/Arc as they stand, as I believe that is the main issue we are facing. That is why I gave a couple of solutions to how to implement this, but didn't really explain why system libraries should be used in the first place. Hopefully that all makes sense, but to help clarify even further, let me try to highlight off the top of my head some of the isolated theoretical benefits to using system libraries:

The main and critical concept behind using system libraries is that you give control of which library the program uses to the user/system. This has a cascade of benefits, including but not limited to (I'll explain these further if I need to, but I feel like I'll have explained enough for now):

  • No system compatibility/configuration issues
  • Lower chance of inter-library compatibility issues
  • The user chooses how libraries are managed (i.e. what version of a library they're using and how they're getting their libraries)
  • Reduced installation size on disk
  • Significant performance improvements from using libraries which are optimized for that specific system (e.g. compiled with -march=native)
  • Possible other runtime improvements (e.g. less memory usage)

In other words, by linking to shared libraries that are included within the same directory (or in this case the mindustry jar), I think you are partially defeating the purpose of using shared libraries in the first place; You are essentially inheriting the downsides of linking to static libraries without the actual benefits of doing so, since you're linking to shared ones but in the same directory. You may even also lose some of the benefits of linking to shared libraries (e.g. larger application size, no performance improvements, no reduction in memory footprint, etc.) since they're not truly shared anymore.


Now, keeping that in mind moving forward:

Let me lay out the pros and cons, as I see them.

I think the problem with why you don't see using system libraries as a positive solution is mainly because you didn't factor in the general benefits (see above) of using system libraries. I think I can also clarify some of the pros/cons you listed:


Fixes your issue with misconfigured GLEW - which, I may note, in the many years of Mindustry's existence, has never been reported as a problem by anyone else, as far as I'm aware. Yes, you mention #131, but unless the issue title is completely wrong (and was not related to method call order), that's unrelated to what you're experiencing.

Like I said, an advantage of using system libraries is that you eliminate compatibility and configuration issues between the library and the system. My misconfigured GLEW was just a specific but perfect example to highlight this problem.

Regardless of if the title is incorrect, the fact that this issue hasn't been reported even more highlights the problem even more in my opinion: My specific issue was unique to my rare setup (specifically, the exceedingly rare environment of running linux mindustry under a wayland DE (GNOME) and with NVIDIA proprietary drivers), which highlights that it's unlikely you can accommodate every different system configuration with how Arc is currently setup.


Might fix wayland support... in some Linux packages?

That's not entirely correct. This PR inherently adds wayland support/capabilities on all Linux platforms, 100%. Since you're linking to the system SDL, anyone with a properly configured SDL can just run any version of mindustry on wayland regardless, without any actual change to Mindustry's or Arc's source code.


Building Arc at all now requires installing certain packages, even if you're not touching native code (I've never seen any Java project require this - and as mentioned above, even as a developer myself, I do not have all the libraries installed for it!)

An immediate swarm of issues of the "can't build mindustry" kind will ensue for anyone who happened to pull the latest Arc/Mindustry after this change

Strangely enough, I don't have glew installed on my current PC, despite using it for many months for game development. There simply has been no reason for me to install it, since the only application that would need it is Mindustry, and the native builds run through CI.

As I mentioned earlier, the only time you need to have these packages install is supposed to be when you specifically need to generate Arc's library file (i.e. the :jnigenBuildLinux64 task). If you just want to compile Arc or the backend itself (i.e. the :compileJava task). Again, you can see this in this PR's CI.

However, it's critical to note that you already require SDL2 to be installed anyway for this. You use [sdl2-config](https://manpages.ubuntu.com/manpages/jammy/man1/sdl2-config.1.html), which gets information about the currently installed SDL. This PR basically does the same thing, but with GLEW now as well. I personally don't see how it makes sense how developers need SDL installed but needing GLEW installed is a problem.

The easiest solution for developers needing to install GLEW is to just have build instructions and a list of dependencies listed in Arc's README (which is basically empty right now).

But even regardless of that, a user needing SDL and GLEW to run mindustry is quite different from a developer needing them to build mindustry/Arc. Hence, I think this is it's own separate issue from the main issue at hand here; Not to mention, the best course of action for this development issue depends on how we implement linking to system libraries. Thus, I think we should figure this out after we come up with a solution for the current issue.

Here are some further comments on this, which may not be relevant (meaning they can be ignored), and don't factor in what I just said about this issue so far

I will quickly say that conceptually, I personally don't find it unreasonable for a developer to have to install libraries on their system; although you may not have seen it often in java projects, but I have seen it myself with java projects that leverage jni, and it is extremely common in many other C family languages (e.g. C#, C, C++, rust) to have library dependencies (especially when building) and thus require developers to install said dependencies on their own (via their package manager, vcpkg, conan, cargo, nuget, or whatever). That may not seem relevant, but it's important to note that you're using native C/C++ libraries (which has a significantly different ecosystem than java libraries), so I believe it applies here. Thus, I think the best solution is to just list SDL and GLEW as a build dependency in gradle if need be (so in order words, *developers* trying to build the arc library file will be notified that they need SDL and GLEW on their system to do so). The opposite alternative is to go through the process of trying to find and link to system libraries in the gradle build *first* and then use a bundled or pre-compiled version of GLEW and SDL if it can't find them in the system. This might make the CI simpler or unchanged, but this obviously requires a lot more work in the gradle build; I personally don't think it's worth the hassle just so that developers can avoid installing GLEW and SDL on their system. But of course, what solution to go with is your decision in the end.


Potential regressions with loading the correct libraries (any changes in the library loading code have been notoriously flaky in my experience)

More code needed to load GLEW/SDL for the bundled platforms (which is not part of this PR, and will have to be written and tested separately)

With the previously proposed solution of bundling GLEW and SDL on binary distributions, this isn't true. The library loading code does not need to be touched/changed at all, as you can see in the commit. By simply changing the gradle build and removing the bundled GLEW and SDL, it will load the system SDL and GLEW.

Hence:

More code needed in various CI scripts to bundle SDL/GLEW

Is true for this specific solution. However, this is only applicable on solutions in which you bundle SDL and GLEW on specific distributions and prioritize loading the bundled versions over the system ones. If that is not the case, then this issue is not applicable, and the previous one is instead.

In other words, these two previous issues are mutually exclusive (at least with the feasible solutions I can think of) depending on which solution you choose. I'll go into more detail about this below.


Potential issues caused by differing versions of SDL/GLEW across systems due to dynamic linking.

There have been times when I needed to downgrade SDL because of version-specific regressions

I actually think the opposite is true. As I mentioned at the top, using system libraries can actually lower the chance of inter-library issues. There is much less of a risk of version incompatibilities when using system libraries, and subsequently a much higher risk when using bundled libraries (but notably, regardless of what I think, there is some risk either way).

This is more theoretical, but think about what happens if GLEW gets updated or changed (which you manually update in Arc) and, since you haven't updated SDL for everyone, it breaks compatibility with the specific version of SDL you bundled (maybe even not necessarily for everyone, maybe just on certain systems/distros which you personally can't account for). Now suddenly, mindustry is broken for the targeted group of people; You would have to go in and either downgrade GLEW or update SDL and then make sure they're compatible. Hopefully this highlights how much of a hassle it is for you to personally have to manage SDL and GLEW and similarly manually have to check compatibility issues and whatnot.

By giving control to the user, you take this load off yourself. Instead of having to worry about SDL and GLEW yourself in every way manually, you can give control to the user and hence they can chose what version/configuration they want to use. If a certain system library isn't working, they can just switch versions or downgrade.

Speaking of downgrade, think about the difference between you wanting to downgrade or change out the SDL mindustry uses versus the average user wanting to the same thing. If you want to downgrade, you can either just change the library file in the git clone and build Arc (i.e. the same way any other developer would), or push a new version of the library file to upstream and change it for everyone. But what is the average user going to do? Let's say they are having similar compatibility issues due to the SDL version. I find it very unreasonable for them to understand that they need to clone both Arc and Mindustry, figure out how to change out the SDL library file within that clone, and then know gradle well enough to know how to build Arc's library file and then build mindustry, The only solution that leaves is for them to replace or delete the SDL library file in Mindustry's desktop jar, and they have to (most likely manually) do this every time they update Mindustry.

Hence, while it may be less likely that they need to downgrade their SDL when using a bundled version of it, they don't have much control to downgrade it in the first place; You're essentially the one in control of what SDL they use. In contrast, with system libraries, there may be a higher risk of specifically using a version of SDL that's incompatibility to the one Arc links to, but in that case they are in control of the SDL and thus have a much easier time changing versions. Also, critically, when using bundled library there is an (arguably greater) risk of issues from linking to an that's misconfigured or incompatible for that system - except now you can't easily change the version of the SDL because it's bundled within mindustry, as stated previously.


Reporting bugs is now more complicated, as the SDL version can be the source of problems and can differ across reports

This definitely is a valid concern, but I think it's only applicable to graphical-related issues specifically on Linux. So, hopefully the SDL version won't be needed very often, since this probably only applies to a small subset of issues.


With all that clarification, I'll lay out the pros and cons of using system libraries with Arc.

Pros:

  • All the many objective/isolated pros of using system libraries on Linux in general, as stated at the top of this comment.
  • Fixes compatibility and configuration issues between the library and the system (again, as stated at the top). My GLEW misconfiguration is just one example of this.
  • Adds wayland support
  • Reduces the possibility of future issues due to misconfiguration, incompatibility, etc. related to GLEW and SDL
  • Changing SDL or GLEW versions/configurations is much easier
  • You no longer have to worry at all about the bundled GLEW and SDL (e.g. no more having to worry about the SDL/GLEW version and compatibility)

Cons:

  • Slower (about ~30 seconds on an average system) initial build times for Arc upon cleaning/cloning
  • Compiling the Arc SDL backend library specifically now requires installing GLEW OR code needs to be added to the gradle build to link to system GLEW first, then download GLEW like before if it can't find it.
  • More code needed to load GLEW/SDL OR more code in the CI to inject pre-compiled libraries into binary distributions of Mindustry (explanation about this below)
  • Users might have to worry about changing their SDL version
  • Graphical-related linux issues on github might require users to list their SDL version.

Now for the issue at hand:

Okay, just for the sake of argument, let's say we go your route, and skip the "unnecessary" step of bundling libraries. Let's suppose a typical user (like me!) without GLEW or SDL installed downloads the itch version of the game, and tries to run it.

But how is this unlikely? I have no reason to install SDL2 (and especially) GLEW unless I am specifically building the Mindustry natives. Is it really reasonable to expect every Mindustry player on Linux to have these?

I should've worded my thoughts about this better. What I meant is that the subset of users specifically playing mindustry on Linux, without SDL and GLEW installed, and downloading specifically a binary distribution may not be very significant. Therefore (and this is what I was trying to say), I think it is worth considering/weighing whether it is worth the hassle and extra complexity to add CI code that injects pre-compiled libraries into the resulting binary, and thus choose one solution or the other based on that. I was personally weighing in favor of not adding the CI code, and just making sure that SDL and GLEW are runtime dependencies of Mindustry on every distribution platform possible.

What happens? Probably nothing. The game crashes, because it can't find the libraries, and the crash dialog probably won't even show up, because that's part of SDL. What do you expect the user to do in this (common) situation? Check the program output by running it through the terminal? Try to figure out what the error means? File a GitHub issue?

You are correct of course; It is unreasonable to expect the average to troubleshoot a missing SDL or GLEW on their system. In this case, they are essentially out luck. Like I said, the point I was trying to drive across was to question if it was worth the CI hassle for such a possibly insignificant subset of users (which could be mitigated/shrunk even further with proper dependency management). But, this isn't too relevant now, so I digress. Of course, like I've mentioned previously, it's ultimately your decision which solution to go with.


To be clear, I'm not necessarily against loading system libraries as the first-tried option when the game runs. But I am against removing the current libraries from the repo, and making them build implicitly in any way.

This is honestly the best solution in my opinion: linking to the system libraries first and only falling back to the bundled ones if the system ones can't be found. It should be a simple change, which I can just add to this PR. This should be possible with just a System.loadLibrary() call, although I have not tested it myself. I didn't propose this idea originally as I was under the impression that you were strongly against it; You mentioned in a comment in Arc's source code that you were having problems with the library loading code:

//skip dynamic load for me because it crashes otherwise

Not to mention, right before you stated you weren't against loading system libraries first, you said (emphasis mine):

Potential regressions with loading the correct libraries (any changes in the library loading code have been notoriously flaky in my experience)

Which (to me at least) implied that you are strongly against changing the library code. Regardless, I still do personally believe this is the best solution.


Let me breakdown the solutions (to the issue of how to implement system library linking on top of this PR/commit I've made) that we've come up with so far, on a basic level:

Solution Change nothing; Keep this PR as-is Inject a pre-compiled GLEW and SDL to binary distributions Link to system GLEW and SDL first; fallback to bundled
Pros
  • No changes to CI
  • No changes to library loading code
  • No changes to library loading code
  • Only one additional CI step should be required
  • No possibility of users missing system libraries
  • No changes to CI
  • Only a single addition of a System.loadLibrary() call should be required
  • No possibility of users missing system libraries
Cons
  • In some (possibly rare?) circumstances, users might not be able to run mindustry due to missing system libraries, and thus get stuck.
  • All distribution platforms would need to now require (not optional) SDL and GLEW as a dependency for Mindustry
  • Significant changes to CI code
  • Binary and source distributions of mindustry are now built differently
  • Changes to library loading code
  • May be difficult to test as a developer (since it requires uninstalling your system SDL and GLEW, which was likely installed as a dependency for another package in the first place)
  • [Optional] Where applicable, SDL and GLEW should be listed as an optional dependency for Mindustry

Note that I only listed pros and cons that are relative to the other solutions. In other words, these pros and cons are on top of the overall pros and cons of Arc linking to system libraries listed above.

Again, I think overall, linking to system GLEW and SDL first and then linking to bundled if GLEW and SDL aren't found on the system is subjectively the best solution. As I've explained, I believe the highest priority is to have the option to link to system libraries and for that to be the default; Thus, the other two solutions (and probably any other solutions we haven't considered yet) can be considered valid as well.


I'm sorry for the incredibly long response. I wanted to respond to every point you made and try to clarify my ideas better. Hopefully I didn't miss anything.

@Anuken
Copy link
Owner

Anuken commented Jan 10, 2024

I should've worded my thoughts about this better. What I meant is that the subset of users specifically playing mindustry on Linux, without SDL and GLEW installed, and downloading specifically a binary distribution may not be very significant.

Why do you assume this? I, personally, am one of those people. Anyone who uses the bleeding edge builds for Mindustry is also one of those people.

I think you missed my point earlier about GLEW and SDL installations, so I just want to make it clear: There is no reason to assume anyone has GLEW and SDL installed on their system by default. I, as a developer, do not have GLEW installed!

There are 87,410 downloads of the latest version of Mindustry on itch.io for Linux, as of this writing. This does not include those who use the bleeding edge/Github jar files. This also does not include people who downloaded earlier versions, of which there are many.

You have absolutely no reason to believe all these people have the right libraries installed. You are asking a "a possibly insignificant subset of users" (87 thousand people) to just download the game and hope (with absolutely no data) that they have GLEW and SDL installed! This is complete madness! The fact that you even suggested this as a possible course of action is utterly baffling to me.

"This guy on Github made a PR to fix his niche problem so it's not my fault your game is crashing" is not something anyone cares about when a new update suddenly broke their game. Telling someone to install packages to fix their problems would get old very quickly.

just making sure that SDL and GLEW are runtime dependencies of Mindustry on every distribution platform possible.

This simply isn't possible, nor should it be necessary.


No system compatibility/configuration issues

Lower chance of inter-library compatibility issues

The user chooses how libraries are managed (i.e. what version of a library they're using and how they're getting their libraries)

These are all essentially different variations of "it might fix some problems for someone", but I've yet to see any aside from the specific one you've pointed out in this issue, which, again, is so incredibly rare that it has taken years for anyone to bring it up. These benefits don't seem to be relevant if they don't actually fix any problems.

Reduced installation size on disk

True, but only by 1.5 MB unzipped, only when distributed through a package manager, and only on top of Mindustry's 60+ MB of code and assets. In this day and age, this is completely insignificant, especially for a game.

Significant performance improvements from using libraries which are optimized for that specific system (e.g. compiled with -march=native)

Possible other runtime improvements (e.g. less memory usage)

In my experience, -march=native does little for performance even in computation-heavy benchmarks, and I have no idea if it's even used in SDL packages at all. Even if it magically made all SDL functions complete instantly, it wouldn't matter, because SDL in Mindustry is only used as a wrapper around OS functions like creating a window. It's not the bottleneck for any operations whatsoever, and thus some tiny theoretical performance gains of using "optimized libraries" is not relevant.

Overall, I still think these benefits are still mostly irrelevant.


That's not entirely correct. This PR inherently adds wayland support/capabilities on all Linux platforms, 100%.

Yes, but this PR in its current state will absolutely not be used, and I was not referring to it when I made my claim. By linking to the system and only system libraries, you are asking (as I mentioned above) 87 thousand people to go install two libraries, or be faced with a game that doesn't start with no error popup whatsoever.

My point was that this PR would not fix wayland support if we went the initial route of linking to pre-bundled (and only pre-bundled) shared libraries for binary distributions.

As I mentioned earlier, the only time you need to have these packages install is supposed to be when you specifically need to generate Arc's library file

Any changes you make to Arc need to be tested, and to be tested, they need to be run on desktop, and to be run on desktop, Arc needs the desktop natives. If I clone the repo and try to do anything useful with it at all, I will need to compile the library file.

However, it's critical to note that you already require SDL2 to be installed anyway for this.

No, it does not. If sdl2-config is not present, the exception from the command invocation is ignored, and nothing happens.
If it really was required, I'd have gotten a lot more issues about it in this repo.

The easiest solution for developers needing to install GLEW

...is to not have it be a requirement at all. I don't think there's any reason to remove the pre-generated libraries.

With the previously proposed solution of bundling GLEW and SDL on binary distributions, this isn't true. The library loading code does not need to be touched/changed at all, as you can see in the commit. By simply changing the gradle build and removing the bundled GLEW and SDL, it will load the system SDL and GLEW.

Your code doesn't load any bundled libraries; it only loads the system libraries, and as I've pointed out above, that is not an acceptable solution. More code has to be added to extract and load the bundled libraries, which is what my point was referring to. GLEW isn't loaded or bundled at all; what happens when it is not present on the system? The game crashes.

However, this is only applicable on solutions in which you bundle SDL and GLEW on specific distributions and prioritize loading the bundled versions over the system ones. If that is not the case, then this issue is not applicable, and the previous one is instead.

I never mentioned prioritizing the bundled versions, so I'm not sure why you bring that part up, but, regardless, both problems apply.

If I want Arc to:

  • Load system libraries first, if possible
  • Upon failure, extract and load bundled libraries (yes, absolutely necessary for binary distributions)

Then I must:

  • Change CI/repo files so they are bundled (at least, GLEW, which is currently not bundled at all)
  • Change the library loading code so both are loaded from the jar file
  • Test both changes
  • Deal with any potential flakyness/bugs

There is much less of a risk of version incompatibilities when using system libraries, and subsequently a much higher risk when using bundled libraries (but notably, regardless of what I think, there is some risk either way).

Yes, but again, this risk seems to have manifested in a grand total of one issue reported here.

But what is the average user going to do?

I think, even for someone using Linux, you vastly overestimate what the average user is going to know about switching SDL versions to suit their game at all. This is such a niche use case that I don't think it's even worth considering.

I find it very unreasonable for them to...

Yes, that is unreasonable, but so is switching their SDL/GLEW version to make the game work. Software should just work without the need for people to tweak their library versions.

As I see it, your point seems to be "with this extremely specific niche problem (1 of which has ever been reported), the user will have to do something extremely unreasonable, as opposed to something moderately unreasonable".

Yes, you could say it's true, but... frankly, the real solution would be the user filing an issue, and the developer figuring out why the bundled version doesn't work for everyone out of the box. Nothing the user can do is a true "solution", it's just a workaround.


Apologies if parts of this response sounded rude, but I want to make absolutely clear that only loading system libraries is not a solution, and I do not consider any change that could conceivably break the game for existing users acceptable.


Assuming we choose the third solution (System + fallback):

Only a single addition of a System.loadLibrary() call should be required

As mentioned above, I don't think this will be enough. How will GLEW be loaded from the JAR? How will the bundled library extractor know whether to extract GLEW/SDL? How will the fallback mechanism work? This seems like quite a bit more work than just a single method call.

@Arastais
Copy link
Author

Arastais commented Jan 11, 2024

I'm going to keep my responses to this comment short, since It seems we fundamentally agree on the idea of using system libraries (and now we also agree on how to go about doing it) so it's not productive to go into depth about this; I'd like to move forward on how to implement using system libraries first with a fallback to bundled.

As an aside, this may not be to relevant now, but I just want to quickly clear up what I feel are some misconceptions and exaggerations about what I've said.

Why do you assume this? I, personally, am one of those people. Anyone who uses the bleeding edge builds for Mindustry is also one of those people.

[...]

"This guy on Github made a PR to fix his niche problem so it's not my fault your game is crashing" is not something anyone cares about when a new update suddenly broke their game. Telling someone to install packages to fix their problems would get old very quickly.

Yes, but this PR in its current state will absolutely not be used, and I was not referring to it when I made my claim. By linking to the system and only system libraries, you are asking (as I mentioned above) 87 thousand people to go install two libraries, or be faced with a game that doesn't start with no error popup whatsoever.

Your code doesn't load any bundled libraries; it only loads the system libraries, and as I've pointed out above, that is not an acceptable solution. More code has to be added to extract and load the bundled libraries, which is what my point was referring to. GLEW isn't loaded or bundled at all; what happens when it is not present on the system? The game crashes.

Apologies if parts of this response sounded rude, but I want to make absolutely clear that only loading system libraries is not a solution, and I do not consider any change that could conceivably break the game for existing users acceptable.

It seems that you are taking what I said as black and white. Like I said, I could've worded that idea better, but I never straight up assumed any of this was the case, and I tried my best to highlight that using explicit language (e.g. "possibly rare?" in the solutions table). I don't even disagree with you - I even explicitly said that the third solution (system libraries + fallback) is the best solution in my opinion, and the other two are up for debate.

I just proposed it as a possibility - one of three solutions (hence the table I made). I never said that we should for sure only use system libraries and that we should just assume everyone has glew and SDL installed since there's so few people that don't. I even said:

the subset of users [...] may not be very significant

because I don't know for sure. Again, it's up to you. You also have to realize that I don't have the numbers and download statistics that you do. Thus, I don't see how it's baffling that I proposed an alternative solution to cover all bases, since I don't have the statistical context that you do (i.e. I have no way of knowing that 87k people downloaded Linux mindustry on itch.io) .


These are all essentially different variations of "it might fix some problems for someone", but I've yet to see any aside from the specific one you've pointed out in this issue, which, again, is so incredibly rare that it has taken years for anyone to bring it up. These benefits don't seem to be relevant if they don't actually fix any problems.

[...]

Overall, I still think these benefits are still mostly irrelevant.

As I see it, your point seems to be "with this extremely specific niche problem (1 of which has ever been reported), the user will have to do something extremely unreasonable, as opposed to something moderately unreasonable".

I don't see the point of comparing principal vs practical benefits; Because regardless, it's bad practice/principal to not use the system libraries if possible. It seems you even agree with me on this part, too:

Yes, but again, this risk seems to have manifested in a grand total of one issue reported here.

Remember that my specific issue was just meant to be a personal example; Wayland support (e.g. Anuken/Mindustry#1393, which had many people wanting wayland support) is also another example, so it's not entirely fair to say it only affects one person, since lack of wayland support is caused by not using system libraries.

Not to mention, your logic of "it only affects one person, so it's not really an issue" is just really bad principal in my opinion. It's still an issue regardless of how many it affects, and again, this isn't factoring in any other future issues that are caused by similar incompatibilities; You're essentially leaving it up to chance how many issues arise due to said incompatibilities. So, it's not entirely correct to just ignore the principal in the name of pure practicality.

Even if the benefits of this PR are irrelevant, if they outweigh the drawbacks (which I think we've agreed that, with the correct solution, they do), it should still be implemented.


Any changes you make to Arc need to be tested, and to be tested, they need to be run on desktop, and to be run on desktop, Arc needs the desktop natives. If I clone the repo and try to do anything useful with it at all, I will need to compile the library file.

That's true; but again, my intention was to avoid compiling the sdl backend library file unless it was necessary, not just if you wanted to compile it without testing. But regardless, if you want to talk about practicality, it only adds about 30 seconds of compilation time on an average system anyway, and only on first clone or a clean; Hence why I listed this as a con in the pros/cons list in my last comment.


No, it does not. If sdl2-config is not present, the exception from the command invocation is ignored, and nothing happens.
If it really was required, I'd have gotten a lot more issues about it in this repo.

This makes so sense at all to me. If it's not required in the first place then why is it there? Let me try to explain this: It essentially does nothing in that case; The point of sdl2-config in this case is to give relevant information about the SDL installed on the system so that Arc can link to it, which is most likely the system SDL. Let's say for the sake of this argument that if there is no system SDL, it somehow finds and links to the bundled one (which in reality I don't see how that's possible) and thus uses that at runtime. But even if it detects a system SDL and links to it, Arc will use the SDL bundled in the jar anyway; So regardless, Arc is going to load the bundled SDL at runtime, meaning sdl2-config is worthless anyway, which definitely shouldn't be the case.

If it really was the case that sdl2-config could return an error yet Arc would still try to compile, I don't see how it wouldn't fail to build. You're still calling SDL functions in Arc but not telling the linker to include SDL2, so I don't see how you wouldn't get linker errors. Maybe I don't fully understand how the jni works, but I still don't see how it could implicitly know to link to SDL2, even the bundled one.

I suspect what's really going on is that sdl2-config is irrelevant because the Arc SDL backend library file is already bundled, so it's never compiled anyway. Thus sdl2-config is never called, and hence why you say it's not required. So it seems that entire section in practice does absolutely nothing. This is why I removed the bundled Arc SDL backend library file in the first place, so that it would actually get compiled.

Regardless, the only thing my PR changes is doing this with GLEW as well (using pkg-config instead of just sdl2-config, but it's essentially the same fundamentally). So, it's quite a trivial change. (Again, more on this in the section below).


I never mentioned prioritizing the bundled versions, so I'm not sure why you bring that part up, but, regardless, both problems apply.

I meant that a solution that removes the bundled libraries completely (e.g. the second solution in the table) would require some CI code changes. Otherwise, a solution that still includes the bundled libraries (e.g. the last and, in my opinion, preferred solution) requires library loading code changes. So, they can be seen as mutually exclusive. I'll touch on this in more detail in the next section below.


The easiest solution for developers needing to install GLEW is to not have it be a requirement at all. I don't think there's any reason to remove the pre-generated libraries.

Either way, what to do in terms of developer requirements is a separate issue that I think should be left for afterwards. The two solutions I can think of off the top of my head is to either have GLEW and SDL as build requirements (which is very common for projects of other languages at least) and thus listed under a set build instructions and dependencies or to add significant gradle build code to try to link to system libraries first, then fallback to linking to the pre-compiled ones if it can't (but this has it's own problems, like the possibility of mismatched SDL versions if it links to the bundled one). It's also important to note that whatever solution is decided on here, it will also apply to people who build and run mindustry from source (which includes those who download mindustry from their package manager). Like always, it's your decision in the end.


I think, even for someone using Linux, you vastly overestimate what the average user is going to know about switching SDL versions to suit their game at all. This is such a niche use case that I don't think it's even worth considering.

Yes, that is unreasonable, but so is switching their SDL/GLEW version to make the game work. Software should just work without the need for people to tweak their library versions.

My point with this was simply that if the average user had to switch SDL versions for whatever reason, then in isolation, I would think it's much easier to use their package manager to switch up their SDL just once as opposed to having to mess with the mindustry jar every time mindustry is updated.


I wanted to highlight this concern separately as it's quite relevant (emphasis mine):

If I want Arc to:

  • Load system libraries first, if possible
  • Upon failure, extract and load bundled libraries (yes, absolutely necessary for binary distributions)

Then I must:

  • Change CI/repo files so they are bundled (at least, GLEW, which is currently not bundled at all)
  • Change the library loading code so both are loaded from the jar file
  • Test both changes
  • Deal with any potential flakyness/bugs

This isn't entirely correct (which thankfully means less work needed); In this case you shouldn't have to change the CI at all just to bundle GLEW; You just need to do what you're already doing with SDL. That is, bundling GLEW is as trivial as adding a libGLEW.so shared library to libs/linux64, just like you have done with libSDL2.so; The current build system will already copy it into the Mindustry jar, so now the only issue is for Arc to prioritize loading the system libraries over the ones in the jar.


Now to the prevalent issue at hand:

How will GLEW be loaded from the JAR?

The current library loading code is already setup to load SDL from the jar:

static{
new SharedLibraryLoader(){
@Override
protected Throwable loadFile(String sourcePath, String sourceCrc, File extractedFile){
//skip dynamic load for me because it crashes otherwise
if(OS.isLinux && !OS.hasProp("SDL2_STATIC") && !OS.username.equals("anuke")){
//on linux, the SDL shared library isn't statically linked, try to load it first
try{
String name = "libSDL2.so";
File result = new File(extractedFile.getParentFile() == null ? name : (extractedFile.getParentFile() + "/" + name));
extractFile(name, crc(readFile(name)), result);
System.load(result.getAbsolutePath());
}catch(Throwable ignored){
}
}
return super.loadFile(sourcePath, sourceCrc, extractedFile);
}
}.load("sdl-arc");
}

So, this code just needs to be adapted/duplicated to do the same thing but with GLEW.

And like I just said above, bundling GLEW is as trivial as dropping a shared library file (libGLEW.so) in libs/linux64, exactly like what you're currently doing with SDL.


How will the bundled library extractor know whether to extract GLEW/SDL? How will the fallback mechanism work?

Breaking it down: we first call System.loadLibrary() to try and load both the system SDL and GLEW. Much like System.load(), System.loadLibrary() will throw if it fails (e.g. if it can't load the library from the system). If it does for one of our libraries, we then just continue on to the already existing code (linked above) that calls System.load() and loads the bundled version of that library. This also means that if loading the system GLEW fails but SDL doesn't for example, the system SDL and bundled GLEW will get loaded (this behavior can of course be changed, but I don't foresee an immediate need to).

Again, right now this is all theory since we haven't done any testing, but I don't see this posing much of an issue; It should be pretty straightforward.

@Anuken
Copy link
Owner

Anuken commented Jan 12, 2024

This makes so sense at all to me. If it's not required in the first place then why is it there?

I personally don't see how it makes sense how developers need SDL installed but needing GLEW installed is a problem.

I'm going to skim over the rest of this answer, because I think you may have misunderstood my point: It's there to configure things if you are explicitly trying to build the natives. If you are simply testing any PR unrelated to natives, it is not required. Your PR, by virtue of requiring the natives to build upon a clone, requires SDL to test anything useful.

Without your PR (as it is now), SDL is not required, unless you explicitly want to rebuild the natives for some reason.


As for your solution, I was a little confused, because your initial wording said (highlights mine):

Only a single addition of a System.loadLibrary() call should be required

...but what you're saying now sounds like several new load/loadLibrary calls, some copy-pasted/extracted code to mimic the SDL linking, and some try-catches, which is rather different.

The two solutions I can think of off the top of my head is

This statement confuses me as well. Why isn't there a third solution of keeping things as they were, except with glew being linked dynamically, and both libraries being system-first? No significant buildscript changes would have to be done (see below), and nobody would need to wait 30 seconds or rebuild sdl-arc, as it would be bundled. Why rebuild it at all when it links to the system libraries first?


I think the overall plan would be this:

  1. Revert the buildscript changes that make jar depends on jni tasks
  2. Build the SDL natives (sdl-arc) and add them back into the repo, along with libSDL2.so and libGLEW.so
  3. Inside the block that is run before sdl-arc is loaded:
    1. Attempt System.loadLibrary("SDL2"), and fallback to the old code that extracts the library upon failure
    2. Do the exact same with GLEW

@Arastais
Copy link
Author

...but what you're saying now sounds like several new load/loadLibrary calls, some copy-pasted/extracted code to mimic the SDL linking, and some try-catches, which is rather different.

I guess I didn't explain that very well; It's better if I just show what I mean in the next commit. My point was just that it should be straightforward and simple to implement.

Before it slips my mind again, I should also mention that this needs to be done with all of GLEW's library dependencies (EGL, GL, GLU, OpenGL). However, this is a trivial change in the library loading code and also would just require adding a few more files to the libs/linux64 directory


Why isn't there a third solution of keeping things as they were, except with glew being linked dynamically, and both libraries being system-first?

  1. Revert the buildscript changes that make jar depends on jni tasks
  2. Build the SDL natives (sdl-arc) and add them back into the repo, along with libSDL2.so and libGLEW.so

This might be difficult to explain, but: This goes beyond the scope of just jni; I originally did this because it's common and better practice, at least from my perspective - e.g. ABI incompatibility shenanigans, not to mention reasons I've listed previously. It's mainly for those that are building mindustry from source anyway (i.e. they would build Arc from source too by default), not just developers. However, after giving it some further thought, I think in this specific case it won't make much of a difference and I don't foresee any issues arising with what you're proposing (especially since we have explicit control over how the libraries are loaded). Just in case though, I'll revert the build script changes in a separate commit.

So with what you're proposing, like you said, you only need SDL and GLEW on your system if you're explicitly trying to build the library file.

@Anuken
Copy link
Owner

Anuken commented Jan 12, 2024

Before it slips my mind again, I should also mention that this needs to be done with all of GLEW's library dependencies (EGL, GL, GLU, OpenGL).

adding a few more files

GLU makes sense, but why bundle the rest? I'm not too familiar with how dynamic linking works, to be honest, but aren't GL/EGL always present on the system? I've always been linking GL dynamically with no bundled libraries up to this point, and it hasn't caused any problems.

You also list OpenGL and GL separately - what is the distinction between the two? The GLEW guide page only mentions linking to -lGLU -lGL on top of -lGLEW.

Additionally: Will linking to EGL cause problems with those that don't use EGL?

@Arastais
Copy link
Author

Arastais commented Jan 12, 2024

GLU makes sense, but why bundle the rest?

They're all the possible dependencies of GLEW (depending on configuration) according to its pkg-config (which is determined based on it's makefile and on how GLEW is configured). You can run pkg-config --libs glew to see this for yourself. So although some of the dependencies might not always be necessary, again, it depends on how the bundled glew will be configured.

Since the pkg-config --libs command is what's used to build the backend, Arc will be linked to all of them, and thus they will need to be bundled. If you wanted to theoretically completely drop support for a specific window system, the build script would have to manually remove the unnecessary ones.


aren't GL/EGL always present on the system?

Probably, but not necessarily; All of these dependencies are part of libglvnd, so there's no explicit guarantee they'll be installed (however likely it is), as I don't think it's a system requirement.


You also list OpenGL and GL separately - what is the distinction between the two? The GLEW guide page only mentions linking to -lGLU -lGL on top of -lGLEW.

Including information from libglvd's documentation:

  • libGLX is the GLX window-system API library (used by X11)
  • libEGL is the EGL window-system API library (platform-agnostic; used by Wayland)
  • libOpenGL is a wrapper library for dispatching OpenGL functions to the correct vendor library
  • libGL essentially combines libOpenGL and libGLX.

(Note how for EGL support, you need libOpenGL and libEGL explicitly, but that point libGL might be redundant for adding X11 support; i.e. if you're already linking to libOpenGL, you can maybe just link to libGLX instead).

My guess is that the GLEW guide only mentions linking to GLU and GL most likely because it is the minimum/default configuration for GLEW; Since there's Xwayland (and thus X11 is supported under Wayland), only X11 support is necessary; Thus, the minimum needed would be the OpenGL function dispatch library and the GLX library (which is essentially what libGL is).

However, even if you only wanted to support X11 (and thus configured GLEW that way), I believe you still need the library loading code to load EGL and have Arc's SDL backend link to EGL. Otherwise, Arc can't use a system GLEW with an EGL configuration, and thus you would lose wayland support/capabilities. Specifically, Arc couldn't function properly if it used a system GLEW that used EGL functions but Arc itself wasn't linked to EGL. Similarly, it would obviously be a problem if Arc was linked to EGL but the EGL library wasn't loaded, even if it wasn't using any of the EGL functions (i.e. if it was using a bundled GLEW with X11 support only).


Additionally: Will linking to EGL cause problems with those that don't use EGL?

No, it shouldn't (although I can't fully speak for the inner workings of jni and if it affects library loading in this regard). Linking to and actually using the functions a library are separate.

In this case, if GLEW isn't configured for EGL, then you'd essentially be linking to an unused library - it wouldn't use the EGL API functions, regardless of if the EGL library was linked to it or not (the linker might even perform some optimization on this). This is essentially the opposite scenario of what I just described above: Like I mentioned previously, since it was linked at compile-time, the bundled library would need be present regardless of configuration; The only problem could be if GLEW was somehow configured for EGL but ran on a system that does not support EGL windows (e.g. native X11).

Change backend-sdl task to link Arc's SDL backend library to a shared GLEW library instead of using a pre-compiled version.

These changes fix many build and mindustry issues caused by not using the system's GLEW.
On the SDL backend on linux, try to load system libraries (SDL2, GLEW, and their dependencies) first.
If that fails, load bundled ones.
@Arastais
Copy link
Author

Arastais commented Jan 13, 2024

I have gone ahead and made the source code changes. Arc's SDL backend should now link to system libraries when being generated; It will also try to load the system libraries first, then falling back to bundled ones if it fails.

The final commit needed is to add/update the bundled libraries themselves, but I won't do this myself (unless you explicitly ask me to) out of security concerns. It should be fairly straightforward to do this; For each of the dependencies (SDL2, GLU, libglvnd, and GLEW):

  1. Download the latest release/tag archive.
  2. Build using the default configuration (e.g. run make or meson/ninja with no arguments). You may need to consult the build instructions for this.
  3. Rename the resulting binary (i.e. the library files needed) to remove the version suffix.
  4. Place it in libs/linux64.

You also need to re-generate libsdl-arc64.so (i.e. run the :jnigenBuildLinux64 task) to update the bundled SDL backend library. (Note that it cleans the libs/linux64 directory, so you may want to do this first). Once all these files have been updated/added, the changes can be committed.

I tested mindustry with my own pre-bundled libraries (I generated the libraries on my end using the above steps and put them in libs/linux64 before building mindustry), and mindustry worked correctly, using my system libraries as intended.

Once you've finalized the aforementioned commit, I suggest you build and test mindustry as well on your system, both with and without the system GLEW and SDL installed. You can tell if mindustry is using the system libraries or not using the LD_DEBUG environment variable (e.g. LD_DEBUG=libs java -jar Mindustry.jar) and looking at the directory of the libraries loaded.

@Arastais Arastais changed the title Generate sdl backend on linux using system libraries (fix build-related issues on linux) Prioritize system libraries on linux SDL backend (fix build-related issues on linux) Jan 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

glewInit() called too early, fails with "Missing GL version" when used with EGL on Wayland Crash on wayland
2 participants