# @file         CMakeLists.txt
# @brief        CMake configuration file
# @details      Process this file with cmake to generate build script
#
# @author       Carsten Spie&szlig; dsltool@carsten-spiess.de
# @date         26.04.2016
#
# @copyright
#       This file is part of @b dsltool.
# @n
#       @b dsltool is free software: you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation, either version 3 of the License, or
#       (at your option) any later version.
# @n
#       dsltool 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.
# @n
#       You should have received a copy of the GNU General Public License
#       along with dsltool.  If not, see <http://www.gnu.org/licenses/>.

# ---------------------------------------------------------
# general settings
cmake_minimum_required (VERSION 3.4)

# ---------------------------------------------------------
# project settings
project (dsltool VERSION 2.4.0
	LANGUAGES C CXX)
set (CMAKE_INCLUDE_CURRENT_DIR ON)

# executables
option (WITH_CMD "compile command line tool" ON)
option (WITH_DAEMON "compile daemon" ON)
option (WITH_GUI "compile Qt gui" ON)
option (UPDATE_TRANSLATION "update Qt translation" OFF)

# protocols
option (WITH_TELNET "compile telnet protocol" ON)
option (WITH_SSH "compile ssh protocol" OFF)
option (WITH_HTTP "compile http protocol" ON)
option (WITH_PCAP "compile pcap protocols" OFF)

# output
option (WITH_PANGO "compile with pango/cairo" ON)
option (WITH_COLLECTD "compile with collectd client" ON)

# options
option (WITH_LOCALE "with locale" ON)
option (WITH_LONGOPT "with long options" ON)
option (ENABLE_CAPTURE "enable capture" ON)
option (ENABLE_TEST "enable test" OFF)

# ---------------------------------------------------------
# configuration types
if (CMAKE_CONFIGURATION_TYPES)
	set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
else (CMAKE_CONFIGURATION_TYPES)
	# fake configuration types for single-config generators
	if (NOT CMAKE_BUILD_TYPE)
		message ("Defaulting to release build.")
		set (CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
	endif()
	set_property (CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING "Choose the type of build")
	# set the valid options for cmake-gui drop-down list
	set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release")
	message (STATUS "Build type is ${CMAKE_BUILD_TYPE}.")
endif (CMAKE_CONFIGURATION_TYPES)

message (STATUS "System version: ${CMAKE_SYSTEM_VERSION}")
message (STATUS "Target Platform: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
# ---------------------------------------------------------
# global flags
# C compiler
# override generated C_FLAGS
set (CMAKE_C_FLAGS_DEBUG "")
set (CMAKE_C_FLAGS_RELEASE "")
set (CMAKE_C_FLAGS "")

if (WIN32)
	# debug build
	set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Od")
	set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
	set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -MDd")
	#release build
	set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
	set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -MD")
	# common flags
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -J")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
else  (WIN32)
	# debug
	set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g ")
	set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
	# release
	set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3")
	# common
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
endif (WIN32)

# C++ compiler
# override generated CXX_FLAGS
set (CMAKE_CXX_FLAGS_DEBUG "")
set (CMAKE_CXX_FLAGS_RELEASE "")
set (CMAKE_CXX_FLAGS "")

if (WIN32)
else (WIN32)
	include (CheckCXXCompilerFlag)
	CHECK_CXX_COMPILER_FLAG ("-std=c++11" COMPILER_SUPPORTS_CXX11)
	CHECK_CXX_COMPILER_FLAG ("-std=c++0x" COMPILER_SUPPORTS_CXX0X)

	if (COMPILER_SUPPORTS_CXX11)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
	elseif (COMPILER_SUPPORTS_CXX0X)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
	else (COMPILER_SUPPORTS_CXX0X)
		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++98")
		message (WARNING "the compiler ${CMAKE_CXX_COMPILER} has no C++11 support.")
	endif (COMPILER_SUPPORTS_CXX11)
endif (WIN32)

if (WIN32)
	# debug build
	set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Od -Ob0 -Zi")
	set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
	set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -MDd")
	#release build
	set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
	set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -MD")
	# common flags
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -J")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVC_EXTRALEAN")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_LEAN_AND_MEAN")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4061")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4127")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4512")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4514")
	#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4625")
	#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4626")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4668")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4710")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4711")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4820")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4917")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -FIconfig.h")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -FIwindows.h")
