project(softshell)
cmake_minimum_required(VERSION 2.8)

if(COMMAND cmake_policy)
  cmake_policy(SET CMP0003 NEW)
  cmake_policy(SET CMP0015 NEW)
  #cmake_policy(SET CMP0017 NEW)
  cmake_policy(SET CMP0012 NEW)
endif(COMMAND cmake_policy)

set(EXPERIMENTAL        OFF)
set(TEST_SELF_CONTAINED OFF)

file(TO_CMAKE_PATH "$ENV{CMAKE_MODULE_PATH}" OT_CMAKE_MODULE_PATH)
set(CMAKE_MODULE_PATH ${OT_CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake ${PROJECT_SOURCE_DIR}/build/cmake)

# first process the modules

include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/core)
include_directories(${PROJECT_BINARY_DIR})

# stuff has to land -> for now we use the source dir since this is how everybody
# seems to use the library
if (WIN32)
  make_directory(${CMAKE_CURRENT_SOURCE_DIR}/bin)
  make_directory(${CMAKE_CURRENT_SOURCE_DIR}/lib)
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
else (WIN32)
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
endif (WIN32)

if (WIN32)
  # for msvc 8 deprecated warning removal
  add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
  add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
  add_definitions(-D_CRT_SECURE_NO_DEPRECATE_GLOBALS)
  add_definitions(-DWIN32 -D_WIN32)
  add_definitions(-DNOMINMAX)

  #set(CMAKE_DEBUG_POSTFIX "D")

  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT.lib;libcmtd.lib")
endif(WIN32)

set(CUDA_BUILD_CUBIN OFF)

if (WIN32)
  add_definitions(-DGL_GLEXT_PROTOTYPES -bigobj)
endif()


# Cuda:
set(CUDA_BUILD_EMULATION OFF CACHE BOOL "enable emulation mode")
find_package(CUDA_DLINK REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})

#set(CUDA_NVCC_FLAGS "-arch=compute_30;-code=sm_30;-use_fast_math;")
if( ${CUDA_VERSION} VERSION_LESS "5")
MESSAGE(INFO "Building with CUDA < 5.0")
message( SEND_ERROR "Softshell requires CUDA 5.0 or higher" )
else()
MESSAGE(INFO "Building with CUDA >= 5.0")
#set(CUDA_NVCC_FLAGS "-gencode;arch=compute_30,code=sm_30;-gencode;arch=compute_20,code=sm_21;-gencode;arch=compute_20,code=sm_20;-use_fast_math;")
endif()

option(CUDA_BUILD_CC20 "Build with compute capability 2.0 support" TRUE)
option(CUDA_BUILD_CC30 "Build with compute capability 3.0 support" TRUE)
option(CUDA_BUILD_CC35 "Build with compute capability 3.5 support" FALSE)
option(CUDA_BUILD_INFO "Build with kernel statistics and line numbers" TRUE)
option(CUDA_BUILD_DEBUG "Build with kernel debug" FALSE)

set(CUDA_NVCC_FLAGS "-use_fast_math;")
if(CUDA_BUILD_CC20)
	set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-gencode=arch=compute_20,code=sm_20")
endif()
if(CUDA_BUILD_CC30)
	set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-gencode=arch=compute_30,code=sm_30")
endif()
if(CUDA_BUILD_CC35)
	set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-gencode=arch=compute_35,code=sm_35;-maxrregcount=64")
endif()
if(CUDA_BUILD_INFO)
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-keep;--ptxas-options=-v;-lineinfo")
endif()
if(CUDA_BUILD_DEBUG)
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-G")
endif()


set(SOFTSHELL_AGGREGATION_FILES
  core/aggregation/aggregation.cu
  core/aggregation/localaggregation.cu
  core/aggregation/aggregation.cuh
  core/aggregation/localaggregation.cuh
  core/aggregation/localworkitem.cuh
  core/aggregation/payloadedworkpackage.cuh
)

set(SOFTSHELL_API_FILES
  core/api/devent.h
  core/api/event.h
  core/api/priority.h
  core/api/procedure.h
  core/api/scheduler.h
  core/api/workitem.h
  core/api/workpackage.h
)

set(SOFTSHELL_COMMUNICATOR_FILES
  core/communicator/dcommunicator.cu
  core/communicator/dparams.cu
  core/communicator/hcommunicator.cu
  core/communicator/communicatordata.h
  core/communicator/hcommunicator.h
  core/communicator/hmessagereceiver.h
  core/communicator/hparams.h
  core/communicator/messageids.h
  core/communicator/params.h
  core/communicator/dcommunicator.cuh
  core/communicator/dcommunicator.ipp
  core/communicator/dparams.cuh
)

