Skip to content

Add separation design doc and reorganize doc navigation#161

Merged
vinniefalco merged 5 commits intocppalliance:developfrom
vinniefalco:develop
Feb 14, 2026
Merged

Add separation design doc and reorganize doc navigation#161
vinniefalco merged 5 commits intocppalliance:developfrom
vinniefalco:develop

Conversation

@vinniefalco
Copy link
Member

@vinniefalco vinniefalco commented Feb 13, 2026

Summary by CodeRabbit

  • New Features

    • Adds mimalloc as an allocation option and includes it in allocator benchmarks.
    • Benchmarks now run three allocators (recycling, mimalloc, standard) with expanded timing and relative performance metrics.
  • Chores

    • Adds CI helper scripts for Windows and shell environments and streamlines CI generation/configuration.

@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds mimalloc v2.2.7 to the allocation example build, links mimalloc-static, and extends the allocation benchmark to include a mimalloc-backed std::pmr::memory_resource with timing and comparative delta output.

Changes

Cohort / File(s) Summary
Build Configuration
example/allocation/CMakeLists.txt, example/allocation/Jamfile
Fetches mimalloc via CMake FetchContent (v2.2.7), disables mimalloc tests, makes it available, and links mimalloc-static; Jamfile documents/install guidance and adds -lmimalloc linker flag.
Allocator Benchmark
example/allocation/allocation.cpp
Adds mi_memory_resource (std::pmr wrapper using mi_malloc_aligned/mi_free_aligned), wires it into the mimalloc benchmark path, expands benchmark from two to three allocator runs, and adds timing/delta calculations and output formatting.
CI / Drone scripts
.drone.star, .drone/drone.bat, .drone/drone.sh
Updates CI matrix and language/compiler requirements (c++20, newer GCC/Clang versions), and adds new Drone scripts (drone.bat, drone.sh) that orchestrate Boost/CI installs, multiple build modes, and cmake-based build flows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • stuff #156 — Modifies the same example/allocation files and introduced the original allocation example and build entries that this change extends.

Poem

🐰
I hopped through headers, tiny and fleet,
Found mimalloc crumbs — a tasty treat.
Three allocators dance in a row,
Timings tumble, numbers glow,
My fluffy heart beats quick and sweet. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title claims to add a separation design doc and reorganize doc navigation, but the changeset includes mimalloc allocation integration, compiler version updates, and CI configuration scripts—none of which relate to documentation. Revise the PR title to accurately reflect the actual changes, such as 'Integrate mimalloc allocator support and update CI configuration' or split into multiple PRs aligned with their respective focuses.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into develop

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cppalliance-bot
Copy link

cppalliance-bot commented Feb 13, 2026

An automated preview of the documentation is available at https://161.capy.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-02-14 02:10:41 UTC

@cppalliance-bot
Copy link

cppalliance-bot commented Feb 13, 2026

