project(Akonadi)

cmake_minimum_required(VERSION 2.6.3 FATAL_ERROR)

# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH "${Akonadi_SOURCE_DIR}/cmake/modules")

############### Build Options ###############

include(CTest)
include(CTestConfig.cmake)
option(AKONADI_BUILD_TESTS "Build the Akonadi unit tests." TRUE)
option(AKONADI_BUILD_QSQLITE "Build the Sqlite backend." TRUE)
option(AKONADI_USE_STRIGI_SEARCH "Build Akonadi with strigi as search engine." FALSE)
option(INSTALL_QSQLITE_IN_QT_PREFIX "Install the QSQLite plugin in QT_PLUGIN_DIR" FALSE)
option(STATIC_LIBRARY "Build Akonadi as a static library." FALSE)

if(NOT DEFINED DATABASE_BACKEND)
  set(DATABASE_BACKEND "MYSQL" CACHE STRING "The default database backend to use for Akonadi. Can be either MYSQL, POSTGRES or SQLITE")
endif()

if(AKONADI_BUILD_TESTS)
  enable_testing()
endif()

if(AKONADI_USE_STRIGI_SEARCH)
  set(AKONADI_DEFINITIONS "-DAKONADI_USE_STRIGI_SEARCH")
  add_definitions(${AKONADI_DEFINITIONS})
  set(SOPRANO_REQUIRED FALSE)
else()
  set(SOPRANO_REQUIRED TRUE)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
   set(CMAKE_CXX_FLAGS_DEBUGFULL      "-g3 -fno-inline" CACHE STRING
       "Flags used by the C++ compiler during debugfull builds." FORCE)

   set(CMAKE_C_FLAGS_DEBUGFULL        "-g3 -fno-inline" CACHE STRING
       "Flags used by the C compiler during debugfull builds." FORCE)

   mark_as_advanced(CMAKE_CXX_FLAGS_DEBUGFULL CMAKE_C_FLAGS_DEBUGFULL)

   # Update the documentation string of CMAKE_BUILD_TYPE for ccache & cmake-gui
   set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
       "Choose the type of build, options are: None debugfull Debug Release RelWithDebInfo MinSizeRel."
       FORCE)
endif()

############### CMake Macros ###############

include(MacroLogFeature)
include(InstallSettings)
include(CheckFunctionExists)
include(CheckIncludeFiles)
include(MacroWriteBasicCMakeVersionFile)

############### CTest options ###############
# Set a timeout value of 1 minute per test
set(DART_TESTING_TIMEOUT 60)

# CTestCustom.cmake has to be in the CTEST_BINARY_DIR.
# in the KDE build system, this is the same as CMAKE_BINARY_DIR.
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake COPYONLY)

############### The Akonadi version (used in AkonadiConfig.cmake) ###############

set(AKONADI_VERSION_MAJOR "1")
set(AKONADI_VERSION_MINOR "8")
set(AKONADI_VERSION_PATCH "1")
set(AKONADI_VERSION "${AKONADI_VERSION_MAJOR}.${AKONADI_VERSION_MINOR}.${AKONADI_VERSION_PATCH}")
set(AKONADI_VERSION_STRING "${AKONADI_VERSION}")

# If Git is installed and a '.git' directory is found,
# we append the Git revision to AKONADI_VERSION_STRING
if(EXISTS "${Akonadi_SOURCE_DIR}/.git")
  find_program(GIT_EXECUTABLE NAMES git)
  if(GIT_EXECUTABLE)
    message(STATUS "Found git: ${GIT_EXECUTABLE}")
    execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
                    WORKING_DIRECTORY ${Akonadi_SOURCE_DIR}
                    OUTPUT_VARIABLE akonadi_git_revision)
    string(REGEX REPLACE "\n" "" akonadi_git_revision "${akonadi_git_revision}")
    set(AKONADI_VERSION_STRING "${AKONADI_VERSION_STRING} (revision: ${akonadi_git_revision})")
  endif()
endif()


############### Macros ###############

macro(MAKE_INSTALL_PATH_ABSOLUTE out in)
   if(IS_ABSOLUTE "${in}")
      set(${out} "${in}")
   else()
      set(${out} "\${AKONADI_INSTALL_DIR}/${in}")
   endif()
endmacro()


