Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
70 changes: 67 additions & 3 deletions .github/workflows/clang-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,74 @@ concurrency:
permissions:
contents: read

# Three independent jobs instead of one sequential one: the Release build and its tests, the
# clang-tidy analysis (sharded), and the ASan/UBSan Debug configuration. Each sets up the same
# toolchain through .github/actions/setup-clang21, so they cannot drift apart.
# The reference build, analysis and sanitizers share setup-clang21. A separate job exercises
# the admitted Clang 20 floor with GCC 16.1's libstdc++ instead of libc++ (#150/#151).
jobs:
clang20-libstdcxx:
name: Linux (Clang 20, libstdc++ GCC 16.1)
runs-on: ubuntu-latest
container: gcc:16.1.0

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Install Clang 20 and host tools
run: |
set -eu
apt-get update
apt-get install -y ca-certificates curl gnupg ninja-build python3
curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key -o /tmp/llvm-snapshot.asc
gpg --show-keys --with-colons --fingerprint /tmp/llvm-snapshot.asc \
| awk -F: '/^fpr:/ {print $10}' | grep -qx '6084F3CF814B57C1CF12EFD515CF4D18AF4F7421'
install -d -m 0755 /etc/apt/keyrings
gpg --dearmor < /tmp/llvm-snapshot.asc > /etc/apt/keyrings/llvm.gpg
codename="$(. /etc/os-release && echo "$VERSION_CODENAME")"
echo "deb [signed-by=/etc/apt/keyrings/llvm.gpg] https://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-20 main" \
> /etc/apt/sources.list.d/llvm20.list
apt-get update
apt-get install -y clang-20 clang-tools-20 llvm-20
git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: Setup pinned CMake
uses: jwlawson/actions-setup-cmake@v2
with:
cmake-version: '4.3.1'

- name: Verify Clang and selected standard library
run: |
set -eu
test "$(g++ -dumpfullversion)" = '16.1.0'
clang++-20 --version
clang++-20 --version | grep -E 'clang version 20\.'
printf '#include <bits/c++config.h>\nstatic_assert(_GLIBCXX_RELEASE == 16);\n' \
| clang++-20 --gcc-toolchain=/usr/local -stdlib=libstdc++ -std=c++23 -x c++ -fsyntax-only -
cmake --version
ninja --version

- name: Configure CMake with warnings as errors
run: cmake --preset ninja-clang20-libstdcxx

- name: Build both libraries, examples and tests
run: cmake --build --preset ninja-clang20-libstdcxx

- name: Verify governed boundary and negative controls
run: ctest --preset ninja-clang20-libstdcxx -L governed --verbose --no-tests=error --timeout 120

- name: Run full suite and independent consumers
run: ctest --preset ninja-clang20-libstdcxx -LE governed --parallel --output-on-failure --no-tests=error --timeout 120

- name: Verify no source-tree writes
run: |
status="$(git status --porcelain)"
if [ -n "$status" ]; then
echo "Build wrote into the source tree:"
echo "$status"
exit 1
fi

clang-build:
name: Linux (Clang 21, libc++)
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/windows-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ jobs:
run: ctest --preset ninja-msvc -LE governed --parallel --output-on-failure --no-tests=error --timeout 120
shell: cmd

- name: Repeat producer and consumer lifecycle
run: ctest --preset ninja-msvc -R "^examples\.contextualInventory\.lifecycle$" --repeat until-fail:20 --output-on-failure --no-tests=error --timeout 60
shell: cmd

- name: Verify no source-tree writes
shell: pwsh
run: |
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ is a certification, a validation for medical-device use, or a production-readine

## Unreleased

