[hipsolver] Refactor build system#2
Conversation
| target_link_libraries(hipsolver-bench PRIVATE | ||
| ${LAPACK_LIBRARIES} | ||
| hipsolver-common | ||
| clients-common | ||
| roc::hipsolver | ||
| ${LAPACK_LIBRARIES} | ||
| hipsolver-clients-common | ||
| roc::hipsolver | ||
| ) |
There was a problem hiding this comment.
Remove redundant direct link to roc::hipsolver
The roc::hipsolver target is already linked as a PUBLIC dependency of hipsolver-clients-common (defined at clients/CMakeLists.txt line 61). Listing it again here creates redundancy in the dependency graph. The transitive link from hipsolver-clients-common already propagates roc::hipsolver to hipsolver-bench, making the explicit link unnecessary.
Recommended action: Remove roc::hipsolver from this target_link_libraries() call to simplify the dependency graph and avoid duplication.
| target_link_libraries(hipsolver-bench PRIVATE | |
| ${LAPACK_LIBRARIES} | |
| hipsolver-common | |
| clients-common | |
| roc::hipsolver | |
| ${LAPACK_LIBRARIES} | |
| hipsolver-clients-common | |
| roc::hipsolver | |
| ) | |
| target_link_libraries(hipsolver-bench PRIVATE | |
| ${LAPACK_LIBRARIES} | |
| hipsolver-clients-common | |
| ) |
Generated by Claude Code
| target_link_libraries(hipsolver-test PRIVATE | ||
| ${LAPACK_LIBRARIES} | ||
| hipsolver-common | ||
| clients-common | ||
| $<IF:$<TARGET_EXISTS:GTest::gtest>,GTest::gtest,GTest::GTest> | ||
| Threads::Threads | ||
| roc::hipsolver | ||
| ${LAPACK_LIBRARIES} | ||
| hipsolver-clients-common | ||
| $<IF:$<TARGET_EXISTS:GTest::gtest>,GTest::gtest,GTest::GTest> | ||
| Threads::Threads | ||
| roc::hipsolver | ||
| ) |
There was a problem hiding this comment.
Remove redundant direct link to roc::hipsolver
Same redundancy as in the benchmarks: roc::hipsolver is already linked transitively through hipsolver-clients-common (which declares it PUBLIC at clients/CMakeLists.txt:61). The explicit link here is unnecessary.
Recommended action: Remove roc::hipsolver from this target_link_libraries() call to eliminate the redundant dependency declaration.
| target_link_libraries(hipsolver-test PRIVATE | |
| ${LAPACK_LIBRARIES} | |
| hipsolver-common | |
| clients-common | |
| $<IF:$<TARGET_EXISTS:GTest::gtest>,GTest::gtest,GTest::GTest> | |
| Threads::Threads | |
| roc::hipsolver | |
| ${LAPACK_LIBRARIES} | |
| hipsolver-clients-common | |
| $<IF:$<TARGET_EXISTS:GTest::gtest>,GTest::gtest,GTest::GTest> | |
| Threads::Threads | |
| roc::hipsolver | |
| ) | |
| target_link_libraries(hipsolver-test PRIVATE | |
| ${LAPACK_LIBRARIES} | |
| hipsolver-clients-common | |
| $<IF:$<TARGET_EXISTS:GTest::gtest>,GTest::gtest,GTest::GTest> | |
| Threads::Threads | |
| ) |
Generated by Claude Code
| $<BUILD_INTERFACE:${CUDA_INCLUDE_DIRS}> | ||
| ) | ||
| if(NOT HIPSOLVER_ENABLE_CUDA) | ||
| target_link_libraries(hipsolver-bench PRIVATE hip::host) |
There was a problem hiding this comment.
Remove redundant link to hip::host (already transitively available)
The hip::host target is already linked as a PUBLIC dependency of roc::hipsolver (see library/src/CMakeLists.txt line 109). Since hipsolver-bench links hipsolver-clients-common, which in turn links roc::hipsolver PUBLIC, the hip::host target is already transitively available. This direct link is redundant.
Recommended action: Remove this hip::host link to keep the dependency graph clean. Note that the same redundancy exists in the gtest CMakeLists.txt at line 119 and should be addressed there as well.
Generated by Claude Code
There was a problem hiding this comment.
@ibrahimw1 hip::host and hip::device should never be public deps. I thought we had rule for this.
| else() | ||
| target_compile_definitions(hipsolver-test PRIVATE __HIP_PLATFORM_NVIDIA__) | ||
| if(NOT HIPSOLVER_ENABLE_CUDA) | ||
| target_link_libraries(hipsolver-test PRIVATE hip::host) |
There was a problem hiding this comment.
Remove redundant link to hip::host (already transitively available)
The hip::host target is already a PUBLIC transitive dependency of roc::hipsolver, which is linked through hipsolver-clients-common. This direct link is redundant.
Recommended action: Remove this hip::host link to simplify the dependency graph. Also review the CUSTOM_TARGET link at line 122 for the same potential redundancy.
Generated by Claude Code
|
|
||
| if(NOT DEFINED CMAKE_Fortran_COMPILER AND NOT DEFINED ENV{FC}) | ||
| set(CMAKE_Fortran_COMPILER "gfortran") | ||
| set(CMAKE_Fortran_COMPILER "gfortran") |
There was a problem hiding this comment.
Hard-coding CMAKE_Fortran_COMPILER violates CMake conventions
Setting CMAKE_Fortran_COMPILER to a hard-coded value ("gfortran") in CMakeLists.txt overrides CMake's standard compiler detection mechanism. CMake automatically searches for a Fortran compiler when enable_language(Fortran) is called. The standard approach for controlling compiler selection is to use the FC environment variable or pass -DCMAKE_Fortran_COMPILER=... on the command line.
This set() call prevents users from selecting their preferred Fortran compiler and makes the build less flexible.
Recommended action: Remove this block entirely and let CMake handle compiler detection through enable_language(Fortran). If a default is needed for your development environment, document it in CMakePresets.json or a toolchain file rather than hard-coding it in the main CMakeLists.txt.
Generated by Claude Code
| option(HIPSOLVER_ENABLE_BENCHMARKS "Build hipSOLVER benchmarks." OFF) | ||
| option(HIPSOLVER_ENABLE_SAMPLES "Build hipSOLVER samples." OFF) | ||
| option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compile_commands.json for clang tooling support." ON) | ||
|
|
There was a problem hiding this comment.
Do not declare CMAKE_EXPORT_COMPILE_COMMANDS as an option()
CMAKE_EXPORT_COMPILE_COMMANDS is a built-in CMake variable, not a project-specific option. Declaring it with option() will override the user's setting even when they explicitly pass -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF on the command line. The presets already configure this variable in the base preset.
Recommended action: Remove this line. If you want to provide a default when the variable is not already defined, use:
if(NOT DEFINED CMAKE_EXPORT_COMPILE_COMMANDS)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()Generated by Claude Code
There was a problem hiding this comment.
I don't think that this is quite right.
| file(GLOB third_party_dlls | ||
| LIST_DIRECTORIES OFF | ||
| CONFIGURE_DEPENDS | ||
| ${cblas_DIR}/bin/*.dll | ||
| ${GTest_DIR}/bin/*.dll | ||
| $ENV{rocblas_DIR}/bin/*.dll | ||
| $ENV{rocsolver_DIR}/bin/*.dll | ||
| $ENV{HIP_DIR}/bin/*.dll | ||
| $ENV{HIP_DIR}/bin/hipinfo.exe | ||
| ${CMAKE_SOURCE_DIR}/rtest.* | ||
| ) |
There was a problem hiding this comment.
Avoid environment variables for dependency path resolution in file(GLOB)
This file(GLOB) block relies on environment variables ($ENV{rocblas_DIR}, $ENV{rocsolver_DIR}, $ENV{HIP_DIR}) to locate DLL files at configure time. Using environment variables for dependency paths creates fragile, non-reproducible builds that can break when the environment changes.
Additionally, line 156 uses ${CMAKE_SOURCE_DIR} which assumes this is the top-level project. This is unsafe for projects that might be consumed via add_subdirectory() and should be ${PROJECT_SOURCE_DIR} instead.
Recommended action: Resolve these paths via find_package() target properties or CMAKE_PREFIX_PATH to make the build more robust and reproducible. Change CMAKE_SOURCE_DIR to PROJECT_SOURCE_DIR for proper subdirectory support.
Generated by Claude Code
| set_target_properties(hipsolver PROPERTIES CXX_EXTENSIONS OFF) | ||
|
|
||
| # Warning suppression (was in hipsolver-common INTERFACE library) | ||
| target_compile_options(hipsolver PRIVATE -Wno-unused-result) |
There was a problem hiding this comment.
Preserve TODO comment explaining -Wno-unused-result suppression
The comment indicates this flag was moved from the hipsolver-common INTERFACE library, but the original code included a TODO comment about addressing [[nodiscard]] warnings. Preserving that TODO ensures the warning suppression is not forgotten and signals that this is temporary technical debt.
Recommended action: Update the comment to include the TODO, for example:
# TODO: address [[nodiscard]] warnings — suppress for now
target_compile_options(hipsolver PRIVATE -Wno-unused-result)Generated by Claude Code
There was a problem hiding this comment.
Don't know how I feel about this i.e. not certain it is worth the context to bother with this type of feedback. Maybe we should consider having different tiers and applying them in waves or something.
| "hidden": true, | ||
| "binaryDir": "${sourceDir}/build/${presetName}", | ||
| "cacheVariables": { | ||
| "CMAKE_CXX_COMPILER": "/opt/rocm/bin/amdclang++", |
There was a problem hiding this comment.
Hard-coded compiler paths reduce preset portability
The base preset hard-codes CMAKE_CXX_COMPILER and CMAKE_C_COMPILER to /opt/rocm/bin/amdclang++ and /opt/rocm/bin/amdclang. This makes the preset non-portable across environments where ROCm is installed at a different location or where developers want to use alternative compilers.
Recommended action: Consider one of these approaches:
- Remove the compiler variables from the
basepreset and letCMAKE_PREFIX_PATHguide compiler discovery - Create a separate
CMakeUserPresets.json(git-ignored) for developer-specific paths - Add a comment explaining that developers should override these in a user preset
This will make the preset more flexible and portable across different development environments.
Generated by Claude Code
| target_link_libraries(hipsolver-clients-common | ||
| PUBLIC roc::hipsolver | ||
| PRIVATE Threads::Threads | ||
| ) |
There was a problem hiding this comment.
Clarify linking strategy for roc::hipsolver on OBJECT library
hipsolver-clients-common is an OBJECT library whose compiled objects are incorporated into the final executables (hipsolver-test, hipsolver-bench). Linking roc::hipsolver PUBLIC here means every consumer of this OBJECT library inherits roc::hipsolver transitively, which creates redundancy since downstream targets (hipsolver-bench and hipsolver-test) also explicitly link roc::hipsolver.
Recommended action: Choose one of these approaches for consistency:
- Option A (preferred): Keep
roc::hipsolverPUBLIC onhipsolver-clients-commonand remove the redundant explicit links fromhipsolver-benchandhipsolver-test - Option B: Change to PRIVATE here and keep the explicit links in the downstream targets
Option A is cleaner and reduces duplication noted in other comments.
Generated by Claude Code
| # --- Include directories --- | ||
|
|
||
| target_include_directories(hipsolver | ||
| PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/library/include> | ||
| $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/library/include/internal> | ||
| $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/hipsolver> | ||
| $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/hipsolver/internal> | ||
| $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include> | ||
| $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | ||
| PRIVATE | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/include | ||
| ${CMAKE_CURRENT_SOURCE_DIR} | ||
| PUBLIC | ||
| $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/library/include> | ||
| $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/library/include/internal> |
There was a problem hiding this comment.
Fix PDB copy command generator expression to handle non-Debug builds
The PDB copy command on line 141 uses "$<$<CONFIG:Debug>:${CMAKE_COMMAND}>" as the COMMAND argument. When the build configuration is not Debug, this evaluates to an empty string, causing the add_custom_command to fail because COMMAND becomes invalid.
Recommended action: Restructure this to properly handle both Debug and non-Debug configurations. For example:
add_custom_command(TARGET hipsolver POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
$<IF:$<CONFIG:Debug>,copy,true>
"${PROJECT_BINARY_DIR}/staging/$<TARGET_PDB_FILE_NAME:hipsolver>"
"${PROJECT_BINARY_DIR}/clients/staging/$<TARGET_PDB_FILE_NAME:hipsolver>"
)Alternatively, wrap the entire add_custom_command in a conditional block that only executes for Debug configurations. The current pattern will cause build failures in Release and other non-Debug configurations.
Generated by Claude Code
PR Review SummaryRecommendation: Approve with suggestions This is a well-structured modernization of the hipSOLVER CMake build system. Key improvements include:
The main issues to address are:
None of these are build-breaking, but addressing them will improve the quality and maintainability of this already excellent refactoring work.
Generated by Claude Code |
Motivation
hipSOLVER's CMake build system used legacy directory-scoped patterns (global
include_directories(),link_directories(),add_definitions()) that cause scope pollution, make dependencies implicit, and complicatemaintenance. This refactoring modernizes the build system to use target-centric design with explicit dependency
propagation.
Goals:
Technical Details
Root CMakeLists.txt
library/andclients/subdirectorieslibrary/CMakeLists.txt
hipsolvertarget to modern target-centric designinclude_directories()withtarget_include_directories()(PUBLIC/PRIVATE scoping)link_libraries()withtarget_link_libraries()with explicit visibilityINTERFACE_INCLUDE_DIRECTORIESfor downstream consumersroc::hipsolver)find_package(hipsolver)supportclients/CMakeLists.txt
hipsolver-test,hipsolver-bench, etc.)CMakePresets.json
CMAKE_CXX_COMPILERto match ROCm toolchainKey Improvements
targets
roc::hipsolvernamespace for clarityfind_package(hipsolver)in downstream projectsValidation Results
Configuration equivalence: ✅ PASS
Build artifact equivalence: ✅ PASS
Install tree equivalence: ✅ PASS
Test Plan
Test Result
Submission Checklist