macro(SET_DEFAULT_DB_BACKEND)
    set(_backend ${ARGV0})
    if("${_backend}" STREQUAL "SQLITE")
        set(AKONADI_DATABASE_BACKEND QSQLITE3)
        set(AKONADI_BUILD_QSQLITE TRUE)
    else()
        if("${_backend}" STREQUAL "POSTGRES")
          set(AKONADI_DATABASE_BACKEND QPSQL)
        else()
          set(AKONADI_DATABASE_BACKEND QMYSQL)
        endif()
    endif()

    message(STATUS "Using default db backend ${AKONADI_DATABASE_BACKEND}")
endmacro()

#### DB BACKEND DEFAULT ####
set_default_db_backend(${DATABASE_BACKEND})


############### Find what we need ###############

#### Qt4 ####
# Don't use absolute path in Akonadi-qtTargets-$buildType.cmake
# note: this will have no effect with cmake < 2.8
set(QT_USE_IMPORTED_TARGETS TRUE)

set(QT_MIN_VERSION 4.6.0)
find_package(Qt4 REQUIRED)

# Load the custom qt4_add_dbus_interface macro.
# TODO: Add if/endif lines when the macro is available in a cmake version
include(AkonadiMacros)

# We need QtDBus and QtSql
set(QT_USE_QTDBUS TRUE)
set(QT_USE_QTSQL TRUE)
if(NOT QT_QTDBUS_FOUND)
  message(FATAL_ERROR  "Akonadi requires Qt4 with QtDBus module in order to built.")
endif()
if(NOT QT_QTSQL_FOUND)
  message(FATAL_ERROR  "Akonadi requires Qt4 with QtSql module in order to built.")
endif()
# properly set up compile flags (QT_DEBUG/QT_NO_DEBUG, ...)
include(${QT_USE_FILE})

# Missing in FindQt4.cmake until Dec 2011: setting QT_NO_DEBUG_OUTPUT
if(CMAKE_BUILD_TYPE)
  string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER)
endif()

if(NOT CMAKE_BUILD_TYPE_TOLOWER MATCHES "debug")
   add_definitions(-DQT_NO_DEBUG_OUTPUT)
endif()

if(WINCE)
    find_package(Wcecompat REQUIRED)
    set(QT_DBUSCPP2XML_EXECUTABLE ${HOST_BINDIR}/qdbuscpp2xml.exe)
    set(QT_DBUSXML2CPP_EXECUTABLE ${HOST_BINDIR}/qdbusxml2cpp.exe)
    set(STATIC_LIBRARY ON)
endif()

if(STATIC_LIBRARY)
  set(LIBRARY_TYPE STATIC)
  set(AKONADI_STATIC_LIBS ON)
  message(STATUS "Building Akonadi as a static library")
else()
  set(LIBRARY_TYPE SHARED)
endif()

#### Soprano ####
set(SOPRANO_MIN_VERSION 2.7.56)
if(NOT WINCE)
  find_package(Soprano)
endif()

macro_log_feature(Soprano_FOUND "Soprano" "Semantic Desktop Storing" "http://soprano.sourceforge.net" ${SOPRANO_REQUIRED} "${SOPRANO_MIN_VERSION}" "Soprano is needed for the Nepomuk search backend")

#### Automoc ####
find_package(Automoc4 REQUIRED)

#### SMI ####
set(SHARED_MIME_INFO_MINIMUM_VERSION "0.20")
find_package(SharedMimeInfo REQUIRED)

#### XSLTProc ####
find_program(XSLTPROC_EXECUTABLE xsltproc)
if(NOT XSLTPROC_EXECUTABLE)
  message(FATAL_ERROR "\nThe command line XSLT processor program 'xsltproc'  could not be found.\nPlease install xsltproc.\n")
endif()

if(WINCE)
  set(XSLTPROC_EXECUTABLE "${HOST_BINDIR}/xsltproc.exe")
endif()

#### Boost ####
# In CMake >= 2.8.6, FindBoost.cmake tries to find BoostConfig.cmake which is
# not compatible with CMake's FindBoost. Disable this function.
set(Boost_NO_BOOST_CMAKE TRUE)

if(MSVC)
  set(_ENABLE_EXCEPTIONS -EHsc)
endif()

if(NOT WINCE)
    find_package(Boost COMPONENTS program_options)
    macro_log_feature(Boost_FOUND "Boost" "Boost C++ Libraries" "http://www.boost.org" TRUE "" "Akonadi requires the Boost C++ libraries (program_options).")
