Skip to content
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
112 changes: 74 additions & 38 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ jobs:
Formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Formatting
uses: DoozyX/clang-format-lint-action@v0.13
uses: DoozyX/clang-format-lint-action@bcb4eb2cb0d707ee4f3e5cc3b456eb075f12cf73 # v0.20
with:
clangFormatVersion: 10

Expand All @@ -41,29 +41,13 @@ jobs:
fail-fast: false
matrix:
include:
# Linux, gcc
- { compiler: gcc-7, cxxstd: '14,17', boostBranch: boost-1.86.0, os: ubuntu-latest, container: 'ubuntu:20.04' }
- { compiler: gcc-10, cxxstd: '14,17,20', boostBranch: boost-1.86.0, os: ubuntu-22.04 }
- { compiler: gcc-12, cxxstd: '14,17,20', boostBranch: master, os: ubuntu-22.04 }
- { compiler: gcc-14, cxxstd: '14,17,20', boostBranch: boost-1.86.0, os: ubuntu-24.04 }
- { compiler: gcc-14, cxxstd: '14,17,20', boostBranch: master, os: ubuntu-24.04 }

# Linux, clang
- { compiler: clang-14, cxxstd: '14,17,20', boostBranch: boost-1.86.0, os: ubuntu-24.04 }
- { compiler: clang-18, cxxstd: '14,17,20', boostBranch: boost-1.86.0, os: ubuntu-24.04 }
- { compiler: clang-18, cxxstd: '14,17,20', boostBranch: master, os: ubuntu-24.04 }

# Windows
- { toolset: msvc-14.2, os: windows-2019, cxxstd: 14, generator: 'Visual Studio 16 2019' }
- { toolset: gcc, os: windows-2019, cxxstd: 17, generator: 'MinGW Makefiles' }
- { toolset: msvc-14.3, os: windows-2022, cxxstd: 20, generator: 'Visual Studio 17 2022' }

- { name: Collect coverage, coverage: yes,
compiler: gcc-8, cxxstd: '14', boostBranch: boost-1.86.0, os: ubuntu-latest, container: 'ubuntu:20.04' }
- { toolset: gcc, os: windows-2022, cxxstd: 17, generator: 'MinGW Makefiles' }

timeout-minutes: 120
runs-on: ${{matrix.os}}
container: ${{matrix.container}}
env:
B2_CXXFLAGS: ${{matrix.cxxflags}}

steps:
- name: Prepare container environment
Expand All @@ -82,19 +66,19 @@ jobs:
git config --global pack.threads 0
git config --global --add safe.directory "$GITHUB_WORKSPACE" # Avoid ownership issues of repo in container

- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
# For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary'
fetch-depth: ${{ matrix.coverage && '0' || '1' }}

# Checking out Boost and all its submodules takes ages...
- name: Cache Boost
uses: actions/cache@v4
uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
with:
path: boost-root
key: boost-${{matrix.boostBranch}}
- name: Checkout Boost
uses: actions/checkout@v4
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: boostorg/boost
ref: ${{matrix.boostBranch}}
Expand Down Expand Up @@ -130,14 +114,17 @@ jobs:
if [[ "${{matrix.coverage}}" == "yes" ]]; then
B2_FLAGS+=" cxxflags=--coverage linkflags=--coverage"
fi
echo "B2_FLAGS=$B2_FLAGS" >> $GITHUB_ENV
if [[ -n $B2_CXXFLAGS ]]; then
B2_FLAGS+=" cxxflags='$B2_CXXFLAGS'"
fi
echo "B2_FLAGS=$B2_FLAGS linkflags=-Wl,--verbose" >> $GITHUB_ENV

# Move the Boost root to a sibling folder
mv boost-root ..
echo "BOOST_ROOT=${{github.workspace}}/../boost-root" >> $GITHUB_ENV

- name: Cache ccache
uses: hendrikmuhs/ccache-action@v1
uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23
if: startsWith(matrix.os, 'ubuntu')
with:
key: ${{matrix.os}}-${{matrix.compiler}}-${{matrix.boostBranch}}
Expand All @@ -148,8 +135,14 @@ jobs:

