Skip to content

Add blas_symbol_suffix CMake option for symbol-suffixed BLAS libraries#129

Open
rileyjmurray wants to merge 4 commits into
icl-utk-edu:masterfrom
rileyjmurray:feature/blas-symbol-suffix
Open

Add blas_symbol_suffix CMake option for symbol-suffixed BLAS libraries#129
rileyjmurray wants to merge 4 commits into
icl-utk-edu:masterfrom
rileyjmurray:feature/blas-symbol-suffix

Conversation

@rileyjmurray

Copy link
Copy Markdown

Lets BLAS++ link against BLAS libraries whose Fortran symbols carry a suffix, e.g. OpenBLAS built with INTERFACE64=1 SYMBOLSUFFIX=64_ exports dgemm_64_ instead of dgemm_. Motivation is downstream consumers (e.g., conda-forge blaspp-feedstock) that want a clean ILP64 build against libopenblas64_ in the same prefix as the LP64 build.

Adds a new CMake cache var blas_symbol_suffix (empty by default, strict no-op) that propagates as -DBLAS_FORTRAN_SUFFIX=<value> into:

  • include/blas/mangling.h (consumer-visible name mangling)
  • config/config.h (compile/link probes in BLASFinder)
  • installed defines.h, via blaspp_defs_, so downstream consumers see the same name mangling.

When the suffix is set, the OpenBLAS search probe links -lopenblas${blas_symbol_suffix} to match upstream library naming convention (libopenblas64_).

Lets BLAS++ link against BLAS libraries whose Fortran symbols carry a
suffix, e.g. OpenBLAS built with INTERFACE64=1 SYMBOLSUFFIX=64_ exports
dgemm_64_ instead of dgemm_. Motivation is downstream consumers (e.g.,
conda-forge blaspp-feedstock) that want a clean ILP64 build against
libopenblas64_ in the same prefix as the LP64 build.

Adds a new CMake cache var `blas_symbol_suffix` (empty by default,
strict no-op) that propagates as `-DBLAS_FORTRAN_SUFFIX=<value>` into:
  - include/blas/mangling.h (consumer-visible name mangling)
  - config/config.h (compile/link probes in BLASFinder)
  - installed defines.h, via blaspp_defs_, so downstream consumers
    see the same name mangling.

When the suffix is set, the OpenBLAS search probe links
-lopenblas${blas_symbol_suffix} to match upstream library naming
convention (libopenblas64_).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@rileyjmurray

Copy link
Copy Markdown
Author

@tdehoff and/or @mgates3 please review when able :)

@rileyjmurray

rileyjmurray commented May 25, 2026

Copy link
Copy Markdown
Author

Question: Does this need to apply to CBLAS/LAPACKE wrappers too? OpenBLAS suffixes CBLAS symbols as cblas_dgemm64_. BLAS++ itself does not link CBLAS, but LAPACK++ does. If a parallel patch is needed in LAPACK++ for lapack_symbol_suffix, I can open one.

EDIT: above is from a robot (along with all commits in this PR).

@mgates3

mgates3 commented May 27, 2026

Copy link
Copy Markdown
Collaborator

LAPACK++ doesn't link with CBLAS.

Perhaps BLAS++ and LAPACK++ use CBLAS and LAPACKE for their testers, but the libraries themselves both directly wrap the Fortran interface, not the CBLAS or LAPACKE interface. (Granted, some libraries are reversed: the Fortran interface is a wrapper around the CBLAS interface.)

@rileyjmurray

rileyjmurray commented May 29, 2026

Copy link
Copy Markdown
Author

Gotcha, RE: LAPACK++ not linking with CBLAS.

Another question for you, @mgates3.

I just landed a PR getting an updated BLAS++ in conda-forge. That PR's implementation set three different internal CMake cache variables across BLASFinder, BLASConfig, and CBLASConfig (blas_libraries_cached / blas_found_cached, blas_config_cache, cblas_config_cache) to facilitate cross-compilation. The naming is inconsistent (_cached vs _cache) and they're all INTERNAL cache variables, so the workaround is poking at the implementation rather than a documented contract.

EDIT: crossing out questions based on Mark's response at conda-forge/blaspp-feedstock#10 (comment). In my next blaspp-feedstock PR I'll revert the changes that related on undocumented CMake config variables above.

I'd like to clean this up, but I don't want to overload this PR. I've given three options below. Can you like me know what you prefer? Either of the latter two options give us a chance to normalize the _cached / _cache naming while we're at it.

Option 1: defer. Land this PR as-is for the symbol-suffix work, and I'll open a separate issue + PR for the cross-compile detection cleanup afterwards.

Option 2: treat BLAS_LIBRARIES + blas_int as a trust contract. When the consumer has set both, short-circuit the detection loop in BLASFinder and skip the vendor-version probes in BLASConfig / CBLASConfig. No new public option; the contract is "if you've told us what BLAS is and how wide its integers are, we believe you." Today, even an explicit BLAS_LIBRARIES still triggers the full try_compile × mangling × int-size loop, since the gate at BLASFinder.cmake:25 is STREQUAL blas_libraries_cached rather than if (BLAS_LIBRARIES). Trade-off: changes the meaning of BLAS_LIBRARIES from "constrain the candidate list" to "skip detection entirely," which is a behavior change for anyone passing it on a native build.

