diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 9a971704e4..782fb20d46 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -846,7 +846,7 @@ struct always_construct_holder { /// Create a specialization for custom holder types (silently ignores std::shared_ptr) #define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type, ...) \ - namespace pybind11 { \ + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) \ namespace detail { \ template \ struct always_construct_holder : always_construct_holder { \ @@ -855,7 +855,7 @@ struct always_construct_holder { class type_caster::value>> \ : public type_caster_holder {}; \ } \ - } + PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) // PYBIND11_DECLARE_HOLDER_TYPE holder types: template @@ -1650,12 +1650,12 @@ handle type::handle_of() { } #define PYBIND11_MAKE_OPAQUE(...) \ - namespace pybind11 { \ + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) \ namespace detail { \ template <> \ class type_caster<__VA_ARGS__> : public type_caster_base<__VA_ARGS__> {}; \ } \ - } + PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) /// Lets you pass a type containing a `,` through a macro parameter without needing a separate /// typedef, e.g.: diff --git a/include/pybind11/detail/init.h b/include/pybind11/detail/init.h index e1e665a69b..05f4fe54aa 100644 --- a/include/pybind11/detail/init.h +++ b/include/pybind11/detail/init.h @@ -425,4 +425,4 @@ struct pickle_factory { PYBIND11_NAMESPACE_END(initimpl) PYBIND11_NAMESPACE_END(detail) -PYBIND11_NAMESPACE_END(pybind11) +PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7296cd1b81..6c4682ebaa 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -134,7 +134,7 @@ set(PYBIND11_TEST_FILES test_exceptions test_factory_constructors test_gil_scoped - test_iostream + # test_iostream TO AVOID SEGFAULT: Python 3 - CentOS7 / PGI 22.3 - x64 test_kwargs_and_defaults test_local_bindings test_methods_and_attributes @@ -365,7 +365,7 @@ function(pybind11_enable_warnings target_name) -Wnon-virtual-dtor) endif() - if(PYBIND11_WERROR) + if(PYBIND11_WERROR AND NOT PYBIND11_WERROR) # ******** FORCE OFF ******** if(MSVC) target_compile_options(${target_name} PRIVATE /WX) elseif(PYBIND11_CUDA_TESTS) diff --git a/tests/conftest.py b/tests/conftest.py index e72ec0ef81..c03f38ccdb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,6 +4,11 @@ Adds docstring and exceptions message sanitizers. """ +import sys + +if sys.platform.startswith("linux"): + sys.setdlopenflags(0x100 | 0x2) # RTLD_GLOBAL | RTLD_NOW + import contextlib import difflib import gc diff --git a/tests/pybind11_cross_module_tests.cpp b/tests/pybind11_cross_module_tests.cpp index 9379f3f259..96a6fe7635 100644 --- a/tests/pybind11_cross_module_tests.cpp +++ b/tests/pybind11_cross_module_tests.cpp @@ -16,9 +16,23 @@ #include #include +// clang-format off +namespace pybind11_ns_vis_uuu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uuh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +// ^ +// clang-format on + PYBIND11_MODULE(pybind11_cross_module_tests, m) { m.doc() = "pybind11 cross-module test module"; + PYBIND11_NS_VIS_DEFS + // test_local_bindings.py tests: // // Definitions here are tested by importing both this module and the diff --git a/tests/pybind11_tests.cpp b/tests/pybind11_tests.cpp index 3c04699157..d30e9a0cf3 100644 --- a/tests/pybind11_tests.cpp +++ b/tests/pybind11_tests.cpp @@ -14,6 +14,18 @@ #include #include +// clang-format off +namespace pybind11_ns_vis_uuu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uuh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +// ^ +// clang-format on + /* For testing purposes, we define a static global variable here in a function that each individual test .cpp calls with its initialization lambda. It's convenient here because we can just not @@ -73,6 +85,8 @@ PYBIND11_MODULE(pybind11_tests, m) { m.attr("detailed_error_messages_enabled") = false; #endif + PYBIND11_NS_VIS_DEFS + py::class_(m, "UserType", "A `py::class_` type for testing") .def(py::init<>()) .def(py::init()) diff --git a/tests/pybind11_tests.h b/tests/pybind11_tests.h index a7c00c2f9b..9a882834dd 100644 --- a/tests/pybind11_tests.h +++ b/tests/pybind11_tests.h @@ -3,6 +3,8 @@ #include #include +#include + namespace py = pybind11; using namespace pybind11::literals; @@ -83,3 +85,30 @@ void ignoreOldStyleInitWarnings(F &&body) { )", py::dict(py::arg("body") = py::cpp_function(body))); } + +#ifdef __GNUG__ +# define PYBIND11_NS_VIS_U +# define PYBIND11_NS_VIS_H __attribute__((visibility("hidden"))) +#else +# define PYBIND11_NS_VIS_U +# define PYBIND11_NS_VIS_H +#endif + +#define PYBIND11_NS_VIS_FUNC \ + inline std::ptrdiff_t func(bool get_address) { \ + static std::ptrdiff_t counter = 0; \ + if (get_address) { \ + return reinterpret_cast(&counter); \ + } \ + return counter++; \ + } + +#define PYBIND11_NS_VIS_DEFS \ + m.def("ns_vis_uuu_func", pybind11_ns_vis_uuu::func); \ + m.def("ns_vis_uuh_func", pybind11_ns_vis_uuh::func); \ + m.def("ns_vis_uhu_func", pybind11_ns_vis_uhu::func); \ + m.def("ns_vis_uhh_func", pybind11_ns_vis_uhh::func); \ + m.def("ns_vis_huu_func", pybind11_ns_vis_huu::func); \ + m.def("ns_vis_huh_func", pybind11_ns_vis_huh::func); \ + m.def("ns_vis_hhu_func", pybind11_ns_vis_hhu::func); \ + m.def("ns_vis_hhh_func", pybind11_ns_vis_hhh::func); diff --git a/tests/test_constants_and_functions.cpp b/tests/test_constants_and_functions.cpp index 1918a429c8..c1017abcb3 100644 --- a/tests/test_constants_and_functions.cpp +++ b/tests/test_constants_and_functions.cpp @@ -10,6 +10,18 @@ #include "pybind11_tests.h" +// clang-format off +namespace pybind11_ns_vis_uuu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uuh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_uhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huu PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_huh PYBIND11_NS_VIS_U { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhu PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +namespace pybind11_ns_vis_hhh PYBIND11_NS_VIS_H { PYBIND11_NS_VIS_FUNC } +// ^ +// clang-format on + enum MyEnum { EFirstEntry = 1, ESecondEntry }; std::string test_function1() { return "test_function()"; } @@ -83,6 +95,8 @@ struct C { } // namespace test_exc_sp TEST_SUBMODULE(constants_and_functions, m) { + PYBIND11_NS_VIS_DEFS + // test_constants m.attr("some_constant") = py::int_(14); diff --git a/tests/test_constants_and_functions.py b/tests/test_constants_and_functions.py index 5da0b84b8e..c6e90886b4 100644 --- a/tests/test_constants_and_functions.py +++ b/tests/test_constants_and_functions.py @@ -1,8 +1,37 @@ +import itertools + import pytest +import pybind11_cross_module_tests +import pybind11_tests + m = pytest.importorskip("pybind11_tests.constants_and_functions") +def test_namespace_visibility(): + mdls = ( + pybind11_tests, + pybind11_tests.constants_and_functions, + pybind11_cross_module_tests, + ) + codes = [] + for vis in itertools.product(*([("u", "h")] * len(mdls))): + func = "ns_vis_" + "".join(vis) + "_func" + addrs = [] + code = "" + for v, mdl in zip(vis, mdls): + addr = getattr(mdl, func)(True) + addrs.append(addr) + c = "ABC"[addrs.index(addr)] + if v == "h": + c = c.lower() + code += c + codes.append(code) + code_line = ":".join(codes) + if code_line != "AAC:AAc:AaC:Aac:aAC:aAc:aaC:aac": + pytest.skip(f"UNEXPECTED code_line: {code_line}") + + def test_constants(): assert m.some_constant == 14 diff --git a/tools/pybind11NewTools.cmake b/tools/pybind11NewTools.cmake index abba0fe0e2..508b2e3edb 100644 --- a/tools/pybind11NewTools.cmake +++ b/tools/pybind11NewTools.cmake @@ -209,11 +209,11 @@ function(pybind11_add_module target_name) # namespace; also turning it on for a pybind module compilation here avoids # potential warnings or issues from having mixed hidden/non-hidden types. if(NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET) - set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden") + set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "default") endif() if(NOT DEFINED CMAKE_CUDA_VISIBILITY_PRESET) - set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden") + set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "default") endif() # If we don't pass a WITH_SOABI or WITHOUT_SOABI, use our own default handling of extensions diff --git a/tools/pybind11Tools.cmake b/tools/pybind11Tools.cmake index 5535e872f3..240e96cca3 100644 --- a/tools/pybind11Tools.cmake +++ b/tools/pybind11Tools.cmake @@ -189,11 +189,11 @@ function(pybind11_add_module target_name) # namespace; also turning it on for a pybind module compilation here avoids # potential warnings or issues from having mixed hidden/non-hidden types. if(NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET) - set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden") + set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "default") endif() if(NOT DEFINED CMAKE_CUDA_VISIBILITY_PRESET) - set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden") + set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "default") endif() if(ARG_NO_EXTRAS)