########################################
# BEGIN_COPYRIGHT
#
# Copyright (C) 2008-2018 SciDB, Inc.
# All Rights Reserved.
#
# SciDB is free software: you can redistribute it and/or modify
# it under the terms of the AFFERO GNU General Public License as published by
# the Free Software Foundation.
#
# SciDB is distributed "AS-IS" AND WITHOUT ANY WARRANTY OF ANY KIND,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
# NON-INFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. See
# the AFFERO GNU General Public License for the complete license terms.
#
# You should have received a copy of the AFFERO GNU General Public License
# along with SciDB.  If not, see <http://www.gnu.org/licenses/agpl-3.0.html>
#
# END_COPYRIGHT
########################################
message(STATUS "****************** BEGIN CMakeLists.txt ******************")

cmake_minimum_required(VERSION 2.8)

if(EXISTS "/usr/bin/g++-4.9")
  set(CMAKE_C_COMPILER "/usr/bin/gcc-4.9")
  set(MPICH_CC "/usr/bin/gcc-4.9")
  set(CMAKE_CXX_COMPILER "/usr/bin/g++-4.9")
  set(MPICH_CXX "/usr/bin/g++-4.9")
  set(CMAKE_Fortran_COMPILER "/usr/bin/gfortran-4.9")
  set(MPICH_FC "/usr/bin/gfortran-4.9")
elseif(EXISTS "/opt/rh/devtoolset-3/root/usr/bin/g++")
  set(CMAKE_C_COMPILER "/opt/rh/devtoolset-3/root/usr/bin/gcc")
  set(MPICH_CC "/opt/rh/devtoolset-3/root/usr/bin/gcc")
  set(CMAKE_CXX_COMPILER "/opt/rh/devtoolset-3/root/usr/bin/g++")
  set(MPICH_CXX "/opt/rh/devtoolset-3/root/usr/bin/g++")
  set(CMAKE_Fortran_COMPILER "/opt/rh/devtoolset-3/root/usr/bin/gfortran")
  set(MPICH_FC "/opt/rh/devtoolset-3/root/usr/bin/gfortran")
else()
  message(FATAL_ERROR "SCIDBTRUNK/CMakeLists.txt: cannot find g++ 4.9")
endif()

project(SciDB C CXX Fortran)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)


#
# configure DISTRO_NAME_VERSION
#
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
include(LinuxDistroVersion)
message(STATUS "DISTRO_NAME_VER is " ${DISTRO_NAME_VER})

if ("${DISTRO_NAME}" STREQUAL "Ubuntu")
  # Ubuntu/Debian makes uses a suffix to mark the
  # differing implementation of MPI.
  # e.g.
  # /usr/bin/mpicxx.mpich, /usr/bin/mpicxx.openmpi"
  #
  set(MPI_CHECK_PATH_ADDITION "")
  set(MPI_CHECK_SUFFIX ".FLAVOR")
elseif ("${DISTRO_NAME}" STREQUAL "CentOS")
  # CentOS uses a different path location for the
  # differing implementations of MPI:
  # e.g.
  # /usr/lib64/mpich/bin/mpicxx, /usr/lib64/openmpi/bin/mpicxx, 
  set(MPI_CHECK_PATH_ADDITION "lib64/FLAVOR/")
  set(MPI_CHECK_SUFFIX "")
else()
  message(WARNING  "Unsupported OS -- ${LSB_RELEASE_ID_SHORT}")
endif()
message(STATUS "  ----------- Looking for /usr/${MPI_CHECK_PATH_ADDITION}bin/XXXX${MPI_CHECK_SUFFIX}")