else (WIN32)
	# debug build
	set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
	set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
	#release build
	set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
	# common flags
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstrict-aliasing")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wstrict-aliasing=2")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-declarations")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunused")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuninitialized")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Winline")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdelete-non-virtual-dtor")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-elide-constructors")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wlogical-op")
endif (WIN32)

# linker
include (GenerateExportHeader)
if (WIN32)
	set (WIN32DLL_SUFFIX "$<$<CONFIG:Debug>:d>")
else (WIN32)
	set (CMAKE_EXELINKER_FLAGS "${CMAKE_EXELINKER_FLAGS} -Wall")
	set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wall")
	set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wall")
endif (WIN32)

# ---------------------------------------------------------
# external  packages
if (WIN32)
else (WIN32)
	find_package (PkgConfig REQUIRED)
endif (WIN32)

if (WITH_GUI)
	find_package (Qt5Widgets REQUIRED)
	find_package (Qt5LinguistTools REQUIRED)
	set (QT5_PATH "${_qt5Widgets_install_prefix}/bin")
endif (WITH_GUI)

if (WITH_PANGO)
	if (WIN32)
	else (WIN32)
		pkg_check_modules (pangocairo-PKG pangocairo)
	endif (WIN32)
endif (WITH_PANGO)

if (WITH_TELNET)
	if (WIN32)
		set (libtelnet-PKG_FOUND true)
	else (WIN32)
		pkg_check_modules (libtelnet-PKG libtelnet)
	endif (WIN32)
endif (WITH_TELNET)

if (WITH_SSH)
	pkg_check_modules (libssh2-PKG libssh2)
endif (WITH_SSH)

if (WITH_HTTP)
	if (WIN32)
	else (WIN32)
		pkg_check_modules (libxml2-PKG libxml-2.0)
	endif (WIN32)
endif (WITH_HTTP)

if (WITH_PCAP)
#	find_package (PCAP REQUIRED)
endif (WITH_PCAP)

if (ENABLE_CAPTURE)
#	find_package (PCAP REQUIRED)
endif (ENABLE_CAPTURE)

# ---------------------------------------------------------
# config header
configure_file (config.h.in config.h)

# ---------------------------------------------------------
# rpath
if (WIN32)
else (WIN32)
	set (CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX})
endif (WIN32)

# ---------------------------------------------------------
# external libraries
if (WIN32)
	# regex
	list (APPEND libregex-SRC ext-libs/regex/src/regex.c)
	list (APPEND libregex-CFLAGS -D_CRT_SECURE_NO_WARNINGS)
	list (APPEND libregex-CFLAGS -wd4018)
	list (APPEND libregex-CFLAGS -wd4100)
	list (APPEND libregex-CFLAGS -wd4127)
	list (APPEND libregex-CFLAGS -wd4189)
	list (APPEND libregex-CFLAGS -wd4242)
	list (APPEND libregex-CFLAGS -wd4244)
	list (APPEND libregex-CFLAGS -wd4267)
	list (APPEND libregex-CFLAGS -wd4311)
	list (APPEND libregex-CFLAGS -wd4312)
	list (APPEND libregex-CFLAGS -wd4388)
	list (APPEND libregex-CFLAGS -wd4701)
	list (APPEND libregex-CFLAGS -wd4711)
	list (APPEND libregex-CFLAGS -wd4820)
	add_library (libregex STATIC
		${libregex-SRC})
	target_include_directories (libregex PUBLIC ext-libs/regex/inc)
	target_compile_options (libregex PUBLIC ${libregex-CFLAGS})
	# getopt
	list (APPEND libgetopt-SRC ext-libs/getopt/src/getopt.c)
	list (APPEND libgetopt-CFLAGS -D_CRT_SECURE_NO_WARNINGS)
	list (APPEND libgetopt-CFLAGS -wd4706)
	list (APPEND libgetopt-CFLAGS -wd4711)
	list (APPEND libgetopt-CFLAGS -wd4820)
	add_library (libgetopt STATIC
		${libgetopt-SRC})
	target_include_directories (libgetopt PUBLIC ext-libs/getopt/inc)
	target_compile_options (libgetopt PUBLIC ${libgetopt-CFLAGS})
	# telnet
	list (APPEND libtelnet-SRC ext-libs/telnet/src/libtelnet.c)
	list (APPEND libtelnet-CFLAGS -D_CRT_SECURE_NO_WARNINGS)
	list (APPEND libtelnet-CFLAGS -wd4100)
	list (APPEND libtelnet-CFLAGS -wd4668)
	list (APPEND libtelnet-CFLAGS -wd4711)
	list (APPEND libtelnet-CFLAGS -wd4820)
	add_library (libtelnet STATIC
		${libtelnet-SRC})
	target_include_directories (libtelnet PUBLIC ext-libs/telnet/inc)
	target_compile_options (libtelnet PUBLIC ${libtelnet-CFLAGS})
