# ============================================================================ # # Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. # # All rights reserved. # # # # This source code and the accompanying materials are made available under # # the terms of the Apache License 2.0 which accompanies this distribution. # # ============================================================================ # cmake_minimum_required(VERSION 3.22 FATAL_ERROR) # Policies # ============================================================================== if(POLICY CMP0068) cmake_policy(SET CMP0068 NEW) set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) endif() if(POLICY CMP0075) cmake_policy(SET CMP0075 NEW) endif() if(POLICY CMP0077) cmake_policy(SET CMP0077 NEW) endif() if(POLICY CMP0057) cmake_policy(SET CMP0057 NEW) endif() if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) endif() # CMP0135: Timestamp for content downloaded with ExternalProject_Add() # New in CMake 3.24 https://cmake.org/cmake/help/latest/policy/CMP0135.html if(POLICY CMP0135) cmake_policy(SET CMP0135 NEW) endif() # CMP0116: Ninja generators transform `DEPFILE`s from `add_custom_command()` # New in CMake 3.20. https://cmake.org/cmake/help/latest/policy/CMP0116.html if(POLICY CMP0116) cmake_policy(SET CMP0116 OLD) endif() # Project setup # ============================================================================== project(cudaq LANGUAGES CXX C) # Prevent In-source builds # ============================================================================== # Using the undocumented `CMAKE_DISABLE_IN_SOURCE_BUILDS` and # `CMAKE_DISABLE_SOURCE_CHANCES` variables is not a good idea: They can change # without warning and they do not accomplish what they are supposed to do, i.e., # cmake files will still be created in the source tree. # Going the extra mile to prevent the user from playing tricks with symlinks. get_filename_component(REAL_PROJECT_SOURCE_DIR "${PROJECT_SOURCE_DIR}" REALPATH) get_filename_component(REAL_PROJECT_BINARY_DIR "${PROJECT_BINARY_DIR}" REALPATH) if("${REAL_PROJECT_SOURCE_DIR}" STREQUAL "${REAL_PROJECT_BINARY_DIR}") message(FATAL_ERROR "In-source builds are not permitted. You must run cmake in a separeted " "directory, e.g.:\n" " mkdir build && cd build && cmake ..\n" "NOTE: Remeber to clean up the source tree by deleting the files already " "created by CMake, e.g, CMakeCache.txt and cmake.check_cache") endif() # Project globals # ============================================================================== set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED on) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) # Set warnings as errors by default. # Individual targets and the command line invocation can override this behavior. if(NOT DEFINED CMAKE_COMPILE_WARNING_AS_ERROR) set(CMAKE_COMPILE_WARNING_AS_ERROR ON) endif() # Enable the REST code by default. if (NOT DEFINED CUDAQ_ENABLE_REST) set(CUDAQ_ENABLE_REST ON CACHE BOOL "Enable building REST client & server.") endif() # Enable the remote simulator by default. if (CUDAQ_ENABLE_REST AND NOT DEFINED CUDAQ_ENABLE_REMOTE_SIM) set(CUDAQ_ENABLE_REMOTE_SIM ON CACHE BOOL "Enable building cudaq-qpud.") # Optionally enable the tests that use cudaq-qpud. if (NOT DEFINED CUDAQ_TEST_REMOTE_SIM) set(CUDAQ_TEST_REMOTE_SIM ON CACHE BOOL "Run remote-sim tests.") endif() endif() # Enable Amazon Braket backends by default. if (NOT DEFINED CUDAQ_ENABLE_BRAKET_BACKEND) set(CUDAQ_ENABLE_BRAKET_BACKEND ON CACHE BOOL "Enable building AWS SDK for Amazon Braket backends.") endif() # Enable Pasqal target by default. if (NOT DEFINED CUDAQ_ENABLE_PASQAL_BACKEND) set(CUDAQ_ENABLE_PASQAL_BACKEND ON CACHE BOOL "Enable building the Pasqal target.") endif() # Enable Quantum Circuits, Inc. (QCI) target by default. if (NOT DEFINED CUDAQ_ENABLE_QCI_BACKEND) set(CUDAQ_ENABLE_QCI_BACKEND ON CACHE BOOL "Enable building the Quantum Circuits, Inc. target.") endif() # Enable Quantum Machines target by default. if (NOT DEFINED CUDAQ_ENABLE_QUANTUM_MACHINES_BACKEND) set(CUDAQ_ENABLE_QUANTUM_MACHINES_BACKEND ON CACHE BOOL "Enable building the Quantum Machines target.") endif() # Generate a CompilationDatabase (compile_commands.json file) for our build, # for use by clang_complete, YouCompleteMe, etc. set(CMAKE_EXPORT_COMPILE_COMMANDS 1) if(NOT LLVM_VERSION_MAJOR) set(LLVM_VERSION_MAJOR 16) endif() find_package(Git QUIET) if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") # Update submodules as needed option(GIT_SUBMODULE "Check submodules during build" ON) if(GIT_SUBMODULE) message(STATUS "Submodule update") execute_process(COMMAND ${GIT_EXECUTABLE} -c submodule.tpls/llvm.update=none submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULT_VARIABLE GIT_SUBMOD_RESULT) if(NOT GIT_SUBMOD_RESULT EQUAL "0") message(FATAL_ERROR "Cloning git submodules failed with ${GIT_SUBMOD_RESULT}, please checkout submodules manually") endif() endif() endif() if(NOT EXISTS "${PROJECT_SOURCE_DIR}/tpls/fmt/CMakeLists.txt") message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.") endif() # Options # ============================================================================== option(CUDAQ_BUILD_TESTS "Build cudaq tests" ON) option(CUDAQ_ENABLE_RPC_LOGGING "Enable verbose printout for client/server qpud connection." OFF) option(CUDAQ_TEST_MOCK_SERVERS "Enable Remote QPU Tests via Mock Servers." OFF) option(CUDAQ_DISABLE_RUNTIME "Build without the CUDA-Q runtime, just the compiler toolchain." OFF) option(CUDAQ_SKIP_MPI "Do not build with MPI, even when it is available." OFF) option(CUDAQ_DISABLE_CPP_FRONTEND "Build without the CUDA-Q C++ Clang-based Frontend." OFF) option(CUDAQ_ENABLE_CC "Enable CUDA-Q code coverage generation." OFF) option(CUDAQ_REQUIRE_OPENMP "Fail the build if OpenMP is not found." OFF) # Certain build configurations may be set directly in the environment. # This facilitates some of the packaging (e.g. python packages built based on the pyproject.toml). if(NOT LLVM_DIR AND EXISTS "$ENV{LLVM_INSTALL_PREFIX}/lib/cmake/llvm") SET(LLVM_DIR "$ENV{LLVM_INSTALL_PREFIX}/lib/cmake/llvm") endif() if(NOT BLAS_LIBRARIES AND EXISTS "$ENV{BLAS_INSTALL_PREFIX}/libblas.a") # CACHE INTERNAL is needed due to how FindBLAS.cmake works... SET(BLAS_LIBRARIES "$ENV{BLAS_INSTALL_PREFIX}/libblas.a" CACHE INTERNAL "") endif() if(NOT CUSTATEVEC_ROOT) SET(CUSTATEVEC_ROOT "$ENV{CUQUANTUM_INSTALL_PREFIX}") endif() if(NOT CUTENSORNET_ROOT) SET(CUTENSORNET_ROOT "$ENV{CUQUANTUM_INSTALL_PREFIX}") endif() if(NOT CUDENSITYMAT_ROOT) SET(CUDENSITYMAT_ROOT "$ENV{CUQUANTUM_INSTALL_PREFIX}") endif() if(NOT CUTENSOR_ROOT) SET(CUTENSOR_ROOT "$ENV{CUTENSOR_INSTALL_PREFIX}") endif() if(NOT ZLIB_ROOT) SET(ZLIB_ROOT "$ENV{ZLIB_INSTALL_PREFIX}") endif() if(NOT OPENSSL_ROOT_DIR) SET(OPENSSL_ROOT_DIR "$ENV{OPENSSL_INSTALL_PREFIX}") endif() if (NOT crypto_LIBRARY AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND EXISTS "$ENV{OPENSSL_INSTALL_PREFIX}/lib64/libcrypto.a") SET(crypto_LIBRARY "$ENV{OPENSSL_INSTALL_PREFIX}/lib64/libcrypto.a" CACHE INTERNAL "") elseif(NOT crypto_LIBRARY AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND EXISTS "$ENV{OPENSSL_INSTALL_PREFIX}/lib/libcrypto.a") SET(crypto_LIBRARY "$ENV{OPENSSL_INSTALL_PREFIX}/lib/libcrypto.a" CACHE INTERNAL "") endif() if (NOT crypto_INCLUDE_DIR AND EXISTS "$ENV{OPENSSL_INSTALL_PREFIX}/include") SET(crypto_INCLUDE_DIR "$ENV{OPENSSL_INSTALL_PREFIX}/include" CACHE INTERNAL "") endif() if(NOT CURL_LIBRARY AND EXISTS "$ENV{CURL_INSTALL_PREFIX}/lib/libcurl.a") SET(CURL_LIBRARY "$ENV{CURL_INSTALL_PREFIX}/lib/libcurl.a") SET(CURL_INCLUDE_DIR "$ENV{CURL_INSTALL_PREFIX}/include") SET(CURL_CONFIG_EXECUTABLE "$ENV{CURL_INSTALL_PREFIX}/bin/curl-config") SET(CMAKE_USE_SYSTEM_CURL TRUE) SET(CURL_NO_CURL_CMAKE ON) endif() if(NOT AWSSDK_ROOT AND CUDAQ_ENABLE_BRAKET_BACKEND) SET(AWSSDK_ROOT "$ENV{AWS_INSTALL_PREFIX}") endif() if(NOT CUDAQ_EXTERNAL_NVQIR_SIMS) SET(CUDAQ_EXTERNAL_NVQIR_SIMS $ENV{CUDAQ_EXTERNAL_NVQIR_SIMS}) endif() if(NOT CUDAQ_ENABLE_CC) SET(CUDAQ_ENABLE_CC $ENV{CUDAQ_ENABLE_CC}) endif() SET(CMAKE_SKIP_BUILD_RPATH FALSE) SET(CMAKE_SKIP_INSTALL_RPATH FALSE) SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) SET(CMAKE_INSTALL_RPATH "$ORIGIN:$ORIGIN/lib:$ORIGIN/lib/plugins:$ORIGIN/../lib:$ORIGIN/../lib/plugins") SET(BLA_STATIC ON) if(NOT DEFINED ZLIB_USE_STATIC_LIBS) SET(ZLIB_USE_STATIC_LIBS TRUE) endif() if(NOT DEFINED OPENSSL_USE_STATIC_LIBS) SET(OPENSSL_USE_STATIC_LIBS TRUE) endif() if(NOT DEFINED CUDAQ_ENABLE_STATIC_LINKING) SET(CUDAQ_ENABLE_STATIC_LINKING $ENV{CUDAQ_ENABLE_STATIC_LINKING}) endif() if (CUDAQ_ENABLE_STATIC_LINKING) # Using -static-libgcc -static-libstdc++ offers more fine grained control here # then using -static (for exe) and -staic-pie (for linker). # At the time of writing, there wasn't any benefit to using those over -static. # When we only link libstdc++ and libgcc statically, we still have a dependency # on GLIBC on the target system, but linking it statically is likely to cause issues. # A better option might be to include the required GNU C Library and have the nvq++ # compiler dynamically pick the newer one of the included or system one. # See also these posts: # - https://blog.gibson.sh/2017/11/26/creating-portable-linux-binaries/ # - https://www.jertype.com/upgrading-glibc/ # If the final application loads multiple dynamic libraries, and two or more # of those dynamic libraries are linked to different versions of the same static # libraries, then the different copies of those static libraries will conflict with # each other. If we were to link everything statically, it is probably advisable to # set CMAKE__VISIBILITY_PRESET to hidden and CMAKE_VISIBILITY_INLINES_HIDDEN # to 1, to avoid some of these issues. # We don't set these configurations here, since the LLVM runtime libraries that we # build from source are already configured to hide symbols and include dependencies. SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++ -static-libgcc") SET(OPENSSL_USE_STATIC_LIBS TRUE) SET(ZLIB_USE_STATIC_LIBS TRUE) set(CURL_STATICLIB ON) message(STATUS "CUDA Quantum static linking enabled.") else() message(STATUS "CUDA Quantum static linking disabled.") endif() # ZLIB is required when we build LLVM with zlib support. # ZLIB support in LLVM is good to have e.g. for the linker, # since some binaries will use zlib compression to store symbols. find_package(ZLIB REQUIRED) include(ExternalProject) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE) endif() # Find and configure LLVM, Clang and MLIR # ============================================================================== # The user can specify the path to LLVM cmake directory using # `-DLLVM_DIR=path/to/cmake/llvm`. If this definition is not provided, we look # for `llvm-config` tool. The user can also provide a LLVM version to look for # using `LLVM_VERSION_MAJOR`, e.g. "-LLVM_VERSION_MAJOR=16". Note that this # version variable is set to the latest LLVM version by default, and setting it # to an older version might break the project. find_package(LLVM ${LLVM_VERSION_MAJOR} CONFIG QUIET) if(NOT LLVM_DIR) message(STATUS "LLVM_DIR not found, will try with llvm-config executable.") macro(find_llvm_config name version_major) set(extra_args ${ARGN}) list(LENGTH extra_args extra_count) if (${extra_count} GREATER 0) list(GET extra_args 0 path) find_program(LLVM_CONFIG NAMES ${name} PATHS ${path} NO_DEFAULT_PATH DOC "Path to llvm-config tool") else() find_program(LLVM_CONFIG NAMES ${name} DOC "Path to llvm-config tool") endif() if(LLVM_CONFIG) execute_process( COMMAND ${LLVM_CONFIG} --version RESULT_VARIABLE LLVM_CONFIG_RESULT OUTPUT_VARIABLE LLVM_CONFIG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) if(NOT LLVM_CONFIG_VERSION MATCHES "^${version_major}[.][0-9]+[.][0-9]+") unset(LLVM_CONFIG CACHE) endif() endif() endmacro() # First we try to find llvm-config in the llvm submodule. find_llvm_config(llvm-config ${LLVM_VERSION_MAJOR} "${CMAKE_CURRENT_SOURCE_DIR}/tpls/llvm/build/bin") # Try to find a system llvm-config and make sure it is the correct version. if(NOT LLVM_CONFIG) find_llvm_config(llvm-config ${LLVM_VERSION_MAJOR}) endif() # If it is not the correct version, try finding llvm-config-VERSION if(NOT LLVM_CONFIG) find_llvm_config(llvm-config-${LLVM_VERSION_MAJOR} ${LLVM_VERSION_MAJOR}) if (LLVM_CONFIG) set(NVQPP_LLVM_EXECUTABLE_SUFFIX -${LLVM_VERSION_MAJOR}) endif() endif() execute_process( COMMAND ${LLVM_CONFIG} --cmakedir RESULT_VARIABLE LLVM_CONFIG_RESULT OUTPUT_VARIABLE LLVM_CONFIG_CMAKE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) if(LLVM_CONFIG_RESULT) message(FATAL_ERROR "Could not find suitable llvm-config(-${LLVM_VERSION_MAJOR}).\ \nTry providing valid -DLLVM_DIR=/path/to/llvm/lib/cmake/llvm.") else() find_package(LLVM ${LLVM_VERSION_MAJOR} REQUIRED CONFIG HINTS ${LLVM_CONFIG_CMAKE_DIR} NO_DEFAULT_PATH) endif() endif() if(NOT MLIR_DIR) set(MLIR_DIR ${LLVM_BINARY_DIR}/lib/cmake/mlir) endif() find_package(MLIR REQUIRED CONFIG) if(NOT Clang_DIR) set(Clang_DIR ${LLVM_BINARY_DIR}/lib/cmake/clang) endif() find_package(Clang CONFIG) if (NOT Clang_FOUND) message(STATUS "Clang not found, turning off C++ Frontend.") set (CUDAQ_DISABLE_CPP_FRONTEND ON) endif() message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") message(STATUS "Using ClangConfig.cmake in: ${Clang_DIR}") message(STATUS "Using MLIRConfig.cmake in: ${MLIR_DIR}") set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/bin) set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/lib) set(MLIR_BINARY_DIR ${CMAKE_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}") list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules") include(TableGen) include(AddLLVM) include(AddMLIR) # Add LLVM, Clang and MLIR headers to the include path include_directories(SYSTEM ${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS} ${MLIR_INCLUDE_DIRS}) link_directories(${LLVM_BUILD_LIBRARY_DIR}) add_definitions(${LLVM_DEFINITIONS}) # Define the default arguments to use with 'lit', and an option for the user to # override. set(LIT_ARGS_DEFAULT "-sv") if(MSVC_IDE OR XCODE) set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") endif() set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") # CUDA Quantum configuration # ============================================================================== message(STATUS "Build type is ${CMAKE_BUILD_TYPE}") set(CUDAQ_MAIN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # --src-root set(CUDAQ_MAIN_INCLUDE_DIR ${CUDAQ_MAIN_SRC_DIR}/include) set(CUDAQ_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(CUDAQ_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(CUDAQ_CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(CUDAQ_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) set(CUDAQ_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib) set(CUDAQ_TOOLS_DIR ${CMAKE_BINARY_DIR}/bin) list(APPEND CMAKE_MODULE_PATH "${CUDAQ_CMAKE_DIR}") include(AddCUDAQ) include(BuildHelpers) # Add CUDA Quantum files to the include path include_directories(BEFORE ${CUDAQ_SOURCE_DIR}/include ${CUDAQ_BINARY_DIR}/include) # Installing the headers and docs needs to depend on generating any public # tablegen'd targets. add_custom_target(cudaq-headers) set_target_properties(cudaq-headers PROPERTIES FOLDER "Misc") add_custom_target(cudaq-doc) # Version # ============================================================================== if (DEFINED ENV{CUDA_QUANTUM_VERSION}) # The version was defined by the user (likely a bot performing the build), so # use the value provided as is. set(CUDA_QUANTUM_VERSION "$ENV{CUDA_QUANTUM_VERSION}") else() # Otherwise, create a version based on the nearest tag in the git repo. execute_process(COMMAND git describe --tags --abbrev=0 --dirty=-developer WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE CUDA_QUANTUM_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) endif() # Retrieve the commit SHA for full revision description execute_process(COMMAND git rev-parse --verify HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE CUDA_QUANTUM_COMMIT_SHA OUTPUT_STRIP_TRAILING_WHITESPACE) configure_file("${CMAKE_SOURCE_DIR}/include/cudaq/Support/Version.h.in" "${CUDAQ_BINARY_DIR}/include/cudaq/Support/Version.h" @ONLY) # Check optional dependencies # ============================================================================== find_package(OpenSSL) if (NOT CUDAQ_SKIP_MPI) find_package(MPI COMPONENTS CXX) if (MPI_FOUND) message(STATUS "MPI CXX Found: ${MPIEXEC}") # Build the built-in MPI Comm plugin add_subdirectory(runtime/cudaq/distributed/builtin) endif() endif() # Third-party libraries (tpls) # ============================================================================== set(FMT_INSTALL ON) cmake_policy(PUSH) # CMP0146: The FindCUDA module is removed. # CMake 3.27 and above no longer provide the modules. # https://cmake.org/cmake/help/latest/policy/CMP0146.html if(POLICY CMP0146) cmake_policy(SET CMP0146 OLD) endif() add_subdirectory(tpls/fmt) cmake_policy(POP) include_directories(SYSTEM tpls/json/include) # Add spdlog set(SPDLOG_BUILD_SHARED OFF) set(SPDLOG_FMT_EXTERNAL ON) set(SPDLOG_BUILD_PIC ON) set(SPDLOG_SYSTEM_INCLUDES ON) add_subdirectory(tpls/spdlog) target_compile_options(spdlog PRIVATE -Wno-covered-switch-default) if (OPENSSL_FOUND AND CUDAQ_ENABLE_REST) # Look for CURL set(CURL_STATICLIB ON) set(CURL_USE_STATIC_LIBS TRUE) find_package(CURL COMPONENTS HTTP HTTPS) if (CURL_FOUND) message(STATUS "Using system curl for CPR.") set(CPR_FORCE_USE_SYSTEM_CURL TRUE) elseif (CMAKE_USE_SYSTEM_CURL) message(FATAL_ERROR "CMAKE_USE_SYSTEM_CURL defined but a suitable package was not found. Make sure that `curl-config --protocols` lists HTTP and HTTPS.") else() message(STATUS "Curl not found. Building curl for CPR.") set(CPR_FORCE_USE_SYSTEM_CURL FALSE) endif() # Now, build CPR as needed set(BUILD_SHARED_LIBS OFF) set(CPR_ENABLE_SSL ON) # needed for https requests set(CPR_FORCE_OPENSSL_BACKEND ON) add_subdirectory(tpls/cpr) target_compile_options(cpr PRIVATE -Wno-covered-switch-default -w) endif() # QPP simulator if (NOT CUDAQ_DISABLE_RUNTIME) add_subdirectory(tpls/qpp EXCLUDE_FROM_ALL) # Required workaround to add libqpp as SYSTEM. This will prevent it from # generating warnings, which we treat as errors. get_target_property(LIBQPP_INCLUDE libqpp INTERFACE_INCLUDE_DIRECTORIES) set_target_properties(libqpp PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${LIBQPP_INCLUDE}") add_openmp_interface_definitions(libqpp) endif() if (OPENSSL_FOUND AND CUDAQ_ENABLE_REST) # The asio submodule doesn't use cmake, so use find_path for it. find_path(ASIO_INCLUDE_DIR asio.hpp PATHS tpls/asio/asio/include) add_subdirectory(tpls/Crow) endif() # Check for CUDA Support # ============================================================================== include(CheckLanguage) check_language(CUDA) set(CUDA_FOUND FALSE) # Generate -gencode arch=compute_XX,code=sm_XX for list of supported # arch values. # List should be sorted in increasing order. function(CUDA_get_gencode_args out_args_string arch_values) # allow the user to pass the list like a normal variable set(arch_list ${arch_values} ${ARGN}) set(out "") foreach(arch IN LISTS arch_list) set(out "${out} -gencode arch=compute_${arch},code=sm_${arch}") endforeach(arch) # Repeat the last one as to ensure the generation of PTX for most # recent virtual architecture for forward compatibility list(GET arch_list -1 last_arch) set(out "${out} -gencode arch=compute_${last_arch},code=compute_${last_arch}") set(${out_args_string} ${out} PARENT_SCOPE) endfunction() if(CMAKE_CUDA_COMPILER) if (NOT CUDA_TARGET_ARCHS) find_package(CUDAToolkit REQUIRED) message(STATUS "Found CUDA Toolkit version: ${CUDAToolkit_VERSION}") if (CUDAToolkit_VERSION VERSION_LESS 13.0) # Turing, Ampere, Hopper set(CUDA_TARGET_ARCHS "75;80;90") else() # Turing, Ampere, Hopper, Blackwell set(CUDA_TARGET_ARCHS "75;80;90;100") endif() endif() CUDA_get_gencode_args(CUDA_gencode_flags ${CUDA_TARGET_ARCHS}) set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -shared -std=c++17 ${CUDA_gencode_flags} --compiler-options -fPIC") enable_language(CUDA) set(CUDA_FOUND TRUE) set(CMAKE_CUDA_STANDARD 17) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) message(STATUS "Cuda language found.") endif() # Code coverage setup # ============================================================================== if(CUDAQ_ENABLE_CC) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") endif() endif(CUDAQ_ENABLE_CC) # Directory setup # ============================================================================== add_subdirectory(cmake) add_subdirectory(include) add_subdirectory(lib) if (NOT CUDAQ_DISABLE_RUNTIME) add_subdirectory(runtime) endif() add_subdirectory(tools) add_subdirectory(utils) if(CUDAQ_BUILD_TESTS) enable_testing() endif() if (CUDAQ_ENABLE_PYTHON) find_package(Python 3 COMPONENTS Interpreter Development) # Apply specific patch to pybind11 for our documentation. # Only apply the patch if not already applied. execute_process(COMMAND ${GIT_EXECUTABLE} -C tpls/pybind11/ apply ../customizations/pybind11/pybind.h.diff --ignore-whitespace --reverse --check WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULT_VARIABLE GIT_PATCH_RESULT ERROR_QUIET) if (NOT GIT_PATCH_RESULT EQUAL "0") execute_process(COMMAND ${GIT_EXECUTABLE} -C tpls/pybind11/ apply ../customizations/pybind11/pybind.h.diff --ignore-whitespace WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULT_VARIABLE GIT_PATCH_RESULT) endif() if (NOT GIT_PATCH_RESULT EQUAL "0") message(FATAL_ERROR "Applying patch to submodule failed with ${GIT_PATCH_RESULT}, please update patch") endif() # Regarding the use of PyBind, we need to be careful that the same STL is used for any # Python bindings generated as part of the CUDA-Q build and bindings generated for # third party CUDA-Q libraries; see also https://github.com/pybind/pybind11/issues/1262 add_subdirectory(tpls/pybind11) add_subdirectory(python) endif() if(CUDAQ_BUILD_TESTS AND NOT CUDAQ_DISABLE_CPP_FRONTEND) umbrella_lit_testsuite_begin(check-all) set(INSTALL_GTEST OFF) add_subdirectory(tpls/googletest-src) # Bug in GCC 12 leads to spurious warnings (-Wrestrict) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105329 if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0.0) target_compile_options(gtest PUBLIC --param=evrp-mode=legacy) endif() if (CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") target_compile_options(gtest PUBLIC -Wno-covered-switch-default) endif() include(GoogleTest) include(CTest) add_subdirectory(test) if (NOT CUDAQ_DISABLE_RUNTIME) add_subdirectory(targettests) add_subdirectory(unittests) add_subdirectory(docs) endif() umbrella_lit_testsuite_end(check-all) endif() if (CUDAQ_EXTERNAL_NVQIR_SIMS) while(CUDAQ_EXTERNAL_NVQIR_SIMS) list(POP_FRONT CUDAQ_EXTERNAL_NVQIR_SIMS LIB_SO_OR_CONFIG_FILE) add_target_libs_to_wheel(${LIB_SO_OR_CONFIG_FILE}) endwhile() endif()