#############################################################
# CMake configuration
cmake_minimum_required(VERSION 3.0)

# Add folder where are supportive functions
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeStuff)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_VERBOSE_MAKEFILE ON)

# This export will allow using the flags to be used by
# youcompleteme (vim plugin).
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" )
  execute_process( COMMAND cmake -E copy_if_different
    ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json
    ${CMAKE_CURRENT_SOURCE_DIR}/compile_commands.json
  )
endif()


# We want C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# deprecated, cmake does the job: ADD_DEFINITIONS(-std=c++11)

# We do not want warnings for unknown pragmas:
ADD_DEFINITIONS(-Wno-unknown-pragmas)

# Include the various colors we want to use in the output
include(outputColors)

# Include the system's uname that fills in SYSTEM_UNAME_S.
# Sets WIN64 if SYSTEM_UNAME_S is "^.*MING64.*"
include(systemUname)


############################################################
# Basic information about project

project(msXpertSuite)
set(VERSION 5.8.9)


# Set additional project information
set(COMPANY "msXpertSuite.org")
set(COPYRIGHT "Copyright (c) 2008-2018 Filippo Rusconi. Licensed under GPLv3+")
set(IDENTIFIER "org.msxpertsuite")


message("")
message(STATUS "${BoldGreen}Starting configuration of msXpertSuite${ColourReset}")
message(STATUS "${BoldYellow}System is detected by CMake as ${SYSTEM_UNAME_S}${ColourReset}")
message("")


# No need to specify position independent code flag on MING64_NT
# because that flag is set automatically and it triggers an error when -Werror
# is set.
if(NOT WIN64)
	ADD_DEFINITIONS(-fPIC)
endif()

if(APPLE)
	add_definitions("-DAPPLE=1")
	add_definitions("-stdlib=libc++")
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
	message(STATUS "using ${CMAKE_CXX_FLAGS}")
endif()

########################################################
# Source tree preparation
# On windows and mac, some libraries are added to the source tree
# while on Debian GNU/Linux there libraries are packaged.
########################################################

if(APPLE OR WIN64)

	message(STATUS "should copy the qcustomplot directory.")

	# This include must come before all the others
	# It must include the config-generated config.h file
	# before the others.
	include_directories(${CMAKE_BINARY_DIR})

	# Copy the qcustomplot directory to the source tree
	execute_process(COMMAND cp -vrp ${CMAKE_SOURCE_DIR}/../helper-libs/qcustomplot
		${CMAKE_SOURCE_DIR}
		WORKING_DIRECTORY	${CMAKE_SOURCE_DIR})

	set(QCUSTOMPLOT_SRC_DIR ${CMAKE_SOURCE_DIR}/qcustomplot)
	include_directories(${QCUSTOMPLOT_SRC_DIR})

	# Copy the tclap directory to the source tree
	message(STATUS "should copy the tclap directory.")

	execute_process(COMMAND cp -vrp ${CMAKE_SOURCE_DIR}/../helper-libs/tclap
		${CMAKE_SOURCE_DIR}
		WORKING_DIRECTORY	${CMAKE_SOURCE_DIR})

	set(TCLAP_SRC_DIR ${CMAKE_SOURCE_DIR}/tclap)
	include_directories(${CMAKE_SOURCE_DIR})

	# Copy the isospec directory to the source tree
	message(STATUS "should copy the isospec directory.")

	execute_process(COMMAND cp -vrp ${CMAKE_SOURCE_DIR}/../helper-libs/isospec
		${CMAKE_SOURCE_DIR}
		WORKING_DIRECTORY	${CMAKE_SOURCE_DIR})

	set(ISOSPEC_SRC_DIR ${CMAKE_SOURCE_DIR}/isospec)
	include_directories(${CMAKE_SOURCE_DIR})

endif()



#############################################################
# On MINGW.* we provide a number of libraries by our own, that we
# put mingw64/usr/local/lib
if(WIN64)
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L/mingw64/usr/local/lib")
endif()


#############################################################
# Enable warnings and possibly treat them as errors
add_definitions(-Wall)

if(WARNASERR)
	message(STATUS "${BoldYellow}Warnings treated as errors.${ColourReset}")
	add_definitions(-Werror)
endif()

# On MINGW64_NT, we want to build as release, otherwise build as debug.
if(WIN64)
	set(CMAKE_BUILD_TYPE "release")
	add_definitions(-DQT_NO_DEBUG)
else()
	if(NOT CMAKE_BUILD_TYPE STREQUAL "release")
		set(CMAKE_BUILD_TYPE "debug")
	endif()
endif()

# But the user may want something easier to set: -DDEBUG
if(DEBUG)
	set(CMAKE_BUILD_TYPE "debug")
endif()

if(CMAKE_BUILD_TYPE STREQUAL "debug")
	add_definitions(-g -O0)
	message(STATUS "${BoldYellow}Debug support requested. Adding -g -O0.${ColourReset}")
else()
	add_definitions(-O3)
	message(STATUS "${BoldYellow}Debug support NOT requested. Adding -O3.${ColourReset}")
endif()

if(APPLE)
	link_directories("/opt/local/lib")
endif()

if(OPENMP)
	message(STATUS "${BoldYellow}OpenMP support is requested, adding -fopenmp flag.${ColourReset}")
	if(APPLE)
		include_directories("/opt/local/include/libomp")
		link_directories("/opt/local/lib/libomp")
	else()
		add_definitions(-fopenmp)
	endif()

	# Depending on the compiler, if we need the omp.h header file,
	# we'll have to look for it in different locations.

	message(STATUS "${BoldRed}CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}${ColourReset}")
	message(STATUS "${BoldRed}CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}${ColourReset}")

	if(CMAKE_CXX_COMPILER MATCHES ".*clang.*")
		message(STATUS "${BoldRed}Using clang++${ColourReset}")
		include_directories("${CMAKE_SOURCE_DIR}/clang-openmp")
		link_directories("${CMAKE_SOURCE_DIR}/clang-openmp")
		set(OPENMP_LIBRARY omp)
	else()
		message(STATUS "${BoldRed}Not using clang++${ColourReset}")
		set(OPENMP_LIBRARY gomp)
	endif()

	message(STATUS "${BoldYellow}Using parallelizing library ${OPENMP_LIBRARY}${ColourReset}")
endif()

if(PROFILE)
	message(STATUS "${BoldYellow}Profiling is requested, adding -pg flag.${ColourReset}")
	add_definitions(-pg)
endif()


message(STATUS "${BoldYellow}Main CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}${ColourReset}")
message(STATUS "${BoldYellow}CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}${ColourReset}")

# For the config.h file.
set(CMAKE_INCLUDE_CURRENT_DIR ON)

add_subdirectory(globals)
add_subdirectory(libmass)
add_subdirectory(libmassgui)

# It is essential to run these config steps before delving into the massxpert
# and minexpert directories, because at that moment they will need what are
# going to prepare right now.
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/CMakeStuff/splashscreen.svg.in
	${CMAKE_SOURCE_DIR}/images/splashscreen.svg @ONLY)

CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/CMakeStuff/msxpertsuite-mingw64-win7+.iss.in
	${CMAKE_SOURCE_DIR}/winInstaller/msxpertsuite-mingw64-win7+.iss @ONLY)

# Let's also set the software version in the DocBook entity file so that the
# user manuals show the right version.
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/CMakeStuff/msxpertsuite-user-manuals.ent.in
	${CMAKE_SOURCE_DIR}/doc/user-manuals/common/msxpertsuite-user-manuals.ent @ONLY)

# Make the conversion of the svg file into a png, but only on GNU/Linux
if(UNIX AND NOT APPLE)
	execute_process(COMMAND convert ${CMAKE_SOURCE_DIR}/images/splashscreen.svg
		${CMAKE_SOURCE_DIR}/images/splashscreen.png)
endif()

# In the following subdirectories, we'll set all the install directories, that
# will always be a subdirectory of the CMake-default CMAKE_INSTALL_PREFIX.

############################## MASSXPERT #############################
add_subdirectory(massxpert)

get_directory_property(MASSXPERT_TARGET_NAME
	DIRECTORY massxpert
	MASSXPERT_TARGET_NAME)

get_directory_property(MASSXPERT_BIN_DIR
	DIRECTORY massxpert
	MASSXPERT_BIN_DIR)

get_directory_property(MASSXPERT_JAVASCRIPT_DIR
	DIRECTORY massxpert
	MASSXPERT_JAVASCRIPT_DIR)

get_directory_property(MASSXPERT_DATA_DIR
	DIRECTORY massxpert
	MASSXPERT_DATA_DIR)

get_directory_property(MASSXPERT_DOC_DIR
	DIRECTORY massxpert
	MASSXPERT_DOC_DIR)

############################## MINEXPERT #############################
add_subdirectory(minexpert)

get_directory_property(MINEXPERT_TARGET_NAME
	DIRECTORY minexpert
	MINEXPERT_TARGET_NAME)

get_directory_property(MINEXPERT_BIN_DIR
	DIRECTORY minexpert
	MINEXPERT_BIN_DIR)

get_directory_property(MINEXPERT_JAVASCRIPT_DIR
	DIRECTORY minexpert
	MINEXPERT_JAVASCRIPT_DIR)

get_directory_property(MINEXPERT_DATA_DIR
	DIRECTORY minexpert
	MINEXPERT_DATA_DIR)

get_directory_property(MINEXPERT_DOC_DIR
	DIRECTORY minexpert
	MINEXPERT_DOC_DIR)

# Use all the configured paths to create the config.h file.
# The config.h file is generated in the CMAKE_BINARY_DIR!!!
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/CMakeStuff/config.h.in
	config.h @ONLY)

add_subdirectory(doc)

if(DEVDOC)
	add_subdirectory(devdoc)
endif()

if(TESTS)
	add_subdirectory(tests)
endif()

#############################################################
# summary
message("")
message(STATUS "${BoldRed}~~~~~~~~~~~~~~~~~~~~~~~~ SUMMARY ~~~~~~~~~~~~~~~~~~~~~~~~${ColourReset}")
message(STATUS "${BoldRed} General configuration of the msXpertSuite project ${ColourReset}")
message("")
message(STATUS "${BoldYellow}The system is detected by CMake as ${SYSTEM_UNAME_S}${ColourReset}")
message("")
message(STATUS "${BoldYellow}CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}${ColourReset}")
message("")
message(STATUS "${BoldRed}~~~~~~~~~~~~~~~~~~~~~~~~~~ massXpert ~~~~~~~~~~~~~~~~~~~~~~~~~~${ColourReset}")
message(STATUS "${BoldRed}~~~~~~~~~~~~~~~~~~~~~~~~~~ massXpert ~~~~~~~~~~~~~~~~~~~~~~~~~~${ColourReset}")
message(STATUS "${BoldYellow}MASSXPERT_BIN_DIR: ${MASSXPERT_BIN_DIR}${ColourReset}")
message(STATUS "${BoldYellow}MASSXPERT_JAVASCRIPT_DIR: ${MASSXPERT_JAVASCRIPT_DIR}${ColourReset}")
message(STATUS "${BoldYellow}MASSXPERT_DATA_DIR: ${MASSXPERT_DATA_DIR}${ColourReset}")
message(STATUS "${BoldYellow}MASSXPERT_DOC_DIR: ${MASSXPERT_DOC_DIR}${ColourReset}")
message("")
message(STATUS "${BoldRed}~~~~~~~~~~~~~~~~~~~~~~~~~~ mineXpert ~~~~~~~~~~~~~~~~~~~~~~~~~~${ColourReset}")
message(STATUS "${BoldRed}~~~~~~~~~~~~~~~~~~~~~~~~~~ mineXpert ~~~~~~~~~~~~~~~~~~~~~~~~~~${ColourReset}")
message(STATUS "${BoldYellow}MINEXPERT_BIN_DIR: ${MINEXPERT_BIN_DIR}${ColourReset}")
message(STATUS "${BoldYellow}MINEXPERT_JAVASCRIPT_DIR ${MINEXPERT_JAVASCRIPT_DIR}${ColourReset}")
message(STATUS "${BoldYellow}MINEXPERT_DATA_DIR: ${MINEXPERT_DATA_DIR}${ColourReset}")
message(STATUS "${BoldYellow}MINEXPERT_DOC_DIR: ${MINEXPERT_DOC_DIR}${ColourReset}")
message("")
if(PROFILE)
	message(STATUS "${BoldYellow}Profiling is requested (-DPROFILE=1)${ColourReset}")
else()
	message(STATUS "${BoldYellow}Profiling is NOT requested (-DPROFILE=0)${ColourReset}")
endif()
message("")
if(OPENMP)
	message(STATUS "${BoldYellow}OpenMP support is requested (-DOPENMP=1)${ColourReset}")
else()
	message(STATUS "${BoldYellow}OpenMP support is NOT requested (-DOPENMP=0)${ColourReset}")
endif()
message("")
if(WARNASERR)
	message(STATUS "${BoldYellow}Warnings treated as errors (-DWARNASERR=1)${ColourReset}")
else()
	message(STATUS "${BoldYellow}Warnings NOT treated as errors (-DWARNASERR=0)${ColourReset}")
endif()
message("")
if(CMAKE_BUILD_TYPE STREQUAL "debug")
	message(STATUS "${BoldYellow}Debug support requested (-DDEBUG=1)${ColourReset}")
else()
	message(STATUS "${BoldYellow}Debug support NOT requested (-DDEBUG=0)${ColourReset}")
endif()
message("")
message(STATUS "${BoldYellow}CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}${ColourReset}")
message("")
message(STATUS "${BoldYellow}You can ask for clang++ by issuing the following command: $CXX=clang++ cmake -DOPENMP=1 -DDEBUG=1 ../development/${ColourReset}")
message(STATUS "${BoldYellow}The typical cmake invocation on mingw64 would be: cmake -DDEBUG=0 -DOPENMP=1 ../development/ -G'Unix Makefiles' -DCMAKE_CXX_COMPILER=/mingw64/bin/x86_64-w64-mingw32-g++.exe ${ColourReset}")
message(STATUS "${BoldYellow}The typical cmake invocation on Debian GNU/Linux would be: $cmake -DOPENMP=1 -DDEBUG=1 ../development${ColourReset}")
message("")
message(STATUS "${BoldYellow}The typical DeveloperMode cmake invocation on Debian GNU/Linux would be: $cmake -DOPENMP=1 -DDEBUG=1 -DDEVMODE=1 -DBUILD_USER_MANUALS=1 ../development${ColourReset}")
message("")
message(STATUS "${BoldYellow}To build the tests, add the -DTESTS=1 flag to the cmake command line: $cmake -DOPENMP=1 -DDEBUG=1 -DDEVMODE=1 -DBUILD_USER_MANUALS=1 -DTESTS=1 ../development${ColourReset}")
message("")
message(STATUS "${BoldRed}~~~~~~~~~~~~~~~~~~~~~~~~ SUMMARY ~~~~~~~~~~~~~~~~~~~~~~~~${ColourReset}")
message("")
