cmake_minimum_required(VERSION 3.16)
project(virtual_casing)
#set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

OPTION (USE_PROFILER "Activate code profiling." OFF)
if (USE_PROFILER)
    add_definitions (-DSCTL_PROFILE=5 -DSCTL_VERBOSE)
endif ()
set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON")

if(DEFINED ENV{CONDA_PREFIX})
    include_directories($ENV{CONDA_PREFIX}/include)
    link_directories("$ENV{CONDA_PREFIX}/lib")
    message(STATUS "Conda prefix is $ENV{CONDA_PREFIX}")
endif()

# Add linker and incldue directories for conda build before finding any library
if (DEFINED ENV{CONDA_BUILD})
  link_directories("$ENV{BUILD_PREFIX}/lib")
  include_directories("$ENV{BUILD_PREFIX}/include")
  message(STATUS "Prefix environment variable is $ENV{BUILD_PREFIX}")
endif ()


find_package (BLAS)
if (BLAS_FOUND)
    add_definitions (-DSCTL_HAVE_BLAS)
    if (NOT ${BLA_VENDOR} MATCHES "^Intel")
        find_package (LAPACK)
        if(LAPACK_FOUND)
            add_definitions (-DSCTL_HAVE_LAPACK)
        endif()
    else()
        add_definitions (-DSCTL_HAVE_LAPACK)
    endif()
endif ()

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(FFTW COMPONENTS FLOAT_LIB DOUBLE_LIB LONGDOUBLE_LIB DOUBLE_OPENMP_LIB)
if(FFTW_DOUBLE_LIB_FOUND)
    message(STATUS "FFTW_INCLUDE_DIR is ${FFTW_INCLUDE_DIRS}")
    add_definitions (-DSCTL_HAVE_FFTW)
    include_directories("${FFTW_INCLUDE_DIRS}")
endif()
if (FFTW_FLOAT_LIB_FOUND)
    add_definitions (-DSCTL_HAVE_FFTWF)
endif()
if (FFTW_LONGDOUBLE_LIB_FOUND)
    add_definitions (-DSCTL_HAVE_FFTWL)
endif()
if (FFTW_FLOAT_OPENMP_FOUND)
    add_definitions (-DSCTL_FFTWF_THREADS)
endif()

set(Python_FIND_STRATEGY LOCATION)
# find_package(Python 3 COMPONENTS Interpreter Development.Module NumPy)
find_package(Python 3 COMPONENTS Interpreter Development.Module)

message(STATUS "Python executable is ${Python_EXECUTABLE}")
message(STATUS "Python Development Module found value is ${Python_Development.Module_FOUND}")
message(STATUS "Python header dirs are ${Python_INCLUDE_DIRS}")
message(STATUS "Python library dirs are ${Python_LIBRARY_DIRS}")
message(STATUS "Python version is ${Python_VERSION}")


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} 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 "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
        endif()
    endif()
endif()

include(CheckCXXCompilerFlag)
IF(DEFINED ENV{VC_ARCH_FLAG})
    message(STATUS "User provided architecture flag: $ENV{VC_ARCH_FLAG}")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 $ENV{VC_ARCH_FLAG} -ffp-contract=fast")
elseif(DEFINED ENV{CONDA_BUILD})
    message(STATUS "conda build environment detected. Let conda set compilation flags accordingly.")
else()
    # Temporary fix till clang 15 is default on macs with Apple silicon
    message(STATUS "Local build detected. Set compilation flags accordingly.")
    unset(COMPILER_SUPPORTS_MARCH_NATIVE CACHE)
    CHECK_CXX_COMPILER_FLAG(-march=native COMPILER_SUPPORTS_MARCH_NATIVE)
    if(COMPILER_SUPPORTS_MARCH_NATIVE)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -march=native -ffp-contract=fast")
    elseif(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "arm64")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -mcpu=native -ffp-contract=fast")
    endif()
endif()

find_package(OpenMP REQUIRED)

add_subdirectory(extern/pybind11)
#Python_add_library(${PROJECT_NAME} MODULE src/python.cpp)
#target_link_libraries(${PROJECT_NAME} PRIVATE pybind11::pybind11)
pybind11_add_module(${PROJECT_NAME} src/python.cpp)
add_executable(vc_testing EXCLUDE_FROM_ALL test/virtual-casing.cpp)
# Fix for PowerPC with PGI compiler
target_compile_options(vc_testing PUBLIC "$<$<CXX_COMPILER_ID:PGI>:-Wc,--pending_instantiations=1000>")
target_compile_options(${PROJECT_NAME} PUBLIC "$<$<CXX_COMPILER_ID:PGI>:-Wc,--pending_instantiations=1000>")

if(OpenMP_CXX_FOUND)
    target_link_libraries(vc_testing PRIVATE OpenMP::OpenMP_CXX)
    target_link_libraries(${PROJECT_NAME} PRIVATE OpenMP::OpenMP_CXX)
endif()

if(FFTW_DOUBLE_LIB_FOUND)
    message(STATUS "FFT DOUBLE FOUND")
    target_link_libraries(vc_testing PUBLIC FFTW::Double)
    target_link_libraries(${PROJECT_NAME} PUBLIC FFTW::Double)
    target_include_directories(vc_testing PRIVATE ${FFTW_INCLUDE_DIRS})
    target_include_directories(${PROJECT_NAME} PRIVATE ${FFTW_INCLUDE_DIRS})
endif()
if (FFTW_FLOAT_LIB_FOUND)
    target_link_libraries (vc_testing PUBLIC FFTW::Float)
    target_link_libraries (${PROJECT_NAME} PUBLIC FFTW::Float)
endif()
if (FFTW_LONGDOUBLE_LIB_FOUND)
    target_link_libraries (vc_testing PUBLIC FFTW::LongDouble)
    target_link_libraries (${PROJECT_NAME} PUBLIC FFTW::LongDouble)
endif()
if (FFTW_FLOAT_OPENMP_FOUND)
    target_link_libraries (vc_testing PUBLIC FFTW::DoubleOpenMP)
    target_link_libraries (${PROJECT_NAME} PUBLIC FFTW::DoubleOpenMP)
endif()
if (BLAS_FOUND)
	target_link_libraries (vc_testing PRIVATE ${BLAS_LIBRARIES})
	target_link_libraries (${PROJECT_NAME} PRIVATE ${BLAS_LIBRARIES})
endif ()
if (LAPACK_FOUND)
	target_link_libraries (vc_testing PRIVATE ${LAPACK_LIBRARIES})
	target_link_libraries (${PROJECT_NAME} PRIVATE ${LAPACK_LIBRARIES})
endif ()

target_include_directories(vc_testing PRIVATE  "include" "extern/SCTL/include")
target_include_directories(vc_testing PRIVATE  "include" "extern/BIEST/include")
target_include_directories(${PROJECT_NAME} PRIVATE  "include" "extern/SCTL/include")
target_include_directories(${PROJECT_NAME} PRIVATE  "include" "extern/BIEST/include")

get_target_property(INC_DIRS vc_testing INCLUDE_DIRECTORIES)
message(STATUS "vc_testing include directories are ${INC_DIRS}")
