-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Required prerequisites
- Make sure you've read the documentation. Your issue may be addressed there.
- Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
- Consider asking first in the Gitter chat room or in a Discussion.
What version (or hash if on master) of pybind11 are you using?
v3.0.0
Problem description
I work on a project, musica, which includes some Fortran sources. We’re starting to support building it on Windows using msys2. The error I’m about to describe is unrelated to Fortran, but I encountered it while trying to build a pybind11 module on ARM-based Windows, hence the use of msys2.
Building on AMD64-based Windows works just fine. However, building with a windows-11-arm runner in GitHub Actions and using clang, a pybind11 module fails to build because of symbol visibility.
I recreated the same error I see in the musica library in this much smaller repository:
- smaller repository (scratch)
- You can see the same visibility build error shows up in the actions
-- Building for: Ninja
-- The CXX compiler identification is Clang 21.1.4
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/a/_temp/msys64/clangarm64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- pybind11 v3.0.0
-- Found Python: C:/hostedtoolcache/windows/Python/3.11.9/arm64/python.exe (found suitable version "3.11.9", minimum required is "3.8") found components: Interpreter Development.Module Development.Embed
Using compatibility mode for Python, set PYBIND11_FINDPYTHON to NEW/OLD to silence this message
-- pybind11::lto disabled (problems with undefined symbols for MinGW for now)
-- pybind11::thin_lto disabled (problems with undefined symbols for MinGW for now)
-- Configuring done (7.1s)
-- Generating done (0.0s)
-- Build files have been written to: C:/a/_temp/msys64/tmp/tmpbydxfxd2/build
*** Building project with Ninja...
2025-10-27 12:55:48,604 - scikit_build_core - DEBUG - RUNENV - changes since last run only:
2025-10-27 12:55:48,604 - scikit_build_core - INFO - RUN: C:\a\_temp\msys64\clangarm64\bin\cmake.EXE --build C:\a\_temp\msys64\tmp\tmpbydxfxd2\build -v
Change Dir: 'C:/a/_temp/msys64/tmp/tmpbydxfxd2/build'
Run Build Command(s): C:\a\_temp\msys64\clangarm64\bin\ninja.EXE -v
[1/4] C:\Windows\system32\cmd.exe /C ""C:/a/_temp/msys64/clangarm64/bin/clang-scan-deps.exe" -format=p1689 -- C:\a\_temp\msys64\clangarm64\bin\c++.exe -DPy_NO_LINK_LIB -Dtest_EXPORTS -isystem C:/hostedtoolcache/windows/Python/3.11.9/arm64/Include -isystem C:/a/_temp/msys64/tmp/tmpbydxfxd2/build/_deps/pybind11-src/include -O3 -DNDEBUG -std=gnu++20 -fvisibility=hidden -x c++ C:/a/scratch/scratch/pybind/test.cpp -c -o CMakeFiles\test.dir\test.cpp.obj -resource-dir "C:/a/_temp/msys64/clangarm64/lib/clang/21" -MT CMakeFiles\test.dir\test.cpp.obj.ddi -MD -MF CMakeFiles\test.dir\test.cpp.obj.ddi.d > CMakeFiles\test.dir\test.cpp.obj.ddi.tmp && "C:/a/_temp/msys64/clangarm64/bin/cmake.exe" -E rename CMakeFiles\test.dir\test.cpp.obj.ddi.tmp CMakeFiles\test.dir\test.cpp.obj.ddi"
[2/4] C:\a\_temp\msys64\clangarm64\bin\cmake.exe -E cmake_ninja_dyndep --tdi=CMakeFiles\test.dir\CXXDependInfo.json --lang=CXX --modmapfmt=clang --dd=CMakeFiles/test.dir/CXX.dd @CMakeFiles/test.dir/CXX.dd.rsp
[3/4] C:\a\_temp\msys64\clangarm64\bin\c++.exe -DPy_NO_LINK_LIB -Dtest_EXPORTS -isystem C:/hostedtoolcache/windows/Python/3.11.9/arm64/Include -isystem C:/a/_temp/msys64/tmp/tmpbydxfxd2/build/_deps/pybind11-src/include -O3 -DNDEBUG -std=gnu++20 -fvisibility=hidden -MD -MT CMakeFiles/test.dir/test.cpp.obj -MF CMakeFiles\test.dir\test.cpp.obj.d @CMakeFiles\test.dir\test.cpp.obj.modmap -o CMakeFiles/test.dir/test.cpp.obj -c C:/a/scratch/scratch/pybind/test.cpp
FAILED: [code=1] CMakeFiles/test.dir/test.cpp.obj
C:\a\_temp\msys64\clangarm64\bin\c++.exe -DPy_NO_LINK_LIB -Dtest_EXPORTS -isystem C:/hostedtoolcache/windows/Python/3.11.9/arm64/Include -isystem C:/a/_temp/msys64/tmp/tmpbydxfxd2/build/_deps/pybind11-src/include -O3 -DNDEBUG -std=gnu++20 -fvisibility=hidden -MD -MT CMakeFiles/test.dir/test.cpp.obj -MF CMakeFiles\test.dir\test.cpp.obj.d @CMakeFiles\test.dir\test.cpp.obj.modmap -o CMakeFiles/test.dir/test.cpp.obj -c C:/a/scratch/scratch/pybind/test.cpp
In file included from C:/a/scratch/scratch/pybind/test.cpp:1:
C:/a/_temp/msys64/tmp/tmpbydxfxd2/build/_deps/pybind11-src/include/pybind11/pybind11.h:3334:20: error: hidden visibility cannot be applied to 'dllexport' declaration
3334 | error_already_set::m_fetched_error_deleter(detail::error_fetch_and_normalize *raw_ptr) {
| ^
C:/a/_temp/msys64/tmp/tmpbydxfxd2/build/_deps/pybind11-src/include/pybind11/pybind11.h:3340:39: error: hidden visibility cannot be applied to 'dllexport' declaration
3340 | inline const char *error_already_set::what() const noexcept {
| ^
2 errors generated.
ninja: build stopped: subcommand failed.
*** CMake build failed
ERROR Backend subprocess exited when trying to invoke build_wheel
- Even if I set the visibility on the cmake target to default, there's still a build error
if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set_property(TARGET test PROPERTY CXX_VISIBILITY_PRESET "default") endif()
-- Building for: Ninja
-- The CXX compiler identification is Clang 21.1.4
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/a/_temp/msys64/clangarm64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- pybind11 v3.0.0
-- Found Python: C:/hostedtoolcache/windows/Python/3.13.5/arm64/python.exe (found suitable version "3.13.5", minimum required is "3.8") found components: Interpreter Development.Module Development.Embed
Using compatibility mode for Python, set PYBIND11_FINDPYTHON to NEW/OLD to silence this message
-- pybind11::lto disabled (problems with undefined symbols for MinGW for now)
-- pybind11::thin_lto disabled (problems with undefined symbols for MinGW for now)
-- Configuring done (6.7s)
-- Generating done (0.0s)
-- Build files have been written to: C:/a/_temp/msys64/tmp/tmpgiskwr9z/build
*** Building project with Ninja...
2025-10-27 13:27:25,636 - scikit_build_core - DEBUG - RUNENV - changes since last run only:
2025-10-27 13:27:25,637 - scikit_build_core - INFO - RUN: C:\a\_temp\msys64\clangarm64\bin\cmake.EXE --build C:\a\_temp\msys64\tmp\tmpgiskwr9z\build -v
Change Dir: 'C:/a/_temp/msys64/tmp/tmpgiskwr9z/build'
Run Build Command(s): C:\a\_temp\msys64\clangarm64\bin\ninja.EXE -v
[1/4] C:\Windows\system32\cmd.exe /C ""C:/a/_temp/msys64/clangarm64/bin/clang-scan-deps.exe" -format=p1689 -- C:\a\_temp\msys64\clangarm64\bin\c++.exe -DPy_NO_LINK_LIB -Dtest_EXPORTS -isystem C:/hostedtoolcache/windows/Python/3.13.5/arm64/Include -isystem C:/a/_temp/msys64/tmp/tmpgiskwr9z/build/_deps/pybind11-src/include -O3 -DNDEBUG -std=gnu++20 -fvisibility=default -x c++ C:/a/scratch/scratch/pybind/test.cpp -c -o CMakeFiles\test.dir\test.cpp.obj -resource-dir "C:/a/_temp/msys64/clangarm64/lib/clang/21" -MT CMakeFiles\test.dir\test.cpp.obj.ddi -MD -MF CMakeFiles\test.dir\test.cpp.obj.ddi.d > CMakeFiles\test.dir\test.cpp.obj.ddi.tmp && "C:/a/_temp/msys64/clangarm64/bin/cmake.exe" -E rename CMakeFiles\test.dir\test.cpp.obj.ddi.tmp CMakeFiles\test.dir\test.cpp.obj.ddi"
[2/4] C:\a\_temp\msys64\clangarm64\bin\cmake.exe -E cmake_ninja_dyndep --tdi=CMakeFiles\test.dir\CXXDependInfo.json --lang=CXX --modmapfmt=clang --dd=CMakeFiles/test.dir/CXX.dd @CMakeFiles/test.dir/CXX.dd.rsp
[3/4] C:\a\_temp\msys64\clangarm64\bin\c++.exe -DPy_NO_LINK_LIB -Dtest_EXPORTS -isystem C:/hostedtoolcache/windows/Python/3.13.5/arm64/Include -isystem C:/a/_temp/msys64/tmp/tmpgiskwr9z/build/_deps/pybind11-src/include -O3 -DNDEBUG -std=gnu++20 -fvisibility=default -MD -MT CMakeFiles/test.dir/test.cpp.obj -MF CMakeFiles\test.dir\test.cpp.obj.d @CMakeFiles\test.dir\test.cpp.obj.modmap -o CMakeFiles/test.dir/test.cpp.obj -c C:/a/scratch/scratch/pybind/test.cpp
FAILED: [code=1] CMakeFiles/test.dir/test.cpp.obj
C:\a\_temp\msys64\clangarm64\bin\c++.exe -DPy_NO_LINK_LIB -Dtest_EXPORTS -isystem C:/hostedtoolcache/windows/Python/3.13.5/arm64/Include -isystem C:/a/_temp/msys64/tmp/tmpgiskwr9z/build/_deps/pybind11-src/include -O3 -DNDEBUG -std=gnu++20 -fvisibility=default -MD -MT CMakeFiles/test.dir/test.cpp.obj -MF CMakeFiles\test.dir\test.cpp.obj.d @CMakeFiles\test.dir\test.cpp.obj.modmap -o CMakeFiles/test.dir/test.cpp.obj -c C:/a/scratch/scratch/pybind/test.cpp
In file included from C:/a/scratch/scratch/pybind/test.cpp:1:
C:/a/_temp/msys64/tmp/tmpgiskwr9z/build/_deps/pybind11-src/include/pybind11/pybind11.h:3334:20: error: hidden visibility cannot be applied to 'dllexport' declaration
3334 | error_already_set::m_fetched_error_deleter(detail::error_fetch_and_normalize *raw_ptr) {
| ^
C:/a/_temp/msys64/tmp/tmpgiskwr9z/build/_deps/pybind11-src/include/pybind11/pybind11.h:3340:39: error: hidden visibility cannot be applied to 'dllexport' declaration
3340 | inline const char *error_already_set::what() const noexcept {
| ^
2 errors generated.
ninja: build stopped: subcommand failed.
*** CMake build failed
ERROR Backend subprocess exited when trying to invoke build_wheel
I think what may be happening is that dllexport gets added from PYBIND11_EXPORT, but that -fvisibility=hidden gets added by tools or maybe new tools.
I can't tell if this is a bug in pybind11, or just a tooling issue that I need to work around. Either way, since I have not changed any defaults, I figured it was worth reporting.
Reproducible example code
cmake_minimum_required(VERSION 3.20)
project(test VERSION 0.0.0 LANGUAGES CXX)
include(FetchContent)
FetchContent_Declare(pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11
GIT_TAG v3.0.0
FIND_PACKAGE_ARGS NAMES pybind11
)
FetchContent_MakeAvailable(pybind11)
find_package(pybind11 REQUIRED)
pybind11_add_module(test
test.cpp
)
target_compile_features(test PUBLIC cxx_std_20)
#include <pybind11/pybind11.h>
using namespace pybind11;
PYBIND11_MODULE(test, m) {
m.def("add", [](int a, int b){ return a + b; });
}
[build-system]
requires = ["scikit-build-core>=0.11.0"]
build-backend = "scikit_build_core.build"
[project]
name = "test"
dynamic = ["version"]
[tool.scikit-build]
cmake.build-type = "Release"
build.verbose = true
logging.level = "DEBUG"
[tool.scikit-build.metadata.version]
provider = "scikit_build_core.metadata.regex"
input = "CMakeLists.txt"
regex = 'test VERSION\s+(?P<value>[0-9.]+)'
[[tool.scikit-build.generate]]
path = "test/_version.py"
template = '''
version = "${version}"
'''
[tool.cibuildwheel]
build-verbosity = 3
[tool.cibuildwheel.windows]
repair-wheel-command = "bash repair_wheel_windows.sh {wheel} {dest_dir}"
name: Python tests
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
jobs:
pybind:
name: Test Python (${{ matrix.os }}, ${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-11-arm]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
exclude:
- os: windows-11-arm
python-version: "3.9"
- os: windows-11-arm
python-version: "3.10"
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: msys2/setup-msys2@v2
with:
msystem: CLANGARM64
update: true
install: |
mingw-w64-clang-aarch64-cmake
mingw-w64-clang-aarch64-clang
mingw-w64-clang-aarch64-flang
mingw-w64-clang-aarch64-hdf5
mingw-w64-clang-aarch64-ninja
mingw-w64-clang-aarch64-netcdf
mingw-w64-clang-aarch64-netcdf-fortran
mingw-w64-clang-aarch64-openblas
mingw-w64-clang-aarch64-pkgconf
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Add python build tools
run: python -m pip install --upgrade wheel setuptools build scikit-build-core
- name: Build wheel (Windows)
if: startsWith(matrix.os, 'windows')
shell: msys2 {0}
run: |
cd pybind
MSYS2_PYTHON=$(cygpath -u "$pythonLocation")
"$MSYS2_PYTHON/python.exe" -m build --wheel --no-isolation --outdir wheelhouse
Is this a regression? Put the last known working version here if it is.
Not a regression