From 0317062ea97aadcc4174bdc1f592f04e7d320d73 Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Fri, 4 Sep 2026 23:36:17 +0200
Subject: [PATCH] Synchronize files with SDL3 and SDL3_image
---
build-scripts/build-release.py | 60 +++++++++++++++++++++++++++------
build-scripts/wikiheaders.pl | 38 +++++++++++++++------
cmake/PrivateSdlFunctions.cmake | 2 +-
cmake/sdlcpu.cmake | 4 ++-
4 files changed, 82 insertions(+), 22 deletions(-)
diff --git a/build-scripts/build-release.py b/build-scripts/build-release.py
index d3725382..faf0dd49 100755
--- a/build-scripts/build-release.py
+++ b/build-scripts/build-release.py
@@ -175,12 +175,18 @@ def find_msbuild(self) -> typing.Optional[Path]:
assert msbuild_path.is_file(), "MSBuild.exe does not exist"
return msbuild_path
- def build(self, arch_platform: VsArchPlatformConfig, projects: list[Path]):
+ def build(self, arch_platform: VsArchPlatformConfig, projects: list[Path], include_paths: list[str], lib_paths: list[str]):
assert projects, "Need at least one project to build"
vsdev_cmd_str = f"\"{self.vsdevcmd}\" -arch={arch_platform.arch}"
msbuild_cmd_str = " && ".join([f"\"{self.msbuild}\" \"{project}\" /m /p:BuildInParallel=true /p:Platform={arch_platform.platform} /p:Configuration={arch_platform.configuration}" for project in projects])
- bat_contents = f"{vsdev_cmd_str} && {msbuild_cmd_str}\n"
+ include_contents = "%INCLUDE%"
+ if include_paths:
+ include_contents = f"{';'.join(str(p) for p in include_paths)};" + include_contents
+ lib_contents = "%LIB%"
+ if lib_paths:
+ lib_contents = f"{';'.join(str(p) for p in lib_paths)};" + lib_contents
+ bat_contents = textwrap.dedent(f"{vsdev_cmd_str} && set INCLUDE={include_contents} && set LIB={lib_paths} && {msbuild_cmd_str}")
bat_path = Path(tempfile.gettempdir()) / "cmd.bat"
with bat_path.open("w") as f:
f.write(bat_contents)
@@ -740,6 +746,12 @@ def extract_filter(member: tarfile.TarInfo, path: str, /):
member.name = "/".join(Path(member.name).parts[1:])
return member
for dep in self.release_info.get("dependencies", {}):
+ if "command" in self.release_info["dependencies"][dep]:
+ for arch, triplet in ARCH_TO_TRIPLET.items():
+ shutil.copytree(self.deps_path / dep, str(mingw_deps_path / triplet), dirs_exist_ok=True)
+ (mingw_deps_path / triplet / "bin").mkdir(exist_ok=True)
+ (mingw_deps_path / triplet / "lib/pkgconfig").mkdir(exist_ok=True, parents=True)
+ continue
extract_path = mingw_deps_path / f"extract-{dep}"
extract_path.mkdir()
with chdir(extract_path):
@@ -856,8 +868,8 @@ def extract_filter(member: tarfile.TarInfo, path: str, /):
f"cmake",
f"-S", str(self.root), "-B", str(build_path),
f"-DCMAKE_BUILD_TYPE={build_type}",
- f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
- f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''',
+ f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}" "-I{str(mingw_deps_path / triplet)}/include"''',
+ f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}" "-I{str(mingw_deps_path / triplet)}/include"''',
f"-DCMAKE_PREFIX_PATH={mingw_deps_path / triplet}",
f"-DCMAKE_INSTALL_PREFIX={install_path}",
f"-DCMAKE_INSTALL_INCLUDEDIR=include",
@@ -1129,6 +1141,15 @@ def download_dependencies(self):
f.write(f"dep-path={self.deps_path.absolute()}\n")
for dep, depinfo in self.release_info.get("dependencies", {}).items():
+ if "command" in depinfo:
+ (self.deps_path / dep).mkdir(exist_ok=True, parents=True)
+ command_args = configure_text_list(shlex.split(depinfo["command"]), context=self.get_context(extra_context={
+ "DEPS_PATH": str(self.deps_path / dep),
+ }))
+ if command_args[0].endswith(".py"):
+ command_args.insert(0, sys.executable)
+ self.executer.run(command_args)
+ continue
startswith = depinfo["startswith"]
dep_repo = depinfo["repo"]
dep_string_data = self.executer.check_output(["gh", "-R", dep_repo, "release", "list", "--exclude-drafts", "--exclude-pre-releases", "--json", "name,createdAt,tagName", "--jq", f'[.[]|select(.name|startswith("{startswith}"))]|max_by(.createdAt)']).strip()
@@ -1143,6 +1164,10 @@ def download_dependencies(self):
def verify_dependencies(self):
for dep, depinfo in self.release_info.get("dependencies", {}).items():
+ if "command" in depinfo:
+ command_matches = glob.glob(depinfo["artifact"], root_dir=self.deps_path)
+ assert len(command_matches) == 1, f"Exactly one archive matches command {dep} dependency: {command_matches}"
+ continue
if "mingw" in self.release_info:
mingw_matches = glob.glob(self.release_info["mingw"]["dependencies"][dep]["artifact"], root_dir=self.deps_path)
assert len(mingw_matches) == 1, f"Exactly one archive matches mingw {dep} dependency: {mingw_matches}"
@@ -1174,7 +1199,12 @@ def build_msvc(self):
deps_path = self.root / "msvc-deps"
shutil.rmtree(deps_path, ignore_errors=True)
dep_roots = []
- for dep, depinfo in self.release_info["msvc"].get("dependencies", {}).items():
+ dep_includes = []
+ for dep in self.release_info.get("dependencies", []):
+ if "command" in self.release_info["dependencies"][dep]:
+ dep_includes.append(self.deps_path / dep / "include")
+ continue
+ depinfo = self.release_info["msvc"]["dependencies"][dep]
dep_extract_path = deps_path / f"extract-{dep}"
msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0]
with zipfile.ZipFile(msvc_zip, "r") as zf:
@@ -1184,13 +1214,21 @@ def build_msvc(self):
dep_roots.append(contents_msvc_zip[0])
for arch in self.release_info["msvc"].get("cmake", {}).get("archs", []):
- self._build_msvc_cmake(arch_platform=self._arch_to_vs_platform(arch=arch), dep_roots=dep_roots)
+ self._build_msvc_cmake(arch_platform=self._arch_to_vs_platform(arch=arch), dep_roots=dep_roots, dep_includes=dep_includes)
with self.section_printer.group("Create SDL VC development zip"):
self._build_msvc_devel()
def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStudio):
platform_context = self.get_context(arch_platform.extra_context())
- for dep, depinfo in self.release_info["msvc"].get("dependencies", {}).items():
+ include_paths = []
+ lib_paths = []
+ for dep in self.release_info.get("dependencies", {}):#release_info["msvc"].get("dependencies", {}).items():
+ if "command" in self.release_info["dependencies"][dep]:
+ include_paths.append(self.deps_path / dep / "include")
+ lib_paths.append(self.deps_path / dep / "lib")
+ lib_paths.append(self.deps_path / dep / "lib" / arch_platform.arch)
+ continue
+ depinfo = self.release_info["msvc"]["dependencies"][dep]
msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0]
src_globs = [configure_text(instr["src"], context=platform_context) for instr in depinfo["copy"]]
@@ -1238,7 +1276,7 @@ def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStu
shutil.copy(src=src, dst=dir_b_props)
with self.section_printer.group(f"Build {arch_platform.arch} VS binary"):
- vs.build(arch_platform=arch_platform, projects=projects)
+ vs.build(arch_platform=arch_platform, projects=projects, include_paths=include_paths, lib_paths=lib_paths)
if self.dry:
for b in built_paths:
@@ -1274,7 +1312,7 @@ def _arch_platform_to_build_path(self, arch_platform: VsArchPlatformConfig) -> P
def _arch_platform_to_install_path(self, arch_platform: VsArchPlatformConfig) -> Path:
return self._arch_platform_to_build_path(arch_platform) / "prefix"
- def _build_msvc_cmake(self, arch_platform: VsArchPlatformConfig, dep_roots: list[Path]):
+ def _build_msvc_cmake(self, arch_platform: VsArchPlatformConfig, dep_roots: list[Path], dep_includes: list[Path]):
build_path = self._arch_platform_to_build_path(arch_platform)
install_path = self._arch_platform_to_install_path(arch_platform)
platform_context = self.get_context(extra_context=arch_platform.extra_context())
@@ -1290,7 +1328,7 @@ def _build_msvc_cmake(self, arch_platform: VsArchPlatformConfig, dep_roots: list
if not self.fast:
for b in built_paths:
b.unlink(missing_ok=True)
-
+ cppflags = list(f"-I{inc}" for inc in dep_includes)
shutil.rmtree(install_path, ignore_errors=True)
build_path.mkdir(parents=True, exist_ok=True)
with self.section_printer.group(f"Configure VC CMake project for {arch_platform.arch}"):
@@ -1303,6 +1341,8 @@ def _build_msvc_cmake(self, arch_platform: VsArchPlatformConfig, dep_roots: list
"-DCMAKE_INSTALL_LIBDIR=lib",
f"-DCMAKE_BUILD_TYPE={build_type}",
f"-DCMAKE_INSTALL_PREFIX={install_path}",
+ f"-DCMAKE_C_FLAGS={shlex.join(cppflags)}",
+ f"-DCMAKE_CXX_FLAGS={shlex.join(cppflags)}",
# MSVC debug information format flags are selected by an abstraction
"-DCMAKE_POLICY_DEFAULT_CMP0141=NEW",
# MSVC debug information format
diff --git a/build-scripts/wikiheaders.pl b/build-scripts/wikiheaders.pl
index 2092912b..801f7ea8 100755
--- a/build-scripts/wikiheaders.pl
+++ b/build-scripts/wikiheaders.pl
@@ -396,6 +396,19 @@ sub wikify {
return $retval;
}
+sub gen_manpage_url {
+ my $url = shift;
+ my $desc = shift;
+
+ # We have to unmangle some mangling we just did. :/
+ $url =~ s/\\\[char46\]/./g;
+
+ # can't have newlines in this.
+ $desc =~ s/\n/ /g;
+
+ return "\n.URL \"$url\" \"$desc\"\n";
+}
+
my $dewikify_mode = 'md';
my $dewikify_manpage_code_indent = 1;
@@ -459,7 +472,7 @@ sub dewikify_chunk {
}
# links
- $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]/\n.URL "$1" "$2"\n/g;
+ $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]\s*/gen_manpage_url($1, $2)/ge;
# <code></code> is also popular. :/
$str =~ s/\s*\<code>(.*?)<\/code>\s*/\n.BR $1\n/gms;
@@ -496,7 +509,7 @@ sub dewikify_chunk {
}
# links
- $str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\n.URL "$2" "$1"\n/g;
+ $str =~ s/\[([^\]]*?)]\((https?\:\/\/.*?)\)\s*/gen_manpage_url($2, $1)/ge;
# <code></code> is also popular. :/
$str =~ s/\s*(\S*?)\`([^\n]*?)\`(\S*)\s*/\n.BR "" "$1" "$2" "$3"\n/gms;
@@ -1362,7 +1375,7 @@ sub generate_envvar_wiki_page {
if (($p eq 'void') || ($p eq '')) {
die("Void parameter in a function with multiple params?! ('$sym' in '$incpath/$dent')") if (scalar(@params) != 1);
} elsif ($p eq '...') {
- die("Mutiple '...' params?! ('$sym' in '$incpath/$dent')") if ($dotdotdot);
+ die("Multiple '...' params?! ('$sym' in '$incpath/$dent')") if ($dotdotdot);
$dotdotdot = 1;
push @paraminfo, '...';
push @paraminfo, '...';
@@ -1673,7 +1686,7 @@ sub generate_envvar_wiki_page {
if ($has_doxygen) {
print STDERR "WARNING: Symbol '$sym' appears to be documented in multiple locations. Only keeping the first one we saw!\n";
}
- push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); # just put the existing declation in as-is.
+ push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); # just put the existing declaration in as-is.
}
}
@@ -1773,20 +1786,20 @@ sub generate_envvar_wiki_page {
} elsif (/\A\= (.*?) \=\Z/) {
$firstline = 0;
$current_section = ($1 eq $sym) ? '[Brief]' : $1;
- die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section};
+ die("Doubly-defined section '$current_section' in '$wikipath/$dent'!\n") if defined $sections{$current_section};
push @section_order, $current_section;
$sections{$current_section} = '';
} elsif (/\A\=\= (.*?) \=\=\Z/) {
$firstline = 0;
$current_section = ($1 eq $sym) ? '[Brief]' : $1;
- die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section};
+ die("Doubly-defined section '$current_section' in '$wikipath/$dent'!\n") if defined $sections{$current_section};
push @section_order, $current_section;
$sections{$current_section} = '';
next;
} elsif (/\A\-\-\-\-\Z/) {
$firstline = 0;
$current_section = '[footer]';
- die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section};
+ die("Doubly-defined section '$current_section' in '$wikipath/$dent'!\n") if defined $sections{$current_section};
push @section_order, $current_section;
$sections{$current_section} = '';
next;
@@ -1798,14 +1811,14 @@ sub generate_envvar_wiki_page {
} elsif (/\A\#+ (.*?)\Z/) {
$firstline = 0;
$current_section = ($1 eq $sym) ? '[Brief]' : $1;
- die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section};
+ die("Doubly-defined section '$current_section' in '$wikipath/$dent'!\n") if defined $sections{$current_section};
push @section_order, $current_section;
$sections{$current_section} = '';
next;
} elsif (/\A\-\-\-\-\Z/) {
$firstline = 0;
$current_section = '[footer]';
- die("Doubly-defined section '$current_section' in '$dent'!\n") if defined $sections{$current_section};
+ die("Doubly-defined section '$current_section' in '$wikipath/$dent'!\n") if defined $sections{$current_section};
push @section_order, $current_section;
$sections{$current_section} = '';
next;
@@ -2912,6 +2925,11 @@ sub generate_envvar_wiki_page {
$brief = shift @briefsplit;
$brief = dewikify($wikitype, $brief);
+ # Hack: `apropros` doesn't like escaped character things like `\[char46]` for `.`...since almost every
+ # manpage will end their Brief section with a period and it won't wordwrap to risk being a groff control
+ # character, just replace it.
+ $brief =~ s/\\\[char46\]/./g;
+
if (defined $remarks) {
$remarks = dewikify($wikitype, join("\n", @briefsplit) . $remarks);
}
@@ -3055,7 +3073,7 @@ sub generate_envvar_wiki_page {
if (defined $returns) {
# Check for md link in return type: ([SDL_Renderer](SDL_Renderer) *)
# This would've prevented the next regex from working properly (it'd leave " *)")
- $returns =~ s/\A\(\[.*?\]\((.*?)\)/\($1/ms;
+ $returns =~ s/\A\((const|)\s*\[.*?\]\((.*?)\)/\($2/ms;
# Chop datatype in parentheses off the front.
$returns =~ s/\A\(.*?\) //;
diff --git a/cmake/PrivateSdlFunctions.cmake b/cmake/PrivateSdlFunctions.cmake
index afabcd73..ab55d63e 100644
--- a/cmake/PrivateSdlFunctions.cmake
+++ b/cmake/PrivateSdlFunctions.cmake
@@ -280,7 +280,7 @@ function(check_linker_support_version_script VAR)
cmake_push_check_state(RESET)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.sym" "n_0 {\n global:\n func;\n local: *;\n};\n")
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/dummy.sym")
- check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error|unrecognized option)")
+ check_c_source_compiles("int func(void) {return 0;} int main(int argc,char*argv[]){(void)argc;(void)argv;return func();}" LINKER_SUPPORTS_VERSION_SCRIPT FAIL_REGEX "(unsupported|syntax error|unrecognized option|ignoring unknown argument|unknown file type)")
cmake_pop_check_state()
endif()
set(${VAR} "${LINKER_SUPPORTS_VERSION_SCRIPT}" PARENT_SCOPE)
diff --git a/cmake/sdlcpu.cmake b/cmake/sdlcpu.cmake
index a27e7329..fa7d4aa8 100644
--- a/cmake/sdlcpu.cmake
+++ b/cmake/sdlcpu.cmake
@@ -1,6 +1,6 @@
function(SDL_DetectTargetCPUArchitectures DETECTED_ARCHS)
- set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 POWERPC32 POWERPC64 RISCV32 RISCV64 X86 X64)
+ set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 MIPS32 MIPS64 POWERPC32 POWERPC64 RISCV32 RISCV64 X86 X64)
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
foreach(known_arch IN LISTS known_archs)
@@ -37,6 +37,8 @@ function(SDL_DetectTargetCPUArchitectures DETECTED_ARCHS)
set(arch_check_ARM64EC "defined(_M_ARM64EC)")
set(arch_check_EMSCRIPTEN "defined(__EMSCRIPTEN__)")
set(arch_check_LOONGARCH64 "defined(__loongarch64)")
+ set(arch_check_MIPS32 "(defined(__mips__) && !defined(__mips64))")
+ set(arch_check_MIPS64 "(defined(__mips__) && defined(__mips64))")
set(arch_check_POWERPC32 "(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)")
set(arch_check_POWERPC64 "defined(__PPC64__) || defined(__powerpc64__)")
set(arch_check_RISCV32 "defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 32")