endif (WIN32)

# ---------------------------------------------------------
# libraries

# libdsltool
if (WIN32)
	list (APPEND libdsltool-SRC src/dynlib-w32.cpp)
else (WIN32)
	list (APPEND libdsltool-SRC src/dynlib.cpp)
endif  (WIN32)
list (APPEND libdsltool-SRC src/run.cpp)
list (APPEND libdsltool-SRC src/oneshot.cpp)
if (WITH_DAEMON)
	list (APPEND libdsltool-SRC src/daemon.cpp)
endif (WITH_DAEMON)
list (APPEND libdsltool-SRC src/config-data.cpp)
list (APPEND libdsltool-SRC src/config-option.cpp)
list (APPEND libdsltool-SRC src/config-list.cpp)
list (APPEND libdsltool-SRC src/basis.cpp)
list (APPEND libdsltool-SRC src/txt.cpp)
list (APPEND libdsltool-SRC src/file.cpp)
if (ENABLE_CAPTURE)
	list (APPEND libdsltool-SRC src/capture.cpp)
endif (ENABLE_CAPTURE)
list (APPEND libdsltool-SRC src/log.cpp)
list (APPEND libdsltool-SRC src/auth.cpp)
list (APPEND libdsltool-SRC src/protocol.cpp)
list (APPEND libdsltool-SRC src/modem.cpp)
list (APPEND libdsltool-SRC src/output.cpp)
list (APPEND libdsltool-SRC src/bandplan.cpp)
list (APPEND libdsltool-SRC src/dsldata.cpp)
list (APPEND libdsltool-SRC src/parser.cpp)
list (APPEND libdsltool-SRC src/regex-parser.cpp)
if (libxml2-PKG_FOUND)
	list (APPEND libdsltool-SRC src/xml-parser.cpp)
	list (APPEND libdsltool-SRC src/xml-context.cpp)
endif (libxml2-PKG_FOUND)

list (APPEND libdsltool-CFLAGS ${libxml2-PKG_CFLAGS})
if (WITH_DAEMON)
	if (WIN32)
	else (WIN32)
		list (APPEND libdsltool-LIBS pthread)
	endif(WIN32)
endif (WITH_DAEMON)
list (APPEND libdsltool-LIBS ${libxml2-PKG_LIBRARIES})
if (ENABLE_CAPTURE)
	if (WIN32)
	else (WIN32)
		list (APPEND libdsltool-LIBS pcap)
	endif (WIN32)
endif (ENABLE_CAPTURE)
if (WIN32)
	list (APPEND libdsltool-LIBS libregex)
	list (APPEND libdsltool-LIBS libgetopt)
endif (WIN32)
list (APPEND dsltool-LIB libdsltool)

