cmake_minimum_required (VERSION 3.1)
project(EZTrace
  VERSION 2.0.0
  LANGUAGES C
)


# include CMake modules
include(CheckLibraryExists)
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(GNUInstallDirs)
include(CheckLanguage)
include(CheckCSourceCompiles)
include(CTest)

# POLICIES #####################
if (POLICY CMP0074)
  cmake_policy(SET CMP0074 NEW)
  cmake_policy(SET CMP0079 NEW)
endif()

# RPATH ########################################
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_SKIP_BUILD_RPATH FALSE) # use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # when building, don't use the install RPATH already (but later on when installing)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") # the RPATH to be used when installing

# CMakeFind repository
list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_modules)

find_package (OTF2 REQUIRED)
if (NOT OTF2_FOUND)
   message(FATAL_ERROR "libotf2 not found.")
endif()

SET(CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -I${OTF2_INCLUDE_PATH}")
SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -I${OTF2_INCLUDE_PATH}")

SET(CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -D_GNU_SOURCE")
SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -D_GNU_SOURCE")

# Check if fortran is available
check_language(Fortran)
if(CMAKE_Fortran_COMPILER)
  enable_language(Fortran)
else()
  message(STATUS "No Fortran support")
endif()

# Look for library

#find_package (OpenMP)

# Options to enable/disable modules

option(EZTRACE_ENABLE_MPI      "Enable MPI module"      OFF)
#option(EZTRACE_ENABLE_CUDA     "Enable CUDA module"     OFF)
#option(EZTRACE_ENABLE_STARPU   "Enable StarPU module"   OFF)
option(EZTRACE_ENABLE_OPENMP   "Enable OpenMP module"   OFF)
#option(EZTRACE_ENABLE_PAPI     "Enable PAPI module"     OFF)
option(EZTRACE_ENABLE_POSIXIO  "Enable POSIXIO module"  ON)
option(EZTRACE_ENABLE_PTHREAD  "Enable Pthread module"  ON)
option(EZTRACE_ENABLE_MEMORY   "Enable Memory module"   OFF)
option(EZTRACE_ENABLE_OMPT     "Enable OMPT module"     OFF)
option(EZTRACE_ENABLE_IOTRACER "Enable IOtracer module" OFF)

SET(MPI_MODULE_NAME "mpi" CACHE STRING "Name of the MPI module")


option(ENABLE_BIN_INSTRUMENTATION "Enable binary instrumentation" OFF)

if(EZTRACE_ENABLE_IOTRACER)
  find_path(IOTRACER_PATH "bcc_iotracer.py" REQUIRED)
endif()

if(ENABLE_BIN_INSTRUMENTATION)
  find_library(BFD NAMES bfd)
  if (NOT BFD)
    message(FATAL_ERROR "libbfd found. This library is required for binary instrumentation")
  endif()

  find_package (LibOpcodes)
  CHECK_LIBRARY_EXISTS(opcodes disassembler "" disassembler_exist)
  if (NOT disassembler_exist)
    message(FATAL_ERROR "libopcodes: disassembler not found. This library is required for binary instrumentation")
  endif()

  set(EZTRACE_BINARY_INSTRUMENTATION_FLAG -DENABLE_BINARY_INSTRUMENTATION)

endif()

set (HAVE_DEMANGLE 0)
check_library_exists(iberty cplus_demangle "" cplus_demangle_exist)
if (cplus_demangle_exist)
  find_path (DEMANGLE_INCLUDEDIR NAMES "demangle.h"
    HINTS /usr/include/libiberty/
    )
  if(DEMANGLE_INCLUDEDIR)
    set (HAVE_DEMANGLE 1)
  else()
    message(WARNING " demangle.h not found. C++ symbols will not be demangled")
  endif()
else()
  message(WARNING " libiberty not found. C++ symbols will not be demangled")
endif()

if (EZTRACE_ENABLE_MPI)
  find_program(MPICC mpicc REQUIRED)
  find_program(MPIF90 mpif90)
endif()

# if (EZTRACE_ENABLE_STARPU)
#   find_package(STARPU "1.2" REQUIRED COMPONENTS HWLOC MPI)
#   list(APPEND CMAKE_INSTALL_RPATH ${STARPU_LIBRARY_DIRS})
# endif()
# 
# if (EZTRACE_ENABLE_PAPI)
#   find_package (LibPapi REQUIRED)
# endif()
# 
# if (EZTRACE_ENABLE_CUDA)
#   find_package (CUDA REQUIRED)
# endif()

if (EZTRACE_ENABLE_OPENMP)
  find_package (OpenMP REQUIRED)
  find_program(OPARI2 opari2)
  find_program(OPARI2_CONFIG opari2-config)
  IF( NOT OPARI2)
    message(FATAL_ERROR " opari2 was not found. Please download it from https://www.vi-hps.org/projects/score-p#opari2 and install it")
  endIF(NOT OPARI2)
  IF (NOT OPARI2_CONFIG)
    message(FATAL_ERROR " opari2-config was not found. Please download it from https://www.vi-hps.org/projects/score-p#opari2 and install it")
  endIF (NOT OPARI2_CONFIG)
endif()

if (EZTRACE_ENABLE_OMPT)
  find_package (OpenMP REQUIRED)
  find_package (OMPT REQUIRED)
endif()

#set(THREADS_PREFER_PTHREAD_GLAF ON)
#find_package(Threads REQUIRED)

####################################################
# Some flags for compilation

set (prefix "${CMAKE_INSTALL_PREFIX}")
set (INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig")

check_include_files("sys/prctl.h" HAVE_PRCTL_H)
if (NOT HAVE_PRCTL_H)
  set(HAVE_PRCTL_H 0)
endif()

check_include_files("libbacktrace/backtrace.h" HAVE_LIBBACKTRACE)
if (NOT HAVE_LIBBACKTRACE)
  set(HAVE_LIBBACKTRACE 0)
endif()

set(LIBRARY_PATH "${CMAKE_INSTALL_PREFIX}/lib")
if ("${APPLE}")
  set(DYNLIB_EXT "dylib")
  set(LD_PRELOAD_NAME "DYLD_INSERT_LIBRARIES")
  set(LD_LIBRARY_PATH_NAME "DYLD_LIBRARY_PATH")
else() # By default -> Linux
  set(DYNLIB_EXT "so")
  set(LD_PRELOAD_NAME "LD_PRELOAD")
  set(LD_LIBRARY_PATH_NAME "LD_LIBRARY_PATH")
endif()

set(EZTRACE_LIB_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
#set(PPTRACE_BINARY_TYPE "PPTRACE_BINARY_TYPE_BFD")
#set(__PPTRACE_BINARY_TYPE "PPTRACE_BINARY_TYPE_BFD")
#set(abs_top_builddir ${CMAKE_BINARY_DIR})

set(INSTALL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
set(INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")

# Subdirectory
add_subdirectory (src)
add_subdirectory (test/unit_tests)

include(PrintOpts)

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/eztrace.pc.in
               ${CMAKE_CURRENT_BINARY_DIR}/eztrace.pc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eztrace.pc DESTINATION "${INSTALL_PKGCONFIG_DIR}")
