Skip to content
Merged
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
32 changes: 12 additions & 20 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,28 +148,20 @@ jobs:
# Inner directory name embeds the platform so extractions of
# multiple platforms into the same parent dir do not collide.
stage="pbr-memory-pool-${version}-${platform}"
mkdir -p "${stage}/include/it/d4np/memorypool" "${stage}/lib"

# Public headers.
cp src/main/cpp/it/d4np/memorypool/memory_pool.h "${stage}/include/it/d4np/memorypool/"
cp src/main/cpp/it/d4np/memorypool/memory_pool.hpp "${stage}/include/it/d4np/memorypool/"
cp src/main/cpp/it/d4np/memorypool/version.hpp "${stage}/include/it/d4np/memorypool/"
# Use the CMake install rules (ADR-0028) so the tarball is a
# complete, find_package-ready tree rather than a hand-copied subset:
# the FULL public-header set (every *.h / *.hpp, not just the three
# core ones), the static archive under whatever name the toolchain
# produced, the CMake package config (pbr_memory_poolConfig.cmake +
# the pbr::memory_pool targets export + the version file), and the
# pkg-config .pc. This is the "installing the artifacts from a GitHub
# Release" path promised by ADR-0004 §5. The exported imported target
# is pbr::memory_pool — identical to the in-build alias (ADR-0028).
cmake --install build/release-artifact --prefix "${PWD}/${stage}"

# Static archive — file name differs by toolchain
# (libpbr_memory_pool.a on GCC/Clang/Apple Clang,
# pbr_memory_pool.lib on MSVC). M1 ships STATIC only; shared
# libraries arrive in a later milestone, see ADR-0004 §4 item 2.
if [[ -f build/release-artifact/libpbr_memory_pool.a ]]; then
cp build/release-artifact/libpbr_memory_pool.a "${stage}/lib/"
elif [[ -f build/release-artifact/pbr_memory_pool.lib ]]; then
cp build/release-artifact/pbr_memory_pool.lib "${stage}/lib/"
else
echo "::error::Could not find the built static library under build/release-artifact/"
ls -la build/release-artifact/
exit 1
fi

# Top-level project docs that travel with every distribution.
# Top-level project docs that travel with every distribution (the
# install also places LICENSE under share/doc/pbr_memory_pool/).
cp LICENSE "${stage}/"
cp README.md "${stage}/"
cp CHANGELOG.md "${stage}/"
Expand Down
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,35 @@ Full release notes will live in `docs/releases/v1.0.0.md` (M7.7).
new **Compatibility** section (Tier-1/Tier-2 platforms, compiler floor versions, C++17 /
C89+C99 standards, thread-safety modes, zero external dependencies — [ADR-0005](docs/adr/0005-toolchain-matrix-and-supported-platforms.md)).

### Added (M7.4)

- **CMake install / export + pkg-config — Phase 1 distribution** ([ADR-0028](docs/adr/0028-install-and-packaging-layout.md),
ROADMAP §7.4, ADR-0004 §5). A `PBR_MEMORY_POOL_INSTALL` option (default
`PROJECT_IS_TOP_LEVEL`) gates `install(TARGETS … EXPORT)` + `install(EXPORT …
NAMESPACE pbr::)`, the full `it/d4np/memorypool/` public-header tree, a
relocatable package config (`configure_package_config_file` +
`SameMajorVersion` version file), a pkg-config
[`pbr-memory-pool.pc`](cmake/pbr-memory-pool.pc.in), and `LICENSE` under
`share/doc/`. Consumers use
`find_package(pbr_memory_pool CONFIG REQUIRED)` +
`target_link_libraries(app pbr::memory_pool)`.
- The internal target carries `EXPORT_NAME memory_pool` so the **installed**
imported target is `pbr::memory_pool` — identical to the in-build alias, so a
single link line serves `add_subdirectory` / `FetchContent` and installed
packages alike. Verified end-to-end locally (MSVC 19.51 + Ninja): install to a
prefix, then a separate `find_package` consumer built, linked, and ran.
- README gains an **Install and consume** section.

