godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.96k stars 21.07k forks source link

Improve toolchains/documentation for building portable custom Linux binaries easily #45626

Closed eh-jogos closed 2 years ago

eh-jogos commented 3 years ago

Godot version: 3.2.3 stable customized with GodotSteam module

OS/device including version: Manjaro i3 20.2 (Godot editor and export templates built using docker with ubuntu:xenial)

Issue description: The exported game works fine for me, as well as the editor, but I've got a user on steam saying the demo for the game won't start. Here is his first comment:

I cannot start the demo on glibc/linux:

  • it expects libpulse to be there or will fail: it should try to dynamically load libpulse and if failing to do so, should fall back to alsa. >That said, you only need to support alsa to be universal on glibc/linux distros.
  • do not use gnu versioning: the game won't start if the glibc is not 2.29.

Well, I understood like, almost nothing about it (what is a glibc/linux distro?) but it seemed like a versioning problem and given that I foolishly built the custom export templates in my own machine as I was in a hurry and didn't follow the docs recommendation of building them in ubuntu 16.04, I just damned my past self, took a weekend to crash-learn docker and rebuilt the export templates using a docker container with ubuntu:xenial.

Granted, at the time I didn't know about https://github.com/godotengine/build-containers, I just found it now looking for similar issues as this one. My dockerfile looks like this:

FROM ubuntu:xenial

RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install build-essential scons pkg-config libx11-dev libxcursor-dev libxinerama-dev \
    libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm

COPY godot-github /home/godot-github/
COPY build_linux_godot_and_templates.sh /home

Basically just following the official docs, installing the packages for ubuntu, and copying the godot source already in the right commit (3.2.3-stable) with Godotsteam module already configured inside it, and a script to compile the editor and export templates. There's another dockerfile extremely similar to this one, only using i386/ubuntu:xenial so that I can compile 32-bit export templates.

So after updating the game on steam an continuing to talk with the user, it now seems like the error has changed, in his own words:

baw... now it does not start because: /mnt/128/home/user/.local/share/Steam/steamapps/common/Escape from the Cosmic Abyss/CosmicAbyss.x86_64: relocation error: /mnt/128/home/user/.local/share/Steam/steamapps/common/Escape from the Cosmic Abyss/CosmicAbyss.x86_64: symbol _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE version GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time reference

This is a c++ ABI breakage/GNU versionning. Don't take it personally, but c++ is an horrible and toxic computer language, and you got hit by one of its most painful flaws. It is not of your doing, godot guys should have pick simple C (c89 with a bit of c99) for their implementation language.

If you want to resolve this, the following "should" fix this:

  • if your compiler is gcc: in the godot engine configuration, "somewhere", you can add compiler options, add those: -static-libgcc >-static-libstdc++
  • if your compiler is clang: I don't know the clang equivalent options, but they should be the same or not that much different.

Here is the full thread if needed And what appears to be his distribution, taken from a link in his steam profile: nyanlinux

Sincerely, I don't fully understand what he is saying or these error messages. So here are some questions:

Another thing I did on the steam side of things is that I setup a Depot for the pcks, another for windows executables and dlls (for steam integragion) and another for linux executables and .so file. Then for the demo, which is what this user is trying to use, I only setup a depot for demo pcks, and I share the executables depots from the full game with the demo app. I tested this in my computer and it worked fine, but could this be the problem?

Anyway, any help so I can at least understand better what's happening here is much appreciated.

Steps to reproduce: I have no idea.

Minimal reproduction project: I can upload the export templates here if needed, or the game itself? He is having a problem with the demo, that's also free to (download through steam)[https://store.steampowered.com/app/1315250].

akien-mga commented 3 years ago

For Linux binaries, you have to build against the oldest glibc version which you want to support. glibc is the GNU C library. If you build against e.g. glibc 2.32 (a fairly recent version), your binary will not be compatible with older distros which ship an older version of glibc.

