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

love.system.getArch() proposal #2008

Open
tpimh opened this issue Jan 19, 2024 · 10 comments
Open

love.system.getArch() proposal #2008

tpimh opened this issue Jan 19, 2024 · 10 comments
Labels
feature New feature or request

Comments

@tpimh
Copy link

tpimh commented Jan 19, 2024

Similar to love.system.getOS(), it should just return the architecture that Love is running on. This is particularly useful for loading native code.

I am now using https, and I want to use it on x86_64 and ARM64. Love2D can be compiled to both these architectures, but doesn't provide the interface that tells for which architecture is was compiled. If Love2D had such method, it would be easy to conditionally load the correct version of the library based on the values returned by getOS and getArch (or print a message that the combination that the user is using is not supported by the game).

This information is easy to get from LuaJIT.

@zorggn
Copy link

zorggn commented Jan 19, 2024

And since löve itself by default uses luaJIT, you can just do local arch = require('jit').arch or something, and you have the architecture.

@slime73
Copy link
Member

slime73 commented Jan 19, 2024

The jit module is always loaded when LuaJIT is used, so just jit.arch would work as well.

@tpimh
Copy link
Author

tpimh commented Jan 19, 2024

Yes, I am using jit.arch now to load the library conditionally. But I can also use jit.os, so redundancy is not a problem for getOS(). Why should it be for getArch()?

@slime73
Copy link
Member

slime73 commented Jan 19, 2024

Maybe this could be added to the info table proposal in #1595 - in a new love.system.getInfo function or something.

@slime73 slime73 added the feature New feature or request label Jan 19, 2024
@bartbes
Copy link
Member

bartbes commented Jan 20, 2024

In the mean time, if you add all architectures to the search path, don't love and lua automatically pick the first one that loads successfully?

@tpimh
Copy link
Author

tpimh commented Jan 20, 2024

Yes, I think lua will try to load all the libraries with matching name in the order that is listed in the search path, and will be satisfied with the first one that doesn't fail. Can be checked with strace.

@tpimh
Copy link
Author

tpimh commented Jan 20, 2024

One curious thing that I discovered just now is the inclusion of CpuArch.h from LZMA here:

/* CpuArch.h -- CPU specific code
2016-06-09: Igor Pavlov : Public domain */

Newer version of this header has #define MY_CPU_NAME "string" where string is the name of CPU arch. Perhaps this is what should be returned by getArch()?

It's also possible that with complete CMake migration (#1991) this preprocessor trickery is unnecessary, and CMake could just set the target architecture in a predefined macro (or could it?), and then only a small workaround would be needed for Apple platforms as they won't be using CMake.

@slime73
Copy link
Member

slime73 commented Jan 20, 2024

Using preprocessor checks is much preferred to putting it in a build system generator, the latter is really inflexible and stops code from working on more than one type of system without generating things again. For example on iOS and macOS the Xcode project builds for multiple architectures together and bundles the result together. Whereas on Windows where we use CMake, I can't switch between x64 and x86 in Visual Studio without regenerating the visual studio projects and other build setup.

I'm not worried about implementing that part of the code, we already do similar preprocessor checks for a few things - e.g. in config.h.

@tpimh
Copy link
Author

tpimh commented Jan 20, 2024

I am curious, how many combinations of OS/Arch does LÖVE support.

This is the list of possible operating systems:

