Skip to content

Add migration guides for the ROCm-packaged Fortran bindings and from CUDA Fortran, and deprecate hipFORT - #548

Draft
amontoison wants to merge 26 commits into
developfrom
docs/migration-guide
Draft

amontoison wants to merge 26 commits into
developfrom
docs/migration-guide

Conversation

@amontoison

@amontoison amontoison commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

Three how-to pages for moving to the Fortran bindings that ship inside ROCm: one generated module, archive and CMake package per library (use rocblas, roc::rocblas_fortran).

Three pages, because there are three audiences with different deadlines and different edits:

  • migration-guide.rst: you build hipFORT and write use hipfort_rocblas. Rename the use statements, change the link target, and your calls stay the same. hipFFT's binding has a second module, hipfftxt, for every hipfftXt* and hipfftMp* routine; it re-exports hipfft, as CUDA Fortran's cufftXt does with cufft, and hipFORT gets the same split into hipfort_hipfft and hipfort_hipfftxt. hipFORT is maintained beside the new bindings from 10.3 until 11.0, when it is removed.
  • migration-guide-in-tree.rst: you use a library's own hand-written module (use rocblas from rocblas_module.f90, use rocrand_m, ...). From 10.3 the generated binding ships beside the hand-written module, which is deprecated and removed in a later release; one program uses one or the other, since the module names are the same. Some call sites change, including handle creation in rocBLAS, hipBLAS and hipSOLVER, which still compiles but fails at run time.
  • migration-guide-cuda-fortran.rst: you call NVIDIA's libraries through the CUDA Fortran modules (use cublas_v2, use cufft, ...). The hip* modules follow their names with hip for cu (cufft and cufftXt become hipfft and hipfftxt), and routine and constant names map the same way. The page maps each module, lists what has to be rewritten by hand (handles, device arrays, kernels, NVTX ranges) and what has no ROCm Fortran equivalent (cublasXt, cublasMp, cusolverMp, curand_device, cuTENSOR, NCCL, NVSHMEM), with a reference to NVIDIA's Fortran CUDA Interfaces.

The PR also deprecates hipFORT itself: configuring it now prints a CMake deprecation warning (maintained through the 10.x series, removed in ROCm 11.0, migrate to the bindings ROCm ships from 10.3), pointing to the migration guide; -Wno-deprecated silences it. The README and the CHANGELOG say the same. A warning on the consumer side (find_package(hipfort)) is left for the last release before 11.0.

The hipFORT guide also covers:

  • why the bindings are moving;
  • when you have to build anything (only for a compiler other than amdflang, or on Windows);
  • the -I / -L paths for the .mod and .a files;
  • the installed sources under share/<lib>/fortran/;
  • codes that build on several ROCm versions;
  • how to try the bindings before 10.3.

The content is checked against the 12 implementation PRs:

Library Pull request
HIP ROCm/rocm-systems#11923
ROCTx ROCm/rocm-systems#14024
rocBLAS ROCm/rocm-libraries#12533
hipBLAS ROCm/rocm-libraries#12370
rocSOLVER ROCm/rocm-libraries#12582
hipSOLVER ROCm/rocm-libraries#12581
rocSPARSE ROCm/rocm-libraries#12514
hipSPARSE ROCm/rocm-libraries#12368
rocFFT ROCm/rocm-libraries#12366
hipFFT, hipFFTW ROCm/rocm-libraries#12367
rocRAND ROCm/rocm-libraries#12505
hipRAND ROCm/rocm-libraries#12506

Around them:

What Pull request
RFC0015 update ROCm/TheRock#9433
TheRock builds the bindings (bindings/fortran/, fortran-bindings stage) ROCm/TheRock#9446
Generator writes to bindings/fortran/ ROCm/rocm-fortran-generator#14
Generator splits hipFFT into hipfft and hipfftxt ROCm/rocm-fortran-generator#17
hipFORT splits hipFFT into hipfort_hipfft and hipfort_hipfftxt #638 (EMU generator: AMD-ROCm-Internal/rocm-fortran-generator#13)
CI test of HIP and ROCTx in TheRock (do not merge) ROCm/rocm-systems#14097
CI test of the rocm-libraries bindings in TheRock (do not merge) ROCm/rocm-libraries#15008
Sandbox preview of the whole set #540