# Add mpich2scidb as a flavor
foreach (flavor "mpich2scidb" "mpich" "openmpi")
  if (NOT "${MPI_CXX_FOUND}")
    string(REGEX REPLACE "FLAVOR" ${flavor} MPI_CHECK_PATH "/usr/${MPI_CHECK_PATH_ADDITION}bin")
    string(REGEX REPLACE "FLAVOR" ${flavor} MPI_SUFFIX "${MPI_CHECK_SUFFIX}")
    set(MPI_CXX_COMPILER "${MPI_CHECK_PATH}/mpicxx${MPI_SUFFIX}")
    set(MPI_Fortran_COMPILER "${MPI_CHECK_PATH}/mpif77${MPI_SUFFIX}")
    set(MPI_C_COMPILER "${MPI_CHECK_PATH}/mpicc${MPI_SUFFIX}")
    message(STATUS "        ------- MPI_CXX_COMPILER = ${MPI_CXX_COMPILER}")
    message(STATUS "        ------- MPI_Fortran_COMPILER = ${MPI_Fortran_COMPILER}")
    message(STATUS "        ------- MPI_C_COMPILER = ${MPI_C_COMPILER}")

    find_package(MPI)
    if("${MPI_CXX_FOUND}")
      set(MPI_FLAVOR "${flavor}")
      execute_process(COMMAND readlink -f ${MPI_CXX_COMPILER} OUTPUT_VARIABLE MPI_CXX_COMPILER_FULL_PATH  OUTPUT_STRIP_TRAILING_WHITESPACE)
      message(STATUS " ------- MPI_CXX_COMPILER_FULL_PATH = ${MPI_CXX_COMPILER_FULL_PATH}")
      string(REGEX REPLACE "/bin/[^/]*$" "" MPI_INST_DIR "${MPI_CXX_COMPILER_FULL_PATH}")
      message(STATUS " ------- MPI_INST_DIR = ${MPI_INST_DIR} ---")
      message(STATUS " ------- MPI_FLAVOR = ${MPI_FLAVOR} ---")
    endif()
  endif()
endforeach()

message(STATUS "MPI_CXX_FOUND = ${MPI_CXX_FOUND}")
message(STATUS "MPI_CXX_COMPILER = ${MPI_CXX_COMPILER}")
message(STATUS "MPI_CXX_COMPILE_FLAGS = ${MPI_CXX_COMPILE_FLAGS}")
message(STATUS "MPI_CXX_INCLUDE_PATH = ${MPI_CXX_INCLUDE_PATH}")
message(STATUS "MPI_CXX_LINK_FLAGS = ${MPI_CXX_LINK_FLAGS}")
message(STATUS "MPI_CXX_LIBRARIES = ${MPI_CXX_LIBRARIES}")

message(STATUS "MPI_C_FOUND = ${MPI_C_FOUND}")
message(STATUS "MPI_C_COMPILER = ${MPI_C_COMPILER}")
message(STATUS "MPI_C_COMPILE_FLAGS = ${MPI_C_COMPILE_FLAGS}")
message(STATUS "MPI_C_INCLUDE_PATH = ${MPI_C_INCLUDE_PATH}")
message(STATUS "MPI_C_LINK_FLAGS = ${MPI_C_LINK_FLAGS}")
message(STATUS "MPI_C_LIBRARIES = ${MPI_C_LIBRARIES}")

message(STATUS "MPI_Fortran_FOUND = ${MPI_Fortran_FOUND}")
message(STATUS "MPI_Fortran_COMPILER = ${MPI_Fortran_COMPILER}")
message(STATUS "MPI_Fortran_COMPILE_FLAGS = ${MPI_Fortran_COMPILE_FLAGS}")
message(STATUS "MPI_Fortran_INCLUDE_PATH = ${MPI_Fortran_INCLUDE_PATH}")
message(STATUS "MPI_Fortran_LINK_FLAGS = ${MPI_Fortran_LINK_FLAGS}")
message(STATUS "MPI_Fortran_LIBRARIES = ${MPI_Fortran_LIBRARIES}")

file(READ "${CMAKE_SOURCE_DIR}/version" _SCIDB_VERSION)
STRING(REGEX MATCH "^([0-9]*)\\.([0-9]*)\\.([0-9]*).*$" __SCIDB_VERSION "${_SCIDB_VERSION}")
if(NOT __SCIDB_VERSION)
    message(FATAL_ERROR "Can not parse 'version' file")
