Skip to content
Open
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
23 changes: 20 additions & 3 deletions cmake/Modules/FindCUQUANTUM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ find_library(
)
message(STATUS "CUQUANTUM_TENSORNET_LIB: ${CUQUANTUM_TENSORNET_LIB}")
message(STATUS "CUQUANTUM_CUSTATEVEC_LIB: ${CUQUANTUM_CUSTATEVEC_LIB}")
set(CUQUANTUM_LIBRARIES "${CUQUANTUM_TENSORNET_LIB};${CUQUANTUM_CUSTATEVEC_LIB}")
message(STATUS "ok")
set(CUQUANTUM_FOUND TRUE)
# Report the directory a library was actually found in (mirrors FindCUTENSOR),
# rather than the earlier guessed ${CUQUANTUM_ROOT}/${CUTNLIB_DIR}.
if(CUQUANTUM_TENSORNET_LIB)
get_filename_component(CUQUANTUM_LIBRARY_DIRS "${CUQUANTUM_TENSORNET_LIB}" DIRECTORY)
endif()
set(CUQUANTUM_LIBRARIES "")
if(CUQUANTUM_TENSORNET_LIB)
list(APPEND CUQUANTUM_LIBRARIES "${CUQUANTUM_TENSORNET_LIB}")
endif()
if(CUQUANTUM_CUSTATEVEC_LIB)
list(APPEND CUQUANTUM_LIBRARIES "${CUQUANTUM_CUSTATEVEC_LIB}")
endif()
Comment on lines +57 to +63

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.

medium

For consistency with FindCUTENSOR.cmake and to ensure that CUQUANTUM_LIBRARY_DIRS accurately reflects the actual location of the found libraries (rather than assuming a hardcoded lib subdirectory), we should dynamically retrieve the directory of the found library using get_filename_component.

if(CUQUANTUM_TENSORNET_LIB)
  get_filename_component(CUQUANTUM_LIBRARY_DIRS "${CUQUANTUM_TENSORNET_LIB}" DIRECTORY)
endif()
set(CUQUANTUM_LIBRARIES "")
if(CUQUANTUM_TENSORNET_LIB)
    list(APPEND CUQUANTUM_LIBRARIES "${CUQUANTUM_TENSORNET_LIB}")
endif()
if(CUQUANTUM_CUSTATEVEC_LIB)
    list(APPEND CUQUANTUM_LIBRARIES "${CUQUANTUM_CUSTATEVEC_LIB}")
endif()


# CUQUANTUM_FOUND must reflect whether the libraries were actually located;
# both cuTensorNet and cuStateVec are linked, so both are required. Setting it
# unconditionally would let a NOTFOUND (e.g. an "...-NOTFOUND" entry on the link
# line) silently pass the caller's REQUIRED check.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CUQUANTUM
REQUIRED_VARS CUQUANTUM_TENSORNET_LIB CUQUANTUM_CUSTATEVEC_LIB CUQUANTUM_INCLUDE_DIRS)
84 changes: 68 additions & 16 deletions cmake/Modules/FindCUTENSOR.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,56 @@ else()
endif()

message(STATUS " cudaver: ${CUDAToolkit_VERSION_MAJOR}" )
if(EXISTS "${CUTENSOR_ROOT}/lib")
set(CUTNLIB_DIR "lib/")
endif()
if((${CUDAToolkit_VERSION_MAJOR} LESS_EQUAL 10))
set(CUTNLIB_DIR "${CUTNLIB_DIR}10.2")
elseif((${CUDAToolkit_VERSION_MAJOR} GREATER_EQUAL 11) AND (${CUDAToolkit_VERSION_MAJOR} LESS 12) AND (${CUDAToolkit_VERSION_MINOR} LESS_EQUAL 0))
set(CUTNLIB_DIR "${CUTNLIB_DIR}11.0")
elseif((${CUDAToolkit_VERSION_MAJOR} GREATER_EQUAL 11) AND (${CUDAToolkit_VERSION_MAJOR} LESS 12) AND (${CUDAToolkit_VERSION_MINOR} GREATER_EQUAL 1))
set(CUTNLIB_DIR "${CUTNLIB_DIR}11")
elseif((${CUDAToolkit_VERSION_MAJOR} GREATER_EQUAL 12))
set(CUTNLIB_DIR "${CUTNLIB_DIR}12")
endif()
# Search both cuTENSOR library layouts: 2.x tarballs place the libraries
# directly under lib/, while older tarballs and apt use a per-CUDA-major
# subdir (lib/<cuda-major>, e.g. lib/11, lib/12, lib/13). Listing both as
Comment on lines +30 to +32

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This layout was changed since 2.3 not 2.x