- name: Boost build
run: |
./b2 "$GITHUB_WORKSPACE/test" -q $B2_FLAGS -j3
set -x
./b2 "$GITHUB_WORKSPACE/test" -q $B2_FLAGS -d+2 -j3
./b2 "$GITHUB_WORKSPACE/doc//mock_examples" -q $B2_FLAGS "$@"
for i in $(find . -name 'test_demangle*.exe'); do
echo $i
objdump -p $i | grep "DLL Name" || true
objdump -p $i | grep -i "characteristics" || true
done
working-directory: ${{env.BOOST_ROOT}}

- name: Run inspect check
Expand All @@ -162,18 +155,30 @@ jobs:

- name: Collect coverage
if: matrix.coverage
working-directory: ${{github.workspace}} # Make sure file is found by upload action
run: |
B2_COMPILER=${{matrix.compiler}}
if [[ "$B2_COMPILER" =~ gcc- ]]; then
ver="${B2_COMPILER##*gcc-}"
else
ver=8
fi
GCOV=gcov-${ver}
lcov --version
lcov --gcov-tool=gcov-8 --directory "$GITHUB_WORKSPACE/test" --capture --output-file all.info
LCOV_OPTIONS=()
LCOV_OPTIONS+=(--rc "branch_coverage=0")
LCOV_OPTIONS+=(--ignore-errors "inconsistent,mismatch,unused")

lcov "${LCOV_OPTIONS[@]}" --gcov-tool="$GCOV" --directory "$GITHUB_WORKSPACE/test" --capture --output-file all.info
# dump a summary on the console
lcov --list all.info
lcov "${LCOV_OPTIONS[@]}" --list all.info
# Limit to our files (header-only in this case)
lcov --extract all.info "$GITHUB_WORKSPACE/include/*" --output-file coverage.info
lcov "${LCOV_OPTIONS[@]}" --extract all.info "$GITHUB_WORKSPACE/include/*" --output-file coverage.info
# Output what was collected
lcov --list coverage.info
lcov "${LCOV_OPTIONS[@]}" --list coverage.info
- name: Upload coverage
if: matrix.coverage
uses: coverallsapp/github-action@master
uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7
with:
path-to-lcov: ${{github.workspace}}/coverage.info
github-token: ${{secrets.GITHUB_TOKEN}}
Expand All @@ -186,9 +191,10 @@ jobs:
echo "LD_LIBRARY_PATH=$PWD/stage/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV

- name: CMake build
env:
CXX_STD: ${{matrix.cxxstd}}
run: |
mkdir build && cd build
CXX_STANDARD="${{matrix.cxxstd}}"
if [[ "${{matrix.os}}" == "windows-"* ]]; then
extra_args=()
else
Expand All @@ -198,12 +204,42 @@ jobs:
extra_args+=(-G "${{matrix.generator}}")
fi
if [[ "${{matrix.generator}}" == "MinGW"* ]]; then
extra_args+=(-DCMAKE_CXX_FLAGS="-Wa,-mbig-obj")
which g++ && g++ --version || true
which c++ && c++ --version || true
extra_args+=(-DCMAKE_CXX_COMPILER=g++)
B2_CXXFLAGS=-fno-inline
fi
if [[ -n $B2_CXXFLAGS ]]; then
extra_args+=(-DCMAKE_CXX_FLAGS="$B2_CXXFLAGS")
fi

