From 864907799af182390fa5cf359300df672410bbc2 Mon Sep 17 00:00:00 2001 From: John Biddiscombe Date: Mon, 28 Apr 2025 11:32:26 +0200 Subject: [PATCH] CMake tweaks and cleanup to help with alps uenv builds gitignore for merge file backups etc --- .gitignore | 1 + CMakeLists.txt | 92 ++++++++++--- CMakeUserPresets.json | 64 +++++++++ README.md | 14 +- alpine/CMakeLists.txt | 2 +- cmake/CompilerOptions.cmake | 18 ++- cmake/Dependencies.cmake | 241 ++++++++++++++++++++++----------- cmake/Messages.cmake | 46 +++++++ cmake/Platforms.cmake | 52 +++---- cmake/ProjectSetup.cmake | 46 +++---- cmake/Version.cmake | 20 --- doc/extras/IPPLonEULER.md | 32 ++--- src/CMakeLists.txt | 8 +- src/Communicate/CMakeLists.txt | 2 + src/FFT/CMakeLists.txt | 2 + src/Types/Variant.h | 2 +- test/field/CMakeLists.txt | 6 +- 17 files changed, 441 insertions(+), 207 deletions(-) create mode 100644 CMakeUserPresets.json create mode 100644 cmake/Messages.cmake delete mode 100644 cmake/Version.cmake diff --git a/.gitignore b/.gitignore index 65eb5e505..97e98882a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ manual/ippl_user_guide.pdf build*/ *~ *.~ +*.orig # ignore build directories build*/ diff --git a/CMakeLists.txt b/CMakeLists.txt index f53d3b5a4..4eb9d83d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,32 +1,88 @@ -cmake_minimum_required(VERSION 3.20) +# ------------------------------------------------------------------------------ +# CMake version requirement +# ------------------------------------------------------------------------------ +cmake_minimum_required(VERSION 3.24) -set(CMAKE_CXX_FLAGS_DEBUG_INIT "-O0 -g") -set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O3 -g") +# ------------------------------------------------------------------------------ +# Policies - use the latest of everything +# ------------------------------------------------------------------------------ +cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) -project(IPPL LANGUAGES CXX VERSION 3.0.2) +# ------------------------------------------------------------------------------ +# Project declaration and version +# ------------------------------------------------------------------------------ +project(IPPL VERSION 3.2 LANGUAGES CXX) -list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +# Symbolic version string (for CLI, logs, headers, etc.) +set(IPPL_VERSION_NAME "IPPL v${IPPL_VERSION}") -option(IPPL_ENABLE_UNIT_TESTS "Enable unit tests using GoogleTest" OFF) -option(IPPL_ENABLE_FFT "Enable FFT support" OFF) -option(IPPL_ENABLE_SOLVERS "Enable IPPL solvers" OFF) -option(IPPL_ENABLE_ALPINE "Enable building the Alpine module" OFF) -option(IPPL_ENABLE_COSMOLOGY "Enable building the Cosmology module" OFF) -option(IPPL_ENABLE_TESTS "Build integration tests in test/ directory" OFF) -option(IPPL_DYL "Build IPPL as a shared library (ON) or static library (OFF)" OFF) -option(IPPL_ENABLE_COVERAGE "Enable code coverage" OFF) -option(IPPL_ENABLE_NSYS_PROFILER "Enable Nvidia Nsys Profiler" OFF) -option(IPPL_ENABLE_SANITIZER "Enable sanitizer(s)" OFF) -option(USE_ALTERNATIVE_VARIANT "Use modified variant implementation (required for CUDA 12.2 + GCC 12.3.0)" OFF) +message(STATUS + "📦 Configuring IPPL Version: ${IPPL_VERSION_MAJOR}.${IPPL_VERSION_MINOR} : \"${IPPL_VERSION_NAME}\"" +) +# ------------------------------------------------------------------------------ +# Module path +# ------------------------------------------------------------------------------ +list(PREPEND CMAKE_MODULE_PATH + "${PROJECT_SOURCE_DIR}/cmake" "${PROJECT_SOURCE_DIR}/CMakeModules") +# ------------------------------------------------------------------------------ +# Primary IPPL options +# ------------------------------------------------------------------------------ +option(IPPL_ENABLE_UNIT_TESTS "Enable unit tests using GoogleTest" OFF) +option(IPPL_ENABLE_FFT "Enable FFT support" OFF) +option(IPPL_ENABLE_SOLVERS "Enable IPPL solvers" OFF) +option(IPPL_ENABLE_ALPINE "Enable building the Alpine module" OFF) +option(IPPL_ENABLE_COSMOLOGY "Enable building the Cosmology module" OFF) +option(IPPL_ENABLE_TESTS "Build integration tests in test/ directory" OFF) +option(IPPL_DYL "Build IPPL as a shared library (ON) or static library (OFF)" OFF) +option(IPPL_ENABLE_COVERAGE "Enable code coverage" OFF) +option(IPPL_ENABLE_NSYS_PROFILER "Enable Nvidia Nsys Profiler" OFF) +option(IPPL_ENABLE_SANITIZER "Enable sanitizer(s)" OFF) +option(IPPL_USE_ALTERNATIVE_VARIANT "Use modified variant implementation (required for CUDA 12.2 + GCC 12.3.0)" OFF) +option(IPPL_USE_STANDARD_FOLDERS "Put all generated binaries in bin/lib folders" OFF) + +# ------------------------------------------------------------------------------ +# Setup Output directories +# ------------------------------------------------------------------------------ +if (IPPL_USE_STANDARD_FOLDERS) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY + ${PROJECT_BINARY_DIR}/bin + CACHE PATH "Single Directory for all Executables.") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY + ${PROJECT_BINARY_DIR}/lib + CACHE PATH "Single Directory for all Libraries") + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY + ${PROJECT_BINARY_DIR}/lib + CACHE PATH "Single Directory for all static libraries.") +endif() + +# ------------------------------------------------------------------------------ +# cmake modules +# ------------------------------------------------------------------------------ +# cmake supplied +include(GNUInstallDirs) +include(FetchContent) +include(CMakePackageConfigHelpers) +# custom ones +include(Messages) include(ProjectSetup) -include(Version) +include(ExternalProject) include(CompilerOptions) include(Platforms) include(Dependencies) +# ------------------------------------------------------------------------------ +# Deprecated vars +# ------------------------------------------------------------------------------ +if(DEFINED USE_ALTERNATIVE_VARIANT) + colour_message(WARNING ${Red} "USE_ALTERNATIVE_VARIANT is deprecated. Please set IPPL_USE_ALTERNATIVE_VARIANT instead.") + set(IPPL_USE_ALTERNATIVE_VARIANT ${USE_ALTERNATIVE_VARIANT}) +endif() + +# ------------------------------------------------------------------------------ +# Define sources for project +# ------------------------------------------------------------------------------ add_subdirectory(src) if (IPPL_ENABLE_UNIT_TESTS OR IPPL_ENABLE_TESTS) diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json new file mode 100644 index 000000000..7b2cca29e --- /dev/null +++ b/CMakeUserPresets.json @@ -0,0 +1,64 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 24, + "patch": 0 + }, + "configurePresets": [ + { + "name": "testing", + "hidden": true, + "cacheVariables": { + "IPPL_ENABLE_TESTS": "ON", + "IPPL_ENABLE_UNIT_TESTS": "ON" + } + }, + { + "name": "default", + "displayName": "Default", + "description": "Default build, release mode with most common options", + "generator": "Unix Makefiles", + "cacheVariables": { + "BUILD_SHARED_LIBS": "ON", + "CMAKE_BUILD_TYPE": "Release", + "Kokkos_VERSION_DEFAULT": "4.5.01", + "Heffte_VERSION_DEFAULT": "2.4.0", + "IPPL_PLATFORMS": "OPENMP;CUDA", + "IPPL_ENABLE_FFT": "ON", + "IPPL_ENABLE_ALPINE": "ON", + "IPPL_ENABLE_COSMOLOGY": "ON", + "IPPL_ENABLE_TESTS": "OFF", + "IPPL_ENABLE_UNIT_TESTS": "OFF", + "IPPL_USE_STANDARD_FOLDERS": "ON" + } + }, + { + "name": "fetch", + "displayName": "ForceDownload", + "description": "Always downloads dependencies", + "inherits": ["default"], + "cacheVariables": { + "Kokkos_VERSION": "git.4.5.01", + "Heffte_VERSION": "git.9eab7c0eb18e86acaccc2b5699b30e85a9e7bdda" + } + }, + { + "name": "release-testing", + "displayName": "Testing(Release)", + "description": "Enables building test in release mode", + "inherits": ["testing", "default"] + }, + { + "name": "debug-testing", + "displayName": "Testing(Debug)", + "description": "Enables building test in debug mode", + "inherits": ["testing", "default"], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "IPPL_ENABLE_SANITIZER": "ON", + "IPPL_PLATFORMS": "SERIAL" + } + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 8c6e14344..6dea0c73b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![License](https://img.shields.io/github/license/IPPL-framework/ippl)](https://github.com/IPPL-framework/ippl/blob/master/LICENSE) # Independent Parallel Particle Layer (IPPL) -Independent Parallel Particle Layer (IPPL) is a performance portable C++ library for Particle-Mesh methods. IPPL makes use of Kokkos (https://github.com/kokkos/kokkos), HeFFTe (https://github.com/icl-utk-edu/heffte), and MPI (Message Passing Interface) to deliver a portable, massively parallel toolkit for particle-mesh methods. IPPL supports simulations in one to six dimensions, mixed precision, and asynchronous execution in different execution spaces (e.g. CPUs and GPUs). +Independent Parallel Particle Layer (IPPL) is a performance portable C++ library for Particle-Mesh methods. IPPL makes use of Kokkos (https://github.com/kokkos/kokkos), HeFFTe (https://github.com/icl-utk-edu/heffte), and MPI (Message Passing Interface) to deliver a portable, massively parallel toolkit for particle-mesh methods. IPPL supports simulations in one to six dimensions, mixed precision, and asynchronous execution in different execution spaces (e.g. CPUs and GPUs). All IPPL releases (< 3.2.0) are available under the BSD 3-clause license. Since version 3.2.0, this repository includes a modified version of the `variant` header by GNU, created to support compilation under CUDA 12.2 with GCC 12.3.0. This header file is available under the same terms as the [GNU Standard Library](https://github.com/gcc-mirror/gcc); note the GNU runtime library exception. As long as this file is not removed, IPPL is available under GNU GPL version 3. @@ -42,11 +42,11 @@ The relevant options of IPPL are - `IPPL_ENABLE_FFT`, default `OFF` - If `IPPL_ENABLE_FFT` is set, `Heffte_ENABLE_CUDA` will default to `ON` if `IPPL_PLATFORMS` contains `cuda` - Otherwise, `Heffte_ENABLE_AVX2` is enabled. FFTW has to be enabled explicitly. -- `Heffte_ENABLE_FFTW`, default `OFF` +- `Heffte_ENABLE_FFTW`, default `OFF` - `IPPL_ENABLE_TESTS`, default `OFF` - `IPPL_ENABLE_UNIT_TESTS`, default `OFF` - `IPPL_ENABLE_ALPINE`, default `OFF` -- `USE_ALTERNATIVE_VARIANT`, default `OFF`. Can turned on for GPU builds where the use of the system-provided variant doesn't work. +- `IPPL_USE_ALTERNATIVE_VARIANT`, default `OFF`. Can turned on for GPU builds where the use of the system-provided variant doesn't work. - `IPPL_ENABLE_SANITIZER, default `OFF` - Furthermore, be aware of `CMAKE_BUILD_TYPE`, which can be either @@ -82,7 +82,7 @@ cmake .. \ -DIPPL_PLATFORMS=openmp \ -DHeffte_ENABLE_FFTW=True ``` -#### Cuda alpine release build +#### Cuda alpine release build ``` cmake .. \ -DCMAKE_BUILD_TYPE=Release \ @@ -90,12 +90,12 @@ cmake .. \ -DCMAKE_CXX_STANDARD=20 \ -DIPPL_ENABLE_FFT=ON \ -DIPPL_ENABLE_TESTS=ON \ - -DUSE_ALTERNATIVE_VARIANT=ON \ + -DIPPL_USE_ALTERNATIVE_VARIANT=ON \ -DIPPL_ENABLE_SOLVERS=ON \ -DIPPL_ENABLE_ALPINE=True \ -DIPPL_PLATFORMS=cuda ``` -#### HIP release build (LUMI) +#### HIP release build (LUMI) ``` cmake .. \ -DCMAKE_BUILD_TYPE=Release \ @@ -135,7 +135,7 @@ m-6.0.3/lib/llvm/lib" # Contributions We are open and welcome contributions from others. Please open an issue and a corresponding pull request in the main repository if it is a bug fix or a minor change. -For larger projects we recommend to fork the main repository and then submit a pull request from it. More information regarding github workflow for forks can be found in this [page](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks) and how to submit a pull request from a fork can be found [here](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). Please follow the coding guidelines as mentioned in this [page](https://github.com/IPPL-framework/ippl/blob/master/WORKFLOW.md). +For larger projects we recommend to fork the main repository and then submit a pull request from it. More information regarding github workflow for forks can be found in this [page](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks) and how to submit a pull request from a fork can be found [here](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). Please follow the coding guidelines as mentioned in this [page](https://github.com/IPPL-framework/ippl/blob/master/WORKFLOW.md). You can add an upstream to be able to get all the latest changes from the master. For example, if you are working with a fork of the main repository, you can add the upstream by: ```bash diff --git a/alpine/CMakeLists.txt b/alpine/CMakeLists.txt index e05921a1d..428a300c5 100644 --- a/alpine/CMakeLists.txt +++ b/alpine/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(ExamplesWithoutPicManager) set(COMMON_LIBS ippl - ${MPI_CXX_LIBRARIES} + MPI::MPI_CXX ) set(COMMON_FLAGS diff --git a/cmake/CompilerOptions.cmake b/cmake/CompilerOptions.cmake index 0c9f8ec24..f96dfe081 100644 --- a/cmake/CompilerOptions.cmake +++ b/cmake/CompilerOptions.cmake @@ -10,13 +10,12 @@ # # Not responsible for: # - Enabling CUDA/OpenMP/Serial → Platforms.cmake -# - Selecting platform specific compiler flags → Platforms.cmake +# - Selecting platform specific compiler flags → Platforms.cmake # # # This file is only concerned with general correctness and development-time safety. # ----------------------------------------------------------------------------- - # === Basic warnings (apply to all builds) === add_compile_options( -Wall @@ -25,8 +24,8 @@ add_compile_options( ) # === Use modified variant implementation === -if (USE_ALTERNATIVE_VARIANT) - add_definitions (-DUSE_ALTERNATIVE_VARIANT) +if (IPPL_USE_ALTERNATIVE_VARIANT) + add_definitions (-DIPPL_USE_ALTERNATIVE_VARIANT) endif() # === Code coverage options === @@ -57,9 +56,14 @@ endif() # === Debug-specific sanitizers === if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND IPPL_ENABLE_SANITIZER) message(STATUS "✅ Enabling AddressSanitizer and UBSan for Debug build") - add_compile_options(-fsanitize=address,undefined) - add_link_options(-fsanitize=address,undefined) + add_compile_options(-fsanitize=address) + add_link_options(-fsanitize=address) endif() -message(STATUS "✅ Compiler options configured") +# === Position Independent Code (PIC) for shared libraries === +if(BUILD_SHARED_LIBS) + message(STATUS "✅ Enabling Position Independent Code (PIC) for shared libraries") + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() +message(STATUS "✅ Compiler options configured") diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 955d292e2..627108907 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -14,99 +14,180 @@ # ----------------------------------------------------------------------------- include(FetchContent) -# === Kokkos === -set(Kokkos_VERSION "4.5.00") -message(STATUS "🔍 Looking for Kokkos ${Kokkos_VERSION}") - -find_package(Kokkos ${Kokkos_VERSION} QUIET) -if(NOT Kokkos_FOUND) - message(STATUS "📥 Kokkos not found — using FetchContent") - FetchContent_Declare( - kokkos - URL https://github.com/kokkos/kokkos/archive/refs/tags/${Kokkos_VERSION}.tar.gz - DOWNLOAD_EXTRACT_TIMESTAMP ON - ) - FetchContent_MakeAvailable(kokkos) +# ------------------------------------------------------------------------------ +# MPI +# ------------------------------------------------------------------------------ +find_package(MPI COMPONENTS CXX REQUIRED) +colour_message(STATUS ${Green} "✅ MPI found ${MPI_CXX_VERSION}") + +# ------------------------------------------------------------------------------ +# CUDA +# ------------------------------------------------------------------------------ +if("CUDA" IN_LIST IPPL_PLATFORMS) + find_package(CUDAToolkit REQUIRED) + colour_message(STATUS ${Green} "✅ CUDA platform requested and CUDAToolkit found ${CUDAToolkit_VERSION}") endif() -message(STATUS "✅ Kokkos ready") +# ------------------------------------------------------------------------------ +# OpenMP +# ------------------------------------------------------------------------------ +if("OPENMP" IN_LIST IPPL_PLATFORMS) + find_package(OpenMP REQUIRED) + colour_message(STATUS ${Green} "✅ OpenMP platform requested OpenMP found ${OPENMP_VERSION}") +endif() -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(Heffte_ENABLE_AVX2 OFF CACHE BOOL "" FORCE) - set(Heffte_ENABLE_CUDA OFF CACHE BOOL "" FORCE) - message(STATUS "❗ Disabling AVX2 and CUDA in Debug build") +# ------------------------------------------------------------------------------ +# Utility function to clear a list of vars one by one +# ------------------------------------------------------------------------------ +function(unset_vars) + foreach(VAR IN LISTS ARGN) + unset(${VAR} PARENT_SCOPE) + endforeach() +endfunction() + +# ------------------------------------------------------------------------------ +# Utility function to get git tag/sha/version from version string +# ------------------------------------------------------------------------------ +function(extract_git_label VERSION_STRING RESULT_VAR) + if("${${VERSION_STRING}}" MATCHES "^git\\.(.+)$") + set(${RESULT_VAR} "${CMAKE_MATCH_1}" PARENT_SCOPE) + else() + unset(${RESULT_VAR} PARENT_SCOPE) + endif() +endfunction() + +# ------------------------------------------------------------------------------ +# Kokkos +# Use find_package with mininimum version requested, +# if that's not found, or not ok (has wrong backends etc), then build from source +# ------------------------------------------------------------------------------ +# set the default version of kokkos we will ask for if not already set +if (NOT Kokkos_VERSION_DEFAULT) + set(Kokkos_VERSION_DEFAULT 4.5.00) +endif() +# if the user has not asked for a specific version, we will use the default +if (NOT Kokkos_VERSION) + set(Kokkos_VERSION ${Kokkos_VERSION_DEFAULT}) endif() -# === Heffte (only if FFT enabled) === -if(IPPL_ENABLE_FFT) - add_compile_definitions(IPPL_ENABLE_FFT) +# is Kokkos_VERSION a git tag/branch/sha +extract_git_label(Kokkos_VERSION KOKKOS_VERSION_GIT) +if (KOKKOS_VERSION_GIT) + # the user has asked for a particular version built from source + set(kokkos_fetch + GIT_TAG ${KOKKOS_VERSION_GIT} + GIT_REPOSITORY https://github.com/kokkos/kokkos.git) +else() + # the user has asked for a version - use find or checkout if needed + set(kokkos_fetch + GIT_TAG ${Kokkos_VERSION} + GIT_REPOSITORY https://github.com/kokkos/kokkos.git + FIND_PACKAGE_ARGS ${Kokkos_VERSION} COMPONENTS ${IPPL_PLATFORMS} + ) +endif() - if(NOT DEFINED Heffte_VERSION) - set(Heffte_VERSION "master") - set(HEFFTE_COMMIT_HASH "9eab7c0eb18e86acaccc2b5699b30e85a9e7bdda") - set(USE_FETCH_HEFFTE TRUE) - message(STATUS "📦 Using Heffte master from commit ${HEFFTE_COMMIT_HASH}") +# Invoke cmake fetch/find +colour_message(STATUS ${Green} "Fetching Kokkos : ${kokkos_fetch}") +FetchContent_Declare(Kokkos ${kokkos_fetch}) +FetchContent_MakeAvailable(Kokkos) + +# Check that kokkos actually has the platform backends that we need +if (Kokkos_FOUND) + set(KOKKOS_PLATFORM_OK TRUE) + foreach(PLATFORM ${IPPL_PLATFORMS}) + kokkos_check(DEVICES "${PLATFORM}" RETURN_VALUE PLATFORM_OK) + if (NOT PLATFORM_OK) + colour_message(FATAL_ERROR ${Red} + "❌ Kokkos does not have backend:${PLATFORM}, but IPPL requested it, use -DKokkos_VERSION=git.xxx (tag/branch/sha)") else() - find_package(Heffte ${Heffte_VERSION} CONFIG QUIET) - if(Heffte_FOUND) - message(STATUS "✅ Found installed Heffte ${Heffte_VERSION}") - else() - message(STATUS "📦 Heffte ${Heffte_VERSION} not found, fetching...") - set(USE_FETCH_HEFFTE TRUE) - endif() + colour_message(STATUS ${Green} "✅ Kokkos has backend: ${PLATFORM}") endif() + endforeach() +endif() - if(USE_FETCH_HEFFTE) - include(FetchContent) - - # Define backend options BEFORE calling MakeAvailable - if(NOT DEFINED Heffte_ENABLE_FFTW AND NOT DEFINED Heffte_ENABLE_CUDA AND NOT DEFINED Heffte_ENABLE_MKL) - set(Heffte_ENABLE_AVX2 ON CACHE BOOL "Use AVX2 backend in Heffte" FORCE) - set(Heffte_ENABLE_FFTW OFF CACHE BOOL "Use FFTW in Heffte" FORCE) - set(Heffte_ENABLE_CUDA OFF CACHE BOOL "Use CUDA in Heffte" FORCE) - endif() - - if(Heffte_VERSION STREQUAL "master") - FetchContent_Declare( - heffte - GIT_REPOSITORY https://github.com/icl-utk-edu/heffte.git - GIT_TAG ${HEFFTE_COMMIT_HASH} - DOWNLOAD_EXTRACT_TIMESTAMP ON - ) - else() - FetchContent_Declare( - heffte - URL https://github.com/icl-utk-edu/heffte/archive/refs/tags/v${Heffte_VERSION}.tar.gz - DOWNLOAD_EXTRACT_TIMESTAMP ON - ) - endif() - - FetchContent_MakeAvailable(heffte) - if(TARGET Heffte AND NOT TARGET Heffte::heffte) - add_library(Heffte::heffte ALIAS Heffte) - message(STATUS "🔗 Created ALIAS Heffte::heffte for Heffte target.") - endif() - - # Safety check - if(NOT TARGET Heffte::heffte) - message(FATAL_ERROR "❌ Heffte::heffte target is missing. Check Heffte build configuration.") - endif() - - message(STATUS "✅ Heffte built from source (${Heffte_VERSION})") - endif() +# ------------------------------------------------------------------------------ +# Heffte (only if FFT enabled) +# ------------------------------------------------------------------------------ +if(IPPL_ENABLE_FFT) + add_compile_definitions(IPPL_ENABLE_FFT) + option (Heffte_ENABLE_GPU_AWARE_MPI "Is an issue ... " OFF) + + # set the default version of Heffte we will ask for if not already set + if (NOT Heffte_VERSION_DEFAULT) + set(Heffte_VERSION_DEFAULT 2.4.0) + endif() + # if the user has not asked for a particular version, we will use the default + if (NOT Heffte_VERSION) + # default is "git.9eab7c0eb18e86acaccc2b5699b30e85a9e7bdda", + # spack installed heffte@git.9eab7c0eb18e86acaccc2b5699b30e85a9e7bdda returns 2.4.0 + set(Heffte_VERSION ${Heffte_VERSION_DEFAULT}) + endif() + + # is Heffte_VERSION a git tag/branch/sha + extract_git_label(Heffte_VERSION HEFFTE_VERSION_GIT) + if (HEFFTE_VERSION_GIT) + # the user has asked for a particular version built from source + set(heffte_fetch + GIT_TAG ${HEFFTE_VERSION_GIT} + GIT_REPOSITORY https://github.com/icl-utk-edu/heffte.git + DOWNLOAD_EXTRACT_TIMESTAMP ON) + else() + # the user has asked for a version - use find or checkout if needed + set(heffte_fetch + GIT_TAG ${Heffte_VERSION} + GIT_REPOSITORY https://github.com/icl-utk-edu/heffte.git + FIND_PACKAGE_ARGS ${Heffte_VERSION} + ) + endif() -endif() + # Invoke cmake fetch/find + colour_message(STATUS ${Green} "Fetching Heffte : ${heffte_fetch}") + FetchContent_Declare(Heffte ${heffte_fetch}) + # If building from source: Define backend options BEFORE calling MakeAvailable + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(Heffte_ENABLE_AVX2 OFF CACHE BOOL "" FORCE) + set(Heffte_ENABLE_CUDA OFF CACHE BOOL "" FORCE) + colour_message(STATUS ${Red} "❗ Disabling AVX2 and CUDA in Debug build") + endif() + if(NOT DEFINED Heffte_ENABLE_FFTW AND NOT DEFINED Heffte_ENABLE_CUDA AND NOT DEFINED Heffte_ENABLE_MKL) + set(Heffte_ENABLE_AVX2 ON) + set(Heffte_ENABLE_FFTW OFF) + set(Heffte_ENABLE_CUDA OFF) + endif() + + FetchContent_MakeAvailable(Heffte) + if (Heffte_FOUND) + colour_message(STATUS ${Green} "✅ Heffte FOUND ${Heffte_VERSION}") + endif() + + if ("CUDA" IN_LIST IPPL_PLATFORMS AND NOT Heffte_ENABLE_CUDA) + colour_message(WARNING ${Red} "Heffte NOT CUDA enabled but IPPL platform CUDA requested") + endif() + if (Heffte_ENABLE_FFTW AND NOT Heffte_ENABLE_FFTW) + colour_message(WARNING ${Red} "Heffte NOT FFTW enabled but IPPL FFTW requested") + endif() + + if(TARGET Heffte AND NOT TARGET Heffte::Heffte) + add_library(Heffte::Heffte ALIAS Heffte) + message(STATUS "🔗 Created ALIAS Heffte::Heffte for Heffte target.") + endif() +endif() +# ------------------------------------------------------------------------------ +# GoogleTest +# ------------------------------------------------------------------------------ if(IPPL_ENABLE_UNIT_TESTS) - include(FetchContent) + find_package(GTest) + if (NOT GTest_FOUND) FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip - DOWNLOAD_EXTRACT_TIMESTAMP ON - ) - + GTest + GIT_REPOSITORY "https://github.com/google/googletest" + GIT_TAG "v1.16.0" + GIT_SHALLOW ON) + # For Windows: Prevent overriding the parent project's compiler/linkersettings set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - FetchContent_MakeAvailable(googletest) - message(STATUS "✅ GoogleTest loaded for unit tests.") + FetchContent_MakeAvailable(GTest) + message(STATUS "✅ GoogleTest built from source (${GTest_VERSION})") + endif() endif() diff --git a/cmake/Messages.cmake b/cmake/Messages.cmake new file mode 100644 index 000000000..b210bedb7 --- /dev/null +++ b/cmake/Messages.cmake @@ -0,0 +1,46 @@ +# ----------------------------------------------------------------------------- +# Messages.cmake +# +# This file is responsible for messages macros, color and debug. +# It should be included near the top of the top-level CMakeLists.txt. +# ----------------------------------------------------------------------------- + +# ------------------------------------------------------------------------------ +# OS specific settings for terminal colour +# ------------------------------------------------------------------------------ +if(NOT WIN32) + string(ASCII 27 Esc) + set(ColourReset "${Esc}[m") + set(Black "${Esc}[30m") + set(Red "${Esc}[31m") + set(Green "${Esc}[32m") + set(Yellow "${Esc}[33m") + set(Blue "${Esc}[34m") + set(Magenta "${Esc}[35m") + set(Cyan "${Esc}[36m") + set(Light_Gray "${Esc}[37m") + set(Gray "${Esc}[90m") + set(Light_Red "${Esc}[91m") + set(Light_Green "${Esc}[92m") + set(Light_Yellow "${Esc}[93m") + set(Light_Blue "${Esc}[94m") + set(Light_Magenta "${Esc}[95m") + set(Light_Cyan "${Esc}[96m") + set(White "${Esc}[97m") +endif() + +# ------------------------------------------------------------------------------ +# Coloured message +# ------------------------------------------------------------------------------ +macro(colour_message TYPE COLOUR message) + message("${TYPE}" "${COLOUR}${message}${ColourReset}") +endmacro() + +# ------------------------------------------------------------------------------ +# Debug message +# ------------------------------------------------------------------------------ +function(debug_message DEBUG message) + if(${DEBUG}) + colour_message(STATUS "${Light_Green}" "DEBUG: ${message}") + endif() +endfunction() diff --git a/cmake/Platforms.cmake b/cmake/Platforms.cmake index 2fcb4d77a..f6642fafe 100644 --- a/cmake/Platforms.cmake +++ b/cmake/Platforms.cmake @@ -21,65 +21,65 @@ endif() # === Normalize to uppercase === string(TOUPPER "${IPPL_PLATFORMS}" IPPL_PLATFORMS) -# === Handle known platform combinations === -if("${IPPL_PLATFORMS}" STREQUAL "SERIAL") +# === Handle known platforms === +set(unhandled_platforms_ ${IPPL_PLATFORMS}) +if("SERIAL" IN_LIST IPPL_PLATFORMS) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Enable Kokkos Serial backend" FORCE) set(Heffte_ENABLE_AVX2 ON CACHE BOOL "Enable AVX2 backend for Heffte" FORCE) + list(REMOVE_ITEM unhandled_platforms_ "SERIAL") message(STATUS "🧩 Backend: SERIAL") +endif() -elseif("${IPPL_PLATFORMS}" STREQUAL "OPENMP") +if("OPENMP" IN_LIST IPPL_PLATFORMS) set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "Enable Kokkos OpenMP backend" FORCE) set(Heffte_ENABLE_AVX2 ON CACHE BOOL "Use Heffte Stock backend with AVX2" FORCE) + list(REMOVE_ITEM unhandled_platforms_ "OPENMP") message(STATUS "🧩 Backend: OPENMP") + endif() -elseif("${IPPL_PLATFORMS}" STREQUAL "CUDA") +if("CUDA" IN_LIST IPPL_PLATFORMS) set(Kokkos_ENABLE_CUDA ON CACHE BOOL "Enable Kokkos CUDA backend" FORCE) set(Heffte_ENABLE_CUDA ON CACHE BOOL "Enable Heffte CUDA backend" FORCE) + list(REMOVE_ITEM unhandled_platforms_ "CUDA") message(STATUS "🧩 Backend: CUDA") + endif() -elseif("${IPPL_PLATFORMS}" STREQUAL "HIP") +if("HIP" IN_LIST IPPL_PLATFORMS) set(Heffte_ENABLE_ROCM ON CACHE BOOL "Set Heffte ROCM Backend" FORCE) set(Kokkos_ENABLE_HIP ON CACHE BOOL "Enable Kokkos HIP Backend" FORCE) + list(REMOVE_ITEM unhandled_platforms_ "HIP") message(STATUS "🧩 Backend: HIP") +endif() -elseif("${IPPL_PLATFORMS}" STREQUAL "CUDA;OPENMP" OR "${IPPL_PLATFORMS}" STREQUAL "OPENMP;CUDA") - set(Kokkos_ENABLE_CUDA ON CACHE BOOL "Enable Kokkos CUDA backend" FORCE) - set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "Enable Kokkos OpenMP backend" FORCE) - set(Heffte_ENABLE_CUDA ON CACHE BOOL "Enable Heffte CUDA backend" FORCE) - message(STATUS "🧩 Backend: CUDA + OPENMP") - -elseif("${IPPL_PLATFORMS}" STREQUAL "HIP;OPENMP" OR "${IPPL_PLATFORMS}" STREQUAL "OPENMP;HIP") - set(Heffte_ENABLE_ROCM ON CACHE BOOL "Set Heffte ROCM Backend" FORCE) - set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "Enable Kokkos OpenMP Backend" FORCE) - set(Kokkos_ENABLE_HIP ON CACHE BOOL "Enable Kokkos HIP Backend" FORCE) - set(KOKKOS_ENABLE_PROFILING ON CACHE BOOL "Enable Kokkos Profiling" FORCE) - set(Kokkos_ENABLE_LIBDL ON CACHE BOOL "Enable LIBDL" FORCE) - message(STATUS "🧩 Backend: HIP + OPENMP") +if(NOT unhandled_platforms_ STREQUAL "") + message(FATAL_ERROR "Unknown or unsupported IPPL_PLATFORMS: '${unhandled_platforms_}'") +endif() -else() - message(FATAL_ERROR "Unknown or unsupported IPPL_PLATFORMS: '${IPPL_PLATFORMS}'") +if("HIP" IN_LIST IPPL_PLATFORMS AND "CUDA" IN_LIST IPPL_PLATFORMS) + message(FATAL_ERROR "CUDA and HIP should not both be present in IPPL_PLATFORMS") endif() if(NOT DEFINED Heffte_ENABLE_FFTW) set(Heffte_ENABLE_FFTW OFF CACHE BOOL "Enable FFTW in Heffte" FORCE) endif() - # Profiler section option (IPPL_ENABLE_HIP_PROFILER "Enable HIP Systems Profiler" OFF) if (IPPL_ENABLE_HIP_PROFILER) - if ("${IPPL_PLATFORMS}" STREQUAL "HIP" OR "${IPPL_PLATFORMS}" STREQUAL "HIP;OPENMP" OR "${IPPL_PLATFORMS}" STREQUAL "OPENMP;HIP") - message (STATUS "Enabling HIP Profiler") - add_compile_definitions(-DIPPL_ENABLE_HIP_PROFILER) + if ("HIP" IN_LIST IPPL_PLATFORMS) + set(KOKKOS_ENABLE_PROFILING ON CACHE BOOL "Enable Kokkos Profiling" FORCE) + set(Kokkos_ENABLE_LIBDL ON CACHE BOOL "Enable LIBDL" FORCE) + message (STATUS "🧩 Enabling HIP Profiler and KOKKOS profiliing") + add_compile_definitions(-DIPPL_ENABLE_HIP_PROFILER) else() message (FATAL_ERROR "Cannot enable HIP Systems Profiler since platform is not HIP") endif() endif() if (IPPL_ENABLE_NSYS_PROFILER) - if ("${IPPL_PLATFORMS}" STREQUAL "CUDA" OR "${IPPL_PLATFORMS}" STREQUAL "CUDA;OPENMP" OR "${IPPL_PLATFORMS}" STREQUAL "OPENMP;CUDA") + if ("CUDA" IN_LIST IPPL_PLATFORMS) message (STATUS "Enabling Nsys Profiler") - add_compile_definitions(-DIPPL_ENABLE_NSYS_PROFILER) + add_compile_definitions(-DIPPL_ENABLE_NSYS_PROFILER) else() message (FATAL_ERROR "Cannot enable Nvidia Nsys Profiler since platform is not CUDA") endif() diff --git a/cmake/ProjectSetup.cmake b/cmake/ProjectSetup.cmake index e65eefc81..e4c0c0419 100644 --- a/cmake/ProjectSetup.cmake +++ b/cmake/ProjectSetup.cmake @@ -16,46 +16,46 @@ # - External dependencies → Dependencies.cmake # ----------------------------------------------------------------------------- -# === C++ Standard === +# ------------------------------------------------------------------------------ +# C++ and language Standards +# ------------------------------------------------------------------------------ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CUDA_EXTENSIONS OFF) -set(IPPL_LIB_TYPE STATIC) - -option (USE_STATIC_LIBRARIES "Link with static libraries if available" ON) -option (Heffte_ENABLE_GPU_AWARE_MPI "Is a issue ... " OFF) +# ------------------------------------------------------------------------------ +# load message macros +# ------------------------------------------------------------------------------ +include(Messages) -if(IPPL_DYL) - set(IPPL_LIB_TYPE SHARED) +# ------------------------------------------------------------------------------ +# Static/Dynamic build : +# use cmake's BUILD_SHARED_LIBS but set IPPL_LIB_TYPE for log purposes +# ------------------------------------------------------------------------------ +set(IPPL_LIB_TYPE STATIC) +if (BUILD_SHARED_LIBS) + set(IPPL_LIB_TYPE SHARED) endif() -message(STATUS "🔧 IPPL will be built as a ${IPPL_LIB_TYPE} library (IPPL_DYL = ${IPPL_DYL})") +message(STATUS "🔧 IPPL will be built as a ${IPPL_LIB_TYPE} library") -# === Default Build Type === +# ------------------------------------------------------------------------------ +# Default Build Type +# ------------------------------------------------------------------------------ set(_allowed_build_types Debug Release RelWithDebInfo MinSizeRel) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(default_build_type "RelWithDebInfo") set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build (${_allowed_build_types})" FORCE) - message(STATUS "No build type specified. Defaulting to ${CMAKE_BUILD_TYPE}") + colour_message(STATUS ${Red} "No build type specified. Defaulting to ${CMAKE_BUILD_TYPE}") else() - message(STATUS "Build type is: ${CMAKE_BUILD_TYPE}") + colour_message(STATUS ${Green} "Build type is: ${CMAKE_BUILD_TYPE}") endif() if(NOT CMAKE_BUILD_TYPE IN_LIST _allowed_build_types) - message(WARNING "Unknown CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") + colour_message(WARNING ${Red} "Unknown CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") endif() -# === Colored Output Macros === -if(NOT WIN32) - string(ASCII 27 Esc) - set(ColorReset "${Esc}[m") - set(ColorRed "${Esc}[31m") - set(ColorGreen "${Esc}[32m") - set(ColorYellow "${Esc}[1;33m") -endif() - -message(STATUS "${ColorGreen}✅ Project setup complete${ColorReset}") - +# ------------------------------------------------------------------------------ +message(STATUS "✅ Project setup complete${ColorReset}") diff --git a/cmake/Version.cmake b/cmake/Version.cmake deleted file mode 100644 index 092964189..000000000 --- a/cmake/Version.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# ----------------------------------------------------------------------------- -# Version.cmake -# -# Defines the version of the IPPL project in a centralized way. -# -# Why both IPPL_VERSION and PROJECT_VERSION? -# - PROJECT_VERSION is set by the top-level project(...) command and used by CMake. -# - IPPL_VERSION is our internal project version we can use freely in code, -# messages, version headers, etc., without relying on CMake internals. -# ----------------------------------------------------------------------------- - -set(IPPL_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) -set(IPPL_VERSION_MINOR ${PROJECT_VERSION_MINOR}) -set(IPPL_VERSION_PATCH ${PROJECT_VERSION_PATCH}) -set(IPPL_VERSION ${PROJECT_VERSION}) - -# Symbolic version string (for CLI, logs, headers, etc.) -set(IPPL_VERSION_NAME "IPPL v${IPPL_VERSION}") - -message(STATUS "📦 IPPL Version: ${IPPL_VERSION_NAME}") diff --git a/doc/extras/IPPLonEULER.md b/doc/extras/IPPLonEULER.md index 493438cde..36a243e9f 100644 --- a/doc/extras/IPPLonEULER.md +++ b/doc/extras/IPPLonEULER.md @@ -1,28 +1,28 @@ # Installing IPPL on EULER {#Installation} -This guide outlines the steps to install the IPPL library on the EULER cluster. Before beginning, ensure you are connected to the ETH-VPN to access the cluster. +This guide outlines the steps to install the IPPL library on the EULER cluster. Before beginning, ensure you are connected to the ETH-VPN to access the cluster. -## Connecting to the EULER Cluster - -Use SSH to connect to EULER. Replace '\' with your actual username. +## Connecting to the EULER Cluster + +Use SSH to connect to EULER. Replace '\' with your actual username. ssh -Y @euler.ethz.ch -The '-Y' flag enables trusted X11 forwarding, necessary for running graphical applications remotely. +The '-Y' flag enables trusted X11 forwarding, necessary for running graphical applications remotely. -## Preparing the Environment +## Preparing the Environment -_Load the New Software Stack:_ Transition to the new software stack to access the latest dependencies: +_Load the New Software Stack:_ Transition to the new software stack to access the latest dependencies: env2lmod _Clean the Environment:_ Ensure no previous modules are loaded to avoid conflicts: - + module purge _Load Dependencies:_ Load the required modules for IPPL: - - module load gcc/11.4.0 cmake/3.26.3 cuda/12.1.1 openmpi/4.1.4 + + module load gcc/11.4.0 cmake/3.26.3 cuda/12.1.1 openmpi/4.1.4 ## Cloning the IPPL Library @@ -43,16 +43,16 @@ Clone the IPPL library from its repository: Choose from the following options based on your needs. If necessary, you can build multiple versions in separate directories. **Serial Version** (for single-node computing) - + cmake .. -DCMAKE_CXX_STANDARD=20 -DIPPL_PLATFORMS=SERIAL -DIPPL_ENABLE_SOLVERS=ON -DIPPL_ENABLE_FFT=ON -DIPPL_ENABLE_ALPINE=ON **OpenMP Version** (for multi-threaded computing): - + cmake .. -DCMAKE_CXX_STANDARD=20 -DIPPL_PLATFORMS=OPENMP -DIPPL_ENABLE_SOLVERS=ON -DIPPL_ENABLE_FFT=ON -DIPPL_ENABLE_ALPINE=ON **Cuda Version** (for GPU computing): - - cmake .. -DCMAKE_CXX_STANDARD=20 -DIPPL_PLATFORMS=CUDA -DIPPL_ENABLE_SOLVERS=ON -DIPPL_ENABLE_FFT=ON -DIPPL_ENABLE_ALPINE=ON -DUSE_ALTERNATIVE_VARIANT=OFF -DKokkos_ARCH_[architecture]=ON + + cmake .. -DCMAKE_CXX_STANDARD=20 -DIPPL_PLATFORMS=CUDA -DIPPL_ENABLE_SOLVERS=ON -DIPPL_ENABLE_FFT=ON -DIPPL_ENABLE_ALPINE=ON -DIPPL_USE_ALTERNATIVE_VARIANT=OFF -DKokkos_ARCH_[architecture]=ON [architecture] should be the target architecture, e.g. @@ -63,7 +63,7 @@ Choose from the following options based on your needs. If necessary, you can bui #### Compile - + make ## Testing Your Installation @@ -80,5 +80,5 @@ This command allocates one computing node with 32GB of RAM for 60 minutes. ## Links Repository for Independent Parallel Particle Layer (IPPL) - + https://github.com/IPPL-framework/ippl diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83b1be10c..65b5e4ece 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,7 +36,7 @@ configure_file( ${CMAKE_CURRENT_BINARY_DIR}/IpplVersions.h ) -add_library(ippl ${IPPL_LIB_TYPE}) +add_library(ippl) target_sources(ippl PRIVATE @@ -86,10 +86,8 @@ target_link_libraries(ippl Kokkos::kokkos ) -if(IPPL_ENABLE_FFT AND TARGET Heffte::heffte) - target_link_libraries(ippl PUBLIC Heffte::heffte) -else() - message(WARNING "⚠️ Heffte::heffte target not found — skipping link.") +if(IPPL_ENABLE_FFT) + target_link_libraries(ippl PUBLIC Heffte::Heffte) endif() set(IPPL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/Communicate/CMakeLists.txt b/src/Communicate/CMakeLists.txt index c6d5480ec..8552820fb 100644 --- a/src/Communicate/CMakeLists.txt +++ b/src/Communicate/CMakeLists.txt @@ -14,6 +14,8 @@ target_sources(ippl LogEntry.cpp ) +target_link_libraries(ippl PRIVATE MPI::MPI_CXX) + target_include_directories(ippl PUBLIC $ diff --git a/src/FFT/CMakeLists.txt b/src/FFT/CMakeLists.txt index 77702185c..7183b6cf8 100644 --- a/src/FFT/CMakeLists.txt +++ b/src/FFT/CMakeLists.txt @@ -4,6 +4,8 @@ # Adds FFT interface headers to the IPPL target. # ----------------------------------------------------------------------------- +target_link_libraries(ippl PRIVATE Heffte::Heffte) + target_include_directories(ippl PUBLIC $ diff --git a/src/Types/Variant.h b/src/Types/Variant.h index 196029878..6332574c0 100644 --- a/src/Types/Variant.h +++ b/src/Types/Variant.h @@ -1,4 +1,4 @@ -#ifdef USE_ALTERNATIVE_VARIANT +#ifdef IPPL_USE_ALTERNATIVE_VARIANT // -*- C++ -*- // Copyright (C) 2016-2023 Free Software Foundation, Inc. diff --git a/test/field/CMakeLists.txt b/test/field/CMakeLists.txt index ef807bf1b..c42f43c36 100644 --- a/test/field/CMakeLists.txt +++ b/test/field/CMakeLists.txt @@ -1,7 +1,7 @@ file (RELATIVE_PATH _relPath "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}") -message (STATUS "Adding index test found in ${_relPath}") +message(STATUS "🔧 Adding index test found in ${_relPath}") -add_ippl_integration_test(TestLaplace +add_ippl_integration_test(TestLaplace LABELS integration field ARGS 10 10 --info 10 ) @@ -15,7 +15,7 @@ add_ippl_integration_test(TestCurl ARGS 10 0 --info 10 ) -add_ippl_integration_test(TestHessian +add_ippl_integration_test(TestHessian LABELS integration field ARGS 10 0 --info 10 )