################################################
# Level: trunk/src/cxx/CMakeLists.txt
################################################

enable_language(Fortran)
enable_language(C)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")

find_package(BLAS REQUIRED)
message("hittade ${BLAS_LIBRARIES}")

find_package(LAPACK REQUIRED)

find_package(BISON REQUIRED)
find_package(FLEX REQUIRED)
#find_package(PNG  REQUIRED)
#find_package(X11  REQUIRED)
find_package(MPI  REQUIRED)

file(MAKE_DIRECTORY ${tmp_man_pages_dir})





If (NOT MPI_C_INCLUDE_PATH)
 # cmake doesn't find mpi from openmpi it seems.
 # We search for it ourselves
  find_path(MY_INC_DIR mpi.h PATH_SUFFIXES usr/lib/openmpi/include include/openmpi)
  if (MY_INC_DIR) 
    set(MPI_C_INCLUDE_PATH ${MY_INC_DIR})
  elseif()
    message(FATAL_ERROR "In prime-trunk/src/cxx/CMakeLists.txt culd not find mpi.h")
  endif()
endif()


if (NOT MPI_C_LIBRARIES)
  message(fatal_error "Could not find mpi C libraries")
endif()


if (NOT MPI_CXX_LIBRARIES)
  message(fatal_error "Could not find mpi CXX libraries")
endif()



if (NOT MPI_CXX_INCLUDE_PATH)
 # cmake doesn't find mpi from openmpi it seems.
 # We search for it ourselves

                                                  #lib/openmpi/include/openmpi/ompi/mpi/cxx
  find_path(MY_INC_CXX_DIR mpicxx.h PATH_SUFFIXES usr/lib/openmpi/include/openmpi/ompi/mpi/cxx   include/openmpi/openmpi/ompi/mpi/cxx)
  if (MY_INC_CXX_DIR) 
    set(MPI_CXX_INCLUDE_PATH ${MY_INC_CXX_DIR})
  elseif()
    message(FATAL_ERROR "In prime-trunk/src/cxx/CMakeLists.txt culd not find mpicxx.h")
  endif()
endif()

#    message(FATAL_ERROR "rwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww ${MPI_CXX_INCLUDE_PATH}")

#include_directories( /usr/lib/openmpi/include/openmpi/ompi/mpi/cxx )
#include_directories( /usr/lib/openmpi/include )


include_directories(${MPI_C_INCLUDE_PATH})
include_directories(${MPI_CXX_INCLUDE_PATH})
include_directories(${MPI_CXX_INCLUDE_PATH}/ompi/mpi/cxx)