- Fix `mddlog::mddlog` failing to compile with Clang on libstdc++ (Clang's Linux default) under
warnings-as-errors: `SinkRegistry`'s deliberate use of the deprecated `shared_ptr` atomic free
functions is now silenced for Clang too, including clang-cl on MSVC's STL. The core was not
affected (#150).
- Exercise Clang 20 with GCC 16.1's libstdc++ in CI under warnings-as-errors, including the full
suite and independent package consumers (#151). The inventory lifecycle example now uses
bounded producer/consumer handoffs instead of an aggregate throughput deadline; Windows CI
repeats the scenario twenty times (#150).

- Propose the 1.0 compatibility commitments in
[ADR-007](docs/adr/ADR-007-compatibility-and-distribution.md): surface tiers recorded in a
checked [inventory](docs/api/public-surface.json), SemVer and deprecation without an ABI/BMI
Expand Down
21 changes: 21 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,25 @@
"MDDLOG_BUILD_TESTS": "ON"
}
},
{
"name": "ninja-clang20-libstdcxx",
"displayName": "Ninja with Clang 20 and libstdc++",
"description": "Clang 20 with GCC 16.1 libstdc++, warnings as errors, examples and full tests; clang-build.yml (#151).",
"generator": "Ninja",
"binaryDir": "build-clang20-libstdcxx",
"toolchainFile": "${sourceDir}/cmake/toolchains/linux-clang20-libstdcxx.cmake",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"WARNINGS_AS_ERRORS": "ON",
"MDDLOG_BUILD_EXAMPLES": "ON",
"MDDLOG_BUILD_TESTS": "ON"
}
},
{
"name": "ninja-clang-debug",
"displayName": "Ninja with Clang (Debug)",
Expand Down Expand Up @@ -135,6 +154,7 @@
{ "name": "ninja-gcc", "configurePreset": "ninja-gcc" },
{ "name": "ninja-gcc-debug", "configurePreset": "ninja-gcc-debug" },
{ "name": "ninja-clang", "configurePreset": "ninja-clang" },
{ "name": "ninja-clang20-libstdcxx", "configurePreset": "ninja-clang20-libstdcxx" },
{ "name": "ninja-clang-debug", "configurePreset": "ninja-clang-debug" },
{ "name": "ninja-macos-clang", "configurePreset": "ninja-macos-clang" },
{ "name": "ninja-macos-clang-debug", "configurePreset": "ninja-macos-clang-debug" }
Expand All @@ -145,6 +165,7 @@
{ "name": "ninja-gcc", "configurePreset": "ninja-gcc", "output": { "outputOnFailure": true } },
{ "name": "ninja-gcc-debug", "configurePreset": "ninja-gcc-debug", "output": { "outputOnFailure": true } },
{ "name": "ninja-clang", "configurePreset": "ninja-clang", "output": { "outputOnFailure": true } },
{ "name": "ninja-clang20-libstdcxx", "configurePreset": "ninja-clang20-libstdcxx", "output": { "outputOnFailure": true } },
{ "name": "ninja-clang-debug", "configurePreset": "ninja-clang-debug", "output": { "outputOnFailure": true } },
{ "name": "ninja-macos-clang", "configurePreset": "ninja-macos-clang", "output": { "outputOnFailure": true } },
{ "name": "ninja-macos-clang-debug", "configurePreset": "ninja-macos-clang-debug", "output": { "outputOnFailure": true } }
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ Configurations de la CI ([matrice détaillée](docs/compatibility-matrix.md)) :
| --- | --- | --- |
| Windows x64 | MSVC 19.40+ | 4.1.1 |
| Linux x86_64 | GCC 16.1.0 / libstdc++ | 4.1.1 |
| Linux x86_64 | Clang 20 amont / libstdc++ de GCC 16.1.0 | 4.3.1 |
| Linux x86_64 | Clang 21 amont / libc++ | 4.3.1 |
| macOS arm64 | Clang 21.1.8 amont / libc++ | 4.3.1 |

Expand Down
40 changes: 40 additions & 0 deletions cmake/toolchains/linux-clang20-libstdcxx.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Clang's admitted floor with GCC 16.1's libstdc++, exercised by clang-build.yml (#151).
if(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
message(FATAL_ERROR "The linux-clang20-libstdcxx toolchain is only valid on Linux hosts.")
endif()

set(_mddlog_llvm_root "$ENV{MDDLOG_LLVM_ROOT}")
if(NOT _mddlog_llvm_root)
set(_mddlog_llvm_root "/usr/lib/llvm-20")
endif()
set(_mddlog_gcc_root "$ENV{MDDLOG_GCC_ROOT}")
if(NOT _mddlog_gcc_root)
# The gcc:16.1.0 container installs its compiler and standard library here.
set(_mddlog_gcc_root "/usr/local")
endif()

set(CMAKE_CXX_COMPILER "${_mddlog_llvm_root}/bin/clang++" CACHE FILEPATH "" FORCE)
set(CMAKE_AR "${_mddlog_llvm_root}/bin/llvm-ar" CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB "${_mddlog_llvm_root}/bin/llvm-ranlib" CACHE FILEPATH "" FORCE)
set(CMAKE_CXX_FLAGS_INIT "--gcc-toolchain=${_mddlog_gcc_root} -stdlib=libstdc++")

# Clang need not discover a separately installed GCC's module manifest on its own.
execute_process(
COMMAND "${_mddlog_gcc_root}/bin/g++" -print-file-name=libstdc++.modules.json
RESULT_VARIABLE _mddlog_manifest_result
OUTPUT_VARIABLE _mddlog_manifest
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT _mddlog_manifest_result EQUAL 0 OR NOT EXISTS "${_mddlog_manifest}")
message(FATAL_ERROR "No libstdc++.modules.json from GCC under '${_mddlog_gcc_root}'.")
endif()
set(CMAKE_CXX_STDLIB_MODULES_JSON "${_mddlog_manifest}" CACHE FILEPATH "" FORCE)

foreach(_mddlog_required_tool
"${CMAKE_CXX_COMPILER}"
"${CMAKE_AR}"
"${CMAKE_RANLIB}")
if(NOT EXISTS "${_mddlog_required_tool}")
message(FATAL_ERROR "Required Clang 20 tool is missing: ${_mddlog_required_tool}")
endif()
endforeach()
4 changes: 2 additions & 2 deletions cmake/toolchains/linux-clang21-libcxx.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ set(CMAKE_CXX_COMPILER "${_mddlog_llvm_root}/bin/clang++" CACHE FILEPATH "" FORC
set(CMAKE_AR "${_mddlog_llvm_root}/bin/llvm-ar" CACHE FILEPATH "" FORCE)
set(CMAKE_RANLIB "${_mddlog_llvm_root}/bin/llvm-ranlib" CACHE FILEPATH "" FORCE)

# libc++ rather than libstdc++: the `std` module is shipped by the standard library, and only
# libc++ ships one this project builds against on Linux/Clang.
# Select libc++ for the reference Clang profile; linux-clang20-libstdcxx.cmake exercises
# Clang's admitted floor with GCC's separate standard library and module manifest.
set(CMAKE_CXX_FLAGS_INIT "-stdlib=libc++")

# Where Debian/Ubuntu put `libc++.modules.json` is not fixed across LLVM packagings, so search the
Expand Down
9 changes: 8 additions & 1 deletion docs/compatibility-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,24 @@ candidate jusqu’au gel 1.0 après #122.
| Plateforme | Compilateur / bibliothèque standard | CMake | Configurations | Consommateurs indépendants | Épinglage |
| --- | --- | --- | --- | --- | --- |
| Linux x86_64 | GCC 16.1.0 / libstdc++ (conteneur `gcc:16.1.0`) | 4.1.1 | Release (suite complète) ; Debug ASan/UBSan et TSan (`sanitizers.yml`) | installés complet et cœur, sous-répertoire, archive | exact |
| Linux x86_64 | Clang 20 amont / libstdc++ de GCC 16.1.0 (conteneur `gcc:16.1.0`) | 4.3.1 | Release, avertissements en erreurs, exemples et suite complète (`clang-build.yml`) | installés complet et cœur, sous-répertoire, archive | majeure Clang 20 contrôlée, GCC exact |
| Linux x86_64 — **profil de référence** | Clang 21 amont / libc++ (apt.llvm.org) | 4.3.1 | Release avec outil CLI ; Debug ASan/UBSan ; fuzzing ; campagnes | installés complet et cœur, sous-répertoire, archive | majeure 21 contrôlée, correctif flottant |
| macOS 15 arm64 | Clang 21.1.8 amont / libc++ (Homebrew `llvm@21`) | 4.3.1 | Release ; Debug ASan/UBSan | installés complet et cœur, sous-répertoire, archive | exact (refus sinon) |
| Windows x64 | MSVC de l’image `windows-latest` | 4.1.1 | Release | installés complet et cœur, sous-répertoire, archive | version de l’image flottante |

Les deux combinaisons à correctif ou image flottants sont **exercées**, non figées. Avant le
Les combinaisons à correctif ou image flottants sont **exercées**, non figées. Avant le
gel 1.0, il faut soit épingler leur version exacte, soit conserver par exécution le
`mddlog-build-info.json` du paquet testé, que `InstallTreeConsumer` imprime. Le signalement
TSan de Clang/libc++ ([#147](https://github.com/ambroise-leclerc/mddlog/issues/147),
[source conservée](validation/audit-robustness/tsan-libcxx/README.md)) reste ouvert : ce tuple
n’est pas qualifié pour TSan ; le TSan qualifié est GCC/libstdc++.

Le preset `ninja-clang20-libstdcxx` couvre le plancher Clang et la bibliothèque standard
qui déclenchait #150. Il sélectionne explicitement GCC 16.1 et son manifeste de modules ;
`MDDLOG_LLVM_ROOT` et `MDDLOG_GCC_ROOT` permettent d'indiquer d'autres racines d'installation.
Le job vérifie aussi `_GLIBCXX_RELEASE == 16` avant de construire. L'ajout du job ne constitue
une preuve pour une révision qu'après sa configuration, sa construction et ses tests réussis.

Le profil de référence est celui qui active tout : adaptateurs fichiers Linux, outil
`mddlog-audit`, sanitizers, fuzzing et campagnes de robustesse. Il ne remplace pas le profil
de déploiement réel, qui relève de #122.
Expand Down
14 changes: 11 additions & 3 deletions docs/contextual-api-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,10 @@ Le scénario `lifecycle` crée deux composants, chacun avec un anneau diagnostic
audit de capacité 4, et des identités de flux distinctes. Des chaînes temporaires alimentent
les factories avant le démarrage ; les liaisons et composants sont copiés dans les producteurs.
Deux `jthread` produisent pendant qu'un seul consommateur d'application draine les quatre
anneaux. Un acquittement atomique par producteur organise la prochaine commande à l'extérieur
du métier ; la méthode d'émission n'attend pas. Le délai de garde arrête l'essai en cas de défaut.
Les tokens d'arrêt permettent aussi aux producteurs de sortir pendant une exception de l'hôte.
anneaux. Deux sémaphores par producteur signalent la publication complète et son acquittement
à l'extérieur du métier ; la méthode d'émission n'attend pas. Chaque attente a un délai de garde
de dix secondes. Les tokens d'arrêt empêchent une nouvelle commande pendant une exception
de l'hôte ; une attente déjà engagée reste bornée par son délai.

200 mutations par producteur donnent 400 diagnostics et 800 événements d'audit. Les multiples
réutilisations des slots vérifient les copies avant acquittement, les séquences propres à
Expand All @@ -111,6 +112,13 @@ liaisons et destinations sortent de portée dans cet ordre. Les copies conservé
consommateur sont examinées après réutilisation des slots ; aucune vue acquittée n'est utilisée.
Ce scénario exerce une ordonnance particulière et ne remplace pas #120.

Suivi de PR #153 (#150/#151) : le job Windows avait échoué après 10,60 s dans `lifecycle`.
La boucle d'attente active avec `yield()` et le délai global de dix secondes sont remplacés
par les rendez-vous ci-dessus : le test ne fixe plus un débit minimal de 200 échanges sous
l'ordonnanceur de l'hôte. Les contrôles de comptage, de phases, de liens et de copies restent
actifs. Le job Windows répète désormais ce scénario vingt fois. Cette correction ultérieure
ne modifie ni les révisions ni les résultats des campagnes historiques ci-dessous.

## Critères C de #113

| Critère | Preuve et limite |
Expand Down
Loading
Loading