endif()

# should be handled by FindBoost.cmake ->  cmake bug #8335
if(WIN32 AND NOT Boost_USE_STATIC_LIBS)
  add_definitions(-DBOOST_DYN_LINK)
  add_definitions(-DBOOST_PROGRAM_OPTIONS_DYN_LINK)
endif()


#### Sqlite ####
# If Sqlite is the default backend, it cannot be optional.
if("${DATABASE_BACKEND}" STREQUAL "SQLITE")
  set(SQLITE_REQUIRED "TRUE")
else()
  set(SQLITE_REQUIRED "FALSE")
endif()

if(AKONADI_BUILD_QSQLITE)
  set(SQLITE_MIN_VERSION 3.6.23)
  find_package(Sqlite)
  macro_log_feature(SQLITE_FOUND "Sqlite" "Sqlite database library" "http://www.sqlite.org" ${SQLITE_REQUIRED} "${SQLITE_MIN_VERSION}" "")
endif()

############### Compilers flags ###############

option(CMAKE_COMPILE_GCOV "Build with coverage support." FALSE)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER MATCHES "icc" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
  set(_ENABLE_EXCEPTIONS -fexceptions)
  set(CMAKE_C_FLAGS    "${CMAKE_C_FLAGS} -Wno-long-long -std=iso9899:1990 -Wundef -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common" CACHE STRING "Flags used by the compiler during all build types" FORCE)
  set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-check-new -fno-common" CACHE STRING "Flags used by the compiler during all build types" FORCE)
  if(CMAKE_COMPILE_GCOV)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
      set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofile_rt" CACHE STRING "Flags used by the linker" FORCE)
      set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -lprofile_rt" CACHE STRING "Flags used by the linker" FORCE)
      set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofile_rt" CACHE STRING "Flags used by the linker" FORCE)
    endif()
  endif()
endif()

add_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII)
add_definitions(-DQT_NO_KEYWORDS)
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)


############### Configure checks ###############

set(AKONADI_SYSTEM_LIBS)

check_include_files(execinfo.h HAVE_EXECINFO_H)
if(HAVE_EXECINFO_H)
  check_function_exists(backtrace BACKTRACE_IN_LIBC)
  if(NOT BACKTRACE_IN_LIBC)
    find_library(EXECINFO_LIBRARY NAMES execinfo)
    if(EXECINFO_LIBRARY)
      set(AKONADI_SYSTEM_LIBS ${AKONADI_SYSTEM_LIBS} ${EXECINFO_LIBRARY})
    endif()
  endif()
endif()

check_include_files(unistd.h HAVE_UNISTD_H)

# set the output paths
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
if(WIN32)
  set(LIBRARY_OUTPUT_PATH   ${EXECUTABLE_OUTPUT_PATH})
else()
  set(LIBRARY_OUTPUT_PATH   ${CMAKE_BINARY_DIR}/lib)
endif()

# Set up RPATH handling, so the libs are found if they are installed to a non-standard location.
# By default cmake builds the targets with full RPATH to everything in the build directory,
# but then removes the RPATH when installing.
# These two options below make it set the RPATH of the installed targets to all
# RPATH directories outside the current CMAKE_BINARY_DIR and also the library
# install directory, but only if this directory is not a default system library directory. Alex
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${LIB_INSTALL_DIR}" _isSystemLibDir)
if("${_isSystemLibDir}" STREQUAL "-1")
  set(CMAKE_INSTALL_RPATH "${LIB_INSTALL_DIR}")
endif("${_isSystemLibDir}" STREQUAL "-1")

if(NOT DEFINED AKONADI_BUNDLE_PATH)
  set(AKONADI_BUNDLE_PATH "/Applications/KDE4")
endif()

if(APPLE)
   message(STATUS "MacOS Bundle Path: ${AKONADI_BUNDLE_PATH}")
   set(CMAKE_INSTALL_NAME_DIR ${LIB_INSTALL_DIR})
endif()

############### Prepare AkonadiConfig.cmake ###############