endif()
set(SCIDB_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(SCIDB_VERSION_MINOR "${CMAKE_MATCH_2}")
set(SCIDB_VERSION_PATCH "${CMAKE_MATCH_3}")

set(SCIDB_VERSION "${SCIDB_VERSION_MAJOR}.${SCIDB_VERSION_MINOR}.${SCIDB_VERSION_PATCH}")
set(SCIDB_SHORT_VERSION "${SCIDB_VERSION_MAJOR}.${SCIDB_VERSION_MINOR}")

set(PACKAGE_NAME "scidb-${SCIDB_SHORT_VERSION}")

if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  set(CMAKE_INSTALL_PREFIX "/opt/scidb/${SCIDB_SHORT_VERSION}" CACHE STRING "Install path" FORCE)
  message(STATUS "CMAKE_INSTALL_PREFIX Initialized to default setting to: " ${CMAKE_INSTALL_PREFIX})
else(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  message(STATUS "CMAKE_INSTALL_PREFIX not Initialized to default keeping: " ${CMAKE_INSTALL_PREFIX})
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Assert) # Default value
endif(NOT CMAKE_BUILD_TYPE)

find_package(Git)
if(GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
    # Get revision from git working copy
    execute_process(COMMAND ${GIT_EXECUTABLE} rev-list --abbrev=8  --abbrev-commit -1 HEAD
        OUTPUT_VARIABLE SCIDB_REVISION
        RESULT_VARIABLE GIT_EXEC_RES
        OUTPUT_STRIP_TRAILING_WHITESPACE
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})

    string(COMPARE NOTEQUAL ${GIT_EXEC_RES} 0 GIT_EXEC_RES)
    if(${GIT_EXEC_RES})
        MESSAGE(FATAL_ERROR "Can not invoke GIT ${GIT_EXECUTABLE}. Check binary!")
    endif()

    message(STATUS "Reading revision from git: ${SCIDB_REVISION}")

    file(WRITE "${CMAKE_BINARY_DIR}/revision" ${SCIDB_REVISION})
endif()
if(NOT SCIDB_REVISION AND EXISTS "${CMAKE_SOURCE_DIR}/revision")
    # Get version from plain source tarball/directory
    file(READ "${CMAKE_SOURCE_DIR}/revision" SCIDB_REVISION)
    string(STRIP ${SCIDB_REVISION} SCIDB_REVISION)
    message(STATUS "Reading revision from file: ${SCIDB_REVISION}")
endif()
if(NOT SCIDB_REVISION)
    message(FATAL_ERROR "Can not fetch working copy version and can't find revision file.")
endif()

set(SCIDB_VERSION "${SCIDB_VERSION}.${SCIDB_REVISION}")

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

message(STATUS "Build type (use -DCMAKE_BUILD_TYPE=[Assert]/RelWithDebInfo/Debug/CC/Profile/Release/Valgrind): ${CMAKE_BUILD_TYPE}")

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Assert) # Default value for end user who want to install scidb from sources
endif(NOT CMAKE_BUILD_TYPE)

#
# configure compile and link flags
#
include(CMakeBuildFlags.cmake)

