You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@stevenhua0320 I checked and this is still not working on our latest vesrsion of the code.
Here are steps to fix this per chatgpt:
Here’s the practical, step-by-step way to bundle a C library DLL (e.g., libcblas.dll) inside a Python wheel so users don’t have to install it separately — exactly what the advice you received is referring to.
✅ How Python wheels handle DLLs on Windows
Wheels can contain native shared libraries (.dll, .so, .dylib) inside the wheel.
At runtime, Python loads them automatically as long as they are placed in the correct location in the wheel.
For Windows, the correct place is usually:
mypackage/
___init__.py
your_python_modules.py
libcblas.dll ← place DLL directly inside your package
Python will automatically search for DLLs located next to your extension modules or package code.
✅ How to include libcblas.dll in your wheel
Step 1 — Get libcblas.dll from conda-forge
Install the conda-forge package:
micromamba install -c conda-forge libcblas
Then locate the DLL:
<micromamba env>/Library/bin/libcblas.dll
Copy that file into your Python package directory, e.g.:
yourpackage/
__init__.py
...
lib/
libcblas.dll
Or put it at the top level of the package:
yourpackage/libcblas.dll
Both layouts work, but top-level inside the package is simplest.
✅ Step 2 — Add the DLL to your wheel using package_data
If you're using pyproject.toml with setuptools, add something like:
@sbillinge I have checked that libcblas file would have different file format. For MacOS (since I'm in Mac), the file ends with .dylib, which is not the file with format dll. I think dll file is supported on windows only. So, to get the file I think I need to manually download the dll file from conda-forge?
From my point, it is safer to do it for a person with a windows system as it can directly download from conda-forge with correct dll format and can build the package locally to see whether there's something wrong in the build of the package.
libcblas.dll from conda-forge doesn't work, and libgslcblas-0.dll from mingw64 suggested by ChatGPT also doesn't work. I'm not sure why, but I tried to use the file downloaded from mingw64, renaming it to libcblas.dll, and it worked.
Install mingw64, run pacman -Syu, pacman -S mingw-w64-x86_64-gsl
Copy libgslcbls-0.dll into diffpy.pdffit2/src/diffpy/pdffit2
Rename libgslcbls-0.dll to libcbls.dll.
Modify setup.py, add libgslcbls.dll as package_data
@ycexiao Let's ask Simon since it is only pertinent to windows platform. @sbillinge Should we add the libgslcbls.dll and the edits on pyproject.toml directly and make a PR or we add a INSTRUCTION.txt to the users? The former approach does less for the users but these edits would only affect windows users. The latter would make the code structure prettier but a little work for the windows user. What do you think?
Thanks so much @ycexiao this is amazing! We will have to include that file for it to work on windows, but it is a bit brittle. For example, we are not sure sure if that will work on all windows environments and if there are any updates in the future we would have to keep updating it.
Sorry just realize this happened. Before we do anything I think it’s better to make the situation clear, because this is not an isolated case. Everything need to be considered with the fact that the same fixing process should also works for diffpy.srreal, libdiffpy, pyobjcryst etc.
The main problem is how to build wheels for PyPI when things are built in a conda-oriented way. Several methods were tried, with the cibuildwheel path and manual build path. I will introduce them one by one.
cibuildwheel path
This path uses the official pypa/cibuildwheel GitHub Action to build wheels on Linux, macOS and Windows in isolated environments.
Good
Standard way to build PyPI wheels:
Cross-platform support out of the box.
Happens in containers, reproducible and isolated builds. it doesn’t pick up arbitrary things from the CI machine or a developer’s conda env, which helps avoid accidentally depending on libraries that users don’t have.
Bad
cibuildwheel runs in isolated build images and does not care about the conda environment. That means:
Any dependency that exists only in conda is invisible during the build. Even if there happens to be replacement from brew/yum/whatever it needs to be specifically configured in the workflow, which is very hard to make it work.
setup.py using $CONDA_PREFIX logics will fail.
Depends on the designed dynamic/static linking, setup.py might not behave good enough. For example here it only copies the gsl DLLs, not the blas / cblas DLLs that gsl depends on (e.g. the libcblas stuff from conda-forge).
In a simple way, because of the conda-oriented design, our wheels are very hard to be self-contained in a plain venv, and could very likely works by accident.
Manual conda-based build path
The manual workflow creates a conda environment on ubuntu-latest, installs everything from conda-forge, builds a wheel, and then repairs it using auditwheel plus custom patchelf steps.
Good
The build sees exactly the same conda environment we use for development and conda packaging, which could be self-contained.
All setup.py works as it is, could even modified to work for pure c libraries like libdiffpy.
We don’t need to fight cibuildwheel’s isolation.
Bad
Not thoroughly tested, could break in unexpected ways.
The patchelf logic is non-standard and could be fragile.
Anyone touching the release process needs to understand the surgery well enough.
As for the problem here, the pypi release for this version is using cibuildwheel. Luckily gsl is available outside of conda and the build process happens to work ok. But as said above, it leads to the self-contained problem. The only working states are (which's closely related to how it was built):
in venv
system level installed gsl on Mac and linux
Or in a conda environment for any platform
If we really want to have working wheels outside of conda, we need to decide which way to go, or maybe other better ways. It's very bad to repeat this every time we make a new release, which inevitably fail if anyone in the chain change anything.
Activity
sbillinge commentedon Apr 28, 2025
@Tieqiong this seems familiar, but please could you take a look?
Tieqiong commentedon May 23, 2025
@sbillinge Yes will test and fix this.
stevenhua0320 commentedon Nov 22, 2025
@sbillinge Have we fixed this? Since I don't have laptop with Windows at hand, I cannot test it right away.
sbillinge commentedon Nov 22, 2025
I will check. Please give me a minute
sbillinge commentedon Nov 22, 2025
I can confirm that everything works when installing from conda-forge, however, when installing directly from pip we are getting this import error:
stevenhua0320 commentedon Nov 22, 2025
I'm looking into this and checking where it breaks the import.
sbillinge commentedon Nov 22, 2025
Thanks. If you need help, please reach out to @Tieqiong
stevenhua0320 commentedon Nov 22, 2025
@Tieqiong could you help to look at why now we cannot import the
pdffit2directly bypip installit?sbillinge commentedon Nov 23, 2025
@stevenhua0320 I checked and this is still not working on our latest vesrsion of the code.
Here are steps to fix this per chatgpt:
Here’s the practical, step-by-step way to bundle a C library DLL (e.g.,
libcblas.dll) inside a Python wheel so users don’t have to install it separately — exactly what the advice you received is referring to.✅ How Python wheels handle DLLs on Windows
Wheels can contain native shared libraries (
.dll,.so,.dylib) inside the wheel.At runtime, Python loads them automatically as long as they are placed in the correct location in the wheel.
For Windows, the correct place is usually:
Python will automatically search for DLLs located next to your extension modules or package code.
✅ How to include
libcblas.dllin your wheelStep 1 — Get
libcblas.dllfrom conda-forgeInstall the conda-forge package:
Then locate the DLL:
Copy that file into your Python package directory, e.g.:
Or put it at the top level of the package:
Both layouts work, but top-level inside the package is simplest.
✅ Step 2 — Add the DLL to your wheel using
package_dataIf you're using pyproject.toml with setuptools, add something like:
Or if you put it into a
lib/folder:If you're using
setup.py, usepackage_data:✅ Step 3 — Verify that the wheel contains the DLL
Build your wheel:
List the wheel contents:
unzip -l dist/yourpackage-*.whlYou should see:
✅ Step 4 — Ensure Python can load the DLL
Put this in your
__init__.pyor in your module that loads C code:Python 3.8+ needs this on Windows because DLL loading rules changed.
If your DLL is in a subfolder:
⭐ Extra Notes
1. Bundling dependencies of dependencies
libcblas.dllmay depend on:You can discover dependencies using:
objdump -p libcblas.dll # On Linuxor:
dumpbin /DEPENDENTS libcblas.dllMost conda-forge DLLs depend on other conda-forge DLLs — you will need to include those as well unless they are Windows system DLLs.
stevenhua0320 commentedon Nov 23, 2025
@sbillinge I have checked that
libcblasfile would have different file format. For MacOS (since I'm in Mac), the file ends with.dylib, which is not the file with formatdll. I thinkdllfile is supported on windows only. So, to get the file I think I need to manually download thedllfile fromconda-forge?From my point, it is safer to do it for a person with a windows system as it can directly download from
conda-forgewith correctdllformat and can build the package locally to see whether there's something wrong in the build of the package.sbillinge commentedon Nov 23, 2025
Sounds good. Please work directly with someone who has windows.
ycexiao commentedon Nov 23, 2025
libcblas.dllfromconda-forgedoesn't work, andlibgslcblas-0.dllfrommingw64suggested by ChatGPT also doesn't work. I'm not sure why, but I tried to use the file downloaded frommingw64, renaming it tolibcblas.dll, and it worked.mingw64, runpacman -Syu,pacman -S mingw-w64-x86_64-gsllibgslcbls-0.dllintodiffpy.pdffit2/src/diffpy/pdffit2libgslcbls-0.dlltolibcbls.dll.setup.py, addlibgslcbls.dllaspackage_datapython -m buildpipinstall thewhlintest-pdffitrun
python -c "import diffpy.pdffit2; print(diffpy.pdffit2.__version__)"I think it is working now. @stevenhua0320, do you need the
whlfile I built in my local machine?stevenhua0320 commentedon Nov 23, 2025
Thanks @ycexiao ! could you create a PR for the edits you created and also send the wheel file to both me and @sbillinge so that we can test it out?
ycexiao commentedon Nov 23, 2025
I think the edits I made only make sense for
windows. Should these be included in our source code?stevenhua0320 commentedon Nov 23, 2025
@ycexiao Let's ask Simon since it is only pertinent to
windowsplatform. @sbillinge Should we add thelibgslcbls.dlland the edits onpyproject.tomldirectly and make a PR or we add aINSTRUCTION.txtto the users? The former approach does less for the users but these edits would only affectwindowsusers. The latter would make the code structure prettier but a little work for thewindowsuser. What do you think?sbillinge commentedon Nov 23, 2025
Thanks so much @ycexiao this is amazing! We will have to include that file for it to work on windows, but it is a bit brittle. For example, we are not sure sure if that will work on all windows environments and if there are any updates in the future we would have to keep updating it.
So, tl;dr, lets
Tieqiong commentedon Nov 24, 2025
Sorry just realize this happened. Before we do anything I think it’s better to make the situation clear, because this is not an isolated case. Everything need to be considered with the fact that the same fixing process should also works for diffpy.srreal, libdiffpy, pyobjcryst etc.
The main problem is how to build wheels for PyPI when things are built in a conda-oriented way. Several methods were tried, with the cibuildwheel path and manual build path. I will introduce them one by one.
This path uses the official pypa/cibuildwheel GitHub Action to build wheels on Linux, macOS and Windows in isolated environments.
Good
Bad
In a simple way, because of the conda-oriented design, our wheels are very hard to be self-contained in a plain venv, and could very likely works by accident.
The manual workflow creates a conda environment on ubuntu-latest, installs everything from conda-forge, builds a wheel, and then repairs it using auditwheel plus custom patchelf steps.
Good
Bad
As for the problem here, the pypi release for this version is using cibuildwheel. Luckily
gslis available outside of conda and the build process happens to work ok. But as said above, it leads to the self-contained problem. The only working states are (which's closely related to how it was built):If we really want to have working wheels outside of conda, we need to decide which way to go, or maybe other better ways. It's very bad to repeat this every time we make a new release, which inevitably fail if anyone in the chain change anything.