# all the following variables are put into AkonadiConfig.cmake, so
# they are usable by projects using Akonadi.
make_install_path_absolute(AKONADI_BIN_DIR             ${BIN_INSTALL_DIR})
make_install_path_absolute(AKONADI_INCLUDE_DIR         ${INCLUDE_INSTALL_DIR})
make_install_path_absolute(AKONADI_LIB_DIR             ${LIB_INSTALL_DIR})
make_install_path_absolute(AKONADI_CONFIG_DIR          ${CONFIG_INSTALL_DIR})
make_install_path_absolute(AKONADI_DBUS_INTERFACES_DIR ${DBUS_INTERFACES_INSTALL_DIR})
make_install_path_absolute(AKONADI_DBUS_SERVICES_DIR   ${DBUS_SERVICES_INSTALL_DIR})
make_install_path_absolute(AKONADI_XDG_MIME_DIR        ${XDG_MIME_INSTALL_DIR})


############### Generate files ###############
# Used in configure_file() and install(EXPORT). Must be set before setting the AkonadiConfig.cmake vars.
set(AKONADI_TARGET_PREFIX Akonadi__)

if(Soprano_FOUND)
  set(HAVE_SOPRANO TRUE)
endif()
configure_file(akonadi-prefix.h.cmake ${Akonadi_BINARY_DIR}/akonadi-prefix.h)
configure_file(config-akonadi.h.cmake ${Akonadi_BINARY_DIR}/config-akonadi.h)
configure_file(AkonadiConfig.cmake.in "${Akonadi_BINARY_DIR}/AkonadiConfig.cmake" @ONLY)

if(NOT WIN32)
  configure_file(${Akonadi_SOURCE_DIR}/akonadi.pc.cmake ${Akonadi_BINARY_DIR}/akonadi.pc @ONLY)
endif()

# this file is used by to check if the installed version can be used.
macro_write_basic_cmake_version_file(${Akonadi_BINARY_DIR}/AkonadiConfigVersion.cmake
                                     ${AKONADI_VERSION_MAJOR} ${AKONADI_VERSION_MINOR} ${AKONADI_VERSION_PATCH})

############### build targets ###############

include_directories(${Akonadi_SOURCE_DIR} ${Akonadi_BINARY_DIR} ${QT_INCLUDES} ${Boost_INCLUDE_DIR})

add_subdirectory(interfaces)
add_subdirectory(libs)
set(AKONADI_PROTOCOLINTERNALS_LIBS ${akonadiprotocolinternals_LIB_DEPENDS} akonadiprotocolinternals)

add_subdirectory(shared)
add_subdirectory(agentserver)

if(XSLTPROC_EXECUTABLE)
  add_subdirectory(server)
endif()

add_subdirectory(rds)
if(SQLITE_FOUND)
  option(SQLITE_LINK_STATIC "link libsqlite3 statically" FALSE)
  add_subdirectory(qsqlite)
endif()

############### install stuff ###############

install(FILES ${Akonadi_BINARY_DIR}/AkonadiConfigVersion.cmake
              ${Akonadi_BINARY_DIR}/AkonadiConfig.cmake
        DESTINATION ${LIB_INSTALL_DIR}/cmake/Akonadi)

install(FILES akonadi-mime.xml DESTINATION ${XDG_MIME_INSTALL_DIR})
update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR})

if(NOT WIN32)
  install(FILES ${Akonadi_BINARY_DIR}/akonadi.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif()

############### CPack setup ##################

SET(CPACK_PACKAGE_NAME "akonadi")
SET(CPACK_PACKAGE_VERSION_MAJOR "${AKONADI_VERSION_MAJOR}")
SET(CPACK_PACKAGE_VERSION_MINOR "${AKONADI_VERSION_MINOR}")
SET(CPACK_PACKAGE_VERSION_PATCH "${AKONADI_VERSION_PATCH}")

set(CPACK_SOURCE_GENERATOR "TBZ2")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "akonadi-${AKONADI_VERSION_MAJOR}.${AKONADI_VERSION_MINOR}.${AKONADI_VERSION_PATCH}")
set(CPACK_SOURCE_IGNORE_FILES "/\\\\.svn/" "/\\\\.git/" "makechangelog")

include(CPack) # needs to happen after the above variables are set!


macro_display_feature_log()

# Install the file with the exported targets
install(EXPORT akonadiLibraryTargets
        NAMESPACE ${AKONADI_TARGET_PREFIX}
        DESTINATION ${LIB_INSTALL_DIR}/cmake/Akonadi
        FILE AkonadiTargetsWithPrefix.cmake)