CXX_STD=${CXX_STD##*,} # Extract last value
case "$CXX_STD" in
latest) CXX_STD="" ;; # MSVC: Use default
# Use older ones instead of aliases
2b) CXX_STD=20 ;;
2c) CXX_STD=23 ;;
esac
if [[ -n "$CXX_STD" ]]; then
extra_args+=(-DCMAKE_CXX_STANDARD="$CXX_STD")
fi
echo "Using extra args: ${extra_args[*]}"
cmake .. -DCMAKE_BUILD_TYPE=Debug -DBoost_ROOT="$BOOST_ROOT/stage" -DCMAKE_CXX_STANDARD="${CXX_STANDARD##*,}" "${extra_args[@]}" -DCMAKE_VERBOSE_MAKEFILE=ON -DBoost_DEBUG=ON -DBoost_VERBOSE=ON
cmake --build . --config Debug --parallel 3
ctest --output-on-failure --build-config Debug
for i in ON OFF; do
echo "Using extra args: ${extra_args[*]} -DCMAKE_EXECUTABLE_ENABLE_EXPORTS=$i"
cmake .. -DCMAKE_BUILD_TYPE=Debug -DBoost_ROOT="$BOOST_ROOT/stage" "${extra_args[@]}" -DCMAKE_EXECUTABLE_ENABLE_EXPORTS=$i -DCMAKE_EXE_LINKER_FLAGS="-Wl,--verbose" -DCMAKE_CXX_EXTENSIONS=OFF -DCMAKE_VERBOSE_MAKEFILE=ON -DBoost_DEBUG=ON -DBoost_VERBOSE=ON
cmake --build . --config Debug --parallel 3
for i in $(find . -name 'test_demangle*.exe'); do
echo $i
objdump -p $i | grep "DLL Name" || true
objdump -p $i | grep -i "characteristics" || true
done
for i in $(find test/CMakeFiles -type f); do
[[ $i == *".rsp" ]] || continue
echo $i; cat $i;
done
ctest --output-on-failure --build-config Debug || true
done

- run: debug.sh

- name: Cleanup Boost folder to reduce cache usage
if: ${{ always() }}
Expand Down
21 changes: 15 additions & 6 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# Copyright 2015 Mathieu Champlon
# Copyright 2020-2025 Alexander Grund
# Copyright 2020-2026 Alexander Grund

skip_branch_with_pr: true

Expand All @@ -30,31 +30,40 @@ environment:
ADDRESS_MODEL: 64
VARIANT: debug
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
BOOST: 1_83_0
BOOST: 1_85_0
TOOLSET: msvc-14.3
CXX_STANDARD: 14,17,20
ADDRESS_MODEL: 64
VARIANT: debug
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
BOOST: 1_86_0
BOOST: 1_89_0
TOOLSET: msvc-14.3
CXX_STANDARD: 14,17
ADDRESS_MODEL: 64
VARIANT: debug
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
BOOST: 1_86_0
BOOST: 1_89_0
TOOLSET: msvc-14.3
CXX_STANDARD: 20
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2026
BOOST: 1_91_0
TOOLSET: msvc-14.5
CXX_STANDARD: 20

- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2026
BOOST: 1_91_0
TOOLSET: msvc-14.5
CXX_STANDARD: latest

# CMake builds
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
BOOST: 1_65_1
CMAKE: true
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
BOOST: 1_83_0
BOOST: 1_85_0
CMAKE: true
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
BOOST: 1_86_0
BOOST: 1_89_0
CMAKE: true

install:
Expand Down
142 changes: 142 additions & 0 deletions debug.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/bin/bash

set +e
SRC="$GITHUB_WORKSPACE/test/detail/test_demangle.cpp"
DIAG_DIR="$GITHUB_WORKSPACE/build/diag"
mkdir -p "$DIAG_DIR"
cd "$DIAG_DIR" || exit 0

echo "========== ENVIRONMENT =========="
g++ --version || true
ld --version || true
cmake --version || true

echo "========== RUNTIME DLL CRT ANALYSIS =========="
echo "--- libstdc++-6.dll DLL deps ---"
objdump -p C:/mingw64/bin/libstdc++-6.dll | grep "DLL Name" || true
echo "--- libgcc_s_seh-1.dll DLL deps ---"
objdump -p C:/mingw64/bin/libgcc_s_seh-1.dll | grep "DLL Name" || true
echo "--- libstdc++-6.dll malloc/free imports ---"
objdump -p C:/mingw64/bin/libstdc++-6.dll | grep -iE "malloc|^[[:space:]]*free" || true

