# -*- mode: cmake -*-

# It is important to match MPQC compiler toolchain and Boost toolchain
# otherwise strange things may happen
# The default is to build Boost to match toolchain in order to avoid issues.
# In case one knows exactly what compiler/Boost are used,
# set BOOST to Boost installation root, e.g. /usr/local

if (DEFINED BOOST)

  set(Boost_USE_STATIC_LIBS ON)
  #set(Boost_USE_MULTITHREADED OFF)
  #set(Boost_USE_STATIC_RUNTIME OFF)

  set(BOOST_ROOT ${BOOST})
  set(Boost_NO_SYSTEM_PATHS TRUE)
  set(Boost_DETAILED_FAILURE_MSG TRUE)
  find_package(Boost 1.48 COMPONENTS thread system )
  # COMPONENTS thread ${pythonlibs} system

  # reset Boost_LIBRARIES
  set(Boost_LIBRARIES "")

  if (NOT Boost_THREAD_FOUND)
    message("** Boost Thread not found")
    set(Boost_FOUND FALSE)
  endif()

  if (NOT Boost_SYSTEM_FOUND)
    message("** Boost System not found")
    set(Boost_FOUND FALSE)
  endif()

  if (NOT Boost_FOUND)
    message(FATAL_ERROR "Necessary Boost install not found in ${BOOST_ROOT}")
  endif()  
   
  list(APPEND Boost_LIBRARIES ${Boost_THREAD_LIBRARY})
  list(APPEND Boost_LIBRARIES ${Boost_SYSTEM_LIBRARY})
  if (Boost_PYTHON_FOUND)
    list(APPEND Boost_LIBRARIES ${Boost_PYTHON_LIBRARY})
  endif()

  set(HAVE_BOOST ON)

elseif (MPQC_EXPERT)

  message("** BOOST was not explicitly set")
  message("** Downloading and building Boost is explicitly disabled in EXPERT mode")
  if (MPQC_UNITTEST)
    message(FATAL_ERROR "No unit testing in expert mode")
  endif()

