#    Copyright (C) 2016 University of the Basque Country, UPV/EHU.
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required( VERSION 2.8 )
project( cuPoisson )

find_package( CUDA REQUIRED )

set( LIB_NAME "cuPoisson" )

option( USE_CUBLAS "Use cuBLAS library for BLAS operations." OFF )
option( MOD_SERIAL "Build Serial module." ON )
option( MOD_MPI "Build MPI module." OFF )
set( DEFS "" CACHE STRING "Particular definitions." )
option( VERBOSE "Write log file." OFF )
option( DEV_TESTS "Include developer tests in the testsuite." OFF )
set( DOXYGEN_PREDEFINED "" )

add_definitions( ${DEFS} )

# Hide advanced options.
mark_as_advanced( CUDA_BUILD_CUBIN )
mark_as_advanced( CUDA_BUILD_EMULATION )
mark_as_advanced( CUDA_SDK_ROOT_DIR )

if( VERBOSE )
	add_definitions( -DVERBOSE=1 )
else( VERBOSE )
	add_definitions( -DVERBOSE=0 )
endif( VERBOSE )

if( NOT ( MOD_SERIAL OR MOD_MPI ) )
	message( FATAL_ERROR "You must select at least one module." )
endif( NOT ( MOD_SERIAL OR MOD_MPI ) )

if( MOD_SERIAL )
	add_definitions( -DMOD_SERIAL )
	set( CUP_MOD_SERIAL 1 )
endif( MOD_SERIAL )
if( MOD_MPI )
	find_package( MPI REQUIRED )
	include_directories( ${MPI_C_INCLUDE_PATH} )
	add_definitions( -DMOD_MPI )
	set( CUP_MOD_MPI 1)
	set( DOXYGEN_PREDEFINED ${DOXYGEN_PREDEFINED} "MOD_MPI" )
endif( MOD_MPI )

if( USE_CUBLAS AND CUDA_cublas_LIBRARY )
	set( CUDA_NVCC_FLAGS -DUSE_CUBLAS )
endif( USE_CUBLAS AND CUDA_cublas_LIBRARY )

find_package( Doxygen )
if( DOXYGEN_FOUND )
	configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxygen/Doxyfile.in
	                ${CMAKE_CURRENT_BINARY_DIR}/doc/Doxygen/Doxyfile @ONLY )
	add_custom_target( doc
	                   ${DOXYGEN_EXECUTABLE}
	                   ${CMAKE_CURRENT_BINARY_DIR}/doc/Doxygen/Doxyfile
	                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
	                   COMMENT "Generating API documentation with Doxygen"
	                   VERBATIM
	                 )
endif( DOXYGEN_FOUND )

set( CMAKE_C_FLAGS_DEBUG "-Wall -g -O0 -DDEBUG=1" )
set( CMAKE_C_FLAGS_RELEASE "-Wall -O3 -DNDEBUG" )
set( CUDA_NVCC_FLAGS_DEBUG -g -G -O0 -DDEBUG=1 --generate-code arch=compute_20,code=compute_20 )
set( CUDA_NVCC_FLAGS_RELEASE -O3 -DNDEBUG --generate-code arch=compute_20,code=\\"sm_20,sm_21,compute_20\\" )

configure_file( include/cuPoisson.h.in "${PROJECT_BINARY_DIR}/include/cuPoisson.h" )
include_directories( include src "${PROJECT_BINARY_DIR}/include" )

set( SRC_BASE
     src/utils/alg.cu
     src/core/init.cu
     src/core/core_utils.cu
     src/utils/utils.cu
     src/core/grid.c
     src/solvers/fft_utils.cu
   )
   
set( SRC_SERIAL
     src/solvers/fft_ser.cu
     src/solvers/fft_utils_ser.cu
)

set( SRC_MPI
     src/solvers/fft_mpi.cu
     src/solvers/fft_utils_mpi.cu
)

if( MOD_SERIAL )
	list( APPEND SRC_BASE ${SRC_SERIAL} )
endif( MOD_SERIAL )

if( MOD_MPI )
	list( APPEND SRC_BASE ${SRC_MPI} )
endif( MOD_MPI )

set( MULTI_SRC_SERIAL
     src/solvers/solver.cu
   )

set( MULTI_SRC_MPI
     src/solvers/solver.cu
   )

set( SRC ${SRC_BASE} )
include( multi_mod.CMake )

link_directories( ${CUDA_TOOLKIT_ROOT_DIR}/lib64 )
link_directories( ${CUDA_TOOLKIT_ROOT_DIR}/lib )
cuda_add_library( ${LIB_NAME} SHARED ${SRC} )
target_link_libraries( ${LIB_NAME} m )
target_link_libraries( ${LIB_NAME} nvToolsExt )

if( MOD_MPI )
	target_link_libraries( ${LIB_NAME} ${MPI_C_LIBRARIES} )
endif( MOD_MPI )

enable_testing()
add_subdirectory( test )
if( DEV_TESTS )
	add_subdirectory( test_dev EXCLUDE_FROM_ALL )
endif( DEV_TESTS )