add_library (libdsltool SHARED
	${libdsltool-SRC})
set_target_properties (libdsltool PROPERTIES
		OUTPUT_NAME dsltool
		VERSION ${PROJECT_VERSION}
		SOVERSION ${PROJECT_VERSION})

target_include_directories (libdsltool PUBLIC inc)
if (WIN32)
	target_include_directories (libdsltool PUBLIC ext-libs/getopt/inc)
	target_include_directories (libdsltool PUBLIC ext-libs/regex/inc)
endif (WIN32)
target_compile_options (libdsltool PUBLIC ${libdsltool-CFLAGS})
target_link_libraries (libdsltool ${libdsltool-LIBS})
if (WIN32)
	set_target_properties(libdsltool PROPERTIES OUTPUT_NAME dsltool-lib${WIN32DLL_SUFFIX})
endif (WIN32)
generate_export_header (libdsltool
	EXPORT_FILE_NAME libdsltool-export.h)

# ---------------------------------------------------------
# protocols
list (APPEND libdsltool-demo-SRC protocol/src/demo.cpp)
list (APPEND libdsltool-PROTOCOL demo)

# telnet
if (WITH_TELNET)
	if (libtelnet-PKG_FOUND)
		list (APPEND libdsltool-telnet-SRC protocol/src/telnet-socket.cpp)
		list (APPEND libdsltool-telnet-SRC protocol/src/telnet-base.cpp)
		if (WIN32)
			list (APPEND libdsltool-telnet-INC ext-libs/telnet/inc)
			list (APPEND libdsltool-telnet-LIBS libtelnet)
			list (APPEND libdsltool-telnet-LIBS ws2_32)
			list (APPEND libdsltool-telnet-CFLAGS -wd4365)
			list (APPEND libdsltool-telnet-CFLAGS -wd4548)
			list (APPEND libdsltool-telnet-CFLAGS -wd4574)
		else (WIN32)
			list (APPEND libdsltool-telnet-LIBS telnet)
		endif (WIN32)

		list (APPEND libdsltool-PROTOCOL telnet)
	
		if (WITH_PCAP)
			list (APPEND libdsltool-pcap-telnet-SRC protocol/src/telnet-pcap.cpp)
			list (APPEND libdsltool-pcap-telnet-SRC protocol/src/telnet-base.cpp)
			if (WIN32)
				list (APPEND libdsltool-pcap-telnet-INC ext-libs/telnet/inc)
				list (APPEND libdsltool-pcap-telnet-LIBS libtelnet)
			else (WIN32)
				list (APPEND libdsltool-pcap-telnet-LIBS telnet)
			endif (WIN32)
			if (WIN32)
			else (WIN32)
				list (APPEND libdsltool-pcap-telnet-LIBS pcap)
			endif (WIN32)

			list (APPEND libdsltool-PROTOCOL pcap-telnet)
		endif (WITH_PCAP)
	endif (libtelnet-PKG_FOUND)
endif (WITH_TELNET)

# ssh
if (WITH_SSH)
	list (APPEND libdsltool-ssh-SRC protocol/src/ssh-socket.cpp)
	list (APPEND libdsltool-ssh-SRC protocol/src/ssh-base.cpp)
	
	list (APPEND libdsltool-ssh-LIBS ssh2)

	list (APPEND libdsltool-PROTOCOL ssh)

	if (WITH_PCAP)
		list (APPEND libdsltool-pcap-ssh-SRC protocol/src/ssh-pcap.cpp)
		list (APPEND libdsltool-pcap-ssh-SRC protocol/src/ssh-base.cpp)
		if (WIN32)
		else (WIN32)
			list (APPEND libdsltool-pcap-ssh-LIBS pcap)
		endif (WIN32)

		list (APPEND libdsltool-PROTOCOL pcap-ssh)
	endif (WITH_PCAP)
endif (WITH_SSH)