echo "========== B2-BUILT EXE ANALYSIS =========="
B2_EXE=$(find "$GITHUB_WORKSPACE/test/bin" -name 'test_demangle*cpp*.exe' 2>/dev/null | head -1)
echo "b2 exe: $B2_EXE"
if [ -n "$B2_EXE" ]; then
objdump -p "$B2_EXE" | grep -E "DLL Name|Characteristics" || true
echo "--- b2 exe exports (malloc/free?) ---"
objdump -p "$B2_EXE" | grep -iE "malloc|free" || true
echo "--- b2 exe run ---"
"$B2_EXE" 2>&1 || true
else
echo "b2 exe not found"
fi

echo "========== CMAKE-BUILT EXE ANALYSIS =========="
CMAKE_EXE="$GITHUB_WORKSPACE/build/test/test_demangle.exe"
if [ -f "$CMAKE_EXE" ]; then
objdump -p "$CMAKE_EXE" | grep -E "DLL Name|Characteristics" || true
echo "--- CMake exe exports (malloc/free?) ---"
objdump -p "$CMAKE_EXE" | grep -iE "malloc|free" || true
echo "--- CMake exe export count ---"
objdump -p "$CMAKE_EXE" | grep -c "\[Ordinal\|Export" || true
echo "--- CMake exe run ---"
"$CMAKE_EXE" 2>&1 || true
fi

echo "========== CREATE DIAGNOSTIC SOURCE =========="
cat > diag_demangle.cpp << 'EOF'
#include <cstdlib>
#include <cxxabi.h>
#include <cstdio>
#include <windows.h>
int main() {
HMODULE hM=NULL, hF=NULL, hD=NULL;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,(LPCSTR)&malloc,&hM);
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,(LPCSTR)&free,&hF);
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS|GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,(LPCSTR)&abi::__cxa_demangle,&hD);
char mP[MAX_PATH],fP[MAX_PATH],dP[MAX_PATH];
GetModuleFileNameA(hM,mP,MAX_PATH); GetModuleFileNameA(hF,fP,MAX_PATH); GetModuleFileNameA(hD,dP,MAX_PATH);
printf("malloc @ %p in %s\n",&malloc,mP);
printf("free @ %p in %s\n",&free,fP);
printf("demangle @ %p in %s\n",&abi::__cxa_demangle,dP);
int status=0;
char* result=abi::__cxa_demangle(typeid(int).name(),0,0,&status);
printf("status=%d result=%s\n",status,result?result:"(null)");
if(result){printf("freeing...\n"); std::free(result); printf("OK\n");}
return 0;
}
EOF
g++ -std=c++17 -O0 -fno-inline -g -c diag_demangle.cpp -o diag.o 2>&1 || true
ar qc diag.a diag.o 2>&1 || true

echo "========== ISOLATION TESTS =========="

echo "--- A: minimal (no flags) ---"
g++ -std=c++17 -g diag.o -o a.exe 2>&1 || true
objdump -p a.exe | grep "DLL Name" || true
./a.exe 2>&1 || true

echo "--- B: --whole-archive only ---"
g++ -std=c++17 -g -Wl,--whole-archive diag.a -Wl,--no-whole-archive -o b.exe 2>&1 || true
objdump -p b.exe | grep "DLL Name" || true
./b.exe 2>&1 || true

echo "--- C: --out-implib only ---"
g++ -std=c++17 -g diag.o -o c.exe -Wl,--out-implib,lc.dll.a -Wl,--major-image-version,0,--minor-image-version,0 2>&1 || true
objdump -p c.exe | grep "DLL Name" || true
echo "exports:"; objdump -p c.exe | grep -c "\[Ordinal" || true
./c.exe 2>&1 || true

echo "--- D: CMake combo (--whole-archive + --out-implib) ---"
g++ -std=c++17 -g -Wl,--whole-archive diag.a -Wl,--no-whole-archive -o d.exe -Wl,--out-implib,ld.dll.a -Wl,--major-image-version,0,--minor-image-version,0 2>&1 || true
objdump -p d.exe | grep "DLL Name" || true
echo "exports:"; objdump -p d.exe | grep -c "\[Ordinal" || true
./d.exe 2>&1 || true