# find_library PATH_SUFFIXES resolves either layout for any CUDA major. The
# older minor-specific lib/10.2 and lib/11.0 special-cases were removed; the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This comment is not useful for the future. It can be put in the commit message.

# generic lib/<major> covers them (apt multiarch paths remain, issue #946).
# The CUDA-version floor is a separate policy decision (issue #962), enforced
# in CMakeLists.txt rather than gated here, so this finder stays policy-free.
set(CUTNLIB_DIR lib lib/${CUDAToolkit_VERSION_MAJOR})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

CUTNLIB_DIR is not used in the new implementation.


set(CUTENSOR_LIBRARY_DIRS ${CUTENSOR_ROOT}/${CUTNLIB_DIR})
set(CUTENSOR_INCLUDE_DIRS ${CUTENSOR_ROOT}/include)

# Require cuTENSOR >= 2.0. The version macros (CUTENSOR_MAJOR/MINOR/PATCH) live
# in cutensor.h (older releases) or cutensor/types.h (newer ones); read whichever
# defines them and fail early on the 1.x API, which Cytnx no longer supports.
set(_cutensor_version_header "")
foreach(_hdr "${CUTENSOR_INCLUDE_DIRS}/cutensor.h" "${CUTENSOR_INCLUDE_DIRS}/cutensor/types.h")
if(EXISTS "${_hdr}")
file(STRINGS "${_hdr}" _cutensor_major_line REGEX "^#define[ \t]+CUTENSOR_MAJOR[ \t]+[0-9]+")
if(_cutensor_major_line)
set(_cutensor_version_header "${_hdr}")
break()
endif()
endif()
endforeach()

if(_cutensor_version_header)
file(STRINGS "${_cutensor_version_header}" _cutensor_minor_line REGEX "^#define[ \t]+CUTENSOR_MINOR[ \t]+[0-9]+")
string(REGEX REPLACE ".*CUTENSOR_MAJOR[ \t]+([0-9]+).*" "\\1" CUTENSOR_VERSION_MAJOR "${_cutensor_major_line}")
# CUTENSOR_MINOR may be absent/unmatched; default it to 0 rather than leaving
# CUTENSOR_VERSION malformed (e.g. "2."), which would break the VERSION_VAR
# comparison in find_package_handle_standard_args.
if(_cutensor_minor_line)
string(REGEX REPLACE ".*CUTENSOR_MINOR[ \t]+([0-9]+).*" "\\1" CUTENSOR_VERSION_MINOR "${_cutensor_minor_line}")
else()
set(CUTENSOR_VERSION_MINOR "0")
endif()
set(CUTENSOR_VERSION "${CUTENSOR_VERSION_MAJOR}.${CUTENSOR_VERSION_MINOR}")
Comment on lines +57 to +67

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.

medium

If CUTENSOR_MINOR is not found or fails to match the regex, _cutensor_minor_line will be empty. Performing string(REGEX REPLACE) on an empty string will result in CUTENSOR_VERSION_MINOR being empty, which leads to a malformed CUTENSOR_VERSION (e.g., 2.). This can cause version comparison failures in find_package_handle_standard_args or downstream scripts.

We should check if _cutensor_minor_line is non-empty before replacing, and default it to 0 otherwise.

  file(STRINGS "${_cutensor_version_header}" _cutensor_minor_line REGEX "^#define[ \t]+CUTENSOR_MINOR[ \t]+[0-9]+")
  string(REGEX REPLACE ".*CUTENSOR_MAJOR[ \t]+([0-9]+).*" "\\1" CUTENSOR_VERSION_MAJOR "${_cutensor_major_line}")
  if(_cutensor_minor_line)
    string(REGEX REPLACE ".*CUTENSOR_MINOR[ \t]+([0-9]+).*" "\\1" CUTENSOR_VERSION_MINOR "${_cutensor_minor_line}")
  else()
    set(CUTENSOR_VERSION_MINOR "0")
  endif()
  set(CUTENSOR_VERSION "${CUTENSOR_VERSION_MAJOR}.${CUTENSOR_VERSION_MINOR}")

message(STATUS "cuTENSOR version: ${CUTENSOR_VERSION} (from ${_cutensor_version_header})")
if(CUTENSOR_VERSION_MAJOR LESS 2)
message(FATAL_ERROR
"cuTENSOR >= 2.0 is required, but found ${CUTENSOR_VERSION} in "
"${CUTENSOR_ROOT}. Install cuTENSOR 2.x and point CUTENSOR_ROOT at it.")
endif()
else()
message(WARNING
"Could not determine the cuTENSOR version from headers under "
"${CUTENSOR_INCLUDE_DIRS}; Cytnx requires cuTENSOR >= 2.0.")
Comment on lines +75 to +77

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require a parsed cuTENSOR version before succeeding

When CUTENSOR_ROOT has a libcutensor library but the headers are missing or don't expose CUTENSOR_MAJOR in one of these two searched files, this branch only emits a warning. The subsequent find_package_handle_standard_args(... VERSION_VAR CUTENSOR_VERSION) does not fail because the repo calls find_package(CUTENSOR REQUIRED) without requesting a version, so CUTENSOR_FOUND becomes true with an empty/unknown version and UNI_CUTENSOR is enabled anyway. That defers an invalid cuTENSOR install to compile/link time, and can also let unsupported headers through when the new >=2 check cannot parse them.

Useful? React with 👍 / 👎.

endif()

# set libs:
find_library(
CUTENSOR_LIB
Expand All @@ -60,6 +94,24 @@ find_library(
)
message(STATUS "CUTENSOR_LIB: ${CUTENSOR_LIB}")
message(STATUS "CUTENSORMg_LIB: ${CUTENSORMg_LIB}")
set(CUTENSOR_LIBRARIES "${CUTENSOR_LIB};${CUTENSORMg_LIB}")
message(STATUS "ok")
set(CUTENSOR_FOUND TRUE)
# Report the directory the library was actually found in (flat lib/ or the
# versioned lib/<major>) rather than guessing a subdir, so callers and runtime
# guidance reference the real location.
if(CUTENSOR_LIB)
get_filename_component(CUTENSOR_LIBRARY_DIRS "${CUTENSOR_LIB}" DIRECTORY)
endif()
set(CUTENSOR_LIBRARIES "")
if(CUTENSOR_LIB)
list(APPEND CUTENSOR_LIBRARIES "${CUTENSOR_LIB}")
endif()
if(CUTENSORMg_LIB)
list(APPEND CUTENSOR_LIBRARIES "${CUTENSORMg_LIB}")
endif()

# CUTENSOR_FOUND must reflect whether the core library was actually located:
# the main cutensor lib is mandatory, cutensorMg is optional. Setting it
# unconditionally would let a NOTFOUND silently pass the caller's REQUIRED check.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CUTENSOR
REQUIRED_VARS CUTENSOR_LIB CUTENSOR_INCLUDE_DIRS
VERSION_VAR CUTENSOR_VERSION)
Loading