else()

  set(EXTERNAL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/external)
  set(EXTERNAL_BUILD_DIR ${PROJECT_BINARY_DIR}/external/build)

  set(BOOST_URL
    http://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2)
  set(BOOST_URL_HASH MD5=d6eef4b4cacb2183f2bf265a5a03a354)
  #set(BOOST_URL ${EXTERNAL_SOURCE_DIR}/boost_1_57_0.tar.bz2)
  #set(BOOST_URL_HASH MD5=1be49befbdd9a5ce9def2983ba3e7b76)

  message("** Will build Boost from ${BOOST_URL}")

  if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
    set(BOOST_TOOLSET gcc)
  endif()

  # gcc/clang seem to use same config under Darwin
  if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    set(BOOST_TOOLSET darwin)
  endif()

  if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
    set(BOOST_TOOLSET clang)
  endif()

  if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel") 
    set(BOOST_TOOLSET intel)
  endif()

  set(BOOST_CONFIG "using ${BOOST_TOOLSET} : : ${CMAKE_CXX_COMPILER} : 
                    <cxxflags>\"${CMAKE_CXX_FLAGS}\"
                    <linkflags>\"${CMAKE_CXX_FLAGS}\" ;\n")

  if (EXISTS ${EXTERNAL_BUILD_DIR}/boost/user-config.jam)
    file(READ ${EXTERNAL_BUILD_DIR}/boost/user-config.jam BOOST_CONFIG_JAM)
    if (NOT ("${BOOST_CONFIG}" STREQUAL "${BOOST_CONFIG_JAM}"))
      message(STATUS "Boost needs to be rebuilt")
      file(REMOVE ${EXTERNAL_BUILD_DIR}/boost/src/boost-stamp/boost-build)
    endif()
  endif()
  file(WRITE ${EXTERNAL_BUILD_DIR}/boost/user-config.jam "${BOOST_CONFIG}")

  set(libraries "thread,system")
  if (HAVE_PYTHON)
    set (libraries "${libraries},python")
  endif()
  if (MPQC_UNITTEST)
    set (libraries "${libraries},test")
  endif()

  # Check for apple clang (assuming here it's 5.1 or later)
  execute_process( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string )
  string(REGEX MATCH "Apple LLVM version" APPLECLANG_NEEDS_BOOST_PATCH ${clang_full_version_string})
  if(APPLECLANG_NEEDS_BOOST_PATCH)
    message(STATUS "Detected recent Apple Clang, will patch boost")
    
    ExternalProject_Add(
      boost
      PREFIX ${EXTERNAL_BUILD_DIR}/boost
      URL ${BOOST_URL}
      URL_HASH ${BOOST_URL_HASH}
    # -----Patch for clang 3.4 --------
      UPDATE_COMMAND ""
      PATCH_COMMAND cp ${PROJECT_SOURCE_DIR}/external/patch/boost_clang34_cas128strong.hpp ${EXTERNAL_BUILD_DIR}/boost/src/boost/boost/atomic/detail/cas128strong.hpp && 
      PATCH_COMMAND cp ${PROJECT_SOURCE_DIR}/external/patch/boost_clang34_gcc-atomic.hpp ${EXTERNAL_BUILD_DIR}/boost/src/boost/boost/atomic/detail/gcc-atomic.hpp
    # ------------
      BUILD_IN_SOURCE 1
      CONFIGURE_COMMAND ./bootstrap.sh --with-libraries=${libraries}
      BUILD_COMMAND ./b2 --user-config=${EXTERNAL_BUILD_DIR}/boost/user-config.jam
      --toolset=${BOOST_TOOLSET}
      --link=static
      INSTALL_COMMAND ""
      )
  else(APPLECLANG_NEEDS_BOOST_PATCH)
    ExternalProject_Add(
      boost
      PREFIX ${EXTERNAL_BUILD_DIR}/boost
      URL ${BOOST_URL}
      URL_HASH ${BOOST_URL_HASH}
      BUILD_IN_SOURCE 1
      CONFIGURE_COMMAND ./bootstrap.sh --with-libraries=${libraries}
      BUILD_COMMAND ./b2 --user-config=${EXTERNAL_BUILD_DIR}/boost/user-config.jam
      --toolset=${BOOST_TOOLSET}
      --link=static
      INSTALL_COMMAND ""
      )
  endif(APPLECLANG_NEEDS_BOOST_PATCH)


  add_dependencies(External boost)

  set(Boost_INCLUDE_DIRS ${EXTERNAL_BUILD_DIR}/boost/src/boost)
  set(Boost_LIBRARY_DIR ${EXTERNAL_BUILD_DIR}/boost/src/boost/stage/lib)

  list(APPEND Boost_LIBRARIES ${Boost_LIBRARY_DIR}/libboost_thread.a)
  list(APPEND Boost_LIBRARIES ${Boost_LIBRARY_DIR}/libboost_system.a)
  if (HAVE_PYTHON)
    list(APPEND Boost_LIBRARIES ${Boost_LIBRARY_DIR}/libboost_python.a)
  endif()
  if (MPQC_UNITTEST)
    list(APPEND Boost_UNITTEST_LIBRARIES ${Boost_LIBRARY_DIR}/libboost_unit_test_framework.a)
  endif()

  set(HAVE_BOOST ON)
  
endif()

if (HAVE_BOOST)
  include_directories(${Boost_INCLUDE_DIRS})
  message(STATUS "Boost include dir: ${Boost_INCLUDE_DIRS}")
  message(STATUS "Boost libraries: ${Boost_LIBRARIES}")
  if (MPQC_UNITTEST)
    message(STATUS "Boost unit testing libraries: ${Boost_UNITTEST_LIBRARIES}")
  endif()
endif()