GCOVR code coverage report https://161.capy.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://161.capy.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://161.capy.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-02-13 23:19:20 UTC

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@include/boost/capy/ex/channel.hpp`:
- Line 83: The doc comment for template parameter T is incorrect: the
implementation currently requires T to be default-constructible and
move-assignable (uses std::make_unique<T[]> to value-initialize storage and
assigns with buf_[idx] = std::move(v)), not just move-constructible. Fix by
either updating the `@tparam` to list default-constructible and move-assignable,
or (preferred) change the ring buffer implementation in channel.hpp
(functions/methods buf_push, buf_pop and the allocation that uses
std::make_unique<T[]>) to use raw aligned storage + placement-new and explicit
destructor calls so elements are constructed only on push and destroyed on pop,
and change error-return paths to return std::optional<T> (or another sentinel)
instead of returning T{}.
- Around line 246-257: The move constructor read_awaiter(read_awaiter&&)
currently transfers has_value_ but does not move the actual stored value in
value_buf_, leading to garbage in the destination when has_value_ is true;
update the move ctor in class read_awaiter to, after transferring flags, check
the source's has_value_ and if true move-construct (or memcpy for trivially
copyable types) the value from o.value_buf_ into this->value_buf_ (using
placement new or std::launder as appropriate), then destroy or mark the source
value as moved (set o.has_value_ = false) to maintain invariants; reference
symbols: read_awaiter(read_awaiter&&), value_buf_, has_value_, and ensure
noexcept/active_/in_list_ logic remains unchanged.
- Around line 568-571: Destructor ~channel() currently calls close(), which
posts coroutine handles that will resume and dereference ch_ leading to
use-after-free if the channel is destroyed; replace that behavior by asserting
no suspended coroutines remain: in ~channel() remove the call to close() and
instead add BOOST_CAPY_ASSERT(readers_.empty() && writers_.empty()) (or
equivalent) to catch misuse early, referencing the close(), ~channel(),
readers_, writers_, ch_, and await_resume() symbols when locating the change.
🧹 Nitpick comments (1)
include/boost/capy/ex/channel.hpp (1)

73-132: Async/awaitable javadoc for read() and write() is incomplete per coding guidelines.

The guidelines require completion conditions (@li list), cancellation documentation, @throws, @par Example per function, @see, concurrency/overlap notes, and error condition details. The current docs cover the basics but omit most of these elements.

Not blocking, but worth filling in over time—especially the cancellation behavior (stop_token support, resulting error::canceled) which is required per the project's doc-awaitable rule.

Also applies to: 591-626

a write suspends until a reader arrives (and vice versa), and
the value is transferred directly.

@tparam T The value type. Must be move-constructible.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

T requirements are broader than documented.

The @tparam says "Must be move-constructible", but the actual code imposes additional requirements:

  • Default-constructible: std::make_unique<T[]>(limit) (line 587) value-initializes every element, and T{} is used in error-return paths (lines 309, 367).
  • Move-assignable: buf_push (line 155) uses buf_[idx] = std::move(v).

Either tighten the documentation to reflect the true constraints, or (preferably) relax the implementation so only move-constructibility is required—e.g., back the ring buffer with raw aligned storage + placement-new/manual destruction, and return std::optional<T> or a sentinel on error paths instead of T{}.

Sketch: aligned-storage ring buffer (eliminates default-constructible + move-assignable requirements)
- std::unique_ptr<T[]> buf_;
+ std::unique_ptr<unsigned char[]> buf_storage_;
+ // Access element i:  *std::launder(reinterpret_cast<T*>(buf_storage_.get() + i * sizeof(T)))

  // Constructor
  explicit channel(std::size_t limit = 0)
      : limit_(limit)
-     , buf_(limit > 0
-         ? std::make_unique<T[]>(limit) : nullptr)
+     , buf_storage_(limit > 0
+         ? std::make_unique<unsigned char[]>(limit * sizeof(T)) : nullptr)
  {
  }

For buf_push / buf_pop, use placement-new and explicit destructor calls instead of move-assignment.

Also applies to: 145-145, 308-309, 367-367, 584-588

🤖 Prompt for AI Agents
In `@include/boost/capy/ex/channel.hpp` at line 83, The doc comment for template
parameter T is incorrect: the implementation currently requires T to be
default-constructible and move-assignable (uses std::make_unique<T[]> to
value-initialize storage and assigns with buf_[idx] = std::move(v)), not just
move-constructible. Fix by either updating the `@tparam` to list
default-constructible and move-assignable, or (preferred) change the ring buffer
implementation in channel.hpp (functions/methods buf_push, buf_pop and the
allocation that uses std::make_unique<T[]>) to use raw aligned storage +
placement-new and explicit destructor calls so elements are constructed only on
push and destroyed on pop, and change error-return paths to return
std::optional<T> (or another sentinel) instead of returning T{}.

Comment on lines 246 to 257
read_awaiter(read_awaiter&& o) noexcept
: ch_(o.ch_)
, h_(o.h_)
, ex_(o.ex_)
, claimed_(o.claimed_.load(
std::memory_order_relaxed))
, canceled_(o.canceled_)
, active_(std::exchange(o.active_, false))
, in_list_(std::exchange(o.in_list_, false))
, has_value_(std::exchange(o.has_value_, false))
{
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Latent bug: move constructor doesn't relocate value_buf_ contents.

has_value_ is transferred via std::exchange, but the actual value in value_buf_ is never moved to the new object. If the move constructor ever runs after has_value_ is set to true, the new awaiter would hold garbage in its value_buf_.

Currently this is safe because the compiler-generated move happens before await_suspend (and has_value_ is only set during suspension). Still, it is fragile—a future refactor or a different coroutine transform could break the invariant silently.

Defensive fix
  read_awaiter(read_awaiter&& o) noexcept
      : ch_(o.ch_)
      , h_(o.h_)
      , ex_(o.ex_)
      , claimed_(o.claimed_.load(
          std::memory_order_relaxed))
      , canceled_(o.canceled_)
      , active_(std::exchange(o.active_, false))
      , in_list_(std::exchange(o.in_list_, false))
      , has_value_(std::exchange(o.has_value_, false))
  {
+     if(has_value_)
+         ::new(value_buf_) T(std::move(o.value_ref_()));
  }
🤖 Prompt for AI Agents
In `@include/boost/capy/ex/channel.hpp` around lines 246 - 257, The move
constructor read_awaiter(read_awaiter&&) currently transfers has_value_ but does
not move the actual stored value in value_buf_, leading to garbage in the
destination when has_value_ is true; update the move ctor in class read_awaiter
to, after transferring flags, check the source's has_value_ and if true
move-construct (or memcpy for trivially copyable types) the value from
o.value_buf_ into this->value_buf_ (using placement new or std::launder as
appropriate), then destroy or mark the source value as moved (set o.has_value_ =
false) to maintain invariants; reference symbols: read_awaiter(read_awaiter&&),
value_buf_, has_value_, and ensure noexcept/active_/in_list_ logic remains
unchanged.

Comment on lines 568 to 571
~channel()
{
close();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Destructor + close() can post handles that outlive the channel.

close() posts suspended coroutine handles back to the executor. Those coroutines will call await_resume(), which dereferences ch_. If the channel is destroyed immediately after close() returns (which it is here—this is the destructor), every posted resumption is a use-after-free.

This is safe only if the caller guarantees all coroutines have already completed or been canceled before the channel is destroyed. Consider adding an assertion (BOOST_CAPY_ASSERT(readers_.empty() && writers_.empty())) in the destructor instead of calling close(), to catch misuse early.

Suggested safer destructor
  ~channel()
  {
-     close();
+     // All awaiters must have completed before the
+     // channel is destroyed.
+     BOOST_CAPY_ASSERT(readers_.empty());
+     BOOST_CAPY_ASSERT(writers_.empty());
+     closed_ = true;
  }
🤖 Prompt for AI Agents
In `@include/boost/capy/ex/channel.hpp` around lines 568 - 571, Destructor
~channel() currently calls close(), which posts coroutine handles that will
resume and dereference ch_ leading to use-after-free if the channel is
destroyed; replace that behavior by asserting no suspended coroutines remain: in
~channel() remove the call to close() and instead add
BOOST_CAPY_ASSERT(readers_.empty() && writers_.empty()) (or equivalent) to catch
misuse early, referencing the close(), ~channel(), readers_, writers_, ch_, and
await_resume() symbols when locating the change.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@example/allocation/allocation.cpp`:
- Around line 160-178: The printed percent values pct_rc_std, pct_mi_std and
pct_rc_mi currently always have a hardcoded '+' prefix which yields awkward
"+-X.X%" for negative values; update the print formatting in the output block
that prints "Recycling allocator", "mimalloc" and "std::allocator" to either
enable std::showpos on the stream before printing those percent values (so
positives show '+', negatives show '-' correctly) or remove the hardcoded '+'
and prepend a '+' only when the computed value is >= 0 (i.e., conditionally
format the sign for pct_rc_std, pct_rc_mi and pct_mi_std). Ensure you restore
the stream flags if you use std::showpos so other numeric output is unaffected.
🧹 Nitpick comments (4)
example/allocation/Jamfile (1)

