Skip to content

Commit 9006afb

Browse files
committed
fix: add comprehensive workaround for conda libc++ on macOS
The conda-provided libc++ on macOS has compatibility issues with ptrdiff_t and other standard library types due to _LIBCPP_USING_IF_EXISTS failing to resolve types from the global namespace. Changes: - Include stddef.h (C header) before C++ headers to ensure types are defined - Add _LIBCPP_DISABLE_AVAILABILITY flag on macOS to disable availability checks that can conflict with conda environments This resolves the 'reference to unresolved using declaration' error for ptrdiff_t in char_traits.h when building with conda on macOS. References: - conda/conda#11196 - llvm/llvm-project#54233
1 parent 643a30f commit 9006afb

336 files changed

Lines changed: 89576 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

local_install/include/pybind11/attr.h

Lines changed: 690 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
pybind11/buffer_info.h: Python buffer object interface
3+
4+
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5+
6+
All rights reserved. Use of this source code is governed by a
7+
BSD-style license that can be found in the LICENSE file.
8+
*/
9+
10+
#pragma once
11+
12+
#include "detail/common.h"
13+
14+
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
15+
16+
PYBIND11_NAMESPACE_BEGIN(detail)
17+
18+
// Default, C-style strides
19+
inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
20+
auto ndim = shape.size();
21+
std::vector<ssize_t> strides(ndim, itemsize);
22+
if (ndim > 0) {
23+
for (size_t i = ndim - 1; i > 0; --i) {
24+
strides[i - 1] = strides[i] * shape[i];
25+
}
26+
}
27+
return strides;
28+
}
29+
30+
// F-style strides; default when constructing an array_t with `ExtraFlags & f_style`
31+
inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
32+
auto ndim = shape.size();
33+
std::vector<ssize_t> strides(ndim, itemsize);
34+
for (size_t i = 1; i < ndim; ++i) {
35+
strides[i] = strides[i - 1] * shape[i - 1];
36+
}
37+
return strides;
38+
}
39+
40+
template <typename T, typename SFINAE = void>
41+
struct compare_buffer_info;
42+
43+
PYBIND11_NAMESPACE_END(detail)
44+
45+
/// Information record describing a Python buffer object
46+
struct buffer_info {
47+
void *ptr = nullptr; // Pointer to the underlying storage
48+
ssize_t itemsize = 0; // Size of individual items in bytes
49+
ssize_t size = 0; // Total number of entries
50+
std::string format; // For homogeneous buffers, this should be set to
51+
// format_descriptor<T>::format()
52+
ssize_t ndim = 0; // Number of dimensions
53+
std::vector<ssize_t> shape; // Shape of the tensor (1 entry per dimension)
54+
std::vector<ssize_t> strides; // Number of bytes between adjacent entries
55+
// (for each per dimension)
56+
bool readonly = false; // flag to indicate if the underlying storage may be written to
57+
58+
buffer_info() = default;
59+
60+
buffer_info(void *ptr,
61+
ssize_t itemsize,
62+
const std::string &format,
63+
ssize_t ndim,
64+
detail::any_container<ssize_t> shape_in,
65+
detail::any_container<ssize_t> strides_in,
66+
bool readonly = false)
67+
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
68+
shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
69+
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) {
70+
pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
71+
}
72+
for (size_t i = 0; i < (size_t) ndim; ++i) {
73+
size *= shape[i];
74+
}
75+
}
76+
77+
template <typename T>
78+
buffer_info(T *ptr,
79+
detail::any_container<ssize_t> shape_in,
80+
detail::any_container<ssize_t> strides_in,
81+
bool readonly = false)
82+
: buffer_info(private_ctr_tag(),
83+
ptr,
84+
sizeof(T),
85+
format_descriptor<T>::format(),
86+
static_cast<ssize_t>(shape_in->size()),
87+
std::move(shape_in),
88+
std::move(strides_in),
89+
readonly) {}
90+
91+
buffer_info(void *ptr,
92+
ssize_t itemsize,
93+
const std::string &format,
94+
ssize_t size,
95+
bool readonly = false)
96+
: buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) {}
97+
98+
template <typename T>
99+
buffer_info(T *ptr, ssize_t size, bool readonly = false)
100+
: buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) {}
101+
102+
template <typename T>
103+
buffer_info(const T *ptr, ssize_t size, bool readonly = true)
104+
: buffer_info(
105+
const_cast<T *>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) {}
106+
107+
explicit buffer_info(Py_buffer *view, bool ownview = true)
108+
: buffer_info(
109+
view->buf,
110+
view->itemsize,
111+
view->format,
112+
view->ndim,
113+
{view->shape, view->shape + view->ndim},
114+
/* Though buffer::request() requests PyBUF_STRIDES, ctypes objects
115+
* ignore this flag and return a view with NULL strides.
116+
* When strides are NULL, build them manually. */
117+
view->strides
118+
? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
119+
: detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
120+
(view->readonly != 0)) {
121+
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
122+
this->m_view = view;
123+
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
124+
this->ownview = ownview;
125+
}
126+
127+
buffer_info(const buffer_info &) = delete;
128+
buffer_info &operator=(const buffer_info &) = delete;
129+
130+
buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); }
131+
132+
buffer_info &operator=(buffer_info &&rhs) noexcept {
133+
ptr = rhs.ptr;
134+
itemsize = rhs.itemsize;
135+
size = rhs.size;
136+
format = std::move(rhs.format);
137+
ndim = rhs.ndim;
138+
shape = std::move(rhs.shape);
139+
strides = std::move(rhs.strides);
140+
std::swap(m_view, rhs.m_view);
141+
std::swap(ownview, rhs.ownview);
142+
readonly = rhs.readonly;
143+
return *this;
144+
}
145+
146+
~buffer_info() {
147+
if (m_view && ownview) {
148+
PyBuffer_Release(m_view);
149+
delete m_view;
150+
}
151+
}
152+
153+
Py_buffer *view() const { return m_view; }
154+
Py_buffer *&view() { return m_view; }
155+
156+
/* True if the buffer item type is equivalent to `T`. */
157+
// To define "equivalent" by example:
158+
// `buffer_info::item_type_is_equivalent_to<int>(b)` and
159+
// `buffer_info::item_type_is_equivalent_to<long>(b)` may both be true
160+
// on some platforms, but `int` and `unsigned` will never be equivalent.
161+
// For the ground truth, please inspect `detail::compare_buffer_info<>`.
162+
template <typename T>
163+
bool item_type_is_equivalent_to() const {
164+
return detail::compare_buffer_info<T>::compare(*this);
165+
}
166+
167+
private:
168+
struct private_ctr_tag {};
169+
170+
buffer_info(private_ctr_tag,
171+
void *ptr,
172+
ssize_t itemsize,
173+
const std::string &format,
174+
ssize_t ndim,
175+
detail::any_container<ssize_t> &&shape_in,
176+
detail::any_container<ssize_t> &&strides_in,
177+
bool readonly)
178+
: buffer_info(
179+
ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) {}
180+
181+
Py_buffer *m_view = nullptr;
182+
bool ownview = false;
183+
};
184+
185+
PYBIND11_NAMESPACE_BEGIN(detail)
186+
187+
template <typename T, typename SFINAE>
188+
struct compare_buffer_info {
189+
static bool compare(const buffer_info &b) {
190+
// NOLINTNEXTLINE(bugprone-sizeof-expression) Needed for `PyObject *`
191+
return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T);
192+
}
193+
};
194+
195+
template <typename T>
196+
struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
197+
static bool compare(const buffer_info &b) {
198+
return (size_t) b.itemsize == sizeof(T)
199+
&& (b.format == format_descriptor<T>::value
200+
|| ((sizeof(T) == sizeof(long))
201+
&& b.format == (std::is_unsigned<T>::value ? "L" : "l"))
202+
|| ((sizeof(T) == sizeof(size_t))
203+
&& b.format == (std::is_unsigned<T>::value ? "N" : "n")));
204+
}
205+
};
206+
207+
PYBIND11_NAMESPACE_END(detail)
208+
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

0 commit comments

Comments
 (0)