set(SOFTSHELL_DISTRIBUTOR_FILES
  core/distributor/event.cu
  core/distributor/device.cu
  core/distributor/eventmanager.cu
  core/distributor/hscheduler.cu
  core/distributor/proceduremanager.cu
  core/distributor/defaultcreatorparams.h
  core/distributor/device.h
  core/distributor/deviceentries.h
  core/distributor/devicepointerlist.h
  core/distributor/eventData.h
  core/distributor/eventlist.h
  core/distributor/eventworkpackagemanagement.h
  core/distributor/event_impl.h
  core/distributor/hscheduler.h
  core/distributor/deviceentries.cuh
  core/distributor/event.ipp
  core/distributor/eventcommunicator.cuh
  core/distributor/eventmanager.cuh
  core/distributor/eventmanager.ipp
  core/distributor/event_impl.ipp
  core/distributor/hscheduler.cuh
  core/distributor/proceduremanager.cuh
  core/distributor/eventlist.cpp
  core/distributor/hscheduler.cpp
  core/distributor/scheduler.cpp
)

set(SOFTSHELL_MEGAKERNEL_FILES
  core/megakernel/def_controller.cu
  core/megakernel/launchstates.cu
  core/megakernel/megakernel.cu
  core/megakernel/megakernel_simple.cu
  core/megakernel/megakernelissuer.cu
  core/megakernel/controller.h
  core/megakernel/kernelissuer.h
  core/megakernel/megakernel.h
  core/megakernel/megakernelissuer.h
  core/memory/mappedMemory.h
  core/megakernel/controller.cuh
  core/megakernel/def_controller.cuh
  core/megakernel/execstate.cuh
  core/megakernel/launchstates.cuh
  core/megakernel/localprepull.cuh
)

set(SOFTSHELL_MEMORY_FILES
  core/memory/roundrobinalloc.cu
  core/memory/ScatterAlloc.cu
  core/memory/roundrobinalloc.cuh
  core/memory/ScatterAlloc.cuh
  core/memory/UseScatterAlloc.cuh
  core/memory/mappedMemory.cpp
)

set(SOFTSHELL_PRIORITIES_FILES
  core/priorities/eventPriorityEval.h
)
set(SOFTSHELL_QUEUE_FILES
  core/queue/dscheduler.cu
  core/queue/dscheduler.cuh
  core/queue/queue.cuh
  core/queue/queueEntry.cuh
)
set(SOFTSHELL_STDLIB_FILES
   core/stdlib/asms.cuh
  core/stdlib/hash.cuh
  core/stdlib/maintained_linked_list.cuh
  core/stdlib/mutex.cuh
  core/stdlib/pair.cuh
  core/stdlib/unordered_map.cuh
  core/stdlib/vector.cuh
)
set(SOFTSHELL_TIMING_FILES
  core/timing/timesync.cu
  core/timing/timesync.h
  core/timing/timesync.cuh
  core/timing/timesync.cpp
)
set(SOFTSHELL_TOOLS_FILES
  core/tools/align.h
  core/tools/any.h
  core/tools/config.h
  core/tools/configcollection.h
  core/tools/idmanager.h
  core/tools/thread.h
  core/tools/types.h
  core/tools/utils.h
  core/tools/bitonicSort.cuh
  core/tools/common.cuh
  core/tools/math.cuh
  core/tools/config.cpp
)

set(SOFTSHELL_CORE_HEADERS  
  core/softshell.h
)

SOURCE_GROUP(Aggregation FILES ${SOFTSHELL_AGGREGATION_FILES})
SOURCE_GROUP(API FILES ${SOFTSHELL_API_FILES})
SOURCE_GROUP(Communicator FILES ${SOFTSHELL_COMMUNICATOR_FILES})
SOURCE_GROUP(Distributor FILES ${SOFTSHELL_DISTRIBUTOR_FILES})
SOURCE_GROUP(Megakernel FILES ${SOFTSHELL_MEGAKERNEL_FILES})
SOURCE_GROUP(Memory FILES ${SOFTSHELL_MEMORY_FILES})
SOURCE_GROUP(Priorities FILES ${SOFTSHELL_PRIORITIES_FILES})
SOURCE_GROUP(Queue FILES ${SOFTSHELL_QUEUE_FILES})
SOURCE_GROUP(StdLib FILES ${SOFTSHELL_STDLIB_FILES})
SOURCE_GROUP(Timing FILES ${SOFTSHELL_TIMING_FILES})
SOURCE_GROUP(Tools FILES ${SOFTSHELL_TOOLS_FILES})



SET(SOFTSHELL_CORE_ALL_FILES
  ${SOFTSHELL_CORE_HEADERS}
  ${SOFTSHELL_AGGREGATION_FILES}
  ${SOFTSHELL_API_FILES}
  ${SOFTSHELL_COMMUNICATOR_FILES}
  ${SOFTSHELL_DISTRIBUTOR_FILES}
  ${SOFTSHELL_MEGAKERNEL_FILES}
  ${SOFTSHELL_MEMORY_FILES}
  ${SOFTSHELL_PRIORITIES_FILES}
  ${SOFTSHELL_QUEUE_FILES}
  ${SOFTSHELL_STDLIB_FILES}
  ${SOFTSHELL_TIMING_FILES}
  ${SOFTSHELL_TOOLS_FILES}
)

IF (WIN32)
cuda_add_device_library(core ${SOFTSHELL_CORE_ALL_FILES})
set_target_properties(core PROPERTIES OUTPUT_NAME core)
get_target_property(corelib_name core LOCATION)
ELSE (WIN32)
cuda_add_device_library(core ${SOFTSHELL_CORE_ALL_FILES})
get_target_property(corelib_name core LOCATION_<CONFIG>)
ENDIF (WIN32)

message(STATUS "outputname: ${corelib_name}")

include_directories(${PROJECT_SOURCE_DIR}/examples/framework)
include_directories(${PROJECT_SOURCE_DIR}/examples/framework/GL_utils)
include_directories(${PROJECT_SOURCE_DIR}/examples/utils)

###############################################################################
#
#   simple example
#
###############################################################################

set(SIMPLE_HEADERS
  examples/simple/proc1.cuh
  examples/simple/proc2.cuh
)
set(SIMPLE_SRC
  examples/simple/main.cpp
  examples/simple/proc1.cu
  examples/simple/proc2.cu
  examples/simple/simple.cu
)

cuda_add_device_executable(simple ${SIMPLE_SRC} ${SIMPLE_HEADERS}
 PRELINK_LIBRARIES ${corelib_name}
)

target_link_libraries(simple
  ${corelib_name}
)

add_dependencies(simple core)

###############################################################################
#
#   priority example
#
###############################################################################

set(PRIORITY_HEADERS
  examples/priority/myproc.cuh
  examples/priority/mypriority.cuh
  examples/priority/myworkpackage.cuh
)
set(PRIORITY_SRC
  examples/priority/main.cpp
  examples/priority/myproc.cu
  examples/priority/priority.cu
)

cuda_add_device_executable(priority ${PRIORITY_SRC} ${PRIORITY_HEADERS}
 PRELINK_LIBRARIES ${corelib_name}
)

target_link_libraries(priority
  ${corelib_name}
)

add_dependencies(priority core)

###############################################################################
#
#   workitem example
#
###############################################################################

set(WORKITEM_HEADERS
  examples/workitem/consumerproc.cuh
  examples/workitem/generatorproc.cuh
)

set(WORKITEM_SRC
  examples/workitem/main.cpp
  examples/workitem/workitem.cu
  examples/workitem/consumerproc.cu
  examples/workitem/generatorproc.cu
)

cuda_add_device_executable(workitem ${WORKITEM_SRC} ${WORKITEM_HEADERS}
 PRELINK_LIBRARIES ${corelib_name}
)

target_link_libraries(workitem
  ${corelib_name}
)

add_dependencies(workitem core)

###############################################################################
#
#   thirdtier example
#
###############################################################################

set(THIRDTIER_HEADERS
  examples/thirdtier/payloadedproc.cuh
)

set(THIRDTIER_SRC
  examples/thirdtier/main.cpp
  examples/thirdtier/thirdtier.cu
  examples/thirdtier/payloadedproc.cu
)

cuda_add_device_executable(thirdtier ${THIRDTIER_SRC} ${THIRDTIER_HEADERS}
 PRELINK_LIBRARIES ${corelib_name}
)

target_link_libraries(thirdtier
  ${corelib_name}
)

add_dependencies(thirdtier core)