# http
if (WITH_HTTP)
	if (libxml2-PKG_FOUND)
		list (APPEND libdsltool-http-SRC protocol/src/http-socket.cpp)
		list (APPEND libdsltool-http-SRC protocol/src/http-base.cpp)
		list (APPEND libdsltool-http-SRC protocol/src/http_parser.c)

		list (APPEND libdsltool-PROTOCOL http)
	
		if (WITH_PCAP)
			list (APPEND libdsltool-pcap-http-SRC protocol/src/http-pcap.cpp)
			list (APPEND libdsltool-pcap-http-SRC protocol/src/http-base.cpp)
			list (APPEND libdsltool-pcap-http-SRC protocol/src/http_parser.c)
			if (WIN32)
			else (WIN32)
				list (APPEND libdsltool-pcap-http-LIBS pcap)
			endif (WIN32)

			list (APPEND libdsltool-PROTOCOL pcap-http)
		endif (WITH_PCAP)
	endif (libxml2-PKG_FOUND)
endif (WITH_HTTP)

foreach (_protocol ${libdsltool-PROTOCOL})
	# append to install list
	list (APPEND dsltool-LIB libdsltool-${_protocol})

	# build library
	add_library (libdsltool-${_protocol} SHARED
		${libdsltool-${_protocol}-SRC})
	set_target_properties (libdsltool-${_protocol} PROPERTIES
		OUTPUT_NAME dsltool-${_protocol}${WIN32DLL_SUFFIX}
		VERSION ${PROJECT_VERSION}
		SOVERSION ${PROJECT_VERSION})
	target_include_directories (libdsltool-${_protocol}
		PUBLIC inc protocol/inc libdsltool-${_protocol}-INC)
	target_compile_options (libdsltool-${_protocol} PUBLIC
		${libdsltool-${_protocol}-CFLAGS})
	target_link_libraries (libdsltool-${_protocol}
		libdsltool
		${libdsltool-${_protocol}-LIBS})
	generate_export_header (libdsltool-${_protocol}
		EXPORT_FILE_NAME libdsltool-${_protocol}-export.h)
endforeach ()

# ---------------------------------------------------------
# modems
list (APPEND libdsltool-avm-tr064-LIBS crypto)

list (APPEND libdsltool-MODEM demo-adsl)
list (APPEND libdsltool-MODEM demo-vdsl)

list (APPEND libdsltool-MODEM amazon)
list (APPEND libdsltool-MODEM ar7)
if (WIN32)
else (WIN32)
	list (APPEND libdsltool-MODEM avm-tr064)
endif (WIN32)
list (APPEND libdsltool-MODEM bc63)
list (APPEND libdsltool-MODEM conexant)
list (APPEND libdsltool-MODEM openwrt)
list (APPEND libdsltool-MODEM speedtouch)
list (APPEND libdsltool-MODEM trendchip)
list (APPEND libdsltool-MODEM vigor)
list (APPEND libdsltool-MODEM vinax)

foreach (_modem ${libdsltool-MODEM})
	# append to install list
	list (APPEND dsltool-LIB libdsltool-${_modem})

	# build library
	add_library (libdsltool-${_modem} SHARED
		modem/src/${_modem}.cpp)
	set_target_properties (libdsltool-${_modem} PROPERTIES
		OUTPUT_NAME dsltool-${_modem}${WIN32DLL_SUFFIX}
		VERSION ${PROJECT_VERSION}
		SOVERSION ${PROJECT_VERSION})
	target_include_directories (libdsltool-${_modem}
		PUBLIC inc modem/inc)
	target_compile_options (libdsltool-${_modem} PUBLIC
		${dsltool-${_modem}-CFLAGS})
	target_link_libraries (libdsltool-${_modem}
		libdsltool
		${libdsltool-${_modem}-LIBS})
	generate_export_header (libdsltool-${_modem}
		EXPORT_FILE_NAME libdsltool-${_modem}-export.h)
endforeach ()

# ---------------------------------------------------------
# output
list (APPEND libdsltool-dat-SRC output/src/dat.cpp)
list (APPEND libdsltool-OUTPUT dat)

