Skip to content

Commit f6539b1

Browse files
emerybergerclaude
andcommitted
Fix Windows wheel missing libscalene.dll for memory profiling
The Windows wheels on PyPI were missing libscalene.dll because the CI workflow did not install CMake, causing the DLL build to be silently skipped. Changes: - Add CMake installation step for Windows builds in CI workflow - Add verification step to fail build if libscalene.dll is missing - Improve setup.py Windows build with explicit architecture detection - Add more search paths for built DLL and better debug output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent adb2ce2 commit f6539b1

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

.github/workflows/build-and-upload.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ jobs:
117117
if: matrix.os == 'macos-latest'
118118
run: sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*
119119

120+
- name: Install CMake on Windows
121+
# CMake is required to build libscalene.dll for memory profiling on Windows
122+
if: matrix.os == 'windows-latest'
123+
run: choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y
124+
120125
- name: Build source dist
121126
if: matrix.upload_source
122127
run: make sdist
@@ -139,6 +144,33 @@ jobs:
139144
fi
140145
done
141146
done
147+
148+
- name: Check that libscalene.dll is included in Windows wheel
149+
if: matrix.os == 'windows-latest'
150+
shell: python
151+
run: |
152+
import zipfile
153+
import glob
154+
import sys
155+
156+
wheels = glob.glob('dist/*.whl')
157+
if not wheels:
158+
print("ERROR: No wheel files found")
159+
sys.exit(1)
160+
161+
for whl in wheels:
162+
print(f"Checking {whl}...")
163+
with zipfile.ZipFile(whl, 'r') as z:
164+
files = z.namelist()
165+
dll_files = [f for f in files if 'libscalene.dll' in f]
166+
if dll_files:
167+
print(f" Found: {dll_files}")
168+
else:
169+
print(f" ERROR: libscalene.dll not found in wheel!")
170+
print(f" Files in wheel: {[f for f in files if f.endswith(('.dll', '.pyd', '.so'))]}")
171+
sys.exit(1)
172+
173+
print("All Windows wheels contain libscalene.dll")
142174
143175
- name: Non-release (dev) upload
144176
if: github.event_name != 'release'

setup.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,15 +248,33 @@ def build_libscalene_windows(self):
248248
return
249249

250250
try:
251+
# Detect architecture for Windows builds
252+
import platform
253+
machine = platform.machine().lower()
254+
if machine in ('amd64', 'x86_64'):
255+
cmake_arch = 'x64'
256+
elif machine in ('arm64', 'aarch64'):
257+
cmake_arch = 'ARM64'
258+
else:
259+
cmake_arch = None
260+
print(f"Warning: Unknown architecture '{machine}', using default CMake generator")
261+
251262
# Configure with CMake
252-
self.spawn([
263+
cmake_config = [
253264
'cmake',
254265
'-S', '.',
255266
'-B', cmake_build_dir,
256267
'-DCMAKE_BUILD_TYPE=Release',
257268
f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={scalene_temp}',
258269
f'-DCMAKE_RUNTIME_OUTPUT_DIRECTORY={scalene_temp}',
259-
])
270+
]
271+
272+
# Add architecture-specific options for Visual Studio generator
273+
if cmake_arch:
274+
cmake_config.extend(['-A', cmake_arch])
275+
print(f"Building libscalene.dll for {cmake_arch} architecture")
276+
277+
self.spawn(cmake_config)
260278

261279
# Build
262280
self.spawn([
@@ -266,19 +284,28 @@ def build_libscalene_windows(self):
266284
])
267285

268286
# Copy the DLL
269-
# On Windows, CMake may put the DLL in a Release subdirectory
287+
# On Windows, CMake may put the DLL in various locations depending on
288+
# how the build is configured. Check all possible locations.
289+
project_dir = path.dirname(path.abspath(__file__))
270290
possible_paths = [
271291
path.join(scalene_temp, libscalene),
272292
path.join(scalene_temp, 'Release', libscalene),
273293
path.join(cmake_build_dir, 'Release', libscalene),
294+
path.join(cmake_build_dir, libscalene),
295+
# CMakeLists.txt may override output dir to project's scalene folder
296+
path.join(project_dir, 'scalene', libscalene),
297+
path.join(project_dir, 'scalene', 'Release', libscalene),
274298
]
275299

276300
for src_path in possible_paths:
277301
if path.exists(src_path):
302+
print(f"Found {libscalene} at {src_path}")
278303
self.copy_file(src_path, path.join(scalene_lib, libscalene))
304+
print(f"Copied to {path.join(scalene_lib, libscalene)}")
279305
break
280306
else:
281307
print(f"Warning: Could not find {libscalene} after build")
308+
print(f"Searched in: {possible_paths}")
282309

283310
except Exception as e:
284311
print(f"Warning: Failed to build libscalene on Windows: {e}")

0 commit comments

Comments
 (0)