From 9e8a741baac7485a7f81904bbb9c06a9ae423c40 Mon Sep 17 00:00:00 2001 From: Jerome Robert Date: Fri, 30 Jul 2021 19:48:41 +0200 Subject: [PATCH] fix: Mingw64 corrected and add a CI job to test it (#3132) * mingw64 platform string is like mingw_xxx not "mingw" See https://github.com/msys2/MINGW-packages/blob/master/mingw-w64-python/0099-Change-the-get_platform-method-in-sysconfig-and-dist.patch * Mingw: Do not dllexport exceptions This is a fix for errors like: D:/a/pybind11/pybind11/include/pybind11/detail/common.h:735:23: error: 'dllexport' implies default visibility, but 'class pybind11::builtin_exception' has already been declared with a different visibility 735 | class PYBIND11_EXPORT builtin_exception : public std::runtime_error { | ^~~~~~~~~~~~~~~~~ * GHA: Test Mingw64 build * fix: avoid thin binaries on mingw * fix: drop lto on MinGW * Mingw64: disable PYBIND11_DEPRECATED It trigger many warnings for unknown reasons Co-authored-by: Henry Schreiner --- .github/workflows/ci.yml | 31 +++++++++++++++++++++++++++++++ include/pybind11/detail/common.h | 20 +++++++++++++++++--- include/pybind11/pytypes.h | 2 +- pybind11/setup_helpers.py | 3 +-- tests/test_exceptions.h | 2 +- tools/pybind11Common.cmake | 7 ++++++- 6 files changed, 57 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03c9225c1..73a6fd519 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -859,3 +859,34 @@ jobs: - name: Run all checks run: cmake --build build -t check + + mingw: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + steps: + - uses: msys2/setup-msys2@v2 + with: + install: >- + mingw-w64-x86_64-gcc + mingw-w64-x86_64-python-pip + mingw-w64-x86_64-cmake + mingw-w64-x86_64-make + mingw-w64-x86_64-python-pytest + mingw-w64-x86_64-eigen3 + mingw-w64-x86_64-boost + mingw-w64-x86_64-catch + + - uses: actions/checkout@v1 + + - name: Configure + # LTO leads to many undefined reference like + # `pybind11::detail::function_call::function_call(pybind11::detail::function_call&&) + run: cmake -G "MinGW Makefiles" -S . -B build + + - name: Build + run: cmake --build build -j 2 + + - name: Python tests + run: cmake --build build --target pytest diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 0add6272f..d63e3e9c7 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -89,13 +89,27 @@ # endif #endif +#if !defined(PYBIND11_EXPORT_EXCEPTION) +# ifdef __MINGW32__ +// workaround for: +// error: 'dllexport' implies default visibility, but xxx has already been declared with a different visibility +# define PYBIND11_EXPORT_EXCEPTION +# else +# define PYBIND11_EXPORT_EXCEPTION PYBIND11_EXPORT +# endif +#endif + #if defined(_MSC_VER) # define PYBIND11_NOINLINE __declspec(noinline) #else # define PYBIND11_NOINLINE __attribute__ ((noinline)) #endif -#if defined(PYBIND11_CPP14) +#if defined(__MINGW32__) +// For unknown reasons all PYBIND11_DEPRECATED member trigger a warning when declared +// whether it is used or not +# define PYBIND11_DEPRECATED(reason) +#elif defined(PYBIND11_CPP14) # define PYBIND11_DEPRECATED(reason) [[deprecated(reason)]] #else # define PYBIND11_DEPRECATED(reason) __attribute__((deprecated(reason))) @@ -740,7 +754,7 @@ PYBIND11_NAMESPACE_END(detail) # pragma warning(disable: 4275) // warning C4275: An exported class was derived from a class that wasn't exported. Can be ignored when derived from a STL class. #endif /// C++ bindings of builtin Python exceptions -class PYBIND11_EXPORT builtin_exception : public std::runtime_error { +class PYBIND11_EXPORT_EXCEPTION builtin_exception : public std::runtime_error { public: using std::runtime_error::runtime_error; /// Set the error using the Python C API @@ -751,7 +765,7 @@ public: #endif #define PYBIND11_RUNTIME_EXCEPTION(name, type) \ - class PYBIND11_EXPORT name : public builtin_exception { public: \ + class PYBIND11_EXPORT_EXCEPTION name : public builtin_exception { public: \ using builtin_exception::builtin_exception; \ name() : name("") { } \ void set_error() const override { PyErr_SetString(type, what()); } \ diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 161aed06f..4cf606e8d 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -327,7 +327,7 @@ PYBIND11_NAMESPACE_END(detail) /// thrown to propagate python-side errors back through C++ which can either be caught manually or /// else falls back to the function dispatcher (which then raises the captured error back to /// python). -class PYBIND11_EXPORT error_already_set : public std::runtime_error { +class PYBIND11_EXPORT_EXCEPTION error_already_set : public std::runtime_error { public: /// Constructs a new exception from the current Python error indicator, if any. The current /// Python error indicator will be cleared. diff --git a/pybind11/setup_helpers.py b/pybind11/setup_helpers.py index 2b27f1f5a..0888ab487 100644 --- a/pybind11/setup_helpers.py +++ b/pybind11/setup_helpers.py @@ -59,8 +59,7 @@ except ImportError: import distutils.errors import distutils.ccompiler - -WIN = sys.platform.startswith("win32") and sysconfig.get_platform() != "mingw" +WIN = sys.platform.startswith("win32") and "mingw" not in sysconfig.get_platform() PY2 = sys.version_info[0] < 3 MACOS = sys.platform.startswith("darwin") STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}" diff --git a/tests/test_exceptions.h b/tests/test_exceptions.h index 5d02d1b35..9d428312e 100644 --- a/tests/test_exceptions.h +++ b/tests/test_exceptions.h @@ -4,7 +4,7 @@ // shared exceptions for cross_module_tests -class PYBIND11_EXPORT shared_exception : public pybind11::builtin_exception { +class PYBIND11_EXPORT_EXCEPTION shared_exception : public pybind11::builtin_exception { public: using builtin_exception::builtin_exception; explicit shared_exception() : shared_exception("") {} diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake index 57e42536e..7afb0d0b1 100644 --- a/tools/pybind11Common.cmake +++ b/tools/pybind11Common.cmake @@ -302,13 +302,18 @@ function(_pybind11_return_if_cxx_and_linker_flags_work result cxxflags linkerfla endfunction() function(_pybind11_generate_lto target prefer_thin_lto) + if(MINGW) + message(STATUS "${target} disabled (problems with undefined symbols for MinGW for now)") + return() + endif() + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set(cxx_append "") set(linker_append "") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT APPLE) # Clang Gold plugin does not support -Os; append -O3 to MinSizeRel builds to override it set(linker_append ";$<$:-O3>") - elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND NOT MINGW) set(cxx_append ";-fno-fat-lto-objects") endif()