list (APPEND libdsltool-text-SRC output/src/text.cpp)
list (APPEND libdsltool-OUTPUT text)

if (WITH_PANGO)
	list (APPEND libdsltool-png-SRC output/src/png.cpp)
	list (APPEND libdsltool-png-SRC output/src/graph.cpp)
	list (APPEND libdsltool-png-SRC output/src/image-png.cpp)
	list (APPEND libdsltool-png-CFLAGS ${pangocairo-PKG_CFLAGS})
	list (APPEND libdsltool-png-LIBS ${pangocairo-PKG_LIBRARIES})
	list (APPEND libdsltool-OUTPUT png)
endif (WITH_PANGO)
if (WITH_COLLECTD)
	list (APPEND libdsltool-rrd-SRC output/src/rrd.cpp)
	list (APPEND libdsltool-rrd-SRC output/src/collect.cpp)
	list (APPEND libdsltool-rrd-LIBS collectdclient)
	list (APPEND libdsltool-OUTPUT rrd)
endif (WITH_COLLECTD)

foreach (_output ${libdsltool-OUTPUT})
	# append to install list
	list (APPEND dsltool-LIB libdsltool-${_output})

	# build library
	add_library (libdsltool-${_output} SHARED
		${libdsltool-${_output}-SRC})
	set_target_properties (libdsltool-${_output} PROPERTIES
		OUTPUT_NAME dsltool-${_output}${WIN32DLL_SUFFIX}
		VERSION ${PROJECT_VERSION}
		SOVERSION ${PROJECT_VERSION})
	target_include_directories (libdsltool-${_output} PUBLIC
		inc output/inc)
	target_compile_options (libdsltool-${_output} PUBLIC
		${libdsltool-${_output}-CFLAGS})
	target_link_libraries (libdsltool-${_output}
		libdsltool
		${libdsltool-${_output}-LIBS})
	generate_export_header (libdsltool-${_output}
		EXPORT_FILE_NAME libdsltool-${_output}-export.h)
endforeach ()

# ---------------------------------------------------------
# executables
# dsltool
if (WITH_CMD)
	list (APPEND dsltool-SRC src/dsltool.cpp)
	list (APPEND dsltool-LIBS libdsltool)

	# append to install list
	list (APPEND dsltool-BIN dsltool)

	# build executable
	add_executable (dsltool ${dsltool-SRC})
	target_compile_options (dsltool PUBLIC
		${dsltoold-CFLAGS})
	target_include_directories (dsltool PUBLIC
		inc)
	target_link_libraries (dsltool ${dsltool-LIBS} ${CMAKE_DL_LIBS})
endif (WITH_CMD)

# dsltoold
if (WITH_DAEMON)
	list (APPEND dsltoold-SRC src/dsltoold.cpp)
	list (APPEND dsltoold-LIBS libdsltool)

	# append to install list
	list (APPEND dsltool-BIN dsltoold)

	# build executable
	add_executable (dsltoold ${dsltoold-SRC})
	target_compile_options (dsltoold PUBLIC
		${dsltoold-CFLAGS})
	target_include_directories (dsltoold PUBLIC
		inc)
	target_link_libraries (dsltoold ${dsltoold-LIBS} ${CMAKE_DL_LIBS})
endif (WITH_DAEMON)

