#/////////////////// P /// L /// A /// S /// M /// A //////////////////
#///  PLASMA - version 2.1.0                                       ///
#///  Release Date: November, 15th 2009                            ///
#/// PLASMA is a software package provided by Univ. of Tennessee,  ///
#/// Univ. of California Berkeley and Univ. of Colorado Denver     ///
#//////////////////////////////////////////////////////////////////////

project( PLASMA )
cmake_minimum_required( VERSION 2.6 )
set( CMAKE_CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)

set( PLASMA_VERSION_MAJOR "2" )
set( PLASMA_VERSION_MINOR "1" )
set( PLASMA_VERSION_PATCH "0" )
set( PLASMA_VERSION "${PLASMA_VERSION_MAJOR}.${PLASMA_VERSION_MINOR}.${PLASMA_VERSION_PATCH}" )

# Disallow in-source build
string( COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" INSOURCE )
if( INSOURCE )
  message( FATAL_ERROR "\n"
  "PLASMA requires an out-of-source-directory "
  "build. Please create a separate build directory and "
  "use CMake to configure and build there. \n"
  "e.g. mkdir build_dir; cd build_dir; cmake ..; make" )
endif()

# Release build is the default
if( NOT DEFINED CMAKE_BUILD_TYPE )
  set(CMAKE_BUILD_TYPE "Release")
endif()

enable_language( Fortran C )

## Are we building 32 or 64 bit libraries
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
  set( BUILD64BIT 1)
else ()
  set( BUILD32BIT 1)
endif ()

# --------------------------------------------------

# WINDOWS specific setup
if (WIN32 AND NOT UNIX)

  find_package( Threads )
  if(CMAKE_USE_WIN32_THREADS_INIT)
    message(STATUS "Building multithreaded libraries using Windows threads.")
  endif(CMAKE_USE_WIN32_THREADS_INIT)
  link_libraries(${CMAKE_THREAD_LIBS_INIT})

  ## Setup Windows output locations
  set( LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib/" CACHE PATH "Output directory for all libraries" )
  ## set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH}/bin" CACHE PATH "Output directory for all executables")

  # Setup BLAS libaries, specifically MKL blas
  if (BUILD64BIT)
    set( CMAKE_FORCE_WIN64 )
    # 64 bit MKL BLAS
    set( PLASMA_LIBS plasma coreblas cblas corelapack )
    set( BLAS_LIBS mkl_intel_lp64.lib mkl_sequential.lib mkl_core.lib )
    set( LINK_LIBS ${PLASMA_LIBS} ${BLAS_LIBS} libcmt.lib )
    set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE /INCREMENTAL:NO" )

  else ()
    # 32 bit MKL BLAS
    set( PLASMA_LIBS plasma coreblas cblas corelapack )
    set( BLAS_LIBS mkl_intel_c.lib mkl_sequential.lib mkl_core.lib )
    set( LINK_LIBS ${PLASMA_LIBS} ${BLAS_LIBS} libcmt.lib )
    set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE /INCREMENTAL:NO" )

  endif ()

  # Change /MD flags to /MT flags to get multi-threaded static libraries 
  # Change any /O1 optimization flags to /O2
  foreach(flag_var
    CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
    CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
    CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
    CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
    CMAKE_Fortran_FLAGS CMAKE_Fortran_FLAGS_DEBUG CMAKE_Fortran_FLAGS_RELEASE
    CMAKE_Fortran_FLAGS_MINSIZEREL CMAKE_Fortran_FLAGS_RELWITHDEBINFO)
    if(${flag_var} MATCHES "/MD")
      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
    endif(${flag_var} MATCHES "/MD")
    if(${flag_var} MATCHES "/O1")
      string(REGEX REPLACE "/O1" "/O2" ${flag_var} "${${flag_var}}")
    endif(${flag_var} MATCHES "/O1")
  endforeach(flag_var)

  # Don't include MSVCRT runtime library by default
  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:MSVCRT.lib ")

  # Set Windows C compiler  specific flags 
  if ( "${CMAKE_C_COMPILER}" MATCHES "icl" )
    # Intel C; Force C99 mode
    set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qstd=c99 /Zi" )
  elseif ( "${CMAKE_C_COMPILER}" MATCHES "cl" )
    # MS C compiler; Force C++ mode, error handler
    set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /TP /EHsc" )
  else ()
    set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" )
  endif ()

  # Set Windows Fortran compiler specific flags 
  if ( "${CMAKE_Fortran_COMPILER}" MATCHES "ifort" )
    set( CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /fltconsistency /Zi /names:uppercase" )
    set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUPCASE" )
    set( Fortran_LINKER_C_MAIN_FLAGS " " )
  else ()
    set( Fortran_LINKER_C_MAIN_FLAGS " " )
  endif ()

else(not windows)

  find_package( BLAS REQUIRED )
  find_library( PTHREADS_LIBRARY NAMES pthread pthreads DOC "The Standard PTHREADS library")
  set( LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib/" CACHE PATH "Output directory for all libraries" )  
  #set( EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin/" CACHE PATH "Output directory for all executables" )  
  set( PLASMA_LIBS plasma coreblas corelapack cblas )
  set( LINK_LIBS ${PLASMA_LIBS} corelapack ${BLAS_LIBRARIES} ${PTHREADS_LIBRARY} m )
  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUPCASE" )
  if ( "${CMAKE_Fortran_COMPILER}" MATCHES "ifort" )
    set( CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fltconsistency -fp_port" )
    set( Fortran_LINKER_C_MAIN_FLAGS " -nofor_main " )
  else ()
    set( Fortran_LINKER_C_MAIN_FLAGS " " )
  endif ()

endif()

# Macro to setup compile flags for binaries with C main files
macro( PLASMA_SETUP_C_MAIN target )
  target_link_libraries ( ${target} ${LINK_LIBS} )
  set_target_properties( ${target} PROPERTIES LINKER_LANGUAGE Fortran)
  set_target_properties( ${target} PROPERTIES LINK_FLAGS ${Fortran_LINKER_C_MAIN_FLAGS} )
  #if (WIN32 AND NOT UNIX)
    # Embed the manifest in the windows file 
    #add_custom_command( TARGET ${target} POST_BUILD COMMAND mt.exe ARGS -nologo -manifest ${EXECUTABLE_OUTPUT_PATH}//${target}.exe.manifest "-outputresource:${EXECUTABLE_OUTPUT_PATH}//${target}.exe;1"  )
  #endif()
endmacro( PLASMA_SETUP_C_MAIN )


# Macro to setup compile flags for binaries with Fortran main files
macro( PLASMA_SETUP_Fortran_MAIN target )
  target_link_libraries ( ${target} ${LINK_LIBS} )
  set_target_properties( ${target} PROPERTIES LINKER_LANGUAGE Fortran)
  #if (WIN32 AND NOT UNIX)
    # Embed the manifest in the windows file
    #add_custom_command( TARGET ${target} POST_BUILD COMMAND mt.exe ARGS -nologo -manifest ${EXECUTABLE_OUTPUT_PATH}//${target}.exe.manifest "-outputresource:${EXECUTABLE_OUTPUT_PATH}//${target}.exe;1"  )
  #endif()
endmacro( PLASMA_SETUP_Fortran_MAIN )

# Subdirectories that need to be processed
include_directories( include )
subdirs( include core_blas cblas core_lapack src timing testing examples )

# Install some additional source files in the distribution
INSTALL( FILES CMakeLists.txt CMakeBuildNotes LICENSE Makefile README ReleaseNotes make.inc.example DESTINATION . )

# Install all the files in the docs directory in the distribution
INSTALL( DIRECTORY docs/html DESTINATION ./docs PATTERN ".svn" EXCLUDE PATTERN "*~" EXCLUDE PATTERN "#*" EXCLUDE PATTERN "*htmlbrowsing*" EXCLUDE)
INSTALL( DIRECTORY docs/pdf DESTINATION ./docs PATTERN ".svn" EXCLUDE PATTERN "*~" EXCLUDE PATTERN "#*" EXCLUDE)

# --------------------------------------------------
# CPACK Packaging 

SET(CPACK_PACKAGE_NAME "PLASMA")
SET(CPACK_PACKAGE_VENDOR "Innovative Computing Lab - University of Tennessee")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "PLASMA ${PLASMA_VERSION} - Parallel Linear Algebra Software for Multicore Architectures")
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
SET(CPACK_PACKAGE_VERSION_MAJOR ${PLASMA_VERSION_MAJOR} )
SET(CPACK_PACKAGE_VERSION_MINOR ${PLASMA_VERSION_MINOR} )
SET(CPACK_PACKAGE_VERSION_PATCH ${PLASMA_VERSION_PATCH} )
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "PLASMA")
IF(WIN32 AND NOT UNIX)
  SET( CPACK_GENERATOR "NSIS")  
  # There is a bug in NSI that does not handle full unix paths properly. Make
  # sure there is at least one set of four (4) backlasshes.
  ##SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
  ##SET(CPACK_NSIS_INSTALLED_ICON_NAME "PLASMA Linear Algebra Library")
  ##SET(CPACK_NSIS_MODIFY_PATH ON)
  SET(CPACK_NSIS_DISPLAY_NAME "PLASMA-${PLASMA_VERSION}")
  SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\icl.eecs.utk.edu\\\\plasma")
  SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\icl.eecs.utk.edu\\\\plasma")
  SET(CPACK_NSIS_CONTACT "plasma@eecs.utk.edu")
  set(CPACK_PACKAGE_RELOCATABLE "true")
  ##set (CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS Microsoft.VC90.CRT.manifest msvcr90.dll msvcm90.dll msvcp90.dll libifcoremd.dll libmmd.dll )
  ##FIND_PATH(FREDIST_PATH libifcoremd.lib )
  IF(BUILD64BIT)
    SET(CPACK_SYSTEM_NAME win64)
    SET(FREDIST_PATH "c:/Program Files (x86)/Intel/Compiler/Fortran/10.1.025/em64t/Lib" )
  ELSE()
    SET(CPACK_SYSTEM_NAME win32)
    SET(FREDIST_PATH "c:/Program Files (x86)/Intel/Compiler/Fortran/10.1.025/IA32/Lib" )
  ENDIF()
  INSTALL( PROGRAMS 
    ${FREDIST_PATH}/ifconsol.lib 
    ${FREDIST_PATH}/libifcoremd.lib 
    ${FREDIST_PATH}/libifcoremt.lib 
    ${FREDIST_PATH}/libifport.lib 
    ${FREDIST_PATH}/libifportmd.lib 
    ${FREDIST_PATH}/libirc.lib 
    ${FREDIST_PATH}/libmmd.lib 
    ${FREDIST_PATH}/libmmt.lib 
    ${FREDIST_PATH}/svml_disp.lib 
    DESTINATION lib )
  INCLUDE(InstallRequiredSystemLibraries)
ELSE(WIN32 AND NOT UNIX)
  SET(CPACK_SOURCE_STRIP_FILES "")
ENDIF(WIN32 AND NOT UNIX)
INCLUDE(CPack)


message("------------------------------------------------------------------------")
message("Configuration:")
message("")
message(" Source code location: ${CMAKE_SOURCE_DIR}")
message(" Build type: ${CMAKE_BUILD_TYPE}")
message(" C Compiler: ${CMAKE_C_COMPILER}")
message(" C Compiler flags: ${CMAKE_C_FLAGS}")
message(" Fortran Compiler: ${CMAKE_Fortran_COMPILER}")
message(" Fortran flags: ${CMAKE_Fortran_FLAGS}")
message(" Install path: ${CMAKE_INSTALL_PREFIX}")
message(" BLAS_LIBS: ${BLAS_LIBS}")
message(" PLASMA_LIBS: ${PLASMA_LIBS}")
message(" LINK_LIBS: ${LINK_LIBS}")
message(" CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")
message("")
message("------------------------------------------------------------------------")
