Skip to content

fix: expose required symbol using clang #5700

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ jobs:
- name: Interface test
run: cmake --build . --target test_cmake_build

- name: Visibility test
run: cmake --build . --target test_cross_module_rtti


manylinux:
name: Manylinux on 🐍 3.13t • GIL
Expand Down Expand Up @@ -328,6 +331,9 @@ jobs:
- name: C++ tests
run: cmake --build --preset default --target cpptest

- name: Visibility test
run: cmake --build --preset default --target test_cross_module_rtti

- name: Run Valgrind on Python tests
if: matrix.valgrind
run: cmake --build --preset default --target memcheck
Expand Down Expand Up @@ -386,6 +392,8 @@ jobs:
- name: Interface test
run: cmake --build build --target test_cmake_build

- name: Visibility test
run: cmake --build build --target test_cross_module_rtti

# Testing NVCC; forces sources to behave like .cu files
cuda:
Expand Down Expand Up @@ -505,6 +513,8 @@ jobs:
- name: Interface test
run: cmake --build build --target test_cmake_build

- name: Visibility test
run: cmake --build build --target test_cross_module_rtti

# Testing on GCC using the GCC docker images (only recent images supported)
gcc:
Expand Down Expand Up @@ -556,6 +566,9 @@ jobs:
- name: Interface test
run: cmake --build build --target test_cmake_build

- name: Visibility test
run: cmake --build build --target test_cross_module_rtti

- name: Configure - Exercise cmake -DPYBIND11_TEST_OVERRIDE
if: matrix.gcc == '12'
shell: bash
Expand Down Expand Up @@ -638,6 +651,11 @@ jobs:
set +e; source /opt/intel/oneapi/setvars.sh; set -e
cmake --build build-11 --target test_cmake_build
- name: Visibility test
run: |
set +e; source /opt/intel/oneapi/setvars.sh; set -e
cmake --build build-11 --target test_cross_module_rtti
- name: Configure C++17
run: |
set +e; source /opt/intel/oneapi/setvars.sh; set -e
Expand Down Expand Up @@ -670,6 +688,10 @@ jobs:
set +e; source /opt/intel/oneapi/setvars.sh; set -e
cmake --build build-17 --target test_cmake_build
- name: Visibility test
run: |
set +e; source /opt/intel/oneapi/setvars.sh; set -e
cmake --build build-17 --target test_cross_module_rtti
# Testing on CentOS (manylinux uses a centos base).
centos:
Expand Down Expand Up @@ -732,6 +754,9 @@ jobs:
- name: Interface test
run: cmake --build build --target test_cmake_build

- name: Visibility test
run: cmake --build build --target test_cross_module_rtti


# This tests an "install" with the CMake tools
install-classic:
Expand Down Expand Up @@ -967,6 +992,9 @@ jobs:
- name: Interface test C++20
run: cmake --build build --target test_cmake_build

- name: Visibility test
run: cmake --build build --target test_cross_module_rtti

- name: Configure C++20 - Exercise cmake -DPYBIND11_TEST_OVERRIDE
run: >
cmake -S . -B build_partial
Expand Down Expand Up @@ -1040,6 +1068,9 @@ jobs:
- name: Interface test C++11
run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build --target test_cmake_build

- name: Visibility test
run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build --target test_cross_module_rtti

- name: Clean directory
run: git clean -fdx

Expand All @@ -1061,6 +1092,9 @@ jobs:
- name: Interface test C++14
run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build2 --target test_cmake_build

- name: Visibility test
run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build2 --target test_cross_module_rtti

- name: Clean directory
run: git clean -fdx

Expand All @@ -1082,6 +1116,9 @@ jobs:
- name: Interface test C++17
run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build3 --target test_cmake_build

- name: Visibility test
run: PYTHONHOME=/${{matrix.sys}} PYTHONPATH=/${{matrix.sys}} cmake --build build3 --target test_cross_module_rtti

windows_clang:
if: github.event.pull_request.draft == false

Expand Down Expand Up @@ -1149,6 +1186,9 @@ jobs:
- name: Interface test
run: cmake --build . --target test_cmake_build -j 2

- name: Visibility test
run: cmake --build . --target test_cross_module_rtti -j 2

