From 5e2a46e56245dd12f53206686a2a8019ce290382 Mon Sep 17 00:00:00 2001 From: Matt Wozniski Date: Sat, 11 Jul 2026 18:54:59 -0400 Subject: [PATCH 1/2] Sync build configuration with Memray - Start setting `CMAKE_CXX_VISIBILITY_PRESET` to `hidden` to avoid unintentionally exposing symbols from our extension module that could potentially conflict with other modules. - Ensure that directories searched for shared libraries are added to the RPATH with `CMAKE_INSTALL_RPATH_USE_LINK_PATH`. - Ensure that the Python version we find includes a configuration for building extension modules that against the stable ABI. - Build with -Wall to enable extra warnings. - Pass `-D_FILE_OFFSET_BITS=64` to opt into 64-bit file IO APIs even on 32-bit platforms. This currently doesn't have any effect, since we only build for 64-bit platforms, but it would be needed if we ever added i686 support, and matching Memray will make maintenance cheaper. - Enable extra debugging in the C++ STL for debug builds. - Build with link time optimizations enabled for CMake release mode builds. - Optimize for debugging in CMake debug builds. - Require `scikit-build-core` 0.9 or newer. - Enable extra logging during builds. - Avoid stripping debug info from the built extension module. - Automatically build in debug mode rather than release mode when passing the `-e` / `--editable` flag to `pip install`. Signed-off-by: Matt Wozniski --- CMakeLists.txt | 17 ++++++++++++++++- pyproject.toml | 12 ++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43c3cf6a..5f78c089 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,24 @@ project(pystack LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # Find Python -find_package(Python 3.9 COMPONENTS Interpreter Development.Module REQUIRED) +find_package(Python COMPONENTS Interpreter Development.Module Development.SABIModule REQUIRED) + +# Set compiler flags +add_compile_options(-Wall) +add_compile_definitions(_FILE_OFFSET_BITS=64) + +add_compile_definitions( + "$<$:_GLIBCXX_DEBUG>" + "$<$:_LIBCPP_DEBUG>" +) + +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -flto") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og") # Find nanobind execute_process( diff --git a/pyproject.toml b/pyproject.toml index f320c983..57941b75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,11 @@ Homepage = "https://github.com/bloomberg/pystack" pystack = "pystack.__main__:main" [tool.scikit-build] +minimum-version = "0.9" +cmake.verbose = true +cmake.build-type = "RelWithDebInfo" +logging.level = "INFO" +install.strip = false wheel.packages = ["src/pystack"] wheel.install-dir = "pystack" wheel.exclude = ["pystack/_pystack/**"] @@ -75,8 +80,11 @@ sdist.exclude = [ "uv.lock", ] -[tool.scikit-build.cmake.define] -CMAKE_BUILD_TYPE = "Release" +[[tool.scikit-build.overrides]] +if.state = "editable" +build-dir = "build" +editable.verbose = false +cmake.build-type = "Debug" [tool.ruff] line-length = 95 From 7f155010115140d78c058c0933d317f2dfb14c25 Mon Sep 17 00:00:00 2001 From: Matt Wozniski Date: Sun, 12 Jul 2026 14:38:56 -0400 Subject: [PATCH 2/2] Remove an unused function This function is exposed by our extension module, but never used by any of our Python modules. Signed-off-by: Matt Wozniski --- src/pystack/_pystack.pyi | 1 - src/pystack/_pystack/bindings.cpp | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/src/pystack/_pystack.pyi b/src/pystack/_pystack.pyi index fe3a956f..64545320 100644 --- a/src/pystack/_pystack.pyi +++ b/src/pystack/_pystack.pyi @@ -82,7 +82,6 @@ def get_process_threads_for_core( method: StackMethod = StackMethod.AUTO, ) -> List[PyThread]: ... def get_bss_info(binary: Union[str, pathlib.Path]) -> Optional[Dict[str, Any]]: ... -def copy_memory_from_address(pid: int, address: int, size: int) -> bytes: ... def _check_interpreter_shutdown(manager: ProcessManager) -> None: ... def is_eval_frame(symbol: str, python_version: Tuple[int, int]) -> bool: ... def _normalize_threads_for_testing( diff --git a/src/pystack/_pystack/bindings.cpp b/src/pystack/_pystack/bindings.cpp index 1d16d08d..562e38ae 100644 --- a/src/pystack/_pystack/bindings.cpp +++ b/src/pystack/_pystack/bindings.cpp @@ -363,18 +363,6 @@ class ProcessManagerWrapper std::shared_ptr d_manager; }; -nb::bytes -copy_memory_from_address(pid_t pid, uintptr_t address, size_t size) -{ - auto manager = std::make_shared(pid); - PyObject* py_bytes = PyBytes_FromStringAndSize(nullptr, static_cast(size)); - if (!py_bytes) { - throw nb::python_error(); - } - manager->copyMemoryFromProcess(address, size, PyBytes_AS_STRING(py_bytes)); - return nb::steal(py_bytes); -} - nb::object get_bss_info(const std::filesystem::path& binary) { @@ -972,13 +960,6 @@ NB_MODULE(_pystack, m) nb::rv_policy::reference) .def("__exit__", [](ProcessManagerWrapper& self, nb::args) { self.reset(); }); - m.def("copy_memory_from_address", - ©_memory_from_address, - "pid"_a, - "address"_a, - "size"_a, - "Copy memory from a remote process"); - m.def("get_bss_info", &get_bss_info, "binary"_a, "Get BSS section information from an ELF binary"); // Note: We use nb::arg().none() to allow None to be passed explicitly