Skip to content

feat(fortran): add generated Fortran bindings for HIP - #11923

Open
amontoison wants to merge 7 commits into
ROCm:developfrom
amontoison:users/amontoison/hip-fortran-bindings
Open

amontoison wants to merge 7 commits into
ROCm:developfrom
amontoison:users/amontoison/hip-fortran-bindings

Conversation

@amontoison

@amontoison amontoison commented Sep 21, 2026 •

Copy link
Copy Markdown

Implements RFC0015, Fortran Bindings Split for HIP: the Fortran binding is generated from the C headers and committed next to them. Shape previewed in ROCm/hipfort#540.

Merge first. The ten rocm-libraries binding PRs (ROCm/rocm-libraries#12533, ROCm/rocm-libraries#12370, ROCm/rocm-libraries#12582, ROCm/rocm-libraries#12581, ROCm/rocm-libraries#12514, ROCm/rocm-libraries#12368, ROCm/rocm-libraries#12366, ROCm/rocm-libraries#12367, ROCm/rocm-libraries#12505, ROCm/rocm-libraries#12506) stay in draft until this lands.

What lands

  • bindings/fortran/, a standalone project for the Fortran bindings of the rocm-systems libraries. ROCTx follows in feat(fortran): add the ROCTx Fortran binding to bindings/fortran #14024 in the same directory.
  • bindings/fortran/hip.F90 (45 281 lines, generated, marked linguist-generated): one module hip with the interfaces, enums, derived types and the hipCheck helper. Code using hipFORT's hipfort module for HIP writes use hip.
  • bindings/fortran/metadata/hip.toml: what the C headers cannot express (scalar, optional, by-value and function-pointer arguments), one table per C function, read by the generator when it runs on this checkout. Everything else is derived from the C signature.
  • Host outputs are typed and passed by reference: pass the variable, not c_loc(x). Outputs the API documents as nullable (sizeOut, the capture id, the graph node and edge arrays, bytes of hipModuleGetGlobal) are optional; omitting one passes NULL, so hipGraphGetNodes can return only the count. Handles are plain type(c_ptr). As in hipFORT, every function X is a generic around its bind(C) specific X_.
  • The project builds against an installed HIP (find_package(hip)); clr is untouched. The new shared/cmake/ROCmFortran.cmake publishes ROCM_HAVE_FORTRAN to rocm-systems projects.
  • bindings/fortran/test/ registers 41 runtime tests, labelled gpu; the four that use a kernel need the HIP language (occupancy, cooperative_launch) or hipcc (module_kernel, library_module), and a device lacking a feature reports the test skipped.

Options

Option Default Effect
BUILD_FORTRAN_BINDINGS ${UNIX} builds the binding; skipped without a Fortran compiler
BUILD_FORTRAN_CLIENTS ON builds and registers test/
FORTRAN_ARRAY_INTERFACES assumed-shape array overloads compiled into the module: assumed-shape (per rank, Fortran 2008), assumed-rank (dimension(..), Fortran 2018) or none
HIP_BUILD_FORTRAN_* unset per-library override of the two BUILD_FORTRAN_* options

Without CMAKE_Fortran_COMPILER or FC, ROCm's amdflang is preferred over the first compiler on PATH.

Build and test

From the repository root; the rocm-libraries tests find the binding in $PREFIX:

cmake -S bindings/fortran -B build/fortran \
  -DCMAKE_Fortran_COMPILER=/opt/rocm/bin/amdflang \
  -DCMAKE_PREFIX_PATH=/opt/rocm -DCMAKE_INSTALL_PREFIX="$PREFIX"
cmake --build build/fortran
ctest --test-dir build/fortran --output-on-failure
cmake --install build/fortran

Files install, in the dev component, under include/fortran/<compiler>/ and lib/fortran/<compiler>/ (GNUInstallDirs); a consumer uses find_package(hip-fortran) and target_link_libraries(app PRIVATE hip::hip_fortran), and sets HIP_FORTRAN_COMPILER_DIR to pick another compiler's build.

Verification

hip.F90 and metadata/hip.toml are byte-identical to the output of ROCm/rocm-fortran-generator 9c8b3e4 run on this checkout (strict mode), on develop 7215ce9.

Standalone configure, build and test against ROCm 10.2 on one gfx1101 GPU, with amdflang and gfortran 13.3, each under the three FORTRAN_ARRAY_INTERFACES values: all tests pass in the six configurations (41 registered, 34 with none, which skips the f2008 tests). mem_advise, peer_copy and cooperative_launch report skipped on this device. Against ROCm 10.1, rdma_flush and library_module do not link (their entry points are newer than its HIP); the other tests pass, from the build tree and from an install with ctest --test-dir $PREFIX/bin/hip-fortran (/opt/rocm/lib on LD_LIBRARY_PATH).

JIRA ID: ROCM-31390

The bindings live in bindings/fortran/, rocm-systems' tree for API consumers, outside the implementation projects (RFC0015): they use only the public API and build standalone against the installed libraries.

@therock-pr-bot

therock-pr-bot Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

✅ All Policy Checks Passed

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ⚠️ Warning Error: Source/code files changed without an accompanying unit test.
Expected: add at least one test file named like test_<name>.py / test_<name>.cpp (or <name>_test.*).
Current: code file(s) changed: bindings/fortran/test/vecadd_kernel.hip.cpp; no test file found
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —

🎉 All policy checks passed!

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

Copy link
Copy Markdown

🚫 Please fix the failed policies before requesting reviews.

The following policy checks failed:

  • ❌ PR Description

The Not ready to Review label has been added to this PR.
Once all policies pass, the label will be removed automatically.

amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 21, 2026
rocfft.F90 is generated from the rocFFT public headers by the rocm-fortran
generator and committed next to them, so that a header change and its
binding travel in the same pull request. It is a single self-contained
module, `rocfft`, carrying the interfaces, the enum constants, the opaque
handles and the rocfftCheck status helper. A consumer writes one `use rocfft`.

Implements RFC0014 (ROCm/TheRock#8122) for rocFFT, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: a Fortran binding declares bind(C)
interfaces only, so it compiles against neither the rocFFT headers nor
librocfft, and needs no GPU and no HIP compiler to build. librocfft is a
link-time dependency of a final executable and is carried as the target's
link interface. The subdirectory guards itself, returning early when
BUILD_FORTRAN_BINDINGS is OFF or no Fortran compiler is present, so a C-only
site is unaffected.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCFFT_BUILD_FORTRAN_* so one library
can be singled out in a monorepo build. FORTRAN_ARRAY_INTERFACES is a
tri-state (none / assumed-shape / assumed-rank, default assumed-shape)
replacing the two booleans USE_FPOINTER_INTERFACES and ASSUMED_RANK: the two
upper tiers cannot legally coexist in one generic, because an assumed-rank
dummy is not distinguishable by rank from the per-rank specifics.
ROCFFT_HAVE_FORTRAN_BINDINGS reports whether they were really built, and the
config package sets rocfft_FORTRAN_FOUND.

The compiler probe is read from ROCM_HAVE_FORTRAN, which is the name to
settle on across both monorepos. This repository's root publishes
ROCM_LIBS_HAVE_FORTRAN today, so that spelling is honoured second, never over
the new name. It is a bridge with an end: when the root is switched over,
that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, Flang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper, where a
plain basename would not.

The config package lands in lib/cmake/rocfft beside the C package, and a
forwarder in lib/cmake/rocfft-fortran makes find_package(rocfft-fortran)
resolve to the same place.

Tests
-----
test/ carries 19 tests under CTest. Eighteen are runtime tests that allocate
device memory, so they write `use hip` next to `use rocfft` and need the HIP
Fortran binding at compile time; they are skipped with a named message when
it is absent. test_rocfft.F03, the exhaustive symbol test, uses only
iso_c_binding and rocfft, so it is registered outside that guard. That
distinction is load-bearing: ROCm does not currently ship a HIP Fortran
binding, so guarding the whole directory would mean zero tests against a
stock /opt/rocm, including the only one that proves every bind(C) symbol
resolves against librocfft.

Runtime tests are labelled "gpu" and the symbol test "symbols", so
ctest -LE gpu stays meaningful on a machine without one.

Verified against ROCm 10.0 on gfx1101 with gfortran 13.3.0. Against a stock
/opt/rocm the symbol test builds, links and passes on its own. With the HIP
Fortran binding available, 19 of 19 pass; one of those, field_brick_z, prints
SKIPPED and exits 0 because it wants two GPUs, so the honest reading is 17
real GPU tests, 1 self-skip and the symbol test. The documented consumer path
was exercised end to end: install, find_package(rocfft-fortran), link
roc::rocfft_fortran, run on the GPU.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 21, 2026
hipfft.F90 and hipfftw.F90 are generated from the public headers by the
rocm-fortran generator and committed next to them, so that a header change
and its binding travel in the same pull request. Each is a single
self-contained module, `hipfft` and `hipfftw`, carrying the interfaces, the
enum constants, the opaque handles and the status helper. A consumer writes
one `use hipfft`.

Implements RFC0014 (ROCm/TheRock#8122) for hipFFT, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

Two bindings in one directory, because hipFFTW is built by the hipFFT
project rather than one of its own. They are separate modules, separate
targets and separate config packages, but they live next to the headers they
bind rather than in a directory of their own.

The bindings declare bind(C) interfaces only, so they compile against neither
the hipFFT headers nor libhipfft, and need no GPU and no HIP compiler to
build. The C libraries are link-time dependencies of a final executable and
are carried as each target's link interface. The subdirectory guards itself,
returning early when BUILD_FORTRAN_BINDINGS is OFF or no Fortran compiler is
present, so a C-only site is unaffected.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPFFT_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic,
because an assumed-rank dummy is not distinguishable by rank from the
per-rank specifics. The config packages set hipfft_FORTRAN_FOUND and
hipfftw_FORTRAN_FOUND.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on
across both monorepos. This repository's root publishes
ROCM_LIBS_HAVE_FORTRAN today, so that spelling is honoured second, never over
the new name. It is a bridge with an end: when the root is switched over,
that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so each .mod and archive installs
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper, where a
plain basename would not.

Both config packages land in lib/cmake/hipfft beside the C package, and
forwarders in lib/cmake/hipfft-fortran and lib/cmake/hipfftw-fortran make
find_package(hipfft-fortran) and find_package(hipfftw-fortran) resolve to the
same place.

Tests
-----
test/ carries 21 tests under CTest. Nineteen are runtime tests that allocate
device memory, so they write `use hip` next to their own `use`, which makes
the HIP Fortran binding a compile-time dependency; they are skipped with a
named message when it is absent. The two exhaustive symbol tests use only
iso_c_binding and the module under test, so they are registered outside that
guard. That distinction matters: ROCm does not currently ship a HIP Fortran
binding, so guarding the whole directory would mean zero tests against a
stock /opt/rocm, including the only ones that prove every bind(C) symbol
resolves against the installed libraries.

Runtime tests are labelled "gpu" and the symbol tests "symbols", so
ctest -LE gpu stays meaningful on a machine without one.

Verified against ROCm 10.0 on gfx1101 with BOTH compilers, gfortran 13.3.0
and amdflang 23.0.0. Against a stock /opt/rocm the two symbol tests build,
link and pass on their own; with the HIP Fortran binding available, 21 of 21
pass. The documented consumer path was exercised end to end with amdflang:
install, find_package on both packages, link hip::hipfft_fortran and
hip::hipfftw_fortran in one program, run on the GPU. The compiler-mismatch
diagnostic was exercised for real by installing with amdflang and consuming
with gfortran, which is what confirms the CMAKE_Fortran_COMPILER_ID mapping
handles LLVMFlang and that the message renders as prose rather than as a
semicolon-separated list.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 21, 2026
hipsparse.F90 is generated from the hipSPARSE public headers by the
rocm-fortran generator and committed next to them, so that a header change
and its binding travel in the same pull request. It is a single
self-contained module, `hipsparse`, carrying the interfaces, the enum
constants, the opaque handles and the hipsparseCheck status helper. A
consumer writes one `use hipsparse`.

Implements RFC0014 (ROCm/TheRock#8122) for hipSPARSE, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: it compiles against neither the hipSPARSE
headers nor libhipsparse, and needs no GPU to build. libhipsparse is a
link-time dependency of a final executable and is carried as the target's
link interface. The subdirectory guards itself, returning early when
BUILD_FORTRAN_BINDINGS is OFF or no Fortran compiler is present, so a C-only
site is unaffected.

Target naming
-------------
hipSPARSE already creates a target called hipsparse_fortran: the hand-written
Fortran layer for its own test clients, under HIPSPARSE_ENABLE_FORTRAN. CMake
target names are global, so the generated binding is built as
hipsparse_fortran_bindings and given EXPORT_NAME hipsparse_fortran. Consumers
therefore still write roc::hipsparse_fortran and link
libhipsparse_fortran.a, exactly as the other libraries, while the two targets
coexist in one build tree. The hand-written layer is untouched: the generated
module is not yet source-compatible with it, so superseding it is a separate
coordinated change.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPSPARSE_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic,
because an assumed-rank dummy is not distinguishable by rank from the
per-rank specifics. HIPSPARSE_HAVE_FORTRAN_BINDINGS reports whether they were
really built, and the config package sets hipsparse_FORTRAN_FOUND.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on
across both monorepos. This repository's root publishes
ROCM_LIBS_HAVE_FORTRAN today, so that spelling is honoured second, never over
the new name. It is a bridge with an end: when the root is switched over,
that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

The config package lands in lib/cmake/hipsparse beside the C package, and a
forwarder in lib/cmake/hipsparse-fortran makes find_package(hipsparse-fortran)
resolve to the same place.

Tests
-----
test/ carries 50 tests under CTest. Forty-nine are runtime tests that
allocate device memory around each hipSPARSE call, so they write `use hip`
and need the HIP Fortran binding at compile time; they are skipped with a
named message when it is absent. test_hipsparse.F03, the exhaustive symbol
test, uses only iso_c_binding and hipsparse, so it is registered outside that
guard. That distinction is load-bearing: ROCm does not currently ship a HIP
Fortran binding, so guarding the whole directory would mean zero tests
against a stock /opt/rocm, including the only one that proves every bind(C)
symbol resolves against libhipsparse.

The generated sources are named hipsparse_<op>.f03, so the library name is
stripped when composing the CMake and CTest identifiers: the test is
hipsparse_fortran_dspmv rather than hipsparse_fortran_hipsparse_dspmv. The
source files are untouched.

Runtime tests are labelled "gpu" and the symbol test "symbols", so
ctest -LE gpu stays meaningful on a machine without one.

Verified against ROCm 10.0 on gfx1101 with BOTH compilers, gfortran 13.3.0
and amdflang 23.0.0. A standalone configure is clean under -Wdev. Against a
stock /opt/rocm the symbol test builds, links and passes on its own; with the
HIP Fortran binding available, 50 of 50 pass with each compiler. The
documented consumer path was exercised end to end with amdflang: install,
find_package(hipsparse-fortran), link roc::hipsparse_fortran, run on the GPU.
The compiler-mismatch diagnostic was exercised for real by installing with
amdflang and consuming with gfortran, which is what confirms the
CMAKE_Fortran_COMPILER_ID mapping handles LLVMFlang and that the message
renders as prose rather than as a semicolon-separated list.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 21, 2026
JIRA ID : ROCM-31390

hipblas.F90 is generated from the hipBLAS public headers by the rocm-fortran
generator and committed next to them, so that a header change and its
binding travel in the same pull request. It is a single self-contained
module, `hipblas`, carrying the interfaces, the enum constants, the opaque
handles and the hipblasCheck status helper. A consumer writes one
`use hipblas`.

Implements RFC0014 (ROCm/TheRock#8122) for hipBLAS, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: it compiles against neither the hipBLAS
headers nor libhipblas, and needs no GPU to build. libhipblas is a link-time
dependency of a final executable and is carried as the target's link
interface. The subdirectory guards itself, returning early when
BUILD_FORTRAN_BINDINGS is OFF or no Fortran compiler is present, so a C-only
site is unaffected. The hook sits outside the SKIP_LIBRARY guard: that guard
controls whether libhipblas is built here, and the bindings need it linked,
not built.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPBLAS_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic,
because an assumed-rank dummy is not distinguishable by rank from the
per-rank specifics. HIPBLAS_HAVE_FORTRAN_BINDINGS reports whether they were
really built, and the config package sets hipblas_FORTRAN_FOUND.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on
across both monorepos. This repository's root publishes
ROCM_LIBS_HAVE_FORTRAN today, so that spelling is honoured second, never over
the new name. It is a bridge with an end: when the root is switched over,
that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
HIPBLAS_FORTRAN_COMPILER_DIR with a suffixed name, so the config package
accepts the recorded directory when it is the derived name OR that name
followed by a separator and anything. A strict equality would reject exactly
the sites that used the documented override. The comparison is done by length
and substring rather than by regex: the derived name comes from the
compiler's basename on the fallback branch, so it is an arbitrary file name,
and interpolating it into a regex would let a compiler called flang(2) either
mismatch silently or abort CMake outright. CMake has no regex-escape.

The config package lands in lib/cmake/hipblas beside the C package, and a
forwarder in lib/cmake/hipblas-fortran makes find_package(hipblas-fortran)
resolve to the same place.

Tests
-----
test/ carries 69 tests under CTest. Sixty-eight are runtime tests that
allocate and copy device memory around each hipBLAS call, so they write
`use hip` and need the HIP Fortran binding at compile time; they are skipped
with a named message when it is absent. test_hipblas.F03, the exhaustive
symbol test, uses only iso_c_binding and hipblas, so it is registered outside
that guard. That distinction is load-bearing: ROCm does not currently ship a
HIP Fortran binding, so guarding the whole directory would mean zero tests
against a stock /opt/rocm, including the only one that proves every bind(C)
symbol resolves against libhipblas.

Runtime tests are labelled "gpu" and the symbol test "symbols", so
ctest -LE gpu stays meaningful on a machine without one.

Verified against ROCm 10.0 on gfx1101 with BOTH compilers, gfortran 13.3.0
and amdflang 23.0.0. A standalone configure is clean under -Wdev. Against a
stock /opt/rocm the symbol test builds, links and passes on its own; with the
HIP Fortran binding available, 69 of 69 pass. The documented consumer path
was exercised end to end with amdflang: install,
find_package(hipblas-fortran), link roc::hipblas_fortran, run on the GPU.

The compiler check was exercised in both directions rather than only the
happy one. Installed under an overridden gfortran-13.3.0 directory, a
gfortran consumer is accepted; an amdflang consumer against that same install
is rejected with a named diagnostic. Installing with amdflang and consuming
with gfortran is what confirms the CMAKE_Fortran_COMPILER_ID mapping handles
LLVMFlang, and that the message renders as prose rather than as a
semicolon-separated list.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 21, 2026
JIRA ID : ROCM-31390

hipblas.F90 is generated from the hipBLAS public headers by the rocm-fortran
generator and committed next to them, so that a header change and its
binding travel in the same pull request. It is a single self-contained
module, `hipblas`, carrying the interfaces, the enum constants, the opaque
handles and the hipblasCheck status helper. A consumer writes one
`use hipblas`.

Implements RFC0014 (ROCm/TheRock#8122) for hipBLAS, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: it compiles against neither the hipBLAS
headers nor libhipblas, and needs no GPU to build. libhipblas is a link-time
dependency of a final executable and is carried as the target's link
interface. The subdirectory guards itself, returning early when
BUILD_FORTRAN_BINDINGS is OFF or no Fortran compiler is present, so a C-only
site is unaffected. The hook sits outside the SKIP_LIBRARY guard: that guard
controls whether libhipblas is built here, and the bindings need it linked,
not built.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPBLAS_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic,
because an assumed-rank dummy is not distinguishable by rank from the
per-rank specifics. HIPBLAS_HAVE_FORTRAN_BINDINGS reports whether they were
really built, and the config package sets hipblas_FORTRAN_FOUND.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on
across both monorepos. This repository's root publishes
ROCM_LIBS_HAVE_FORTRAN today, so that spelling is honoured second, never over
the new name. It is a bridge with an end: when the root is switched over,
that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
HIPBLAS_FORTRAN_COMPILER_DIR with a suffixed name, so the config package
accepts the recorded directory when it is the derived name OR that name
followed by a separator and anything. A strict equality would reject exactly
the sites that used the documented override. The comparison is done by length
and substring rather than by regex: the derived name comes from the
compiler's basename on the fallback branch, so it is an arbitrary file name,
and interpolating it into a regex would let a compiler called flang(2) either
mismatch silently or abort CMake outright. CMake has no regex-escape.

The config package lands in lib/cmake/hipblas beside the C package, and a
forwarder in lib/cmake/hipblas-fortran makes find_package(hipblas-fortran)
resolve to the same place.

Tests
-----
test/ carries 69 tests under CTest. Sixty-eight are runtime tests that
allocate and copy device memory around each hipBLAS call, so they write
`use hip` and need the HIP Fortran binding at compile time; they are skipped
with a named message when it is absent. test_hipblas.F03, the exhaustive
symbol test, uses only iso_c_binding and hipblas, so it is registered outside
that guard. That distinction is load-bearing: ROCm does not currently ship a
HIP Fortran binding, so guarding the whole directory would mean zero tests
against a stock /opt/rocm, including the only one that proves every bind(C)
symbol resolves against libhipblas.

Runtime tests are labelled "gpu" and the symbol test "symbols", so
ctest -LE gpu stays meaningful on a machine without one.

Verified against ROCm 10.0 on gfx1101 with BOTH compilers, gfortran 13.3.0
and amdflang 23.0.0. A standalone configure is clean under -Wdev. Against a
stock /opt/rocm the symbol test builds, links and passes on its own; with the
HIP Fortran binding available, 69 of 69 pass. The documented consumer path
was exercised end to end with amdflang: install,
find_package(hipblas-fortran), link roc::hipblas_fortran, run on the GPU.

The compiler check was exercised in both directions rather than only the
happy one. Installed under an overridden gfortran-13.3.0 directory, a
gfortran consumer is accepted; an amdflang consumer against that same install
is rejected with a named diagnostic. Installing with amdflang and consuming
with gfortran is what confirms the CMAKE_Fortran_COMPILER_ID mapping handles
LLVMFlang, and that the message renders as prose rather than as a
semicolon-separated list.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

rocrand.F90 is generated from the rocRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocrand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the rocrandCheck status helper. A consumer writes one
`use rocrand`.

Implements RFC0014 (ROCm/TheRock#8122) for rocRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: it compiles against neither the rocRAND headers
nor librocrand, and needs no GPU to build. librocrand is a link-time dependency
of a final executable and is carried as the target's link interface. The
subdirectory guards itself, returning early when BUILD_FORTRAN_BINDINGS is OFF
or no Fortran compiler is present, so a C-only site is unaffected. The hook sits
outside the USE_SYSTEM_LIB branch: that branch controls whether librocrand is
built here, and the bindings need it linked, not built.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. ROCRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name. It is a bridge
with an end: when the root is switched over, that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
ROCRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. A strict equality would reject exactly the sites that
used the documented override. The comparison is done by length and substring
rather than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Coexistence with the deprecated wrapper
---------------------------------------
rocRAND already ships a hand-written wrapper (library/src/fortran/rocrand_m.f90)
under BUILD_FORTRAN_WRAPPER, itself deprecated in favour of hipfort. It is left
untouched here, and it collides with these bindings in two places.

The target name is the first. Both want rocrand_fortran, which is a hard CMake
error naming neither option, so the clash is reported here instead, with the
flag to turn off. It is not resolved by silently winning: a site that asked for
BUILD_FORTRAN_WRAPPER asked for the wrapper.

The config file name is the second, and it is why this package does not use the
layout the other libraries use. lib/cmake/rocrand/rocrand-fortran-config.cmake
already belongs to the wrapper, and rocrand-config.cmake include()s that name
unconditionally -- it is in /opt/rocm today. Installing there would not shadow a
stale file, it would splice this package into the middle of every
find_package(rocrand) in existence, C++ consumers included, and drop
rocrand_FORTRAN_SRC_DIRS with it. So the real config stands alone in
lib/cmake/rocrand-fortran, which find_package(rocrand-fortran) already searches,
and nothing is written into lib/cmake/rocrand. For the same reason the package
reports rocrand_FORTRAN_BINDINGS_FOUND rather than overloading
rocrand_FORTRAN_FOUND, which the wrapper's config defines with a different
meaning. When the wrapper is retired, both can move to the shared spelling.

Tests
-----
24 tests under CTest, off by default. Twenty-three are runtime tests, one per
(generator, distribution) pair, that allocate and copy device memory around each
rocRAND call, so they write `use hip` and need the HIP Fortran binding at
compile time; they are skipped with a named message when it is absent.

test_rocrand.F03, the exhaustive symbol test, uses only iso_c_binding and
rocrand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against librocrand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

hiprand.F90 is generated from the hipRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`hiprand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the hiprandCheck status helper. A consumer writes one
`use hiprand`.

Implements RFC0014 (ROCm/TheRock#8122) for hipRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: it compiles against neither the hipRAND headers
nor libhiprand, and needs no GPU to build. libhiprand is a link-time dependency
of a final executable and is carried as the target's link interface. The
subdirectory guards itself, returning early when BUILD_FORTRAN_BINDINGS is OFF
or no Fortran compiler is present, so a C-only site is unaffected.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. HIPRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name. It is a bridge
with an end: when the root is switched over, that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
HIPRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. A strict equality would reject exactly the sites that
used the documented override. The comparison is done by length and substring
rather than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Coexistence with the deprecated wrapper
---------------------------------------
hipRAND already ships a hand-written wrapper (library/src/fortran/hiprand_m.f90)
under BUILD_FORTRAN_WRAPPER, itself deprecated in favour of hipfort. It is left
untouched here, and it collides with these bindings in two places.

The target name is the first. Both want hiprand_fortran, which is a hard CMake
error naming neither option, so the clash is reported here instead, with the
flag to turn off. It is not resolved by silently winning: a site that asked for
BUILD_FORTRAN_WRAPPER asked for the wrapper.

The config file name is the second, and it is why this package does not use the
layout the other libraries use. lib/cmake/hiprand/hiprand-fortran-config.cmake
already belongs to the wrapper, and hiprand-config.cmake include()s that name
unconditionally -- it is in /opt/rocm today. Installing there would not shadow a
stale file, it would splice this package into the middle of every
find_package(hiprand) in existence, C++ consumers included, and drop
hiprand_FORTRAN_SRC_DIRS with it. So the real config stands alone in
lib/cmake/hiprand-fortran, which find_package(hiprand-fortran) already searches,
and nothing is written into lib/cmake/hiprand. For the same reason the package
reports hiprand_FORTRAN_BINDINGS_FOUND rather than overloading
hiprand_FORTRAN_FOUND, which the wrapper's config defines with a different
meaning. When the wrapper is retired, both can move to the shared spelling.

Tests
-----
24 tests under CTest, off by default. Twenty-three are runtime tests, one per
(generator, distribution) pair, that allocate and copy device memory around each
hipRAND call, so they write `use hip` and need the HIP Fortran binding at
compile time; they are skipped with a named message when it is absent.

test_hiprand.F03, the exhaustive symbol test, uses only iso_c_binding and
hiprand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against libhiprand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

rocrand.F90 is generated from the rocRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocrand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the rocrandCheck status helper. A consumer writes one
`use rocrand`.

Implements RFC0014 (ROCm/TheRock#8122) for rocRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: it compiles against neither the rocRAND headers
nor librocrand, and needs no GPU to build. librocrand is a link-time dependency
of a final executable and is carried as the target's link interface. The
subdirectory guards itself, returning early when BUILD_FORTRAN_BINDINGS is OFF
or no Fortran compiler is present, so a C-only site is unaffected. The hook sits
outside the USE_SYSTEM_LIB branch: that branch controls whether librocrand is
built here, and the bindings need it linked, not built.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. ROCRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name. It is a bridge
with an end: when the root is switched over, that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
ROCRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. A strict equality would reject exactly the sites that
used the documented override. The comparison is done by length and substring
rather than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Coexistence with the deprecated wrapper
---------------------------------------
rocRAND already ships a hand-written wrapper (library/src/fortran/rocrand_m.f90)
under BUILD_FORTRAN_WRAPPER, itself deprecated in favour of hipfort. It is left
untouched here, and it collides with these bindings in two places.

The target name is the first. Both want rocrand_fortran, which is a hard CMake
error naming neither option, so the clash is reported here instead, with the
flag to turn off. It is not resolved by silently winning: a site that asked for
BUILD_FORTRAN_WRAPPER asked for the wrapper.

The config file name is the second, and it is why this package does not use the
layout the other libraries use. lib/cmake/rocrand/rocrand-fortran-config.cmake
already belongs to the wrapper, and rocrand-config.cmake include()s that name
unconditionally -- it is in /opt/rocm today. Installing there would not shadow a
stale file, it would splice this package into the middle of every
find_package(rocrand) in existence, C++ consumers included, and drop
rocrand_FORTRAN_SRC_DIRS with it. So the real config stands alone in
lib/cmake/rocrand-fortran, which find_package(rocrand-fortran) already searches,
and nothing is written into lib/cmake/rocrand. For the same reason the package
reports rocrand_FORTRAN_BINDINGS_FOUND rather than overloading
rocrand_FORTRAN_FOUND, which the wrapper's config defines with a different
meaning. When the wrapper is retired, both can move to the shared spelling.

Tests
-----
24 tests under CTest, off by default. Twenty-three are runtime tests, one per
(generator, distribution) pair, that allocate and copy device memory around each
rocRAND call, so they write `use hip` and need the HIP Fortran binding at
compile time; they are skipped with a named message when it is absent.

test_rocrand.F03, the exhaustive symbol test, uses only iso_c_binding and
rocrand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against librocrand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

hiprand.F90 is generated from the hipRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`hiprand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the hiprandCheck status helper. A consumer writes one
`use hiprand`.

Implements RFC0014 (ROCm/TheRock#8122) for hipRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: it compiles against neither the hipRAND headers
nor libhiprand, and needs no GPU to build. libhiprand is a link-time dependency
of a final executable and is carried as the target's link interface. The
subdirectory guards itself, returning early when BUILD_FORTRAN_BINDINGS is OFF
or no Fortran compiler is present, so a C-only site is unaffected.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. HIPRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name. It is a bridge
with an end: when the root is switched over, that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
HIPRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. A strict equality would reject exactly the sites that
used the documented override. The comparison is done by length and substring
rather than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Coexistence with the deprecated wrapper
---------------------------------------
hipRAND already ships a hand-written wrapper (library/src/fortran/hiprand_m.f90)
under BUILD_FORTRAN_WRAPPER, itself deprecated in favour of hipfort. It is left
untouched here, and it collides with these bindings in two places.

The target name is the first. Both want hiprand_fortran, which is a hard CMake
error naming neither option, so the clash is reported here instead, with the
flag to turn off. It is not resolved by silently winning: a site that asked for
BUILD_FORTRAN_WRAPPER asked for the wrapper.

The config file name is the second, and it is why this package does not use the
layout the other libraries use. lib/cmake/hiprand/hiprand-fortran-config.cmake
already belongs to the wrapper, and hiprand-config.cmake include()s that name
unconditionally -- it is in /opt/rocm today. Installing there would not shadow a
stale file, it would splice this package into the middle of every
find_package(hiprand) in existence, C++ consumers included, and drop
hiprand_FORTRAN_SRC_DIRS with it. So the real config stands alone in
lib/cmake/hiprand-fortran, which find_package(hiprand-fortran) already searches,
and nothing is written into lib/cmake/hiprand. For the same reason the package
reports hiprand_FORTRAN_BINDINGS_FOUND rather than overloading
hiprand_FORTRAN_FOUND, which the wrapper's config defines with a different
meaning. When the wrapper is retired, both can move to the shared spelling.

Tests
-----
24 tests under CTest, off by default. Twenty-three are runtime tests, one per
(generator, distribution) pair, that allocate and copy device memory around each
hipRAND call, so they write `use hip` and need the HIP Fortran binding at
compile time; they are skipped with a named message when it is absent.

test_hiprand.F03, the exhaustive symbol test, uses only iso_c_binding and
hiprand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against libhiprand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

rocrand.F90 is generated from the rocRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocrand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the rocrandCheck status helper. A consumer writes one
`use rocrand` and links roc::rocrand_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written wrapper
---------------------------------
library/src/fortran (rocrand_m.f90, hip_m.f90), its config template, and the
FRUIT-based suite under test/fortran go with it, along with
BUILD_FORTRAN_WRAPPER and its references in the top-level CMakeLists,
library/CMakeLists.txt, test/CMakeLists.txt, cmake/Summary.cmake,
cmake/Dependencies.cmake and docs/install/build.rst.

That API was deprecated in favour of hipfort in rocRAND 4.0.0 / ROCm 7.0 and has
never been shipped enabled: ROCm builds with BUILD_FORTRAN_WRAPPER=OFF, so in an
installed /opt/rocm rocrand_FORTRAN_FOUND is NOTFOUND, rocrand_FORTRAN_SRC_DIRS
is never set, and rocrand/src/fortran does not exist. No consumer of a ROCm
package can therefore be using it; only a source build that passed the flag.

Removing it also frees two names the generated bindings want. The target
rocrand_fortran was defined by both, which is a hard CMake error. More
importantly lib/cmake/rocrand/rocrand-fortran-config.cmake belonged to the
wrapper, and rocrand-config.cmake include()s that name unconditionally, so the
new package could not have been co-installed beside the C one while the wrapper
stood. With the wrapper gone, rocRAND uses the same layout as the rest of the
series: the real config in lib/cmake/rocrand, a forwarder in
lib/cmake/rocrand-fortran, and rocrand_FORTRAN_FOUND back to its ordinary
meaning.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. ROCRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name.

The bindings hook sits outside the USE_SYSTEM_LIB branch: that branch controls
whether librocrand is built here, and the bindings need it linked, not built.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
ROCRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. The comparison is done by length and substring rather
than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Note that rocm_export_targets' INCLUDE argument is not a substitute for the
OPTIONAL sibling include the config comment describes: it emits a bare,
non-OPTIONAL include(), and emits it before the targets file, so a Fortran
config reached that way would run before roc::rocrand exists. That hook belongs
in rocm-cmake.

Tests
-----
24 tests under CTest, off by default, replacing the FRUIT suite. Twenty-three
are runtime tests, one per (generator, distribution) pair, that allocate and
copy device memory around each rocRAND call, so they write `use hip` and need
the HIP Fortran binding at compile time; they are skipped with a named message
when it is absent.

test_rocrand.F03, the exhaustive symbol test, uses only iso_c_binding and
rocrand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against librocrand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

rocrand.F90 is generated from the rocRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocrand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the rocrandCheck status helper. A consumer writes one
`use rocrand` and links roc::rocrand_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written wrapper
---------------------------------
library/src/fortran (rocrand_m.f90, hip_m.f90), its config template, and the
FRUIT-based suite under test/fortran go with it, along with
BUILD_FORTRAN_WRAPPER and its references in the top-level CMakeLists,
library/CMakeLists.txt, test/CMakeLists.txt, cmake/Summary.cmake,
cmake/Dependencies.cmake and docs/install/build.rst.

That API was deprecated in favour of hipfort in rocRAND 4.0.0 / ROCm 7.0 and has
never been shipped enabled: ROCm builds with BUILD_FORTRAN_WRAPPER=OFF, so in an
installed /opt/rocm rocrand_FORTRAN_FOUND is NOTFOUND, rocrand_FORTRAN_SRC_DIRS
is never set, and rocrand/src/fortran does not exist. No consumer of a ROCm
package can therefore be using it; only a source build that passed the flag.

Removing it also frees two names the generated bindings want. The target
rocrand_fortran was defined by both, which is a hard CMake error. More
importantly lib/cmake/rocrand/rocrand-fortran-config.cmake belonged to the
wrapper, and rocrand-config.cmake include()s that name unconditionally, so the
new package could not have been co-installed beside the C one while the wrapper
stood. With the wrapper gone, rocRAND uses the same layout as the rest of the
series: the real config in lib/cmake/rocrand, a forwarder in
lib/cmake/rocrand-fortran, and rocrand_FORTRAN_FOUND back to its ordinary
meaning.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. ROCRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name.

The bindings hook sits outside the USE_SYSTEM_LIB branch: that branch controls
whether librocrand is built here, and the bindings need it linked, not built.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
ROCRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. The comparison is done by length and substring rather
than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Note that rocm_export_targets' INCLUDE argument is not a substitute for the
OPTIONAL sibling include the config comment describes: it emits a bare,
non-OPTIONAL include(), and emits it before the targets file, so a Fortran
config reached that way would run before roc::rocrand exists. That hook belongs
in rocm-cmake.

Tests
-----
24 tests under CTest, off by default, replacing the FRUIT suite. Twenty-three
are runtime tests, one per (generator, distribution) pair, that allocate and
copy device memory around each rocRAND call, so they write `use hip` and need
the HIP Fortran binding at compile time; they are skipped with a named message
when it is absent.

test_rocrand.F03, the exhaustive symbol test, uses only iso_c_binding and
rocrand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against librocrand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

rocrand.F90 is generated from the rocRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocrand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the rocrandCheck status helper. A consumer writes one
`use rocrand` and links roc::rocrand_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written wrapper
---------------------------------
library/src/fortran (rocrand_m.f90, hip_m.f90), its config template, and the
FRUIT-based suite under test/fortran go with it, along with
BUILD_FORTRAN_WRAPPER and its references in the top-level CMakeLists,
library/CMakeLists.txt, test/CMakeLists.txt, cmake/Summary.cmake,
cmake/Dependencies.cmake and docs/install/build.rst.

That API was deprecated in favour of hipfort in rocRAND 4.0.0 / ROCm 7.0 and has
never been shipped enabled: ROCm builds with BUILD_FORTRAN_WRAPPER=OFF, so in an
installed /opt/rocm rocrand_FORTRAN_FOUND is NOTFOUND, rocrand_FORTRAN_SRC_DIRS
is never set, and rocrand/src/fortran does not exist. No consumer of a ROCm
package can therefore be using it; only a source build that passed the flag.

Removing it also frees two names the generated bindings want. The target
rocrand_fortran was defined by both, which is a hard CMake error. More
importantly lib/cmake/rocrand/rocrand-fortran-config.cmake belonged to the
wrapper, and rocrand-config.cmake include()s that name unconditionally, so the
new package could not have been co-installed beside the C one while the wrapper
stood. With the wrapper gone, rocRAND uses the same layout as the rest of the
series: the real config in lib/cmake/rocrand, a forwarder in
lib/cmake/rocrand-fortran, and rocrand_FORTRAN_FOUND back to its ordinary
meaning.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. ROCRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name.

The bindings hook sits outside the USE_SYSTEM_LIB branch: that branch controls
whether librocrand is built here, and the bindings need it linked, not built.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
ROCRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. The comparison is done by length and substring rather
than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Note that rocm_export_targets' INCLUDE argument is not a substitute for the
OPTIONAL sibling include the config comment describes: it emits a bare,
non-OPTIONAL include(), and emits it before the targets file, so a Fortran
config reached that way would run before roc::rocrand exists. That hook belongs
in rocm-cmake.

Tests
-----
24 tests under CTest, off by default, replacing the FRUIT suite. Twenty-three
are runtime tests, one per (generator, distribution) pair, that allocate and
copy device memory around each rocRAND call, so they write `use hip` and need
the HIP Fortran binding at compile time; they are skipped with a named message
when it is absent.

test_rocrand.F03, the exhaustive symbol test, uses only iso_c_binding and
rocrand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against librocrand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

hiprand.F90 is generated from the hipRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`hiprand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the hiprandCheck status helper. A consumer writes one
`use hiprand` and links hip::hiprand_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for hipRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written wrapper
---------------------------------
library/src/fortran (hiprand_m.f90, hip_m.f90), its config template, and the
FRUIT-based suite under test/fortran go with it, along with
BUILD_FORTRAN_WRAPPER and its references in the top-level CMakeLists,
library/CMakeLists.txt, test/CMakeLists.txt, cmake/Summary.cmake,
cmake/Dependencies.cmake, docs/install/build.rst and testing.md.

That API was deprecated in favour of hipfort in hipRAND 3.0.0 / ROCm 7.0 and has
never been shipped enabled: ROCm builds with BUILD_FORTRAN_WRAPPER=OFF, so in an
installed /opt/rocm hiprand_FORTRAN_FOUND is NOTFOUND, hiprand_FORTRAN_SRC_DIRS
is never set, and hiprand/src/fortran does not exist. No consumer of a ROCm
package can therefore be using it; only a source build that passed the flag.

Removing it frees the target name hiprand_fortran, which both defined and which
is a hard CMake error.

Why the config package still stands alone
-----------------------------------------
It does NOT free lib/cmake/hiprand/hiprand-fortran-config.cmake, and that is the
one place rocRAND and hipRAND diverge from the rest of the series.

Removing the wrapper frees that name in this source tree, but not in prefixes
that are already installed. Every ROCm shipped so far has a hiprand-config.cmake
whose line 94 is a bare, unguarded include() of a sibling by that exact name.
Installing this package's config there hands that include a file that calls
find_dependency(hiprand), which re-enters hiprand-config.cmake, which includes
the Fortran config again -- unbounded recursion until CMake gives up. That is
precisely the documented standalone path: build the binding yourself and install
it into an existing /opt/rocm, which is what anyone whose compiler is not the
shipped amdflang has to do.

So the package installs only into lib/cmake/hiprand-fortran, where
find_package(hiprand-fortran) resolves it directly and no forwarder is needed.
When rocm-cmake grows an OPTIONAL end-of-config hook and no supported ROCm still
carries the old unguarded include, this can join the shared layout.

A config-version file is installed alongside, so find_package(hiprand-fortran
3.4) resolves. Its version is parsed from this tree's own VERSION_STRING, not
from hiprand_VERSION: that variable is set by the find_package(hiprand) this
directory does for its link interface, so it would report whatever hipRAND
happens to be installed rather than the headers the bindings were generated
from. When the version cannot be determined, no file is written at all, because
a version file claiming the wrong number is worse than none.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. HIPRAND_HAVE_FORTRAN_BINDINGS reports whether they were built.

BUILD_FORTRAN_BINDINGS is declared at the top level as well as in fortran/,
because print_configuration_summary() runs before add_subdirectory(fortran) and
would otherwise report an empty value.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the name derived
from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name, which
survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. A site installing two versions of one compiler overrides
HIPRAND_FORTRAN_COMPILER_DIR; the config accepts the derived name or that name
followed by a separator and anything, compared by length and substring rather
than by regex, since the derived name can be an arbitrary file name.

Tests
-----
24 tests under CTest, off by default, replacing the FRUIT suite. Twenty-three
are runtime tests, one per (generator, distribution) pair, that allocate and
copy device memory around each hipRAND call, so they write `use hip` and need
the HIP Fortran binding at compile time; they are skipped with a named message
when it is absent.

test_hiprand.F03, the exhaustive symbol test, uses only iso_c_binding and
hiprand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. ROCm ships no HIP Fortran binding, so guarding the
whole directory would mean zero tests against a stock /opt/rocm, including the
only one that proves every bind(C) symbol resolves against libhiprand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
JIRA ID : ROCM-31390

rocrand.F90 is generated from the rocRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocrand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the rocrandCheck status helper. A consumer writes one
`use rocrand` and links roc::rocrand_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written wrapper
---------------------------------
library/src/fortran (rocrand_m.f90, hip_m.f90), its config template, and the
FRUIT-based suite under test/fortran go with it, along with
BUILD_FORTRAN_WRAPPER and its references in the top-level CMakeLists,
library/CMakeLists.txt, test/CMakeLists.txt, cmake/Summary.cmake,
cmake/Dependencies.cmake and docs/install/build.rst.

That API was deprecated in favour of hipfort in rocRAND 4.0.0 / ROCm 7.0 and has
never been shipped enabled: ROCm builds with BUILD_FORTRAN_WRAPPER=OFF, so in an
installed /opt/rocm rocrand_FORTRAN_FOUND is NOTFOUND, rocrand_FORTRAN_SRC_DIRS
is never set, and rocrand/src/fortran does not exist. No consumer of a ROCm
package can therefore be using it; only a source build that passed the flag.

Removing it also frees two names the generated bindings want. The target
rocrand_fortran was defined by both, which is a hard CMake error. More
importantly lib/cmake/rocrand/rocrand-fortran-config.cmake belonged to the
wrapper, and rocrand-config.cmake include()s that name unconditionally, so the
new package could not have been co-installed beside the C one while the wrapper
stood. With the wrapper gone, rocRAND uses the same layout as the rest of the
series: the real config in lib/cmake/rocrand, a forwarder in
lib/cmake/rocrand-fortran, and rocrand_FORTRAN_FOUND back to its ordinary
meaning.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. ROCRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name.

The bindings hook sits outside the USE_SYSTEM_LIB branch: that branch controls
whether librocrand is built here, and the bindings need it linked, not built.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
ROCRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. The comparison is done by length and substring rather
than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Note that rocm_export_targets' INCLUDE argument is not a substitute for the
OPTIONAL sibling include the config comment describes: it emits a bare,
non-OPTIONAL include(), and emits it before the targets file, so a Fortran
config reached that way would run before roc::rocrand exists. That hook belongs
in rocm-cmake.

Tests
-----
24 tests under CTest, off by default, replacing the FRUIT suite. Twenty-three
are runtime tests, one per (generator, distribution) pair, that allocate and
copy device memory around each rocRAND call, so they write `use hip` and need
the HIP Fortran binding at compile time; they are skipped with a named message
when it is absent.

test_rocrand.F03, the exhaustive symbol test, uses only iso_c_binding and
rocrand, so it is registered outside that guard, behind
BUILD_FORTRAN_EXTENDED_TESTS. That distinction is load bearing: ROCm does not
currently ship a HIP Fortran binding, so guarding the whole directory would mean
zero tests against a stock /opt/rocm, including the only one that proves every
bind(C) symbol resolves against librocrand.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
…rated one

JIRA ID : ROCM-31390

rocsparse.F90 is generated from the rocSPARSE public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocsparse`, carrying the interfaces, the enum constants, the opaque handles and
the rocsparseCheck status helper. A consumer writes one `use rocsparse` and
links roc::rocsparse_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocSPARSE, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written binding
---------------------------------
library/src/rocsparse.f90 and library/src/rocsparse_enums.f90 are removed, along
with the rocm_install(FILES ...) rule that shipped them into include/rocsparse.
Unlike rocRAND's wrapper, this one WAS shipped and built by default, so the
removal is user visible: the module keeps the name `rocsparse`, but the separate
`rocsparse_enums` module is gone -- its constants are part of `rocsparse` --
and consumers get a compiled archive and .mod rather than .f90 sources to build
themselves.

clients no longer compiles its own rocsparse_fortran object library from those
sources; it consumes the one ../fortran exports. Both carried the same target
name, so this also removes a latent duplicate-target clash. All fourteen
existing Fortran samples compile unmodified against the generated module.

The add_subdirectory(fortran) hook moves out of the BUILD_CLIENTS_ONLY branch.
That is a bug fix, not tidying: clients now require the rocsparse_fortran target
and BUILD_FORTRAN_CLIENTS defaults to ON, so -DBUILD_CLIENTS_ONLY=ON skipped the
directory and then stopped in clients with "the rocsparse_fortran target is
missing".

Linking against an older rocSPARSE
----------------------------------
The archive is built with -ffunction-sections -fdata-sections and exports
--gc-sections to its consumers. This is not a size optimisation: the module is
generated from THIS tree's headers, so it wraps API no released ROCm has yet
(rocsparse_dnvec_descr_create_scalar, rocsparse_ell_set_strided_batch,
rocsparse_spmat_scale today). A static archive links at object granularity, so
pulling in one wrapper pulls in every undefined C symbol the object references.
Without section GC a consumer who never touches the new API still fails to link,
with 25 undefined references to functions they have never heard of; with it, the
unreferenced wrappers are discarded and the link succeeds.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCSPARSE_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. ROCSPARSE_HAVE_FORTRAN_BINDINGS reports whether they were built.

The compiler probe is read from ROCM_HAVE_FORTRAN, with ROCM_LIBS_HAVE_FORTRAN
honoured second as the spelling this repository's root publishes today.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name,
which survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. A site installing two versions of one compiler overrides
ROCSPARSE_FORTRAN_COMPILER_DIR; the config accepts the derived name or that name
followed by a separator and anything, compared by length and substring rather
than by regex, since the derived name can be an arbitrary file name.

This uses the SHARED layout: the real config is co-installed in
lib/cmake/rocsparse beside the C package, with a forwarder in
lib/cmake/rocsparse-fortran. rocRAND and hipRAND cannot do this because their
shipped <lib>-config.cmake carries a bare unguarded include() of a sibling
<lib>-fortran-config.cmake and a file there would recurse; rocsparse-config.cmake
has no such include, checked against an installed ROCm.

A config-version file is installed alongside, its version parsed from this tree's
VERSION_STRING rather than from rocsparse_VERSION -- that variable is set by the
find_package(rocsparse) this directory does for its link interface, so it would
report whatever rocSPARSE happens to be installed.

Tests
-----
58 tests under CTest, off by default: 57 runtime tests carried over from hipFORT,
which allocate and copy device memory and so need the HIP Fortran binding at
compile time, plus test_rocsparse.F03, the exhaustive symbol test, which uses
only iso_c_binding and rocsparse and is registered outside that guard behind
BUILD_FORTRAN_EXTENDED_TESTS.

The csrgeam and csrgemm tests, all four precisions of each, are listed but
commented out because they segfault, with the analysis recorded next to them.
The cause is in the tests: both families select what they compute from whether
alpha and beta are NULL POINTERS rather than from their values, and these tests
pass beta = 0.0_c_double, a valid pointer, while passing c_null_ptr for descr_D
and every D array, so rocSPARSE looks for a D term that is not there. The
binding can express the NULL -- it carries a _dptr specific taking
type(c_ptr),value :: alpha,beta -- so fixing them is a follow-up, not a change
to the binding.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
…rated one

JIRA ID : ROCM-31390

rocsparse.F90 is generated from the rocSPARSE public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocsparse`, carrying the interfaces, the enum constants, the opaque handles and
the rocsparseCheck status helper. A consumer writes one `use rocsparse` and
links roc::rocsparse_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocSPARSE, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written binding
---------------------------------
library/src/rocsparse.f90 and library/src/rocsparse_enums.f90 are removed, along
with the rocm_install(FILES ...) rule that shipped them into include/rocsparse.
Unlike rocRAND's wrapper, this one WAS shipped and built by default, so the
removal is user visible: the module keeps the name `rocsparse`, but the separate
`rocsparse_enums` module is gone -- its constants are part of `rocsparse` --
and consumers get a compiled archive and .mod rather than .f90 sources to build
themselves.

clients no longer compiles its own rocsparse_fortran object library from those
sources; it consumes the one ../fortran exports. Both carried the same target
name, so this also removes a latent duplicate-target clash. All fourteen
existing Fortran samples compile unmodified against the generated module.

The add_subdirectory(fortran) hook moves out of the BUILD_CLIENTS_ONLY branch.
That is a bug fix, not tidying: clients now require the rocsparse_fortran target
and BUILD_FORTRAN_CLIENTS defaults to ON, so -DBUILD_CLIENTS_ONLY=ON skipped the
directory and then stopped in clients with "the rocsparse_fortran target is
missing".

Linking against an older rocSPARSE
----------------------------------
The archive is built with -ffunction-sections -fdata-sections and exports
--gc-sections to its consumers. This is not a size optimisation: the module is
generated from THIS tree's headers, so it wraps API no released ROCm has yet
(rocsparse_dnvec_descr_create_scalar, rocsparse_ell_set_strided_batch,
rocsparse_spmat_scale today). A static archive links at object granularity, so
pulling in one wrapper pulls in every undefined C symbol the object references.
Without section GC a consumer who never touches the new API still fails to link,
with 25 undefined references to functions they have never heard of; with it, the
unreferenced wrappers are discarded and the link succeeds.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCSPARSE_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. ROCSPARSE_HAVE_FORTRAN_BINDINGS reports whether they were built.

The compiler probe is read from ROCM_HAVE_FORTRAN, with ROCM_LIBS_HAVE_FORTRAN
honoured second as the spelling this repository's root publishes today.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name,
which survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. A site installing two versions of one compiler overrides
ROCSPARSE_FORTRAN_COMPILER_DIR; the config accepts the derived name or that name
followed by a separator and anything, compared by length and substring rather
than by regex, since the derived name can be an arbitrary file name.

This uses the SHARED layout: the real config is co-installed in
lib/cmake/rocsparse beside the C package, with a forwarder in
lib/cmake/rocsparse-fortran. rocRAND and hipRAND cannot do this because their
shipped <lib>-config.cmake carries a bare unguarded include() of a sibling
<lib>-fortran-config.cmake and a file there would recurse; rocsparse-config.cmake
has no such include, checked against an installed ROCm.

A config-version file is installed alongside, its version parsed from this tree's
VERSION_STRING rather than from rocsparse_VERSION -- that variable is set by the
find_package(rocsparse) this directory does for its link interface, so it would
report whatever rocSPARSE happens to be installed.

Tests
-----
58 tests under CTest, off by default: 57 runtime tests carried over from hipFORT,
which allocate and copy device memory and so need the HIP Fortran binding at
compile time, plus test_rocsparse.F03, the exhaustive symbol test, which uses
only iso_c_binding and rocsparse and is registered outside that guard behind
BUILD_FORTRAN_EXTENDED_TESTS.

The csrgeam and csrgemm tests, all four precisions of each, are listed but
commented out because they segfault, with the analysis recorded next to them.
The cause is in the tests: both families select what they compute from whether
alpha and beta are NULL POINTERS rather than from their values, and these tests
pass beta = 0.0_c_double, a valid pointer, while passing c_null_ptr for descr_D
and every D array, so rocSPARSE looks for a D term that is not there. The
binding can express the NULL -- it carries a _dptr specific taking
type(c_ptr),value :: alpha,beta -- so fixing them is a follow-up, not a change
to the binding.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 24, 2026
…ted one

JIRA ID : ROCM-31390

rocblas.F90 is generated from the rocBLAS public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocblas`, carrying the interfaces, the enum constants, the opaque handles and
the rocblasCheck status helper. A consumer writes one `use rocblas` and links
roc::rocblas_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocBLAS, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written binding
---------------------------------
library/include/rocblas_module.f90 is removed, along with the rocm_install()
rule that shipped it into include/rocblas. It defined TWO modules, rocblas and
rocblas_enums; the generated binding defines only rocblas, with the enum
constants folded in. `use rocblas` is unchanged, but `use rocblas_enums` becomes
`use rocblas`, which is applied here to the clients' shims and samples.
Consumers get a compiled archive and .mod rather than a .f90 source to build
themselves.

clients no longer compiles its own rocblas_fortran object library from that
source; rocblas_fortran_client links the target ../fortran exports. Both carried
the same name, so this also removes a latent duplicate-target clash.
next-cmake, which built its own rocblas-fortran-module from the same file, now
builds the generated source instead.

The add_subdirectory(fortran) hook moves out of the SKIP_LIBRARY guard: that
guard decides whether librocblas is built here, and the bindings need it linked,
not built. With clients now consuming the target rather than building their own,
inheriting the skip would leave BUILD_FORTRAN_CLIENTS with no rocblas_fortran.

Linking against an older rocBLAS
--------------------------------
The archive is built with -ffunction-sections -fdata-sections and exports
--gc-sections to its consumers. The module is generated from THIS tree's
headers, so it wraps API no released ROCm has yet -- the six
rocblas_*gemm_grouped_batched entry points today. A static archive links at
object granularity, so pulling in one wrapper pulls in every undefined C symbol
the object references, and a consumer who never touches the new API would still
fail to link. With section GC the unreferenced wrappers are discarded.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCBLAS_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. ROCBLAS_HAVE_FORTRAN_BINDINGS reports whether they were built.

The compiler probe is read from ROCM_HAVE_FORTRAN, with ROCM_LIBS_HAVE_FORTRAN
honoured second as the spelling this repository's root publishes today.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name,
which survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. A site installing two versions of one compiler overrides
ROCBLAS_FORTRAN_COMPILER_DIR; the config accepts the derived name or that name
followed by a separator and anything, compared by length and substring rather
than by regex.

This uses the shared layout: the real config is co-installed in lib/cmake/rocblas
beside the C package, with a forwarder in lib/cmake/rocblas-fortran.
rocblas-config.cmake carries no Fortran include, so the recursion hazard that
keeps rocRAND and hipRAND in a directory of their own does not apply here.

The config-version file is installed into BOTH package directories. CMake looks
for it next to the <pkg>-config.cmake it actually resolved, and
find_package(rocblas-fortran 5.8) resolves the forwarder, so a version file only
beside the real config is never consulted and the call fails even though the
version matches. Its version is parsed from this tree's VERSION_STRING rather
than from rocblas_VERSION, which is set by the find_package(rocblas) this
directory does for its link interface and would report whatever rocBLAS happens
to be installed.

Tests
-----
81 tests under CTest, off by default: 80 runtime tests carried over from hipFORT,
which allocate and copy device memory and so need the HIP Fortran binding at
compile time, plus test_rocblas.F03, the exhaustive symbol test, which uses only
iso_c_binding and rocblas and is registered outside that guard behind
BUILD_FORTRAN_EXTENDED_TESTS.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
…rated one

JIRA ID : ROCM-31390

hipsparse.F90 is generated from the hipSPARSE public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`hipsparse`, carrying the interfaces, the enum constants, the opaque handles and
the hipsparseCheck status helper. A consumer writes one `use hipsparse` and
links roc::hipsparse_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for hipSPARSE, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written module
--------------------------------
library/src/hipsparse.f90 and hipsparse_enums.f90 are removed, along with the
hipsparse_fortran OBJECT target in library/CMakeLists.txt that compiled them.
That target carried the SAME NAME as the one this directory creates, so with
-DHIPSPARSE_ENABLE_CLIENT=ON the two collided outright:

    CMake Error at fortran/CMakeLists.txt (add_library):
      add_library cannot create target "hipsparse_fortran" because another
      target with the same name already exists

CI never saw it because HIPSPARSE_ENABLE_FORTRAN is declared inside
if(HIPSPARSE_ENABLE_CLIENT), which defaults OFF. The Fortran samples now link
roc::hipsparse_fortran, which carries both the .mod directory and the archive,
and HIPSPARSE_ENABLE_FORTRAN is turned off with a message when the bindings were
not built, so -DHIPSPARSE_ENABLE_CLIENT=ON still works without a Fortran
compiler.

Host and device pointer mode
----------------------------
The generated binding follows hipFORT and binds a `const T*` scalar as a
by-reference `real(c_double) :: alpha`. The removed module bound the same
argument as `type(c_ptr), value`, so every sample passes `c_loc(alpha)`. Both
are ABI-correct, but only the second can express
HIPSPARSE_POINTER_MODE_DEVICE, where the library reads alpha from device
memory: a type(c_ptr) cannot be passed where a real is expected.
example_fortran_spmv.f90 does exactly that, passing a hipMalloc'd d_alpha to
hipsparseDbsrmv.

So 25 generics gained a second specific taking those scalars as
type(c_ptr),value and forwarding through c_f_pointer, which only records the
address and never dereferences it on the host. Six zeroPivot routines were plain
functions rather than generics and became generics to carry both; their own
documentation states that `position` can be in host OR device memory. No sample
and no test was modified: all 32 samples and all 49 tests build and pass against
the binding as committed.

This is a local fix in a GENERATED file, kept narrow deliberately. The ~700
other scalar arguments in hipSPARSE, and the same arguments in rocBLAS,
hipBLAS, rocSPARSE and rocSOLVER, still cannot express device pointer mode. The
durable fix belongs in the generator and will have to re-emit these variants.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPSPARSE_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape). HIPSPARSE_HAVE_FORTRAN_BINDINGS reports whether the
bindings were really built. The compiler probe reads ROCM_HAVE_FORTRAN, with
ROCM_LIBS_HAVE_FORTRAN honoured second.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name.
The config picks the consumer's own compiler when its .mod is installed, so a
prefix holding several compilers' artifacts resolves without an override, and
repoints the imported target accordingly.

The real config is co-installed in lib/cmake/hipsparse beside the C package,
with a forwarder in lib/cmake/hipsparse-fortran. The config-version file goes
into both directories, because CMake looks for it next to the config it actually
resolved and the versioned spelling resolves the forwarder. Its version is
parsed from this tree's project(hipsparse VERSION ...) rather than from
hipsparse_VERSION, which the find_package(hipsparse) this directory does for its
link interface would set to the installed version.

The generated hipsparse.F90 installs to share/hipsparse/fortran, so a user on a
compiler with no shipped .mod can rebuild the binding without cloning a monorepo
to get one file.

Tests
-----
49 tests under CTest, off by default: the runtime tests carried over from
hipFORT, which allocate and copy device memory and so need the HIP Fortran
binding at compile time, and are skipped with a named message when it is
absent. They are labelled gpu, so ctest -LE gpu stays meaningful on a machine
without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
…ted one

JIRA ID : ROCM-31390

hipblas.F90 is generated from the hipBLAS public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`hipblas`, carrying the interfaces, the enum constants, the opaque handles and
the hipblasCheck status helper. A consumer writes one `use hipblas` and links
roc::hipblas_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for hipBLAS, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923, and mirroring rocBLAS.

Removing the hand-written binding
---------------------------------
library/src/hipblas_module.f90 is removed, along with the rocm_install() rule
that shipped it into include/hipblas. It defined TWO modules, hipblas and
hipblas_enums; the generated binding defines only hipblas, with the hipBLAS enum
constants folded in. `use hipblas` is unchanged, `use hipblas_enums` becomes
`use hipblas`, applied here across 1197 sites in the clients.

clients no longer compiles its own hipblas_fortran object library from that
source; hipblas_fortran_client links the target ../fortran exports. Both carried
the same name, so this also removes a latent duplicate-target clash. The
BUILD_WITH_SOLVER split is preserved. Because hipBLAS's consumers absorb
$<TARGET_OBJECTS:hipblas_fortran_client> rather than linking it, and that
carries neither the archive nor the .mod include directory, the Fortran samples
and rocblas-bench now link hipblas_fortran_client explicitly.

The hipDataType enumerators, and why a stub ships temporarily
-------------------------------------------------------------
hipblas_enums also re-exported HIP's hipDataType enumerators. The generated
module does not: a hipDataType belongs to HIP, and the generated interfaces type
those arguments as plain integer(c_int). That is correct, but it leaves the
client shims -- which declare their datatype arguments as
integer(kind(HIP_R_16F)) -- with no source for the name. 57 scopes across
clients/include/hipblas_fortran_blas{,_64}.f90 are affected, and they now say
`use hip`.

ROCm ships no HIP Fortran binding yet, so fortran/hip_datatypes_stub.F90
provides one, carrying only the sixteen enumerators those scopes reference, with
values copied verbatim from the HIP binding. It is compiled into
hipblas_fortran_client and is NOT installed, exported or packaged, so no second
hip.mod can reach an installed prefix and collide with the real binding.

It is meant to be deleted. When ROCm/rocm-systems#11923 lands: drop the stub
from the source list and from fortran/, then find_package(hip-fortran) and link
hip::hip_fortran. The `use hip` lines do not change -- they start resolving to
the real module, which declares the same enumerators with the same values, so
the swap is observably a no-op.

Note that a hipBLAS USER calling hipblasGemmEx needs those values too, and the
stub does not help them since it is not installed. Until the HIP binding ships
they need `use hip` from a HIP binding of their own. hipSPARSE has the same gap.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable through HIPBLAS_BUILD_FORTRAN_*. FORTRAN_ARRAY_INTERFACES is a
tri-state (none / assumed-shape / assumed-rank, default assumed-shape).

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The shared layout
is used: the real config in lib/cmake/hipblas beside the C package, a forwarder
in lib/cmake/hipblas-fortran.

The config-version file is installed into BOTH package directories, because
CMake looks for it next to the <pkg>-config.cmake it actually resolved and
find_package(hipblas-fortran 3.8) resolves the forwarder. Its version is parsed
from this tree's VERSION_STRING rather than from hipblas_VERSION, which the
find_package(hipblas) this directory does for its link interface would set to
the installed version.

Section GC (-ffunction-sections, --gc-sections) is carried over from rocBLAS.
hipBLAS needs none of it today -- every symbol the module references is present
in the installed libhipblas -- because this binding currently lags the headers
rather than running ahead of them. It is kept so the next regeneration that
picks up a new entry point does not reintroduce undefined references in
downstream builds.

Tests
-----
69 tests under CTest, off by default: 68 runtime tests from hipFORT plus
test_hipblas.F03, the exhaustive symbol test, registered outside the
hip::hip_fortran guard behind BUILD_FORTRAN_EXTENDED_TESTS.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
JIRA ID : ROCM-31390

hiprand.F90 is generated from the hipRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`hiprand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the hiprandCheck status helper. A consumer writes one
`use hiprand` and links hip::hiprand_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for hipRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written wrapper
---------------------------------
library/src/fortran (hiprand_m.f90, hip_m.f90), its config template, and the
FRUIT-based suite under test/fortran go with it, along with
BUILD_FORTRAN_WRAPPER and its references in the top-level CMakeLists,
library/CMakeLists.txt, test/CMakeLists.txt, cmake/Summary.cmake,
cmake/Dependencies.cmake, docs/install/build.rst and testing.md.

That API was deprecated in favour of hipfort in hipRAND 3.0.0 / ROCm 7.0 and has
never been shipped enabled: ROCm builds with BUILD_FORTRAN_WRAPPER=OFF, so in an
installed /opt/rocm hiprand_FORTRAN_FOUND is NOTFOUND, hiprand_FORTRAN_SRC_DIRS
is never set, and hiprand/src/fortran does not exist. No consumer of a ROCm
package can therefore be using it; only a source build that passed the flag.

Removing it frees the target name hiprand_fortran, which both defined and which
is a hard CMake error.

Why the config package still stands alone
-----------------------------------------
It does NOT free lib/cmake/hiprand/hiprand-fortran-config.cmake, and that is the
one place rocRAND and hipRAND diverge from the rest of the series.

Removing the wrapper frees that name in this source tree, but not in prefixes
that are already installed. Every ROCm shipped so far has a hiprand-config.cmake
whose line 94 is a bare, unguarded include() of a sibling by that exact name.
Installing this package's config there hands that include a file that calls
find_dependency(hiprand), which re-enters hiprand-config.cmake, which includes
the Fortran config again -- unbounded recursion until CMake gives up. That is
precisely the documented standalone path: build the binding yourself and install
it into an existing /opt/rocm, which is what anyone whose compiler is not the
shipped amdflang has to do.

So the package installs only into lib/cmake/hiprand-fortran, where
find_package(hiprand-fortran) resolves it directly and no forwarder is needed.
When rocm-cmake grows an OPTIONAL end-of-config hook and no supported ROCm still
carries the old unguarded include, this can join the shared layout.

A config-version file is installed alongside, so find_package(hiprand-fortran
3.4) resolves. Its version is parsed from this tree's own VERSION_STRING, not
from hiprand_VERSION: that variable is set by the find_package(hiprand) this
directory does for its link interface, so it would report whatever hipRAND
happens to be installed rather than the headers the bindings were generated
from. When the version cannot be determined, no file is written at all, because
a version file claiming the wrong number is worse than none.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. HIPRAND_HAVE_FORTRAN_BINDINGS reports whether they were built.

BUILD_FORTRAN_BINDINGS is declared at the top level as well as in fortran/,
because print_configuration_summary() runs before add_subdirectory(fortran) and
would otherwise report an empty value.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the name derived
from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name, which
survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. A site installing two versions of one compiler overrides
HIPRAND_FORTRAN_COMPILER_DIR; the config accepts the derived name or that name
followed by a separator and anything, compared by length and substring rather
than by regex, since the derived name can be an arbitrary file name.

Tests
-----
23 tests under CTest, off by default, replacing the FRUIT suite. One per
(generator, distribution) pair, each allocating and copying device memory
around its hipRAND call, so they write `use hip` and need the HIP Fortran
binding at compile time; they are skipped with a named message when it is
absent.

They are labelled gpu, so ctest -LE gpu stays meaningful on a machine without
one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
…ted one

JIRA ID : ROCM-31390

rocblas.F90 is generated from the rocBLAS public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocblas`, carrying the interfaces, the enum constants, the opaque handles and
the rocblasCheck status helper. A consumer writes one `use rocblas` and links
roc::rocblas_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocBLAS, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written binding
---------------------------------
library/include/rocblas_module.f90 is removed, along with the rocm_install()
rule that shipped it into include/rocblas. It defined TWO modules, rocblas and
rocblas_enums; the generated binding defines only rocblas, with the enum
constants folded in. `use rocblas` is unchanged, but `use rocblas_enums` becomes
`use rocblas`, which is applied here to the clients' shims and samples.
Consumers get a compiled archive and .mod rather than a .f90 source to build
themselves.

clients no longer compiles its own rocblas_fortran object library from that
source; rocblas_fortran_client links the target ../fortran exports. Both carried
the same name, so this also removes a latent duplicate-target clash.
next-cmake, which built its own rocblas-fortran-module from the same file, now
builds the generated source instead.

The add_subdirectory(fortran) hook moves out of the SKIP_LIBRARY guard: that
guard decides whether librocblas is built here, and the bindings need it linked,
not built. With clients now consuming the target rather than building their own,
inheriting the skip would leave BUILD_FORTRAN_CLIENTS with no rocblas_fortran.

Linking against an older rocBLAS
--------------------------------
The archive is built with -ffunction-sections -fdata-sections and exports
--gc-sections to its consumers. The module is generated from THIS tree's
headers, so it wraps API no released ROCm has yet -- the six
rocblas_*gemm_grouped_batched entry points today. A static archive links at
object granularity, so pulling in one wrapper pulls in every undefined C symbol
the object references, and a consumer who never touches the new API would still
fail to link. With section GC the unreferenced wrappers are discarded.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCBLAS_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. ROCBLAS_HAVE_FORTRAN_BINDINGS reports whether they were built.

The compiler probe is read from ROCM_HAVE_FORTRAN, with ROCM_LIBS_HAVE_FORTRAN
honoured second as the spelling this repository's root publishes today.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name,
which survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. A site installing two versions of one compiler overrides
ROCBLAS_FORTRAN_COMPILER_DIR; the config accepts the derived name or that name
followed by a separator and anything, compared by length and substring rather
than by regex.

This uses the shared layout: the real config is co-installed in lib/cmake/rocblas
beside the C package, with a forwarder in lib/cmake/rocblas-fortran.
rocblas-config.cmake carries no Fortran include, so the recursion hazard that
keeps rocRAND and hipRAND in a directory of their own does not apply here.

The config-version file is installed into BOTH package directories. CMake looks
for it next to the <pkg>-config.cmake it actually resolved, and
find_package(rocblas-fortran 5.8) resolves the forwarder, so a version file only
beside the real config is never consulted and the call fails even though the
version matches. Its version is parsed from this tree's VERSION_STRING rather
than from rocblas_VERSION, which is set by the find_package(rocblas) this
directory does for its link interface and would report whatever rocBLAS happens
to be installed.

Tests
-----
80 tests under CTest, off by default: the runtime tests carried over from
hipFORT, which allocate and copy device memory and so need the HIP Fortran
binding at compile time, and are skipped with a named message when it is
absent. They are labelled gpu, so ctest -LE gpu stays meaningful on a machine
without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
JIRA ID : ROCM-31390

rocrand.F90 is generated from the rocRAND public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocrand`, carrying the interfaces, the enum constants, the derived types, the
opaque handles and the rocrandCheck status helper. A consumer writes one
`use rocrand` and links roc::rocrand_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocRAND, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written wrapper
---------------------------------
library/src/fortran (rocrand_m.f90, hip_m.f90), its config template, and the
FRUIT-based suite under test/fortran go with it, along with
BUILD_FORTRAN_WRAPPER and its references in the top-level CMakeLists,
library/CMakeLists.txt, test/CMakeLists.txt, cmake/Summary.cmake,
cmake/Dependencies.cmake and docs/install/build.rst.

That API was deprecated in favour of hipfort in rocRAND 4.0.0 / ROCm 7.0 and has
never been shipped enabled: ROCm builds with BUILD_FORTRAN_WRAPPER=OFF, so in an
installed /opt/rocm rocrand_FORTRAN_FOUND is NOTFOUND, rocrand_FORTRAN_SRC_DIRS
is never set, and rocrand/src/fortran does not exist. No consumer of a ROCm
package can therefore be using it; only a source build that passed the flag.

Removing it also frees two names the generated bindings want. The target
rocrand_fortran was defined by both, which is a hard CMake error. More
importantly lib/cmake/rocrand/rocrand-fortran-config.cmake belonged to the
wrapper, and rocrand-config.cmake include()s that name unconditionally, so the
new package could not have been co-installed beside the C one while the wrapper
stood. With the wrapper gone, rocRAND uses the same layout as the rest of the
series: the real config in lib/cmake/rocrand, a forwarder in
lib/cmake/rocrand-fortran, and rocrand_FORTRAN_FOUND back to its ordinary
meaning.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCRAND_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic, because
an assumed-rank dummy is not distinguishable by rank from the per-rank
specifics. ROCRAND_HAVE_FORTRAN_BINDINGS reports whether they were really built.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on across
both monorepos. This repository's root publishes ROCM_LIBS_HAVE_FORTRAN today,
so that spelling is honoured second, never over the new name.

The bindings hook sits outside the USE_SYSTEM_LIB branch: that branch controls
whether librocrand is built here, and the bindings need it linked, not built.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper.

A site installing two versions of one compiler side by side overrides
ROCRAND_FORTRAN_COMPILER_DIR with a suffixed name, so the config package accepts
the recorded directory when it is the derived name OR that name followed by a
separator and anything. The comparison is done by length and substring rather
than by regex: the derived name comes from the compiler's basename on the
fallback branch, so it is an arbitrary file name, and interpolating it into a
regex would let a compiler called flang(2) either mismatch silently or abort
CMake outright.

Note that rocm_export_targets' INCLUDE argument is not a substitute for the
OPTIONAL sibling include the config comment describes: it emits a bare,
non-OPTIONAL include(), and emits it before the targets file, so a Fortran
config reached that way would run before roc::rocrand exists. That hook belongs
in rocm-cmake.

Tests
-----
23 tests under CTest, off by default, replacing the FRUIT suite. One per
(generator, distribution) pair, each allocating and copying device memory
around its rocRAND call, so they write `use hip` and need the HIP Fortran
binding at compile time; they are skipped with a named message when it is
absent.

They are labelled gpu, so ctest -LE gpu stays meaningful on a machine without
one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
…rated one

JIRA ID : ROCM-31390

rocsparse.F90 is generated from the rocSPARSE public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`rocsparse`, carrying the interfaces, the enum constants, the opaque handles and
the rocsparseCheck status helper. A consumer writes one `use rocsparse` and
links roc::rocsparse_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocSPARSE, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written binding
---------------------------------
library/src/rocsparse.f90 and library/src/rocsparse_enums.f90 are removed, along
with the rocm_install(FILES ...) rule that shipped them into include/rocsparse.
Unlike rocRAND's wrapper, this one WAS shipped and built by default, so the
removal is user visible: the module keeps the name `rocsparse`, but the separate
`rocsparse_enums` module is gone -- its constants are part of `rocsparse` --
and consumers get a compiled archive and .mod rather than .f90 sources to build
themselves.

clients no longer compiles its own rocsparse_fortran object library from those
sources; it consumes the one ../fortran exports. Both carried the same target
name, so this also removes a latent duplicate-target clash. All fourteen
existing Fortran samples compile unmodified against the generated module.

The add_subdirectory(fortran) hook moves out of the BUILD_CLIENTS_ONLY branch.
That is a bug fix, not tidying: clients now require the rocsparse_fortran target
and BUILD_FORTRAN_CLIENTS defaults to ON, so -DBUILD_CLIENTS_ONLY=ON skipped the
directory and then stopped in clients with "the rocsparse_fortran target is
missing".

Linking against an older rocSPARSE
----------------------------------
The archive is built with -ffunction-sections -fdata-sections and exports
--gc-sections to its consumers. This is not a size optimisation: the module is
generated from THIS tree's headers, so it wraps API no released ROCm has yet
(rocsparse_dnvec_descr_create_scalar, rocsparse_ell_set_strided_batch,
rocsparse_spmat_scale today). A static archive links at object granularity, so
pulling in one wrapper pulls in every undefined C symbol the object references.
Without section GC a consumer who never touches the new API still fails to link,
with 25 undefined references to functions they have never heard of; with it, the
unreferenced wrappers are discarded and the link succeeds.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCSPARSE_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. ROCSPARSE_HAVE_FORTRAN_BINDINGS reports whether they were built.

The compiler probe is read from ROCM_HAVE_FORTRAN, with ROCM_LIBS_HAVE_FORTRAN
honoured second as the spelling this repository's root publishes today.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name,
which survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. A site installing two versions of one compiler overrides
ROCSPARSE_FORTRAN_COMPILER_DIR; the config accepts the derived name or that name
followed by a separator and anything, compared by length and substring rather
than by regex, since the derived name can be an arbitrary file name.

This uses the SHARED layout: the real config is co-installed in
lib/cmake/rocsparse beside the C package, with a forwarder in
lib/cmake/rocsparse-fortran. rocRAND and hipRAND cannot do this because their
shipped <lib>-config.cmake carries a bare unguarded include() of a sibling
<lib>-fortran-config.cmake and a file there would recurse; rocsparse-config.cmake
has no such include, checked against an installed ROCm.

A config-version file is installed alongside, its version parsed from this tree's
VERSION_STRING rather than from rocsparse_VERSION -- that variable is set by the
find_package(rocsparse) this directory does for its link interface, so it would
report whatever rocSPARSE happens to be installed.

Tests
-----
58 tests under CTest, off by default: 57 runtime tests carried over from hipFORT,
which allocate and copy device memory and so need the HIP Fortran binding at
compile time, plus test_rocsparse.F03, the exhaustive symbol test, which uses
only iso_c_binding and rocsparse and is registered outside that guard behind
BUILD_FORTRAN_EXTENDED_TESTS.

The csrgeam and csrgemm tests, all four precisions of each, are listed but
commented out because they segfault, with the analysis recorded next to them.
The cause is in the tests: both families select what they compute from whether
alpha and beta are NULL POINTERS rather than from their values, and these tests
pass beta = 0.0_c_double, a valid pointer, while passing c_null_ptr for descr_D
and every D array, so rocSPARSE looks for a D term that is not there. The
binding can express the NULL -- it carries a _dptr specific taking
type(c_ptr),value :: alpha,beta -- so fixing them is a follow-up, not a change
to the binding.

Runtime tests are labelled gpu and the symbol test symbols, so ctest -LE gpu
stays meaningful on a machine without one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
rocfft.F90 is generated from the rocFFT public headers by the rocm-fortran
generator and committed next to them, so that a header change and its
binding travel in the same pull request. It is a single self-contained
module, `rocfft`, carrying the interfaces, the enum constants, the opaque
handles and the rocfftCheck status helper. A consumer writes one `use rocfft`.

Implements RFC0014 (ROCm/TheRock#8122) for rocFFT, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

The directory is self-contained: a Fortran binding declares bind(C)
interfaces only, so it compiles against neither the rocFFT headers nor
librocfft, and needs no GPU and no HIP compiler to build. librocfft is a
link-time dependency of a final executable and is carried as the target's
link interface. The subdirectory guards itself, returning early when
BUILD_FORTRAN_BINDINGS is OFF or no Fortran compiler is present, so a C-only
site is unaffected.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through ROCFFT_BUILD_FORTRAN_* so one library
can be singled out in a monorepo build. FORTRAN_ARRAY_INTERFACES is a
tri-state (none / assumed-shape / assumed-rank, default assumed-shape)
replacing the two booleans USE_FPOINTER_INTERFACES and ASSUMED_RANK: the two
upper tiers cannot legally coexist in one generic, because an assumed-rank
dummy is not distinguishable by rank from the per-rank specifics.
ROCFFT_HAVE_FORTRAN_BINDINGS reports whether they were really built, and the
config package sets rocfft_FORTRAN_FOUND.

The compiler probe is read from ROCM_HAVE_FORTRAN, which is the name to
settle on across both monorepos. This repository's root publishes
ROCM_LIBS_HAVE_FORTRAN today, so that spelling is honoured second, never over
the new name. It is a bridge with an end: when the root is switched over,
that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, Flang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper, where a
plain basename would not.

The generated source is installed too, as share/rocfft/fortran/rocfft.F90, so
that a user on a compiler ROCm ships no .mod for can rebuild the binding
without cloning a monorepo to get one file, and cannot end up with source
generated from a different ROCm than the librocfft they link. It goes under
share/ rather than include/ deliberately: everything under include/fortran/
is partitioned by compiler and the config enumerates that directory to report
which compilers are installed, so a compiler-independent source file there
would be listed as though it were one.

The config package lands in lib/cmake/rocfft beside the C package, and a
forwarder in lib/cmake/rocfft-fortran makes find_package(rocfft-fortran)
resolve to the same place. A version file is installed into BOTH directories,
and it has to be: CMake looks for the version file next to the config it
actually resolved, so find_package(rocfft-fortran 1.0) resolves the forwarder
and would never see a version file kept only beside the real config. The
number is parsed from this tree's projects/rocfft/CMakeLists.txt, never from
rocfft_VERSION, which in a standalone build reports whatever rocFFT happens
to be installed. rocFFT composes VERSION_STRING from ROCFFT_VERSION_MAJOR /
_MINOR / _PATCH rather than spelling a literal, so the three components are
read and recomposed; when that fails, no version file is installed and a
STATUS message says so, because a file claiming the wrong number is worse
than none.

The recorded compiler directory is only a DEFAULT. A prefix can hold
artifacts for several compilers at once, while the config package is written
once and names whichever install ran last, so the config prefers the
consumer's own compiler when its .mod is present under the prefix, falls back
to the recorded directory otherwise, and fails naming what IS available. When
the resolved directory differs from the recorded one it repoints
INTERFACE_INCLUDE_DIRECTORIES and every IMPORTED_LOCATION_<CFG>, without
which find_package would succeed while linking the wrong archive.

The archive is compiled with -ffunction-sections -fdata-sections and exports
--gc-sections to consumers. A static archive links at object granularity and
this module is one object, so one wrapper otherwise pulls in every undefined C
symbol the object references: the first rocFFT entry point added after a
release would break the link for consumers who never call it. Both are guarded
on the compilers known to accept the spelling.

Tests
-----
test/ carries 18 tests under CTest. All are runtime tests that allocate
device memory, so they write `use hip` next to `use rocfft` and need the HIP
Fortran binding at compile time; they are skipped with a named message when
it is absent.

They are labelled "gpu", so ctest -LE gpu stays meaningful on a machine
without one.

Verified against ROCm 10.0 on gfx1101 with gfortran 13.3.0. Standalone
configure is clean under -Wdev, the version resolves to 1.0.41 and the
version file installs into both cmake directories. With the HIP Fortran
binding available, 18 of 18 pass; one of those, field_brick_z, prints SKIPPED
and exits 0 because it wants two GPUs, so the honest reading is 17 real GPU
tests and 1 self-skip. The documented consumer path was
exercised end to end: install, find_package(rocfft-fortran 1.0), link
roc::rocfft_fortran, run on the GPU. The per-compiler fallback was exercised
by hand too: with the recorded directory pointing at a compiler whose .mod is
not installed, the consumer's own compiler is picked and the imported target
repointed at it, and with no usable directory at all find_package fails
naming what is installed.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
hipfft.F90 and hipfftw.F90 are generated from the public headers by the
rocm-fortran generator and committed next to them, so that a header change
and its binding travel in the same pull request. Each is a single
self-contained module, `hipfft` and `hipfftw`, carrying the interfaces, the
enum constants, the opaque handles and the status helper. A consumer writes
one `use hipfft`.

Implements RFC0014 (ROCm/TheRock#8122) for hipFFT, following the shape
already reviewed for HIP in ROCm/rocm-systems#11923.

Two bindings in one directory, because hipFFTW is built by the hipFFT
project rather than one of its own. They are separate modules, separate
targets and separate config packages, but they live next to the headers they
bind rather than in a directory of their own.

The bindings declare bind(C) interfaces only, so they compile against neither
the hipFFT headers nor libhipfft, and need no GPU and no HIP compiler to
build. The C libraries are link-time dependencies of a final executable and
are carried as each target's link interface. The subdirectory guards itself,
returning early when BUILD_FORTRAN_BINDINGS is OFF or no Fortran compiler is
present, so a C-only site is unaffected.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPFFT_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK: the two upper tiers cannot legally coexist in one generic,
because an assumed-rank dummy is not distinguishable by rank from the
per-rank specifics. The config packages set hipfft_FORTRAN_FOUND and
hipfftw_FORTRAN_FOUND.

The compiler probe is read from ROCM_HAVE_FORTRAN, the name to settle on
across both monorepos. This repository's root publishes
ROCM_LIBS_HAVE_FORTRAN today, so that spelling is honoured second, never over
the new name. It is a bridge with an end: when the root is switched over,
that branch is dead code and goes.

Install layout
--------------
A .mod is not portable across compilers, so each .mod and archive installs
under include/fortran/<compiler> and lib/fortran/<compiler>. The directory is
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name
(GNU to gfortran, LLVMFlang to amdflang, Cray to ftn), which survives an MPI
wrapper, a versioned binary, an absolute path and the Cray wrapper, where a
plain basename would not.

Both config packages land in lib/cmake/hipfft beside the C package, and
forwarders in lib/cmake/hipfft-fortran and lib/cmake/hipfftw-fortran make
find_package(hipfft-fortran) and find_package(hipfftw-fortran) resolve to the
same place. Each package gets a config-version file, stamped with hipFFT's
version (hipFFTW has none of its own) parsed from the HIPFFT_VERSION_* components
in this tree rather than from hipfft_VERSION, which reports whatever hipFFT is
INSTALLED. Both files install into BOTH of their package directories, because
CMake looks for the version file next to the config it actually resolved and the
versioned spelling resolves the forwarder. When the version cannot be read, no
version file is installed and a STATUS message says so: a file claiming the wrong
number is worse than none.

The recorded compiler directory is only a DEFAULT. A prefix can hold artifacts
for several compilers while the config is written once, so each config prefers
the consumer's own compiler when its .mod is installed under the prefix --
hipfft.mod for one package, hipfftw.mod for the other, since either half is
switchable on its own -- falls back to the recorded directory, and otherwise
names what IS available. When the resolved directory differs from the recorded
one, INTERFACE_INCLUDE_DIRECTORIES and every IMPORTED_LOCATION_<CFG> are
repointed, or find_package would succeed while linking the wrong archive.

Both generated sources also install to share/hipfft/fortran, so that a user on a
compiler ROCm ships no .mod for can rebuild without cloning a monorepo. Under
share/ and not include/, because everything under include/fortran/ is partitioned
by compiler and the configs glob that directory to report which compilers are
present.

Both archives are built with -ffunction-sections -fdata-sections and export
--gc-sections to consumers, guarded on the compilers that accept the spelling. A
static archive links at object granularity and each of these is one object, so
without section GC one wrapper pulls in every undefined C symbol the whole module
references, and a consumer fails to link over API their installed .so lacks.

Tests
-----
test/ carries 19 tests under CTest. All are runtime tests that allocate
device memory, so they write `use hip` next to their own `use`, which makes
the HIP Fortran binding a compile-time dependency; they are skipped with a
named message when it is absent.

They are labelled "gpu", so ctest -LE gpu stays meaningful on a machine
without one.

Verified against ROCm 10.0 on gfx1101 with BOTH compilers, gfortran 13.3.0
and amdflang 23.0.0. With the HIP Fortran binding available, 19 of 19 pass.
The documented consumer path was exercised end to end with amdflang:
install, find_package on both packages, link hip::hipfft_fortran and
hip::hipfftw_fortran in one program, run on the GPU. The compiler-mismatch
diagnostic was exercised for real by installing with amdflang and consuming
with gfortran, which is what confirms the CMAKE_Fortran_COMPILER_ID mapping
handles LLVMFlang and that the message renders as prose rather than as a
semicolon-separated list.

The per-compiler selection was verified the same way: both bindings installed
into one prefix twice, with gfortran and then amdflang, so that the configs
record amdflang while the gfortran artifacts are still present. A gfortran
consumer then still resolves both packages, compiles against
include/fortran/gfortran and links lib/fortran/gfortran, which is the repointing
working. Removing only gfortran's hipfftw.mod makes hipfftw-fortran fail with the
named message while hipfft-fortran still resolves, which is the per-module glob
working. find_package(hipfft-fortran 1.0) and find_package(hipfftw-fortran 1.0)
both resolve through their forwarders and report 1.0.27; 2.0 is refused.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
…rated one

hipsolver.F90 is generated from the hipSOLVER public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single self-contained module,
`hipsolver`, carrying the interfaces, the enum constants, the opaque handles and
the hipsolverCheck status helper. A consumer writes one `use hipsolver` and links
roc::hipsolver_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for hipSOLVER, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

Removing the hand-written binding
---------------------------------
library/src/hipsolver_module.f90 is removed, along with the install(FILES ...)
rule that shipped it into include/hipsolver and the backward-compatibility
symlinks to it. It was deprecated in hipSOLVER 2.3.0 (ROCm 6.3.0) and was shipped
and built by default, so the removal is user visible: the module keeps the name
`hipsolver`, but the separate `hipsolver_enums` module is gone -- its constants
are part of `hipsolver` -- and consumers get a static archive and a .mod rather
than a shared library plus a .f90 to build themselves.

No enumerators are lost, which is the thing that bit hipBLAS. hipsolver_enums
declared 27 enumerators; all 27 are present in the generated module, which
declares 58. Neither module carries HIP's hipDataType enumerators, so hipSOLVER
needs nothing like the hip_datatypes_stub.F90 hipBLAS had to add.

EXPORT_FORTRAN_BINDINGS is removed with the target it controlled: it only chose
whether the old shared hipsolver_fortran joined the hipsolver-targets export set.
The generated binding has an export set and a config package of its own.

clients no longer compiles its shim against the removed module; it links the
target ../fortran exports. Both halves used the target name hipsolver_fortran,
which is why the previous revision of fortran/ had to call its target
hipsolver_fortran_bindings and paper over it with EXPORT_NAME and OUTPUT_NAME;
that workaround is gone with the clash.

Two latent bugs in the client shim
----------------------------------
Both were invisible while the shim compiled against a hand-written binding that
made the same mistakes, and both are errors against the generated one.

hipsolver{SS,DD,CC,ZZ}gels and ...gesv declare lwork as size_t in
hipsolver-functions.h AND in the shim's own C++ prototype in
hipsolver_fortran.hpp, but the Fortran shim typed it integer(c_int), as did the
removed module. Eight functions now say integer(c_size_t).

hipsolver{S,D,C,Z}gesvd{,_bufferSize} take jobu and jobv as signed char. The
shim keeps integer(c_signed_char) to match the C++ prototype it exposes, and now
converts with achar(..., kind=c_char) at the eight call sites, because the
generated binding types the C signed char as character(c_char).

Linking against an older hipSOLVER
----------------------------------
The archive is built with -ffunction-sections -fdata-sections and exports
--gc-sections to its consumers. A static archive links at object granularity, so
pulling in one wrapper pulls in every undefined C symbol the object references;
a consumer who never touches API their installed libhipsolver lacks would still
fail to link. Against the ROCm installed here every symbol the module references
is already present, so this is insurance rather than a fix for a present
failure, matching the flags the rest of the series carries.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded),
both overridable per library through HIPSOLVER_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. HIPSOLVER_HAVE_FORTRAN_BINDINGS reports whether they were built.

The compiler probe is read from ROCM_HAVE_FORTRAN, with ROCM_LIBS_HAVE_FORTRAN
honoured second as the spelling this repository's root publishes today.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name,
which survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. The recorded HIPSOLVER_FORTRAN_COMPILER_DIR is only a default: the
config prefers the consumer's own compiler when its .mod is installed under the
prefix, repoints INTERFACE_INCLUDE_DIRECTORIES and every IMPORTED_LOCATION_<CFG>
when that differs from the recorded directory, and otherwise names what IS
available.

The generated source is installed as share/hipsolver/fortran/hipsolver.F90, so a
user on a compiler ROCm ships no .mod for can rebuild the binding without cloning
a monorepo. Under share/ and not include/, because everything under
include/fortran/ is partitioned by compiler and the config enumerates that
directory to report which compilers are present.

This uses the SHARED layout: the real config is co-installed in
lib/cmake/hipsolver beside the C package, with a forwarder in
lib/cmake/hipsolver-fortran. rocRAND and hipRAND cannot do this because their
shipped <lib>-config.cmake carries a bare unguarded include() of a sibling
<lib>-fortran-config.cmake and a file there would recurse; hipsolver-config.cmake
has no such include, checked against an installed ROCm.

A config-version file is installed into BOTH package directories, because CMake
looks for it next to the *-config.cmake it actually resolved and the versioned
spelling resolves the forwarder. Its version is parsed from this tree's
VERSION_STRING rather than from hipsolver_VERSION -- that variable is set by the
find_package(hipsolver) this directory does for its link interface, so it would
report whatever hipSOLVER happens to be installed.

Tests
-----
48 tests under CTest, off by default: the runtime tests carried over from
hipFORT, which allocate and copy device memory and so need the HIP Fortran
binding at compile time, and are skipped with a named message when it is
absent.

They are labelled gpu, so ctest -LE gpu stays meaningful on a machine without
one.
amontoison added a commit to amontoison/rocm-libraries that referenced this pull request Sep 28, 2026
rocsolver.F90 is generated from the rocSOLVER public headers by the rocm-fortran
generator and committed next to them, so that a header change and its binding
travel in the same pull request. It is a single module, `rocsolver`, carrying the
interfaces, the enum constants, the opaque handles and the rocsolverCheck status
helper. A consumer writes one `use rocsolver` and links roc::rocsolver_fortran.

Implements RFC0014 (ROCm/TheRock#8122) for rocSOLVER, following the shape already
reviewed for HIP in ROCm/rocm-systems#11923.

This is an add, not a replacement: rocSOLVER ships no hand-written Fortran
module, so nothing is removed and no existing consumer changes.

Depends on the rocBLAS binding
------------------------------
Alone in this series, this binding is not self-contained at COMPILE time.
rocsolver-functions.h includes rocblas.h and the rocSOLVER API is spelled in
rocBLAS types, so the generated module opens with

    use rocblas, only: rocblas_diagonal_non_unit, rocblas_fill_upper,
                       rocblas_handle_t, rocblas_operation_none,
                       rocblas_side_left, rocblas_status_success

and rocblas.mod, built by the SAME compiler, must exist before the archive can be
compiled at all. In-tree the rocblas_fortran target is already defined;
standalone the directory finds the rocBLAS Fortran package, searching
lib/cmake/rocblas for the real config as well as the default suffixes that the
forwarder in lib/cmake/rocblas-fortran covers. Absent, the directory says so and
returns, leaving the rocSOLVER C library to build normally: BUILD_FORTRAN_BINDINGS
is ON by default, so a missing optional binding must not take the whole library
down with it. The lookup happens before the target is created, so nothing is left
half configured.

The dependency is PUBLIC, not INTERFACE, because a consumer that says
`use rocsolver` needs rocblas.mod on its own include path: the compiler follows
the module's use-association to read it. The config package carries this through,
importing roc::rocblas_fortran before the targets file and naming it when it is
missing.

Linking against an older rocSOLVER
----------------------------------
The archive is built with -ffunction-sections -fdata-sections and exports
--gc-sections to its consumers. Against ROCm 10.0 (librocsolver 3.36) 52 of the C
symbols this module references are missing, the cholqr, gehd2/gehrd and *_64
families that 3.38 adds. A static archive links at object granularity, so pulling
in one wrapper pulls in every undefined C symbol the object references: a program
that does nothing but call rocsolverCheck fails with 156 undefined references
without these flags, and links with them.

Only a consumer that touches a module procedure (rocsolverCheck, or any array
overload) pulls the object in at all; one that calls the plain bind(C) interfaces
references the C symbols directly. That is why the failure looks arbitrary from
the outside, and why the flags are not optional.

Build options
-------------
BUILD_FORTRAN_BINDINGS (ON, guarded) and BUILD_FORTRAN_TESTS (OFF, guarded), both
overridable per library through ROCSOLVER_BUILD_FORTRAN_*.
FORTRAN_ARRAY_INTERFACES is a tri-state (none / assumed-shape / assumed-rank,
default assumed-shape) replacing the two booleans USE_FPOINTER_INTERFACES and
ASSUMED_RANK. ROCSOLVER_HAVE_FORTRAN_BINDINGS reports whether they were built.

The compiler probe is read from ROCM_HAVE_FORTRAN, with ROCM_LIBS_HAVE_FORTRAN
honoured second as the spelling this repository's root publishes today.

Install layout
--------------
A .mod is not portable across compilers, so the .mod and the archive install
under include/fortran/<compiler> and lib/fortran/<compiler>, the directory
derived from CMAKE_Fortran_COMPILER_ID and mapped back to the executable name,
which survives an MPI wrapper, a versioned binary, an absolute path and the Cray
wrapper. The recorded ROCSOLVER_FORTRAN_COMPILER_DIR is only a default: the
config prefers the consumer's own compiler when its .mod is installed under the
prefix, repoints INTERFACE_INCLUDE_DIRECTORIES and every IMPORTED_LOCATION_<CFG>
when that differs from the recorded directory, and otherwise names what IS
available.

The generated source is installed as share/rocsolver/fortran/rocsolver.F90, so a
user on a compiler ROCm ships no .mod for can rebuild the binding without cloning
a monorepo. Under share/ and not include/, because everything under
include/fortran/ is partitioned by compiler and the config enumerates that
directory to report which compilers are present.

This uses the SHARED layout: the real config is co-installed in
lib/cmake/rocsolver beside the C package, with a forwarder in
lib/cmake/rocsolver-fortran. rocRAND and hipRAND cannot do this because their
shipped <lib>-config.cmake carries a bare unguarded include() of a sibling
<lib>-fortran-config.cmake and a file there would recurse; rocsolver-config.cmake
has no such include, checked against an installed ROCm.

A config-version file is installed into BOTH package directories, because CMake
looks for it next to the *-config.cmake it actually resolved and the versioned
spelling resolves the forwarder. Its version is parsed from this tree's
VERSION_STRING (3.38.0) rather than from rocsolver_VERSION -- that variable is
set by the find_package(rocsolver) this directory does for its link interface, so
it would report whatever rocSOLVER happens to be installed (3.36.0 here).

Tests
-----
82 tests under CTest, off by default: the runtime tests carried over from
hipFORT, which allocate and copy device memory and so need the HIP Fortran
binding at compile time, and are skipped with a named message when it is
absent.

They are labelled gpu, so ctest -LE gpu stays meaningful on a machine without
one.

@mangupta mangupta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 AI-assisted pre-review (for @mangupta)

Comment thread projects/hip/fortran/CMakeLists.txt Outdated
Comment on lines +443 to +447
# duplicating the real config, which would also need its own copy of the targets
# file and would then be a second thing to keep in step.
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/forward/hip-fortran-config.cmake"
"# Generated forwarder. The real config lives beside the HIP C package, in
# lib/cmake/hip, so that hip-config.cmake can include it as a sibling. This file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 AI-assisted pre-review (for @mangupta)

[BLOCKING] Create the forwarder directory before writing the package config

The configuration writes forward/hip-fortran-config.cmake without first creating the forward directory.

Suggested fix: Add file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/forward") before file(WRITE ...), or write the forwarder directly to an existing binary-directory path.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Not applicable.
file(WRITE) creates missing parent directories itself.
From the CMake docs for file(WRITE) (https://cmake.org/cmake/help/latest/command/file.html#writing):

Any directories in the path specified by <filename> that do not exist will be created.

Verified with the exact construct from this file:

cmake_minimum_required(VERSION 3.16)
project(t NONE)
file(WRITE
"${CMAKE_CURRENT_BINARY_DIR}/forward/hip-fortran-config.cmake"
"hello\n")
$ ls build/forward/
hip-fortran-config.cmake

No MAKE_DIRECTORY, no error.
This behaviour is documented and has been in place for many releases, so it is not a recent addition.

That said, the finding did point at a real gap: nothing in the surrounding comments explained why the forwarder needs a subdirectory at all.
It is there because the real config, configured at line 382, already occupies ${CMAKE_CURRENT_BINARY_DIR}/hip-fortran-config.cmake, the same basename, so the forwarder needs a directory of its own.

I will explain it in the comment block.

@amontoison

Copy link
Copy Markdown
Author

@mangupta Is it possible to get another review? We need this for 10 PRs in rocm-libraries.

@mangupta

mangupta commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

🤖 AI-assisted pre-review (for @mangupta)

Re-reviewed the updated head (75b49751755e) — no new findings at or above the posting threshold.

@mangupta

mangupta commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

🤖 AI-assisted pre-review (for @mangupta)

Re-reviewed the updated head (cafda3ec2388) — no new findings at or above the posting threshold.

Add projects/fortran/hip.F90, the hip module generated from the HIP C
headers by rocm-fortran-generator under RFC0015 (ROCm/TheRock#8122).
projects/fortran is a standalone project for the Fortran bindings of
the rocm-systems libraries. The module is not edited by hand:
.gitattributes marks it linguist-generated, and metadata/ holds what
the C headers cannot express (scalar arguments, optional arguments,
by-value arguments, function pointers), read by the generator when it
runs on this checkout.
Build projects/fortran/hip.F90 as hip::hip_fortran, a standalone CMake
project built against an installed HIP (find_package(hip)).
BUILD_FORTRAN_BINDINGS (default ${UNIX}), BUILD_FORTRAN_CLIENTS (default
ON) and FORTRAN_ARRAY_INTERFACES (default assumed-shape) control it, and
HIP_BUILD_FORTRAN_* override them. The .mod and the archive install per
compiler under <includedir>/fortran/<compiler> and
<libdir>/fortran/<compiler>, beside a hip-fortran config package.
shared/cmake/ROCmFortran.cmake adds the amdflang-first compiler probe
for rocm-systems projects.

test/ adds 41 CTest tests labelled gpu (39 without a HIP compiler). The
Fortran tests of the rocm-libraries bindings use hip and skip until this
lands.

Refs: ROCm/TheRock#8122 (RFC0015)
The binding consumes HIP's public API and builds standalone against an
installed HIP, so it gets its own top-level tree instead of sitting next
to the implementation projects: projects/fortran moves to
bindings/fortran, the layout every monorepo and TheRock use for the
Fortran bindings.

- read HIP's VERSION from projects/hip, now two levels up
- CODEOWNERS: /bindings/fortran/, same owners
- repos-config.json: register bindings/fortran so CI detects changes
  to it, as for emulation/rocjitsu
Install the test executables in bin/, and a CTestTestfile.cmake in
bin/hip-fortran/, with the same tests and properties as the build tree,
so that ctest --test-dir runs them from an install, as TheRock's test
jobs do for the libraries. The code object of module_kernel and
library_module installs beside it, and they find it by a relative path.
…object

TheRock's hipcc comes from the HIP install and does not know where the
device libraries are; it passes their path through HIP_FORTRAN_GENCO_FLAGS.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants