cmake_minimum_required(VERSION 3.5.0...3.31.0)

PROJECT(morpheus VERSION 2.4.1)
# SET(MORPHEUS_BETA 3)
# SET(MORPHEUS_RC 1)


SET(MORPHEUS_BINARY_SUFFIX "" CACHE STRING "Morpheus binary suffix to use for the build. The 'branch' token gets substituted by the git branch.")
mark_as_advanced(MORPHEUS_BINARY_SUFFIX)
SET(MORPHEUS_BINARY_NAME "${CMAKE_PROJECT_NAME}" )

IF (NOT "${MORPHEUS_BINARY_SUFFIX}" STREQUAL "" )
	IF(MORPHEUS_BINARY_SUFFIX STREQUAL "branch")
		find_package(Git REQUIRED)
		# Get the current working branch
		execute_process(
			COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
			WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
			OUTPUT_VARIABLE GIT_BRANCH
			OUTPUT_STRIP_TRAILING_WHITESPACE
		)
		IF ("${GIT_BRANCH}" STREQUAL "")
			message(FATAL_ERROR "Unable to extract git branch name of the source")
		ENDIF()
		
		SET(MORPHEUS_BINARY_SUFFIX ${GIT_BRANCH})
		SET(MORPHEUS_BINARY_NAME ${MORPHEUS_BINARY_NAME}-${MORPHEUS_BINARY_SUFFIX})
	ELSE()
		SET(MORPHEUS_BINARY_NAME ${MORPHEUS_BINARY_NAME}-${MORPHEUS_BINARY_SUFFIX})
	ENDIF()
ENDIF()
SET(MORPHEUS_BINARY_STRING "\"${MORPHEUS_BINARY_NAME}\"")


SET(MORPHEUS_VERSION "${PROJECT_VERSION}")
IF(DEFINED MORPHEUS_BETA)
	SET(MORPHEUS_VERSION "${MORPHEUS_VERSION}-beta${MORPHEUS_BETA}")
ELSEIF(DEFINED MORPHEUS_RC)
	SET(MORPHEUS_VERSION "${MORPHEUS_VERSION}-rc${MORPHEUS_RC}")
ENDIF()
SET(MORPHEUS_VERSION_STRING "\"${MORPHEUS_VERSION}\"")


STRING(TIMESTAMP MORPHEUS_REVISION "%y%m%d" )
STRING(TIMESTAMP MORPHEUS_REVISION_STRING "\"%d.%m.%Y\"")

MESSAGE(STATUS "MORPHEUS VERSION IS ${MORPHEUS_VERSION}, REVISION ${MORPHEUS_REVISION}" )

CONFIGURE_FILE("version.h.in" ${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY)
INCLUDE_DIRECTORIES( ${PROJECT_BINARY_DIR})

SET(HAVE_OBJECT_LINKAGE TRUE)

IF (CMAKE_VERSION VERSION_GREATER 3.9 OR CMAKE_VERSION VERSION_EQUAL 3.9)
	cmake_policy(SET CMP0069 NEW)
	include(CheckIPOSupported)
	check_ipo_supported(RESULT HAVE_IPO)
ELSE()
	SET(HAVE_IPO FALSE)
ENDIF()

IF(HAVE_IPO AND CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
	SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${HAVE_IPO} )
ENDIF()

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include(cmake/tools.cmake)

SET(ARCH_x64 "x86_64;AMD64")
if (CMAKE_CXX_FLAGS STREQUAL "")
	if (CMAKE_SYSTEM_PROCESSOR IN_LIST ARCH_x64 )
		if(MSVC)
			SET(ARCH_FLAGS "/arch:AVX") # /arch:SSE2 /arch:AVX2
		elseif(CMAKE_CXX_COMPILER MATCHES "/(icpc|icc)$")
			SET(ARCH_FLAGS "-xAVX") # -SSE2 -xSSSE3 -xSSE4.2 -xCORE-AVX2
		else()
			SET(ARCH_FLAGS "-mavx") # -msse2 -mssse3 -msse4.2 -mavx -mavx2
		endif()
		SET(CMAKE_CXX_FLAGS "${ARCH_FLAGS}" CACHE STRING "Flags used by the CXX compiler during all buildtypes." FORCE)
		message(STATUS "Defaulting to architecture flags ${CMAKE_CXX_FLAGS}")
	else()
		#message(STATUS "UNKNOWN PLATFORM ${CMAKE_SYSTEM_PROCESSOR}")
	endif()
endif()

# Add Clang-specific flags to suppress warnings
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=missing-template-arg-list-after-template-kw")
    message(STATUS "Added Clang-specific flag to suppress template warning")
endif()

### PLATFORM DEPENDEND INSTALL DIRs of TARGETS
IF( UNIX AND NOT APPLE )
	SET(MORPHEUS_OS "UNIX")
	MESSAGE(STATUS "Compiling for platform *NIX.")
	set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
		OWNER_READ OWNER_WRITE OWNER_EXECUTE
		GROUP_READ GROUP_EXECUTE
		WORLD_READ WORLD_EXECUTE
	)
ELSEIF(APPLE)
	SET(MORPHEUS_OS "APPLE")
	MESSAGE(STATUS "Compiling for platform OSX.")
	## Make sure HomeBrew library path is there 
	SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L /usr/local/lib")
	## Switch to Release Build Mode
	OPTION(MORPHEUS_RELEASE_BUNDLE "Build Mac Application Bundle of morpheus." TRUE)
	IF (MORPHEUS_RELEASE_BUNDLE) 
		SET(MORPHEUS_BUNDLE_DIR "Morpheus.app")
 		#SET( CMAKE_BUILD_TYPE "RELEASE" )
		IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
			SET(CMAKE_INSTALL_PREFIX "~/Applications" CACHE PATH "Install path prefix, prepended onto install directories." FORCE)
		ENDIF()
	ENDIF()
ELSEIF(WIN32)
	SET(MORPHEUS_OS "WIN32")
	SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -DWIN32")
	MESSAGE(STATUS "Compiling for platform WIN32.")
ELSE()
	SET(MORPHEUS_OS "UNKNOWN")
	MESSAGE(STATUS "Compiling for unknown platform. Assuming WIN32")
	SET(WIN32 TRUE)
ENDIF()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)

OPTION(BUILD_TESTING "Enable testing" OFF)
IF (BUILD_TESTING)
	add_compile_options("-fPIC")
ENDIF()


OPTION(DOWNLOAD_XTENSOR "Download latest xtensor source" ON)

OPTION(MORPHEUS_STATIC_BUILD "Create a statically linked binary." OFF)
if (MORPHEUS_STATIC_BUILD OR NOT BUILD_TESTING)
	set(Boost_USE_STATIC_LIBS ON)
endif()

IF(MORPHEUS_STATIC_BUILD)
	set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
	SET(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-static -static-libstdc++ -static-libgcc")
ENDIF()

SET(MORPHEUS_GRAPHVIZ "WebRenderer" CACHE STRING "Select Graph rendering backend")
SET_PROPERTY(CACHE MORPHEUS_GRAPHVIZ PROPERTY STRINGS None WebRenderer Library)

FIND_PACKAGE(OpenMP)
option(MORPHEUS_OPENMP "Switch off the usage of OPENMP" ON)

IF (OPENMP_FOUND AND MORPHEUS_OPENMP)
	MESSAGE(STATUS "Enabling OpenMP support for ${CMAKE_CXX_COMPILER_ID} using\n\
	FLAGS     '${OpenMP_CXX_FLAGS}'\n\
	INCLUDE   '${OpenMP_CXX_INCLUDE_DIRS}'\n\
	LIBRARIES '${OpenMP_CXX_LIBRARIES}'")
	# dump_target_properties(OpenMP::OpenMP_CXX)
	SET(HAVE_OPENMP ON)
ELSEIF(NOT HAVE_OPENMP)
	MESSAGE(STATUS "Unable to detect OpenMP compiler support. Disabling OpenMP.")
	SET(HAVE_OPENMP OFF)
ELSE()
	MESSAGE(STATUS "OpenMP support was switched off manually. Disabling OpenMP. ")
	SET(HAVE_OPENMP OFF)
ENDIF()

# Configuration file for the uninstall target
CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
	"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
	IMMEDIATE @ONLY
)

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

IF(NOT CMAKE_BUILD_TYPE)
	SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
		"Choose the type of build, options are: Debug RelWithDebInfo Release MinSizeRel." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug RelWithDebInfo Release MinSizeRel)   

## Naming of target executables
IF (MORPHEUS_STATIC_BUILD)
	SET(MORPHEUS_EXEC_NAME ${MORPHEUS_BINARY_NAME}-${MORPHEUS_VERSION})
	message(STATUS "Excluding MorpheusGUI from static build")
	SET(MORPHEUS_GUI OFF)
ELSE()
	SET(MORPHEUS_EXEC_NAME ${MORPHEUS_BINARY_NAME})
ENDIF()

SET( GUI_EXEC_NAME "${MORPHEUS_BINARY_NAME}-gui")

OPTION(MORPHEUS_GUI "Build the graphical user interface." ON)

INCLUDE_DIRECTORIES( 3rdparty)
ADD_SUBDIRECTORY( 3rdparty )


ADD_SUBDIRECTORY( xmlutils )
ADD_SUBDIRECTORY( morpheusML )
ADD_SUBDIRECTORY( morpheus )

IF(MORPHEUS_GUI)
	ADD_SUBDIRECTORY( Examples )
	ADD_SUBDIRECTORY( gui )
ENDIF()

# Adjust the morpheus target if the graphviz Library option was chosen
IF(MORPHEUS_GRAPHVIZ STREQUAL "Library")
	SET(GRAPHVIZ_ROOT "" CACHE PATH "Set root directory to search for GraphViz" )
	MARK_AS_ADVANCED(GRAPHVIZ_ROOT)
	FIND_PACKAGE(Graphviz)
ENDIF()

IF(GRAPHVIZ_FOUND)
	target_compile_definitions(MorpheusCore PUBLIC HAVE_GRAPHVIZ=1)
# 	FIND_PACKAGE(EXPAT REQUIRED)
	TARGET_LINK_LIBRARIES_PATCHED(MorpheusCore PUBLIC ${GRAPHVIZ_GVC_LIBRARY} ${GRAPHVIZ_CDT_LIBRARY} ${GRAPHVIZ_PATHPLAN_LIBRARY})
	IF (EXISTS "${GRAPHVIZ_GRAPH_LIBRARY}")
		TARGET_LINK_LIBRARIES_PATCHED(MorpheusCore PUBLIC ${GRAPHVIZ_GRAPH_LIBRARY})
	ELSE()
		TARGET_LINK_LIBRARIES_PATCHED(MorpheusCore PUBLIC ${GRAPHVIZ_CGRAPH_LIBRARY})
	ENDIF()
ENDIF()

# INCLUDE(InstallRequiredSystemLibraries)

MESSAGE(STATUS "Configuring Generators for packaging Morpheus")
INCLUDE(Package.cmake)