The bindings live in their own bindings/fortran/ tree, apart from the libraries: HIP and ROCTx build together in rocm-systems' bindings/fortran/, and each math library's binding is in rocm-libraries' bindings/fortran/<library>/.

These PRs are still open, so the guides need another pass if anything changes before they merge. The design is in RFC0015.

Previews: migration-guide · migration-guide-in-tree · migration-guide-cuda-fortran

amontoison added a commit to amontoison/TheRock that referenced this pull request Oct 4, 2026
- hipfort is maintained beside the packaged bindings through 10.x and
  removed at 11.0; a binding holds for a major ROCm series
- add the population that builds one code on several ROCm versions,
  some older than 10.2
- list the call-site changes for users of a library's own module,
  including handle creation by reference, which still compiles
- link the migration guides (ROCm/hipfort#548) and list the 12
  implementation pull requests
amontoison added a commit to amontoison/TheRock that referenced this pull request Oct 13, 2026
- hipfort is maintained beside the packaged bindings through 10.x and
  removed at 11.0; a binding holds for a major ROCm series
- add the population that builds one code on several ROCm versions,
  some older than 10.2
- list the call-site changes for users of a library's own module,
  including handle creation by reference, which still compiles
- link the migration guides (ROCm/hipfort#548) and list the 12
  implementation pull requests
@amontoison
amontoison force-pushed the docs/migration-guide branch from 2d8b4c1 to 6fda387 Compare October 17, 2026 19:49
@amontoison amontoison changed the title Add a migration guide for the ROCm-packaged Fortran bindings Add a migration guide for the ROCm-packaged Fortran bindings, and deprecate hipFORT Oct 17, 2026
@amontoison
amontoison force-pushed the docs/migration-guide branch 2 times, most recently from caceba0 to f466708 Compare October 21, 2026 18:25
Document the move from hipFORT to the bindings that ship inside ROCm
(rocm-systems and rocm-libraries), in the spirit of the layout previewed
in #540: one self-contained module per library, ROCm only.

The guide covers the two edits a consumer has to make (the `use`
statement rename, with a sed recipe and the cases it deliberately leaves
to review; and the per-library Fortran archive and CMake target), the
build options, the per-compiler install layout and how to rebuild a
binding for a non-amdflang compiler, what does not change, and an FAQ
covering the old/new coexistence.

Wire the page into the docs index and the Sphinx TOC.
"Building one library's binding from source" opened on
`cmake -S projects/rocblas/fortran` without ever saying where that
directory comes from. That was harmless while shipping the .F90 was
still open; now that ROCm ships precompiled bindings for amdflang only
and installs no sources, it is the mandatory path for every gfortran,
Cray and ifx user, and the command as written assumes a checkout the
reader does not have.

Name the prerequisite: which repository holds which binding, and that
the tag has to match the installed ROCm rather than the default branch
-- a binding generated from a newer ROCm declares entry points the
installed .so does not export, and that surfaces as an undefined symbol
at link time or as an interface that quietly differs from the one being
called.

Give a blobless sparse clone rather than a plain one, so fetching a
single directory does not drag in a monorepo the reader has no other use
for; verified at 9.6 MB. Also note the case that skips the step
entirely: a site already building ROCm from source through Spack,
EasyBuild or a distro package build has the tree, and wants
BUILD_FORTRAN_BINDINGS=ON there instead.

Splits the section in two so the new prerequisite and the existing build
commands each have a heading.
Two claims about <LIB>_FORTRAN_COMPILER_DIR and the per-compiler
subdirectory did not match what the config packages do.

The override was described as mattering "only at a site that installs
several compilers' artifacts side by side". That is the one case it is
not needed for: a prefix holding artifacts for several compilers now
resolves on its own, because the config prefers the consumer's own
compiler when its .mod is installed and repoints the imported target at
it. The override is for a directory the compiler alone does not imply,
such as a version-suffixed gfortran-13.3.0, or for selecting one
deliberately.

"find_package picks your compiler's subdirectory automatically" was
already the intended behaviour and is now the implemented one, so say
explicitly that it holds when a prefix carries more than one compiler.

Also show the diagnostic for the case where nothing is installed for the
consumer's compiler. It names the compilers that ARE present, which is
what tells a reader whether they need to rebuild the bindings or merely
point at a directory that already exists.
Getting the source of a binding currently means cloning a monorepo and
picking the tag that matches the installed ROCm, because ROCm does not
install the .F90. That is the path the section documents, and it stays
the path until the install lands.

Note the agreed destination, share/<library>/fortran/<library>.F90, and
why it is not include/: the .F90 is compiler-independent where the .mod
is not, and everything under include/fortran/ is partitioned by
compiler, so a source file there reads as if it named one.

Marked as planned rather than described as working. The install is
agreed in the design document and implemented nowhere, and this guide
has already had one sentence that described intent as if it were
behaviour.
ROCm now installs the generated .F90 alongside the binding, at
share/<library>/fortran/<library>.F90, so a user on a compiler with no
shipped .mod has the source already and does not have to sparse-clone a
monorepo to obtain one file.

That also retires the warning this section had to carry. Source fetched
separately can come from a different ROCm than the installed .so, which
is why the old text told readers to check out a therock-<version> tag
and explained what goes wrong if they do not. Installed source is
generated from the same headers as the installed library, so the
mismatch cannot arise.

The clone survives as a note for a ROCm that predates the install,
keeping the tag advice where it is still needed.
Two things the page stated that the preview no longer does.

HIPFORT_EXTENDED_TESTS was mapped to BUILD_FORTRAN_EXTENDED_TESTS. Both
audits it gated are dropped instead: the shared-link check went with the
single archive it linked, and the exhaustive per-library symbol tests
with it. Neither tests the reader's code -- they audit the bindings at
link time -- so the row now says they are gone and points at the runtime
suite, which is what BUILD_FORTRAN_TESTS actually builds.

The install paths were written as include/fortran/<compiler> and
lib/fortran/<compiler>. They hang off the platform's own directories,
which is lib64 on Fedora, RHEL and SUSE and lib/<triplet> on Debian
multiarch, so a reader on any of those would have gone looking in a
directory that does not exist. Spelled as <libdir>/<includedir>, with
the concrete ROCm values given once so the raw -I/-L examples that
follow still read literally.
The page served two audiences with a shared destination and almost
nothing else in common: hipFORT users, who build a separate repository
and write use hipfort_rocblas, and users of the hand-written module a
library ships itself, who write use rocblas. Different deadlines (11.0
against 10.2), different edits, and a different answer to the question
that matters most.

Keeping both made one of them wrong wherever they disagreed. The page
led with "nothing else in your code changes", which is true for hipFORT
and false for the in-tree path: the hand-written modules pass scalars as
type(c_ptr) and the generated bindings declare them typed, so every call
site with an alpha or beta stops compiling. That was buried in a single
sentence advising readers to "check the call sites", which badly
understates a systematic break.

Separated, each page can be accurate. migration-guide.rst keeps its
claim and addresses hipFORT only, with pointers where the reader might
be on the other path. migration-guide-in-tree.rst states the call-site
break plainly, with the rocblas_daxpy before-and-after, the note that
the two forms are ABI-identical and therefore invisible to any symbol or
link check, and a grep to size the work. It also takes the hipSOLVER and
hipRAND collisions and BUILD_FORTRAN_CLIENTS, none of which were
hipFORT's business.

Measured rather than inferred: the libraries' own
clients/samples/example_fortran_*.f90, compiled unmodified against the
generated bindings, all 18 fail to build -- four in rocBLAS, fourteen in
rocSPARSE -- and reduce to the two differences the new page describes.

The sed recipe loses its in-tree-only rules, which were renaming names
no hipFORT user writes.
Two things the pages now got wrong.

The in-tree page led with a warning that scalar call sites break: the
hand-written modules pass alpha and beta as type(c_ptr), value, and the
generated bindings declared them typed, so every c_loc(alpha) had
nothing to resolve against. That was measured, and it was true of the
bindings as they stood. It is no longer: the generator emits both forms
as specifics of one generic, so c_loc(alpha) resolves on the _dptr
specific and existing call sites compile untouched.

Re-measured against the libraries' own samples, built unmodified against
today's bindings, two differences remain and both are one-liners: a
`use <lib>_enums` to delete, now that the enumerators live in the
library module, and a c_loc() to add when passing a character buffer to
the revision-query helpers. The latter is what fails all fourteen
rocSPARSE samples at once, since each opens by printing the revision --
worth saying, because fourteen failures reads like a deep problem and it
is one line.

Separately, BUILD_FORTRAN_TESTS is gone: the Fortran tests now ride on
BUILD_FORTRAN_CLIENTS, ON by default, one option name across every
library. The table, the per-library override and the paragraph
describing the two as distinct are updated to match.
760 lines for a page whose message is "rename your use statements, change one
link target". The facts were right; the prose was doing too much work around
them.

Merged the two twelve-row library tables into one. They listed the same twelve
libraries, one mapping old use to new use and the other new use to link target,
so a reader had to look up the same library twice to find out what to change.
One table now carries old use, new use and CMake target on one row, and the
linking section points at it.

Cut four duplications. "Do I need to do anything now?" and the FAQ's "Do I have
to change my code now?" gave the same answer six hundred lines apart; only the
section survives. The coexistence rules were stated in the body and again in
the FAQ.

Compressed the passages that explained more than a reader needs to act: the
rationale for the tri-state FORTRAN_ARRAY_INTERFACES, the package-versus-target
naming note, the amdflang version-skew note, and the fixed-form answer, which
spent sixteen lines on "yes, unless you are pre-Fortran 90".

Rewrote most of the "not X, it is Y" constructions as plain statements; the
count drops from fourteen to eight.

No fact removed: every library, target, option and install path the page listed
before is still there, the hipFFTW packaging note included. 672 lines.
Ten dashes standing in for punctuation across the two pages, most of them
parenthetical asides that read as an aside rather than as a sentence. Replaced
with commas, or with a full stop where the clause was doing enough work to be
its own sentence.

Left alone: the double dashes inside code blocks, which are command-line
options, and the two em-dashes in the in-tree table, which mark a cell as not
applicable rather than punctuating a sentence.
Address the questions raised on the hipFORT migration guide:

- explain why the bindings move into ROCm, up front instead of in the FAQ
- add "Do I need to build anything?", a decision table per situation
- add "Compile and link": the -I directory for the .mod files, the -L
  directory for the archives, with CMake and without
- document the installed sources under <datadir>/<lib>/fortran/, why
  they are installed, and how to build them by hand or with CMake
- state the overlap: hipFORT is maintained beside the new bindings from
  10.2 until 11.0; give a pattern for codes built on several ROCm
  versions, and the hipFORT tag to use on ROCm older than 10.2
- reword the build-options intro, which read as a riddle
- add a "Trying the bindings before ROCm 10.2" section with the 12 PRs

Correct what the PRs no longer match:

- ROCTx has a binding now (roctx, roc::roctx_fortran, roctx-fortran)
- BUILD_FORTRAN_BINDINGS defaults to ${UNIX}, not ON
- hipSPARSE's old module was never installed
- rocRAND and hipRAND drop BUILD_FORTRAN_WRAPPER without an error
- Fortran clients with the bindings off are skipped, not refused
- the scalar overloads are not _dptr specifics
- the in-tree call-site changes are wider than two edits: handle
  creation by reference in rocBLAS and hipBLAS compiles but leaves the
  handle unset, and rocSPARSE has buffer-size, sort and argument-order
  changes
- the packaged bindings land in 10.3, not 10.2; hipFORT alone through 10.2
- hipfort_handles never existed in hipFORT: drop it from the folded-module
  table, the sed recipe, and the follow-up notes
- the sed recipe needs GNU sed; say how to run it on macOS
- HIP and ROCTx build together in rocm-systems' projects/fortran, not
  under projects/<library>/fortran; ROCTx's branch still has to move.
- The bindings are committed next to the headers and kept in sync by
  CI, carry no documentation comments, and ship in ROCm's development
  packages.
- Calling styles: handles and const char* results stay type(c_ptr),
  every routine X is a generic around its bind(C) specific X_, nullable
  arguments are optional, and ROCTx accepts character strings.
- In-tree guide: c_loc(x) still works for output scalars; the run-time
  traps are the pointer outputs (handle, stream and info creation in
  rocBLAS, hipBLAS and hipSOLVER, rocSPARSE's p_error) and the argument
  order of csr2csr_compress. Fix the install and option history, the
  hipSOLVER package change, keyword and procedure-pointer changes, and
  the cross-version example.
- Fortran 77 wording and the compiler list follow RFC0015.
Configuring hipFORT now prints a CMake deprecation warning: hipFORT is
maintained through the ROCm 10.x series and removed in ROCm 11.0, and
from ROCm 10.3 ROCm ships Fortran bindings for HIP, ROCTx and the math
libraries itself, one module and one CMake package per library. The
warning points to the migration guide; -Wno-deprecated silences it.
The README and the CHANGELOG say the same.
A binding stays valid across 10.x only one way: a binding newer than the
libraries it links against can declare routines they do not export, and
since each binding compiles to one object, one such routine fails every
link of the library. Add a "Binding and library versions" subsection:
take a binding and its library from the same release, or build the
binding with one section per procedure and link with -Wl,--gc-sections
(the archives ROCm ships are not built that way). Point to it from the
version paragraph, the installed sources, the build recipes, the
pre-10.3 trial and the in-tree guide; hipFORT develop links that way
too. Also say that the default array overloads need Fortran 2008.
…he bindings' archives

--exclude-libs,ALL hid the symbols of every static archive the shared
library links, not only the bindings', and the text did not say that the
wrappers stay in the library and keep working, only unexported. Name the
bindings' archives, colon-separated since -Wl, splits on commas.
hipfort_hipfft_types (hipXtDesc, hipLibXtDesc) came with the hipFFT Xt
API (#611); the migration table lists it beside _enums, as it does for
hipFFTW and rocRAND.
The bindings ship as a tech preview in 10.3 and are production from
10.4, where the compatibility promise starts; the archives ROCm ships
are compiled with one section per procedure; Intel and NVIDIA
toolchain files are a convenience, not supported compilers; and
configuring hipFORT now prints a deprecation warning.
@amontoison
amontoison force-pushed the docs/migration-guide branch from f466708 to 06de420 Compare November 3, 2026 04:16
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Security scan found no critical or high findings on lines changed by this pull request

View the security scan run for complete reports.

“New” means the finding is located in a changed file on an added or modified line; it is not a base-versus-head findings delta.

The Fortran bindings move out of the library projects into a
bindings/fortran tree in rocm-libraries and rocm-systems, and are no
longer built with the libraries. Update the source paths, the build
commands, and the row for users who build ROCm from source.
…10.3

The generated bindings now ship beside the libraries' hand-written
modules, which are deprecated from 10.3 and removed in a later release:
replace the 10.3 deadline with a deprecation window, say that one
program uses one module or the other, keep BUILD_FORTRAN_WRAPPER and
hipSOLVER's options while their modules remain, note the
roc::hipsolver_fortran clash in a hipSOLVER built with
EXPORT_FORTRAN_BINDINGS=ON, and point the binding tests to their own
bindings/fortran/<library> project.
Every hipfftXt* and hipfftMp* routine is in hipfftxt, which re-exports
hipfft, as CUDA Fortran's cufftXt does with cufft. hipFORT gets the same
split into hipfort_hipfft and hipfort_hipfftxt.
Map the CUDA Fortran interface modules to the ROCm bindings, give the
cu to hip naming rule, and list what has to be rewritten by hand and
what has no ROCm Fortran equivalent.
@amontoison amontoison changed the title Add a migration guide for the ROCm-packaged Fortran bindings, and deprecate hipFORT Add migration guides for the ROCm-packaged Fortran bindings and from CUDA Fortran, and deprecate hipFORT Nov 7, 2026

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant