cmake_minimum_required(VERSION 3.17)
project(openjij)

include(CheckLanguage)

check_language(C)
check_language(CXX)
check_language(CUDA)

if(CMAKE_C_COMPILER)
  enable_language(C)
endif() 
if(CMAKE_CXX_COMPILER)
  enable_language(CXX)
endif() 

set(CMAKE_VERBOSE_MAKEFILE TRUE)

if (APPLE)
    set(CMAKE_MACOSX_RPATH TRUE)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -Wno-unused-command-line-argument")
endif()

set(CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
set(CMAKE_CXX_STANDARD 17)

 

##### Set default behavior #####
set(DEFAULT_USE_OMP Yes)
set(DEFAULT_USE_CUDA Yes)
set(DEFAULT_USE_TEST No)
option(USE_TEST "Use test code" No)


# Use OpenMP as default behavior
if(NOT APPLE) 
  if(NOT DEFINED USE_OMP) 
    set(USE_OMP ${DEFAULT_USE_OMP})
  endif() 
else() 
  if(FORCE_USE_OMP) 
    set(USE_OMP ${DEFAULT_USE_OMP})
  endif()
endif()

if(NOT DEFINED USE_CUDA)
    if(CMAKE_CUDA_COMPILER)
      enable_language(CUDA)
      find_package(CUDAToolkit)
      if(CUDAToolkit_FOUND)
        message(STATUS "CUDA Found")
        set(USE_CUDA Yes)
      endif()
    else()
        message(STATUS "No CUDA support")
        set(USE_CUDA No)
    endif()
elseif(USE_CUDA)
  if(CMAKE_CUDA_COMPILER)
    enable_language(CUDA)
    find_package(CUDAToolkit REQUIRED)
    if(CUDAToolkit_FOUND)
      message(STATUS "CUDA Found")
      set(USE_CUDA Yes)
    endif()
  endif()
endif()

if(USE_CUDA)
    set(CMAKE_CUDA_STANDARD 11)
    set(CMAKE_CUDA_STANDARD_REQUIRED ON)
    if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
      set(CMAKE_CUDA_ARCHITECTURES 52 53 60 61 62 70 72 75 80 86)
    endif()
    message(STATUS "CUDA architectures set to ${CMAKE_CUDA_ARCHITECTURES}")
    add_definitions(-DUSE_CUDA)
endif()


if(NOT DEFINED USE_TEST)
    set(USE_TEST ${DEFAULT_USE_TEST})
endif()

if(USE_OMP)
    set(CMAKE_INSTALL_OPENMP_LIBRARIES ON)
    if(APPLE) 
      if(NOT CMAKE_OSX_ARCHITECTURES)
        message(STATUS "Apple Native Build")
	set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp")
	set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp")
        find_package(OpenMP REQUIRED)
	if(OpenMP_FOUND)
           message(STATUS "OMP_FOUND = YES")
	   add_definitions(-DEIGEN_DONT_PARALLELIZE)
           add_definitions(-DUSE_OMP)
	endif()
      elseif(${CMAKE_OSX_ARCHITECTURES} STREQUAL "arm64")
        message(STATUS "APPLE SILICON")
	set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp")
	set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp")
        find_package(OpenMP REQUIRED)
	if(OpenMP_FOUND)
           message(STATUS "OMP_FOUND = YES")
	   add_definitions(-DEIGEN_DONT_PARALLELIZE)
           add_definitions(-DUSE_OMP)
        else() 
          message(STATUS "OMP_FOUND = NO") 
	endif()
      else()
        message(STATUS "APPLE X86-64")
        find_package(OpenMP REQUIRED)
	if(OpenMP_FOUND)
           message(STATUS "OMP_FOUND = YES")
	   add_definitions(-DEIGEN_DONT_PARALLELIZE)
           add_definitions(-DUSE_OMP)
	endif()
      endif()
    else()
      find_package(OpenMP REQUIRED)
      if(OpenMP_FOUND)
        message(STATUS "OMP_FOUND = YES")
	add_definitions(-DEIGEN_DONT_PARALLELIZE)
        add_definitions(-DUSE_OMP)
      endif()
    endif()
else() 
  if(APPLE) 
      if(NOT CMAKE_OSX_ARCHITECTURES)
        message(STATUS "APPLE Native Build")
	set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp")
	set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp")
        find_package(OpenMP)
	if(OpenMP_FOUND)
           set(USE_OMP ${DEFAULT_USE_OMP})
           message(STATUS "OMP_FOUND = YES")
	   add_definitions(-DEIGEN_DONT_PARALLELIZE)
           add_definitions(-DUSE_OMP)
	else() 
          message(STATUS "OMP_FOUND = NO") 
	endif()
      elseif(${CMAKE_OSX_ARCHITECTURES} STREQUAL "arm64")
        message(STATUS "APPLE SILICON")
	set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp")
	set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp")
        find_package(OpenMP)
	if(OpenMP_FOUND)
           set(USE_OMP ${DEFAULT_USE_OMP})
           message(STATUS "OMP_FOUND = YES")
	   add_definitions(-DEIGEN_DONT_PARALLELIZE)
           add_definitions(-DUSE_OMP)
        else() 
          message(STATUS "OMP_FOUND = NO") 
	endif()
      else()
        message(STATUS "APPLE X86-64")
        find_package(OpenMP)
	if(OpenMP_FOUND)
           set(USE_OMP ${DEFAULT_USE_OMP})
           message(STATUS "OMP_FOUND = YES")
	   add_definitions(-DEIGEN_DONT_PARALLELIZE)
           add_definitions(-DUSE_OMP)
	else() 
          message(STATUS "OMP_FOUND = NO") 
	endif()
      endif()
  endif()
endif()

message(STATUS "USE_OMP = ${USE_OMP}")
message(STATUS "USE_CUDA = ${USE_CUDA}")
message(STATUS "USE_TEST = ${USE_TEST}")

if (APPLE)
    find_package(BLAS)
    find_package(LAPACK)
endif()

if(USE_TEST)
       include(external/googletest.cmake)          
else()
	message(STATUS "Skip downloding googletest")
endif()


find_package(Eigen3 3.3 NO_MODULE)

if(NOT TARGET Eigen3::Eigen)
  include(external/eigen.cmake)
endif() 

include(external/pybind11.cmake)
include(external/json.cmake)
include(external/pybind11-json.cmake)
find_package(Python COMPONENTS Development.Module)

#find_package(pybind11 REQUIRED CONFIG)

add_subdirectory(src)
add_subdirectory(openjij)
if(USE_TEST)
    add_subdirectory(tests)
endif()