- name: Clean directory
run: git clean -fdx

Expand Down Expand Up @@ -1216,6 +1256,9 @@ jobs:
- name: Interface test
run: cmake --build . --target test_cmake_build -j 2

- name: Visibility test
run: cmake --build . --target test_cross_module_rtti -j 2

- name: CMake Configure - Exercise cmake -DPYBIND11_TEST_OVERRIDE
run: >
cmake -S . -B build_partial
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/reusable-standard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ jobs:
- name: Interface test
run: cmake --build build --target test_cmake_build

- name: Visibility test
run: cmake --build build --target test_cross_module_rtti

- name: Setuptools helpers test
run: |
uv pip install --python=python --system setuptools
Expand Down
4 changes: 2 additions & 2 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
"name": "tests",
"displayName": "Tests (for workflow)",
"configurePreset": "default",
"targets": ["pytest", "cpptest", "test_cmake_build"]
"targets": ["pytest", "cpptest", "test_cmake_build", "test_cross_module_rtti"]
},
{
"name": "testsvenv",
"displayName": "Tests Venv (for workflow)",
"configurePreset": "venv",
"targets": ["pytest", "cpptest", "test_cmake_build"]
"targets": ["pytest", "cpptest", "test_cmake_build", "test_cross_module_rtti"]
}
],
"workflowPresets": [
Expand Down
15 changes: 14 additions & 1 deletion include/pybind11/detail/struct_smart_holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ High-level aspects:
#include <typeinfo>
#include <utility>

// IMPORTANT: This code block must stay BELOW the #include <stdexcept> above.
// This is only required on some builds with libc++ (one of three implementations
// in
// https://github.com/llvm/llvm-project/blob/a9b64bb3180dab6d28bf800a641f9a9ad54d2c0c/libcxx/include/typeinfo#L271-L276
// require it)
#if !defined(PYBIND11_EXPORT_GUARDED_DELETE)
# if defined(_LIBCPP_VERSION) && !defined(WIN32) && !defined(_WIN32)
# define PYBIND11_EXPORT_GUARDED_DELETE __attribute__((visibility("default")))
# else
# define PYBIND11_EXPORT_GUARDED_DELETE
# endif
#endif

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(memory)

Expand All @@ -78,7 +91,7 @@ static constexpr bool type_has_shared_from_this(const void *) {
return false;
}

struct guarded_delete {
struct PYBIND11_EXPORT_GUARDED_DELETE guarded_delete {
std::weak_ptr<void> released_ptr; // Trick to keep the smart_holder memory footprint small.
std::function<void(void *)> del_fun; // Rare case.
void (*del_ptr)(void *); // Common case.
Expand Down
3 changes: 3 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -649,4 +649,7 @@ if(NOT PYBIND11_CUDA_TESTS)

# Test CMake build using functions and targets from subdirectory or installed location
add_subdirectory(test_cmake_build)

# Test visibility of common symbols across shared libraries
add_subdirectory(test_cross_module_rtti)
endif()
68 changes: 68 additions & 0 deletions tests/test_cross_module_rtti/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
possibly_uninitialized(PYTHON_MODULE_EXTENSION Python_INTERPRETER_ID)

set(CMAKE_CXX_VISIBILITY_PRESET hidden)

if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy"
OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
OR "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy")
message(STATUS "Skipping visibility test on PyPy or GraalPy")
add_custom_target(test_cross_module_rtti
)# Dummy target on PyPy or GraalPy. Embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return()
endif()

if(TARGET Python::Module AND NOT TARGET Python::Python)
message(STATUS "Skipping visibility test since no embed libs found")
add_custom_target(test_cross_module_rtti) # Dummy target since embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return()
endif()

find_package(Catch 2.13.10)

if(CATCH_FOUND)
message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}")
else()
message(STATUS "Catch not detected. Interpreter tests will be skipped. Install Catch headers"
" manually or use `cmake -DDOWNLOAD_CATCH=ON` to fetch them automatically.")
return()
endif()

include(GenerateExportHeader)

add_library(test_cross_module_rtti_lib SHARED lib.h lib.cpp)
add_library(test_cross_module_rtti_lib::test_cross_module_rtti_lib ALIAS
test_cross_module_rtti_lib)
target_include_directories(test_cross_module_rtti_lib PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(test_cross_module_rtti_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_features(test_cross_module_rtti_lib PUBLIC cxx_std_11)

generate_export_header(test_cross_module_rtti_lib)

pybind11_add_module(test_cross_module_rtti_bindings SHARED bindings.cpp)
target_link_libraries(test_cross_module_rtti_bindings
PUBLIC test_cross_module_rtti_lib::test_cross_module_rtti_lib)

add_executable(test_cross_module_rtti_main catch.cpp test_cross_module_rtti.cpp)
target_link_libraries(
test_cross_module_rtti_main PUBLIC test_cross_module_rtti_lib::test_cross_module_rtti_lib
pybind11::embed Catch2::Catch2)

# Ensure that we have built the python bindings since we load them in main
add_dependencies(test_cross_module_rtti_main test_cross_module_rtti_bindings)

pybind11_enable_warnings(test_cross_module_rtti_main)
pybind11_enable_warnings(test_cross_module_rtti_bindings)
pybind11_enable_warnings(test_cross_module_rtti_lib)

add_custom_target(
test_cross_module_rtti
COMMAND "$<TARGET_FILE:test_cross_module_rtti_main>"
DEPENDS test_cross_module_rtti_main
WORKING_DIRECTORY "$<TARGET_FILE_DIR:test_cross_module_rtti_main>")

set_target_properties(test_cross_module_rtti_bindings PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}")

add_dependencies(check test_cross_module_rtti)
20 changes: 20 additions & 0 deletions tests/test_cross_module_rtti/bindings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <pybind11/pybind11.h>

#include <lib.h>

class BaseTrampoline : public lib::Base, public pybind11::trampoline_self_life_support {
public:
using lib::Base::Base;
int get() const override { PYBIND11_OVERLOAD(int, lib::Base, get); }
};

PYBIND11_MODULE(test_cross_module_rtti_bindings, m) {
pybind11::classh<lib::Base, BaseTrampoline>(m, "Base")
.def(pybind11::init<int, int>())
.def_readwrite("a", &lib::Base::a)
.def_readwrite("b", &lib::Base::b);

m.def("get_foo", [](int a, int b) -> std::shared_ptr<lib::Base> {
return std::make_shared<lib::Foo>(a, b);
});
}
22 changes: 22 additions & 0 deletions tests/test_cross_module_rtti/catch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// The Catch implementation is compiled here. This is a standalone
// translation unit to avoid recompiling it for every test change.

#include <pybind11/embed.h>

// Silence MSVC C++17 deprecation warning from Catch regarding std::uncaught_exceptions (up to
// catch 2.0.1; this should be fixed in the next catch release after 2.0.1).
PYBIND11_WARNING_DISABLE_MSVC(4996)

// Catch uses _ internally, which breaks gettext style defines
#ifdef _
# undef _
#endif

#define CATCH_CONFIG_RUNNER
#include <catch.hpp>

int main(int argc, char *argv[]) {
pybind11::scoped_interpreter guard{};
auto result = Catch::Session().run(argc, argv);
return result < 0xff ? result : 0xff;
}
13 changes: 13 additions & 0 deletions tests/test_cross_module_rtti/lib.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <lib.h>

namespace lib {

Base::Base(int a, int b) : a(a), b(b) {}

int Base::get() const { return a + b; }

Foo::Foo(int a, int b) : Base{a, b} {}

int Foo::get() const { return 2 * a + b; }

} // namespace lib
30 changes: 30 additions & 0 deletions tests/test_cross_module_rtti/lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <memory>
#include <test_cross_module_rtti_lib_export.h>

#if defined(_MSC_VER)
__pragma(warning(disable : 4251))
#endif

namespace lib {

class TEST_CROSS_MODULE_RTTI_LIB_EXPORT Base : public std::enable_shared_from_this<Base> {
public:
Base(int a, int b);
virtual ~Base() = default;

virtual int get() const;

int a;
int b;
};

class TEST_CROSS_MODULE_RTTI_LIB_EXPORT Foo : public Base {
public:
Foo(int a, int b);

int get() const override;
};

} // namespace lib
Loading
Loading