-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathCytnxBKNDCMakeLists.cmake
More file actions
468 lines (422 loc) · 23.8 KB
/
Copy pathCytnxBKNDCMakeLists.cmake
File metadata and controls
468 lines (422 loc) · 23.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
#ARPACK
# Found ahead of the BLAS/LAPACK resolution below (regardless of USE_MKL)
# so the OpenBLAS branch's runtime-dependency check can inspect ARPACK_LIB's
# own dependencies, and so it's available for the target_link_libraries(cytnx
# PRIVATE ${ARPACK_LIB}) call in the main CMakeLists.txt after this file is
# included.
find_library(ARPACK_LIB arpack REQUIRED)
message(STATUS "Found ARPACK_LIB at: ${ARPACK_LIB}")
######################################################################
### Find BLAS and LAPACK
######################################################################
if( NOT (DEFINED BLAS_LIBRARIES AND DEFINED LAPACK_LIBRARIES AND DEFINED LAPACKE_LIBRARIES))
if (USE_MKL)
#message(STATUS "ENV{MKLROOT}: $ENV{MKLROOT}")
# Set MKL interface to LP64 by default, but allow ILP64
set(MKL_INTERFACE "lp64" CACHE STRING "MKL interface (lp64 or ilp64)")
set(CYTNX_VARIANT_INFO "${CYTNX_VARIANT_INFO} UNI_MKL")
set(MKL_ROOT $ENV{MKLROOT})
message(STATUS "MKL_ROOT: ${MKL_ROOT}")
message(STATUS "MKL_INTERFACE: ${MKL_INTERFACE}")
if(MKL_INTERFACE STREQUAL "ilp64")
set(BLA_VENDOR Intel10_64ilp)
else()
set(BLA_VENDOR Intel10_64lp)
endif()
message(STATUS "BLA_VENDOR: ${BLA_VENDOR}")
find_package( BLAS REQUIRED)
find_package( LAPACK REQUIRED)
message( STATUS "LAPACK found: ${LAPACK_LIBRARIES}")
#find_package(MKL CONFIG REQUIRED)
#Provides available list of targets based on input
#message(STATUS "MKL_IMPORTED_TARGETS: ${MKL_IMPORTED_TARGETS}")
# target_compile_options(cytnx PUBLIC $<TARGET_PROPERTY:MKL::MKL,INTERFACE_COMPILE_OPTIONS>)
# target_include_directories(cytnx PUBLIC $<TARGET_PROPERTY:MKL::MKL,INTERFACE_INCLUDE_DIRECTORIES>)
# target_link_libraries(cytnx PUBLIC $<LINK_ONLY:MKL::MKL>)
# message( STATUS "MKL_LIBRARIES: ${MKL_LIBRARIES}" )
target_link_libraries(cytnx PUBLIC ${LAPACK_LIBRARIES})
target_compile_definitions(cytnx PUBLIC UNI_MKL)
else()
set(BLA_VENDOR OpenBLAS)
set(CYTNX_VARIANT_INFO "${CYTNX_VARIANT_INFO} UNI_OPENBLAS")
message(STATUS "BLA_VENDOR: ${BLA_VENDOR}")
find_package( BLAS REQUIRED)
find_package( LAPACK REQUIRED)
find_package( LAPACKE REQUIRED)
# Some OpenBLAS packagings (e.g. Fedora/RHEL's "openblas-devel", used by
# the manylinux_2_28 image) install a serial and a pthread-threaded
# build side by side, and the system's prebuilt "arpack" package (found
# as ARPACK_LIB above) can end up needing a different one than
# find_package(BLAS) above resolved (the generic "-lopenblas" name), so
# both variants get linked and both are vendored into the wheel. Rather
# than guess a vendor-specific naming convention for the "other" build,
# ask the loader what arpack actually needs, and switch to that OpenBLAS
# build if it differs, so only one variant is linked overall.
# find_package(LAPACKE) above already resolved LAPACKE_INCLUDE_DIRS
# through morse_cmake's hardened, cross-platform header search (see the
# "Vendor FindLAPACKE via Inria morse_cmake submodule" commit for why
# cytnx moved off a homegrown find_path(lapacke.h)); only the library
# selection is revisited here, since the header itself is agnostic to
# which OpenBLAS build backs it.
#
# This project only ships Linux and macOS wheels (see the
# [tool.cibuildwheel.*] sections in pyproject.toml), so `ldd`/`otool -L`
# cover every platform that needs this check; CMake's own
# file(GET_RUNTIME_DEPENDENCIES) would also work here, but its own docs
# (see Help/command/file.rst) say it "is not intended to be used in
# project mode" -- it's meant for install(CODE)/install(SCRIPT), which
# run too late to influence target_link_libraries below -- and we only
# need arpack's one direct OpenBLAS dependency, not the full recursive
# dependency graph that command computes, so a single ldd/otool call is
# enough.
set(CYTNX_ARPACK_OPENBLAS "")
if(APPLE)
execute_process(
COMMAND otool -L "${ARPACK_LIB}"
OUTPUT_VARIABLE CYTNX_ARPACK_DEPS_OUTPUT
RESULT_VARIABLE CYTNX_ARPACK_DEPS_RESULT
ERROR_QUIET
)
if(CYTNX_ARPACK_DEPS_RESULT EQUAL 0)
string(REPLACE "\n" ";" CYTNX_ARPACK_DEPS_LINES "${CYTNX_ARPACK_DEPS_OUTPUT}")
foreach(_cytnx_line ${CYTNX_ARPACK_DEPS_LINES})
if(_cytnx_line MATCHES "([^ \t]*libopenblas[^ \t]*)")
set(CYTNX_ARPACK_OPENBLAS "${CMAKE_MATCH_1}")
break()
endif()
endforeach()
endif()
elseif(UNIX)
execute_process(
COMMAND ldd "${ARPACK_LIB}"
OUTPUT_VARIABLE CYTNX_ARPACK_DEPS_OUTPUT
RESULT_VARIABLE CYTNX_ARPACK_DEPS_RESULT
ERROR_QUIET
)
if(CYTNX_ARPACK_DEPS_RESULT EQUAL 0)
string(REPLACE "\n" ";" CYTNX_ARPACK_DEPS_LINES "${CYTNX_ARPACK_DEPS_OUTPUT}")
foreach(_cytnx_line ${CYTNX_ARPACK_DEPS_LINES})
if(_cytnx_line MATCHES "libopenblas[^ \t]* => ([^ \t]+)")
set(CYTNX_ARPACK_OPENBLAS "${CMAKE_MATCH_1}")
break()
endif()
endforeach()
endif()
endif()
if(CYTNX_ARPACK_OPENBLAS)
# find_package(BLAS BLA_VENDOR OpenBLAS) can resolve BLAS_LIBRARIES to a
# bare linker flag (e.g. "-lopenblas") rather than an absolute path on
# some platforms; REALPATH on that yields a bogus path resolved against
# the current working directory, which never matches
# CYTNX_ARPACK_OPENBLAS_REAL. That's harmless here -- it just means the
# "already matches, no switch needed" fast-path below only ever fires
# when find_package returned a real path, and falls through to the
# switch (the correct, dedup-preserving direction) otherwise.
get_filename_component(CYTNX_ARPACK_OPENBLAS_REAL "${CYTNX_ARPACK_OPENBLAS}" REALPATH)
set(CYTNX_FOUND_OPENBLAS_MATCHES_ARPACK FALSE)
foreach(_cytnx_found_lib ${BLAS_LIBRARIES})
get_filename_component(_cytnx_found_lib_real "${_cytnx_found_lib}" REALPATH)
if(_cytnx_found_lib_real STREQUAL CYTNX_ARPACK_OPENBLAS_REAL)
set(CYTNX_FOUND_OPENBLAS_MATCHES_ARPACK TRUE)
endif()
endforeach()
if(NOT CYTNX_FOUND_OPENBLAS_MATCHES_ARPACK)
# arpack needs a different OpenBLAS build than find_package(BLAS)
# picked. Only switch to it if it itself exposes LAPACKE symbols
# directly (cytnx's own C++ code calls the LAPACKE C API, unlike
# arpack's Fortran BLAS/LAPACK calls, so this isn't guaranteed just
# because arpack is happy with it); otherwise leave the
# find_package() result as-is and accept both variants being linked.
include(CheckLibraryExists)
# check_library_exists() only runs its try_compile when the result
# variable is NOT DEFINED (see CheckLibraryExists.cmake); unset the
# cache entry first so a reconfigure against a different
# arpack/OpenBLAS pairing in the same build tree re-checks instead of
# reusing a stale cached result from a previous CYTNX_ARPACK_OPENBLAS.
unset(CYTNX_ARPACK_OPENBLAS_HAS_LAPACKE CACHE)
check_library_exists("${CYTNX_ARPACK_OPENBLAS}" LAPACKE_dgesdd "" CYTNX_ARPACK_OPENBLAS_HAS_LAPACKE)
if(CYTNX_ARPACK_OPENBLAS_HAS_LAPACKE)
set(BLAS_LIBRARIES "${CYTNX_ARPACK_OPENBLAS}")
set(LAPACK_LIBRARIES "${CYTNX_ARPACK_OPENBLAS}")
set(LAPACKE_LIBRARIES "${CYTNX_ARPACK_OPENBLAS}")
message(STATUS "Switching to arpack's own OpenBLAS build to avoid linking two copies: ${CYTNX_ARPACK_OPENBLAS}")
endif()
endif()
endif()
target_link_libraries(cytnx PUBLIC ${LAPACK_LIBRARIES} ${LAPACKE_LIBRARIES})
target_include_directories(cytnx PUBLIC ${LAPACKE_INCLUDE_DIRS})
message( STATUS "LAPACK found: ${LAPACK_LIBRARIES}" )
message( STATUS "LAPACKE Header found: ${LAPACKE_INCLUDE_DIRS}" )
message( STATUS "LAPACKE Library found: ${LAPACKE_LIBRARIES}" )
endif()
else()
set(LAPACK_LIBRARIES ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} ${LAPACKE_LIBRARIES})
message( STATUS "LAPACK found: ${LAPACK_LIBRARIES}")
target_link_libraries(cytnx PUBLIC ${LAPACK_LIBRARIES} ${LAPACKE_LIBRARIES})
message( STATUS "LAPACKE Header found: ${LAPACKE_INCLUDE_DIRS}" )
message( STATUS "LAPACKE Library found: ${LAPACKE_LIBRARIES}" )
endif()
if (USE_HPTT)
set(HPTT_SUBMODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/hptt")
if(NOT EXISTS "${HPTT_SUBMODULE_DIR}/CMakeLists.txt")
message(FATAL_ERROR
"thirdparty/hptt submodule missing. "
"Run: git submodule update --init --recursive")
endif()
# Declare cytnx's HPTT_ENABLE_* knobs as cache options so they show up in
# cmake-gui / ccmake with a help string and a documented OFF default
# (a bare -DHPTT_ENABLE_AVX=ON on the command line would otherwise work
# but stay invisible/undocumented).
option(HPTT_ENABLE_ARM "HPTT option ARM" OFF)
option(HPTT_ENABLE_AVX "HPTT option AVX" OFF)
option(HPTT_ENABLE_IBM "HPTT option IBM" OFF)
option(HPTT_ENABLE_FINE_TUNE "HPTT option FINE_TUNE" OFF)
# Forward cytnx's HPTT_ENABLE_* options to the names hptt's CMakeLists
# expects (ENABLE_ARM / ENABLE_AVX / ENABLE_IBM / FINE_TUNE). These four
# names are generic and unprefixed, so unset() them right after
# add_subdirectory (below) to keep them from leaking into the rest of
# this scope.
set(ENABLE_ARM "${HPTT_ENABLE_ARM}")
set(ENABLE_AVX "${HPTT_ENABLE_AVX}")
set(ENABLE_IBM "${HPTT_ENABLE_IBM}")
set(FINE_TUNE "${HPTT_ENABLE_FINE_TUNE}")
# cytnx treats hptt as a private implementation detail: no cytnx public
# header includes an hptt header, and cytnx bundles libhptt.a into its
# own export set (`install(TARGETS hptt_static EXPORT cytnx_targets)`
# below) so downstream `find_package(Cytnx)` sees `Cytnx::hptt_static`
# without needing a separate `find_package(hptt)`. Turn hptt's own
# install/export rules off so it doesn't also emit a competing
# hpttTargets.cmake / hpttConfig.cmake into the install tree.
set(HPTT_INSTALL OFF)
# Build hptt in-tree. add_subdirectory works with any CMake generator
# (no BUILD_BYPRODUCTS gymnastics like ExternalProject_Add needs under
# Ninja), is faster (no separate sub-build), and exposes hptt_static
# as a real CMake target — so we can drop the manual include_directories,
# add_dependencies, and absolute-path library link below.
add_subdirectory("${HPTT_SUBMODULE_DIR}" "${CMAKE_BINARY_DIR}/hptt")
# Drop the generic forwarding variables so a later if(ENABLE_AVX) /
# if(FINE_TUNE) elsewhere in the build doesn't see HPTT's values.
unset(ENABLE_ARM)
unset(ENABLE_AVX)
unset(ENABLE_IBM)
unset(FINE_TUNE)
# libhptt.a is linked into cytnx, which is in turn linked into the Python
# extension (a shared object), so its objects must be position-independent.
# The old ExternalProject_Add passed -DCMAKE_POSITION_INDEPENDENT_CODE=ON
# explicitly; add_subdirectory only inherits the parent's value, so set it
# on the target directly as a safety net independent of the preset.
set_property(TARGET hptt_static PROPERTY POSITION_INDEPENDENT_CODE ON)
set(CYTNX_VARIANT_INFO "${CYTNX_VARIANT_INFO} UNI_HPTT")
message(STATUS " Build HPTT Support: YES")
message(STATUS " --HPTT option FINE_TUNE: ${HPTT_ENABLE_FINE_TUNE}")
message(STATUS " --HPTT option ARM: ${HPTT_ENABLE_ARM}")
message(STATUS " --HPTT option AVX: ${HPTT_ENABLE_AVX}")
message(STATUS " --HPTT option IBM: ${HPTT_ENABLE_IBM}")
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-DUNI_HPTT\n" "")
endif() #use_HPTT
#####################################################################
### Dependency of CUTT
#####################################################################
if(USE_CUDA)
set(CYTNX_VARIANT_INFO "${CYTNX_VARIANT_INFO} UNI_CUDA")
enable_language(CUDA)
find_package(CUDAToolkit REQUIRED)
set_target_properties(cytnx PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
)
set_target_properties(cytnx PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe=--display_error_number -lineinfo -m64")
#set(CMAKE_CUDA_FLAGS "-Xcompiler=-Wall -Xcompiler=-Wno-deprecated-gpu-targets -Xcudafe=--display_error_number")
##set(CMAKE_CUDA_FLAGS "-Xcompiler=-Wall -Wno-deprecated-gpu-targets -Xcudafe=--display_error_number")
## set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-DUNI_GPU")
# set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-arch=sm_50 \
# -gencode=arch=compute_50,code=sm_50 \
# -gencode=arch=compute_52,code=sm_52 \
# -gencode=arch=compute_60,code=sm_60 \
# -gencode=arch=compute_61,code=sm_61 \
# -gencode=arch=compute_70,code=sm_70 \
# -gencode=arch=compute_75,code=sm_75 \
# -gencode=arch=compute_75,code=compute_75 ")
target_compile_definitions(cytnx PUBLIC UNI_GPU)
target_include_directories(cytnx PRIVATE ${CUDAToolkit_INCLUDE_DIRS})
# CUDA 12+/13 may place Thrust/CUB headers (incl. <cuda/std/complex>) under
# include/cccl. Detection is shared with the installed CytnxConfig.cmake so
# both use identical logic; see cmake/CytnxDetectCCCL.cmake.
include(${CMAKE_CURRENT_LIST_DIR}/cmake/CytnxDetectCCCL.cmake)
cytnx_detect_cccl_include_dir(_cytnx_cccl_dir)
if(NOT "${_cytnx_cccl_dir}" STREQUAL "")
# UNI_GPU is PUBLIC and makes the public header Type.hpp include
# <cuda/std/complex>, which CUDA 12+/13 relocate under the cccl/ subdir.
# That subdir is not part of any CUDA:: imported target's INTERFACE, so it
# must propagate to in-tree consumers (gpu_test_main, benchmarks_main,
# test_doc_cplusplus) that inherit the PUBLIC UNI_GPU macro; otherwise their
# host .cpp compilation fails with "cuda/std/complex: No such file". Wrap in
# BUILD_INTERFACE so the absolute build-machine path is not baked into the
# installed/exported target; the installed package re-detects cccl against
# the consumer's own toolkit in CytnxConfig.cmake (keeps find_package(Cytnx)
# relocatable).
target_include_directories(cytnx PUBLIC $<BUILD_INTERFACE:${_cytnx_cccl_dir}>)
message(STATUS "Detected CCCL headers at: ${_cytnx_cccl_dir}")
endif()
# Expose the detected CCCL dir so host-compiled consumers that include a
# public cytnx header pulling <cuda/std/complex> (e.g. gpu_test_main, whose
# .cpp TUs include Type.hpp) can add the same include path. cytnx adds it
# PRIVATE above, so it does not propagate through target_link_libraries.
set(CYTNX_CCCL_INCLUDE_DIR "${_cytnx_cccl_dir}" CACHE INTERNAL
"CCCL (libcu++) include dir for host-compiled consumers of cytnx public headers")
target_link_libraries(cytnx PUBLIC CUDA::toolkit)
target_link_libraries(cytnx PUBLIC CUDA::cudart CUDA::cublas CUDA::cusparse CUDA::curand CUDA::cusolver)
if(USE_CUTENSOR)
find_package(CUTENSOR REQUIRED)
if(CUTENSOR_FOUND)
target_compile_definitions(cytnx PUBLIC UNI_CUTENSOR)
target_include_directories(cytnx PUBLIC ${CUTENSOR_INCLUDE_DIRS})
target_link_libraries(cytnx PUBLIC ${CUTENSOR_LIBRARIES})
else()
message(FATAL_ERROR "cannot find cutensor! please specify cutensor root with -DCUTENSOR_ROOT")
endif()
message( STATUS "Build with CuTensor: YES")
if(MSVC)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "/DUNI_CUTENSOR\n" "")
foreach(CUTENSOR_INCLUDE_DIR IN LISTS CUTENSOR_INCLUDE_DIRS)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "/I${CUTENSOR_INCLUDE_DIR}\n" "")
endforeach()
foreach(CUTENSOR_LIBRARY IN LISTS CUTENSOR_LIBRARIES)
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUTENSOR_LIBRARY}\n" "")
endforeach()
elseif(WIN32)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-DUNI_CUTENSOR\n" "")
foreach(CUTENSOR_INCLUDE_DIR IN LISTS CUTENSOR_INCLUDE_DIRS)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-I${CUTENSOR_INCLUDE_DIR}\n" "")
endforeach()
foreach(CUTENSOR_LIBRARY IN LISTS CUTENSOR_LIBRARIES)
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUTENSOR_LIBRARY}\n" "")
endforeach()
else()
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-DUNI_CUTENSOR\n" "")
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-I${CUTENSOR_INCLUDE_DIRS}\n" "")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUTENSOR_LIBRARIES} -ldl\n" "") # use > to indicate special rt processing
endif()
message( STATUS "CuTensor: libdir:${CUTENSOR_LIBRARY_DIRS} incdir:${CUTENSOR_INCLUDE_DIRS} libs:${CUTENSOR_LIBRARIES}")
endif()
if(USE_CUQUANTUM)
find_package(CUQUANTUM REQUIRED)
if(CUQUANTUM_FOUND)
target_compile_definitions(cytnx PUBLIC UNI_CUQUANTUM)
target_include_directories(cytnx PUBLIC ${CUQUANTUM_INCLUDE_DIRS})
target_link_libraries(cytnx PUBLIC ${CUQUANTUM_LIBRARIES})
else()
message(FATAL_ERROR "cannot find cuquantum! please specify cuquantum root with -DCUQUANTUM_ROOT")
endif()
message( STATUS "Build with CuQuantum: YES")
if(MSVC)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "/DUNI_CUQUANTUM\n" "")
foreach(CUQUANTUM_INCLUDE_DIR IN LISTS CUQUANTUM_INCLUDE_DIRS)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "/I${CUQUANTUM_INCLUDE_DIR}\n" "")
endforeach()
foreach(CUQUANTUM_LIBRARY IN LISTS CUQUANTUM_LIBRARIES)
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUQUANTUM_LIBRARY}\n" "")
endforeach()
elseif(WIN32)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-DUNI_CUQUANTUM\n" "")
foreach(CUQUANTUM_INCLUDE_DIR IN LISTS CUQUANTUM_INCLUDE_DIRS)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-I${CUQUANTUM_INCLUDE_DIR}\n" "")
endforeach()
foreach(CUQUANTUM_LIBRARY IN LISTS CUQUANTUM_LIBRARIES)
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUQUANTUM_LIBRARY}\n" "")
endforeach()
else()
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-DUNI_CUQUANTUM\n" "")
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-I${CUQUANTUM_INCLUDE_DIRS}\n" "")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUQUANTUM_LIBRARIES} -ldl\n" "") # use > to indicate special rt processing
endif()
message( STATUS "CuQuantum: libdir:${CUQUANTUM_LIBRARY_DIRS} incdir:${CUQUANTUM_INCLUDE_DIRS} libs:${CUQUANTUM_LIBRARIES}")
endif()
message( STATUS " Build CUDA Support: YES")
message( STATUS " - CUDA Version: ${CUDA_VERSION_STRING}")
message( STATUS " - CUDA Toolkit Root: ${CUDA_TOOLKIT_ROOT_DIR}")
message( STATUS " - Internal macro switch: GPU/CUDA")
if(MSVC)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "/DUNI_GPU\n" "")
else()
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-DUNI_GPU\n" "")
endif()
message( STATUS " - Cudatoolkit include dir: ${CUDAToolkit_INCLUDE_DIRS}")
if(MSVC)
foreach(CUDAToolkit_INCLUDE_DIR IN LISTS CUDAToolkit_INCLUDE_DIRS)
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "/I${CUDAToolkit_INCLUDE_DIR}\n" "")
endforeach()
else()
FILE(APPEND "${CMAKE_BINARY_DIR}/cxxflags.tmp" "-I${CUDAToolkit_INCLUDE_DIRS}\n" "")
endif()
message( STATUS " - Cudatoolkit lib dir: ${CUDAToolkit_LIBRARY_DIR}")
if(MSVC)
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "/LIBPATH:${CUDAToolkit_LIBRARY_DIR}\n" "")
elseif(WIN32)
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "-L${CUDAToolkit_LIBRARY_DIR}\n" "")
else()
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "-L${CUDAToolkit_LIBRARY_DIR}\n" "")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "-Wl,-rpath,${CUDAToolkit_LIBRARY_DIR}\n" "")
endif()
message( STATUS " - CuSolver library: ${CUDA_cusolver_LIBRARY}")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_cusolver_LIBRARY}\n" "")
message( STATUS " - Curand library: ${CUDA_curand_LIBRARY}")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_curand_LIBRARY}\n" "")
message( STATUS " - CuBlas library: ${CUDA_cublas_LIBRARY}")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_cublas_LIBRARY}\n" "")
if(WIN32)
message( STATUS " - Cuda rt library: ${CUDA_cudart_static_LIBRARY}")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_cudart_static_LIBRARY}\n" "")
message( STATUS " - Cuda devrt library: ${CUDA_cudadevrt_LIBRARY}")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_cudadevrt_LIBRARY}\n" "")
else()
message( STATUS " - Cuda rt library: ${CUDA_cudart_static_LIBRARY} -ldl")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_cudart_static_LIBRARY} -ldl\n" "") # use > to indicate special rt processing
message( STATUS " - Cuda devrt library: ${CUDA_cudadevrt_LIBRARY} -lrt -lcudadevrt")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_cudadevrt_LIBRARY} -lrt -lcudadevrt\n" "") # use > to indicate special rt processing
endif()
message( STATUS " - Cuda cusparse library: ${CUDA_cusparse_LIBRARY}")
FILE(APPEND "${CMAKE_BINARY_DIR}/linkflags.tmp" "${CUDA_cusparse_LIBRARY}\n" "")
else()
message( STATUS " Build CUDA Support: NO")
endif()
#####################################################################
### Dependency of HPTT
#####################################################################
if(USE_HPTT)
target_compile_definitions(cytnx PRIVATE UNI_HPTT)
# Plain PRIVATE link to hptt_static. The encapsulated hptt keeps its
# optimization / architecture flags (`-march=native`, `-ffast-math`,
# `-O3`, …) in a PRIVATE `target_compile_options`, so they no longer
# leak into cytnx's own compilation — earlier they were PUBLIC and
# broke bit-level FP tests like `DenseUniTensorTest.Mul_UT_UT` and
# `.arange`, which forced a `$<LINK_ONLY:hptt_static>` wrap plus an
# explicit include directory. Both workarounds are gone now: cytnx's
# `Movemem_cpu.cpp` picks up `hptt.h` through hptt's PUBLIC
# `target_include_directories` (properly wrapped in
# `$<BUILD_INTERFACE:>` / `$<INSTALL_INTERFACE:>`), and PRIVATE keeps
# hptt out of cytnx's outward compile interface.
target_link_libraries(cytnx PRIVATE hptt_static)
# OpenMP must still be PUBLIC even though hptt_static is PRIVATE: libcytnx
# is a STATIC archive (`add_library(cytnx STATIC)` in CMakeLists.txt) and
# libhptt.a uses OpenMP internally, so libhptt's OpenMP symbol references
# (`__kmpc_*`, `omp_*`) stay unresolved until the consumer's final
# executable link — the consumer's link line therefore needs OpenMP to
# satisfy them. See commit 5733a441 ("Propagate `-fopenmp` linking flag
# when using HPTT").
find_package(OpenMP REQUIRED)
target_link_libraries(cytnx PUBLIC OpenMP::OpenMP_CXX)
# cytnx is a STATIC archive, so its PRIVATE link to hptt_static is still
# recorded in INTERFACE_LINK_LIBRARIES as `$<LINK_ONLY:hptt_static>`
# (a static archive can't absorb another archive's objects, so the
# consumer's final link must pull libhptt.a in too). CMake then requires
# every target referenced by an exported target to itself be in some
# export set. Bundle hptt_static into cytnx's own cytnx_targets export
# (it surfaces downstream as `Cytnx::hptt_static`) so a consumer's
# `find_package(Cytnx)` resolves it without a separate
# `find_package(hptt)`; otherwise `install(EXPORT cytnx_targets)` fails
# with "target hptt_static is not in any export set".
install(TARGETS hptt_static EXPORT cytnx_targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Development)
endif()