Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
CMakeLists.txt 7.93 KiB
# CMake >= 3.18 is required for good support of FindCUDAToolkit
cmake_minimum_required(VERSION 3.18)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS  OFF)

file(STRINGS "${CMAKE_SOURCE_DIR}/version.txt" version)

# Parse version.txt to retrieve Major, Minor and Path
string(REGEX MATCH "([0-9]+\\.[0-9]+\\.[0-9]+)" _ MATCHES ${version})
set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1})
set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2})
set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3})

project(aidge_backend_cuda
        VERSION ${version}
        DESCRIPTION "CUDA implementations of the operators of aidge framework."
        LANGUAGES CXX)

message(STATUS "Project name: ${CMAKE_PROJECT_NAME}")
message(STATUS "Project version: ${version}")

execute_process(
    COMMAND git rev-parse --short HEAD
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    OUTPUT_VARIABLE GIT_COMMIT_HASH
    OUTPUT_STRIP_TRAILING_WHITESPACE
    ERROR_QUIET
)
message(STATUS "Latest git commit: ${GIT_COMMIT_HASH}")
# Define a preprocessor macro with the Git commit version

# Note : project name is ${CMAKE_PROJECT_NAME} and python module name is also ${CMAKE_PROJECT_NAME}
set(module_name _${CMAKE_PROJECT_NAME}) # target name

##############################################
# Define options
option(PYBIND "python binding (Default: OFF)" OFF)
option(WERROR "Warning as error (Default: OFF)" OFF)
option(TEST "Enable tests (Default: ON)" ON)
option(COVERAGE "Enable coverage (Default: OFF)" OFF)
option(ENABLE_ASAN "Enable ASan (AddressSanitizer) for runtime analysis of memory use (over/underflow, memory leak, ...) (Default: OFF)" OFF)

##############################################
# Import utils CMakeLists
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")

if(CMAKE_COMPILER_IS_GNUCXX AND COVERAGE)
    Include(CodeCoverage)
endif()

##############################################
# Find system dependencies
##############################################
# FIND AIDGE Dependencies
if(NOT $ENV{AIDGE_INSTALL} STREQUAL "")
    set(CMAKE_INSTALL_PREFIX $ENV{AIDGE_INSTALL})
    list(APPEND CMAKE_PREFIX_PATH $ENV{AIDGE_INSTALL})
    message(WARNING "Env var AIDGE_INSTALL detected : $ENV{AIDGE_INSTALL}. Set CMAKE_INSTALL_PREFIX to AIDGE_INSTALL & added to CMAKE_PREFIX_PATH"
                    "\n\tCMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}"
                    "\n\tCMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
endif()
find_package(aidge_core REQUIRED)
if(TEST)
    find_package(aidge_backend_cpu REQUIRED)
endif()

##########
# CUDA
if(NOT $ENV{CIBUILDWHEEL} STREQUAL "")
    message(WARNING "Env var CIBUILDWHEEL detected : currently building for a release job."
                    "\nSetting manually CUDACXX, PATH & LD_LIBRARY_PATH Variables")
    list(APPEND ENV{LD_LIBRARY_PATH} /usr/local/cuda/lib64)
    list(APPEND ENV{PATH} /usr/local/cuda/bin)
    set(ENV{CUDACXX} /usr/local/cuda/bin/nvcc)
endif()
find_package(CUDAToolkit 12 REQUIRED)
if(NOT DEFINED CMAKE_CUDA_STANDARD)
    set(CMAKE_CUDA_STANDARD 14)
    set(CMAKE_CUDA_STANDARD_REQUIRED ON)
endif()
if(NOT DEFINED CMAKE_CUDA_ARCHITECURE)
    set(CMAKE_CUDA_ARCHITECTURE native)
endif()

message(STATUS "Cuda compiler version = ${CMAKE_CUDA_COMPILER_VERSION}")
# Define a preprocessor macro with the Cuda compiler version
add_definitions(-DCUDA_COMPILER_VERSION="${CMAKE_CUDA_COMPILER_VERSION}")

message(STATUS "CUDA STANDARD : ${CMAKE_CUDA_STANDARD}")
message(STATUS "CUDA ARCHITECTURE : ${CMAKE_CUDA_ARCHITECTURES}")

enable_language(CUDA)

##############################################
# Create target and set properties
file(GLOB_RECURSE src_files "src/*.cpp" "src/*.cu")
file(GLOB_RECURSE inc_files "include/*.hpp")

add_library(${module_name} ${src_files} ${inc_files})

# PYTHON BINDING
if (PYBIND)
    # Handles Python + pybind11 headers dependencies
    include(PybindModuleCreation)
    # creates a target of the same name as CMAKE_PROJECT_NAME
    generate_python_binding(${CMAKE_PROJECT_NAME} ${module_name}) # the python bindings module has the same name as the project.

    target_link_libraries(${module_name}
        PUBLIC
            pybind11::pybind11
        PRIVATE
            Python::Module
        )
endif()

message(STATUS "Creating ${CMAKE_CURRENT_SOURCE_DIR}/include/aidge/backend/cuda_version.h")
# Generate version.h file from config file version.h.in
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/include/aidge/backend/version.h.in"
    "${CMAKE_CURRENT_SOURCE_DIR}/include/aidge/backend/cuda_version.h"
)


target_link_libraries(${module_name}
    PUBLIC
        _aidge_core # _ is added because we link the target not the project
    PRIVATE
        CUDA::cublas
        cudnn
        CUDA::cudart
        curand
)

if( ${ENABLE_ASAN} )
    message("Building ${module_name} with ASAN.")
    set(SANITIZE_FLAGS -fsanitize=address -fno-omit-frame-pointer)
    target_link_libraries(${module_name}
        PUBLIC
            -fsanitize=address
    )
    target_compile_options(${module_name}
        PRIVATE
            ${SANITIZE_FLAGS}
    )
endif()

if(TEST)
    target_link_libraries(${module_name}
    PUBLIC
        _aidge_backend_cpu # _ is added because we link the target not the project
    )
endif()

#Set target properties
target_include_directories(${module_name}
    PUBLIC
        $<INSTALL_INTERFACE:include>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src
)

set_property(TARGET ${module_name} PROPERTY POSITION_INDEPENDENT_CODE ON)
set_target_properties(${module_name} PROPERTIES CUDA_SEPARABLE_COMPILATION ON)

target_compile_features(${module_name} PRIVATE cxx_std_14)

target_compile_options(${module_name} PRIVATE
    $<$<COMPILE_LANGUAGE:CPP>:$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
    -Wall -Wextra -Wold-style-cast -Winline -pedantic -Werror=narrowing -Wshadow $<$<BOOL:${WERROR}>:-Werror>>>)
target_compile_options(${module_name} PRIVATE
    $<$<COMPILE_LANGUAGE:CUDA>:
    -Wall>)
target_compile_options(${module_name} PRIVATE
    $<$<CXX_COMPILER_ID:MSVC>:
    /W4>)

if(CMAKE_COMPILER_IS_GNUCXX AND COVERAGE)
    append_coverage_compiler_flags()
endif()

##############################################
# Installation instructions
include(GNUInstallDirs)
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME})

install(TARGETS ${module_name} EXPORT ${CMAKE_PROJECT_NAME}-targets
  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

#Export the targets to a script

install(EXPORT ${CMAKE_PROJECT_NAME}-targets
 FILE "${CMAKE_PROJECT_NAME}-targets.cmake"
 DESTINATION ${INSTALL_CONFIGDIR}
#  COMPONENT ${module_name}
)

#Create a ConfigVersion.cmake file
include(CMakePackageConfigHelpers)

write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}-config-version.cmake"
    VERSION ${version}
    COMPATIBILITY AnyNewerVersion
)

configure_package_config_file("${CMAKE_PROJECT_NAME}-config.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}-config.cmake"
    INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
)

#Install the config, configversion and custom find modules
install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}-config.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}-config-version.cmake"
    DESTINATION ${INSTALL_CONFIGDIR}
)

##############################################
## Exporting from the build tree
export(EXPORT ${CMAKE_PROJECT_NAME}-targets
    FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}-targets.cmake")

##############################################
## Add test
if(TEST)
    if(PYBIND)
        message(FATAL_ERROR "PYBIND and TEST are both enabled. But cannot compile with catch_2.\nChoose between pybind and Catch2 for compilation.")
    endif()
    enable_testing()
    add_subdirectory(unit_tests)
endif()