Skip to content

Reorder cintw includes so linked libcint cint.h wins (transitional)#94

Draft
joshkamm wants to merge 1 commit into
mainfrom
fix-cint-h-include-shadow
Draft

Reorder cintw includes so linked libcint cint.h wins (transitional)#94
joshkamm wants to merge 1 commit into
mainfrom
fix-cint-h-include-shadow

Conversation

@joshkamm

@joshkamm joshkamm commented Jun 4, 2026

Copy link
Copy Markdown
Member

Context

In a DM yesterday, Paul flagged that include/cint.h in this repo is a vendored copy of libcint 4.4.0's header, and that it can disagree with whatever libcint we actually link against -- pixi's, or his patched manual build at LIBCINT_PATH. His suggested direction: "include cint.h from the linked libcint directory" instead.

The risk is concrete because libcint's own cint.h is generated from cint.h.in by its CMake with #cmakedefine I8, #cmakedefine CACHE_SIZE_I8, etc. Two libcint builds at the same version tag can ship genuinely different headers depending on flags. If the vendored copy disagrees with the linked .so on sizeof(FINT), BAS_SLOTS/ATM_SLOTS, or env[] offsets, integrals come out silently wrong -- no link error, no crash.

The vendored header (include/cint.h:7) hard-codes CINT_VERSION 4.4.0 and was last touched in Nov 2024; we have meanwhile been linking against libcint 5.3.0 (manual) and pixi-provided libcint.

Related: #82 / memory note libcint_pixi_runtime_conflict -- pixi can also silently shadow Paul's patched libcint at runtime. Same disease (header vs .so mismatch), opposite end of the link.

What this PR does

Smallest possible step toward Paul's goal, scoped to the wrapper that actually calls libcint at runtime:

  • Reorders target_include_directories(cintw PRIVATE ...) in src/libcintw/CMakeLists.txt so ${LIBCINT_PATH}/include and $ENV{PREFIX}/include come before ${CMAKE_SOURCE_DIR}/include.
  • Now #include <cint.h> from cint_funcs.h resolves to the linked libcint's own header inside the cintw translation units.
  • Leaves the vendored include/cint.h in place for now -- see below.

Why not just delete include/cint.h outright?

That's the right end state, but it's not a one-line change:

  1. include/cintwrapper.h:9 and include/cintprep.h:11 unconditionally do extern \"C\" { #include \"cint_funcs.h\" }, which transitively pulls in <cint.h>.
  2. Those headers are included by src/integrals/integrals_aux.cpp, which builds into the SlaterGPU target -- whose target_include_directories in src/integrals/CMakeLists.txt:46-49 does not carry LIBCINT_PATH/include or PREFIX/include. It compiles today only because the vendored header sits in ${CMAKE_SOURCE_DIR}/include.
  3. When DO_GTO=OFF, libcint is not linked at all, and the vendored header is what lets these C++ class signatures parse without a libcint dependency.

So a clean removal needs: (a) libcint include paths plumbed into the SlaterGPU target too, (b) a decision on the DO_GTO=OFF case -- either require a libcint header to be reachable even when not linked, or guard the extern \"C\" includes behind #ifdef. Worth talking through before doing.

Test plan

  • Pixi build on Perlmutter: pixi run cmake --build succeeds and cintw picks up pixi's cint.h (verify via verbose include trace).
  • Manual libcint build on Athena: LIBCINT_PATH=... cmake ... succeeds and the libcint 5.3.0 header wins.
  • A smoke test through cintw (one int2e_sph call) returns the same numbers as before this change.

Discussion points for our next meeting

  • Do we want to do the full removal of include/cint.h?
  • For DO_GTO=OFF, would you rather (a) still require a libcint header in the include path (cheap, but adds a non-link dependency), or (b) #ifdef DO_GTO-guard the extern \"C\" block in cintwrapper.h / cintprep.h?
  • Should cintw's include dirs become PUBLIC so that downstream consumers (via SlaterGPU::cintw in SlaterGPUConfig.cmake.in) also see the linked libcint headers consistently?

The vendored include/cint.h is libcint 4.4.0's header with build-time
toggles (I8, CACHE_SIZE_I8) frozen in via #cmakedefine. When cintw is
built against a different libcint -- pixi's, or the manual 5.3.0 at
LIBCINT_PATH -- the vendored header was winning the search order and
hiding the real headers, risking a silent ABI mismatch on FINT width
or struct slot offsets.

Move LIBCINT_PATH/include and PREFIX/include ahead of SlaterGPU/include
in cintw's PRIVATE include path so the linked libcint's own cint.h is
the one the wrapper sees.

This is a transitional fix scoped to the cintw target. A follow-up can
remove the vendored copy entirely once SlaterGPU's target_include_dirs
also carry the libcint header path (and the DO_GTO=OFF case is sorted).
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.

1 participant