set(GENERAL_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(GENERAL_TEST_DIRECTORY "${CMAKE_BINARY_DIR}/tests/basic")
set(GENERAL_HARNESSTEST_DIRECTORY "${CMAKE_BINARY_DIR}/tests/harness")

set(PYTHON_SAMPLE_DIRECTORY "${CMAKE_BINARY_DIR}/bin/pythonexamples")

################################################################
# Setting DT_RUNPATH in the elf header:
#
# A. review of library resolution steps
#
# From "man ld.so":
##The shared libraries needed by the program are searched for in the following order:
##
## 1. (ELF only) Using the directories specified in the DT_RPATH dynamic section attribute of the binary if
## present and DT_RUNPATH attribute does not exist. Use of DT_RPATH is deprecated.
##
## 2. Using the environment variable LD_LIBRARY_PATH. Except if the executable is a set-user-ID/set-group-ID
## binary, in which case it is ignored.
##
## 3. (ELF only) Using the directories specified in the DT_RUNPATH dynamic section attribute of the binary if
## present.
##
## 4. From the cache file /etc/ld.so.cache which contains a compiled list of candidate libraries previously
## found in the augmented library path. If, however, the binary was linked with the -z nodeflib linker
## option, libraries in the default library paths are skipped.
##
## 5. In the default path /lib, and then /usr/lib. If the binary was linked with the -z nodeflib linker
## option, this step is skipped.
#
# NOTE:
#  a. We set DT_RUNPATH so (1) does not apply.
#  b. If the user sets LD_LIBRARY_PATH, then (2) applies, and it is the user's repsonsibility.
#  c. Resolution is normally via step (3).
#  d. Only if that fails, (5) and (6) do apply [we do not use -z nodeflib at this time.]
#
# B. $ORIGIN
#
# From "man ld.so":
##RPATH TOKEN EXPANSION
## The runtime linker provides a number of tokens that can be used in an rpath specification (DT_RPATH or DT_RUNPATH).
##
## $ORIGIN
## ld.so understands the string $ORIGIN (or equivalently ${ORIGIN}) in an rpath specification to mean the directory
## containing the application executable. Thus, an application located in somedir/app could be compiled with
## gcc -Wl,-rpath,'$ORIGIN/../lib' so that it finds an associated shared library in somedir/lib no matter where
## somedir is located in the directory hierarchy.
#
# NOTE:
#   We use $ORIGIN to find the locations
#      ../scidb/<version>/lib and
#      ../scidb/<version>/lib/scidb/plugins
#   from
#        either location above or
#      ../scidb/<version>/bin.
#
# by setting it to "$ORIGIN/../lib:$ORIGIN/../.."
#
#   And we use $ORIGIN/../plugins to find plugins from plugins
#
# NOTE:
#  this also allows resolution to ../scidb/<version>.  This will be fixed at a later point.
#
# C. CMAKE macros and the linker
#
# It should be noted that there is no command to the linker to set RUNPATH directly.
# Instead we set RPATH and pass --enable-new-dtags to the linker.
# The linker then sets DT_RUNPATH rather than DT_RPATH.
#
#  Setting CMAKE_SHARED_LINKER_FLAGS to "-Wl,--enable-new-dtags"
#    means CMAKE macros that set RPATH for shared objects results in RUNPATH being set.
#  Setting CMAKE_EXE_LINKER_FLAGS to "-Wl,--enable-new-dtags"
#    means CMAKE macros that set RPATH for programs results in RUNPATH being set.
#  Setting CMAKE_SKIP_BUILD_RPATH to FALSE
#    assures us that CMAKE sets RPATH at build time.
#  Setting CMAKE_BUILD_WITH_INSTALL_RPATH to TRUE tells CMAKE the object is built with the install time RPATH
#    (which for our purpose is the same as build time) so it will not re-instrument at install time.
#  Setting CMAKE_INSTALL_RPATH_USE_LINK_PATH to TRUE tells CMAKE to add any linkages that were used at build time
#    as absolute paths. This applies to boost objects in /opt/scidb/<version>/3rdparty/boost/lib.
#
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_INSTALL_RPATH "$ORIGIN/../plugins:$ORIGIN/../lib:$ORIGIN/../../")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-new-dtags")
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-new-dtags")

include(FindPkgConfig)
#
# CENTOS check
#
if(${DISTRO_NAME_VER} MATCHES "RedHat-6")
 message(FATAL_ERROR "We do not support RedHat build. Use CentOS instead")
endif()

#
# LIBRT config
#
find_package(LibRT REQUIRED)

#
# CITYHASH CONFIG
#
set(CITYHASH_ROOT /opt/scidb/${SCIDB_VERSION_MAJOR}.${SCIDB_VERSION_MINOR}/3rdparty/cityhash)
set(CityHash_NO_SYSTEM_PATHS TRUE)
set(CityHash_NO_CITYHASH_CMAKE TRUE)

find_package(CityHash REQUIRED system program_options serialization regex filesystem thread date_time)

if(NOT CityHash_FOUND)
 message(FATAL_ERROR "Could not find any version of cityhash")
