﻿cmake_minimum_required(VERSION 3.5)
cmake_policy(SET CMP0091 NEW) # for CMAKE_MSVC_RUNTIME_LIBRARY
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # cmake_policy(SET CMP0077 NEW)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
project(proxy LANGUAGES CXX)

################################################################################

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/cmake")

include(CheckCXXCompilerFlag)
include(CheckLibraryExists)
include(CheckCXXLinkerFlag)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_EXTENSIONS OFF)

################################################################################

# Disable in-source builds to prevent source tree corruption.
if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
  message(FATAL_ERROR "
FATAL: In-source builds are not allowed.
       You should create a separate directory for build files.
")
endif()
message(STATUS "CMAKE Version: ${CMAKE_VERSION}")

message(STATUS "Source Dir: ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "Host System name: ${CMAKE_HOST_SYSTEM_NAME}")

set(default_build_type "Release")

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
        STRING "Choose the type of build." FORCE)
    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
                 "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

message(STATUS "System name: ${CMAKE_SYSTEM_NAME}")
message(STATUS "System version: ${CMAKE_SYSTEM_VERSION}")
if (WIN32)
	message(STATUS "Platform version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
endif()

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "SYSTEM NAME: ${CMAKE_SYSTEM_NAME}")


################################################################################

option(ENABLE_BUILD_WERROR			"All warnings being treated as errors" OFF)
option(ENABLE_GIT_VERSION			"Enable git version" ON)

option(ENABLE_USE_IO_URING			"Enable auto use io_uring" OFF)
option(ENABLE_BUILD_WITH_LIBCXX		"Build with libc++" OFF)
option(ENABLE_REUSEPORT				"Build with REUSEPORT support" OFF)

option(ENABLE_SYSTEM_ZLIB			"Build with system zlib support" OFF)
option(ENABLE_SYSTEM_OPENSSL		"Build with system openssl support" OFF)

option(ENABLE_USE_SYSTEMD_LOG		"Build with systemd log support" OFF)
option(ENABLE_USE_PAM_AUTH 			"Build with PAM authentication support" OFF)

option(ENABLE_USE_OPENSSL			"Build with openssl support" ON)
option(ENABLE_USE_BORINGSSL			"Build with boringssl support" OFF)
option(ENABLE_USE_WOLFSSL			"Build with wolfssl support" OFF)

option(ENABLE_MOLD					"Build using mold" OFF)
option(ENABLE_LLD					"Build using lld" OFF)
option(ENABLE_USE_CCACHE				"Using ccache for fast compile" OFF)

option(ENABLE_ASIO_HANDLER_TRACKING "Enable asio handler tracking" OFF)

option(ENABLE_STATIC_LINK_TO_GCC	"Build static link to gcc" ON)

option(ENABLE_TCMALLOC_STATIC		"Build with Tcmalloc support" OFF)
option(ENABLE_JEMALLOC_STATIC		"Build with Jemalloc support" OFF)
option(ENABLE_MIMALLOC_STATIC		"Build with mimalloc support" OFF)
option(ENABLE_SNMALLOC_STATIC		"Build with snmalloc support" OFF)

option(ENABLE_BUILD_EXAMPLES		"Build proxy examples" OFF)
option(ENABLE_LINKE_TO_LIBATOMIC	"Link to libatomic.so - some platform requires it" OFF)

################################################################################

if (ENABLE_GIT_VERSION)
	find_package(Git)
	gitGetVersion(${CMAKE_CURRENT_SOURCE_DIR} proxy)
	string(STRIP "${proxy_WC_REVISION_HASH}" VERSION_GIT)
	if (VERSION_GIT STREQUAL "")
		string(TIMESTAMP PVERSION "(%Y-%m-%d %H:%M:%S)")
	else()
		string(TIMESTAMP PVERSION "${VERSION_GIT} (%Y-%m-%d %H:%M:%S)")
	endif()
	message(STATUS "Git Version: ${PVERSION}")
endif()

################################################################################

find_program(MOLD_LINKER mold)
find_program(LLD_LINKER lld)
find_program(CCACHE_PROGRAM ccache)

if (CCACHE_PROGRAM AND ENABLE_USE_CCACHE)
    # 针对 C 和 C++ 分别开启 ccache
    message(STATUS "Using ccache: ${CCACHE_PROGRAM}")
    set(CMAKE_C_COMPILER_LAUNCHER   "${CCACHE_PROGRAM}")
    set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
endif()


################################################################################

if (ENABLE_MIMALLOC_STATIC)
	if (UNIX AND NOT APPLE)
		# 必须先编译安装 mimalloc 库(这里限制版本为2.1.2) 编译安装办法：
		# git clone https://github.com/microsoft/mimalloc.git
		# mkdir build && cd build && git checkout tags/v2.1.2
		# cmake -DCMAKE_BUILD_TYPE=Release -DMI_BUILD_STATIC=ON -DMI_BUILD_SHARED=OFF -DMI_BUILD_TESTS=OFF -DMI_BUILD_OBJECT=ON ..
		# make -j4 && make install
		set(MIMALLOC_OBJECT "/usr/local/lib/mimalloc-2.1/mimalloc.o")
		set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MIMALLOC_OBJECT} -lpthread")
	else()
		message(FATAL_ERROR "mimalloc only support linux!!!")
	endif()