While it should be relatively easy to determine the possible architectures for the top of the list, the last options have some variety:

  1. Modern macOS runs only on x86_64 and ARM64; version 10.14.6 is the last supporting running 32-bit x86 applications, 10.6.8 is the last that could be installed on a 32-bit x86 hardware, and it is also the last version that can run PPC64 applications, 10.5.8 is the last that could be installed on PPC64 hardware, and 10.4.11 is the last that could be installed on 32-bit PPC. Are any of these versions still supported? What is the minimum requirement?
  2. iOS now only runs on ARM64. If LÖVE can run on anything older than iPhone 5s, then there's a second option: 32-bit ARMv7 (also ARMv6 for iPhone 3G and the original iPhone, but I am sure there's no LÖVE on these devices).
  3. UWP/Windows have at most 4 options: x86, x86_64 (simply called x64), ARMv7 and ARM64. Starting with Windows 11, 32-bit x86 and ARMv7 are no longer supported, reducing the number to just 2. Older versions of Windows supported more architectures: XP also supported Itanium, NT up to 4.0 supported Alpha, MIPS, PPC. These operating systems are ancient, I expect some trouble compiling LÖVE for these platforms.
  4. Android is where it gets interesting. Officially, only ARM64 is supported. However, because it's using Linux kernel and lots of open-source tools, it can be compiled for many other platforms: x86, x86_64, ARMv7, RV64 (the last one is about to become officially supported).
  5. Finally, Linux is a wild territory. The kernel itself runs on dozens of architectures, however every distro picks a subset of them to support. Additionally, every distro that adds LÖVE to its repos choses to compile or not to compile it for one or another architecture that the distro supports. I picked a few popular ones (only checking the latest versions and not historical ones):
  • Ubuntu 24.04 (Noble Numbat): building LÖVE for x86_64, ARMv7, ARM64, PPC64, RV64; not building LÖVE for x86 and S390X.
  • Debian 13 (Trixie): building LÖVE for x86, x86_64, ARMv6, ARMv7, ARM64, MIPS64, PPC64; not building LÖVE for S390X.
  • Alpine 3.19: building LÖVE for x86, x86_64, ARMv6, ARMv7, ARM64; not building LÖVE for PPC64 and S390X.
  • FreeBSD is not Linux, but is compiled using similar preprocessor definitions, thus would identify as Linux:
    // I know it's not linux, but it seems most "linux-only" code is bsd-compatible

    I just wanted to include one BSD to the list. So FreeBSD port marks LÖVE incompatible with MIPS, MIPS64 and PPC, but it is being built for x86, x86_64, ARMv6, ARMv7, ARM64, PPC64.

This is probably a pain to read, but I tried to list the architectures more or less uniformly. There are a lot of variations, and different operating systems might give them different names. Also, I was rewriting and editing my lists to be consistent as I was adding new info to it, so I might have made mistakes, used sources with false information in them, so this is for reference only, don't trust this information without confirming by doing your own research!

Anyway, if you absolutely need to bundle native code with your library, compile it for these 5 architectures:

  • macOS x86_64
  • Windows x86_64
  • Linux x86_64
  • iOS ARM64
  • Android ARM64

This would cover like 90% of the users. And if you want to get it to 99%, then also add these 3:

  • macOS ARM64
  • Windows ARM64
  • Linux ARM64

Finally, if you want to get it to like 99,9% then consider adding some legacy 32-bit architectures as well:

  • Windows x86
  • Linux x86

I am sure Windows and UWP builds will use exactly the same binary format, so I combined them into one. Not so sure about macOS ARM64 and iOS ARM64 code, pretty sure it must be different. And once again, Linux is a completely wild territory: if you will be linking against libc (and you probably will), Linux ARM64 and Android ARM64 binaries will be different (Android is using bionic libc, and most of the Linux distros are using GNU libc). And some Linux distros like Alpine are using musl libc, so neither binary would be compatible with it. What's the solution? love.system.getLibc() to differentiate between linux-gnu-arm64 and linux-musl-arm64? And this is not even touching BSD, because it is completely different yet identified as Linux by getOS()...

In conclusion, I must say that the only way to support 100% of the platforms that LÖVE runs on, just avoid using native code, write in Lua. I have no other solution.

If I made a mistake somewhere, please, feel free to correct me!

@slime73
Copy link
Member

slime73 commented Jan 20, 2024

I am curious, how many combinations of OS/Arch does LÖVE support.

  • macOS: arm64 (Apple Silicon), x64
  • iOS: arm64-iOS (device), arm64-macOS (Simulator), x64-macOS (Simulator)
  • Windows: x86, x64 (you can support arm64 but love does not officially support it for Windows at the moment).
  • Linux: x64 (for the official appimage), or also x86, maybe arm64, and maybe armv7 depending on what other niche devices you want to compile for like Raspberry Pi.
  • Android: arm64 (device), armv7 (device), not sure about emulators/simulators on desktop.

On macOS and iOS it's fairly easy to compile for all architectures at once and have one library binary that has everything, like I mentioned earlier. x86 on Windows is close to being extinct. If you want, you could just have one binary for macOS, one for Windows, one for Linux, one for iOS, and one for Android (or take away the last two if you don't need to support mobile).

OS X (should be renamed to macOS?)

So far we haven't wanted to break code compatibility for this, but maybe it'll happen in the future.

According to https://store.steampowered.com/hwsurvey/Steam-Hardware-Software-Survey-Welcome-to-Steam?platform=mac 70% of mac steam users have an arm64 system, so you might not want to leave that out - and your x64 library will fail to work on those systems anyway unless you strip out the arm64 part of love.app to make it use Rosetta x64 emulation. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants