diff --git a/.github/workflows/reusable/cached-install/action.yml b/.github/workflows/reusable/cached-install/action.yml index 18a5a8af..f65467ee 100644 --- a/.github/workflows/reusable/cached-install/action.yml +++ b/.github/workflows/reusable/cached-install/action.yml @@ -4,18 +4,43 @@ description: "install dependencies, build and cache result, or restore from cach runs: using: "composite" steps: - - name: cache homedir + # The cache keys must distinguish the TARGET platform, not just the + # runner: the macOS host build, the iOS build and the Android build + # all run on the same macos runner image, and GitHub's cache is + # write-once per key — with a shared key the first job to save owns + # the cache forever and the other platforms' saves fail ("Cache save + # failed."), so their dependencies were rebuilt from source on every + # run (~30 min Android, ~35 min iOS). ARCHFLAGS is the workflow-level + # platform selector (empty = host, --ios, --android). The vcpkg + # submodule commit is part of the key because the tool version + # changes what it builds; the restore-keys prefix fallback reuses the + # newest previous cache on any key miss — vcpkg's own per-package ABI + # hashing makes stale archive entries harmless (they are ignored) and + # `vcpkg install` reconciles a stale installed tree. + - name: compute cache keys + id: keys + run: | + echo "platform=${ARCHFLAGS:-host}" >> "$GITHUB_OUTPUT" + echo "vcpkg_sha=$(git rev-parse HEAD:vcpkg)" >> "$GITHUB_OUTPUT" + shell: bash + - name: cache vcpkg binary archives id: cache-homedir uses: actions/cache/restore@v4 with: - key: ${{ runner.arch }}-${{ runner.os }}-cache-homedir2-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} + key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-archives-${{ steps.keys.outputs.vcpkg_sha }}-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} + restore-keys: | + ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-archives-${{ steps.keys.outputs.vcpkg_sha }}- + ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-archives- path: | ~/.cache/vcpkg/archives - name: cache vcpkg installed id: cache-vcpkg-installed uses: actions/cache/restore@v4 with: - key: ${{ runner.arch }}-${{ runner.os }}-cache-vcpkg-installed2-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} + key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-installed-${{ steps.keys.outputs.vcpkg_sha }}-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} + restore-keys: | + ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-installed-${{ steps.keys.outputs.vcpkg_sha }}- + ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-installed- path: | ./build/vcpkg_installed - name: install-prerequisities @@ -45,30 +70,22 @@ runs: exit "$EXITCODE" fi shell: bash - - name: cache homedir save + # Save even on failure (if: always()) so a partially built dependency + # set is reused by the retry. Saving is skipped when the exact key was + # already restored (nothing new to store). + - name: cache vcpkg binary archives save id: cache-homedir-save - if: always() + if: always() && steps.cache-homedir.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: - key: ${{ runner.arch }}-${{ runner.os }}-cache-homedir2-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} + key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-archives-${{ steps.keys.outputs.vcpkg_sha }}-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} path: | ~/.cache/vcpkg/archives - name: cache vcpkg installed save id: cache-vcpkg-installed-save - if: always() + if: always() && steps.cache-vcpkg-installed.outputs.cache-hit != 'true' uses: actions/cache/save@v4 with: - key: ${{ runner.arch }}-${{ runner.os }}-cache-vcpkg-installed2-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} + key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-installed-${{ steps.keys.outputs.vcpkg_sha }}-${{ hashFiles('./vcpkg.json', './overlaytriplets/**', './overlayports/**') }} path: | ./build/vcpkg_installed - #- name: Commit compiled binaries - # run: | - # git config --global user.name 'github-actions[bot]' - # git config --global user.email 'github-actions[bot]@users.noreply.github.com' - # git add packages/streamr-libstreamrproxyclient/dist - # git add packages/streamr-libstreamrproxyclient/wrappers/go - # git commit -m "Automatically compiled binaries" - # git pull --rebase --no-edit - # git push --no-verify - # shell: bash - diff --git a/MODERNIZATION.md b/MODERNIZATION.md index 5ab75a64..c6f68a90 100644 --- a/MODERNIZATION.md +++ b/MODERNIZATION.md @@ -1011,7 +1011,31 @@ exactly that. So consolidation walks the dependency chain from the top: version accepts it — owner-approved selective disabling, compiler coverage unaffected (fourth exclusion overall; revisit each clangd release). -7. C-7 streamr-json +7. **C-7 streamr-json** ✅ — the 3 headers (jsonConcepts, toJson, + toString) became named sub-modules (`streamr.json.X`); façade and + include/ tree deleted; the 4 importers (json's own tests + example) + flipped to narrow imports, and the logger units' temporary TEXTUAL + `streamr-json/toJson.hpp` include from C-6 flipped to + `import streamr.json.toJson;`. First conversion with zero compile + errors on the first whole-tree build — the accumulated rules + (std-include pass, curated-name consumer flip, minimal imports, + inline-constexpr, GMF-only C declarations) now cover the whole + failure surface. + **The same PR repairs the CI dependency caching** (owner asked for it + to be folded in): the C-2 consolidation commit had accidentally + REVERTED PR #41's per-platform cache keys in + `.github/workflows/reusable/cached-install/action.yml` (a rebase + mishap — #41 and C-2 were in flight simultaneously). Since C-2 the + Android/iOS jobs shared one `ARM64-macOS-…` key with the host macOS + leg; the host job saved first and owned the write-once key, so the + cross builds restored a useless host cache and rebuilt every vcpkg + dependency from source — degrading as the old per-platform entries + were LRU-evicted (repo cache 11.7 GB > 10 GB cap): Android leg C-3 + 48 min → C-6 139/123 min. The #41 scheme (`${ARCHFLAGS:-host}` + platform component + vcpkg submodule SHA + restore-keys fallbacks + + skip-save-on-exact-hit) is restored verbatim; the first post-merge + run per platform repopulates the caches (slow once), after which + Android returns to ~10 min and iOS to ~5 min. 8. C-8 streamr-eventemitter (+ final bench.sh metrics and memo closure) One package per PR, `bench.sh` measured at the dht step and at the end diff --git a/packages/streamr-json/CMakeLists.txt b/packages/streamr-json/CMakeLists.txt index 0a5f220f..46ab52b5 100644 --- a/packages/streamr-json/CMakeLists.txt +++ b/packages/streamr-json/CMakeLists.txt @@ -47,19 +47,16 @@ endif() # project() because it inspects the compiler id. include(${CMAKE_CURRENT_SOURCE_DIR}/StreamrModules.cmake) -# Module façade (MODERNIZATION.md Part 2): the package is now a STATIC -# library whose module interface units re-export the public headers. -# #include consumers are unaffected; import consumers get the BMIs. +# CONSOLIDATED (MODERNIZATION.md Phase 2.6): one named sub-module per +# former public header (settled architecture: no umbrella). The include/ +# tree is gone; the module interface units are the source of truth, so +# the package no longer exports any include directory. +file(GLOB_RECURSE STREAMR_JSON_MODULE_UNITS CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/modules/*.cppm) streamr_add_module_library(streamr-json - FILES - modules/streamr.json.cppm - modules/streamr.json-all.cppm) + FILES ${STREAMR_JSON_MODULE_UNITS}) add_library(streamr::streamr-json ALIAS streamr-json) -target_include_directories( - streamr-json PUBLIC $ - $) - # PUBLIC (was INTERFACE): the module interface units themselves compile # against boost-pfr/nlohmann in their global module fragments. target_link_libraries(streamr-json PUBLIC Boost::pfr) diff --git a/packages/streamr-json/lint.sh b/packages/streamr-json/lint.sh index 547d26c0..1c7dc752 100755 --- a/packages/streamr-json/lint.sh +++ b/packages/streamr-json/lint.sh @@ -10,11 +10,14 @@ clangd-tidy -p ./build $FILES echo "Running clang-format --dry-run on $FILES" ../../run-clang-format.py $FILES -# Module interface units: format check only. clangd-tidy is not run on -# .cppm files (headers remain the fully linted source of truth during the -# façade migration; clangd modules support is still experimental). +# CONSOLIDATED (MODERNIZATION.md Phase 2.6): the include/ tree is gone — +# the code lives in the module interface units, which are linted with +# clangd-tidy as the source of truth. MODULE_FILES=$(find ./modules -type f -name "*.cppm" 2>/dev/null | xargs echo) if [ -n "$MODULE_FILES" ]; then + echo "Running clangd-tidy on $MODULE_FILES" + clangd-tidy -p ./build $MODULE_FILES + echo "Running clang-format --dry-run on $MODULE_FILES" ../../run-clang-format.py $MODULE_FILES fi diff --git a/packages/streamr-json/include/streamr-json/jsonConcepts.hpp b/packages/streamr-json/modules/jsonConcepts.cppm similarity index 87% rename from packages/streamr-json/include/streamr-json/jsonConcepts.hpp rename to packages/streamr-json/modules/jsonConcepts.cppm index c402da5a..7abda68a 100644 --- a/packages/streamr-json/include/streamr-json/jsonConcepts.hpp +++ b/packages/streamr-json/modules/jsonConcepts.cppm @@ -1,10 +1,19 @@ -#ifndef STREAMR_JSON_JSONCONCEPTS_HPP -#define STREAMR_JSON_JSONCONCEPTS_HPP - +// Module streamr.json.jsonConcepts +// CONSOLIDATED from the former header +// streamr-json/jsonConcepts.hpp (MODERNIZATION.md Phase 2.6): +// this file is now the source of truth. +module; + +#include +#include +#include +#include #include #include -namespace streamr::json { +export module streamr.json.jsonConcepts; + +export namespace streamr::json { namespace suppresslint { // linter does not support concepts, and thinks this // file is unused using SuppressLint = void; @@ -88,6 +97,4 @@ std::initializer_list>); }; */ -} // namespace streamr::json - -#endif // STREAMR_JSON_JSONCONCEPTS_HPP \ No newline at end of file +} // namespace streamr::json \ No newline at end of file diff --git a/packages/streamr-json/modules/streamr.json-all.cppm b/packages/streamr-json/modules/streamr.json-all.cppm deleted file mode 100644 index 6ff5c7fc..00000000 --- a/packages/streamr-json/modules/streamr.json-all.cppm +++ /dev/null @@ -1,48 +0,0 @@ -// Coarse façade partition over ALL public headers of streamr-json. -// One partition (instead of one per header) keeps the number of -// module units — and thus repeated global-module-fragment parses -// of the expensive header stacks — minimal during the façade -// stage (measured at the Phase 2.4 bench checkpoint). Per-header -// granularity returns at consolidation if needed. -module; - -#include "streamr-json/jsonConcepts.hpp" -#include "streamr-json/toJson.hpp" -#include "streamr-json/toString.hpp" - -export module streamr.json:all; - -export namespace streamr::json { - -using streamr::json::AssignableToNlohmannJson; -using streamr::json::AssociativeType; -using streamr::json::InitializerList; -using streamr::json::IterableType; -using streamr::json::NotAssignableToNlohmannJson; -using streamr::json::PointerLike; -using streamr::json::PointerType; -using streamr::json::ReflectableType; -using streamr::json::TypeWithToJson; - -} // namespace streamr::json - -export namespace streamr::json { - -using streamr::json::addStructElementsToJson; -using streamr::json::addStructElementToJson; -using streamr::json::AssignableToJsonBuilder; -using streamr::json::json; -using streamr::json::JsonBuilder; -using streamr::json::JsonInitializerList; -using streamr::json::pointerToJson; -using streamr::json::StreamrJsonInitializerList; -using streamr::json::toJson; - -} // namespace streamr::json - -export namespace streamr::json { - -using streamr::json::toString; -using streamr::json::TypeWithToString; - -} // namespace streamr::json diff --git a/packages/streamr-json/modules/streamr.json.cppm b/packages/streamr-json/modules/streamr.json.cppm deleted file mode 100644 index 3c7ca62c..00000000 --- a/packages/streamr-json/modules/streamr.json.cppm +++ /dev/null @@ -1,4 +0,0 @@ -// Primary module interface unit of streamr.json. -export module streamr.json; - -export import :all; diff --git a/packages/streamr-json/include/streamr-json/toJson.hpp b/packages/streamr-json/modules/toJson.cppm similarity index 95% rename from packages/streamr-json/include/streamr-json/toJson.hpp rename to packages/streamr-json/modules/toJson.cppm index beed7d02..632fe30e 100644 --- a/packages/streamr-json/include/streamr-json/toJson.hpp +++ b/packages/streamr-json/modules/toJson.cppm @@ -1,9 +1,16 @@ -#ifndef STREAMR_JSON_TOJSON_HPP -#define STREAMR_JSON_TOJSON_HPP +// Module streamr.json.toJson +// CONSOLIDATED from the former header +// streamr-json/toJson.hpp (MODERNIZATION.md Phase 2.6): +// this file is now the source of truth. +module; +#include #include +#include +#include #include #include +#include #include #include #include @@ -11,8 +18,11 @@ #include #include -#include "streamr-json/jsonConcepts.hpp" -namespace streamr::json { +export module streamr.json.toJson; + +import streamr.json.jsonConcepts; + +export namespace streamr::json { using suppresslint::SuppressLint; // otherwise linter thinks jsonConcepts.hpp // is unused using json = nlohmann::json; @@ -253,6 +263,4 @@ json toJson(const T& value) { using StreamrJsonInitializerList = std::initializer_list; -} // namespace streamr::json - -#endif +} // namespace streamr::json \ No newline at end of file diff --git a/packages/streamr-json/include/streamr-json/toString.hpp b/packages/streamr-json/modules/toString.cppm similarity index 69% rename from packages/streamr-json/include/streamr-json/toString.hpp rename to packages/streamr-json/modules/toString.cppm index a195d918..53e35068 100644 --- a/packages/streamr-json/include/streamr-json/toString.hpp +++ b/packages/streamr-json/modules/toString.cppm @@ -1,14 +1,22 @@ -#ifndef STREAMR_JSON_TOSTRING_HPP -#define STREAMR_JSON_TOSTRING_HPP +// Module streamr.json.toString +// CONSOLIDATED from the former header +// streamr-json/toString.hpp (MODERNIZATION.md Phase 2.6): +// this file is now the source of truth. +module; + +#include +#include + +export module streamr.json.toString; + +import streamr.json.jsonConcepts; +import streamr.json.toJson; /** * Convert (almost) any struct to string in C++20. **/ -#include "streamr-json/jsonConcepts.hpp" -#include "streamr-json/toJson.hpp" - -namespace streamr::json { +export namespace streamr::json { using suppresslint::SuppressLint; // otherwise linter thinks jsonConcepts.hpp // is unused @@ -42,6 +50,4 @@ std::string toString(const T& value) { return value.toString(); } -} // namespace streamr::json - -#endif +} // namespace streamr::json \ No newline at end of file diff --git a/packages/streamr-json/src/examples/JsonExample.cpp b/packages/streamr-json/src/examples/JsonExample.cpp index 5f247e46..713144e5 100644 --- a/packages/streamr-json/src/examples/JsonExample.cpp +++ b/packages/streamr-json/src/examples/JsonExample.cpp @@ -4,7 +4,8 @@ #include #include -import streamr.json; +import streamr.json.toJson; +import streamr.json.toString; using streamr::json::StreamrJsonInitializerList; using streamr::json::toJson; diff --git a/packages/streamr-json/test/unit/TestJsonConcepts.cpp b/packages/streamr-json/test/unit/TestJsonConcepts.cpp index d7abc40a..cdcf70b0 100644 --- a/packages/streamr-json/test/unit/TestJsonConcepts.cpp +++ b/packages/streamr-json/test/unit/TestJsonConcepts.cpp @@ -1,6 +1,6 @@ #include -import streamr.json; +import streamr.json.toJson; using streamr::json::toJson; // NOLINT diff --git a/packages/streamr-json/test/unit/toJsonTest.cpp b/packages/streamr-json/test/unit/toJsonTest.cpp index f8e49bf0..945a0c1f 100644 --- a/packages/streamr-json/test/unit/toJsonTest.cpp +++ b/packages/streamr-json/test/unit/toJsonTest.cpp @@ -10,7 +10,7 @@ #include "TestClass.hpp" #include "WeatherData.hpp" -import streamr.json; +import streamr.json.toJson; using streamr::json::toJson; diff --git a/packages/streamr-json/test/unit/toStringTest.cpp b/packages/streamr-json/test/unit/toStringTest.cpp index 94756839..fd2e83a1 100644 --- a/packages/streamr-json/test/unit/toStringTest.cpp +++ b/packages/streamr-json/test/unit/toStringTest.cpp @@ -10,7 +10,7 @@ #include "TestClass.hpp" #include "WeatherData.hpp" -import streamr.json; +import streamr.json.toString; using streamr::json::toString; diff --git a/packages/streamr-logger/modules/Logger.cppm b/packages/streamr-logger/modules/Logger.cppm index b31eae33..ee6ae622 100644 --- a/packages/streamr-logger/modules/Logger.cppm +++ b/packages/streamr-logger/modules/Logger.cppm @@ -10,10 +10,10 @@ module; #include #include #include -#include "streamr-json/toJson.hpp" export module streamr.logger.Logger; +import streamr.json.toJson; import streamr.logger.FollyLoggerImpl; import streamr.logger.LoggerImpl; import streamr.logger.StreamrLogLevel; diff --git a/packages/streamr-logger/modules/SLogger.cppm b/packages/streamr-logger/modules/SLogger.cppm index 33b92e90..67a0d192 100644 --- a/packages/streamr-logger/modules/SLogger.cppm +++ b/packages/streamr-logger/modules/SLogger.cppm @@ -8,10 +8,10 @@ module; #include #include #include -#include "streamr-json/toJson.hpp" export module streamr.logger.SLogger; +import streamr.json.toJson; import streamr.logger.Logger; export namespace streamr::logger {