#!/usr/bin/env python3 """Fail when a release binary needs a library its players may not have. Windows .exe: every DLL in the import and delay-import tables must ship with Windows (no VCRUNTIME140.dll, vulkan-1.dll, ...): Vulkan and the like are loaded at run time, so a missing driver is an error message, not a dialog. Linux ELF: the loader must be the standard one (not a /nix/store path) and the needed libraries the ones every desktop distribution has. `--server`: a server build, which may not need ALSA or udev either (minimal server images lack them). """ import argparse import struct import sys from pathlib import Path # DLLs that are part of Windows 10 and 11. api-ms-win-* and ext-ms-win-* API # sets resolve inside Windows too. WINDOWS_SYSTEM = { "advapi32.dll", "bcrypt.dll", "bcryptprimitives.dll", "cfgmgr32.dll", "combase.dll", "comctl32.dll", "comdlg32.dll", "crypt32.dll", "d2d1.dll", "d3d11.dll", "d3d12.dll", "d3dcompiler_47.dll", "dbghelp.dll", "dcomp.dll", "dwmapi.dll", "dwrite.dll", "dxgi.dll", "gdi32.dll", "hid.dll", "icuuc.dll", "imm32.dll", "iphlpapi.dll", "kernel32.dll", "kernelbase.dll", "mfplat.dll", "mmdevapi.dll", "msvcrt.dll", "ncrypt.dll", "ntdll.dll", "ole32.dll", "oleaut32.dll", "opengl32.dll", "propsys.dll", "secur32.dll", "setupapi.dll", "shcore.dll", "shell32.dll", "shlwapi.dll", "ucrtbase.dll", "user32.dll", "userenv.dll", "uxtheme.dll", "version.dll", "winmm.dll", "ws2_32.dll", "xinput1_4.dll", } LINUX_LOADER = "/lib64/ld-linux-x86-64.so.2" LINUX_SYSTEM = { "libc.so.6", "libm.so.6", "libgcc_s.so.1", "libdl.so.2", "libpthread.so.0", "librt.so.1", "ld-linux-x86-64.so.2", "libasound.so.2", "libudev.so.1", } # The game's sound (cpal) and controllers (gilrs): a desktop has them, a server image may not. LINUX_DESKTOP_ONLY = {"libasound.so.2", "libudev.so.1"} def windows_allowed(name): name = name.lower() return name in WINDOWS_SYSTEM or name.startswith(("api-ms-win-", "ext-ms-win-")) def pe_imports(data): """DLL names in a PE32+ file's import and delay-import tables.""" pe = struct.unpack_from("