Option 3: add a first-class skip flag. Add a single public CMake option, e.g. -Dblaspp_skip_blas_detection=ON, that gates the search loop in BLASFinder and the version probes in BLASConfig / CBLASConfig, and requires the consumer to pass BLAS_LIBRARIES, blas_int, and any BLAS_HAVE_* defines they want set. Could default to ON when CMAKE_CROSSCOMPILING is true and the required inputs are present. Trade-off: one new public option to document and maintain, but BLAS_LIBRARIES keeps its current meaning.

Finally, can you approve the CI workflow? I imagine "passing CI" is a prerequisite to merge this PR.

rileyjmurray added a commit to rileyjmurray/blaspp that referenced this pull request May 31, 2026
…fails, PR icl-utk-edu#129 works

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rileyjmurray added a commit to rileyjmurray/blaspp that referenced this pull request May 31, 2026
…P64 OpenBLAS

Holds the conda environment fixed and varies only the source tree, exposing
the conda prefix via CPATH/LIBRARY_PATH/LD_LIBRARY_PATH so the OpenBLAS search
probe can resolve -lopenblas64_.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rileyjmurray added a commit to rileyjmurray/blaspp that referenced this pull request May 31, 2026
…nk diagnostic

System g++ couldn't resolve conda OpenBLAS transitive deps (libgfortran etc.);
switch to conda's $CXX (cxx-compiler) with rpath flags and add a direct
g++ -lopenblas64_ probe to capture the real linker error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rileyjmurray added a commit to rileyjmurray/blaspp that referenced this pull request May 31, 2026
Real cause of prior failures: conda's libopenblas-ilp64 runtime ships only
libopenblas64_.so.0 (no unversioned .so), and bash -el's set -e aborted the
diagnose step on the expected-to-fail -lopenblas64_ probe. Resolve LIB to the
real .so.0, guard probes from set -e, prove icl-utk-edu#129 via explicit full path, and
recreate the dev .so symlink to also exercise the -lopenblas64_ auto-search.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rileyjmurray added a commit to rileyjmurray/blaspp that referenced this pull request May 31, 2026
One run emits one attachable log per claim, each stating its claim and ending
in FATAL_ERROR or 'Built target blaspp': apt master FAILS, apt by-path BUILDS,
conda master FAILS, conda PR icl-utk-edu#129 BUILDS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rileyjmurray added a commit to rileyjmurray/blaspp that referenced this pull request May 31, 2026
…bol suffix)

Shows there is no blaspp-free workaround for conda's libopenblas64_: master
mangles to dgemm_ but the lib only exports dgemm_64_, so even a correct
-DBLAS_LIBRARIES path fails the routine link probe. Renumber PR icl-utk-edu#129 demo to 05.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rileyjmurray added a commit to rileyjmurray/blaspp that referenced this pull request May 31, 2026
config/lapack.py hardcodes -lopenblas (line 321) and has no symbol-suffix
dimension, so 'configure.py blas=openblas blas_int=int64' fails to auto-detect
ILP64 OpenBLAS for both apt and conda. Shows the issue is not CMake-specific;
PR icl-utk-edu#129 (CMake-only) does not fix the Make build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mgates3

mgates3 commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

I would have to review the exact behavior, but I think setting BLAS_LIBRARIES and blas_int=int64 should constrain it so it tests only 64-bit versions. It will still test all the mangling options, unless that is also constrained. In other words, if you provide enough constraints, it ideally should try_compile only 1 option.

rileyjmurray and others added 3 commits June 1, 2026 12:46
Apply the symbol-suffix handling to the Make/configure.py build (config/lapack.py),
matching the existing CMake option: probe -lopenblas${suffix} and define
BLAS_FORTRAN_SUFFIX so calls mangle to e.g. dgemm_64_. Both build systems now also
probe -lopenblas64, so the ILP64 OpenBLAS that Debian/Ubuntu ship as libopenblas64
(plain symbols) is auto-detected without BLAS_LIBRARIES or BLA_VENDOR.

Adds a throwaway CI workflow (ilp64-fix-verify.yml) that builds against apt and
conda-forge ILP64 OpenBLAS via both build systems; to be removed once logs pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rileyjmurray

rileyjmurray commented Jun 1, 2026

Copy link
Copy Markdown
Author

Thanks for the feedback Mark. I've pushed updates:

  • Added -lopenblas64 to the BLAS++ search (CMake + Make). The ILP64 OpenBLAS that Debian/Ubuntu ship as libopenblas64 (plain dgemm_ symbols) now auto-detects with no BLAS_LIBRARIES and no BLA_VENDOR.
  • Extended blas_symbol_suffix to the Make/configure.py build. It was CMake-only before; config/lapack.py now probes -lopenblas${suffix} and writes BLAS_FORTRAN_SUFFIX into defines.h, so calls mangle to dgemm_64_. Still opt-in (empty default = no change), so MKL/ESSL etc. are unaffected.

Verified on a stock ubuntu-latest runner — built libblaspp four ways:

build BLAS result
CMake apt libopenblas64-dev, auto-detect finds -lopenblas64, builds
Make apt libopenblas64-dev, auto-detect finds -lopenblas64, builds
CMake conda libopenblas-ilp64, blas_symbol_suffix=64_ finds -lopenblas64_, builds
Make conda libopenblas-ilp64, blas_symbol_suffix=64_ finds -lopenblas64_, builds

Logs attached. LMK if other changes are needed!

04-make-conda-suffix.log
03-make-apt-auto.log
02-cmake-conda-suffix.log
01-cmake-apt-auto.log

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.

2 participants