Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
/projects/rocfft/**/.readthedocs.yaml @ROCm/fft-reviewers @ROCm/fft-docs-reviewers
/projects/rocfft/docs/ @ROCm/fft-reviewers @ROCm/fft-docs-reviewers
/projects/rocfft/library/include/ @ROCm/fft-reviewers @ROCm/fft-docs-reviewers
/bindings/fortran/rocfft/ @ROCm/rocm-fortran-maintainers @ROCm/fft-reviewers

/projects/rocprim/**/*.md @ROCm/prims-rands-reviewers @ROCm/prims-docs-reviewers
/projects/rocprim/**/*.rst @ROCm/prims-rands-reviewers @ROCm/prims-docs-reviewers
Expand Down
9 changes: 9 additions & 0 deletions .github/repos-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,15 @@
"auto_subtree_pull": false,
"auto_subtree_push": false,
"monorepo_source_of_truth": true
},
{
"name": "rocfft",
"url": "ROCm/rocm-libraries",
"branch": "develop",
"category": "bindings/fortran",
"auto_subtree_pull": false,
"auto_subtree_push": false,
"monorepo_source_of_truth": true
}
]
}
2 changes: 2 additions & 0 deletions bindings/fortran/rocfft/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Generated by the rocm-fortran generator
/rocfft.F90 linguist-generated=true
13 changes: 13 additions & 0 deletions bindings/fortran/rocfft/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog for the rocFFT Fortran binding

## Unreleased

### Added

* Generated Fortran bindings, as a single `rocfft` module: `use rocfft`, link `roc::rocfft_fortran`.
Controlled by `BUILD_FORTRAN_BINDINGS` (on by default on Linux, off on Windows),
`BUILD_FORTRAN_CLIENTS` and `FORTRAN_ARRAY_INTERFACES` (`assumed-shape` by default; `none` or `assumed-rank`).
Found with `find_package(rocfft-fortran)`; the archive and the `.mod` files install per compiler,
under `<libdir>/fortran/<compiler>` and `<includedir>/fortran/<compiler>`.
The archive has one section per procedure: link with `-Wl,--gc-sections` to keep only the wrappers
you call.
208 changes: 208 additions & 0 deletions bindings/fortran/rocfft/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# #############################################################################
# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# #############################################################################

# Fortran bindings for rocFFT. rocfft.F90 is GENERATED by the rocm-fortran
# generator: regenerate it, do not edit it.

cmake_minimum_required(VERSION 3.19)

project(rocfft-fortran LANGUAGES NONE)

# Not ON: ROCm ships no Fortran compiler on Windows.
option(BUILD_FORTRAN_BINDINGS "Build the rocFFT Fortran bindings" "${UNIX}")
option(BUILD_FORTRAN_CLIENTS "Build the rocFFT Fortran binding tests" ON)

set(FORTRAN_ARRAY_INTERFACES "assumed-shape" CACHE STRING
"Array-argument overloads to expose: none, assumed-shape, or assumed-rank")
set_property(CACHE FORTRAN_ARRAY_INTERFACES PROPERTY STRINGS
none assumed-shape assumed-rank)

if(NOT BUILD_FORTRAN_BINDINGS)
return()
endif()

include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ROCmFortranCompiler.cmake")
if(NOT CMAKE_Fortran_COMPILER)
message(STATUS "rocFFT: no Fortran compiler found, skipping the Fortran bindings")
return()
endif()

enable_language(Fortran)

include(GNUInstallDirs)

if(NOT FORTRAN_ARRAY_INTERFACES MATCHES "^(none|assumed-shape|assumed-rank)$")
message(FATAL_ERROR
"FORTRAN_ARRAY_INTERFACES must be none, assumed-shape or assumed-rank, "
"not '${FORTRAN_ARRAY_INTERFACES}'.")
endif()

add_library(rocfft_fortran STATIC rocfft.F90)
add_library(roc::rocfft_fortran ALIAS rocfft_fortran)

# Each module compiles to one object, and a linker extracts whole objects from
# an archive, so a program that calls one wrapper links all of them. One section
# per procedure lets a program linked with -Wl,--gc-sections keep only the
# wrappers it calls, and still link when another wrapper names a C function the
# installed library does not export. Only these compilers split the sections
# (the Intel ones accept the flags but do not).
target_compile_options(rocfft_fortran PRIVATE
"$<$<COMPILE_LANG_AND_ID:Fortran,GNU,LLVMFlang,Flang,NVHPC>:-ffunction-sections;-fdata-sections>")

# A .mod is compiler-specific, so artifacts install per compiler. This mapping
# MUST match the one in rocfft-fortran-config.cmake.in.
if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
set(_fc_name "gfortran")
elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Flang") # Flang, LLVMFlang
set(_fc_name "amdflang")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Cray")
set(_fc_name "ftn")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM")
set(_fc_name "ifx")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
set(_fc_name "ifort")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "NVHPC")
set(_fc_name "nvfortran")
else()
get_filename_component(_fc_name "${CMAKE_Fortran_COMPILER}" NAME_WE)
string(TOLOWER "${_fc_name}" _fc_name)
endif()

