Skip to content

Commit f966b6a

Browse files
fdr400Fedor Osetrov
andauthored
feat boost.stacktrace: C++20 modules support (#230)
- Introduce `boost.stacktrace_dump` module for safe_dump interface - Introduce `boost.stacktrace_<backend>` module for each unwind/collect implementation method - Introduce `boost.stacktrace` module exposing best available backend implementation Also many tests was added for checking all available backend build and also header only library version Moreover, there are some checks for `Boost::stacktrace_<backend>` and `Boost::stacktrace_from_exception` compatibility --------- Co-authored-by: Fedor Osetrov <fdr400@Fedors-MacBook-Pro.local>
1 parent 8dd3018 commit f966b6a

45 files changed

Lines changed: 709 additions & 84 deletions

Some content is hidden

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

.github/workflows/ci.yml

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,21 @@ jobs:
2727
- toolset: gcc-9
2828
cxxstd: "03,11,14,17,2a"
2929
os: ubuntu-22.04
30-
install: g++-9
30+
install: [g++-9]
3131
- toolset: clang-15
3232
cxxstd: "03,11,14,17,2a"
3333
os: ubuntu-22.04
34+
- toolset: clang-19
35+
compiler: clang++-19
36+
cxxstd: "20"
37+
os: ubuntu-24.04
38+
install: &cxx19
39+
- clang-19
40+
- llvm-19
41+
- libclang-rt-19-dev
42+
- libc++-19-dev
43+
- libc++abi-19-dev
44+
- clang-tools-19
3445
# TODO: fix and uncomment
3546
#- toolset: clang
3647
# cxxstd: "03,11,14,17,2a"
@@ -45,7 +56,7 @@ jobs:
4556

4657
- name: Install packages
4758
if: matrix.install
48-
run: sudo apt install ${{matrix.install}}
59+
run: sudo apt install -y ${{join(matrix.install, ' ')}}
4960

5061
- name: Setup Boost
5162
run: |
@@ -71,6 +82,35 @@ jobs:
7182
./bootstrap.sh
7283
./b2 -d0 headers
7384
./b2 -j4 variant=debug tools/inspect
85+
86+
- name: Build libbacktrace
87+
if: ${{matrix.toolset == 'clang-19'}}
88+
run: |
89+
# libc++ do not have bundled libbacktrace implementation
90+
git clone --depth=1 https://github.com/ianlancetaylor/libbacktrace.git
91+
cd libbacktrace
92+
CC=clang-19 OBJCOPY=/usr/bin/llvm-objcopy NM=/usr/bin/llvm-nm \
93+
./configure --prefix="$HOME/.local" --with-system-libunwind
94+
make -j"$(nproc)"
95+
make install
96+
97+
- name: Run modules tests without 'import std;'
98+
if: ${{matrix.toolset == 'clang-19'}}
99+
run: |
100+
pwd
101+
cd ../boost-root/libs/$LIBRARY
102+
cmake -S test/cmake_subdir_test \
103+
-B build_module \
104+
-GNinja \
105+
-DBOOST_USE_MODULES=1 \
106+
-DBUILD_TESTING=1 \
107+
-DCMAKE_CXX_STANDARD=20 \
108+
-DCMAKE_CXX_COMPILER=${{matrix.compiler}} \
109+
-DCMAKE_CXX_FLAGS="-stdlib=libc++ -I$HOME/.local/include" \
110+
-DCMAKE_EXE_LINKER_FLAGS="-L$HOME/.local"
111+
cmake --build build_module
112+
ctest --test-dir build_module -VV
113+
rm -rf build_module
74114
75115
- name: Run tests
76116
run: |
@@ -205,11 +245,14 @@ jobs:
205245
206246
- name: Use library with add_subdirectory
207247
run: |
208-
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
209-
mkdir __build__ && cd __build__
210-
cmake -DBUILD_SHARED_LIBS=${{matrix.shared}} ..
211-
cmake --build .
212-
ctest --output-on-failure --no-tests=error
248+
cd ../boost-root/libs/$LIBRARY
249+
cmake -S test/cmake_subdir_test -B __build__ \
250+
-GNinja \
251+
-DBUILD_SHARED_LIBS=${{matrix.shared}}
252+
253+
cmake --build __build__
254+
ctest --test-dir __build__ --output-on-failure --no-tests=error
255+
rm -rf __build__
213256
214257
posix-cmake-install:
215258
strategy:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
build?*
2+
.cache
3+
.vscode

CMakeLists.txt

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,18 @@ cmake_minimum_required(VERSION 3.8...4.20)
77

88
project(boost_stacktrace VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
99

10-
function(stacktrace_add_library suffix opt public_libs libs defs)
10+
function(stacktrace_add_module name)
11+
target_sources(${name}
12+
PUBLIC
13+
FILE_SET CXX_MODULES
14+
BASE_DIRS "${CMAKE_CURRENT_LIST_DIR}/modules"
15+
FILES "${CMAKE_CURRENT_LIST_DIR}/modules/${name}.cppm"
16+
)
17+
target_compile_features(${name} PUBLIC cxx_std_20)
18+
target_compile_definitions(${name} PUBLIC BOOST_USE_MODULES)
19+
endfunction()
20+
21+
function(stacktrace_add_library suffix opt public_libs libs defs add_module)
1122

1223
if(NOT opt)
1324
return()
@@ -38,10 +49,14 @@ function(stacktrace_add_library suffix opt public_libs libs defs)
3849
${defs}
3950
)
4051

41-
target_sources(boost_stacktrace_${suffix}
42-
PRIVATE
43-
${CMAKE_CURRENT_LIST_DIR}/src/${suffix}.cpp
44-
)
52+
if (add_module)
53+
stacktrace_add_module(boost_stacktrace_${suffix})
54+
else()
55+
target_sources(boost_stacktrace_${suffix}
56+
PRIVATE
57+
"${CMAKE_CURRENT_LIST_DIR}/src/${suffix}.cpp"
58+
)
59+
endif()
4560

4661
if(BUILD_SHARED_LIBS)
4762
target_compile_definitions(boost_stacktrace_${suffix} PUBLIC BOOST_STACKTRACE_DYN_LINK)
@@ -110,24 +125,40 @@ if(BOOST_STACKTRACE_ENABLE_BACKTRACE OR
110125
BOOST_STACKTRACE_ENABLE_WINDBG_CACHED
111126
)
112127
set(_enable_non_noop_backend TRUE)
128+
else()
129+
set(_enable_non_noop_backend FALSE)
113130
endif()
114131

115-
if(_enable_non_noop_backend)
116-
stacktrace_add_library(dump ON "" "" "")
132+
if(NOT BOOST_USE_MODULES)
133+
set(BOOST_USE_MODULES OFF)
117134
endif()
118-
stacktrace_add_library(noop ${BOOST_STACKTRACE_ENABLE_NOOP} "" "" "")
119-
stacktrace_add_library(backtrace ${BOOST_STACKTRACE_ENABLE_BACKTRACE} Boost::stacktrace_dump "backtrace;${CMAKE_DL_LIBS}" "")
120-
stacktrace_add_library(addr2line ${BOOST_STACKTRACE_ENABLE_ADDR2LINE} Boost::stacktrace_dump "${CMAKE_DL_LIBS}" "")
121-
stacktrace_add_library(basic ${BOOST_STACKTRACE_ENABLE_BASIC} Boost::stacktrace_dump "${CMAKE_DL_LIBS}" "")
122-
stacktrace_add_library(windbg ${BOOST_STACKTRACE_ENABLE_WINDBG} Boost::stacktrace_dump "dbgeng;ole32" "_GNU_SOURCE=1")
123-
stacktrace_add_library(windbg_cached ${BOOST_STACKTRACE_ENABLE_WINDBG_CACHED} Boost::stacktrace_dump "dbgeng;ole32" "_GNU_SOURCE=1")
135+
136+
stacktrace_add_library(dump ${_enable_non_noop_backend} "" "" "" ${BOOST_USE_MODULES})
137+
stacktrace_add_library(noop ${BOOST_STACKTRACE_ENABLE_NOOP} "" "" "" ${BOOST_USE_MODULES})
138+
stacktrace_add_library(backtrace ${BOOST_STACKTRACE_ENABLE_BACKTRACE} Boost::stacktrace_dump "backtrace;${CMAKE_DL_LIBS}" "" ${BOOST_USE_MODULES})
139+
stacktrace_add_library(addr2line ${BOOST_STACKTRACE_ENABLE_ADDR2LINE} Boost::stacktrace_dump "${CMAKE_DL_LIBS}" "" ${BOOST_USE_MODULES})
140+
stacktrace_add_library(basic ${BOOST_STACKTRACE_ENABLE_BASIC} Boost::stacktrace_dump "${CMAKE_DL_LIBS}" "" ${BOOST_USE_MODULES})
141+
stacktrace_add_library(windbg ${BOOST_STACKTRACE_ENABLE_WINDBG} Boost::stacktrace_dump "dbgeng;ole32" "_GNU_SOURCE=1" ${BOOST_USE_MODULES})
142+
stacktrace_add_library(windbg_cached ${BOOST_STACKTRACE_ENABLE_WINDBG_CACHED} Boost::stacktrace_dump "dbgeng;ole32" "_GNU_SOURCE=1" ${BOOST_USE_MODULES})
124143

125144
# boost_stacktrace, default library
126145

127-
add_library(boost_stacktrace INTERFACE)
146+
if(BOOST_USE_MODULES)
147+
add_library(boost_stacktrace)
148+
stacktrace_add_module(boost_stacktrace boost_stacktrace)
149+
set(__scope PUBLIC)
128150

129-
target_include_directories(boost_stacktrace INTERFACE include)
151+
foreach(backend noop backtrace addr2line basic windbg windbg_cached)
152+
if (TARGET boost_stacktrace_${backend})
153+
target_compile_definitions(boost_stacktrace_${backend} INTERFACE BOOST_STACKTRACE_BACKEND_MODULE=${backend})
154+
endif()
155+
endforeach()
156+
else()
157+
add_library(boost_stacktrace INTERFACE)
158+
set(__scope INTERFACE)
159+
endif()
130160

161+
target_include_directories(boost_stacktrace ${__scope} "${CMAKE_CURRENT_LIST_DIR}/include")
131162
add_library(Boost::stacktrace ALIAS boost_stacktrace)
132163

133164
if(BOOST_STACKTRACE_ENABLE_WINDBG)
@@ -147,13 +178,13 @@ else()
147178
endif()
148179

149180
message(STATUS "Boost.stacktrace default backend: ${__default_stacktrace_backend}")
150-
target_link_libraries(boost_stacktrace INTERFACE Boost::stacktrace_${__default_stacktrace_backend})
181+
target_link_libraries(boost_stacktrace ${__scope} Boost::stacktrace_${__default_stacktrace_backend})
151182

152183
# Boost::stacktrace_from_exception is never the default
153184
if(_enable_non_noop_backend)
154-
stacktrace_add_library(from_exception ${BOOST_STACKTRACE_ENABLE_FROM_EXCEPTION} Boost::stacktrace_dump "${CMAKE_DL_LIBS}" "")
155-
unset(_enable_non_noop_backend)
185+
stacktrace_add_library(from_exception ${BOOST_STACKTRACE_ENABLE_FROM_EXCEPTION} Boost::stacktrace_dump "${CMAKE_DL_LIBS}" "" FALSE)
156186
endif()
187+
unset(_enable_non_noop_backend)
157188

158189
if(BUILD_TESTING)
159190
add_subdirectory(test)

include/boost/stacktrace.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
#ifndef BOOST_STACKTRACE_HPP
88
#define BOOST_STACKTRACE_HPP
99

10-
#include <boost/config.hpp>
10+
#include <boost/stacktrace/detail/backend_config.hpp>
11+
12+
#if !defined(BOOST_USE_MODULES) || defined(BOOST_STACKTRACE_INTERFACE_UNIT)
13+
1114
#ifdef BOOST_HAS_PRAGMA_ONCE
1215
# pragma once
1316
#endif
@@ -17,4 +20,6 @@
1720
#include <boost/stacktrace/safe_dump_to.hpp>
1821
#include <boost/stacktrace/this_thread.hpp>
1922

23+
#endif // !defined(BOOST_USE_MODULES) || defined(BOOST_STACKTRACE_INTERFACE_UNIT)
24+
2025
#endif // BOOST_STACKTRACE_HPP

include/boost/stacktrace/detail/addr2line_impls.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@
1212
# pragma once
1313
#endif
1414

15-
#include <boost/stacktrace/detail/addr_base.hpp>
16-
#include <boost/stacktrace/detail/to_hex_array.hpp>
17-
#include <boost/stacktrace/detail/to_dec_array.hpp>
18-
#include <boost/stacktrace/detail/try_dec_convert.hpp>
15+
#if !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
1916
#include <boost/core/demangle.hpp>
17+
2018
#include <cstdio>
2119
#include <cstring>
2220

2321
#include <sys/types.h>
2422
#include <sys/wait.h>
2523
#include <signal.h>
24+
#endif // !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
2625

26+
#include <boost/stacktrace/detail/addr_base.hpp>
27+
#include <boost/stacktrace/detail/to_hex_array.hpp>
28+
#include <boost/stacktrace/detail/to_dec_array.hpp>
29+
#include <boost/stacktrace/detail/try_dec_convert.hpp>
2730

2831
namespace boost { namespace stacktrace { namespace detail {
2932

include/boost/stacktrace/detail/addr_base.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
# pragma once
1313
#endif
1414

15+
#if !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
1516
#include <fstream>
1617
#include <sstream>
1718
#include <cstdint>
1819
#include <cstdlib>
20+
#endif // !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
1921

2022
namespace boost { namespace stacktrace { namespace detail {
2123

include/boost/stacktrace/detail/addr_base_msvc.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# pragma once
1313
#endif
1414

15+
#if !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
1516
#include <cstdio>
1617
#include <cstdint>
1718
#include <memory>
@@ -27,6 +28,7 @@
2728
#include <psapi.h>
2829
#undef WIN32_LEAN_AND_MEAN
2930
#endif
31+
#endif // !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
3032

3133
namespace boost { namespace stacktrace { namespace detail {
3234
inline std::uintptr_t get_own_proc_addr_base(const void* addr) {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright Antony Polukhin, 2025-2026.
2+
// Copyright Fedor Osetrov, 2025-2026.
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See
5+
// accompanying file LICENSE_1_0.txt or copy at
6+
// http://www.boost.org/LICENSE_1_0.txt)
7+
8+
#ifndef BOOST_STACKTRACE_DETAIL_BACKEND_CONFIG_HPP
9+
#define BOOST_STACKTRACE_DETAIL_BACKEND_CONFIG_HPP
10+
11+
#if !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
12+
# include <boost/config.hpp>
13+
# ifdef BOOST_HAS_PRAGMA_ONCE
14+
# pragma once
15+
# endif
16+
#endif
17+
18+
#include "boost/stacktrace/detail/config.hpp"
19+
20+
#if defined(BOOST_USE_MODULES) && !defined(BOOST_STACKTRACE_INTERFACE_UNIT) && !defined(BOOST_STACKTRACE_INTERNAL_BUILD_LIBS)
21+
import boost.stacktrace.BOOST_STACKTRACE_BACKEND_MODULE;
22+
#endif
23+
24+
#endif

include/boost/stacktrace/detail/collect_msvc.ipp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
# pragma once
1313
#endif
1414

15-
#include <boost/stacktrace/safe_dump_to.hpp>
16-
15+
#if !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
1716
#include <boost/winapi/stack_backtrace.hpp>
17+
#endif // !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
18+
19+
#include <boost/stacktrace/safe_dump_to.hpp>
1820

1921
namespace boost { namespace stacktrace { namespace detail {
2022

include/boost/stacktrace/detail/collect_unwind.ipp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
# pragma once
1313
#endif
1414

15-
#include <boost/stacktrace/safe_dump_to.hpp>
16-
15+
#if !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
1716
// On iOS 32-bit ARM architecture _Unwind_Backtrace function doesn't exist, symbol is undefined.
1817
// Forcing libc backtrace() function usage.
1918
#include <boost/predef.h>
@@ -28,11 +27,14 @@
2827
#include <unwind.h>
2928
#endif
3029
#include <cstdio>
30+
#endif // !defined(BOOST_STACKTRACE_INTERFACE_UNIT)
3131

3232
#if !defined(_GNU_SOURCE) && !defined(BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED) && !defined(BOOST_WINDOWS)
3333
#error "Boost.Stacktrace requires `_Unwind_Backtrace` function. Define `_GNU_SOURCE` macro or `BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED` if _Unwind_Backtrace is available without `_GNU_SOURCE`."
3434
#endif
3535

36+
#include <boost/stacktrace/safe_dump_to.hpp>
37+
3638
namespace boost { namespace stacktrace { namespace detail {
3739

3840
#if !defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION)

0 commit comments

Comments
 (0)