# dsltool-gui
if (WITH_GUI)
	# sources
	list (APPEND dsltool-gui-SRC src/dsltool-gui.cpp)
	list (APPEND dsltool-gui-SRC src/gui-main.cpp)
	list (APPEND dsltool-gui-SRC src/gui-config.cpp)
	list (APPEND dsltool-gui-SRC src/gui-info.cpp)
	list (APPEND dsltool-gui-SRC output/src/image-qt.cpp)
	list (APPEND dsltool-gui-SRC output/src/graph.cpp)
	# include files
	list (APPEND dsltool-gui-INC inc/gui-main.h)
	list (APPEND dsltool-gui-INC inc/gui-config.h)
	list (APPEND dsltool-gui-INC inc/gui-info.h)
	# ui files
	list (APPEND dsltool-gui-UI gui/main.ui)
	list (APPEND dsltool-gui-UI gui/config.ui)
	list (APPEND dsltool-gui-UI gui/info.ui)
	# resources
	list (APPEND dsltool-gui-RES gui/dsltool.qrc)
	# libraries
	list (APPEND dsltool-gui-LIBS libdsltool)
	list (APPEND dsltool-gui-LIBS Qt5::Widgets)

	if (WIN32)
		list (APPEND dsltool-gui-CFLAGS -wd4350)
		list (APPEND dsltool-gui-CFLAGS -wd4365)
		list (APPEND dsltool-gui-CFLAGS -wd4619)
		list (APPEND dsltool-gui-CFLAGS -wd4625)
		list (APPEND dsltool-gui-CFLAGS -wd4626)
		list (APPEND dsltool-gui-CFLAGS -wd4640)
	endif (WIN32)

	# generate moc and ui files
	qt5_wrap_cpp (dsltool-gui-MOC ${dsltool-gui-INC})
	qt5_wrap_ui (dsltool-gui-UI-INC	${dsltool-gui-UI})

	# translations
	list (APPEND dsltool-gui-QM-SRC ${dsltool-gui-SRC})
	list (APPEND dsltool-gui-QM-SRC ${CMAKE_BINARY_DIR}/ui_main.h)
	list (APPEND dsltool-gui-QM-SRC ${CMAKE_BINARY_DIR}/ui_config.h)

	list (APPEND dsltool-gui-TS gui/dsltool-en.ts)
	list (APPEND dsltool-gui-TS gui/dsltool-de.ts)

	if (UPDATE_TRANSLATION)
		set_directory_properties (PROPERTIES CLEAN_NO_CUSTOM TRUE)
		qt5_create_translation (dsltool-gui-QM
			${dsltool-gui-QM-SRC}
			${dsltool-gui-TS}
			OPTIONS -no-obsolete -I${CMAKE_SOURCE_DIR}/inc)
	else (UPDATE_TRANSLATION)
		qt5_add_translation (dsltool-gui-QM
			${dsltool-gui-TS})
	endif (UPDATE_TRANSLATION)

	add_custom_target (dsltool-gui-QMT
		DEPENDS ${dsltool-gui-QM} ${dsltool-gui-SRC})

	# resources
	qt5_add_resources (dsltool-gui-RCC	${dsltool-gui-RES})

	# append to install list
	list (APPEND dsltool-BIN dsltool-gui)

	# build executable
	add_executable (dsltool-gui
		WIN32
		${dsltool-gui-SRC}
		${dsltool-gui-MOC}
		${dsltool-gui-UI-INC}
		${dsltool-gui-RCC})
	target_compile_options (dsltool-gui PUBLIC
		${dsltool-gui-CFLAGS})
	target_include_directories (dsltool-gui PUBLIC
		inc output/inc ${Qt5Widgets_INCLUDE_DIRS})
	add_dependencies (dsltool-gui dsltool-gui-QMT)
	target_link_libraries (dsltool-gui ${dsltool-gui-LIBS} ${CMAKE_DL_LIBS})
	if (WIN32)
		add_custom_command (TARGET dsltool-gui POST_BUILD
			COMMAND ${CMAKE_COMMAND} -E copy_if_different
				 ${dsltool-gui-QM} ${CMAKE_BINARY_DIR}/$<CONFIG>)
		list (APPEND windeployqt-ARGS --no-translations)
		list (APPEND windeployqt-ARGS --no-system-d3d-compiler)
		list (APPEND windeployqt-ARGS --no-compiler-runtime)
		list (APPEND windeployqt-ARGS --no-svg)
		add_custom_command (TARGET dsltool-gui POST_BUILD
			COMMAND ${QT5_PATH}/windeployqt ${windeployqt-ARGS} $<TARGET_FILE:dsltool-gui>)
	endif (WIN32)