That's why official Godot binaries are built on Ubuntu 14.04 - they're compatible with any distro that has the same or a newer version of glibc. In your case, you use Ubuntu 18.04 which has glibc 2.23, so it won't run for users who are on older distros like Ubuntu 16.04 or Debian 8. I would recommend going with Ubuntu 16.04 if you want to support users on old distros - or state clearly in your system requirements that you support Ubuntu 18.04 and later, or distros with glibc 2.23 or later. It's not a reasonable decision to make on a platform like Steam where the percentage of users running outdated distros is really small (because people playing games usually want recent GPU drivers for decent performance or even for them to work at all, and this typically means a recent - less than 2 years old - distro).

As to the C++ library, it is indeed recommended to use -static-libgcc to embed it statically in the binary and not depend on whatever too old or too recent version the user may have. You can do that by compiling with use_static_cpp=yes. I've been thinking lately that we should make it default to yes as it's not well covered in the documentation yet and many users miss it in their custom builds. That doesn't remove the requirement to build against the oldest glibc version / distro you want to support though.

eh-jogos commented 3 years ago

Thanks a lot @akien-mga! I guess I'll add use_static_cpp to my compile script!

Also I am actually using ubuntu 16.04 already, as ubuntu:xenial is that, at least according to dockerhub ubuntu page. But would you recommend I actually use trusty, or even better, base my Docker container in the official template Dockerfile?

Or if I'm not using mono I can just stick to the container I already made and just change xenial for trusty?

akien-mga commented 3 years ago

Ah right Xenial is 16.04... I could never get used to Debian and Ubuntu's terrible "you gotta remember our names" marketing scheme...

So use_static_cpp=yes use_lto=yes should get you covered. IMO Ubuntu 16.04 is old enough for 99.99% of users, so unless you care about the 0.01%, it should be fine.

And yes, another good option is to build the same container that we use for official builds: https://github.com/godotengine/build-containers/blob/master/Dockerfile.ubuntu-64 It's based on Ubuntu 14.04, but includes a recent version of GCC (the trick is that we want old glibc but new gcc, as recent compilers have much better optimizations, especially much better LTO).

Then you can see https://github.com/godotengine/godot-build-scripts/blob/master/build-linux/build.sh for the actual build options we use (use_static_cpp=yes though only for 64-bit, not sure why it couldn't be done on 32-bit, use_lto=yes, and also udev=yes for better controller support - that last one should really default to yes though, I'll fix that in a minute).

Building portable binaries for Linux is really a pain... but we have some ideas on how to make this easier for Godot users, and we've started working on a command tool in the past that could build Godot in our own official containers with the right options. It's not fully ready yet but we should hopefully have some options in the feature so that users don't need to figure it all out by themselves.

eh-jogos commented 3 years ago

Thanks a lot akien! I'll take some time tonight after work to do these changes, base my container on the official ones and change my compile script to use the same options you mentioned!

I just skimmed the docs page for compiling fox X11 again, and the page actually mentions libudev and udev=yes but I had no idea this helped with controller support, so I guess I just ignored it and forgot!

Maybe adding this options as an example in the Building export templates section and a mention to the official builds containers in the "use an old distribution" warning would already help a lot?

akien-mga commented 3 years ago

Yeah the documentation could use some extra info. And we're discussing options with @hpvb to simplify further, e.g. by providing our own toolchain images on DockerHub that users could use easily on CI or locally.

I'll keep this issue open as a reminder for this.

Calinou commented 3 years ago

As for the PulseAudio issue, this is something we should improve on our end. Still, keep in mind non-PulseAudio users make for a very small portion of Linux gamers nowadays, especially since notable software like Firefox removed non-PulseAudio support a few years ago.

Edit: PulseAudio is now loaded at run-time in the master branch.

Calinou commented 2 years ago

udev=yes and use_static_cpp=yes are now the default in both master and 3.x, and audio libraries are loaded at run-time. Should we consider this issue addressed (as the docs already recommend using Ubuntu 16.04 for building portable binaries)?

akien-mga commented 2 years ago

Yeah I guess we can close this. I still intend to improve the documentation to share more details on do's and dont's to make portable Linux builds properly, but I don't need this issue as reminder, it's in my (crazy long) task list.