Skip to content

Commit c828924

Browse files
committed
Update binary loading system.
1 parent 64a7460 commit c828924

File tree

1 file changed

+41
-26
lines changed

1 file changed

+41
-26
lines changed

sdl3/__init__.py

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ def SDL_FORMAT_ARCH(arch: str) -> str:
2424
assert False, "Unknown architecture."
2525

2626
SDL_SYSTEM, SDL_ARCH = platform.system(), SDL_FORMAT_ARCH(platform.machine())
27-
SDL_BINARY_PATTERNS: dict[str, list[str]] = \
28-
{"Windows": ["{}.dll"], "Darwin": ["lib{}.dylib", "{0}.framework/{0}", "{0}.framework/Versions/A/{0}"], "Linux": ["lib{}.so"]}
27+
SDL_BINARY_EXTENSIONS, SDL_BINARY_PATTERNS = {"Windows": ["dll"], "Darwin": ["dylib"], "Linux": ["so"]}, \
28+
{"Windows": ["{}.dll"], "Darwin": ["lib{}.dylib", "{0}.framework/{0}", "{0}.framework/Versions/Current/{0}"], "Linux": ["lib{}.so"]}
2929

3030
def SDL_PLATFORM_SPECIFIC(system: list[str] = None, arch: list[str] = None) -> bool:
3131
"""Check if the current platform is inside the given platforms."""
@@ -64,10 +64,10 @@ def Log(cls, level: int, message: str | None = None, end: str | None = "\n") ->
6464
def SDL_FIND_BINARIES(libraries: list[str]) -> list[str]:
6565
"""Search for binaries in the system libraries."""
6666
libraries = libraries + [f"{library}d" for library in libraries]
67-
binaries = [f"./{file}" if SDL_SYSTEM in ["Windows"] and not ("/" in file or "\\" in file) else file for library in libraries if (file := ctypes.util.find_library(library))]
67+
binaries = [(f"./{file}" if SDL_SYSTEM in ["Windows"] and not ("/" in file or "\\" in file) else file) for library in libraries if (file := ctypes.util.find_library(library))]
6868

6969
if SDL_SYSTEM in ["Darwin"] and SDL_ARCH in ["ARM64"] and os.path.exists(path := "/opt/Homebrew/lib"):
70-
binaries += [file for library in libraries for pattern in SDL_BINARY_PATTERNS if os.path.exists(file := os.path.join(path, pattern.format(library)))]
70+
binaries += [file for library in libraries for pattern in SDL_BINARY_PATTERNS[SDL_SYSTEM] if os.path.exists(file := os.path.join(path, pattern.format(library)))]
7171

7272
return binaries
7373

@@ -139,6 +139,15 @@ def SDL_DOWNLOAD_BINARIES(path: str, system: str = SDL_SYSTEM, arch: str = SDL_A
139139
SDL_LOGGER.Log(SDL_LOGGER.Error, f"Failed to download binaries: {exc}.")
140140
return False
141141

142+
def SDL_CHECK_BINARY_NAME(name: str) -> bool:
143+
"""Check if the given name is a valid binary name in the current system."""
144+
145+
if len(_ := name.split(".")) > 1:
146+
return _[1] in SDL_BINARY_EXTENSIONS[SDL_SYSTEM]
147+
148+
else:
149+
return SDL_SYSTEM in ["Darwin"]
150+
142151
if not __initialized__:
143152
if int(os.environ.get("SDL_CHECK_VERSION", "0" if __frozen__ else "1")) > 0:
144153
try:
@@ -150,24 +159,30 @@ def SDL_DOWNLOAD_BINARIES(path: str, system: str = SDL_SYSTEM, arch: str = SDL_A
150159
except requests.RequestException:
151160
...
152161

153-
functions, binaryMap = {i: {} for i in SDL_BINARY_VAR_MAP_INV}, {}
162+
functions, binaryMap = {binary: {} for binary in SDL_BINARY_VAR_MAP_INV}, {}
154163
binaryData, missing = {"system": SDL_SYSTEM, "arch": SDL_ARCH, "files": []}, None
155164
binaryPath = os.environ.get("SDL_BINARY_PATH", os.path.join(os.path.dirname(__file__), "bin"))
156165
absPath = lambda path: path if os.path.isabs(path) else os.path.abspath(os.path.join(binaryPath, path))
157-
if not os.path.exists(binaryPath): os.makedirs(binaryPath)
166+
167+
if not os.path.exists(binaryPath):
168+
try:
169+
os.makedirs(binaryPath)
170+
171+
except OSError as exc:
172+
SDL_LOGGER.Log(SDL_LOGGER.Error, f"Failed to create binary path: {exc}.")
158173

159174
if int(os.environ.get("SDL_DISABLE_METADATA", "0")) > 0:
160-
for root, _, files in os.walk(binaryPath):
161-
for file in files:
162-
if (file.endswith(".dll") and SDL_SYSTEM in ["Windows"]) \
163-
or ((file.endswith(".dylib") or ".framework" in file) and SDL_SYSTEM in ["Darwin"]) \
164-
or (".so" in file and SDL_SYSTEM in ["Linux"]):
165-
binaryData["files"].append(os.path.join(root, file))
175+
if os.path.exists(binaryPath) and os.path.isdir(binaryPath):
176+
for root, _, files in os.walk(binaryPath):
177+
binaryData["files"] += [os.path.join(root, file) for file in files if SDL_CHECK_BINARY_NAME(file)]
178+
179+
else:
180+
SDL_LOGGER.Log(SDL_LOGGER.Warning, f"Binary path does not exist.")
166181

167182
elif "metadata.json" in (files := os.listdir(binaryPath)):
168183
with open(os.path.join(binaryPath, "metadata.json"), "r") as file:
169-
missing, binaryData = True, json.load(file)
170-
binaryData["files"] = [absPath(i) for i in binaryData["files"]]
184+
binaryData, missing = json.load(file), True
185+
binaryData["files"] = [absPath(path) for path in binaryData["files"]]
171186

172187
if packaging.version.parse(__version__) > packaging.version.parse(binaryData.get("target", __version__)):
173188
SDL_LOGGER.Log(SDL_LOGGER.Warning, f"Incompatible target version detected: '{binaryData['target']}', current: 'v{__version__}'.")
@@ -176,11 +191,11 @@ def SDL_DOWNLOAD_BINARIES(path: str, system: str = SDL_SYSTEM, arch: str = SDL_A
176191
SDL_LOGGER.Log(SDL_LOGGER.Warning, f"Incompatible binary architecture and/or system detected: '{binaryData['system']} ({binaryData['arch']})'.")
177192
binaryData["repair"] = True
178193

179-
for i in binaryData["files"]:
180-
if os.path.exists(i): os.remove(i)
194+
for path in binaryData["files"]:
195+
if os.path.exists(path): os.remove(path)
181196

182197
else:
183-
if missing := [i for i in binaryData["files"] if not os.path.exists(i)]:
198+
if missing := [path for path in binaryData["files"] if not os.path.exists(path)]:
184199
SDL_LOGGER.Log(SDL_LOGGER.Warning, f"Missing binary file(s) detected: '{', '.join(missing)}'.")
185200

186201
else:
@@ -191,20 +206,20 @@ def SDL_DOWNLOAD_BINARIES(path: str, system: str = SDL_SYSTEM, arch: str = SDL_A
191206
if _ := SDL_DOWNLOAD_BINARIES(binaryPath, SDL_SYSTEM, SDL_ARCH):
192207
with open(os.path.join(binaryPath, "metadata.json"), "r") as file:
193208
binaryData, missing = json.load(file), None
194-
binaryData["files"] = [absPath(i) for i in binaryData["files"]]
209+
binaryData["files"] = [absPath(path) for path in binaryData["files"]]
195210

196211
if int(os.environ.get("SDL_FIND_BINARIES", "1" if binaryData.get("find", missing is None) else "0")) > 0:
197212
binaryData["files"] += SDL_FIND_BINARIES(list(SDL_BINARY_VAR_MAP_INV.keys()))
198213

199214
for binary in SDL_BINARY_VAR_MAP_INV:
200-
for path in binaryData["files"].copy():
201-
if (file := os.path.split(path)[1]).split(".")[0].endswith(binary) and os.path.exists(path):
202-
if (file.endswith(".dll") and SDL_SYSTEM in ["Windows"]) \
203-
or ((file.endswith(".dylib") or ".framework" in file) and SDL_SYSTEM in ["Darwin"]) \
204-
or (".so" in file and SDL_SYSTEM in ["Linux"]):
205-
binaryMap[binary], functions[binary] = ctypes.CDLL(os.path.abspath(path)), {}
206-
binaryData["files"].remove(path)
207-
break
215+
for path in binaryData["files"]:
216+
if binary in binaryMap:
217+
break
218+
219+
if os.path.exists(path) and SDL_CHECK_BINARY_NAME(name := os.path.split(path)[1]):
220+
for _binary in [binary, f"{binary}d"]:
221+
if (name.split(".")[0] if "." in name else name).endswith(_binary):
222+
binaryMap[binary] = ctypes.CDLL(os.path.abspath(path))
208223

209224
BaseType = typing.TypeVar("BaseType")
210225
TargetType = typing.TypeVar("TargetType")

0 commit comments

Comments
 (0)