endif()

################################################################################

if (ENABLE_SNMALLOC_STATIC)
	set(SNMALLOC_HEADER_ONLY_LIBRARY ON)

	add_definitions(-DUSE_SNMALLOC)
	add_definitions(-DSNMALLOC_USE_WAIT_ON_ADDRESS=1)
	add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/snmalloc EXCLUDE_FROM_ALL)

	link_libraries(snmalloc)
	include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/snmalloc)
endif()

################################################################################

if (ENABLE_USE_SYSTEMD_LOG)
	add_definitions(-DUSE_SYSTEMD_LOGGING)
	link_libraries(systemd)
endif()

################################################################################

if (UNIX AND NOT APPLE)
	if (ENABLE_USE_PAM_AUTH)
		add_definitions(-DUSE_PAM_AUTH)
		link_libraries(pam)
	endif()
endif()

################################################################################

if (WIN32)
	set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

	add_definitions(
		-DWIN32_LEAN_AND_MEAN
		-D_WIN32_WINNT=0x0A00
		#-DNOMINMAX # Comment out NOMINMAX for wolfSSL dependency on min/max macro in MSVC.
		-DUNICODE
		-D_UNICODE
	)

	add_definitions(
		-DBOOST_ALL_STATIC_LINK
		-DBOOST_THREAD_USE_LIB
		-DBOOST_FILESYSTEM_STATIC_LINK
	)

endif()

################################################################################

if (MSVC)
	set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

	add_definitions(
		-D_CRT_SECURE_NO_DEPRECATE
		-D_CRT_SECURE_NO_WARNINGS
		-D_CRT_NONSTDC_NO_DEPRECATE
		-D_CRT_NONSTDC_NO_WARNINGS
		-D_SCL_SECURE_NO_DEPRECATE
		-D_SCL_SECURE_NO_WARNINGS
	)

	add_definitions(
		-D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
		-D_SILENCE_ALL_CXX23_DEPRECATION_WARNINGS
		-D_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
		-D_SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS
	)

	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP /Zc:__cplusplus")
	message(STATUS "Using parallel compiling (/MP)")
	set(CMAKE_CXX_STACK_SIZE "100000000") #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:100000000")
	message(STATUS "Set stack size: 100000000 bytes")

	CHECK_CXX_COMPILER_FLAG(/std:c++20 COMPILER_HAS_STD_CXX20)

	if (COMPILER_HAS_STD_CXX20)
		set(CMAKE_CXX_STANDARD 20)
		set(CMAKE_CXX_STANDARD_REQUIRED ON)
		message(STATUS "Set default cxx standard: C++20")
	elseif (MSVC_VERSION GREATER_EQUAL "1900")
		set(CMAKE_CXX_STANDARD 17)
		set(CMAKE_CXX_STANDARD_REQUIRED ON)
		message(STATUS "Set default cxx standard: C++17")
	endif()
endif()

################################################################################