endif(NOT CityHash_FOUND)

#
# BOOST CONFIG
#
set(BOOST_ROOT /opt/scidb/${SCIDB_VERSION_MAJOR}.${SCIDB_VERSION_MINOR}/3rdparty/boost)
set(Boost_NO_SYSTEM_PATHS TRUE)
set(Boost_NO_BOOST_CMAKE TRUE)

find_package(Boost REQUIRED system program_options serialization regex
                            filesystem thread date_time)

if(NOT Boost_FOUND)
 message(FATAL_ERROR "Could not find any version of boost (1.54 required)")
endif(NOT Boost_FOUND)

if(NOT (${Boost_MAJOR_VERSION} EQUAL 1 AND
        ${Boost_MINOR_VERSION} EQUAL 54))
 message(FATAL_ERROR "Could not find the required 1.54 version of boost")
endif(NOT (${Boost_MAJOR_VERSION} EQUAL 1 AND
           ${Boost_MINOR_VERSION} EQUAL 54))

#
# PROTOBUF CONFIG
#
# outputs PROTOBUF_LIBRARY, not _LIBRARIES as documented
find_package(Protobuf REQUIRED)
find_package(Log4CXX REQUIRED)
find_package(Doxygen)
find_package(LibPQXX REQUIRED)
find_package(LibPQ REQUIRED)

#
# configure CPPUNIT
# configure SWIG & PYTHON
# TODO: configuring of SWIG and PYTHON should be separated as
#       items should not be grouped by special platform handling
pkg_check_modules(CPPUNIT cppunit)

#SWIG-based python connector is temporarily disabled because it does not work with C++14. See #4745
#if (NOT WITHOUT_PYTHON_BINDING)
if(false)
    find_package(SWIG2 "2.0")
    find_package(PythonLibs)
    if (NOT SWIG2_FOUND OR NOT PYTHONLIBS_FOUND)
        message(FATAL_ERROR "SWIG 2 and Python headers required for building Python API bindings. You can set proper SWIG executable with argument -DSWIG_EXECUTABLE=/path/to/swig2.0")
    endif()
endif()

set(FLEX_MINIMAL_VERSION "2.5.35")
find_package(FLEX REQUIRED)
set(BISON_MINIMAL_VERSION "2.4")
find_package(BISON REQUIRED)
find_package(SED REQUIRED)
find_package(ZLIB REQUIRED)
find_package(BZip2 REQUIRED)
find_package(Threads REQUIRED)
find_package(PythonInterp REQUIRED)
find_package(EditLine REQUIRED)

#
# configure BLAS & LAPACK
#
# set BLA_VENDOR (see Find{BLAS,LAPACK}.cmake) to experiment
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)

#
# doc packages, not required
#
find_package(XsltProc)
find_package(Fop)
find_package(DocBook)
if(XSLTPROC_EXECUTABLE AND FOP_EXECUTABLE AND DOCBOOK_XSL_FILE)
    set(BUILD_USER_DOC 1)
else()
    set(BUILD_USER_DOC 0)
endif()

#
# Function Check
#
include(CheckFunctionExists)
check_function_exists(malloc_stats HAVE_MALLOC_STATS)

#
# INCLUDE DIRECTORIES
#
include_directories("${CMAKE_SOURCE_DIR}/src")
include_directories("${CMAKE_SOURCE_DIR}/include")
include_directories("${CMAKE_SOURCE_DIR}/utils")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/src")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/utils")
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
include_directories(${PROTOBUF_INCLUDE_DIR})
include_directories(${LOG4CXX_INCLUDE_DIRS})
include_directories(${LIBPQXX_INCLUDE_DIRS})
include_directories(${LIBPQ_INCLUDE_DIRS})
include_directories(${ZLIB_INCLUDE_DIRS})
include_directories(${BZIP2_INCLUDE_DIR})
include_directories(${READLINE_INCLUDE_DIRS})
include_directories("${CMAKE_SOURCE_DIR}/extern")

link_directories(${LIBPQXX_LIBRARY_DIRS})
link_directories(${LIBPQ_LIBRARY_DIRS})