set(primexml_namespace http://prime.sbc.su.se/primexml/1)

if(NOT prime_dynamic) 
  set(Boost_USE_STATIC_LIBS   ON)

else()
set(Boost_USE_STATIC_RUNTIME OFF)
  set(Boost_USE_STATIC_LIBS   OFF)

endif()

set(Boost_USE_MULTITHREADED ON)

#set(Boost_ADDITIONAL_VERSIONS "1.46.1.1" "1.46")
#find_package( Boost 1..0 COMPONENTS date_time filesystem system ... )




find_package(Boost 1.40.0 COMPONENTS mpi serialization REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
#message("Boost inc dir ${Boost_INCLUDE_DIRS}")


find_package(LibXml2 REQUIRED)
include_directories( ${LIBXML2_INCLUDE_DIR} )
add_definitions( ${LIBXML2_DEFINITIONS} )


set(CMAKE_INCLUDE_CURRENT_DIR ON)





#============================================================================
# DOCUMENTATION AND DOXYGEN
#============================================================================

if(BUILD_DOCUMENTATION)
  find_package(Doxygen REQUIRED)
  file(GLOB_RECURSE sourcefiles "*.cc"  "*.c" "*.hh" "*.h" )
  set(doxygenconf ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
  set(doxygenoutputdir ${CMAKE_CURRENT_BINARY_DIR}/doxygen)
  configure_file( Doxyfile.cmake ${doxygenconf} @ONLY)
  add_custom_command(OUTPUT "${doxygenoutputdir}/html/index.html"
    COMMAND ${DOXYGEN_EXECUTABLE} ${doxygenconf} 
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
    DEPENDS ${FILES} ${doxygenconf}
  )
  add_custom_target(doxygen ALL DEPENDS "${doxygenoutputdir}/html/index.html")
  install(DIRECTORY ${doxygenoutputdir} DESTINATION share/doc/PrIME PATTERN ".svn" EXCLUDE )
endif()


#============================================================================
# INCLUDE DIRECTORIES
#============================================================================

include_directories( ${CMAKE_SOURCE_DIR}/src/cxx/libraries/prime )

# We include this directory e.g. for platform-dependent auto-generated includes
# placed in the build dir
include_directories( ${CMAKE_BINARY_DIR}/src/cxx/libraries/prime )

#include_directories( ${CMAKE_SOURCE_DIR}/src/cxx/libraries/sfile )
# actually sfile seems to be included like this: #include "sfile/sfile.h" 
# /Someone (Erik?)
#
# I think this is because '..../cxx/libraries' is set as an include directory,
# which by the way seems unnecessary.
# Right now you could also type, for instance, #include "prime/Tree.hh" and it would work.
# /Peter

include_directories( ${CMAKE_SOURCE_DIR}/src/cxx/libraries )


#============================================================================
# GENERAL BUILD FLAGS
# Examples when running cmake:
#   Default and debug flags:   "cmake -D CMAKE_BUILD_TYPE=Debug ..."
#   Default and release flags: "cmake -D CMAKE_BUILD_TYPE=Release ..."
#============================================================================

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wreorder -Wall -fexceptions")
if( ${CMAKE_CXX_COMPILER} MATCHES "icpc" )
    # Remove annoying Intel warnings.
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd383 -wd869 -wd981")
endif( ${CMAKE_CXX_COMPILER} MATCHES "icpc" )
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -funroll-loops -DNDEBUG")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fexceptions")
#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")


#============================================================================
# PRIME BEHAVIOUR FLAGS
# Note: All of these should be made into settings within the source
#       code -- remember: defining behaviour with ifdefs is bad style!
# Important note: Default is specified with ON/OFF in option definition.
#                 Notify the other developers if you check in changes.
# Example when running cmake: "cmake -D ENABLE_MY_OPTION=ON ..."
#============================================================================

option(ENABLE_PERTURBED_NODE "Speeds up calculation of SubstitutionLike.
  This is meaningful when, in some iterations, parameters are perturbed that
  do not affect or only affects part of the tree. Note! When using this
  speed-up, all classes that perturb a Tree in som way MUST set
  Tree::perturbed_node properly, else SubstLike will not be correctly
  calculated!! Look at example code in EdgeRateMCMC_common or
  ReconciliationTimeMCMC. /bens
" ON)
option(ENABLE_PERTURBED_TREE "Speeds up calculation of SubstitutionLike.
  NOTE! Currently only works when the tree root and 'topology' not change
  between iterations.
" OFF)
option(ENABLE_ONLY_ONE_TIMESAMPLE "Is not really an optimization, but
  does  speed things up. 
" ON)
# joelgs: The following are now handled with enums in subclasses of
# EdgeWeightModel. Thank god. Default is in most cases option off.
# The first two have been merged into one since they mean the same thing.
#option(ENABLE_INCLUDE_ROOT_RATE "Enables separate perturbation of the two
#  edges going out from the root in EdgeRateMCMC_common. If not enabled,
#  only one of them will be perturbed. Don't enable simultaneously with
#  ENABLE_FIX_ROOT_EDGES_RATE. Note: Don't confuse with similarly named
#  ENABLE_ROOT_RATES.
#" OFF)
#option(ENABLE_INCLUDE_ROOT_RATES "Enables separate perturbation of the two
#  edges going out from the root in VarRateModel and EdgeWeightMCMC. If
#  not enabled, only one of them will be perturbed. Don't enable
#  simultaneously with ENABLE_FIX_ROOT_EDGES_RATE. Note: Don't confuse with
#  similarly named ENABLE_INCLUDE_ROOT_RATE.
#" OFF)
#option(ENABLE_FIX_ROOT_EDGES_RATE "Turns off perturbation of the edges
#  going out from the root in various models. Don't enable simultaneously
#  with ENABLE_INCLUDE_ROOT_RATE or ENABLE_INCLUDE_ROOT_RATES.
#" OFF)
option(ENABLE_USE_EMBEDDED_PARAMS "Perturbs the embedded parameters
  (currently only variance) of EdgeRateMCMC -- test to see if this improves
  convergence rate.
" OFF)


if(ENABLE_PERTURBED_NODE)
    add_definitions("-DPERTURBED_NODE")
endif()
if(ENABLE_PERTURBED_TREE)
    add_definitions("-DPERTURBED_TREE")
endif()
if(ENABLE_ONLY_ONE_TIMESAMPLE)
    add_definitions("-DONLY_ONE_TIMESAMPLE")
endif()
if(ENABLE_INCLUDE_ROOT_RATE)
    add_definitions("-DINCLUDE_ROOT_RATE")
endif()
if(ENABLE_INCLUDE_ROOT_RATES)
    add_definitions("-DINCLUDE_ROOT_RATES")
endif()
if(ENABLE_FIX_ROOT_EDGES_RATE)
    add_definitions("-DFIX_ROOT_EDGES_RATE")
endif()
if(ENABLE_USE_EMBEDDED_PARAMS)
    add_definitions("-DUSE_EMBEDDED_PARAMS")
endif()


#===========================================================================
# PRIME DEBUG FLAGS
# Note: NDEBUG, which turns off assertions etc., is enabled by default in
#       the release build.
# Important note: Default is specified with ON/OFF in option definition.
#                 Notify the other developers if you check in changes.
# Example when running cmake: "cmake -D ENABLE_MY_OPTION=ON ..."
#===========================================================================

option(ENABLE_DEBUG_BRANCHSWAPPING    "Activate debugging of BranchSwapping."                  OFF)
option(ENABLE_DEBUG_DP                "Activate debugging of GuestTreeModel."                  OFF)
option(ENABLE_DEBUG_SAMPLING          "Activate debugging of ReconciliationSampler."           OFF)
option(ENABLE_DEBUG_SHOW_CONSTRUCTORS "Write constructor names as they are invoked."           OFF)
option(ENABLE_SHOW_LAMBDA             "?"                                                      OFF)
option(ENABLE_DEBUG_SHOWPROBS         "Output a likelihood for all models."                    OFF)
option(ENABLE_ABORT_ERRORS            "Stops when AnError is created, before throwing."        OFF)
option(ENABLE_YYDEBUG_EQ_1            "This is for NHXparse.y."                                OFF)
option(ENABLE_TIME_DEBUGGING          "?"                                                      OFF)
option(ENABLE_DEBUG_PARAMS            "Prints out all parameters when params4os() is called."  OFF)
option(ENABLE_DISTR_DEBUG             "For PVM-related debugging."                             OFF)
option(ENABLE_DEBUG_PROPOSAL          "Used in SimpleMCMC."                                    OFF)


if(ENABLE_DEBUG_BRANCHSWAPPING)
    add_definitions("-DDEBUG_BRANCHSWAPPING")
endif()
if(ENABLE_DEBUG_DP)
    add_definitions("-DDEBUG_DP")
endif()
if(ENABLE_DEBUG_SAMPLING)
    add_definitions("-DDEBUG_SAMPLING")
endif()
if(ENABLE_DEBUG_SHOW_CONSTRUCTORS)
    add_definitions("-DDEBUG_SHOW_CONSTRUCTORS")
endif()
if(ENABLE_SHOW_LAMBDA)
    add_definitions("-DSHOW_LAMBDA")
endif()
if(ENABLE_DEBUG_SHOWPROBS)
    add_definitions("-DDEBUG_SHOWPROBS")
endif()
if(ENABLE_ABORT_ERRORS)
    add_definitions("-DABORT_ERRORS")
endif()
if(ENABLE_YYDEBUG_EQ_1)
    add_definitions("-DYYDEBUG=1")
endif()
if(ENABLE_TIME_DEBUGGING)
    add_definitions("-DTIME_DEBUGGING")
endif()
if(ENABLE_DEBUG_PARAMS)
    add_definitions("-DDEBUG_PARAMS")
endif()
if(ENABLE_DISTR_DEBUG)
    add_definitions("-DDISTR_DEBUG")
endif()
if(ENABLE_DEBUG_PROPOSAL)
    add_definitions("-DDEBUG_PROPOSAL")
endif()


#===========================================================================
# PLATFORM OPTIMIZATION FLAGS
# Note: Off by default.
# Example when running cmake: "cmake -D ENABLE_MY_OPTIMIZATION=ON ..."
#===========================================================================

if(CMAKE_COMPILER_IS_GNUCXX)
    if(OPTIMIZE_FOR_FERLIN)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=core2 -mfpmath=sse")
    endif(OPTIMIZE_FOR_FERLIN)
    if(OPTIMIZE_FOR_DELL_DIM_5000)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=prescott -mfpmath=sse")
    endif(OPTIMIZE_FOR_DELL_DIM_5000)
endif(CMAKE_COMPILER_IS_GNUCXX)

#============================================================================
# PROFILING
#============================================================================

list(APPEND CMAKE_BUILD_TYPES Profile)
set(CMAKE_C_FLAGS_PROFILE "-pg -g")
set(CMAKE_CXX_FLAGS_PROFILE "-pg -g")
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-pg")


#============================================================================
# C++ COMPILATION AND LINKING FLAGS
# Note: duma and efence checks writing to unallocated memory
#============================================================================

if(CMAKE_HOST_APPLE)
  if(ENABLE_PROFILING)
    SET(ENV{DYLD_IMAGE_SUFFIX} "_profile")
  endif()
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework accelerate -bind_at_load")
else()
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
endif()

# CMAKE_C_FLAGS_DEBUG 
# SET_TARGET_PROPERTIES(target_name PROPERTIES COMPILE_FLAGS -pg LINK_FLAGS -pg)



#============================================================================
# LAPACK
#============================================================================
#      default             Real typedef to double and the classes LA_* use 
#                          double precision LAPACK functions
#      LA_SINGLE_PRECISION Real typedef to float and LA_* use single 
#                          precision LAPACK functions

########## LA_PRECISION = #-DLA_SINGLE_PRECISION



#===========================================================================
# The prime_add_tests macro that is to be used in
# src/cxx/applications/*/CMakeLists.txt and
# src/cxx/tools/*/CMakeLists.txt for automatic testing
#===========================================================================

macro(prime_add_tests tests_dir)
  get_target_property(program_exe ${programname_of_this_subdir} LOCATION)
  file(GLOB tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${tests_dir}/test*[^~])
  foreach(i ${tests})
    get_filename_component(test ${i} NAME)
    configure_file(${i}/command.sh.cmake  ${CMAKE_CURRENT_BINARY_DIR}/${i}/command.sh @ONLY)
# Erik Sjolund trying to build for Debian Squeeze...
#    add_test(NAME ${programname_of_this_subdir}_${test} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${i} COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/${i}/command.sh ${i})
  endforeach()
endmacro()


add_subdirectory(libraries/prime)
add_subdirectory(libraries/sfile)




file(GLOB applications ${CMAKE_CURRENT_SOURCE_DIR}/applications/[^.]*[^~])
file(GLOB tools ${CMAKE_CURRENT_SOURCE_DIR}/tools/[^.]*[^~])
file(GLOB test_applications ${CMAKE_CURRENT_SOURCE_DIR}/test_applications/[^.]*[^~])


# These programs have build errors
set(EXCLUDE_MAPDP on)
set(EXCLUDE_PRIMEGSRORTHO on)
set(EXCLUDE_PRIMECT on)
#set(EXCLUDE_PRIMEORTHOLOGY on)
set(EXCLUDE_ORTHOPROJECT on)
set(EXCLUDE_TEST_GSR_ORTHOLOGY on)
set(EXCLUDE_TEST_PHYLODAG on)
set(EXCLUDE_SBP on)
set(EXCLUDE_SCRAMBLE_TREE on)
set(EXCLUDE_ORTHO_PARSE on)
set(EXCLUDE_ROOT2LEAVES on)
set(EXCLUDE_RECONCILIATION2TAB on)
set(EXCLUDE_BEEPGENERATETREE on)
set(EXCLUDE_SHOWHOST on)

# I removed the dependency on Codesynthesis XSD whose license might not be compatible with neither GPLv2 nor GPLv3.
# http://programmers.stackexchange.com/questions/157265/can-i-use-codesynthesis-xsd-c-tree-mapping-together-with-a-gplv3-licensed-li
# As a consequence of removing the dependency on Codesynthesis XSD, the tool genGSR can't be built. /Erik Sjolund 
set(EXCLUDE_GENGSR on)


# lsdcombine depends on many packages, for instance libx11.
# lsdcombine builds just fine but we exclude it because
# we want to build an Ubuntu package that has fewer dependencies.

set(EXCLUDE_LSDCOMBINE on)

if(official_binary_packaging)
  set(all_tools_and_applications 
       ${CMAKE_CURRENT_SOURCE_DIR}/applications/primeGEM
       ${CMAKE_CURRENT_SOURCE_DIR}/applications/primeDTLSR
       ${CMAKE_CURRENT_SOURCE_DIR}/applications/primeDLRS
       ${CMAKE_CURRENT_SOURCE_DIR}/tools/treesize
       ${CMAKE_CURRENT_SOURCE_DIR}/tools/showtree
       ${CMAKE_CURRENT_SOURCE_DIR}/tools/reconcile
       ${CMAKE_CURRENT_SOURCE_DIR}/tools/reroot
       ${CMAKE_CURRENT_SOURCE_DIR}/tools/tree2leafnames
       ${CMAKE_CURRENT_SOURCE_DIR}/tools/chainsaw
     )
else()
  set(all_tools_and_applications ${applications} ${tools} ${test_applications})
endif()

foreach(i ${all_tools_and_applications})
 get_filename_component(progname ${i} NAME)
 string(TOUPPER ${progname} progname_uppercase)
 if(NOT EXCLUDE_${progname_uppercase})
    set(ENV{PATH} "ENV{PATH}:${i}")
    add_subdirectory(${i})
 elseif(INCLUDE_${progname_uppercase})
    set(ENV{PATH} "ENV{PATH}:${i}")
    add_subdirectory(${i})
 endif()
endforeach(i)
