cmake: forward TA_ASSERT_POLICY to BTAS built from source - #587
Conversation
TA_ASSERT_POLICY was not forwarded to BTAS, so BTAS_ASSERT_THROWS fell back to its own default, BUILD_TESTING -- i.e. BTAS_ASSERT threw (regardless of NDEBUG) whenever TA's tests were built, even in configurations where TA_ASSERT aborts or is a no-op. FindOrFetchBTAS.cmake now sets BTAS_ASSERT_THROWS ON iff TA_ASSERT_POLICY is TA_ASSERT_THROW, OFF for TA_ASSERT_ABORT and TA_ASSERT_IGNORE (BTAS has no abort mode; with BTAS_ASSERT_THROWS=OFF BTAS_ASSERT is a plain assert(), the closest match for TA_ASSERT_ABORT). Guarded by NOT DEFINED, so a user -D or a parent project that sets BTAS_ASSERT_THROWS first keeps control.
BTAS (ValeevGroup/BTAS#188) now has the same three assertion modes as TA; map TA_ASSERT_{THROW,ABORT,IGNORE} onto BTAS_ASSERT_{THROW,ABORT,IGNORE} instead of the deprecated boolean BTAS_ASSERT_THROWS, whose OFF setting was a plain assert() (elided under NDEBUG) rather than an abort.
|
BTAS now has BTAS_ASSERT_POLICY (ValeevGroup/BTAS#188, merged as 52aadfe54): daedd95 bumps the BTAS tag and b4dafc8 forwards TA_ASSERT_POLICY as BTAS_ASSERT_POLICY (all three modes map 1:1) instead of the deprecated boolean BTAS_ASSERT_THROWS. |
There was a problem hiding this comment.
🟡 Changes recommended
The BTAS policy implementation/documentation mismatch and stale cache behavior must be corrected before approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Updates TA’s from-source BTAS integration to forward assertion policies, refreshes the BTAS revision, and documents the configuration.
Changes:
- Updates the BTAS source revision.
- Adds assertion-policy forwarding.
- Documents the forwarding behavior.
File summaries
| File | Summary and findings |
|---|---|
INSTALL.md |
Documents forwarding behavior. Nit (1 vote): correct the variable and policy mapping documentation. |
external/versions.cmake |
Updates the BTAS source revision. |
cmake/modules/FindOrFetchBTAS.cmake |
Adds policy forwarding. Critical (2 votes): implementation and pin use BTAS_ASSERT_POLICY rather than the documented BTAS_ASSERT_THROWS behavior. Moderate (1 vote): cached derived values can remain stale after policy changes. |
Review details
Suppressed comments (3)
INSTALL.md:427
- The documentation repeats the wrong variable and claims BTAS has the same three policy modes. BTAS consumes
BTAS_ASSERT_THROWS(a boolean); document theTA_ASSERT_THROW→ONand the other modes →OFFmapping and the correct override variable.
* `TA_ASSERT_POLICY` -- Set to `TA_ASSERT_IGNORE` to disable `TA_ASSERT` assertions, `TA_ASSERT_THROW` to cause `TA_ASSERT` assertions to throw, `TA_ASSERT_ABORT` to cause `TA_ASSERT` assertions to abort. The default is `TA_ASSERT_IGNORE` if CMake uses a single-configuration generator and`CMAKE_BUILD_TYPE` is set to `Release` or `MinSizeRel`, else the default is `TA_ASSERT_THROW`. This is also forwarded to BTAS, as `BTAS_ASSERT_POLICY` (`TA_ASSERT_THROW`/`TA_ASSERT_ABORT`/`TA_ASSERT_IGNORE` map onto `BTAS_ASSERT_THROW`/`BTAS_ASSERT_ABORT`/`BTAS_ASSERT_IGNORE`), when BTAS is built from source; set `BTAS_ASSERT_POLICY` explicitly to override.
cmake/modules/FindOrFetchBTAS.cmake:41
- These assignments create a persistent
BTAS_ASSERT_POLICYcache entry, so after the first configure thisNOT DEFINEDguard is false. Reconfiguring the same build tree with a differentTA_ASSERT_POLICYtherefore leaves BTAS at the old derived policy unless the BTAS cache entry is manually removed or overridden. Please track whether the cache value was auto-derived, or otherwise refresh only non-user values, so changing TA's policy keeps both dependencies synchronized.
if (NOT DEFINED BTAS_ASSERT_POLICY)
if (TA_ASSERT_POLICY STREQUAL TA_ASSERT_THROW)
set(BTAS_ASSERT_POLICY BTAS_ASSERT_THROW CACHE STRING "Controls the behavior of BTAS_ASSERT")
elseif (TA_ASSERT_POLICY STREQUAL TA_ASSERT_ABORT)
set(BTAS_ASSERT_POLICY BTAS_ASSERT_ABORT CACHE STRING "Controls the behavior of BTAS_ASSERT")
cmake/modules/FindOrFetchBTAS.cmake:35
- This configures
BTAS_ASSERT_POLICY, but the fetched BTAS CMake option isBTAS_ASSERT_THROWS; the new cache variable is therefore ignored and BTAS will continue selecting its behavior fromBUILD_TESTING. SetBTAS_ASSERT_THROWSinstead, enabling it only forTA_ASSERT_THROWand disabling it for the other two TA modes.
# forward TA's assertion policy to BTAS, else BTAS picks its own default
# (BTAS_ASSERT_THROW whenever BUILD_TESTING=ON, no matter what TA_ASSERT does).
# BTAS_ASSERT_POLICY has the same three modes as TA_ASSERT_POLICY, and
# like it is not affected by NDEBUG.
# N.B. only if the user did not ask for a specific BTAS_ASSERT_POLICY, hence a
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Two review comments on the forwarding added in the previous commit:
1. mapping IGNORE (and ABORT) onto BTAS_ASSERT_THROWS=OFF does not
implement IGNORE. At the BTAS tracked so far, BTAS_ASSERT_THROWS=OFF
makes BTAS_ASSERT a plain assert(), so a Debug build configured with
SEQUANT_ASSERT_BEHAVIOR=IGNORE still aborted on a BTAS assertion.
BTAS has since gained a real 3-mode policy, BTAS_ASSERT_POLICY =
BTAS_ASSERT_{THROW,ABORT,IGNORE} (ValeevGroup/BTAS#188), that is not
affected by NDEBUG; forward that as the primary knob, in both modules.
BTAS_ASSERT_THROWS is kept as the compatibility shim for a BTAS older
than that -- notably the one the tracked TiledArray builds, until its
tag moves past ValeevGroup/tiledarray#587 -- where both ABORT and
IGNORE still degrade to assert() semantics. The modules, AGENTS.md and
installing.rst say so; that is a limitation of the older BTAS, not
alignment.
2. in FindOrFetchTiledArray.cmake the BTAS setting was derived from
SEQUANT_ASSERT_BEHAVIOR, so a user who overrode TA_ASSERT_POLICY (e.g.
TA_ASSERT_IGNORE with SEQUANT_ASSERT_BEHAVIOR=THROW) got a BTAS that
disagreed with TiledArray. Derive it from the effective
TA_ASSERT_POLICY instead, i.e. after the override guard, and derive
the BTAS_ASSERT_THROWS shim from the effective BTAS_ASSERT_POLICY, so
that an explicit BTAS_ASSERT_POLICY is not contradicted by the shim.
The independent BTAS_ASSERT_{POLICY,THROWS} override guards remain.
…t it The derived value is a cache entry, so on the second configure the NOT DEFINED guard was false and a changed TA_ASSERT_POLICY left BTAS at the old policy. Record the derived value (TA_BTAS_ASSERT_POLICY_DERIVED, INTERNAL) and re-derive whenever BTAS_ASSERT_POLICY still equals it; an explicit user value survives reconfigures.
The forwarded values are cache entries, so on the second configure the NOT DEFINED guard was false and a changed SEQUANT_ASSERT_BEHAVIOR left TiledArray and BTAS at the policies derived from the old value. Record what was derived (SEQUANT_TA_ASSERT_POLICY_DERIVED, SEQUANT_BTAS_ASSERT_POLICY_DERIVED, SEQUANT_BTAS_ASSERT_THROWS_DERIVED, all INTERNAL) and re-derive, with FORCE, whenever the forwarded variable is undefined or still equals what was recorded; a value the user or a parent project set explicitly differs from the record and survives reconfigures. Same pattern as TiledArray's own forwarding (ValeevGroup/tiledarray#587).
… BTAS policy forwarding CMake cannot distinguish an explicit -DBTAS_ASSERT_POLICY=<X> from a cache entry that already holds <X>, so matching the value against the last derived one could clobber an explicit override. Now: while TA_BTAS_ASSERT_POLICY_FOLLOWS_TA (default ON) is on, BTAS_ASSERT_POLICY is re-derived from TA_ASSERT_POLICY on every configure; an explicit value that differs from the one TA last acknowledged (TA_BTAS_ASSERT_POLICY_SEEN, INTERNAL) is honored and turns the option OFF; passing the option OFF explicitly is the unambiguous way to pin any value, and turning it back ON resumes following.
There was a problem hiding this comment.
🟡 Changes recommended
Cache-marker persistence and first-configure opt-out handling have unresolved issues.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
cmake/modules/FindOrFetchBTAS.cmake:61
- If
TA_BTAS_ASSERT_POLICY_FOLLOWS_TA=OFFis used on the first configure without also settingBTAS_ASSERT_POLICY, this block runs beforeFetchContent_MakeAvailable(BTAS)and therefore records noSEENvalue; BTAS creates its default policy only afterward. On the next configure, turningFOLLOWS_TAback ON sees that cached default with no marker and immediately turns the option OFF again, so the documented opt-in cannot resume. Record the BTAS value after the source project has initialized its default (while retaining the prior marker for the pre-fetch comparison).
if (DEFINED BTAS_ASSERT_POLICY)
# the value TA acknowledged (derived, or explicit); turning the option back ON with this value still in the cache resumes following
set(TA_BTAS_ASSERT_POLICY_SEEN ${BTAS_ASSERT_POLICY} CACHE INTERNAL "BTAS_ASSERT_POLICY last acknowledged by TiledArray")
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
…gured On a first configure with TA_BTAS_ASSERT_POLICY_FOLLOWS_TA=OFF and no explicit BTAS_ASSERT_POLICY the entry did not exist yet when the marker was recorded (BTAS creates it), so turning the option back ON later mistook BTAS's default for an explicit value. Record TA_BTAS_ASSERT_POLICY_SEEN after FetchContent_MakeAvailable(BTAS); spell out FORCE (INTERNAL already implies it).
…-out
CMake cannot distinguish an explicit -DTA_ASSERT_POLICY=<X> (or
-DBTAS_ASSERT_POLICY=<X>) from a cache entry that already holds <X>, so
matching the value against the one last derived could clobber an explicit
override that happened to equal it.
Now each forwarded knob has an opt-out option, both ON by default:
SEQUANT_TA_ASSERT_POLICY_FOLLOWS_SEQUANT for TA_ASSERT_POLICY, and
SEQUANT_BTAS_ASSERT_POLICY_FOLLOWS_SEQUANT for BTAS_ASSERT_POLICY together
with its deprecated predecessor BTAS_ASSERT_THROWS. While an option is ON
the corresponding value is re-derived with FORCE on every configure; a
value that differs from the one SeQuant last acknowledged
(SEQUANT_TA_ASSERT_POLICY_SEEN, SEQUANT_BTAS_ASSERT_{POLICY,THROWS}_SEEN,
all INTERNAL) is taken as an explicit user value: it is honored and turns
the option OFF with a STATUS message. Turning the option back ON resumes
following.
The SEEN entries are recorded after FetchContent_MakeAvailable of the
subproject, so that on a first configure with following OFF and no
explicit value the subproject's own default is what gets acknowledged, and
turning following back ON later still works.
Same pattern as TiledArray's own forwarding (ValeevGroup/tiledarray#587).
The two options and the -D-vs-cache ambiguity are documented in
installing.rst and AGENTS.md.
Brings in the TiledArray side of the assert-policy forwarding (ValeevGroup/tiledarray#587): TiledArray now pins a BTAS that has BTAS_ASSERT_POLICY (ValeevGroup/BTAS#188) and forwards TA_ASSERT_POLICY to it itself. Without this, the BTAS that TiledArray builds in a SEQUANT_TILEDARRAY build only understands the deprecated BTAS_ASSERT_THROWS, whose OFF is a plain assert() -- neither ABORT nor IGNORE.
…_THROWS shim Both tracked tags are past BTAS_ASSERT_POLICY (ValeevGroup/BTAS#188) and TiledArray's own forwarding of TA_ASSERT_POLICY to BTAS (ValeevGroup/tiledarray#587), so SeQuant no longer needs to derive BTAS's policy itself when TiledArray builds BTAS, nor to set the deprecated boolean. FindOrFetchTiledArray forwards SEQUANT_ASSERT_BEHAVIOR as TA_ASSERT_POLICY only, and only when TiledArray is built from source (probed the way FetchContent's FIND_PACKAGE_ARGS will); FindOrFetchBTAS (used when SeQuant builds BTAS itself) forwards BTAS_ASSERT_POLICY only. Each keeps its SEQUANT_*_ASSERT_POLICY_FOLLOWS_SEQUANT opt-out and _SEEN marker. This retires the cases where the shim and the duplicate derivation disagreed: an undefined TA_ASSERT_POLICY producing BTAS_ASSERT_ (following off on a fresh configure), a changed BTAS_ASSERT_THROWS ignored next to a cached BTAS_ASSERT_POLICY, the shim losing to TiledArray's own forwarding, and forced cache entries when TiledArray comes installed.
Problem
TA_ASSERT_POLICYwas not forwarded to BTAS when BTAS is built from source, so BTAS fell back to its own default (throwingBTAS_ASSERTwheneverBUILD_TESTING=ON, regardless ofNDEBUG). SinceBUILD_TESTINGis ON in a normal TA developer configure,BTAS_ASSERTthrew even whereTA_ASSERTaborts or is a no-op, e.g. aReleasebuild withTA_ASSERT_IGNOREstill got throwing BTAS asserts.Change
BTAS_ASSERT_POLICY=BTAS_ASSERT_{THROW,ABORT,IGNORE}, none affected byNDEBUG(BTAS_ASSERT_POLICY: real THROW / ABORT / IGNORE modes BTAS#188, merged as 52aadfe54). The BTAS tag is bumped to that commit (own commit, per the dependency-pin rule).cmake/modules/FindOrFetchBTAS.cmake, on the from-source path only, derivesBTAS_ASSERT_POLICYfromTA_ASSERT_POLICY1:1:TA_ASSERT_POLICYBTAS_ASSERT_POLICYTA_ASSERT_THROWBTAS_ASSERT_THROWTA_ASSERT_ABORTBTAS_ASSERT_ABORTTA_ASSERT_IGNOREBTAS_ASSERT_IGNORETA_BTAS_ASSERT_POLICY_FOLLOWS_TA(defaultON) is the opt-out. While ON,BTAS_ASSERT_POLICYis re-derived on every configure, so changingTA_ASSERT_POLICYkeeps BTAS in sync. An explicitBTAS_ASSERT_POLICYthat differs from the value TA last acknowledged (INTERNAL cache entryTA_BTAS_ASSERT_POLICY_SEEN) is honored and turns the option OFF; turning it back ON resumes following. CMake cannot distinguish an explicit-DBTAS_ASSERT_POLICY=<X>from a cache entry already holding<X>, so pinning BTAS to a value TA derived earlier requires-DTA_BTAS_ASSERT_POLICY_FOLLOWS_TA=OFFas well;INSTALL.mdsays so.INSTALL.md'sTA_ASSERT_POLICYentry documents the forwarding and the override variable.History: the first commit (091de97) forwarded the deprecated boolean
BTAS_ASSERT_THROWSbecause BTAS had no abort mode at the time; the later commits switch to the three-mode policy once BTAS#188 landed.Verification
Configure-only (nothing built):
cmake -S <tree> -B <scratch> -G Ninja -DTA_PYTHON=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfowith MADNESS/BTAS supplied viaFETCHCONTENT_SOURCE_DIR_{MADNESS,BTAS}(BTAS at 52aadfe54), reconfiguring the same scratch tree in sequence and readingTA_ASSERT_POLICY,BTAS_ASSERT_POLICY,TA_BTAS_ASSERT_POLICY_FOLLOWS_TAfromCMakeCache.txt(prefixes dropped below).Tree A:
-DTA_ASSERT_POLICY=TA_ASSERT_ABORTTA_ASSERT_POLICY=TA_ASSERT_IGNORE BTAS_ASSERT_POLICY=BTAS_ASSERT_THROWTA_ASSERT_POLICY=TA_ASSERT_THROWTA_ASSERT_POLICY=TA_ASSERT_ABORT TA_BTAS_ASSERT_POLICY_FOLLOWS_TA=ONTA_ASSERT_POLICY=TA_ASSERT_IGNORETree B (fresh):
-DBTAS_ASSERT_POLICY=BTAS_ASSERT_ABORT(first configure)TA_ASSERT_POLICY=TA_ASSERT_ABORT BTAS_ASSERT_POLICY=BTAS_ASSERT_THROWTA_BTAS_ASSERT_POLICY_FOLLOWS_TA=OFFTree C (fresh; first configure opts out without an explicit value):
-DTA_BTAS_ASSERT_POLICY_FOLLOWS_TA=OFFTA_ASSERT_POLICY=TA_ASSERT_ABORT TA_BTAS_ASSERT_POLICY_FOLLOWS_TA=ONTA_ASSERT_POLICY=TA_ASSERT_IGNOREThe acknowledged value (
TA_BTAS_ASSERT_POLICY_SEEN) was read back at every step and always equals theBTAScolumn.Notes
SEQUANT_ASSERT_BEHAVIORtoTA_ASSERT_POLICYandBTAS_ASSERT_POLICY): cmake: forward SEQUANT_ASSERT_BEHAVIOR to TiledArray and BTAS built from source SeQuant#616. It becomes fully effective for BTAS once SeQuant's TA pin moves past this PR.