# static link requires adding a few more libraries
set (LINK_APR_LIBS "")

#
# DEBUG symbols
#
set(DEBUG_SYMBOLS_DIRECTORY ".debug")
set(DEBUG_SYMBOLS_EXTENSION "${DEBUG_SYMBOLS_DIRECTORY}")

# TODO: should probably factor to a xxxxx.cmake file in scidb
macro(extractDebugInfo input_dir input_file targ)
    if("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
        set(DEBUG_SYMBOLS_OUTPUT_DIRECTORY "${input_dir}/${DEBUG_SYMBOLS_DIRECTORY}")

        file(MAKE_DIRECTORY "${DEBUG_SYMBOLS_OUTPUT_DIRECTORY}")
        add_custom_command(TARGET ${targ}
            POST_BUILD
            COMMAND objcopy --only-keep-debug "${input_dir}/${input_file}" "${DEBUG_SYMBOLS_OUTPUT_DIRECTORY}/${input_file}${DEBUG_SYMBOLS_EXTENSION}"
            COMMAND strip --strip-debug --strip-unneeded "${input_dir}/${input_file}"
            COMMAND objcopy --add-gnu-debuglink=${DEBUG_SYMBOLS_DIRECTORY}/${input_file}${DEBUG_SYMBOLS_EXTENSION} ${input_dir}/${input_file}
            COMMAND chmod -x "${DEBUG_SYMBOLS_OUTPUT_DIRECTORY}/${input_file}${DEBUG_SYMBOLS_EXTENSION}"
            WORKING_DIRECTORY "${input_dir}"
        )
    endif()
endmacro(extractDebugInfo)

#
# SUBDIRECTORIES
#
add_subdirectory("extern")
add_subdirectory("src")
add_subdirectory("utils")
if (NOT WITHOUT_SERVER)
    add_subdirectory("tests")
    add_subdirectory("examples")
endif()

#
# TESTING: CTest, Dart, and Cdash
#
ENABLE_TESTING()
INCLUDE(CTest)

if (CDASH_CONFIG)
  ADD_TEST(ScidbInstall "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/scidb/install.sh ${CDASH_CONFIG})
  ADD_TEST(ScidbTest "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/scidb/harness.sh ${CDASH_CONFIG} "prepare_run")
  ADD_TEST(ScidbResult "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/scidb/harness.sh ${CDASH_CONFIG} "collect_cleanup")
  ADD_TEST(P4Install "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/p4/install.sh ${CDASH_CONFIG})
  ADD_TEST(P4Test "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/scidb/harness.sh ${CDASH_CONFIG} "prepare_run")
  ADD_TEST(P4Result "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/scidb/harness.sh ${CDASH_CONFIG} "collect_cleanup")
  ADD_TEST(NamespaceInstall "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/p4/install.sh ${CDASH_CONFIG})
  ADD_TEST(NamespaceTest "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/scidb/harness.sh ${CDASH_CONFIG} "prepare_run")
  ADD_TEST(NamespaceResult "/bin/bash" ${CMAKE_BINARY_DIR}/cdash2/scidb/harness.sh ${CDASH_CONFIG} "collect_cleanup")
  #
  # TEST INSTALL TIMEOUT
  #
  if (NOT INSTALL_TIMEOUT)
    set(INSTALL_TIMEOUT 3600) # 1 hour.
  endif(NOT INSTALL_TIMEOUT)
  #
  # TEST TIMEOUT
  #
  if (NOT HARNESS_TEST_TIMEOUT)
    set(HARNESS_TEST_TIMEOUT 32000) # Between 8 and 9 hours - for regular build/tests.
    if("${CMAKE_BUILD_TYPE}" STREQUAL "Valgrind")
      set(HARNESS_TEST_TIMEOUT 86400) # 24 hours - for Valgrind build/tests.
    endif("${CMAKE_BUILD_TYPE}" STREQUAL "Valgrind")
  endif(NOT HARNESS_TEST_TIMEOUT)
  #
  # TEST RESULTS COLLECTION TIMEOUT
  #
  if (NOT RESULTS_COLLECTION_TIMEOUT)
    set(RESULTS_COLLECTION_TIMEOUT 3600) # 1 hour.
  endif(NOT RESULTS_COLLECTION_TIMEOUT)

  set_tests_properties (ScidbInstall PROPERTIES TIMEOUT ${INSTALL_TIMEOUT})
  set_tests_properties (P4Install PROPERTIES TIMEOUT ${INSTALL_TIMEOUT})
  set_tests_properties (NamespaceInstall PROPERTIES TIMEOUT ${INSTALL_TIMEOUT})
  set_tests_properties (ScidbTest PROPERTIES TIMEOUT ${HARNESS_TEST_TIMEOUT})
  set_tests_properties (P4Test PROPERTIES TIMEOUT ${HARNESS_TEST_TIMEOUT})
  set_tests_properties (NamespaceTest PROPERTIES TIMEOUT ${HARNESS_TEST_TIMEOUT})
  set_tests_properties (ScidbResult PROPERTIES TIMEOUT ${RESULTS_COLLECTION_TIMEOUT})
  set_tests_properties (P4Result PROPERTIES TIMEOUT ${RESULTS_COLLECTION_TIMEOUT})
  set_tests_properties (NamespaceResult PROPERTIES TIMEOUT ${RESULTS_COLLECTION_TIMEOUT})
endif()
#
# Custom uninstall target
#
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/uninstall.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake"
    IMMEDIATE @ONLY)

add_custom_target(uninstall
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake)

# BEGIN dummy target for adding misc files into the IDE projects like QtCreator
file(GLOB MISC_FILES_SRC
    "src/capi/scidbpython.i"
)
add_library(misc_files EXCLUDE_FROM_ALL examples/point/point.cpp ${MISC_FILES_SRC})
# End of dummy target


#
# all outputs must go to CMAKE_BINARY_DIR to support out-of-tree build and test
#
# TODO: these should be done at make time, not cmake time, so a developer need
#       not do a full rebuild when only changing a test or doc file.
#       (HINT add CMakeLists.txt files, with targets with ADD_CUSTOM_COMMAND()s intead of execute_process()
#

#
# COPY CDASH
#
message(STATUS "copying ${CMAKE_SOURCE_DIR}/cdash to ${CMAKE_BINARY_DIR}/cdash")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/cdash
                                                           ${CMAKE_BINARY_DIR}/cdash)
#
# COPY DOC
#
    # NOTE: doc must be copied before tests, so long as test/examples is a link into
    # doc. This does not seem to cause a problem when the source and destination
    # are in the same volume.
    # However, when they are in different volumes, copy_directory seems to check
    # and detect that the link "tests/examples" to "../doc/tests/examples is not
    # valid (the first time), and the copy of tests stops with an error, and
    # without copying the rest of tests.
    # To confuse matters, doc is then copied, and the second time this is tried,
    # it succeeds.

    # This is a workaround.  The 'right' fix is that source code repositories
    # should not have links in them.
    #
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/doc
                                                           ${CMAKE_BINARY_DIR}/doc)

#
# COPY TESTS
#
message(STATUS "copying ${CMAKE_SOURCE_DIR}/tests to ${CMAKE_BINARY_DIR}/tests")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/tests
                                                           ${CMAKE_BINARY_DIR}/tests)

set(ignoreMe "${RUN_PY}")
if (DEFINED RUN_PY)
  # Remove the actual test cases and expected results from the build area:
  # they will be accessed directly from the source tree.
  message(STATUS "removing ${CMAKE_SOURCE_DIR}/tests/harness/testcases/t from ${CMAKE_BINARY_DIR}/tests/harness/testcases/t")
  execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/tests/harness/testcases/t)
  execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/tests/harness/testcases/data)
endif (DEFINED RUN_PY)

#
# COPY VERSION
#
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/version
                                                 ${CMAKE_BINARY_DIR}/version)

#
# INSTALL
#
include(install.cmake)

message(STATUS "****************** END CMakeLists.txt ******************")