20-22: Hardcoded -lmimalloc is not portable to MSVC.

<linkflags>-lmimalloc is GCC/Clang-specific. On MSVC this flag will be silently ignored or cause an error. Consider using a conditional or a Boost.Build lib rule:

Suggested approach
+lib mimalloc : : <name>mimalloc ;
+
 exe allocation :
     [ glob *.cpp ]
     :
-    <linkflags>-lmimalloc
+    <library>mimalloc
     ;

Alternatively, wrap the flag in a toolset condition:

-    <linkflags>-lmimalloc
+    <toolset>gcc:<linkflags>-lmimalloc
+    <toolset>clang:<linkflags>-lmimalloc
+    <toolset>msvc:<linkflags>mimalloc.lib
example/allocation/CMakeLists.txt (1)

10-15: Consider disabling unneeded mimalloc build targets.

FetchContent will build all of mimalloc's default targets (shared lib, tests, etc.). Since only mimalloc-static is needed, you can reduce build time by disabling extras:

Suggested addition
 FetchContent_Declare(mimalloc
     GIT_REPOSITORY https://github.com/microsoft/mimalloc
     GIT_TAG v2.2.7
     GIT_SHALLOW TRUE)
+set(MI_BUILD_SHARED OFF CACHE BOOL "" FORCE)
+set(MI_BUILD_TESTS OFF CACHE BOOL "" FORCE)
 FetchContent_MakeAvailable(mimalloc)
example/allocation/allocation.cpp (2)

42-73: The mi_memory_resource class lacks a docstring.

Per the coding guidelines, classes should have documentation. A brief comment exists on line 42, but a Doxygen-style block would be more appropriate. This is an example file so it's less critical, but a brief /** */ block describing purpose and noting that it's non-thread-safe (or thread-safe, per mimalloc's guarantees) would be helpful.


127-139: Minor: mi_mr construction is included in untimed region but counter.store(0) placement is inconsistent.

In the recycling and std::allocator benchmarks, counter.store(0) is immediately followed by the timestamp capture. Here, mi_memory_resource mi_mr is constructed between the counter reset (line 128) and the timestamp (line 130). While mi_mr construction is trivially cheap, moving it before the counter reset (or outside the timed block entirely) would keep the pattern consistent.

Suggested reorder
+    mi_memory_resource mi_mr;
+
     // With mimalloc
     counter.store(0);
-    mi_memory_resource mi_mr;
     auto t2 = std::chrono::steady_clock::now();

Comment on lines +160 to 178
auto pct_rc_std = std::round(
(ms_standard / ms_recycling - 1.0) * 1000.0) / 10.0;
auto pct_mi_std = std::round(
(ms_standard / ms_mimalloc - 1.0) * 1000.0) / 10.0;
auto pct_rc_mi = std::round(
(ms_mimalloc / ms_recycling - 1.0) * 1000.0) / 10.0;

std::cout
<< iterations << " iterations, "
<< "4-deep coroutine chain\n\n"
<< std::fixed << std::setprecision(1)
<< " Recycling allocator: "
<< ms_recycling << " ms\n"
<< ms_recycling << " ms (+"
<< pct_rc_std << "% vs std, +"
<< pct_rc_mi << "% vs mimalloc)\n"
<< " mimalloc: "
<< ms_mimalloc << " ms (+"
<< pct_mi_std << "% vs std)\n"
<< " std::allocator: "
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hardcoded + prefix will produce +-X.X% when a ratio is negative.

If one allocator is unexpectedly faster than another (e.g., mimalloc faster than recycling), the computed percentage goes negative, and the output becomes +-3.5% vs mimalloc. Either drop the hardcoded + and use std::showpos, or conditionally format:

Suggested fix using showpos
     std::cout
         << iterations << " iterations, "
         << "4-deep coroutine chain\n\n"
-        << std::fixed << std::setprecision(1)
+        << std::fixed << std::setprecision(1) << std::showpos
         << "  Recycling allocator: "
-        << ms_recycling << " ms  (+"
-        << pct_rc_std << "% vs std, +"
-        << pct_rc_mi << "% vs mimalloc)\n"
-        << "  mimalloc:            "
-        << ms_mimalloc << " ms  (+"
-        << pct_mi_std << "% vs std)\n"
+        << std::noshowpos << ms_recycling << " ms  ("
+        << std::showpos << pct_rc_std << "% vs std, "
+        << pct_rc_mi << "% vs mimalloc)\n"
+        << "  mimalloc:            "
+        << std::noshowpos << ms_mimalloc << " ms  ("
+        << std::showpos << pct_mi_std << "% vs std)\n"
         << "  std::allocator:      "
-        << ms_standard << " ms\n";
+        << std::noshowpos << ms_standard << " ms\n";
🤖 Prompt for AI Agents
In `@example/allocation/allocation.cpp` around lines 160 - 178, The printed
percent values pct_rc_std, pct_mi_std and pct_rc_mi currently always have a
hardcoded '+' prefix which yields awkward "+-X.X%" for negative values; update
the print formatting in the output block that prints "Recycling allocator",
"mimalloc" and "std::allocator" to either enable std::showpos on the stream
before printing those percent values (so positives show '+', negatives show '-'
correctly) or remove the hardcoded '+' and prepend a '+' only when the computed
value is >= 0 (i.e., conditionally format the sign for pct_rc_std, pct_rc_mi and
pct_mi_std). Ensure you restore the stream flags if you use std::showpos so
other numeric output is unaffected.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@example/allocation/Jamfile`:
- Around line 21-22: The Jamfile currently hardcodes "<linkflags>-lmimalloc",
which is GCC/Clang-specific and conflicts with the project's CMake static
mimalloc; update the Jamfile to avoid the non-portable flag by either (A)
conditionalizing the link flag per toolset (e.g., apply
"<toolset>gcc:<linkflags>-lmimalloc" and "<toolset>clang:<linkflags>-lmimalloc"
and add an MSVC-specific alternative or no-op for "<toolset>msvc"), or (B)
declare mimalloc as a Boost.Build library target with a lib rule and use that
target in your target requirements so both MSVC and GCC/Clang resolve it
consistently with the CMake static build (refer to the existing
"<linkflags>-lmimalloc" usage to locate where to replace it and to the new lib
declaration to unify resolution).

Comment on lines +21 to +22
:
<linkflags>-lmimalloc
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hardcoded -lmimalloc is not portable across toolsets.

<linkflags>-lmimalloc is a GCC/Clang-ism and will fail (or be silently ignored) on MSVC. Also, the CMake build fetches and statically links mimalloc v2.2.7, whereas this Jamfile expects a system-installed shared library — the two build paths are inconsistent.

Consider either:

  • Conditionalizing on toolset (e.g., <toolset>gcc:<linkflags>-lmimalloc) and adding an MSVC equivalent, or
  • Using a Boost.Build lib rule to declare mimalloc so both toolsets resolve it.
🤖 Prompt for AI Agents
In `@example/allocation/Jamfile` around lines 21 - 22, The Jamfile currently
hardcodes "<linkflags>-lmimalloc", which is GCC/Clang-specific and conflicts
with the project's CMake static mimalloc; update the Jamfile to avoid the
non-portable flag by either (A) conditionalizing the link flag per toolset
(e.g., apply "<toolset>gcc:<linkflags>-lmimalloc" and
"<toolset>clang:<linkflags>-lmimalloc" and add an MSVC-specific alternative or
no-op for "<toolset>msvc"), or (B) declare mimalloc as a Boost.Build library
target with a lib rule and use that target in your target requirements so both
MSVC and GCC/Clang resolve it consistently with the CMake static build (refer to
the existing "<linkflags>-lmimalloc" usage to locate where to replace it and to
the new lib declaration to unify resolution).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.drone/drone.bat:
- Around line 1-47: The .drone/drone.bat file must use CRLF line endings to
avoid Windows batch parser failures; convert .drone/drone.bat to CRLF line
endings (ensure the file in the repo is saved with CRLF) and add a
.gitattributes entry to force CRLF for .bat files (e.g., add a line targeting
.drone/*.bat such as " .drone/*.bat text eol=crlf" in .gitattributes) so future
commits preserve CRLF; ensure you commit the updated .drone/drone.bat and
.gitattributes so CI on Windows parses labels and commands like the IF/SET/CALL
blocks correctly.
- Around line 22-23: Replace the Unix commands in the batch script: instead of
using "cp -prf boost-ci-cloned/ci .", copy the directory with the native Windows
command xcopy using recursive and overwrite flags to copy boost-ci-cloned\ci
into the current folder (preserve subdirectories and files); and instead of "rm
-rf boost-ci-cloned", remove the source directory with rmdir using /s /q to
recursively delete without prompts. Update the commands referencing
boost-ci-cloned and ci accordingly (use xcopy and rmdir) so the .drone/drone.bat
script uses only native Windows commands.
🧹 Nitpick comments (3)
.drone/drone.sh (2)

83-86: Use [[ ]] or separate [ ] tests instead of -a/-o operators.

The -a and -o operators inside [ ] are POSIX-deprecated and can produce unexpected results when operands resemble operators. Since the script already uses [[ ]] elsewhere (line 39), prefer it here for consistency and correctness.

Proposed fix
-if  [ -n "${COVERITY_SCAN_NOTIFICATION_EMAIL}" -a \( "$TRAVIS_BRANCH" = "develop" -o "$TRAVIS_BRANCH" = "master" \) -a \( "$DRONE_BUILD_EVENT" = "push" -o "$DRONE_BUILD_EVENT" = "cron" \) ] ; then
+if [[ -n "${COVERITY_SCAN_NOTIFICATION_EMAIL}" && ( "$TRAVIS_BRANCH" = "develop" || "$TRAVIS_BRANCH" = "master" ) && ( "$DRONE_BUILD_EVENT" = "push" || "$DRONE_BUILD_EVENT" = "cron" ) ]]; then

22-22: Minor: export SELF=\basename ...`` masks the return value (SC2155).

This pattern appears on several lines (9, 13, 16, 22, 34, 99). Under set -e, if the command substitution fails, the export still succeeds and the error is silently swallowed. Since this is a CI script where silent failures can waste debugging time, consider splitting declare and assign on at least the critical ones.

Example for line 22:

-  export SELF=`basename $REPO_NAME`
+  SELF=$(basename "$REPO_NAME")
+  export SELF
.drone/drone.bat (1)

10-10: Quote the SET assignment for safety.

Unquoted SET values can include trailing whitespace or cause issues with special characters.

-  SET TRAVIS_BRANCH=!DRONE_BRANCH!
+  SET "TRAVIS_BRANCH=!DRONE_BRANCH!"

Comment on lines +1 to +47

@ECHO ON
setlocal enabledelayedexpansion

set TRAVIS_OS_NAME=windows

IF "!DRONE_BRANCH!" == "" (
for /F %%i in ("!GITHUB_REF!") do @set TRAVIS_BRANCH=%%~nxi
) else (
SET TRAVIS_BRANCH=!DRONE_BRANCH!
)

if "%DRONE_JOB_BUILDTYPE%" == "boost" (

echo "Running boost job"
echo '==================================> INSTALL'
REM there seems to be some problem with b2 bootstrap on Windows
REM when CXX env variable is set
SET "CXX="

git clone https://github.com/boostorg/boost-ci.git boost-ci-cloned --depth 1
cp -prf boost-ci-cloned/ci .
rm -rf boost-ci-cloned
REM source ci/travis/install.sh
REM The contents of install.sh below:

for /F %%i in ("%DRONE_REPO%") do @set SELF=%%~nxi
SET BOOST_CI_TARGET_BRANCH=!TRAVIS_BRANCH!
SET BOOST_CI_SRC_FOLDER=%cd%
if "%BOOST_BRANCH%" == "" (
SET BOOST_BRANCH=develop
if "%BOOST_CI_TARGET_BRANCH%" == "master" set BOOST_BRANCH=master
)

call ci\common_install.bat

echo '==================================> ZLIB'
git clone --branch v1.2.13 https://github.com/madler/zlib.git !BOOST_ROOT!\zlib-src --depth 1
set ZLIB_SOURCE=!BOOST_ROOT!\zlib-src

echo '==================================> COMPILE'

REM set B2_TARGETS=libs/!SELF!/test libs/!SELF!/example
set B2_TARGETS=libs/!SELF!/test
call !BOOST_ROOT!\libs\!SELF!\ci\build.bat

)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Unix line endings (LF) in a .bat file will cause parsing failures on Windows.

The Windows batch parser has known issues with LF-only line endings, including label parsing failures at 512-byte boundaries. This file must use CRLF line endings. Consider adding a .gitattributes entry:

.drone/*.bat text eol=crlf
🧰 Tools
🪛 Blinter (1.0.112)

[error] 1-1: Unix line endings detected. Explanation: Batch file uses Unix line endings (LF-only) which can cause GOTO/CALL label parsing failures and script malfunction due to Windows batch parser 512-byte boundary bugs. Recommendation: Convert file to Windows line endings (CRLF). Use tools like dos2unix, notepad++, or configure git with 'git config core.autocrlf true'. Context: File uses Unix line endings (LF-only) - 47 LF sequences found

(E018)


[error] 10-10: Unsafe SET command usage. Explanation: SET commands without proper validation or quoting can cause security issues. Recommendation: Always quote SET values and validate input: SET "var=safe value". Context: SET command value should be quoted for safety

(SEC002)

🤖 Prompt for AI Agents
In @.drone/drone.bat around lines 1 - 47, The .drone/drone.bat file must use
CRLF line endings to avoid Windows batch parser failures; convert
.drone/drone.bat to CRLF line endings (ensure the file in the repo is saved with
CRLF) and add a .gitattributes entry to force CRLF for .bat files (e.g., add a
line targeting .drone/*.bat such as " .drone/*.bat text eol=crlf" in
.gitattributes) so future commits preserve CRLF; ensure you commit the updated
.drone/drone.bat and .gitattributes so CI on Windows parses labels and commands
like the IF/SET/CALL blocks correctly.

Comment on lines +22 to +23
cp -prf boost-ci-cloned/ci .
rm -rf boost-ci-cloned
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, locate the .drone/drone.bat file
fd -g "drone.bat" -t f

# Then examine its contents with line numbers
if [ -f ".drone/drone.bat" ]; then
  wc -l ".drone/drone.bat"
  cat -n ".drone/drone.bat"
fi

Repository: cppalliance/capy

Length of output: 1690


🏁 Script executed:

#!/bin/bash
# Check for .gitattributes files in the repository
fd -g '.gitattributes' -t f --exec cat {}

Repository: cppalliance/capy

Length of output: 267


🏁 Script executed:

#!/bin/bash
# Look for context about the CI/CD setup (check if Git for Windows is explicitly required/configured)
fd -g '*.md' -t f | head -5 | xargs grep -l -i "git.*windows\|windows.*git" 2>/dev/null || echo "No direct references found"
fd -g 'appveyor*' -t f || echo "No AppVeyor config found"
fd -g '.drone.yml' -t f

Repository: cppalliance/capy

Length of output: 311


🏁 Script executed:

#!/bin/bash
# Search for .gitattributes with hidden files enabled
fd -g '.gitattributes' -H -t f --exec cat {}

Repository: cppalliance/capy

Length of output: 78


🏁 Script executed:

#!/bin/bash
# Search for any CI documentation or setup files
fd -E 'node_modules' -E '.git' -t f \( -name '*.md' -o -name 'README*' -o -name 'INSTALL*' \) | head -10

Repository: cppalliance/capy

Length of output: 290


🏁 Script executed:

#!/bin/bash
# Look for references to cp or rm in batch/bash scripts to see execution pattern
rg -t batch -t shell "cp|rm" --max-count 20

Repository: cppalliance/capy

Length of output: 89


🏁 Script executed:

#!/bin/bash
# Check if there are shell scripts that might set up the environment
fd -g '*.sh' -t f | head -10 | xargs -I {} sh -c 'echo "=== {} ===" && head -5 {}'

Repository: cppalliance/capy

Length of output: 305


🏁 Script executed:

#!/bin/bash
# Search for .drone.yml or drone configuration
fd -g '.drone.yml' -o -g '.drone.yaml' -H -t f --exec cat {}

Repository: cppalliance/capy

Length of output: 176


🏁 Script executed:

#!/bin/bash
# Search for README or CI documentation
fd -H -t f -E 'node_modules' -E '.git' '(README|CI|CONTRIBUTE)' | head -5 | xargs -I {} sh -c 'echo "=== {} ===" && head -20 {}'

Repository: cppalliance/capy

Length of output: 3403


🏁 Script executed:

#!/bin/bash
# Look for other .bat files to see patterns
fd -g '*.bat' -t f --exec sh -c 'echo "=== {} ===" && cat {}'

Repository: cppalliance/capy

Length of output: 717


🏁 Script executed:

#!/bin/bash
# Search for any documentation about Windows builds
rg -i "windows|batch|cmd|drone" --type md --max-count 30 | head -40

Repository: cppalliance/capy

Length of output: 2502


Replace Unix commands with native Windows equivalents in batch script.

Lines 22–23 use cp and rm, which are not standard Windows commands and require external tools (Git for Windows, etc.). The repository's own batch file (doc/build_antora.bat) demonstrates the correct pattern by using only native Windows commands. Use xcopy and rmdir for consistency and robustness.

Proposed fix
-cp -prf boost-ci-cloned/ci .
-rm -rf boost-ci-cloned
+xcopy /s /e /y /q boost-ci-cloned\ci ci\
+rmdir /s /q boost-ci-cloned
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cp -prf boost-ci-cloned/ci .
rm -rf boost-ci-cloned
xcopy /s /e /y /q boost-ci-cloned\ci ci\
rmdir /s /q boost-ci-cloned
🤖 Prompt for AI Agents
In @.drone/drone.bat around lines 22 - 23, Replace the Unix commands in the
batch script: instead of using "cp -prf boost-ci-cloned/ci .", copy the
directory with the native Windows command xcopy using recursive and overwrite
flags to copy boost-ci-cloned\ci into the current folder (preserve
subdirectories and files); and instead of "rm -rf boost-ci-cloned", remove the
source directory with rmdir using /s /q to recursively delete without prompts.
Update the commands referencing boost-ci-cloned and ci accordingly (use xcopy
and rmdir) so the .drone/drone.bat script uses only native Windows commands.

@vinniefalco vinniefalco merged commit 8d7a48c into cppalliance:develop Feb 14, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants