#
# Intel VCA Software Stack (VCASS)
#
# Copyright(c) 2017 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
#
# Intel VCA Scripts.
#

cmake_minimum_required (VERSION 2.8)

# project name
project (ValleyVistaApps)

if(NOT DEFINED OS)
    set(OS "CENTOS")
    message(STATUS "Setting OS value by default!")
endif()
if(NOT DEFINED PKG_VER)
    set(PKG_VER "0.0.0")
    message(STATUS "Setting PKG_VER value by default!")
endif()

# change to ON if you want to get more logs from Makefile
set(CMAKE_VERBOSE_MAKEFILE ON)

# setting ValleyVistaApps sources
set (vcactl_sources ${PROJECT_SOURCE_DIR}/src/vcactrl.cpp
                    ${PROJECT_SOURCE_DIR}/src/log_args.cpp
                    ${PROJECT_SOURCE_DIR}/src/vca_eeprom_update.cpp)
set (vcactld_sources ${PROJECT_SOURCE_DIR}/src/vcassd.c
                     ${PROJECT_SOURCE_DIR}/src/vcassd_virtio_backend.c
                     ${PROJECT_SOURCE_DIR}/src/vcassd_common.c
                     ${PROJECT_SOURCE_DIR}/src/vca_watchdog.cpp)
set (helper_sources ${PROJECT_SOURCE_DIR}/src/helper_funcs.cpp
                    ${PROJECT_SOURCE_DIR}/src/vca_config_parser.cpp
                    ${PROJECT_SOURCE_DIR}/src/vca_devices.cpp
                    ${PROJECT_SOURCE_DIR}/src/vca_blockio_ctl.cpp)
set (vcactl_headers ${PROJECT_SOURCE_DIR}/src/vcactrl.h
                    ${PROJECT_SOURCE_DIR}/src/log_args.h
                    ${PROJECT_SOURCE_DIR}/src/vca_eeprom_update.h)
set (vcactld_headers ${PROJECT_SOURCE_DIR}/src/vcassd.h
                     ${PROJECT_SOURCE_DIR}/src/vcassd_virtio_backend.h
                     ${PROJECT_SOURCE_DIR}/src/vcassd_common.h)
set (helper_headers ${PROJECT_SOURCE_DIR}/src/helper_funcs.h
                    ${PROJECT_SOURCE_DIR}/src/vca_defs.h
                    ${PROJECT_SOURCE_DIR}/src/vca_config_parser.h
                    ${PROJECT_SOURCE_DIR}/src/vca_devices.h
                    ${PROJECT_SOURCE_DIR}/src/vca_blockio_ctl.h)

# adding OSAL (OS abstraction layer)
if(UNIX)
    set(helper_sources ${helper_sources} ${PROJECT_SOURCE_DIR}/src/linux_osal.cpp)
    set(helper_headers ${helper_headers} ${PROJECT_SOURCE_DIR}/src/linux_osal.h)
elseif(WIN32)
    set(helper_sources ${helper_sources} ${PROJECT_SOURCE_DIR}/src/windows_osal.cpp)
    set(helper_headers ${helper_headers} ${PROJECT_SOURCE_DIR}/src/windows_osal.h)
endif()

# getting ValleyVistaModules path
if(NOT DEFINED MODULES_SRC)
    set(MODULES_SRC "${PROJECT_SOURCE_DIR}/../ValleyVistaModules")
    message(STATUS "Using default MODULES_SRC value!")
endif()
if(EXISTS "${MODULES_SRC}" AND IS_DIRECTORY "${MODULES_SRC}")
    message(STATUS "MODULES_SRC = ${MODULES_SRC}")
else()
    message(FATAL_ERROR "MODULES_SRC directory not exist under path: ${MODULES_SRC}! Exiting!")
endif()
message(STATUS "OS = ${OS}")

# getting boost library path
# change to ON if you want to print more logs from FindBoost.cmake module
set(Boost_DEBUG OFF)

if(UNIX)
    # for linux setting to OFF to use shared object installed from boost-devel.<version>x86_64.rpm
    set(Boost_USE_STATIC_LIBS OFF)
else()
    set(Boost_USE_STATIC_LIBS ON)
endif()
set(Boost_USE_STATIC_RUNTIME OFF)
if("x_${OS}" STREQUAL "x_CENTOS")
	#set(Boost_USE_MULTITHREADED ON)	# CentOS: boots MT-safe library in libboost-thread-dev is boost-thread-mt.*
elseif("x_${OS}" STREQUAL "x_UBUNTU")
	set(Boost_USE_MULTITHREADED OFF)	# Ubuntu: the -mt suffix has been removed. The installed libboost-thread-dev libraries are MT-safe
endif()
unset(Boost_INCLUDE_DIRS CACHE)		# unnecessary?
unset(Boost_LIBRARY_DIRS CACHE)		# unnecessary?
find_package(Boost
	REQUIRED
	COMPONENTS regex filesystem date_time thread system
)
if(NOT Boost_FOUND)
    message(FATAL_ERROR "Boost-devel package not installed! Exiting!")
endif()

message(STATUS "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}")
message(STATUS "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}")
message(STATUS "Boost_LIBRARY_DIRS = ${Boost_LIBRARY_DIRS}")
message(STATUS "Boost_INCLUDE_DIRS = ${Boost_INCLUDE_DIRS}")

if(Boost_USE_STATIC_LIBS)
   message(STATUS "Linking against boost static libraries")
else()
   message(STATUS "Linking against boost dynamic libraries")
endif()

# setting compile flags for both Linux and Windows
if(CMAKE_COMPILER_IS_GNUCXX)
    message(STATUS "GCC detected, adding compile flags")
	set(COMMON_FLAGS    "")              							  # Initialize
    set(COMMON_FLAGS    "${COMMON_FLAGS} -Wall -Werror")              # Turn on all warnings and treat it as errors
    set(COMMON_FLAGS    "${COMMON_FLAGS} -Wformat -Wformat-security") # Format string vulnerabilities
    set(COMMON_FLAGS    "${COMMON_FLAGS} -fstack-protector")          # Stack-based Buffer Overrun Detection
    set(COMMON_FLAGS    "${COMMON_FLAGS} -O2 -D_FORTIFY_SOURCE=2")    # Fortify source
    set(COMMON_FLAGS    "${COMMON_FLAGS} -fPIE -fPIC")                # Position Independent Execution (PIE)
    set(COMMON_FLAGS    "${COMMON_FLAGS} -g")
    set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -g")
    set_property(SOURCE ${PROJECT_SOURCE_DIR}/src/vca_config_parser.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -lstdc++ ")
    add_definitions("${COMMON_FLAGS}")

    # linker flags used to create executables
    set(CMAKE_EXE_LINKER_FLAGS "-g")                                        # Generate and retain symbol information in the executable
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack")  # Stack execution protection
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # Data relocation and protection (RELRO)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")            # Position Independent Execution (PIE)
    message(STATUS "CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")

    execute_process(COMMAND date +"%Y-%m-%d %H:%M:%S %z" OUTPUT_VARIABLE BUILDDATE)
    string(REGEX REPLACE "\n" "" BUILDDATE ${BUILDDATE})

    if(DEFINED BUILDNO)
	add_definitions(-DBUILDNO=\"${BUILDNO}\" -DBUILDDATE=${BUILDDATE})
    else()
	add_definitions(-DBUILDNO=\"${PKG_VER}\" -DBUILDDATE=${BUILDDATE})
    endif()
else()
    message(FATAL_ERROR "Cannot find any expected compiler!")
endif()

if(DEFINED DEBUG)
    add_definitions(-DDEBUG=${DEBUG})
endif()

set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} ${COMMON_FLAGS}")
set(CMAKE_CXX_FLAGS   "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS}")

# printing cmake project settings
message(STATUS "CMAKE_C_FLAGS = ${CMAKE_C_FLAGS}")
message(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")
message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}")
message(STATUS "CMAKE_BINARY_DIR = ${CMAKE_BINARY_DIR}")

# setting directory for executables
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
message(STATUS "CMAKE_RUNTIME_OUTPUT_DIRECTORY = ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")

# adding directories which need to include to projects
include_directories ("${PROJECT_SOURCE_DIR}/src")
include_directories ("${MODULES_SRC}/vca/common")
include_directories ("${MODULES_SRC}/vca/blockio")
include_directories(${Boost_INCLUDE_DIRS})

# adding main targets
add_executable(vcactl ${vcactl_sources} ${helper_sources}
                      ${vcactl_headers} ${helper_headers})
add_executable(vcactld ${vcactld_sources} ${helper_sources}
                       ${vcactld_headers} ${helper_headers})
target_include_directories(vcactld PRIVATE ${MODULES_SRC}/vca/vop)
target_include_directories(vcactl PRIVATE ${MODULES_SRC}/vca/vca_csm
                                          ${MODULES_SRC}/vca/vca_mgr
                                          ${MODULES_SRC}/vca/vca_mgr_extd)
target_link_libraries(vcactl pthread rt ${Boost_LIBRARIES})
target_link_libraries(vcactld pthread rt ${Boost_LIBRARIES})

set_property(TARGET vcactl PROPERTY FOLDER "vcactl")
set_property(TARGET vcactld PROPERTY FOLDER "vcactld")

# installing configuration
if(NOT DEFINED DESTDIR)
    set(DESTDIR "${CMAKE_BINARY_DIR}/install_dir")
	message(STATUS "Using default DESTDIR = ${DESTDIR}" )
else()
	message(STATUS "DESTDIR = ${DESTDIR}" )
endif()

set(prefix "/usr")
set(exec_prefix "${prefix}")
set(sbindir "${exec_prefix}/sbin")
set(etcprofiledir "/etc/profile.d")
set(vcaconfigdir "/etc/vca_config.d")
set(udevrulesdir "/lib/udev/rules.d")
set(vcalibdir "/usr/lib/vca")
set(compl_dir "/usr/share/bash-completion/completions")
if(	"x_${OS}" STREQUAL "x_CENTOS")
	set(systemd_dir "${prefix}/lib/systemd")	# only correct for CentOS >= 7.0
elseif("x_${OS}" STREQUAL "x_UBUNTU")
	set(systemd_dir "/lib/systemd")				# only correct for Ubuntu >= 15.04
endif()
set(services_dir_systemd "${systemd_dir}/system")
set(services_dir_rcd_initd "/etc/rc.d/init.d")
set(tmpfilesconfigdir "/usr/lib/tmpfiles.d")
set(all_rwx OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ GROUP_EXECUTE WORLD_WRITE WORLD_READ WORLD_EXECUTE) #777
set(ug_rwx_rx OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) #775
set(ug_rwx_r OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ) #774
set(ug_rwx OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ GROUP_EXECUTE) #770
set(ug_rw_r OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ WORLD_READ) #664
set(ug_rw OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ) #660

# for CentOS 7X and 6X there are different default service mangers (init systems): systemd or SysVinit
# so we need two targets: install_systemd - for CentOS 7X and install_systemV - for CentOS 6X
add_custom_target(install_systemd DEPENDS
	${PROJECT_SOURCE_DIR}/services/vcactl.service
)
add_custom_command(TARGET install_systemd
	COMMAND ${CMAKE_COMMAND} -E make_directory ${DESTDIR}/${services_dir_systemd}
	COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/services/vcactl.service ${DESTDIR}/${services_dir_systemd}
)
add_custom_target(install_systemV DEPENDS
	${PROJECT_SOURCE_DIR}/services/vcactl
)
add_custom_command(TARGET install_systemV
	COMMAND ${CMAKE_COMMAND} -E make_directory ${DESTDIR}/${services_dir_rcd_initd}
	COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/services/vcactl ${DESTDIR}/${services_dir_rcd_initd}
)
# files to be install after build target "install"
install(FILES ${PROJECT_SOURCE_DIR}/services/vcactl.service						PERMISSIONS ${ug_rw}  	DESTINATION ${DESTDIR}${services_dir_systemd})
install(FILES ${PROJECT_SOURCE_DIR}/bin/vcactl  								PERMISSIONS ${all_rwx}  DESTINATION ${DESTDIR}${sbindir})
install(FILES ${PROJECT_SOURCE_DIR}/bin/vcactld									PERMISSIONS ${all_rwx}	DESTINATION ${DESTDIR}${sbindir})
install(FILES ${PROJECT_SOURCE_DIR}/vca_config.d/vca_config.xml 				PERMISSIONS ${ug_rw_r}	DESTINATION ${DESTDIR}${vcaconfigdir})
install(FILES ${PROJECT_SOURCE_DIR}/vca_config.d/vca_xen_multicast_config.xml   PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${vcaconfigdir})
install(FILES ${PROJECT_SOURCE_DIR}/vca_config.d/vca_daemon_default.sh          PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${vcaconfigdir})
install(FILES ${PROJECT_SOURCE_DIR}/vca_config.d/vca_auto_boot.sh               PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${vcaconfigdir})
install(FILES ${PROJECT_SOURCE_DIR}/vca_config.d/MACUpdateImage.img             PERMISSIONS ${ug_rw}  	DESTINATION ${DESTDIR}${vcaconfigdir})
install(FILES ${PROJECT_SOURCE_DIR}/vca_config.d/ClearSMBiosEventLogImage.img   PERMISSIONS ${ug_rw}  	DESTINATION ${DESTDIR}${vcaconfigdir})
install(FILES ${PROJECT_SOURCE_DIR}/tmpfiles.d/vca.conf                         PERMISSIONS ${all_rwx}  DESTINATION ${DESTDIR}${tmpfilesconfigdir})
install(FILES ${PROJECT_SOURCE_DIR}/rules/95-vca.rules                          PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${udevrulesdir})
install(FILES ${PROJECT_SOURCE_DIR}/rules/96-vop.rules                          PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${udevrulesdir})
install(FILES ${PROJECT_SOURCE_DIR}/rules/97-host_eth_up.rules                  PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${udevrulesdir})
install(FILES ${PROJECT_SOURCE_DIR}/rules/98-vca_mgr.rules                      PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${udevrulesdir})
install(FILES ${PROJECT_SOURCE_DIR}/rules/99-vca_mgr_extd.rules                 PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${udevrulesdir})
install(FILES ${PROJECT_SOURCE_DIR}/rules/99-vca_blk_bcknd.rules                PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${udevrulesdir})
install(FILES ${PROJECT_SOURCE_DIR}/xen_scripts/domUsetup.sh                    PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${vcalibdir})
install(FILES ${PROJECT_SOURCE_DIR}/xen_scripts/card_vm.hvm                     PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${vcalibdir})
install(FILES ${PROJECT_SOURCE_DIR}/xen_scripts/card_gfx_vm.hvm                 PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${vcalibdir})
install(FILES ${PROJECT_SOURCE_DIR}/xen_scripts/windows_card_gfx_vm.hvm         PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${vcalibdir})
install(FILES ${PROJECT_SOURCE_DIR}/xen_scripts/vca_start_card_domu.sh          PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${sbindir})
install(FILES ${PROJECT_SOURCE_DIR}/bash_completion/vcactl                      PERMISSIONS ${ug_rw_r}  DESTINATION ${DESTDIR}${compl_dir})
install(FILES ${PROJECT_SOURCE_DIR}/scripts/vca_eth_ifup.sh                     PERMISSIONS ${ug_rwx_r} DESTINATION ${DESTDIR}${sbindir})
install(FILES ${PROJECT_SOURCE_DIR}/scripts/make_config.py                      PERMISSIONS ${ug_rwx_r} DESTINATION ${DESTDIR}${vcalibdir})
install(FILES ${PROJECT_SOURCE_DIR}/scripts/vca_config_upgrade.sh               PERMISSIONS ${ug_rwx_r} DESTINATION ${DESTDIR}${sbindir})
install(FILES ${PROJECT_SOURCE_DIR}/kvm_scripts/vca_start_card_kvm.sh		PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${sbindir})
install(FILES ${PROJECT_SOURCE_DIR}/kvm_scripts/kvmsetup.sh			PERMISSIONS ${ug_rwx}  	DESTINATION ${DESTDIR}${vcalibdir})
install(FILES ${PROJECT_SOURCE_DIR}/kvm_scripts/vca_kvmgtctl.sh			PERMISSIONS ${ug_rwx}   DESTINATION ${DESTDIR}${sbindir})
install(FILES ${PROJECT_SOURCE_DIR}/kvm_scripts/kvmgtctl_node.sh		PERMISSIONS ${ug_rwx}   DESTINATION ${DESTDIR}${vcalibdir})
install(FILES ${PROJECT_SOURCE_DIR}/etc_profile_scripts/vcausers_setup_path.sh  PERMISSIONS ${ug_rwx_rx} DESTINATION ${DESTDIR}${etcprofiledir})

SET(CPACK_GENERATOR "DEB")
SET(CPACK_PACKAGE_VENDOR "Intel Corporation")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Intel Corporation") #required
SET(CPACK_PACKAGE_VERSION ${PKG_VER} )
message(STATUS "CPACK_PACKAGE_VERSION = ${CPACK_PACKAGE_VERSION}")

#SET(CPACK_PACKAGE_FILE_NAME "daemon-vca-${CPACK_PACKAGE_VERSION}")
# CPACK_PACKAGE_FILE_NAME=${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}.
# CPACK_PACKAGE_NAME=PROJECT name
# CPACK_SYSTEM_NAME=CMAKE_SYSTEM_NAME= return of 'uname -s'
SET(CPACK_PACKAGE_NAME "daemon-vca")
SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")	# why not set by default?
SET(CPACK_SYSTEM_NAME ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE} )
# For DEB: conffiles, preinst, postinst, prerm, postrm:
SET(PKG_SCRIP_NAME "${PROJECT_SOURCE_DIR}/pkg_scripts")
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
    "${PKG_SCRIP_NAME}/preinst"
	"${PKG_SCRIP_NAME}/postinst"
	"${PKG_SCRIP_NAME}/prerm"
	"${PKG_SCRIP_NAME}/postrm")
set(CPACK_DEBIAN_PACKAGE_DEPENDS
	"bridge-utils, mtools, libboost-date-time1.58.0, libboost-filesystem1.58.0, libboost-regex1.58.0, libboost-system1.58.0, libboost-thread1.58.0, pciutils, ipcalc, initscripts")

INCLUDE(CPack)

# adding target "clean_cmake_files" to clean-up cmake generated files
add_custom_target(clean_cmake_files)
add_custom_command(TARGET clean_cmake_files
COMMAND ${CMAKE_COMMAND} -E remove ${PROJECT_SOURCE_DIR}/CMakeCache.txt
                                   ${PROJECT_SOURCE_DIR}/cmake_install.cmake
                                   ${PROJECT_SOURCE_DIR}/install_manifest.txt
                                   ${PROJECT_SOURCE_DIR}/Makefile
COMMAND ${CMAKE_COMMAND} -E remove_directory ${PROJECT_SOURCE_DIR}/CMakeFiles)

# unset variables to make sure that next cmake generation will use correct one
unset(MODULES_SRC CACHE)
