Last active
August 2, 2026 21:42
-
-
Save trojanfoe/aae4fe796c7bb8a58fd53d6562b4400d to your computer and use it in GitHub Desktop.
Build SDL_shadercross
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # | |
| # Builds the SDL shadercross tool and installs it locally. | |
| # | |
| # Prerequisites: | |
| # Python 3 | |
| # Git | |
| # C++ compiler | |
| # CMake | |
| # Ninja | |
| # | |
| # Linux-only prerequisites: | |
| # patchelf | |
| # | |
| # Edit WORKING_DIR and BIN_INSTALL_DIR and LIB_INSTALL_DIR to suit your needs. | |
| # | |
| import argparse | |
| import os | |
| import shutil | |
| import subprocess | |
| import sys | |
| SDL_TAG = "release-3.4.8" | |
| platform = sys.platform | |
| if platform == "darwin" or platform == "linux": | |
| WORKING_DIR = os.path.expanduser("~/source/SDL3") | |
| BIN_INSTALL_DIR = os.path.expanduser("~/bin") | |
| LIB_INSTALL_DIR = os.path.expanduser("~/lib") | |
| elif platform == "win32": | |
| WORKING_DIR = os.path.expanduser("~/source/SDL3") | |
| BIN_INSTALL_DIR = os.path.expanduser("~/AppData/Local/Programs") | |
| LIB_INSTALL_DIR = BIN_INSTALL_DIR | |
| else: | |
| raise RuntimeError("Unsupported platform") | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument( | |
| "--cleanup", | |
| action="store_true", | |
| help="Run cleanup of build directories and exit", | |
| ) | |
| parser.add_argument( | |
| "--no-build", | |
| action="store_true", | |
| help="Skip clone/build steps and run installation only", | |
| ) | |
| parser.add_argument( | |
| "--no-cleanup", | |
| action="store_true", | |
| help="Skip cleanup of build directories after installation", | |
| ) | |
| args = parser.parse_args() | |
| if args.cleanup: | |
| cleanup() | |
| return | |
| if platform == "win32": | |
| if not os.environ.get("VSINSTALLDIR"): | |
| raise RuntimeError( | |
| "This script must be run from a Developer Command Prompt or " | |
| "Developer PowerShell for Visual Studio." | |
| ) | |
| os.makedirs(WORKING_DIR, exist_ok=True) | |
| if not os.path.exists(BIN_INSTALL_DIR): | |
| raise RuntimeError(f"Install directory {BIN_INSTALL_DIR} does not exist") | |
| if not os.path.exists(LIB_INSTALL_DIR): | |
| raise RuntimeError(f"Install directory {LIB_INSTALL_DIR} does not exist") | |
| if not args.no_build: | |
| clone_and_build_sdl() | |
| clone_and_build_shadercross() | |
| if platform == "darwin": | |
| install_binaries_macos() | |
| elif platform == "win32": | |
| install_binaries_windows() | |
| elif platform == "linux": | |
| install_binaries_linux() | |
| else: | |
| raise RuntimeError("Unsupported platform") | |
| if not args.no_cleanup: | |
| cleanup() | |
| def clone_and_build_sdl(): | |
| sdl_dir = os.path.join(WORKING_DIR, "SDL") | |
| if not os.path.exists(sdl_dir): | |
| run( | |
| "Cloning SDL", | |
| ["git", "clone", "https://github.com/libsdl-org/SDL", sdl_dir], | |
| ) | |
| run("Fetching SDL origin", ["git", "fetch", "origin"], cwd=sdl_dir) | |
| run(f"Resetting SDL to {SDL_TAG}", ["git", "reset", "--hard", SDL_TAG], cwd=sdl_dir) | |
| build_dir = os.path.join(sdl_dir, "build") | |
| if os.path.exists(build_dir): | |
| shutil.rmtree(build_dir) | |
| run( | |
| "Configuring SDL", | |
| ["cmake", "-Bbuild", "-S.", "-GNinja", "-DCMAKE_BUILD_TYPE=Release"], | |
| cwd=sdl_dir, | |
| ) | |
| run("Building SDL", ["cmake", "--build", "build"], cwd=sdl_dir) | |
| def clone_and_build_shadercross(): | |
| shadercross_dir = os.path.join(WORKING_DIR, "SDL_shadercross") | |
| if not os.path.exists(shadercross_dir): | |
| run( | |
| "Cloning shadercross", | |
| [ | |
| "git", | |
| "clone", | |
| "--recursive", | |
| "https://github.com/libsdl-org/SDL_shadercross", | |
| shadercross_dir, | |
| ], | |
| ) | |
| run("Fetching shadercross origin", ["git", "fetch", "origin"], cwd=shadercross_dir) | |
| run( | |
| "Resetting shadercross to origin/main", | |
| ["git", "reset", "--hard", "--recurse-submodules", "origin/main"], | |
| cwd=shadercross_dir, | |
| ) | |
| build_dir = os.path.join(shadercross_dir, "build") | |
| if os.path.exists(build_dir): | |
| shutil.rmtree(build_dir) | |
| run( | |
| "Configuring shadercross", | |
| [ | |
| "cmake", | |
| "-Bbuild", | |
| "-S.", | |
| "-GNinja", | |
| "-DCMAKE_BUILD_TYPE=Release", | |
| "-DSDLSHADERCROSS_DXC=ON", | |
| "-DSDLSHADERCROSS_VENDORED=ON", | |
| "-DSDL3_DIR=../SDL/build", | |
| ], | |
| cwd=shadercross_dir, | |
| ) | |
| run("Building shadercross", ["cmake", "--build", "build"], cwd=shadercross_dir) | |
| def install_binaries_macos(): | |
| print( | |
| f"Installing binaries to {BIN_INSTALL_DIR} and libraries to {LIB_INSTALL_DIR}" | |
| ) | |
| binaries_to_fix = [] | |
| shadercross_build_dir = os.path.join(WORKING_DIR, "SDL_shadercross", "build") | |
| shutil.copy(os.path.join(shadercross_build_dir, "shadercross"), BIN_INSTALL_DIR) | |
| binaries_to_fix.append(os.path.join(BIN_INSTALL_DIR, "shadercross")) | |
| shutil.copy( | |
| os.path.join(shadercross_build_dir, "libSDL3_shadercross.0.dylib"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| binaries_to_fix.append(os.path.join(LIB_INSTALL_DIR, "libSDL3_shadercross.0.dylib")) | |
| spirv_cross_build_dir = os.path.join( | |
| shadercross_build_dir, "external", "SPIRV-Cross" | |
| ) | |
| shutil.copy( | |
| os.path.join(spirv_cross_build_dir, "libspirv-cross-c-shared.0.dylib"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| binaries_to_fix.append(os.path.join(LIB_INSTALL_DIR, "libspirv-cross-c-shared.0.dylib")) | |
| directx_shader_compiler_build_dir = os.path.join( | |
| shadercross_build_dir, "external", "DirectXShaderCompiler", "lib" | |
| ) | |
| shutil.copy( | |
| os.path.join(directx_shader_compiler_build_dir, "libdxcompiler.dylib"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| binaries_to_fix.append(os.path.join(LIB_INSTALL_DIR, "libdxcompiler.dylib")) | |
| sdl_build_dir = os.path.join(WORKING_DIR, "SDL", "build") | |
| shutil.copy(os.path.join(sdl_build_dir, "libSDL3.0.dylib"), LIB_INSTALL_DIR) | |
| binaries_to_fix.append(os.path.join(LIB_INSTALL_DIR, "libSDL3.0.dylib")) | |
| for binary in binaries_to_fix: | |
| fix_macos_rpaths(binary) | |
| def install_binaries_windows(): | |
| print( | |
| f"Installing binaries to {BIN_INSTALL_DIR} and libraries to {LIB_INSTALL_DIR}" | |
| ) | |
| shadercross_build_dir = os.path.join(WORKING_DIR, "SDL_shadercross", "build") | |
| shutil.copy(os.path.join(shadercross_build_dir, "shadercross.exe"), BIN_INSTALL_DIR) | |
| shutil.copy( | |
| os.path.join(shadercross_build_dir, "SDL3_shadercross.dll"), LIB_INSTALL_DIR | |
| ) | |
| spirv_cross_build_dir = os.path.join( | |
| shadercross_build_dir, "external", "SPIRV-Cross" | |
| ) | |
| shutil.copy( | |
| os.path.join(spirv_cross_build_dir, "spirv-cross-c-shared.dll"), LIB_INSTALL_DIR | |
| ) | |
| directx_shader_compiler_build_dir = os.path.join( | |
| shadercross_build_dir, "external", "DirectXShaderCompiler", "bin" | |
| ) | |
| shutil.copy( | |
| os.path.join(directx_shader_compiler_build_dir, "dxcompiler.dll"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| shutil.copy( | |
| os.path.join(directx_shader_compiler_build_dir, "dxil.dll"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| sdl_build_dir = os.path.join(WORKING_DIR, "SDL", "build") | |
| shutil.copy(os.path.join(sdl_build_dir, "SDL3.dll"), LIB_INSTALL_DIR) | |
| def install_binaries_linux(): | |
| print( | |
| f"Installing binaries to {BIN_INSTALL_DIR} and libraries to {LIB_INSTALL_DIR}" | |
| ) | |
| shadercross_build_dir = os.path.join(WORKING_DIR, "SDL_shadercross", "build") | |
| shutil.copy(os.path.join(shadercross_build_dir, "shadercross"), BIN_INSTALL_DIR) | |
| shutil.copy( | |
| os.path.join(shadercross_build_dir, "libSDL3_shadercross.so"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| spirv_cross_build_dir = os.path.join( | |
| shadercross_build_dir, "external", "SPIRV-Cross" | |
| ) | |
| shutil.copy( | |
| os.path.join(spirv_cross_build_dir, "libspirv-cross-c-shared.so.0"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| directx_shader_compiler_build_dir = os.path.join( | |
| shadercross_build_dir, "external", "DirectXShaderCompiler", "lib" | |
| ) | |
| shutil.copy( | |
| os.path.join(directx_shader_compiler_build_dir, "libdxcompiler.so"), | |
| LIB_INSTALL_DIR, | |
| ) | |
| sdl_build_dir = os.path.join(WORKING_DIR, "SDL", "build") | |
| shutil.copy(os.path.join(sdl_build_dir, "libSDL3.so.0"), LIB_INSTALL_DIR) | |
| shadercross_bin = os.path.join(BIN_INSTALL_DIR, "shadercross") | |
| run( | |
| "Fixing shadercross rpath", | |
| ["patchelf", "--set-rpath", LIB_INSTALL_DIR, shadercross_bin], | |
| ) | |
| def fix_macos_rpaths(file_path): | |
| print(f"Fixing rpaths for {file_path}") | |
| result = subprocess.run( | |
| ["otool", "-l", file_path], capture_output=True, text=True, check=True | |
| ) | |
| lines = result.stdout.splitlines() | |
| rpaths = [] | |
| i = 0 | |
| while i < len(lines): | |
| if "cmd LC_RPATH" in lines[i]: | |
| for j in range(i + 1, min(i + 5, len(lines))): | |
| path_line = lines[j].strip() | |
| if path_line.startswith("path "): | |
| path_val = path_line[5:].split(" (offset")[0].strip() | |
| rpaths.append(path_val) | |
| break | |
| i += 1 | |
| has_lib_install_dir = False | |
| for rpath in rpaths: | |
| if rpath == LIB_INSTALL_DIR: | |
| has_lib_install_dir = True | |
| continue | |
| run( | |
| f"Remove rpath {rpath} from {os.path.basename(file_path)}", | |
| ["install_name_tool", "-delete_rpath", rpath, file_path], | |
| ) | |
| if not has_lib_install_dir: | |
| run( | |
| f"Add lib dir rpath to {os.path.basename(file_path)}", | |
| ["install_name_tool", "-add_rpath", LIB_INSTALL_DIR, file_path], | |
| ) | |
| def cleanup(): | |
| print("Cleaning-up") | |
| shutil.rmtree(os.path.join(WORKING_DIR, "SDL", "build")) | |
| shutil.rmtree(os.path.join(WORKING_DIR, "SDL_shadercross", "build")) | |
| def run(purpose, cmd_line, cwd=None): | |
| print("{}: {}".format(purpose, " ".join(cmd_line))) | |
| subprocess.run(cmd_line, check=True, encoding="utf-8", cwd=cwd) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment