Skip to content

Commit b69ea6b

Browse files
committed
fix: fix missing dll for windows binary
1 parent bf70f06 commit b69ea6b

3 files changed

Lines changed: 58 additions & 3 deletions

File tree

anylabeling.spec

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,44 @@
11
# -*- mode: python -*-
22
# vim: ft=python
33

4+
import os
45
import sys
56

67
sys.setrecursionlimit(5000) # required on Windows
78

9+
# Collect onnxruntime native DLLs (onnxruntime.dll, onnxruntime_providers_shared.dll).
10+
# PyInstaller resolves imports but does NOT automatically bundle the DLLs that sit
11+
# next to the .pyd extension inside the onnxruntime/capi package directory.
12+
try:
13+
import onnxruntime as _ort
14+
_ort_capi = os.path.join(os.path.dirname(_ort.__file__), 'capi')
15+
_ort_dlls = [
16+
os.path.join(_ort_capi, f)
17+
for f in os.listdir(_ort_capi)
18+
if f.endswith('.dll')
19+
]
20+
# Place DLLs in both locations:
21+
# onnxruntime/capi/ — matches package structure, found via DLL_LOAD_DIR
22+
# . (root _MEIPASS) — found via PyInstaller's SetDllDirectory(_MEIPASS)
23+
_ort_binaries = (
24+
[(dll, 'onnxruntime/capi') for dll in _ort_dlls]
25+
+ [(dll, '.') for dll in _ort_dlls]
26+
)
27+
except Exception:
28+
_ort_binaries = []
29+
830
a = Analysis(
931
['anylabeling/app.py'],
1032
pathex=['anylabeling'],
11-
binaries=[],
33+
binaries=_ort_binaries,
1234
datas=[
1335
('anylabeling/configs/auto_labeling/*.yaml', 'anylabeling/configs/auto_labeling'),
1436
('anylabeling/configs/*.yaml', 'anylabeling/configs'),
1537
('anylabeling/views/labeling/widgets/auto_labeling/auto_labeling.ui', 'anylabeling/views/labeling/widgets/auto_labeling')
1638
],
1739
hiddenimports=[],
1840
hookspath=[],
19-
runtime_hooks=[],
41+
runtime_hooks=['rthooks/rthook_onnxruntime.py'],
2042
excludes=[],
2143
)
2244
pyz = PYZ(a.pure, a.zipped_data)

anylabeling/app_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
__appname__ = "AnyLabeling"
22
__appdescription__ = "Effortless data labeling with AI support"
3-
__version__ = "0.4.34"
3+
__version__ = "0.4.35"
44
__preferred_device__ = "CPU" # GPU or CPU"

rthooks/rthook_onnxruntime.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""
2+
Runtime hook: preload onnxruntime native DLLs before any Python import can fail.
3+
4+
The problem:
5+
onnxruntime_pybind11_state.pyd imports onnxruntime.dll, which during its
6+
DllMain calls LoadLibraryW("onnxruntime_providers_shared.dll") using the
7+
standard Win32 search order (SetDllDirectory / PATH), NOT the
8+
AddDllDirectory search order. In a one-file PyInstaller bundle the DLLs
9+
land in _MEIPASS/onnxruntime/capi/ — a subdirectory that is NOT covered by
10+
either SetDllDirectory(_MEIPASS) or PATH in a clean deployment.
11+
12+
The fix:
13+
Load both DLLs by absolute path with ctypes.WinDLL() here, before Python's
14+
importlib ever tries to load the .pyd. Once a DLL is loaded into the
15+
process the Windows loader returns the cached handle on any subsequent
16+
LoadLibraryW call for the same module name, so ORT's internal lookup
17+
succeeds regardless of search-path issues.
18+
"""
19+
20+
import ctypes
21+
import os
22+
import sys
23+
24+
if sys.platform == "win32" and hasattr(sys, "_MEIPASS"):
25+
_capi = os.path.join(sys._MEIPASS, "onnxruntime", "capi")
26+
# Load in dependency order: shared lib first, then main DLL
27+
for _dll in ("onnxruntime_providers_shared.dll", "onnxruntime.dll"):
28+
_path = os.path.join(_capi, _dll)
29+
if os.path.isfile(_path):
30+
ctypes.WinDLL(_path)
31+
# Also register the directory so Python's importlib finds the .pyd
32+
if os.path.isdir(_capi):
33+
os.add_dll_directory(_capi)

0 commit comments

Comments
 (0)