project (dmmlib C)

cmake_minimum_required (VERSION 2.6)

set(APPLICATION_NAME ${PROJECT_NAME})

set(APPLICATION_VERSION_MAJOR 0)
set(APPLICATION_VERSION_MINOR 5)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)

set(DMM_DATA_ALIGNMENT "${CMAKE_SIZEOF_VOID_P}")

include(DefineInstallationPaths)
include(DefineOptions.cmake)

include(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")

if(CMAKE_COMPILER_IS_GNUCC)
  add_definitions(-std=c99 -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wconversion -Wstrict-prototypes)
endif(CMAKE_COMPILER_IS_GNUCC)

# Set to debug build if no such choice was made
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Debug)
endif(NOT CMAKE_BUILD_TYPE)

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
  set(WITH_DEBUG ON)
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")

if(WITH_SYSTEM_CALLS STREQUAL "mmap")
  set(PAGESIZE_ALIGN ON)
  if(NOT DEFINED SYS_ALLOC_SIZE)
    message(FATAL_ERROR "You have to set SYS_ALLOC_SIZE by using -DSYS_ALLOC_SIZE={int}.")
  endif(NOT DEFINED SYS_ALLOC_SIZE)
endif(WITH_SYSTEM_CALLS STREQUAL "mmap")

# Checking free-list setups
if(RAW_BLOCKS_TYPE STREQUAL "freelist")
  set(FL_RB_ONLY ON)

  if(FITTING_POLICY STREQUAL "best")
    set(BEST_FIT ON)
  elseif(FITTING_POLICY STREQUAL "exact")
    set(EXACT_FIT ON)
  elseif(FITTING_POLICY STREQUAL "first")
    set(FIRST_FIT ON)
  elseif(FITTING_POLICY STREQUAL "good")
    if(NOT DEFINED GOOD_FIT_PERCENTAGE)
      message(FATAL_ERROR "You have to set GOOD_FIT_PERCENTAGE by using -DGOOD_FIT_PERCENTAGE={0.f}.")
    endif(NOT DEFINED GOOD_FIT_PERCENTAGE)
    set(GOOD_FIT ON)
  else(FITTING_POLICY STREQUAL "best")
    message(FATAL_ERROR "Could not identify the fitting policy of the freelist organization.")
  endif(FITTING_POLICY STREQUAL "best")
  
  if(ORDERING_POLICY STREQUAL "address")
    set(ADDRESS_ORDERED ON)
  elseif(ORDERING_POLICY STREQUAL "fifo")
    set(FIFO_ORDERED ON)
  elseif(ORDERING_POLICY STREQUAL "lifo")
    set(LIFO_ORDERED ON)
  elseif(ORDERING_POLICY STREQUAL "size")
    set(SIZE_ORDERED ON)
  endif(ORDERING_POLICY STREQUAL "address")
  
  if(WITH_COALESCING STREQUAL "fixed")
    if(NOT DEFINED MAX_COAL_SIZE)
      message(FATAL_ERROR "You have to set MAX_COAL_SIZE by using -DMAX_COAL_SIZE={int}.")
    endif(NOT DEFINED MAX_COAL_SIZE)
    set(COALESCING_FIXED ON)
  elseif(WITH_COALESCING STREQUAL "variable")
    if(NOT DEFINED MAX_COAL_SIZE)
      message(FATAL_ERROR "You have to set MAX_COAL_SIZE by using -DMAX_COAL_SIZE={int}.")
    endif(NOT DEFINED MAX_COAL_SIZE)
    set(COALESCING_VARIABLE ON)
  endif(WITH_COALESCING STREQUAL "fixed")
  
  if(WITH_SPLITTING STREQUAL "fixed")
    if(NOT DEFINED MIN_SPLIT_SIZE)
      message(FATAL_ERROR "You have to set MIN_SPLIT_SIZE by using -DMIN_SPLIT_SIZE={int}.")
    endif(NOT DEFINED MIN_SPLIT_SIZE)
    set(SPLITTING_FIXED ON)
  elseif(WITH_SPLITTING STREQUAL "variable")
    if(NOT DEFINED MIN_SPLIT_SIZE)
      message(FATAL_ERROR "You have to set MIN_SPLIT_SIZE by using -DMIN_SPLIT_SIZE={int}.")
    endif(NOT DEFINED MIN_SPLIT_SIZE)
    set(WITH_KNOBS ON)
    set(SPLITTING_VARIABLE ON)
  endif(WITH_SPLITTING STREQUAL "fixed")

  if(COALESCE_AFTER_SPLIT)
    if(WITH_SPLITTING STREQUAL "never")
      message(FATAL_ERROR "You have to set WITH_SPLITTING to fixed or variable if you want to coalesce after split.")
    endif(WITH_SPLITTING STREQUAL "never")
    if(WITH_COALESCING STREQUAL "never")
      message(FATAL_ERROR "You have to set WITH_COALESCING to fixed or variable if you want to coalesce after split.")
    endif(WITH_COALESCING STREQUAL "never")
  endif(COALESCE_AFTER_SPLIT)