echo "--- E: b2-style (--start-group + -Bstatic + -Bdynamic) ---"
g++ -std=c++17 -g -Wl,--start-group diag.o -Wl,-Bstatic -Wl,-Bdynamic -Wl,--end-group -o e.exe 2>&1 || true
objdump -p e.exe | grep "DLL Name" || true
./e.exe 2>&1 || true

echo "--- F: CMake combo + -shared-libgcc ---"
g++ -std=c++17 -g -shared-libgcc -Wl,--whole-archive diag.a -Wl,--no-whole-archive -o f.exe -Wl,--out-implib,lf.dll.a -Wl,--major-image-version,0,--minor-image-version,0 2>&1 || true
objdump -p f.exe | grep "DLL Name" || true
./f.exe 2>&1 || true

echo "--- G: --out-implib + --export-all-symbols (explicit) ---"
g++ -std=c++17 -g diag.o -o g.exe -Wl,--out-implib,lg.dll.a -Wl,--export-all-symbols 2>&1 || true
objdump -p g.exe | grep "DLL Name" || true
echo "exports:"; objdump -p g.exe | grep -c "\[Ordinal" || true
./g.exe 2>&1 || true

echo "--- H: --major-image-version only (no --out-implib) ---"
g++ -std=c++17 -g diag.o -o h.exe -Wl,--major-image-version,0,--minor-image-version,0 2>&1 || true
./h.exe 2>&1 || true

echo "--- I: CMake combo with static Boost.Test ---"
BOOST_STATIC="$BOOST_ROOT/stage/lib/libboost_unit_test_framework-mgw14-mt-d-x64-1_92.a"
if [ -f "$BOOST_STATIC" ]; then
g++ -std=c++17 -g -Wl,--whole-archive diag.a -Wl,--no-whole-archive -o i.exe -Wl,--out-implib,li.dll.a -Wl,--major-image-version,0,--minor-image-version,0 "$BOOST_STATIC" 2>&1 || true
objdump -p i.exe | grep "DLL Name" || true
./i.exe 2>&1 || true
fi

echo "--- J: CMake combo with dynamic Boost.Test ---"
BOOST_DLL_A=$(find "$BOOST_ROOT" -name 'libboost_unit_test_framework-mgw14-d-x64-*.dll.a' 2>/dev/null | head -1)
BOOST_DLL_DIR=$(find "$BOOST_ROOT" -name 'libboost_unit_test_framework-mgw14-d-x64-*.dll' -printf '%h\n' 2>/dev/null | head -1)
if [ -n "$BOOST_DLL_A" ]; then
g++ -std=c++17 -g -Wl,--whole-archive diag.a -Wl,--no-whole-archive -o j.exe -Wl,--out-implib,lj.dll.a -Wl,--major-image-version,0,--minor-image-version,0 "$BOOST_DLL_A" 2>&1 || true
objdump -p j.exe | grep "DLL Name" || true
if [ -n "$BOOST_DLL_DIR" ]; then PATH="$BOOST_DLL_DIR:$PATH" ./j.exe 2>&1 || true; fi
fi

echo "========== MAP FILE ANALYSIS =========="
echo "--- b2-style map ---"
g++ -std=c++17 -g -Wl,--start-group diag.o -Wl,-Bstatic -Wl,-Bdynamic -Wl,--end-group -o map_b2.exe -Wl,-Map,map_b2.map 2>&1 || true
grep -iE "free|malloc|demangle|__cxa" map_b2.map 2>/dev/null || true
echo "--- CMake-style map ---"
g++ -std=c++17 -g -Wl,--whole-archive diag.a -Wl,--no-whole-archive -o map_cm.exe -Wl,--out-implib,lmap.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -Wl,-Map,map_cm.map 2>&1 || true
grep -iE "free|malloc|demangle|__cxa" map_cm.map 2>/dev/null || true

echo "========== DONE =========="
Loading
Loading