CHECK_CXX_COMPILER_FLAG(-fvisibility-inlines-hidden COMPILER_HAS_VISIBILITY_INLINE_HIDDEN)
CHECK_CXX_COMPILER_FLAG(-fvisibility=hidden COMPILER_HAS_VISIBILITY_HIDDEN)
CHECK_CXX_COMPILER_FLAG(-fdiagnostics-color=always COMPILER_HAS_COLOR)
CHECK_CXX_COMPILER_FLAG(-fcoroutines COMPILER_HAS_FCOROUTINES)
CHECK_CXX_COMPILER_FLAG(-fcoroutines-ts COMPILER_HAS_FCOROUTINES_TS)
CHECK_CXX_COMPILER_FLAG(-std=c++20 COMPILER_HAS_STD_CXX20)

if (${COMPILER_HAS_VISIBILITY_INLINE_HIDDEN})
	SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
endif()

if (${COMPILER_HAS_VISIBILITY_HIDDEN})
	SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
endif()

if (${COMPILER_HAS_COLOR})
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
endif()

if (ENABLE_SYSTEMD_LOGGING)
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_SYSTEMD_LOGGING")
endif()

################################################################################

if (NOT MSVC)
	if(NOT APPLE)
		if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
			if (ENABLE_BUILD_WITH_LIBCXX)
				set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
				CHECK_LINKER_FLAG(CXX "-rtlib=compiler-rt" IS_COMPILER_RT_SUPPORTED)

				if (IS_COMPILER_RT_SUPPORTED)
					message(STATUS "clang supports compiler-rt, use it")
					add_link_options(-rtlib=compiler-rt -unwindlib=libunwind)
				endif()
			else()
				set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
				if (ENABLE_STATIC_LINK_TO_GCC)
					set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
				endif()
			endif()
		elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
			if (MINGW)
				set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libstdc++")
				add_compile_options(-Wa,-mbig-obj)
			else()
				set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
			endif()
			if (ENABLE_STATIC_LINK_TO_GCC)
				set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
			endif()
		endif()

		if (ENABLE_REUSEPORT)
			add_definitions(-DENABLE_REUSEPORT)
		endif()
	endif()
	if (ANDROID)
		add_definitions(-DDISABLE_WRITE_LOGGING)
		set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
	endif()
	if(COMPILER_HAS_STD_CXX20)
		set(CMAKE_CXX_STANDARD 20)
		add_definitions(-DUSE_STD_STRING_VIEW)
		message(STATUS "Set default cxx standard: C++20")
	else()
		message(FATAL_ERROR "need at least GCC 11 or clang 14")
	endif()

	if (ENABLE_MOLD)
		if (MOLD_LINKER)
			message(STATUS "Using the mold linker")
			set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=mold")
		endif()
	endif()

	if (ENABLE_LLD)
		if (LLD_LINKER)
			message(STATUS "Using the lld linker")
			set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
		endif()
	endif()
endif(NOT MSVC)

################################################################################
# 全局使用静态链接库

set(BUILD_SHARED_LIBS OFF)

################################################################################
# 使用 system openssl

if (ENABLE_USE_OPENSSL)
	if (ENABLE_SYSTEM_OPENSSL)
		find_package(OpenSSL)
	else()
		set(OpenSSL_FOUND TRUE)
		add_subdirectory(third_party/openssl)
		if (NOT MSVC AND NOT APPLE)
			if (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
				set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-libs,ALL ${CMAKE_SHARED_LINKER_FLAGS}")
				set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--exclude-libs,ALL ${CMAKE_MODULE_LINKER_FLAGS}")
				set(CMAKE_EXE_LINKER_FLAGS "-Wl,--exclude-libs,ALL ${CMAKE_EXE_LINKER_FLAGS}")
			endif()
		endif()
	endif()

	message(STATUS "Using openssl...")
endif()

################################################################################
# 使用 wolfssl

if (ENABLE_USE_WOLFSSL)

	set(WOLFSSL_EXAMPLES OFF)
	set(WOLFSSL_CRYPT_TESTS OFF)

	# 打开 wolfssl 的 asio 支持, 它会自动定义 asio 所用到的 openssl 函数以及相关的宏.
	set(WOLFSSL_ASIO ON)
	# OpenSSL_FOUND 设置为 TRUE, 以便在编译 asio 时, 添加 ssl 代码的编译.
	set(OpenSSL_FOUND TRUE)

	# 必须定义 BOOST_ASIO_USE_WOLFSSL 以便 asio 使用 wolfssl.
	add_definitions(-DBOOST_ASIO_USE_WOLFSSL)

	# 打开 TLSX 以允许 alpn 设置.
	set(WOLFSSL_TLSX ON)

	# gcc 编译时 wolfssl 会有一些 stringop-overflow 警告, 这里忽略掉.
	if (NOT MSVC AND NOT APPLE)
		if (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
			set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-stringop-overflow -Wno-stringop-overread -Wno-maybe-uninitialized")
		endif()
	endif()

	add_subdirectory(third_party/wolfssl)

	# WOLFSSL_INCLUDE_DIRS 用于 wolfssl 的头文件包含.
	set(WOLFSSL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/wolfssl/wolfssl/)

	# WOLFSSL_LIBRARIES 用于 wolfssl 的库文件包含.
	set(WOLFSSL_LIBRARIES wolfssl::wolfssl)

	add_library(OpenSSL::SSL ALIAS wolfssl)
	add_library(OpenSSL::Crypto ALIAS wolfssl)

	# 包含 wolfssl 的头文件和库文件.
	include_directories(${WOLFSSL_INCLUDE_DIRS})
	link_libraries(${WOLFSSL_LIBRARIES})

	message(STATUS "Using wolfssl...")
endif()


################################################################################

if (ENABLE_USE_BORINGSSL)
	set(OPENSSL_FOUND TRUE)
	add_subdirectory(third_party/boringssl)

	# BORINGSSL_INCLUDE_DIRS 用于 boringssl 的头文件包含.
	set(BORINGSSL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/boringssl/include)

	# BORINGSSL_LIBRARIES 用于 boringssl 的库文件包含.
	set(BORINGSSL_LIBRARIES crypto ssl)

	add_library(OpenSSL::SSL ALIAS ssl)
	add_library(OpenSSL::Crypto ALIAS crypto)

	# 包含 boringssl 的头文件和库文件.
	include_directories(${BORINGSSL_INCLUDE_DIRS})
	link_libraries(${BORINGSSL_LIBRARIES})

	message(STATUS "Using boringssl...")
endif()

################################################################################
# 使用 boost asio 和 boost beast

if (ENABLE_BUILD_TESTS)
	set(USE_BOOST_TEST ON)
endif()

if (ENABLE_ASIO_HANDLER_TRACKING)
	add_definitions(-DBOOST_ASIO_ENABLE_HANDLER_TRACKING)
endif()

set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)

#默认使用 boost.filesystem 而不是 std.filesystem, 这是因为
#std.filesystem 在 GCC-12.3 以下的版本在非 ASCII 中会构造失败
#参考链接:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95048
add_definitions(-DUSE_BOOST_FILESYSTEM)

#独立编译asio时, 必须要在使用者项目定义, 否则会将
#定义BOOST_ASIO_HEADER_ONLY, 使用者将会导致符号冲突.

add_definitions(-DBOOST_ASIO_SEPARATE_COMPILATION)
add_definitions(-DBOOST_BEAST_SEPARATE_COMPILATION)

#此BOOST_ASIO_DYN_LINK只有在编译asio为动态链接的时候
#才能启用, 它在msvc下将BOOST_ASIO_DECL分别自动作为
#dllimport、dllexport添加.
#add_definitions(-DBOOST_ASIO_DYN_LINK)

add_definitions(-DBOOST_LOCALE_HIDE_AUTO_PTR)
add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
add_definitions(-DBOOST_DISABLE_PRAGMA_MESSAGE)
add_definitions(-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
add_definitions(-DBOOST_PROCESS_USE_STD_FS)
if (ENABLE_USE_IO_URING)
	find_package(IOUring)

	if (IOUring_FOUND)
		message(STATUS "Linux using io_uring...")
		add_definitions(-DBOOST_ASIO_HAS_IO_URING -DBOOST_ASIO_DISABLE_EPOLL)
		link_libraries(${IOUring_LIBRARIES})
	endif()
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
	add_definitions(-DBOOST_ASIO_HAS_CO_AWAIT)
endif()

set(BOOST_IOSTREAMS_ENABLE_ZSTD OFF)
set(BOOST_IOSTREAMS_ENABLE_LZMA OFF)
set(BOOST_IOSTREAMS_ENABLE_BZIP2 OFF)
set(BOOST_IOSTREAMS_ENABLE_ZLIB OFF)

set(BOOST_ASIO_BUILD_CONTEXT OFF)
set(BOOST_EXCLUDE_LIBRARIES "context;coroutine;fiber;iostreams;graph;math;stacktrace;redis;mysql;multiprecision;log;iostreams;charconv;locale")

add_subdirectory(third_party/boost EXCLUDE_FROM_ALL)

set_property(TARGET boost_assert PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_container PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_atomic PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_chrono PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_core PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_date_time PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_exception PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_filesystem PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_json PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_url PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_nowide PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_program_options PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_system PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_thread PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_variant2 PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_unordered PROPERTY FOLDER "third_party/boost")
set_property(TARGET boost_optional PROPERTY FOLDER "third_party/boost")

################################################################################
# 使用 Threads

find_package(Threads)
link_libraries(${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})

################################################################################
# 使用 tcmalloc/jemalloc

if (ENABLE_TCMALLOC_STATIC)
	find_package(Tcmalloc)
	link_libraries(${Tcmalloc_LIBRARY})
endif()

if (ENABLE_JEMALLOC_STATIC)
	find_package(JeMalloc)
	link_libraries(${JEMALLOC_LIBRARIES})
endif()

################################################################################
# 使用 zlib

if (WIN32 OR NOT ENABLE_SYSTEM_ZLIB)

	set(ZLIB_BUILD_TESTING OFF)
	set(ZLIB_BUILD_SHARED OFF)
	set(ZLIB_INSTALL OFF)
	add_subdirectory(third_party/zlib EXCLUDE_FROM_ALL)

	set(ZLIB_LIBRARIES zlibstatic)
	set(ZLIB_INCLUDE_DIRS
		${CMAKE_CURRENT_SOURCE_DIR}/third_party/zlib
		${CMAKE_CURRENT_SOURCE_DIR}/third_party/zlib/contrib/minizip
	)

	set_property(TARGET zlibstatic PROPERTY FOLDER "third_party")

else()
	find_package(ZLIB REQUIRED)
endif()

################################################################################
# 使用 fmt

add_subdirectory(third_party/fmt)
set(FMT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/fmt/include)
set(FMT_LIBRARIES fmt)

################################################################################
# 添加 proxy 项目

add_subdirectory(proxy)

################################################################################
# 添加 include 目录

include_directories(third_party
	${ZLIB_INCLUDE_DIRS}
	${PROXY_INCLUDE_DIRS}
	${FMT_INCLUDE_DIRS}
)

################################################################################
# 添加 link 项目

link_libraries(
	${FMT_LIBRARIES}
	${ZLIB_LIBRARIES}
	${PROXY_LIBRARIES}
)

################################################################################
# windows 下的链接库

if (WIN32)

	if (MINGW)
		link_libraries(
			secur32
			ws2_32
			mswsock
			bcrypt
			iphlpapi
		)
	else()
		link_libraries(
			Secur32.lib
			Bcrypt.lib
			Crypt32.lib
			Winmm.lib
			Mswsock.lib
		)
	endif()
elseif (UNIX AND NOT APPLE)
	# aviod link std::filesystem fail.
	set(std_fs_workaround "")
	if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
		set(std_fs_workaround stdc++fs)
	endif()

	link_libraries(
		${std_fs_workaround}
	)
endif()

if (ENABLE_LINKE_TO_LIBATOMIC)
	link_libraries(atomic)
endif()

################################################################################
# 设置输出目录

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

if (WIN32)
	set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/debug)
	set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/release)
endif()

################################################################################
# 添加 server 项目

add_subdirectory(server)

################################################################################
# 添加 example 项目

if (ENABLE_BUILD_EXAMPLES)
	add_subdirectory(example)
endif()

################################################################################
# 安装 proxy_server 服务

configure_file(proxy.service.in proxy-server@.service)

install(TARGETS proxy_server RUNTIME DESTINATION bin)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/proxy-server@.service DESTINATION /usr/lib/systemd/system/)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/doc/server.conf.example DESTINATION /etc/proxy_server/)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/doc/client.conf.example DESTINATION /etc/proxy_server/)