# Checking bitmap setups
elseif(RAW_BLOCKS_TYPE STREQUAL "bitmap")

  set(BITMAP_RB_ONLY ON)

endif(RAW_BLOCKS_TYPE STREQUAL "freelist")

if(STATS STREQUAL "global")
  set(WITH_ALLOCATOR_STATS ON)
endif(STATS STREQUAL "global")

configure_file (
	"${PROJECT_SOURCE_DIR}/config.h.cmake"
	"${PROJECT_BINARY_DIR}/dmmlib/config.h"
)

install(
  FILES
    ${PROJECT_BINARY_DIR}/dmmlib/config.h
  DESTINATION
    ${INCLUDE_INSTALL_DIR}/dmmlib
  COMPONENT
    headers
)

include_directories("${PROJECT_BINARY_DIR}")

add_subdirectory(include)
add_subdirectory(src)

if(WITH_EXAMPLES)
  add_subdirectory(examples)
endif (WITH_EXAMPLES)

if(WITH_DOC)
  add_subdirectory(doc)
endif (WITH_DOC)

message(STATUS "********************************************")
message(STATUS "********** ${PROJECT_NAME} v${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR} build options : **********")
message(STATUS "OS call for memory requests: " ${WITH_SYSTEM_CALLS})
if(NOT WITH_SYSTEM_CALLS STREQUAL "none")
  message(STATUS "Default allocation size for OS calls: " ${SYS_ALLOC_SIZE} " bytes")
endif(NOT WITH_SYSTEM_CALLS STREQUAL "none")

message(STATUS "POSIX locking mechanisms: " ${HAVE_LOCKS})

message(STATUS "Raw blocks type: " ${RAW_BLOCKS_TYPE})

if(RAW_BLOCKS_TYPE STREQUAL "freelist")

  if(BLOCKS_ORGANIZATION STREQUAL "dll")
    message(STATUS "Block organization: Doubly-Linked Lists")
  else(BLOCKS_ORGANIZATION STREQUAL "dll")
    message(STATUS "Block organization: Singly-Linked Lists")
  endif(BLOCKS_ORGANIZATION STREQUAL "dll")

  message(STATUS "Fitting policy: " ${FITTING_POLICY})
  if(GOOD_FIT)
    message(STATUS "Acceptable fit percentage: " ${GOOD_FIT_PERCENTAGE})
  endif(GOOD_FIT)
  message(STATUS "Ordering policy: " ${ORDERING_POLICY})

  message(STATUS "Coalescing: " ${WITH_COALESCING})
  if(MAX_COAL_SIZE)
    if(WITH_COALESCING STREQUAL "fixed")
      message(STATUS "  with max. coalescing size: " ${MAX_COAL_SIZE} " bytes")
    elseif(WITH_COALESCING STREQUAL "variable")
      message(STATUS "  with initial max. coalescing size: " ${MAX_COAL_SIZE}
        " bytes")
    endif(WITH_COALESCING STREQUAL "fixed")
  endif(MAX_COAL_SIZE)

  message(STATUS "Splitting: " ${WITH_SPLITTING})
  if(MIN_SPLIT_SIZE)
    if(WITH_SPLITTING STREQUAL "fixed")
      message(STATUS "  with min. splitting size: " ${MIN_SPLIT_SIZE} " bytes")
    elseif(WITH_SPLITTING STREQUAL "variable")
      message(STATUS "  with initial min. splitting size: "
        ${MIN_SPLIT_SIZE} " bytes")
    endif(WITH_SPLITTING STREQUAL "fixed")
    if(COALESCE_AFTER_SPLIT)
      message(STATUS "Coalesce after split: " ${COALESCE_AFTER_SPLIT})
    endif(COALESCE_AFTER_SPLIT)
  endif(MIN_SPLIT_SIZE)

elseif(RAW_BLOCKS_TYPE STREQUAL "bitmap")
  message(STATUS "Bitmap cell resolution: " ${BITMAP_RESOLUTION} " bytes")

endif(RAW_BLOCKS_TYPE STREQUAL "freelist")

message(STATUS "Have knobs: " ${WITH_KNOBS})
message(STATUS "Have statistics: " ${STATS})
message(STATUS "Requested Size per Block: " ${REQUEST_SIZE_INFO})
message(STATUS "Support for debug functions: " ${WITH_DEBUG})
message(STATUS "Support for memory traces: " ${WITH_MEM_TRACE})
message(STATUS "Support for statistics traces: " ${WITH_STATS_TRACE})
message(STATUS "Support for realloc(): " ${WITH_REALLOC})
message(STATUS "Support for calloc(): " ${WITH_CALLOC})
message(STATUS "Support for memalign(): " ${WITH_MEMALIGN})
message(STATUS "Support to parse dmmlib environment variables: " ${PARSE_ENV})
message(STATUS "********************************************")
