diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 64d59a59d..fa7ca4234 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -228,6 +228,7 @@ jobs: -DENABLE_TESTING=ON -DFLOAT_PRECISION=${{ matrix.precision }} -DENABLE_DEPRECATED_API=${{ matrix.deprecated }} + -DDISABLE_DEPRECATION_WARNINGS=${{ matrix.deprecated }} -DENABLE_MULTITHREADING=${{ matrix.omp }} -DENABLE_DISTRIBUTION=${{ matrix.mpi }} -DENABLE_CUDA=${{ matrix.cuda }} diff --git a/.github/workflows/test_free.yml b/.github/workflows/test_free.yml index 7efd540d3..e0837bfde 100644 --- a/.github/workflows/test_free.yml +++ b/.github/workflows/test_free.yml @@ -66,6 +66,7 @@ jobs: -DENABLE_TESTING=ON -DENABLE_MULTITHREADING=OFF -DENABLE_DEPRECATED_API=${{ matrix.version == 3 && 'ON' || 'OFF' }} + -DDISABLE_DEPRECATION_WARNINGS=${{ matrix.version == 3 && 'ON' || 'OFF' }} -DFLOAT_PRECISION=${{ matrix.precision }} # force 'Release' build (needed by MSVC to enable optimisations) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32db779d6..71c8f127b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # @author Oliver Thomson Brown # @author Erich Essmann (patches including MSVC support) -# @author Tyson Jones (tidying + patches including clang multithreading) +# @author Tyson Jones (centralising macros, doc, patches including clang multithreading) # @author Luc Jaulmes (NUMA awareness, patching install) # # Contributions to previous builds from: @@ -54,7 +54,7 @@ endif() # ============================ -# Declare options +# Obtain options # ============================ @@ -90,21 +90,6 @@ message(STATUS "Library will be named lib${LIB_NAME}. Set LIB_NAME to modify.") option(VERBOSE_LIB_NAME "Modify library name based on compilation configuration. Turned OFF by default." OFF) message(STATUS "Verbose library naming is turned ${VERBOSE_LIB_NAME}. Set VERBOSE_LIB_NAME to modify.") -if (VERBOSE_LIB_NAME) - # Same headers will be used for several verbosely-named libraries - set(MULTI_LIB_HEADERS 1) - function(compile_option VAR VALUE) - target_compile_definitions(QuEST PUBLIC ${VAR}=${VALUE}) - endfunction() -else() - # Headers will be used for a single library with a single valid configuration - set(MULTI_LIB_HEADERS 0) - function(compile_option VAR VALUE) - target_compile_definitions(QuEST PRIVATE ${VAR}=${VALUE}) - set(${VAR} ${VALUE} PARENT_SCOPE) - endfunction() -endif() - # Precision set(FLOAT_PRECISION 2 @@ -119,10 +104,6 @@ set_property(CACHE FLOAT_PRECISION PROPERTY STRINGS ) message(STATUS "Precision set to ${FLOAT_PRECISION}. Set FLOAT_PRECISION to modify.") -if (VERBOSE_LIB_NAME) - string(CONCAT LIB_NAME ${LIB_NAME} "-fp${FLOAT_PRECISION}") -endif() - # Examples option( @@ -174,14 +155,12 @@ option( ) message(STATUS "NVIDIA GPU acceleration is turned ${ENABLE_CUDA}. Set ENABLE_CUDA to modify.") -if (ENABLE_CUDA) - option( - ENABLE_CUQUANTUM - "Whether QuEST will be built with support for NVIDIA CuQuantum. Turned OFF by default." - OFF - ) - message(STATUS "CuQuantum support is turned ${ENABLE_CUQUANTUM}. Set ENABLE_CUQUANTUM to modify.") -endif() +option( + ENABLE_CUQUANTUM + "Whether QuEST will be built with support for NVIDIA cuQuantum. Turned OFF by default." + OFF +) +message(STATUS "CuQuantum support is turned ${ENABLE_CUQUANTUM}. Set ENABLE_CUQUANTUM to modify.") option( ENABLE_HIP @@ -190,33 +169,95 @@ option( ) message(STATUS "AMD GPU acceleration is turned ${ENABLE_HIP}. Set ENABLE_HIP to modify.") -# Throw on disallowed GPU combinations + +# Deprecated API +option( + ENABLE_DEPRECATED_API + "Whether QuEST will be built with deprecated API support. Turned OFF by default." + OFF +) +message(STATUS "Deprecated API support is turned ${ENABLE_DEPRECATED_API}. Set ENABLE_DEPRECATED_API to modify.") + +option( + DISABLE_DEPRECATION_WARNINGS + "Whether to disable compile-time warnings ordinarily triggered by use of the deprecated API. Turned OFF by default." + OFF +) +message(STATUS "Disabling of deprecated API warnings is turned ${DISABLE_DEPRECATION_WARNINGS}. Set DISABLE_DEPRECATION_WARNINGS to modify.") + + + +# ============================ +# Validate options +# ============================ + + if (ENABLE_CUDA AND ENABLE_HIP) message(FATAL_ERROR "QuEST cannot support CUDA and HIP simultaneously.") endif() + if ((ENABLE_CUDA OR ENABLE_HIP) AND FLOAT_PRECISION STREQUAL 4) message(FATAL_ERROR "Quad precision is not supported on GPU. Please disable GPU acceleration or lower precision.") endif() -# Deprecated API -option( - ENABLE_DEPRECATED_API - "Whether QuEST will be built with deprecated API support. Turned OFF by default." - OFF -) -message(STATUS "Deprecated API support is turned ${ENABLE_DEPRECATED_API}. Set ENABLE_DEPRECATED_API to modify.") +if (ENABLE_CUQUANTUM AND NOT ENABLE_CUDA) + message(FATAL_ERROR "Use of cuQuantum requires CUDA.") +endif() -# Windows Specific Options if(WIN32) # Force MSVC to export all symbols in a shared library, like GCC and clang set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) - if (ENABLE_TESTING) + + if (ENABLE_TESTING AND BUILD_SHARED_LIBS) + message(WARNING "Compiling the tests on Windows requires BUILD_SHARED_LIBS=OFF which we now force.") set(BUILD_SHARED_LIBS OFF) endif() + + if (ENABLE_DEPRECATED_API) + message(FATAL_ERROR "The deprecated API is not compatible with MSVC.") + endif() + +endif() + + + +# ============================ +# Extend verbose library name +# ============================ + + +if (VERBOSE_LIB_NAME) + + string(CONCAT LIB_NAME ${LIB_NAME} "-fp${FLOAT_PRECISION}") + + if (ENABLE_MULTITHREADING) + string(CONCAT LIB_NAME ${LIB_NAME} "+mt") + endif() + + if (ENABLE_DISTRIBUTION) + string(CONCAT LIB_NAME ${LIB_NAME} "+mpi") + endif() + + if (ENABLE_CUDA) + string(CONCAT LIB_NAME ${LIB_NAME} "+cuda") + endif() + + if (ENABLE_HIP) + string(CONCAT LIB_NAME ${LIB_NAME} "+hip") + endif() + + if (ENABLE_CUQUANTUM) + string(CONCAT LIB_NAME ${LIB_NAME} "+cuquantum") + endif() + + if (ENABLE_DEPRECATED_API) + string(CONCAT LIB_NAME ${LIB_NAME} "+depr") + endif() + endif() @@ -234,15 +275,15 @@ add_library(QuEST::QuEST ALIAS QuEST) # Set include directories target_include_directories(QuEST - PUBLIC - $ - $ - $ - $ + PUBLIC + $ + $ + $ + $ ) set_target_properties(QuEST PROPERTIES - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} ) @@ -277,13 +318,10 @@ target_compile_options(QuEST # ============================ -# Pass options to library +# Link optional dependencies # ============================ -compile_option(FLOAT_PRECISION ${FLOAT_PRECISION}) - - # OpenMP if (ENABLE_MULTITHREADING) @@ -299,42 +337,44 @@ if (ENABLE_MULTITHREADING) message(FATAL_ERROR ${ErrorMsg}) endif() - compile_option(COMPILE_OPENMP 1) target_link_libraries(QuEST PRIVATE OpenMP::OpenMP_CXX OpenMP::OpenMP_C ) +else() + + # suppress GCC "unknown pragma" warning when OpenMP disabled + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(QuEST PRIVATE $<$:-Wno-unknown-pragmas>) + endif() + +endif() + + +# NUMA (only relevant when multithreading) +if (ENABLE_MULTITHREADING) + # Find NUMA - location of NUMA headers if (WIN32) - compile_option(NUMA_AWARE 0) + set(NUMA_AWARE 0) message(WARNING "Building on Windows, QuEST will not be aware of numa locality") else() include(FindPkgConfig) pkg_search_module(NUMA numa IMPORTED_TARGET GLOBAL) if (${NUMA_FOUND}) - compile_option(NUMA_AWARE ${NUMA_FOUND}) + set(NUMA_AWARE ${NUMA_FOUND}) target_link_libraries(QuEST PRIVATE PkgConfig::NUMA) message(STATUS "NUMA awareness is enabled.") else() - compile_option(NUMA_AWARE 0) + set(NUMA_AWARE 0) message(WARNING "libnuma not found, QuEST will not be aware of numa locality") endif() endif() - if (VERBOSE_LIB_NAME) - string(CONCAT LIB_NAME ${LIB_NAME} "+mt") - endif() - else() - - # suppress GCC "unknown pragma" warning when OpenMP disabled - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - target_compile_options(QuEST PRIVATE $<$:-Wno-unknown-pragmas>) - endif() - - compile_option(COMPILE_OPENMP 0) + set(NUMA_AWARE 0) endif() @@ -343,16 +383,10 @@ if (ENABLE_DISTRIBUTION) find_package(MPI REQUIRED COMPONENTS CXX ) - compile_option(COMPILE_MPI 1) target_link_libraries(QuEST PRIVATE MPI::MPI_CXX ) - if (VERBOSE_LIB_NAME) - string(CONCAT LIB_NAME ${LIB_NAME} "+mpi") - endif() -else() - compile_option(COMPILE_MPI 0) endif() @@ -366,32 +400,9 @@ if (ENABLE_CUDA) enable_language(CUDA) set(CMAKE_CUDA_STANDARD_REQUIRED ON) - - set_property(TARGET QuEST PROPERTY CUDA_STANDARD 20) - set(CUDA_PROPAGATE_HOST_FLAGS OFF) - if (VERBOSE_LIB_NAME) - string(CONCAT LIB_NAME ${LIB_NAME} "+cuda") - endif() - - # beware that compile_option(COMPILE_CUDA) is deferred to below because - # it is triggered by both/either ENABLE_CUDA and ENABLE_HIP - -endif() - - -# cuQuantum -if (ENABLE_CUQUANTUM) - find_package(CUQUANTUM REQUIRED) - compile_option(COMPILE_CUQUANTUM 1) - target_link_libraries(QuEST PRIVATE CUQUANTUM::cuStateVec) - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) - if (VERBOSE_LIB_NAME) - string(CONCAT LIB_NAME ${LIB_NAME} "+cuquantum") - endif() -else() - compile_option(COMPILE_CUQUANTUM 0) + set_property(TARGET QuEST PROPERTY CUDA_STANDARD 20) endif() @@ -413,36 +424,50 @@ if (ENABLE_HIP) find_package(HIP REQUIRED) message(STATUS "Found HIP: " ${HIP_VERSION}) - compile_option(COMPILE_CUQUANTUM 0) target_link_libraries(QuEST PRIVATE hip::host) - if (VERBOSE_LIB_NAME) - string(CONCAT LIB_NAME ${LIB_NAME} "+hip") - endif() endif() -# set COMPILE_CUDA -if (ENABLE_CUDA OR ENABLE_HIP) - compile_option(COMPILE_CUDA 1) -else() - compile_option(COMPILE_CUDA 0) +# cuQuantum +if (ENABLE_CUQUANTUM) + find_package(CUQUANTUM REQUIRED) + target_link_libraries(QuEST PRIVATE CUQUANTUM::cuStateVec) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) endif() -# v3 API -if (ENABLE_DEPRECATED_API) - target_compile_definitions(QuEST PRIVATE INCLUDE_DEPRECATED_FUNCTIONS=1) - if (VERBOSE_LIB_NAME) - string(CONCAT LIB_NAME ${LIB_NAME} "+depr") - endif() +# =============================== +# Set options to save in config.h +# =============================== + +# set vars which will be written to config.h.in (auto-converted to 0 or 1) +set(COMPILE_OPENMP ${ENABLE_MULTITHREADING}) +set(COMPILE_MPI ${ENABLE_DISTRIBUTION}) +set(COMPILE_CUQUANTUM ${ENABLE_CUQUANTUM}) +set(INCLUDE_DEPRECATED_FUNCTIONS ${ENABLE_DEPRECATED_API}) + + +# (for the love of God cmake, create a concise syntax for this) +if (ENABLE_CUDA OR ENABLE_HIP) + set(COMPILE_CUDA 1) else() - target_compile_definitions(QuEST PRIVATE INCLUDE_DEPRECATED_FUNCTIONS=0) + set(COMPILE_CUDA 0) endif() +# these vars are already set, but repeated here for clarity +set(FLOAT_PRECISION ${FLOAT_PRECISION}) +set(NUMA_AWARE ${NUMA_AWARE}) +set(DISABLE_DEPRECATION_WARNINGS ${DISABLE_DEPRECATION_WARNINGS}) + + +# these do not appear in src but are saved for record-keeping in config.h.in +set(COMPILE_HIP ${ENABLE_HIP}) + + # ============================ # Pass files to library @@ -625,7 +650,7 @@ install(FILES ) install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/include/quest/include/config.h" + "${CMAKE_CURRENT_BINARY_DIR}/quest/include/config.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/quest/include" ) diff --git a/docs/cmake.md b/docs/cmake.md index 336dcf28c..9240b6793 100644 --- a/docs/cmake.md +++ b/docs/cmake.md @@ -8,13 +8,13 @@ @author Tyson Jones (test variables) --> -Version 4 of QuEST includes reworked CMake to support library builds, CMake export, and installation. Here we detail useful variables to configure the compilation of QuEST. If using a Unix-like operating system any of these variables can be set using the `-D` flag when invoking CMake, for example: +Version 4 of QuEST includes reworked CMake to support library builds, CMake export, and installation. Here we detail useful variables to configure the compilation of QuEST. If using a Unix-like operating system, any of these variables can be set using the `-D` flag when invoking CMake, for example: ``` cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/QuEST -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DENABLE_MULTITHREADING=ON -DENABLE_DISTRIBUTION=OFF ./ ``` -Then one need only move to the build directory, and invoke make: +Then, as detailed in [`compile.md`](compile.md), one need only move to the build directory and compile by invoking make: ``` cd build @@ -42,10 +42,13 @@ make | `ENABLE_CUQUANTUM` | (`OFF`), `ON` | Determines whether QuEST will make use of the NVIDIA CuQuantum library. Cannot be turned on if `ENABLE_CUDA` is off. | | `ENABLE_HIP` | (`OFF`), `ON` | Determines whether QuEST will be built with support for AMD GPU acceleration. If turned on, `CMAKE_HIP_ARCHITECTURES` should probably also be set. | | `ENABLE_DEPRECATED_API` | (`OFF`), `ON` | Determines whether QuEST will be built with support for the deprecated (v3) API. ***Note**: this will generate compiler warnings and is not supported by MSVC.* | +| `DISABLE_DEPRECATION_WARNINGS` | (`OFF`), `ON` | Whether to disable the compile-time deprecation warnings when using the deprecated (v3) API. | | `USER_SOURCE` | (Undefined), String | The source file for a user program which will be compiled alongside QuEST. `OUTPUT_EXE` *must* also be defined. | | `OUTPUT_EXE` | (Undefined), String | The name of the executable which will be created from the provided `USER_SOURCE`. `USER_SOURCE` *must* also be defined. | + + -------------------------- ## Test variables diff --git a/docs/compile.md b/docs/compile.md index 37fc6ad23..f11677fbf 100644 --- a/docs/compile.md +++ b/docs/compile.md @@ -55,6 +55,9 @@ Compiling is configured with variables supplied by the [`-D` flag](https://cmake > [!TIP] > QuEST's [Github Actions](https://github.com/QuEST-Kit/QuEST/actions/workflows/compile.yml) regularly test QuEST compilation using a broad combination of deployment settings; presently `108` combinations! The [`compile.yml`](/.github/workflows/compile.yml) workflow can serve as a concrete example of how to compile QuEST in a sanitised, virtual setting. +> [!NOTE] +> Afraid of CMake? See [`compile.sh`](/utils/scripts/compile.sh) for manual compilation (which we discourage!) + ------------------ diff --git a/quest/include/CMakeLists.txt b/quest/include/CMakeLists.txt index bf0d1cd09..2ab3d569d 100644 --- a/quest/include/CMakeLists.txt +++ b/quest/include/CMakeLists.txt @@ -1,5 +1,12 @@ # @author Oliver Thomson Brown # @author Erich Essmann # @author Luc Jaulmes (using config file) +# @author Tyson Jones (doc) -configure_file(config.h.in "${CMAKE_BINARY_DIR}/include/quest/include/config.h" @ONLY) +# Generate a header file which defines all configurable preprocessors +# needed by the QuEST source (e.g. COMPILE_MPI), as informed by the +# user-set CMake options. This permits us to avoid passing any macros +# through compiler flags and the associated conflicts arising when +# installing QuEST. Note that config.h must be manually created when +# not compiling via CMake, e.g. when using a custom build script +configure_file(config.h.in config.h @ONLY) diff --git a/quest/include/config.h.in b/quest/include/config.h.in index 8326259b6..2cb12fa90 100644 --- a/quest/include/config.h.in +++ b/quest/include/config.h.in @@ -1,22 +1,169 @@ +/** @file + * The input file to CMake's configure_file() which produces + * the config.h header, which in-turn defines macros needed by + * the QuEST source, as informed by user-specified CMake options. + * + * Use of this configured header file enables all macros to be + * defined in one central place (right here) rather than being + * passed to each source file as compiler flags. It further + * ensures that when QuEST is installed, critical user-facing + * macros such as FLOAT_PRECISION cannot ever be changed from + * their value during source compilation. Finally, it enables + * users to access macros such as COMPILE_OPENMP at pre-build + * time of their own source code, which could prove necessary + * when interfacing with external libraries. + * + * Use of this config file however means that manual compilation + * (through GNUMake or a manual script) requires generating the + * config.h file manually. + * + * @author Luc Jaulmes + * @author Oliver Brown + * @author Tyson Jones (centralising macros, validation, doc) + */ + #ifndef CONFIG_H #define CONFIG_H -// be warned, the below is sensitive to whitespace after the slash -#if !defined(FLOAT_PRECISION)\ - || !defined(COMPILE_MPI)\ - || !defined(COMPILE_OPENMP)\ - || !defined(COMPILE_CUDA)\ - || !defined(COMPILE_CUQUANTUM) -// bind compile settings to installed exec -#if !@MULTI_LIB_HEADERS@ + +/* + * check that the below CMake options are not being erroneously + * passed as macros (as was previously accepted), which would + * anyway trigger a 'macro redefined' warning below. + */ + + +#if defined(FLOAT_PRECISION) || \ + defined(COMPILE_OPENMP) || \ + defined(COMPILE_MPI) || \ + defined(COMPILE_CUDA) || \ + defined(COMPILE_HIP) || \ + defined(COMPILE_CUQUANTUM) || \ + defined(NUMA_AWARE) || \ + defined(INCLUDE_DEPRECATED_FUNCTIONS) || \ + defined(DISABLE_DEPRECATION_WARNINGS) + + #error "Pre-config macros were erroneously passed directly to the source rather than through the CMake config file." + +#endif + + +#if defined(QUEST_VERSION_MAJOR) || \ + defined(QUEST_VERSION_MINOR) || \ + defined(QUEST_VERSION_PATCH) || \ + defined(QUEST_VERSION_STRING) + + #error "QuEST version macros were erroneously passed directly to the source rather than through the CMake config file." + +#endif + + + +/* + * save the CMake option values as macros. + * + * Note we use cmakedefine (rather than just define @VAL) so that + * the macro is totally avoided being defined if the corresponding + * CMake variable was not passed to this config file, which we can + * subsequently detect and error-out below + */ + + +// crucial to user source (informs API) #cmakedefine FLOAT_PRECISION @FLOAT_PRECISION@ -#cmakedefine01 COMPILE_MPI +#cmakedefine01 INCLUDE_DEPRECATED_FUNCTIONS +#cmakedefine01 DISABLE_DEPRECATION_WARNINGS + + +// crucial to QuEST source (informs external library usage) #cmakedefine01 COMPILE_OPENMP +#cmakedefine01 COMPILE_MPI #cmakedefine01 COMPILE_CUDA #cmakedefine01 COMPILE_CUQUANTUM + + +// not actually a CMake option (user cannot disable) but nonetheless crucial +#cmakedefine01 NUMA_AWARE + + +// not consulted by src (included for book-keeping) +#cmakedefine01 COMPILE_HIP + + + +/* + * inherit the version information from CMake. + * + * Note we do not (and actually cannot) validate these using the + * cmakedefine trick used above since they are always gauranteed + * to be passed and substituted by CMake + */ + + +#define QUEST_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define QUEST_VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define QUEST_VERSION_PATCH @PROJECT_VERSION_PATCH@ +#define QUEST_VERSION_STRING "@PROJECT_VERSION@" + + + +/* + * check that all above expected CMake options were + * actually passed (since use of 'cmakedefine' means + * they otherwise default to no macro definition) + */ + + +#if ! defined(FLOAT_PRECISION) || \ + ! defined(COMPILE_OPENMP) || \ + ! defined(COMPILE_MPI) || \ + ! defined(COMPILE_CUDA) || \ + ! defined(COMPILE_HIP) || \ + ! defined(COMPILE_CUQUANTUM) || \ + ! defined(NUMA_AWARE) || \ + ! defined(INCLUDE_DEPRECATED_FUNCTIONS) || \ + ! defined(DISABLE_DEPRECATION_WARNINGS) + + #error "Expected macros were not defined by the config.h header, possibly because their corresponding CMake variables were not substituted." + #endif + + +/* + * validate boolean macro definitions. + * + * Note that more specific checks (e.g. whether non-boolean + * macros have legal values, or whether combinations of + * multiple macro values are legal) are performed by the files + * that concern them. These checks merely validate the macro + * has the right 'type' so will not trip up other preprocesing + */ + + +#if ! (COMPILE_OPENMP == 0 || COMPILE_OPENMP == 1) || \ + ! (COMPILE_MPI == 0 || COMPILE_MPI == 1) || \ + ! (COMPILE_CUDA == 0 || COMPILE_CUDA == 1) || \ + ! (COMPILE_HIP == 0 || COMPILE_HIP == 1) || \ + ! (COMPILE_CUQUANTUM == 0 || COMPILE_CUQUANTUM == 1) || \ + ! (NUMA_AWARE == 0 || NUMA_AWARE == 1) || \ + ! (INCLUDE_DEPRECATED_FUNCTIONS == 0 || INCLUDE_DEPRECATED_FUNCTIONS == 1) || \ + ! (DISABLE_DEPRECATION_WARNINGS == 0 || DISABLE_DEPRECATION_WARNINGS == 1) + + #error "A macro defined by the config.h header (as inferred from a CMake variable) had an illegal value." + +#endif + + +// ensure __cplusplus macro is valid (API headers use #ifdef, not #if) + +#ifdef __cplusplus +#if !__cplusplus +#error "Preprocessor __cplusplus was 0 and should instead be undefined" #endif +#endif + + -#endif \ No newline at end of file +#endif // CONFIG_H \ No newline at end of file diff --git a/quest/include/modes.h b/quest/include/modes.h index 2bb608be9..f8fc52a1c 100644 --- a/quest/include/modes.h +++ b/quest/include/modes.h @@ -1,12 +1,12 @@ /** @file - * Compile-time checks that all expected - * preprocessor macros are defined and valid + * Constants related to configuring QuEST runtime modes, + * and documentation of environment variables * * @author Tyson Jones * * @defgroup modes Modes * @ingroup api - * @brief Macros for controlling QuEST compilation. + * @brief Constants and environment variables for controlling QuEST execution. * @{ */ @@ -15,75 +15,6 @@ -// ensure all mode flags are valid values -// undefined allowed as undefined == 0 in C/C++ standards - -#if ! (COMPILE_MPI == 0 || COMPILE_MPI == 1) - #error "Macro COMPILE_MPI must have value 0 or 1" -#endif - -#if ! (COMPILE_OPENMP == 0 || COMPILE_OPENMP == 1) - #error "Macro COMPILE_OPENMP must have value 0 or 1" -#endif - -#if ! (COMPILE_CUDA == 0 || COMPILE_CUDA == 1) - #error "Macro COMPILE_CUDA must have value 0 or 1" -#endif - -#if ! (COMPILE_CUQUANTUM == 0 || COMPILE_CUQUANTUM == 1) - #error "Macro COMPILE_CUQUANTUM must have value 0 or 1" -#endif - - - -// ensure mode flags are compatible - -#if COMPILE_CUQUANTUM && ! COMPILE_CUDA - #error "Cannot enable cuQuantum without simultaneously enabling GPU-acceleration" -#endif - - - -// ensure C++ macro is valid (API headers use #ifdef, not #if) - -#ifdef __cplusplus -#if !__cplusplus -#error "Preprocessor __cplusplus was 0 and should instead be undefined" -#endif -#endif - - - -// define optional-macro defaults (mostly to list them) - -#ifndef INCLUDE_DEPRECATED_FUNCTIONS -#define INCLUDE_DEPRECATED_FUNCTIONS 0 -#endif - -#ifndef DISABLE_DEPRECATION_WARNINGS -#define DISABLE_DEPRECATION_WARNINGS 0 -#endif - -// further macros are defined in precision.h - -// spoofing above macro as consts to doc -#if 0 - - - /// @notyetdoced - /// @macrodoc - const int INCLUDE_DEPRECATED_FUNCTIONS = 0; - - - /// @notyetdoced - /// @macrodoc - const int DISABLE_DEPRECATION_WARNINGS = 0; - - -#endif - - - // document environment variables // spoof env-vars as consts to doc (hackily and hopefully temporarily) diff --git a/quest/include/precision.h b/quest/include/precision.h index f7a18e416..d37b9a2d3 100644 --- a/quest/include/precision.h +++ b/quest/include/precision.h @@ -1,6 +1,6 @@ /** @file - * User-overridable numerical precision of - * both the QuEST API and backends + * The precision of QuEST's numerical types, some of which + * are overridable and others of which are intendedly fixed. * * @author Tyson Jones * @author Milos Prokop (patched trig overloads in v3) @@ -14,7 +14,7 @@ #ifndef PRECISION_H #define PRECISION_H -#include "quest/include/modes.h" +#include "quest/include/config.h" @@ -76,11 +76,6 @@ * RE-CONFIGURABLE FLOATING-POINT PRECISION */ -// assume double precision as default -#ifndef FLOAT_PRECISION - #define FLOAT_PRECISION 2 -#endif - // validate precision is 1 (float), 2 (double) or 4 (long double) #if ! (FLOAT_PRECISION == 1 || FLOAT_PRECISION == 2 || FLOAT_PRECISION == 4) #error "FLOAT_PRECISION must be 1 (float), 2 (double) or 4 (long double)" @@ -100,10 +95,14 @@ /// @notyetdoced /// @macrodoc + /// + /// (note this macro is informed by the FLOAT_PRECISION CMake variable) const int FLOAT_PRECISION = 2; /// @notyetdoced /// @macrodoc + /// + /// (note this macro is informed by the FLOAT_PRECISION CMake variable) typedef double int FLOAT_TYPE; #endif diff --git a/quest/include/quest.h b/quest/include/quest.h index c0a30ed1f..409253ff8 100644 --- a/quest/include/quest.h +++ b/quest/include/quest.h @@ -2,9 +2,6 @@ * The main QuEST header, exposing the entire API. * This header is intendedly included by user * source-code, and is both C11 and C++14 compatible. - * Preprocessor 'INCLUDE_DEPRECATED_FUNCTIONS' can - * be defined as 1 to additionally include QuEST's - * deprecated v3 API, before including this header. * * @author Tyson Jones * @author Luc Jaulmes (patching CMake install) @@ -30,18 +27,11 @@ #ifndef QUEST_H #define QUEST_H - -// include version first so it is accessible to -// debuggers in case a subsequent include fails -#include "quest/include/version.h" - +// include config.h first to define macros +// consulted by subsequent headers #include "quest/include/config.h" -// include before API headers since it validates -// preprocessor configuration, and affirms macro -// preconditions assumed by subsequent header #include "quest/include/modes.h" - #include "quest/include/precision.h" #include "quest/include/types.h" #include "quest/include/calculations.h" diff --git a/quest/include/types.h b/quest/include/types.h index c006b02cd..066d35e9d 100644 --- a/quest/include/types.h +++ b/quest/include/types.h @@ -19,7 +19,7 @@ #ifndef TYPES_H #define TYPES_H -#include "quest/include/modes.h" +#include "quest/include/config.h" #include "quest/include/precision.h" @@ -157,26 +157,10 @@ static inline qcomp getQcomp(qreal re, qreal im) { // Furthermore, the user might do arithmetic on complex literals which are // not the same precision as qcomp, so compilation will fail depending // on the setting of PRECISION. To avoid this, we'll define overloads - // between all type/precision permutations, always returning qcomp. - // Via the unholy macros below, we create 312 overloads; since this will - // no doubt break somebody's build/integration, users can disable this - // attempt at precision-agnostic arithmetic via DEFINE_ARITHMETIC_OVERLOADS=0 - - #ifndef DEFINE_ARITHMETIC_OVERLOADS - #define DEFINE_ARITHMETIC_OVERLOADS 1 - #endif - - // spoofing above macro as const to doc - #if 0 - - /// @notyetdoced - /// @macrodoc - const int DEFINE_ARITHMETIC_OVERLOADS = 1; - - #endif - - - #if DEFINE_ARITHMETIC_OVERLOADS + // between all type/precision permutations, always returning qcomp. These + // overloads are also used by the QuEST source code. Via the unholy macros + // below, we create 312 overloads; no doubt this is going to break something + // in the future, for which I am already sorry :'( /// @cond EXCLUDE_FROM_DOXYGEN @@ -274,8 +258,6 @@ static inline qcomp getQcomp(qreal re, qreal im) { /// @endcond // EXCLUDE_FROM_DOXYGEN - #endif // DEFINE_ARITHMETIC_OVERLOADS - #endif diff --git a/quest/include/version.h b/quest/include/version.h deleted file mode 100644 index bd3e99a50..000000000 --- a/quest/include/version.h +++ /dev/null @@ -1,18 +0,0 @@ -/** @file - * QuEST version information. - * - * @author Tyson Jones - * - * (no doxygen doc) - */ - -#ifndef VERSION_H -#define VERSION_H - -// TODO: automate this from git somehow -#define QUEST_VERSION_MAJOR 4 -#define QUEST_VERSION_MINOR 1 -#define QUEST_VERSION_PATCH 0 -#define QUEST_VERSION_STRING "4.1.0" - -#endif // VERSION_H \ No newline at end of file diff --git a/quest/src/api/matrices.cpp b/quest/src/api/matrices.cpp index d1c118d17..b17987eb4 100644 --- a/quest/src/api/matrices.cpp +++ b/quest/src/api/matrices.cpp @@ -9,8 +9,9 @@ */ #include "quest/include/matrices.h" -#include "quest/include/environment.h" +#include "quest/include/modes.h" #include "quest/include/types.h" +#include "quest/include/environment.h" #include "quest/src/core/validation.hpp" #include "quest/src/core/autodeployer.hpp" diff --git a/quest/src/api/qureg.cpp b/quest/src/api/qureg.cpp index 7d68528a1..fa7c73b05 100644 --- a/quest/src/api/qureg.cpp +++ b/quest/src/api/qureg.cpp @@ -6,6 +6,7 @@ */ #include "quest/include/qureg.h" +#include "quest/include/modes.h" #include "quest/include/environment.h" #include "quest/include/initialisations.h" diff --git a/quest/src/comm/comm_config.cpp b/quest/src/comm/comm_config.cpp index ae8009ed2..854a12bd5 100644 --- a/quest/src/comm/comm_config.cpp +++ b/quest/src/comm/comm_config.cpp @@ -12,7 +12,7 @@ * @author Tyson Jones */ -#include "quest/include/modes.h" +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/src/comm/comm_config.hpp" diff --git a/quest/src/comm/comm_routines.cpp b/quest/src/comm/comm_routines.cpp index 6e161db18..19ebcb9f8 100644 --- a/quest/src/comm/comm_routines.cpp +++ b/quest/src/comm/comm_routines.cpp @@ -10,6 +10,7 @@ * @author Ania (Anna) Brown (developed QuEST v1 logic) */ +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/matrices.h" diff --git a/quest/src/core/parser.cpp b/quest/src/core/parser.cpp index 8884acc4c..5448d3862 100644 --- a/quest/src/core/parser.cpp +++ b/quest/src/core/parser.cpp @@ -10,6 +10,7 @@ * @author Tyson Jones */ +#include "quest/include/config.h" #include "quest/include/precision.h" #include "quest/include/types.h" #include "quest/include/paulis.h" diff --git a/quest/src/core/printer.cpp b/quest/src/core/printer.cpp index 3d2a4d9f0..e4d4cbc32 100644 --- a/quest/src/core/printer.cpp +++ b/quest/src/core/printer.cpp @@ -9,6 +9,7 @@ * @author Erich Essmann (improved OS agnosticism, patched mem-leak) */ +#include "quest/include/config.h" #include "quest/include/qureg.h" #include "quest/include/types.h" #include "quest/include/matrices.h" diff --git a/quest/src/core/utilities.cpp b/quest/src/core/utilities.cpp index 4966d1916..999bd9a72 100644 --- a/quest/src/core/utilities.cpp +++ b/quest/src/core/utilities.cpp @@ -8,6 +8,7 @@ * @author Luc Jaulmes (distributing ranges over blocks) */ +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/paulis.h" diff --git a/quest/src/core/utilities.hpp b/quest/src/core/utilities.hpp index cb2d8e713..4b7fb5db6 100644 --- a/quest/src/core/utilities.hpp +++ b/quest/src/core/utilities.hpp @@ -12,6 +12,7 @@ #ifndef UTILITIES_HPP #define UTILITIES_HPP +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/paulis.h" diff --git a/quest/src/cpu/cpu_config.cpp b/quest/src/cpu/cpu_config.cpp index e488e6a9c..c11ec224d 100644 --- a/quest/src/cpu/cpu_config.cpp +++ b/quest/src/cpu/cpu_config.cpp @@ -6,7 +6,7 @@ * @author Luc Jaulmes (NUMA awareness) */ -#include "quest/include/modes.h" +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/include/paulis.h" diff --git a/quest/src/cpu/cpu_subroutines.cpp b/quest/src/cpu/cpu_subroutines.cpp index 26c80dabc..2b77638d3 100644 --- a/quest/src/cpu/cpu_subroutines.cpp +++ b/quest/src/cpu/cpu_subroutines.cpp @@ -15,7 +15,6 @@ * @author Ania (Anna) Brown (developed QuEST v1 logic) */ -#include "quest/include/modes.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/paulis.h" diff --git a/quest/src/gpu/gpu_config.cpp b/quest/src/gpu/gpu_config.cpp index 87a1c5192..c7db834b7 100644 --- a/quest/src/gpu/gpu_config.cpp +++ b/quest/src/gpu/gpu_config.cpp @@ -5,7 +5,7 @@ * @author Tyson Jones */ -#include "quest/include/modes.h" +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/matrices.h" diff --git a/quest/src/gpu/gpu_config.hpp b/quest/src/gpu/gpu_config.hpp index 7517cb2a3..1b3be6295 100644 --- a/quest/src/gpu/gpu_config.hpp +++ b/quest/src/gpu/gpu_config.hpp @@ -12,6 +12,7 @@ #ifndef GPU_CONFIG_HPP #define GPU_CONFIG_HPP +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/matrices.h" diff --git a/quest/src/gpu/gpu_cuquantum.cuh b/quest/src/gpu/gpu_cuquantum.cuh index f627990fd..6ba321000 100644 --- a/quest/src/gpu/gpu_cuquantum.cuh +++ b/quest/src/gpu/gpu_cuquantum.cuh @@ -25,7 +25,9 @@ #define GPU_CUQUANTUM_HPP -// check preprocessors and compilers are valid before #includes to avoid compile errors +// check preprocessors and compilers are valid before #includes to avoid +// compile errors (though we must still obtain the preprocessors from config.h) +#include "quest/include/config.h" #if ! COMPILE_CUQUANTUM #error "A file being compiled somehow included gpu_cuquantum.hpp despite QuEST not being compiled in cuQuantum mode." diff --git a/quest/src/gpu/gpu_kernels.cuh b/quest/src/gpu/gpu_kernels.cuh index 448073fe0..4f2a737e4 100644 --- a/quest/src/gpu/gpu_kernels.cuh +++ b/quest/src/gpu/gpu_kernels.cuh @@ -18,7 +18,7 @@ #ifndef GPU_KERNELS_HPP #define GPU_KERNELS_HPP -#include "quest/include/modes.h" +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/src/core/bitwise.hpp" diff --git a/quest/src/gpu/gpu_subroutines.cpp b/quest/src/gpu/gpu_subroutines.cpp index 034d87f48..5e18048f7 100644 --- a/quest/src/gpu/gpu_subroutines.cpp +++ b/quest/src/gpu/gpu_subroutines.cpp @@ -32,11 +32,13 @@ * @author Tyson Jones */ +// obtain preprocessors from config.h prior to validation +#include "quest/include/config.h" + #if (COMPILE_CUQUANTUM && ! COMPILE_CUDA) #error "Cannot define COMPILE_CUQUANTUM=1 without simultaneously defining COMPILE_CUDA=1" #endif -#include "quest/include/modes.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/paulis.h" diff --git a/quest/src/gpu/gpu_thrust.cuh b/quest/src/gpu/gpu_thrust.cuh index 44a37fadd..9f8d8f1ab 100644 --- a/quest/src/gpu/gpu_thrust.cuh +++ b/quest/src/gpu/gpu_thrust.cuh @@ -21,11 +21,13 @@ #ifndef GPU_THRUST_HPP #define GPU_THRUST_HPP +// obtain preprocessors from config.h prior to validation +#include "quest/include/config.h" + #if ! COMPILE_CUDA #error "A file being compiled somehow included gpu_thrust.hpp despite QuEST not being compiled in GPU-accelerated mode." #endif -#include "quest/include/modes.h" #include "quest/include/types.h" #include "quest/include/qureg.h" #include "quest/include/paulis.h" diff --git a/quest/src/gpu/gpu_types.cuh b/quest/src/gpu/gpu_types.cuh index 8fe8e6930..a934ecef6 100644 --- a/quest/src/gpu/gpu_types.cuh +++ b/quest/src/gpu/gpu_types.cuh @@ -14,7 +14,7 @@ #ifndef GPU_TYPES_HPP #define GPU_TYPES_HPP -#include "quest/include/modes.h" +#include "quest/include/config.h" #include "quest/include/types.h" #include "quest/include/precision.h" diff --git a/tests/deprecated/CMakeLists.txt b/tests/deprecated/CMakeLists.txt index 0887bce16..f9132c74a 100644 --- a/tests/deprecated/CMakeLists.txt +++ b/tests/deprecated/CMakeLists.txt @@ -13,7 +13,6 @@ add_executable(dep_tests test_utilities.cpp ) target_link_libraries(dep_tests PUBLIC QuEST::QuEST Catch2::Catch2) -target_compile_definitions(dep_tests PRIVATE INCLUDE_DEPRECATED_FUNCTIONS=1) if (ENABLE_DISTRIBUTION) target_link_libraries(dep_tests PRIVATE MPI::MPI_CXX) diff --git a/tests/deprecated/test_calculations.cpp b/tests/deprecated/test_calculations.cpp index 3ed8f560e..0f02a6dea 100644 --- a/tests/deprecated/test_calculations.cpp +++ b/tests/deprecated/test_calculations.cpp @@ -15,13 +15,7 @@ #include #include -// must define preprocessors to enable quest's -// deprecated v3 API, and disable the numerous -// warnings issued by its compilation -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 #include "quest.h" - #include "test_utilities.hpp" /* allows concise use of ContainsSubstring in catch's REQUIRE_THROWS_WITH */ @@ -918,8 +912,8 @@ TEST_CASE( "calcInnerProduct", "[calculations]" ) { toQureg(vec2, r2); qcomp res = calcInnerProduct(vec1,vec2); - REQUIRE( real(res) == Approx(real(prod)) ); - REQUIRE( imag(res) == Approx(imag(prod)) ); + REQUIRE( real(res) == Approx(real(prod)).margin(REAL_EPS) ); + REQUIRE( imag(res) == Approx(imag(prod)).margin(REAL_EPS) ); } } } diff --git a/tests/deprecated/test_data_structures.cpp b/tests/deprecated/test_data_structures.cpp index 258d83f75..bc336f7dd 100644 --- a/tests/deprecated/test_data_structures.cpp +++ b/tests/deprecated/test_data_structures.cpp @@ -15,13 +15,7 @@ #include #include -// must define preprocessors to enable quest's -// deprecated v3 API, and disable the numerous -// warnings issued by its compilation -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 #include "quest.h" - #include "test_utilities.hpp" /* allows concise use of ContainsSubstring in catch's REQUIRE_THROWS_WITH */ diff --git a/tests/deprecated/test_decoherence.cpp b/tests/deprecated/test_decoherence.cpp index 295263ef2..edf1d9f61 100644 --- a/tests/deprecated/test_decoherence.cpp +++ b/tests/deprecated/test_decoherence.cpp @@ -16,12 +16,7 @@ #include #include -// must define preprocessors to enable quest's -// deprecated v3 API, and disable the numerous -// warnings issued by its compilation -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 - +#include "quest.h" #include "test_utilities.hpp" #include diff --git a/tests/deprecated/test_gates.cpp b/tests/deprecated/test_gates.cpp index f8c175666..5542318a4 100644 --- a/tests/deprecated/test_gates.cpp +++ b/tests/deprecated/test_gates.cpp @@ -18,13 +18,7 @@ #include #include -// must define preprocessors to enable quest's -// deprecated v3 API, and disable the numerous -// warnings issued by its compilation -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 #include "quest.h" - #include "test_utilities.hpp" /* allows concise use of ContainsSubstring in catch's REQUIRE_THROWS_WITH */ diff --git a/tests/deprecated/test_main.cpp b/tests/deprecated/test_main.cpp index fc75d8190..35ba37477 100644 --- a/tests/deprecated/test_main.cpp +++ b/tests/deprecated/test_main.cpp @@ -17,10 +17,6 @@ */ #include - -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 - #include "quest.h" #include "test_utilities.hpp" diff --git a/tests/deprecated/test_operators.cpp b/tests/deprecated/test_operators.cpp index 6130ad3b8..12f2cb0a7 100644 --- a/tests/deprecated/test_operators.cpp +++ b/tests/deprecated/test_operators.cpp @@ -15,13 +15,7 @@ #include #include -// must define preprocessors to enable quest's -// deprecated v3 API, and disable the numerous -// warnings issued by its compilation -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 #include "quest.h" - #include "test_utilities.hpp" /** Prepares the needed data structures for unit testing some operators. diff --git a/tests/deprecated/test_state_initialisations.cpp b/tests/deprecated/test_state_initialisations.cpp index aca87f68f..995cf8a41 100644 --- a/tests/deprecated/test_state_initialisations.cpp +++ b/tests/deprecated/test_state_initialisations.cpp @@ -14,10 +14,7 @@ #include #include -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 #include "quest.h" - #include "test_utilities.hpp" /* allows concise use of ContainsSubstring in catch's REQUIRE_THROWS_WITH */ diff --git a/tests/deprecated/test_unitaries.cpp b/tests/deprecated/test_unitaries.cpp index 6414880d1..f0bb2f5aa 100644 --- a/tests/deprecated/test_unitaries.cpp +++ b/tests/deprecated/test_unitaries.cpp @@ -15,13 +15,7 @@ #include #include -// must define preprocessors to enable quest's -// deprecated v3 API, and disable the numerous -// warnings issued by its compilation -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 #include "quest.h" - #include "test_utilities.hpp" /** Prepares the needed data structures for unit testing unitaries. diff --git a/tests/deprecated/test_utilities.cpp b/tests/deprecated/test_utilities.cpp index 27ef8af9f..81be43525 100644 --- a/tests/deprecated/test_utilities.cpp +++ b/tests/deprecated/test_utilities.cpp @@ -9,10 +9,7 @@ #include #include -#define INCLUDE_DEPRECATED_FUNCTIONS 1 -#define DISABLE_DEPRECATION_WARNINGS 1 #include "quest.h" - #include "test_utilities.hpp" #include diff --git a/utils/scripts/compile.sh b/utils/scripts/compile.sh index ac6eccf02..8eca0ae27 100755 --- a/utils/scripts/compile.sh +++ b/utils/scripts/compile.sh @@ -16,27 +16,35 @@ FLOAT_PRECISION=2 # deployments to compile (0, 1) -COMPILE_MPI=0 # distribution -COMPILE_OPENMP=0 # multithreading -COMPILE_CUDA=0 # GPU acceleration -COMPILE_CUQUANTUM=0 # GPU + cuQuantum +ENABLE_DISTRIBUTION=0 # MPI +ENABLE_MULTITHREADING=0 # OpenMP +ENABLE_CUDA=0 # NVIDIA GPU +ENABLE_HIP=0 # AMD GPU +ENABLE_CUQUANTUM=0 # NVIDIA cuStateVec +ENABLE_NUMA=0 # NUMA awareness -# GPU compute capability -GPU_CC=90 +# other options (0, 1) +ENABLE_DEPRECATED_API=0 +DISABLE_DEPRECATION_WARNINGS=0 + +# NVIDIA compute capability or AMD arch (e.g. 60 or gfx908) +GPU_ARCH=90 # backend compilers TESTS_COMPILER=g++ BASE_COMPILER=g++ OMP_COMPILER=g++ MPI_COMPILER=mpic++ -GPU_COMPILER=nvcc +CUDA_COMPILER=nvcc +HIP_COMPILER=hipcc # linker LINKER=g++ -# whether to compile unit tests (1) or the below user files (0), -# or the v3 deprecated unit tests (2). when either tests are -# compiled, all user-source related settings are ignored. +# whether to compile the below user source files (0), +# or the unit tests (1), which when paired with above +# ENABLE_DEPRECATED_API=1, will use the v3 tests (which +# you should pair with DISABLE_DEPRECATION_WARNINGS=1) COMPILE_TESTS=0 # name of the compiled test executable @@ -64,7 +72,7 @@ USER_CXX_COMP_FLAGS='-std=c++14' # user linker flags USER_LINK_FLAGS='-lstdc++' -# whether to compile cuQuantum (consulted only when COMPILE_CUQUANTUM=1) +# whether to compile cuQuantum (consulted only when ENABLE_CUQUANTUM=1) # in debug mode, which logs to below file with performance tips and errors CUQUANTUM_LOG=0 CUQUANTUM_LOG_FN="./custatevec_log.txt" @@ -72,14 +80,10 @@ CUQUANTUM_LOG_FN="./custatevec_log.txt" # external library locations (replace with "." to default) CUQUANTUM_LIB_DIR="${CUQUANTUM_ROOT}" CUDA_LIB_DIR="/usr/local/cuda" +ROCM_LIB_DIR="/opt/rocm" OMP_LIB_DIR="/opt/homebrew/opt/libomp" MPI_LIB_DIR="/opt/homebrew/opt/openmpi" -CATCH_LIB_DIR="tests/deprecated/catch" - -# TODO: -# use of 'CATCH_LIB_DIR' above will change when v4 tests -# switch to using Catch2 as supplied by CMake, rather -# than the hacky use of deprecated v3's single-header +CATCH_LIB_DIR="$(pwd)/catch" @@ -91,6 +95,8 @@ TEST_OBJ_PREF='test_' INDENT=' ' +CATCH_VERSION="3.4.0" + # QUEST FILE LAYOUT @@ -112,6 +118,10 @@ TEST_UNIT_DIR="${TEST_MAIN_DIR}/unit" TEST_DEPR_DIR="${TEST_MAIN_DIR}/deprecated" TEST_DEPR_CATCH_DIR="${TEST_DEPR_DIR}/catch" +# files that require modification by this script +CONFIG_FILE_IN="${INCLUDE_DIR}/config.h.in" +CONFIG_FILE_OUT="${INCLUDE_DIR}/config.h" + # files in API_DIR API_FILES=( "calculations" @@ -122,9 +132,11 @@ API_FILES=( "initialisations" "matrices" "modes" + "multiplication" "operations" "paulis" "qureg" + "trotterisation" "types" ) @@ -132,10 +144,12 @@ API_FILES=( CORE_FILES=( "accelerator" "autodeployer" + "envvars" "errors" "localiser" "memory" "parser" + "paulilogic" "printer" "randomiser" "utilities" @@ -169,6 +183,7 @@ TEST_MAIN_FILES=( TEST_UTIL_FILES=( "cache" "compare" + "config" "convert" "evolve" "linalg" @@ -188,9 +203,11 @@ TEST_UNIT_FILES=( "environment" "initialisations" "matrices" + "multiplication" "operations" "paulis" "qureg" + "trotterisation" "types" ) @@ -216,10 +233,11 @@ TEST_DEPR_MPI_FILES=( # COMPILER AND LINKER FLAG OPTIONS # compiler flags given to all (non-deprecated) files -TEST_COMP_FLAGS="-std=c++20 -I${CATCH_LIB_DIR}" +TEST_COMP_FLAGS="-std=c++20 -I${CATCH_LIB_DIR}/include" +TEST_LINK_FLAGS="-L${CATCH_LIB_DIR}/lib -lCatch2" # compiler flags given to deprecated test files -TEST_DEPR_COMP_FLAGS="-std=c++17 -I${TEST_DEPR_CATCH_DIR}" +TEST_DEPR_COMP_FLAGS="-std=c++17 -I${CATCH_LIB_DIR}/include" # compiler flags given to all backend files BACKEND_COMP_FLAGS='-std=c++17 -O3' @@ -227,23 +245,27 @@ BACKEND_COMP_FLAGS='-std=c++17 -O3' # warning flags which apply to all compiled and linked files including user's WARNING_FLAGS='-Wall' -# GPU-specific flags -GPU_COMP_FLAGS="-x cu -arch=sm_${GPU_CC} -I${CUDA_LIB_DIR}/include" -GPU_LINK_FLAGS="-L${CUDA_LIB_DIR}/lib -L${CUDA_LIB_DIR}/lib64 -lcudart -lcuda" +# CUDA specific flags +CUDA_COMP_FLAGS="-x cu -arch=sm_${GPU_ARCH} -I${CUDA_LIB_DIR}/include" +CUDA_LINK_FLAGS="-L${CUDA_LIB_DIR}/lib -L${CUDA_LIB_DIR}/lib64 -lcudart -lcuda" -if [ $COMPILE_CUQUANTUM == 1 ] +if [ $ENABLE_CUQUANTUM == 1 ] then # extend GPU flags if cuQuantum enabled - GPU_COMP_FLAGS+=" -I${CUQUANTUM_LIB_DIR}/include" - GPU_LINK_FLAGS+=" -L${CUQUANTUM_LIB_DIR}/lib -L${CUQUANTUM_LIB_DIR}/lib64 -lcustatevec" + CUDA_COMP_FLAGS+=" -I${CUQUANTUM_LIB_DIR}/include" + CUDA_LINK_FLAGS+=" -L${CUQUANTUM_LIB_DIR}/lib -L${CUQUANTUM_LIB_DIR}/lib64 -lcustatevec" # optional debug logging - will slow down code if [ $CUQUANTUM_LOG == 1 ] then - GPU_COMP_FLAGS+=" -DCUSTATEVEC_LOG_LEVEL=5 -DCUSTATEVEC_LOG_FILE=${CUQUANTUM_LOG_FN}" + CUDA_COMP_FLAGS+=" -DCUSTATEVEC_LOG_LEVEL=5 -DCUSTATEVEC_LOG_FILE=${CUQUANTUM_LOG_FN}" fi fi +# HIP specific flags +HIP_COMP_FLAGS="-x hip --offload-arch=${GPU_ARCH} -I${ROCM_LIB_DIR}/include" +HIP_LINK_FLAGS="-L${ROCM_LIB_DIR}/lib -lamdhip64" + # MPI-specific flags MPI_COMP_FLAGS="-I${MPI_LIB_DIR}/include" MPI_LINK_FLAGS="-L${MPI_LIB_DIR}/lib -lmpi" @@ -271,14 +293,10 @@ else OMP_LINK_FLAGS+=' -fopenmp' fi -# define pre-processor macros to indicate deployment mode -MODE_FLAGS="-DCOMPILE_MPI=${COMPILE_MPI} " -MODE_FLAGS+="-DCOMPILE_OPENMP=${COMPILE_OPENMP} " -MODE_FLAGS+="-DCOMPILE_CUDA=${COMPILE_CUDA} " -MODE_FLAGS+="-DCOMPILE_CUQUANTUM=${COMPILE_CUQUANTUM}" - -# define pre-processor macros to set qcomp precision -PREC_FLAG="-DFLOAT_PRECISION=${FLOAT_PRECISION}" +if [ $ENABLE_NUMA == 1 ] +then + OMP_LINK_FLAGS+=' -lnuma' +fi # point compilers to QuEST src HEADER_FLAGS="-I. -I${INCLUDE_DIR}" @@ -290,34 +308,44 @@ HEADER_FLAGS="-I. -I${INCLUDE_DIR}" echo "" echo "deployment modes:" -# flags given to every compilation unit -GLOBAL_COMP_FLAGS="${HEADER_FLAGS} ${MODE_FLAGS} ${PREC_FLAG}" - # choose linker flags (extended below) ALL_LINK_FLAGS="${USER_LINK_FLAGS}" # choose compiler and flags for CPU/OMP files -if [ $COMPILE_OPENMP == 1 ] +CPU_FILES_FLAGS='-Ofast -DCOMPLEX_OVERLOADS_PATCHED=1' + +if [ $ENABLE_MULTITHREADING == 1 ] then echo "${INDENT}(multithreading enabled)" echo "${INDENT}${INDENT}[compiling OpenMP]" + if [ $ENABLE_NUMA == 1 ] + then + echo "${INDENT}${INDENT}[compiling NUMA]" + fi CPU_FILES_COMPILER=$OMP_COMPILER - CPU_FILES_FLAGS=$OMP_COMP_FLAGS + CPU_FILES_FLAGS+=" ${OMP_COMP_FLAGS}" ALL_LINK_FLAGS+=" ${OMP_LINK_FLAGS}" else echo "${INDENT}(multithreading disabled)" CPU_FILES_COMPILER=$BASE_COMPILER - CPU_FILES_FLAGS='' fi # choose compiler and flags for GPU files -if [ $COMPILE_CUDA == 1 ] +if [ $ENABLE_CUDA == 1 ] then echo "${INDENT}(GPU-acceleration enabled)" echo "${INDENT}${INDENT}[compiling CUDA]" - GPU_FILES_COMPILER=$GPU_COMPILER - GPU_FILES_FLAGS=$GPU_COMP_FLAGS - ALL_LINK_FLAGS+=" ${GPU_LINK_FLAGS}" + GPU_FILES_COMPILER=$CUDA_COMPILER + GPU_FILES_FLAGS=$CUDA_COMP_FLAGS + ALL_LINK_FLAGS+=" ${CUDA_LINK_FLAGS}" + GPU_WARNING_FLAGS="-Xcompiler ${WARNING_FLAGS}" +elif [ $ENABLE_HIP == 1 ] +then + echo "${INDENT}(GPU-acceleration enabled)" + echo "${INDENT}${INDENT}[compiling HIP]" + GPU_FILES_COMPILER=$HIP_COMPILER + GPU_FILES_FLAGS=$HIP_COMP_FLAGS + ALL_LINK_FLAGS+=" ${HIP_LINK_FLAGS}" GPU_WARNING_FLAGS="-Xcompiler ${WARNING_FLAGS}" else echo "${INDENT}(GPU-acceleration disabled)" @@ -327,7 +355,7 @@ else fi # merely report cuQuantum status -if [ $COMPILE_CUQUANTUM == 1 ] +if [ $ENABLE_CUQUANTUM == 1 ] then echo "${INDENT}(cuQuantum enabled)" echo "${INDENT}${INDENT}[compiling cuStateVec]" @@ -336,7 +364,7 @@ else fi # choose compiler and flags for communication files -if [ $COMPILE_MPI == 1 ] +if [ $ENABLE_DISTRIBUTION == 1 ] then echo "${INDENT}(distribution enabled)" echo "${INDENT}${INDENT}[compiling MPI]" @@ -349,7 +377,7 @@ else MPI_FILES_FLAGS='' fi -# choose linker warning flag (to avoid pass them to nvcc) +# choose linker warning flag (to avoid passing them to nvcc) if [ "${LINKER}" = "nvcc" ] then ALL_LINK_FLAGS+="-Xcompiler ${WARNING_FLAGS}" @@ -357,6 +385,12 @@ else ALL_LINK_FLAGS+=" ${WARNING_FLAGS}" fi +# test link flags +if [ "${COMPILE_TESTS}" -eq 1 ] +then + ALL_LINK_FLAGS+=" ${TEST_LINK_FLAGS}" +fi + # display precision if [ $FLOAT_PRECISION == 1 ]; then echo "${INDENT}(single precision)" @@ -377,7 +411,6 @@ echo "" # REPORTING COMILERS FLAGS - echo "chosen compilers and flags..." # user compilers @@ -389,14 +422,14 @@ then fi # test compiler -if (( $COMPILE_TESTS == 1 )) +if (( $COMPILE_TESTS == 1 && ENABLE_DEPRECATED_API == 0 )) then echo "${INDENT}tests compiler and flags:" echo "${INDENT}${INDENT}${TESTS_COMPILER} ${TEST_COMP_FLAGS} ${WARNING_FLAGS}" fi # deprecated compiler -if (( $COMPILE_TESTS == 2 )) +if (( $COMPILE_TESTS == 1 && ENABLE_DEPRECATED_API == 1 )) then echo "${INDENT}deprecated tests compiler and flags:" echo "${INDENT}${INDENT}${TESTS_COMPILER} ${TEST_DEPR_COMP_FLAGS} ${WARNING_FLAGS}" @@ -425,7 +458,67 @@ echo "${INDENT}${INDENT}${LINKER} ${ALL_LINK_FLAGS}" # globals echo "${INDENT}header flags:" echo "${INDENT}${INDENT}${HEADER_FLAGS}" +echo "" + + +# OPTIONALLY PREPARING CATCH2 + +if [ "${COMPILE_TESTS}" -eq 1 ] +then + echo "preparing Catch2:" + + if [ -d "${CATCH_LIB_DIR}" ] + then + echo "${INDENT}found at ${CATCH_LIB_DIR}" + else + echo "${INDENT}downloading to ${CATCH_LIB_DIR}..." + git clone --quiet https://github.com/catchorg/Catch2.git "${CATCH_LIB_DIR}" + + ORIGINAL_DIR=$(pwd) + + echo "${INDENT}configuring..." + cd "${CATCH_LIB_DIR}" + git fetch --quiet --tags + git checkout --quiet "v${CATCH_VERSION}" + git submodule update --quiet --init --recursive + + echo "${INDENT}building..." + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX="${CATCH_LIB_DIR}" + cmake --build . --target install --parallel + + cd "${ORIGINAL_DIR}" + fi + + echo "" +fi + + + +# GENERATING CONFIG HEADER + +echo "generating headers:" + +# write user-options as macros to config.h (and set version info to -1) +sed \ + -e "s|#cmakedefine FLOAT_PRECISION @FLOAT_PRECISION@|#define FLOAT_PRECISION ${FLOAT_PRECISION}|" \ + -e "s|#cmakedefine01 INCLUDE_DEPRECATED_FUNCTIONS|#define INCLUDE_DEPRECATED_FUNCTIONS ${ENABLE_DEPRECATED_API}|" \ + -e "s|#cmakedefine01 DISABLE_DEPRECATION_WARNINGS|#define DISABLE_DEPRECATION_WARNINGS ${DISABLE_DEPRECATION_WARNINGS}|" \ + -e "s|#cmakedefine01 COMPILE_OPENMP|#define COMPILE_OPENMP ${ENABLE_MULTITHREADING}|" \ + -e "s|#cmakedefine01 COMPILE_MPI|#define COMPILE_MPI ${ENABLE_DISTRIBUTION}|" \ + -e "s|#cmakedefine01 COMPILE_CUDA|#define COMPILE_CUDA $(( ENABLE_CUDA || ENABLE_HIP ))|" \ + -e "s|#cmakedefine01 COMPILE_CUQUANTUM|#define COMPILE_CUQUANTUM ${ENABLE_CUQUANTUM}|" \ + -e "s|#cmakedefine01 COMPILE_HIP|#define COMPILE_HIP ${ENABLE_HIP}|" \ + -e "s|#cmakedefine01 NUMA_AWARE|#define NUMA_AWARE ${ENABLE_NUMA}|" \ + -e "s|@PROJECT_VERSION@|unknown (not populated by manual compilation)|" \ + -e "s|@PROJECT_VERSION_MAJOR@|-1|" \ + -e "s|@PROJECT_VERSION_MINOR@|-1|" \ + -e "s|@PROJECT_VERSION_PATCH@|-1|" \ + "${CONFIG_FILE_IN}" > "${CONFIG_FILE_OUT}" + +echo "${INDENT}${CONFIG_FILE_OUT}" echo "" @@ -454,7 +547,7 @@ then fi # compile - $COMP -c $USER_DIR/$fn -o ${USER_OBJ_PREF}${fn}.o $FLAG $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $COMP -c $USER_DIR/$fn -o ${USER_OBJ_PREF}${fn}.o $FLAG $HEADER_FLAGS $WARNING_FLAGS done echo "" @@ -464,7 +557,7 @@ fi # COMPILING TESTS -if (( $COMPILE_TESTS == 1 )) +if (( $COMPILE_TESTS == 1 && $ENABLE_DEPRECATED_API == 0 )) then echo "compiling unit test files:" @@ -474,7 +567,7 @@ then for fn in ${TEST_MAIN_FILES[@]} do echo "${INDENT}${INDENT}${fn}.cpp ..." - $TESTS_COMPILER -c $TEST_MAIN_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $TESTS_COMPILER -c $TEST_MAIN_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "${INDENT}utils:" @@ -482,7 +575,7 @@ then for fn in ${TEST_UTIL_FILES[@]} do echo "${INDENT}${INDENT}${fn}.cpp ..." - $TESTS_COMPILER -c $TEST_UTIL_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $TESTS_COMPILER -c $TEST_UTIL_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "${INDENT}unit:" @@ -490,7 +583,7 @@ then for fn in ${TEST_UNIT_FILES[@]} do echo "${INDENT}${INDENT}${fn}.cpp ..." - $TESTS_COMPILER -c $TEST_UNIT_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $TESTS_COMPILER -c $TEST_UNIT_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "" @@ -500,20 +593,25 @@ fi # COMPILING DEPRECATED TESTS -if (( $COMPILE_TESTS == 2 )) +if (( $COMPILE_TESTS == 1 && $ENABLE_DEPRECATED_API == 1 )) then echo "compiling deprecated test files:" + if (( $DISABLE_DEPRECATION_WARNINGS == 0 )) + then + echo "${INDENT}(beware deprecation warnings were not disabled)" + fi + for fn in ${TEST_DEPR_FILES[@]} do echo "${INDENT}${fn}.cpp ..." - $TESTS_COMPILER -c $TEST_DEPR_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_DEPR_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $TESTS_COMPILER -c $TEST_DEPR_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_DEPR_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done for fn in ${TEST_DEPR_MPI_FILES[@]} do echo "${INDENT}${fn}.cpp ..." - $MPI_FILES_COMPILER -c $TEST_DEPR_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_DEPR_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $MPI_FILES_COMPILER -c $TEST_DEPR_DIR/$fn.cpp -o ${TEST_OBJ_PREF}${fn}.o $TEST_DEPR_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "" @@ -528,7 +626,7 @@ echo "compiling core files in C++" for fn in ${CORE_FILES[@]} do echo "${INDENT}${fn}.cpp ..." - $BASE_COMPILER -c $CORE_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $BACKEND_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $BASE_COMPILER -c $CORE_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $BACKEND_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "" @@ -542,7 +640,7 @@ echo "compiling API files in C++:" for fn in ${API_FILES[@]} do echo "${INDENT}${fn}.cpp ..." - $BASE_COMPILER -c $API_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $BACKEND_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $BASE_COMPILER -c $API_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $BACKEND_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "" @@ -556,7 +654,7 @@ echo "compiling CPU/OMP files..." for fn in ${OMP_FILES[@]} do echo "${INDENT}${fn}.cpp ..." - $CPU_FILES_COMPILER -c $OMP_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $CPU_FILES_FLAGS $BACKEND_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $CPU_FILES_COMPILER -c $OMP_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $CPU_FILES_FLAGS $BACKEND_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "" @@ -570,7 +668,7 @@ echo "compiling GPU files..." for fn in ${GPU_FILES[@]} do echo "${INDENT}${fn}.cpp ..." - $GPU_FILES_COMPILER -c $GPU_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $GPU_FILES_FLAGS $BACKEND_COMP_FLAGS $GLOBAL_COMP_FLAGS $GPU_WARNING_FLAGS + $GPU_FILES_COMPILER -c $GPU_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $GPU_FILES_FLAGS $BACKEND_COMP_FLAGS $HEADER_FLAGS $GPU_WARNING_FLAGS done echo "" @@ -584,7 +682,7 @@ echo "compiling communication/MPI files..." for fn in ${MPI_FILES[@]} do echo "${INDENT}${fn}.cpp ..." - $MPI_FILES_COMPILER -c $MPI_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $MPI_FILES_FLAGS $BACKEND_COMP_FLAGS $GLOBAL_COMP_FLAGS $WARNING_FLAGS + $MPI_FILES_COMPILER -c $MPI_DIR/$fn.cpp -o ${QUEST_OBJ_PREF}${fn}.o $MPI_FILES_FLAGS $BACKEND_COMP_FLAGS $HEADER_FLAGS $WARNING_FLAGS done echo "" @@ -606,12 +704,12 @@ OBJECTS+=" $(printf " ${QUEST_OBJ_PREF}%s.o" "${MPI_FILES[@]}")" if (( $COMPILE_TESTS == 0 )) then OBJECTS+=" $(printf " ${USER_OBJ_PREF}%s.o" "${USER_FILES[@]}")" -elif (( $COMPILE_TESTS == 1 )) +elif (( $COMPILE_TESTS == 1 && $ENABLE_DEPRECATED_API == 0 )) then OBJECTS+=" $(printf " ${TEST_OBJ_PREF}%s.o" "${TEST_MAIN_FILES[@]}")" OBJECTS+=" $(printf " ${TEST_OBJ_PREF}%s.o" "${TEST_UTIL_FILES[@]}")" OBJECTS+=" $(printf " ${TEST_OBJ_PREF}%s.o" "${TEST_UNIT_FILES[@]}")" -elif (( $COMPILE_TESTS == 2 )) +elif (( $COMPILE_TESTS == 1 && $ENABLE_DEPRECATED_API == 1 )) then OBJECTS+=" $(printf " ${TEST_OBJ_PREF}%s.o" "${TEST_DEPR_FILES[@]}")" OBJECTS+=" $(printf " ${TEST_OBJ_PREF}%s.o" "${TEST_DEPR_MPI_FILES[@]}")"