### Changed (M7.4)

- **`release.yml` packages via `cmake --install`** instead of hand-copying.
This fixes a latent bug: the previous tarball shipped only three of the seven
public headers (`typed_pool.hpp`, `pool_allocator.hpp`, `instrumented_pool.hpp`,
`free_list_iterator.hpp` were missing) and no CMake config / `.pc`, so the
ADR-0004 §5 "install the artifacts from a Release" path was not actually
deliverable. Release tarballs are now complete `find_package`-ready install
trees.

## [0.6.0] — 2026-06-14

**Milestone 6 — Observability & Decorators.** Optional logging / statistics / tracing
Expand Down
76 changes: 75 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,14 @@ target_compile_features(pbr_memory_pool PUBLIC cxx_std_17)

set_target_properties(pbr_memory_pool PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
SOVERSION ${PROJECT_VERSION_MAJOR}
# Export under the short name so the installed imported target is
# `pbr::memory_pool` — identical to the in-build ALIAS above, so consumers
# write the same `target_link_libraries(... pbr::memory_pool)` whether they
# vendor via add_subdirectory / FetchContent or link an installed package
# (ADR-0028). Without this, NAMESPACE pbr:: + target `pbr_memory_pool` would
# export the mismatched `pbr::pbr_memory_pool`.
EXPORT_NAME memory_pool)

# ---------------------------------------------------------------------------
# Free-list diagnostics gate (ADR-0019). The diagnostic surface (the
Expand Down Expand Up @@ -143,6 +150,72 @@ elseif(NOT PBR_MEMORY_POOL_THREAD_SAFETY STREQUAL "NONE")
endif()
# NONE leaves the macro at the memory_pool.h default — no compile definition.

# ---------------------------------------------------------------------------
# Install / packaging — Phase 1 distribution (ADR-0028, ROADMAP §7.4 /
# ADR-0004 §5). Exports a namespaced imported target so consumers can
# `find_package(pbr_memory_pool CONFIG REQUIRED)` + link `pbr::memory_pool`,
# installs the public-header tree, and emits a pkg-config `.pc`. Gated so a
# parent project that pulls this in via add_subdirectory / FetchContent does
# not leak our install rules into its own `cmake --install`.
# ---------------------------------------------------------------------------
option(PBR_MEMORY_POOL_INSTALL
"Generate install and packaging rules (config file, headers, pkg-config)"
${PROJECT_IS_TOP_LEVEL})
if(PBR_MEMORY_POOL_INSTALL)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

set(PBR_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/pbr_memory_pool"
CACHE STRING "Install location for the CMake package config files")

# The library archive + the install-tree include directory.
install(TARGETS pbr_memory_pool
EXPORT pbr_memory_poolTargets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")

# Public headers, preserving the it/d4np/memorypool/ tree so the
# `#include <it/d4np/memorypool/...>` form resolves against <prefix>/include.
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/it"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING
PATTERN "*.h"
PATTERN "*.hpp")

# The exported targets file — defines the imported pbr::memory_pool target.
install(EXPORT pbr_memory_poolTargets
FILE pbr_memory_poolTargets.cmake
NAMESPACE pbr::
DESTINATION "${PBR_INSTALL_CMAKEDIR}")

# The package config + version files.
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/pbr_memory_poolConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/pbr_memory_poolConfig.cmake"
INSTALL_DESTINATION "${PBR_INSTALL_CMAKEDIR}")
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/pbr_memory_poolConfigVersion.cmake"
VERSION "${PROJECT_VERSION}"
COMPATIBILITY SameMajorVersion)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/pbr_memory_poolConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/pbr_memory_poolConfigVersion.cmake"
DESTINATION "${PBR_INSTALL_CMAKEDIR}")

# pkg-config for non-CMake (autotools / Make / Meson) consumers.
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/pbr-memory-pool.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/pbr-memory-pool.pc"
@ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pbr-memory-pool.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")

install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
DESTINATION "${CMAKE_INSTALL_DOCDIR}")
endif()

# ---------------------------------------------------------------------------
# Optional sub-trees, wired in by later milestones.
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -197,4 +270,5 @@ message(STATUS " C++ standard : C++${CMAKE_CXX_STANDARD} (extensions ${C
message(STATUS " Build type : ${CMAKE_BUILD_TYPE}${CMAKE_CONFIGURATION_TYPES}")
message(STATUS " Tests : ${PBR_MEMORY_POOL_BUILD_TESTS}")
message(STATUS " Benchmarks : ${PBR_MEMORY_POOL_BUILD_BENCHMARKS}")
message(STATUS " Install rules : ${PBR_MEMORY_POOL_INSTALL}")
message(STATUS "")
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,32 @@ Both invocations are exercised end-to-end on every push to `master` by the [CI m

For first-time setup on a fresh clone — installing CMake, Ninja, and the supported compilers per platform, plus troubleshooting and the full quality-bar workflow — see the **[Local Build Guide](docs/development/local-build.md)**.

## Install and consume

Install to a prefix and consume with CMake's `find_package` ([ADR-0028](docs/adr/0028-install-and-packaging-layout.md) — Phase 1 distribution):

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DPBR_MEMORY_POOL_BUILD_TESTS=OFF
cmake --build build
cmake --install build --prefix /your/prefix
```

```cmake
# In the consumer's CMakeLists.txt — the imported target name is identical
# whether you install the package or vendor it via add_subdirectory / FetchContent.
find_package(pbr_memory_pool CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE pbr::memory_pool)
```

The install tree carries every public header (`include/it/d4np/memorypool/`), the static archive, the CMake package config (`SameMajorVersion` compatibility), and a pkg-config `pbr-memory-pool.pc` for non-CMake (Make / autotools / Meson) builds. The same `cmake --install` tree is what each GitHub Release tarball contains. Vendoring without installing also works:

```cmake
add_subdirectory(path/to/pbr-cpp-memory-pool) # or FetchContent
target_link_libraries(my_app PRIVATE pbr::memory_pool)
```

Package-manager distribution (vcpkg / Conan) is Phase 2, deferred post-`v1.0.0` (ROADMAP §7.8–§7.9).

## Repository layout

| Path | What lives there |
Expand Down
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Goal: ship a v1.0.0 reference implementation.
- [x] 7.1 Doxygen-generated API documentation published as a static site. Implemented per [ADR-0027](docs/adr/0027-doxygen-html-site-and-publication-pipeline.md), closing the rendering half that [ADR-0013](docs/adr/0013-doxygen-for-api-markdown-for-narrative.md) §4–§5 deferred to this item. A checked-in **partial** Doxyfile ([`docs/doxygen/Doxyfile`](docs/doxygen/Doxyfile)) plus a hand-written landing page ([`docs/doxygen/mainpage.md`](docs/doxygen/mainpage.md)) drive a **dependency-free** Doxygen HTML build — built-in theme with `GENERATE_TREEVIEW`, no Graphviz (`HAVE_DOT = NO`), no vendored CSS, no Python doc stack (the MkDocs/Sphinx-Breathe unified narrative site sketched in ADR-0013 §4 is explicitly **deferred post-v1.0**, consistent with spec §3.3). `INPUT` is the public-header contract surface only (`*.h` + `*.hpp` under `src/main/cpp/it/d4np/memorypool/`, `EXTRACT_PRIVATE = NO`), with `PBR_MEMORY_POOL_DIAGNOSTICS=1` predefined so the ADR-0019 free-list iterator surface renders. **The warn-as-error gate refines ADR-0013 §5**: `WARN_AS_ERROR = FAIL_ON_WARNINGS` + `WARN_IF_DOC_ERROR = YES` fail CI on the *doc-rot* class (malformed commands, unresolved cross-references, stale `@param` names) while `WARN_IF_UNDOCUMENTED` / `WARN_NO_PARAMDOC` stay **off** — gating documentation *correctness*, not ceremonial *exhaustiveness* on every operator and trait typedef (ADR-0027 §3). `PROJECT_NUMBER` is left blank and **injected at build time from `version.hpp`** so the version string stays single-sourced. A new workflow ([`.github/workflows/docs-site.yml`](.github/workflows/docs-site.yml)) builds the site as a **warn-as-error gate on every PR** (no deploy — PRs are never blocked by Pages configuration) and **publishes to GitHub Pages on push to `master`** via the official `upload-pages-artifact` / `deploy-pages` Actions (no generated HTML committed; `build/` is git-ignored). Three public-header comments gain the Doxygen `%` auto-link escape (`::%operator new` / `::%operator delete`) to silence spurious unresolved-link warnings on the global operators. Verified locally with Doxygen 1.10.0: zero warnings, `build/doxygen/html/index.html` generated. **One-time maintainer action:** enable GitHub Pages with *Source: GitHub Actions* in repository settings before the first `master` deploy (the PR gate works regardless).
- [x] 7.2 README: full usage example, performance summary, compatibility matrix. The README gains a **Usage** section with six compilable examples spanning the whole surface — the C four-function core, the RAII `Pool` (ctor / `make` / `PoolBuilder`, dual-verb `allocate` vs `try_allocate`), `TypedPool<T>` (`construct` / `destroy`), `PoolAllocator<T>` driving a `std::list`, dynamic growth via `Pool::make_dynamic`, and `InstrumentedPool` + a `PoolObserver` — each transcribed from a single program **compiled, linked, and run against the real headers + `memory_pool.cpp` under MSVC 19.51 `/W4`** before commit (so no signature drift). The **Performance** section is consolidated into a one-paragraph summary plus three labelled regimes — fixed single-threaded (4–11×, M2.9), dynamic growth (~2×, M5.4), and threading (M4.5) — each linking its full `docs/bench/` report, with the host disclosed once up front. A new **Compatibility** section captures the [ADR-0005](docs/adr/0005-toolchain-matrix-and-supported-platforms.md) contract: Tier-1 platforms × compiler floor versions, Tier-2 best-effort targets, the C++17 / C89+C99 language-standard matrix, the `NONE`/`MUTEX`/`LOCKFREE` thread-safety knob, and the zero-external-dependency guarantee. Documentation-only — no code, ADR, or spec change.
- [x] 7.3 `CHANGELOG.md` audit for the v1.0.0 entry: consolidate every Unreleased line accumulated since `v0.6.0`, verify category placement, and write the v1.0.0 summary headline (the file itself was introduced in Milestone 1.12). The `[Unreleased]` block accumulated since `v0.6.0` (the M7.1 `Added` + `Changed`, the M7.2 `Changed`) is audited for Keep-a-Changelog category placement — the published Doxygen site and the `docs-site` workflow stay under *Added* (new capabilities), the header `%`-escapes and the README expansion under *Changed* (modifications to existing surfaces) — and a **draft `v1.0.0` summary headline** is written: it frames `v1.0.0` as the first **stable** release that freezes the public C ABI + C++ surface under the SemVer 1.0 promise, seals the M0–M6 feature set, and folds in the M7 release polish (M7.1 docs site, M7.2 README, M7.4 packaging, M7.5/M7.6 audits), with the row-by-row Spec Coverage Map acceptance deferred to M7.6. Per the established convention the per-task `### Added (MX.Y)` / `### Changed (MX.Y)` subsections are retained (not flattened — `[0.6.0]` keeps three `### Added (M6.x)`); the block stays under `## [Unreleased]` and is dated to `## [1.0.0] — <date>` by the release PR (M7.7). Documentation-only — no code, ADR, or spec change; the bottom-of-file link references are untouched until M7.7 adds the `[1.0.0]` anchor.
- [ ] 7.4 ADR: install / packaging layout (public-header export, pkg-config, CMake `find_package` config file) — phase 1 distribution per ADR-0004 §5.
- [x] 7.4 ADR: install / packaging layout (public-header export, pkg-config, CMake `find_package` config file) — phase 1 distribution per ADR-0004 §5. Implemented as [ADR-0028](docs/adr/0028-install-and-packaging-layout.md) plus the CMake install/export machinery: a `PBR_MEMORY_POOL_INSTALL` option (default `PROJECT_IS_TOP_LEVEL`, so an embedding parent's `cmake --install` is not polluted) gates `install(TARGETS … EXPORT)` + `install(EXPORT … NAMESPACE pbr::)`, the full `it/d4np/memorypool/` public-header tree, a relocatable package config via `configure_package_config_file` with a `SameMajorVersion` version file, a pkg-config [`pbr-memory-pool.pc`](cmake/pbr-memory-pool.pc.in), and `LICENSE` under `share/doc/`. The internal target `pbr_memory_pool` carries `EXPORT_NAME memory_pool` so the **installed** imported target is `pbr::memory_pool` — identical to the in-build alias, so `target_link_libraries(app pbr::memory_pool)` is the one link line for `add_subdirectory` / `FetchContent` **and** installed-package consumers. [`release.yml`](.github/workflows/release.yml)'s `build-artifacts` job now packages via `cmake --install` (full headers + archive + config + `.pc`) instead of hand-copying — fixing a latent bug where four of the seven public headers and the package config were missing from release tarballs (the ADR-0004 §5 "install the artifacts from a Release" path). Verified end-to-end locally (MSVC 19.51 + Ninja): configure → build → `cmake --install` to a staging prefix, then a separate consumer project did `find_package(pbr_memory_pool CONFIG REQUIRED)` + linked `pbr::memory_pool` and ran (`consumer OK: got=7 block_size=64`); the exported target resolves to `pbr::memory_pool` and the `.pc` carries the correct prefix/libdir/version. Phase 2 (vcpkg / Conan) stays deferred post-v1.0 (items 7.8 / 7.9). pkg-config `.pc` `prefix=` reflects the configure-time prefix (documented limitation, ADR-0028 §6).
- [ ] 7.5 Patterns catalogue audit — verify every adopted pattern has both an ADR and a code location; refresh statuses.
- [ ] 7.6 **Spec compliance acceptance** — walk every row of the Spec Coverage Map (below) and confirm each requirement is satisfied by a passing test, a documented ADR, or both. Record the audit outcome in an ADR.
- [ ] 7.7 **Close Milestone 7 → `v1.0.0`**: bump `version.hpp`, roll `CHANGELOG.md`, draft `docs/releases/v1.0.0.md`, open the release PR for the maintainer to tag and publish (ADR-0004 §2).
Expand Down
11 changes: 11 additions & 0 deletions cmake/pbr-memory-pool.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: pbr-cpp-memory-pool
Description: Purpose-built reference high-performance fixed-block O(1) memory pool (C++17 / ANSI C)
URL: https://github.com/danielPoloWork/pbr-cpp-memory-pool
Version: @PROJECT_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lpbr_memory_pool
18 changes: 18 additions & 0 deletions cmake/pbr_memory_poolConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@PACKAGE_INIT@

# CMake package config for pbr-cpp-memory-pool (ADR-0028, ROADMAP §7.4).
#
# Consumers use the library with:
#
# find_package(pbr_memory_pool CONFIG REQUIRED)
# target_link_libraries(my_app PRIVATE pbr::memory_pool)
#
# The imported target pbr::memory_pool carries its public include directory and
# its C++17 requirement, so no manual include/flag wiring is needed. The default
# (NONE / single-threaded) build has no external link dependency; a library
# built with the LOCKFREE thread-safety policy on GCC/Clang may export a plain
# `atomic` link requirement (libatomic), which the consumer's linker resolves.

include("${CMAKE_CURRENT_LIST_DIR}/pbr_memory_poolTargets.cmake")

check_required_components(pbr_memory_pool)
Loading
Loading