set(ROCFFT_FORTRAN_COMPILER_DIR "${_fc_name}" CACHE STRING
"Per-compiler subdirectory the .mod and the archive install under")

set(_moddir "${CMAKE_CURRENT_BINARY_DIR}/include")
set_target_properties(rocfft_fortran PROPERTIES
Fortran_MODULE_DIRECTORY "${_moddir}"
Fortran_PREPROCESS ON
Fortran_FORMAT FREE
POSITION_INDEPENDENT_CODE ON)

if(FORTRAN_ARRAY_INTERFACES STREQUAL "assumed-shape")
target_compile_definitions(rocfft_fortran PRIVATE USE_ASSUMED_SHAPE=1)
elseif(FORTRAN_ARRAY_INTERFACES STREQUAL "assumed-rank")
target_compile_definitions(rocfft_fortran PRIVATE USE_ASSUMED_RANK=1)
endif()

target_include_directories(rocfft_fortran PUBLIC
"$<BUILD_INTERFACE:${_moddir}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/fortran/${ROCFFT_FORTRAN_COMPILER_DIR}>")

# Link interface only. C is enabled because hip-config.cmake reaches FindThreads.
enable_language(C)
find_package(rocfft QUIET)

# Always TRUE or FALSE: the config template substitutes it into a bare if().
if(TARGET roc::rocfft)
target_link_libraries(rocfft_fortran INTERFACE roc::rocfft)
set(ROCFFT_FORTRAN_NEEDS_C_PACKAGE TRUE)
else()
set(ROCFFT_FORTRAN_NEEDS_C_PACKAGE FALSE)
message(STATUS
"rocFFT: librocfft was not found, so the Fortran bindings carry no link "
"interface; a consumer will have to link it (-lrocfft) itself.")
endif()

# The uninstrumented Fortran executables cannot link an ASan librocfft.
if(BUILD_FORTRAN_CLIENTS AND BUILD_ADDRESS_SANITIZER)
message(STATUS
"rocFFT: address sanitizer is enabled, skipping the Fortran binding tests.")
set(BUILD_FORTRAN_CLIENTS OFF)
endif()

if(BUILD_FORTRAN_CLIENTS)
enable_testing()
add_subdirectory(test)
endif()

include(CMakePackageConfigHelpers)

set(_fortran_pkgdir "${CMAKE_INSTALL_LIBDIR}/cmake/rocfft-fortran")

install(TARGETS rocfft_fortran
EXPORT rocfft-fortran-targets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}/fortran/${ROCFFT_FORTRAN_COMPILER_DIR}"
COMPONENT devel)
install(DIRECTORY "${_moddir}/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/fortran/${ROCFFT_FORTRAN_COMPILER_DIR}"
COMPONENT devel
FILES_MATCHING PATTERN "*.mod")

# Under share/: the config reads every entry of include/fortran/ as a compiler.
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/rocfft.F90"
DESTINATION "${CMAKE_INSTALL_DATADIR}/rocfft/fortran"
COMPONENT devel)
install(EXPORT rocfft-fortran-targets
FILE rocfft-fortran-targets.cmake
NAMESPACE roc::
DESTINATION "${_fortran_pkgdir}"
COMPONENT devel)

set(ROCFFT_FORTRAN_LIBDIR "${CMAKE_INSTALL_LIBDIR}/fortran")
set(ROCFFT_FORTRAN_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/fortran")

configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/rocfft-fortran-config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/rocfft-fortran-config.cmake"
INSTALL_DESTINATION "${_fortran_pkgdir}"
PATH_VARS ROCFFT_FORTRAN_LIBDIR ROCFFT_FORTRAN_INCLUDEDIR)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/rocfft-fortran-config.cmake"
DESTINATION "${_fortran_pkgdir}"
COMPONENT devel)

# Read from this tree, not rocfft_VERSION, which is the INSTALLED rocFFT's. Judged on the whole match: the minor component "0" is falsy.
set(_fortran_version "")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../../projects/rocfft/CMakeLists.txt")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/../../../projects/rocfft/CMakeLists.txt" _rocfft_root)
set(_rocfft_parts "")
foreach(_part MAJOR MINOR PATCH)
string(REGEX MATCH "set[ \t]*\\([ \t]*ROCFFT_VERSION_${_part}[ \t]+\"?([0-9]+)"
_m "${_rocfft_root}")
if(_m STREQUAL "")
set(_rocfft_parts "")
break()
endif()
list(APPEND _rocfft_parts "${CMAKE_MATCH_1}")
endforeach()
if(_rocfft_parts)
list(JOIN _rocfft_parts "." _fortran_version)
endif()
unset(_rocfft_parts)
unset(_rocfft_root)
endif()

if(_fortran_version)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/rocfft-fortran-config-version.cmake"
VERSION "${_fortran_version}"
COMPATIBILITY SameMajorVersion)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/rocfft-fortran-config-version.cmake"
DESTINATION "${_fortran_pkgdir}"
COMPONENT devel)
else()
message(STATUS
"rocFFT: could not determine the version for the Fortran package, so no "
"rocfft-fortran-config-version.cmake is installed; "
"find_package(rocfft-fortran <version>) will not match.")
endif()
59 changes: 59 additions & 0 deletions bindings/fortran/rocfft/cmake/ROCmFortranCompiler.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT

# Runs check_language(Fortran), preferring ROCm's amdflang over the first
# Fortran compiler on PATH (often gfortran). An explicit CMAKE_Fortran_COMPILER
# or FC wins. CMAKE_Fortran_COMPILER is left false when none is found.

include(CheckLanguage)

# rocm-cmake's ROCMChecks watches CMAKE_Fortran_COMPILER and fails under
# ROCM_ERROR_TOOLCHAIN_VAR=ON; silence it across the writes.
set(_rocm_fc_warn_toolchain_var "${ROCM_WARN_TOOLCHAIN_VAR}")
set(_rocm_fc_error_toolchain_var "${ROCM_ERROR_TOOLCHAIN_VAR}")
set(ROCM_WARN_TOOLCHAIN_VAR OFF)
set(ROCM_ERROR_TOOLCHAIN_VAR OFF)

if(NOT CMAKE_Fortran_COMPILER AND NOT DEFINED ENV{FC})
set(_rocm_fc_hints)
foreach(_rocm_fc_cc "${CMAKE_CXX_COMPILER}" "${CMAKE_C_COMPILER}"
"${CMAKE_HIP_COMPILER}")
if(_rocm_fc_cc)
get_filename_component(_rocm_fc_dir "${_rocm_fc_cc}" DIRECTORY)
list(APPEND _rocm_fc_hints "${_rocm_fc_dir}")
endif()
endforeach()
foreach(_rocm_fc_root "${ROCM_PATH}" "$ENV{ROCM_PATH}" "/opt/rocm")
if(_rocm_fc_root)
list(APPEND _rocm_fc_hints "${_rocm_fc_root}/bin"
"${_rocm_fc_root}/lib/llvm/bin")
endif()
endforeach()
# Uncached, so a changed ROCM_PATH is honoured on reconfigure.
unset(_rocm_amdflang CACHE)
find_program(_rocm_amdflang NAMES amdflang HINTS ${_rocm_fc_hints}
NO_DEFAULT_PATH)
# A ROCm tree can carry a dangling amdflang symlink.
if(_rocm_amdflang)
execute_process(COMMAND "${_rocm_amdflang}" --version
RESULT_VARIABLE _rocm_fc_rc
OUTPUT_QUIET ERROR_QUIET)
if(_rocm_fc_rc EQUAL 0)
set(CMAKE_Fortran_COMPILER "${_rocm_amdflang}" CACHE FILEPATH
"Fortran compiler used for the ROCm Fortran bindings" FORCE)
endif()
endif()
unset(_rocm_amdflang CACHE)
endif()

check_language(Fortran)

set(ROCM_WARN_TOOLCHAIN_VAR "${_rocm_fc_warn_toolchain_var}")
set(ROCM_ERROR_TOOLCHAIN_VAR "${_rocm_fc_error_toolchain_var}")
unset(_rocm_fc_warn_toolchain_var)
unset(_rocm_fc_error_toolchain_var)
unset(_rocm_fc_hints)
unset(_rocm_fc_cc)
unset(_rocm_fc_dir)
unset(_rocm_fc_root)
unset(_rocm_fc_rc)
30 changes: 30 additions & 0 deletions bindings/fortran/rocfft/cmake/toolchains/amdflang.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# #############################################################################
# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# #############################################################################

# AMD ROCm toolchain (amdflang).
# Usage, from bindings/fortran/rocfft:
# cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/amdflang.cmake

set(CMAKE_Fortran_COMPILER amdflang CACHE FILEPATH "Fortran compiler")
set(CMAKE_C_COMPILER amdclang CACHE FILEPATH "C compiler")
30 changes: 30 additions & 0 deletions bindings/fortran/rocfft/cmake/toolchains/cray.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# #############################################################################
# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# #############################################################################

# Cray toolchain (ftn and cc wrappers; the loaded PrgEnv module picks the compiler).
# Usage, from bindings/fortran/rocfft:
# cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/cray.cmake

set(CMAKE_Fortran_COMPILER ftn CACHE FILEPATH "Fortran compiler")
set(CMAKE_C_COMPILER cc CACHE FILEPATH "C compiler")
Loading
Loading