endif (WITH_GUI)

# ---------------------------------------------------------
# install
if (WIN32)
	set (dest-bin ".")
	set (dest-lib ".")
else (LINUX)
	set (dest-bin "bin")
	set (dest-lib "lib")
endif (WIN32)

if (WITH_CMD)
	install (TARGETS dsltool
		DESTINATION ${dest-bin}
		COMPONENT comp_cmd)
	list (APPEND comp-list comp_cmd)
endif (WITH_CMD)
if (WITH_DAEMON)
	install (TARGETS dsltoold
		DESTINATION ${dest-bin}
		COMPONENT comp_daemon)
	list (APPEND comp-list comp_daemon)
endif (WITH_DAEMON)
if (WITH_GUI)
	install (TARGETS dsltool-gui
		DESTINATION ${dest-bin}
		COMPONENT comp_gui)
	list (APPEND comp-list comp_gui)
endif (WITH_GUI)
install (TARGETS ${dsltool-LIB}
	DESTINATION ${dest-lib}
	COMPONENT comp_libs)
list (APPEND comp-list comp_libs)
if (WIN32)
	install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>/
		LIBRARY DESTINATION ${dest-lib}
		COMPONENT comp_Qt
		FILES_MATCHING
		PATTERN "dsltool*.dll" EXCLUDE
		PATTERN "*.dll")
	list (APPEND comp-list comp_Qt)
endif (WIN32)

# ---------------------------------------------------------
# pack
set (CPACK_GENERATOR "DEB;NSIS")
set (CPACK_SOURCE_GENERATOR "TGZ")

# common options
set (CPACK_COMPONENTS_ALL "${comp-list}")

# package description
set (CPACK_PACKAGE_DESCRIPTION "dsltool")
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "dsltool")
set (CPACK_PACKAGE_VENDOR "dsltool")
set (CPACK_PACKAGE_CONTACT "dsltool@carsten-spiess.de")
set (CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set (CPACK_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")

set (CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_ARCHITECTURE}")

# source package
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
set (CPACK_SOURCE_IGNORE_FILES "\.git;\.git/;\.gitattributes")

# debian package
set (CPACK_DEB_PACKAGE_COMPONENT false)
set (CPACK_DEBIAN_PACKAGE_SHLIBDEPS true)

set (CPACK_DEBIAN_PACKAGE_SECTION "net")
set (CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set (CPACK_DEBIAN_ARCHITECTURE ${CPACK_PACKAGE_ARCHITECTURE})
set (CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/debian/postinst;${CMAKE_CURRENT_SOURCE_DIR}/debian/postrm")

# rpm package
# todo

# NSIS package
set (CPACK_NSIS_MODIFY_PATH false)
set (CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL true)

# add menu entries
set (CPACK_NSIS_MENU_LINKS
	"dsltool-gui" "dsltool")

# CPack
include (CPack)

# package components
cpack_add_component (comp_libs
	DISPLAY_NAME "dsltool libraries"
	DESCRIPTION "dsltool libraries")

if (WITH_GUI)
	cpack_add_component (comp_Qt
		DISPLAY_NAME "Qt libraries"
		DESCRIPTION "Qt Libraries")
endif (WITH_GUI)

if (WITH_CMD)
	cpack_add_component (comp_cmd
		DISPLAY_NAME "dsltool cmd"
		DESCRIPTION "command application"
		DEPENDS comp_libs)
endif (WITH_CMD)

if (WITH_DAEMON)
	cpack_add_component (comp_daemon
		DISPLAY_NAME "dsltool daemon"
		DESCRIPTION "background daemon"
		DEPENDS comp_libs)
endif (WITH_DAEMON)

if (WITH_GUI)
	cpack_add_component (comp_gui
		DISPLAY_NAME "dsltool gui"
		DESCRIPTION "Qt5 application"
		DEPENDS comp_libs comp_Qt)
endif (WITH_GUI)

# _oOo_
