#
# libwebsockets - small server side websockets and web server implementation
#
# Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#

include_directories(.)

macro(add_subdir_include_dirs arg1)
	add_subdirectory(${arg1})
	list(APPEND LWS_LIB_BUILD_INC_PATHS ${_CMAKE_INC_LIST}) 
endmacro()



set(LWS_LIB_INCLUDES "")
set(LWS_LIB_BUILD_INC_PATHS_TEMP "")

#
# Plat specific build items
#

if (LWS_PLAT_FREERTOS)
	add_subdir_include_dirs(plat/freertos)
	if (ESP_PLATFORM)
		list(APPEND LWS_ESP_IDF_DIRS
		    $ENV{IDF_PATH}/components/freertos/include
		    $ENV{IDF_PATH}/components/esp_hw_support/include/soc/
		    $ENV{IDF_PATH}/components/esp_common/include
		    $ENV{IDF_PATH}/components/esp_timer/include
		    $ENV{IDF_PATH}/components/soc/include
		    $ENV{IDF_PATH}/components/soc/src/esp32/include
		    $ENV{IDF_PATH}/components/lwip/port/esp32/include
		    $ENV{IDF_PATH}/components/lwip/lwip/src/include
		    $ENV{IDF_PATH}/components/lwip/port/esp32/include
		    ${CMAKE_BINARY_DIR}/config
		    $ENV{IDF_PATH}/components/esp_rom/include
		    $ENV{IDF_PATH}/components/esp_system/include
		    $ENV{IDF_PATH}/components/lwip/include/apps/sntp
		    $ENV{IDF_PATH}/components/soc/soc/esp32/include
		    $ENV{IDF_PATH}/components/heap/include
		    $ENV{IDF_PATH}/components/mbedtls/mbedtls/include
		    $ENV{IDF_PATH}/components/mbedtls/port/include
		    $ENV{IDF_PATH}/components/esp_wifi/include
		    $ENV{IDF_PATH}/components/esp_event/include
		    $ENV{IDF_PATH}/components/esp_netif/include
		    $ENV{IDF_PATH}/components/esp_eth/include
		    $ENV{IDF_PATH}/components/driver/include
		    $ENV{IDF_PATH}/components/soc/soc/include
		    $ENV{IDF_PATH}/components/tcpip_adapter/include
		    $ENV{IDF_PATH}/components/lwip/include/apps
		    $ENV{IDF_PATH}/components/nvs_flash/include
		    $ENV{IDF_PATH}/components/esp32/include
		    $ENV{IDF_PATH}/components/spi_flash/include
		    $ENV{IDF_PATH}/components/mdns/include
		    $ENV{IDF_PATH}/components/lwip/lwip/src/include)

		# IDF v6 renamed the newlib component to esp_libc; its
		# platform_include carries esp_newlib.h / esp_libc.h and the
		# libc override headers.  Pointing at the old dir on v6 loses
		# those, so esp_newlib.h is not found and the toolchain's newlib
		# sysroot headers get mixed in with picolibc's.
		if (EXISTS $ENV{IDF_PATH}/components/esp_libc)
			list(APPEND LWS_ESP_IDF_DIRS
			    $ENV{IDF_PATH}/components/esp_libc/platform_include
			    $ENV{IDF_PATH}/components/esp_libc/include)
		else()
			# Not lwip's own header dir: on the search path it makes
			# <errno.h> resolve to lwip/errno.h, whose plain
			# `extern int errno` can't link against a thread-local
			# libc errno.  Nothing in lws includes a bare lwip header
			# name.
			list(APPEND LWS_ESP_IDF_DIRS
			    $ENV{IDF_PATH}/components/newlib/platform_include)
		endif()

		# mbedtls 4 (IDF v6) keeps the crypto headers, platform_util.h
		# among them, in the TF-PSA-Crypto submodule.  Needed here so
		# the configure-time header checks below can see them.
		set(_lws_tfpsa $ENV{IDF_PATH}/components/mbedtls/mbedtls/tf-psa-crypto)
		if (EXISTS ${_lws_tfpsa})
			list(APPEND LWS_ESP_IDF_DIRS
			    ${_lws_tfpsa}/include
			    ${_lws_tfpsa}/drivers/builtin/include)
		endif()

		    include_directories(${LWS_ESP_IDF_DIRS})

		    list(APPEND CMAKE_REQUIRED_INCLUDES ${LWS_ESP_IDF_DIRS})

	endif()

	
else()
	if (LWS_PLAT_BAREMETAL)
		#		add_subdir_include_dirs(plat/baremetal)
	else()
		if (LWS_PLAT_OPTEE)
			add_subdir_include_dirs(plat/optee)
		else()
			if (WIN32)
				add_subdir_include_dirs(plat/windows)
			else()
				add_subdir_include_dirs(plat/unix)
			endif()
		endif()
	endif()
endif()

if (LIB_LIST)
	set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST} ${CMAKE_REQUIRED_LIBRARIES})
endif()

if (LWS_WITH_ZLIB)
	if (LWS_WITH_BUNDLED_ZLIB)
		if (WIN32)
			# it's trying to delete internal zlib entry
			LIST(REMOVE_AT CMAKE_REQUIRED_LIBRARIES 0 )
		endif()
	endif()
endif()


# ideally we want to use pipe2()

CHECK_C_SOURCE_COMPILES("
	#ifndef _GNU_SOURCE
	#define _GNU_SOURCE
	#endif
	#include <unistd.h>
	int main(void) {
		int fd[2];
		return pipe2(fd, 0);
	}" LWS_HAVE_PIPE2)

# ... and accept4(), so the accepted fd is CLOEXEC atomically, and cannot be
# inherited by a spawn racing on another pt

CHECK_C_SOURCE_COMPILES("
	#ifndef _GNU_SOURCE
	#define _GNU_SOURCE
	#endif
	#include <sys/types.h>
	#include <sys/socket.h>
	int main(void) {
		struct sockaddr sa;
		socklen_t sl = (socklen_t)sizeof(sa);
		return accept4(0, &sa, &sl, SOCK_CLOEXEC);
	}" LWS_HAVE_ACCEPT4)

# tcp keepalive needs this on linux to work practically... but it only exists
# after kernel 2.6.37

CHECK_C_SOURCE_COMPILES("#include <netinet/tcp.h>\nint main(void) { return TCP_USER_TIMEOUT; }\n" LWS_HAVE_TCP_USER_TIMEOUT)
set(LWS_PUBLIC_INCLUDES "")
if (LWS_WITH_TLS)
	add_subdir_include_dirs(tls)
endif()

# Generate the lws_config.h that includes all the private compilation settings.
configure_file(
       "${PROJECT_SOURCE_DIR}/cmake/lws_config_private.h.in"
       "${PROJECT_BINARY_DIR}/lws_config_private.h")

list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/core)
list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/misc)
list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/system)
list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/media)
add_subdirectory(core)
add_subdirectory(misc)
if (LWS_WITH_TRANSCODE)
	set_source_files_properties(media/transcode/transcode.c PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-sign-conversion")
endif()

if (LWS_WITH_V4L2)
	set_source_files_properties(media/v4l2/v4l2.c PROPERTIES COMPILE_FLAGS "-Wno-unused-variable")
endif()

add_subdirectory(system)

if (LWS_WITH_DRIVERS)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/drivers)
	add_subdirectory(drivers)
endif()

if (LWS_WITH_NETWORK)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/core-net)
	add_subdirectory(core-net)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio)
	add_subdirectory(sansio)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/io)
	add_subdirectory(io)
endif()

if (LWS_WITH_JOSE)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/jose ${CMAKE_CURRENT_SOURCE_DIR}/jose/jwe)
	add_subdirectory(jose)
endif()

if (LWS_WITH_COSE)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/cose)
	add_subdirectory(cose)
endif()

if (LWS_ROLE_MQTT)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/mqtt)
endif()

if (LWS_ROLE_DBUS AND NOT LWS_PLAT_FREERTOS)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/io/dbus)
endif()

if (LWS_ROLE_H1 OR LWS_ROLE_H2 OR LWS_ROLE_H3)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/http)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/http/compression)
endif()

if (LWS_ROLE_H1)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/h1)
endif()

if (LWS_ROLE_H2)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/h2)
endif()

if (LWS_ROLE_WS)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/ws)
endif()

if (LWS_ROLE_RAW)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/raw-skt)
endif()

if (LWS_ROLE_RAW_FILE)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/io/raw-file)
endif()

if (LWS_WITH_CGI)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/io/cgi)
endif()

if (LWS_ROLE_RAW_PROXY)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/sansio/raw-proxy)
endif()

if (NOT LWS_WITHOUT_SERVER OR LWS_WITH_SECURE_STREAMS_PROCESS_API)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/io/listen)
endif()

if (LWS_WITH_SECURE_STREAMS)
include_directories(secure-streams)
endif()

list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP "${CMAKE_CURRENT_SOURCE_DIR}/../core")


add_subdir_include_dirs(event-libs)

if (LWS_WITH_SECURE_STREAMS)
	list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/secure-streams)
	add_subdirectory(secure-streams)
endif()

list(APPEND LWS_LIB_BUILD_INC_PATHS_TEMP ${CMAKE_CURRENT_SOURCE_DIR}/secure-streams/serialized/client)
add_subdirectory(secure-streams/serialized/client)

add_subdirectory(media)

#
# The sansIO half (READMEs/README.sans-io-split.md, "The headers"): every
# source under lib/sansio (SOURCES_SANSIO) compiles with LWS_SANSIO_CHECK, so
# IO's private prototypes and IO's half of the object are hidden from it,
# and an implicit declaration is an error: a sansIO call into IO past the
# interface fails the ordinary build, naming its line.  They are properties
# of the sources, so both library targets compile them that way, each with
# its own target defines (LWS_BUILDING_STATIC / LWS_BUILDING_SHARED) as well.
#
if (SOURCES_SANSIO)
	set_property(SOURCE ${SOURCES_SANSIO} APPEND PROPERTY
		     COMPILE_DEFINITIONS LWS_SANSIO_CHECK)
	if (MSVC)
		set_property(SOURCE ${SOURCES_SANSIO} APPEND PROPERTY
			     COMPILE_OPTIONS /we4013)
	elseif (CMAKE_COMPILER_IS_GNUCC OR COMPILER_IS_CLANG)
		set_property(SOURCE ${SOURCES_SANSIO} APPEND PROPERTY
			     COMPILE_OPTIONS -Werror=implicit-function-declaration)
	endif()
endif()

if (LWS_WITH_STATIC)
    if (LWS_STATIC_PIC)
        set(CMAKE_POSITION_INDEPENDENT_CODE ON)
    endif()

	add_library(websockets STATIC ${SOURCES})# ${HDR_PUBLIC})
	set_target_properties(websockets PROPERTIES LINKER_LANGUAGE C)
	list(APPEND LWS_LIBRARIES websockets)
	target_include_directories(websockets INTERFACE
		$<INSTALL_INTERFACE:${LWS_INSTALL_INCLUDE_DIR}>
		$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
		$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>
	)
	target_include_directories(websockets PRIVATE ${LWS_LIB_BUILD_INC_PATHS} ${LWS_LIB_BUILD_INC_PATHS_TEMP} ${CMAKE_CURRENT_SOURCE_DIR}/../core)
	target_compile_definitions(websockets PRIVATE LWS_BUILDING_STATIC)
	foreach(inc ${LWS_PUBLIC_INCLUDES})
		target_include_directories(websockets PUBLIC "$<BUILD_INTERFACE:${inc}>" "$<INSTALL_INTERFACE:${inc}>")
	endforeach()
	set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE)

	if (WIN32)
		# Windows uses the same .lib ending for static libraries and shared
		# library linker files, so rename the static library.
		set_target_properties(websockets
			PROPERTIES
			OUTPUT_NAME websockets_static)
	endif()
	
endif()

if (LWS_WITH_SHARED)
	if (NOT RESOURCES)
		set(RESOURCES "")
	endif()
	
	add_library(websockets_shared SHARED ${SOURCES} ${RESOURCES})# ${HDR_PUBLIC})
	set_target_properties(websockets_shared PROPERTIES LINKER_LANGUAGE C)
	list(APPEND LWS_LIBRARIES websockets_shared)
	target_include_directories(websockets_shared INTERFACE
		$<INSTALL_INTERFACE:${LWS_INSTALL_INCLUDE_DIR}>
		$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
		$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>
	)
	target_include_directories(websockets_shared PRIVATE ${LWS_LIB_BUILD_INC_PATHS} ${LWS_LIB_BUILD_INC_PATHS_TEMP} ${CMAKE_CURRENT_SOURCE_DIR}/../core)
	target_compile_definitions(websockets_shared PRIVATE LWS_BUILDING_SHARED)
	foreach(inc ${LWS_PUBLIC_INCLUDES})
		target_include_directories(websockets_shared PUBLIC "$<BUILD_INTERFACE:${inc}>" "$<INSTALL_INTERFACE:${inc}>")
	endforeach()
	set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE)

	# We want the shared lib to be named "libwebsockets"
	# not "libwebsocket_shared".
	set_target_properties(websockets_shared
		PROPERTIES
		OUTPUT_NAME websockets)

	if (WIN32)
		# Compile as DLL (export function declarations)
		set_property(
			TARGET websockets_shared
			APPEND PROPERTY COMPILE_DEFINITIONS
			LWS_DLL
			LWS_INTERNAL)
		target_compile_definitions(websockets_shared INTERFACE LWS_DLL)
	endif()

	if (APPLE)
		set_property(TARGET websockets_shared PROPERTY MACOSX_RPATH YES)
	endif()

	if (UNIX AND LWS_WITH_PLUGINS_API)
		set (CMAKE_POSITION_INDEPENDENT_CODE ON)
	endif()

endif()

#
# expose the library private include dirs to plugins, test apps etc that are
# part of the lib build but different targets 
#

if (LWS_WITH_SHARED)
	get_target_property(LWS_LIB_INCLUDES websockets_shared INCLUDE_DIRECTORIES)
else()
	get_target_property(LWS_LIB_INCLUDES websockets INCLUDE_DIRECTORIES)
endif()


# Set the so version of the lib.
# Equivalent to LDFLAGS=-version-info x:x:x

if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG)
	foreach(lib ${LWS_LIBRARIES})
		set_target_properties(${lib}
			PROPERTIES
			SOVERSION ${SOVERSION})
	endforeach()
endif()


# Setup the linking for all libs.
#
# The "at end" pieces go at the end of the lib list.  Some are already on it,
# from the top level appending them, or from being on both so feature checks
# could link against them, eg, gnutls: take those out first so each appears
# just once, at the end (Apple ld warns about duplicates)
#
if (LIB_LIST_AT_END)
	list(REMOVE_ITEM LIB_LIST ${LIB_LIST_AT_END})
endif()
list(APPEND LIB_LIST ${LIB_LIST_AT_END})
if (LWS_DEP_LIB_PATHS)
	foreach(libpath ${LWS_DEP_LIB_PATHS})
		list(APPEND LIB_LIST "-L${libpath}")
	endforeach()
endif()
set(STRIPPED_LIB_LIST "")
foreach(lib_path IN LISTS LIB_LIST)
	if(IS_ABSOLUTE "${lib_path}" AND NOT "${lib_path}" MATCHES "^-")
		get_filename_component(lib_name "${lib_path}" NAME)
		string(REGEX REPLACE "^lib" "" lib_name "${lib_name}")
		string(REGEX REPLACE "\\.so.*$" "" lib_name "${lib_name}")
		string(REGEX REPLACE "\\.dylib.*$" "" lib_name "${lib_name}")
		string(REGEX REPLACE "\\.a$" "" lib_name "${lib_name}")
		if (APPLE)
			list(APPEND STRIPPED_LIB_LIST "${lib_path}")
		else()
			list(APPEND STRIPPED_LIB_LIST "$<BUILD_INTERFACE:${lib_path}>$<INSTALL_INTERFACE:-l${lib_name}>")
		endif()
	else()
		list(APPEND STRIPPED_LIB_LIST "${lib_path}")
	endif()
endforeach()

foreach (lib ${LWS_LIBRARIES})
	#	target_link_libraries(${lib} PRIVATE ${LIB_LIST})
	target_link_libraries(${lib} ${STRIPPED_LIB_LIST})

	# On ESP-IDF, inherit the include dirs and defines IDF gives its own
	# consumers of the components lws uses, transitive requirements
	# included, so lws stops depending on where each IDF release keeps
	# its headers and sees the same mbedtls configuration
	# (MBEDTLS_CONFIG_FILE, TF_PSA_CRYPTO_CONFIG_FILE) as the rest of
	# the firmware.  Copied across as PRIVATE usage requirements rather
	# than linked: a link dependency would drag IDF's targets into the
	# install / build-tree exports below, which cannot describe them,
	# and LIB_LIST is off limits since it also feeds the try_compile
	# probes.  IDF links the component libraries into the firmware
	# itself.  Components absent from this IDF are skipped.
	if (LWS_PLAT_FREERTOS AND ESP_PLATFORM)
		foreach(_c freertos esp_libc newlib lwip mbedtls spi_flash
			   esp_hw_support hal soc esp_rom esp_system esp_common
			   esp_timer heap log esp_wifi esp_event esp_netif
			   esp_eth driver esp_driver_gpio esp_driver_spi
			   esp_driver_ledc esp_partition app_update
			   bootloader_support nvs_flash esp_app_format
			   esp_bootloader_format esp_mm xtensa riscv)
			if (TARGET idf::${_c})
				target_include_directories(${lib} PRIVATE
					$<TARGET_PROPERTY:idf::${_c},INTERFACE_INCLUDE_DIRECTORIES>)
				target_compile_definitions(${lib} PRIVATE
					$<TARGET_PROPERTY:idf::${_c},INTERFACE_COMPILE_DEFINITIONS>)
				target_compile_options(${lib} PRIVATE
					$<TARGET_PROPERTY:idf::${_c},INTERFACE_COMPILE_OPTIONS>)
			endif()
		endforeach()
	endif()
endforeach()

#
# The links-alone test (READMEs/README.sans-io-split.md, "The contract"): the
# sansIO half linked as a shared library of its own, websockets-sansio, from
# its sources, the substrate neither half owns and the platform's injected
# clock, random source and file access, with every unresolved symbol an
# error.  It links only when sansIO references nothing of IO's beyond what
# the io_ops table and those injected dependencies provide: the C tree's
# form of the boundary between a sansIO crate and an IO crate.
#
# The substrate is listed, not taken by directory: it is the minimal set the
# sansIO sources need, and each file in it must itself need nothing of IO's.
# Files this configuration does not build are skipped.
#
if (LWS_WITH_SANSIO_LINK_TEST AND LWS_WITH_NETWORK AND SOURCES_SANSIO)
	if (MSVC)
		message(STATUS "LWS_WITH_SANSIO_LINK_TEST: not on MSVC")
	else()
		set(_sio_substrate
			core/alloc.c
			core/buflist.c
			core/libwebsockets.c
			core/logs.c
			core/lws_dll2.c
			core/region.c
			core/vfs.c
			core-net/address.c
			core-net/client/client.c
			core-net/roles.c
			core-net/sorted-usec-list.c
			core-net/wsi-timeout.c
			misc/base64-decode.c
			misc/cache-ttl/lws-cache-ttl.c
			misc/lwsac/lwsac.c
			misc/lws-ring.c
			misc/prng.c
			misc/sha-1.c
			# fault injection's decisions are data, both halves
			# ask them
			system/fault-injection/fault-injection.c
			# the platform's clock, random source and file
			# access: injected dependencies, not requests
			plat/unix/unix-misc.c
			plat/unix/unix-file.c
			# the builtin cmdline handling installs it
			plat/unix/unix-crash.c
		)
		# the generic crypto is neither half's, whichever tls
		# library provides it
		foreach(_s ${SOURCES})
			if (_s MATCHES "^tls/(.*/)?lws-gen" OR
			    _s MATCHES "^tls/(chacha|poly1305)\\.c$")
				list(APPEND _sio_substrate ${_s})
			endif()
		endforeach()

		set(_sio_sources ${SOURCES_SANSIO})
		foreach(_s ${_sio_substrate})
			list(FIND SOURCES ${_s} _i)
			if (NOT _i EQUAL -1)
				list(APPEND _sio_sources ${_s})
			endif()
		endforeach()

		#
		# The allow-list: symbols sansIO still takes from outside
		# the ops, the substrate and the platform, each waiting on a
		# design decision rather than a move (README.sans-io-split.md,
		# "The contract").  They are provided to the link by a stub
		# library, websockets-sansio-allow, generated from these lists,
		# so the rest stays strict.  A symbol leaves the list when its
		# decision is made; one added to it is a new such decision.
		#
		# Secure streams is a layer over both halves, but sansIO calls
		# into it directly: the close tells a stream it disconnected
		# or was unreachable (lws_ss_event_helper(), lws_ss_backoff(),
		# lws_ss_destroy()), an h2 or ws server upgrade binds a stream
		# (lws_ss_server_accept_bind(), protocol_secstream_ws,
		# lws_ss_tag() in its logs) and tells it of the upgrade, acting
		# on its answer (_lws_ss_handle_state_ret_CAN_DESTROY_HANDLE()),
		# and the h1 client reports its
		# conmon to one (lws_conmon_ss_json()).  Whether that becomes
		# callbacks the stream layer registers, as any other protocol,
		# or something else, is open.
		#
		# The system state manager (sansio/state.c) announces its
		# transitions as SMD messages (lws_smd_msg_printf()); SMD wakes
		# the loop and talks to secure streams itself, so it is not
		# substrate as it stands.
		#
		# The worker pool (core-net/async-queue.c) takes the file
		# server's reads off the service thread
		# (lws_async_queue_submit()), but also runs IO's tls accepts
		# and wakes IO's loop when a job is done; it needs its jobs to
		# carry their own work and its wake to be a request of IO
		# before it is substrate.
		#
		set(LWS_SANSIO_LINK_ALLOW_FUNCS
			lws_ss_event_helper lws_ss_backoff lws_ss_destroy
			lws_ss_server_accept_bind lws_ss_tag lws_conmon_ss_json
			_lws_ss_handle_state_ret_CAN_DESTROY_HANDLE
			lws_smd_msg_printf
			lws_async_queue_submit)
		set(LWS_SANSIO_LINK_ALLOW_DATA
			protocol_secstream_ws)

		set(_sio_allow_c ${CMAKE_CURRENT_BINARY_DIR}/sansio-link-allow.c)
		set(_c "/* generated by lib/CMakeLists.txt: stand-ins for the symbols the\n * sansIO links-alone test allows, never run */\n\n")
		string(APPEND _c "#define LWS_SIO_ALLOW __attribute__((visibility(\"default\")))\n\n")
		foreach(_f ${LWS_SANSIO_LINK_ALLOW_FUNCS})
			string(APPEND _c "LWS_SIO_ALLOW void ${_f}(void);\n")
			string(APPEND _c "LWS_SIO_ALLOW void ${_f}(void) { }\n")
		endforeach()
		foreach(_d ${LWS_SANSIO_LINK_ALLOW_DATA})
			string(APPEND _c "LWS_SIO_ALLOW extern const char ${_d}[1];\n")
			string(APPEND _c "LWS_SIO_ALLOW const char ${_d}[1] = { 0 };\n")
		endforeach()
		file(WRITE ${_sio_allow_c}.tmp "${_c}")
		configure_file(${_sio_allow_c}.tmp ${_sio_allow_c} COPYONLY)
		add_library(websockets-sansio-allow SHARED ${_sio_allow_c})
		set_target_properties(websockets-sansio-allow PROPERTIES
				      LINKER_LANGUAGE C)

		add_library(websockets-sansio SHARED ${_sio_sources})
		set_target_properties(websockets-sansio PROPERTIES
				      LINKER_LANGUAGE C)
		target_include_directories(websockets-sansio PRIVATE
			${LWS_LIB_BUILD_INC_PATHS} ${LWS_LIB_BUILD_INC_PATHS_TEMP}
			${CMAKE_CURRENT_SOURCE_DIR}/../core
			${CMAKE_CURRENT_SOURCE_DIR}/../include
			${CMAKE_CURRENT_BINARY_DIR}/../include)
		foreach(inc ${LWS_PUBLIC_INCLUDES})
			target_include_directories(websockets-sansio PRIVATE ${inc})
		endforeach()
		target_include_directories(websockets-sansio INTERFACE
			$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
			$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>)
		target_compile_definitions(websockets-sansio PRIVATE
					   LWS_BUILDING_SHARED)
		if (APPLE)
			set(_sio_nu "-Wl,-undefined,error")
		else()
			set(_sio_nu "-Wl,--no-undefined")
		endif()
		set_property(TARGET websockets-sansio APPEND_STRING PROPERTY
			     LINK_FLAGS " ${_sio_nu}")
		target_link_libraries(websockets-sansio websockets-sansio-allow
				      ${STRIPPED_LIB_LIST})
		# the generated headers come from the library's build
		if (LWS_WITH_SHARED)
			add_dependencies(websockets-sansio websockets_shared)
		else()
			add_dependencies(websockets-sansio websockets)
		endif()
	endif()
endif()

#
# These will be available to parent projects including libwebsockets
# using add_subdirectory()
#
set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries")
if (LWS_WITH_STATIC)
	set(LIBWEBSOCKETS_LIBRARIES_STATIC websockets CACHE STRING "Libwebsocket static library")
endif()
if (LWS_WITH_SHARED)
	set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library")
endif()

# Install libs and headers.
install(TARGETS ${LWS_LIBRARIES}
		EXPORT LibwebsocketsTargets
		LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}" COMPONENT core
		ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}" COMPONENT core
		RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT core # Windows DLLs
		PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
		
	#set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries" PARENT_SCOPE)
set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files" PARENT_SCOPE)


if (UNIX OR MINGW)

# figure out pkfcfg required libs here

set(lws_requires "")
if (LWS_HAVE_LIBCAP)
	if (NOT lws_requires STREQUAL "")
		set(lws_requires "${lws_requires},libcap")
	else()
		set(lws_requires "libcap")
	endif()
endif()
if (LWS_HAVE_SYSTEMD_H)
	if (NOT lws_requires STREQUAL "")
		set(lws_requires "${lws_requires},libsystemd")
	else()
		set(lws_requires "libsystemd")
	endif()
endif()


# Generate and install pkgconfig.
# (This is not indented, because the tabs will be part of the output)
file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets.pc"
"prefix=\"${CMAKE_INSTALL_PREFIX}\"
exec_prefix=\${prefix}
libdir=${PKG_CONFIG_LIBDIR}
includedir=${PKG_CONFIG_INCLUDEDIR}

Name: libwebsockets
Description: Websockets server and client library
Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}

Libs: -L\${libdir} -lwebsockets
Cflags: -I\${includedir}
"
)
if (NOT ${lws_requires} STREQUAL "")
        file(APPEND "${PROJECT_BINARY_DIR}/libwebsockets.pc" "Requires: ${lws_requires}")
endif()


	install(FILES "${PROJECT_BINARY_DIR}/libwebsockets.pc"
		DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets_static.pc"
"prefix=\"${CMAKE_INSTALL_PREFIX}\"
exec_prefix=\${prefix}
libdir=${PKG_CONFIG_LIBDIR}
includedir=${PKG_CONFIG_INCLUDEDIR}

Name: libwebsockets_static
Description: Websockets server and client static library
Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}

Libs: -L\${libdir} -l:libwebsockets${CMAKE_STATIC_LIBRARY_SUFFIX}
Libs.private:
Cflags: -I\${includedir}
"
)

if (NOT ${lws_requires} STREQUAL "")
        file(APPEND "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" "Requires: ${lws_requires}")
endif()


	install(FILES "${PROJECT_BINARY_DIR}/libwebsockets_static.pc"
		DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

endif(UNIX OR MINGW)


# Keep explicit parent scope exports at end
#

set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} ${LWS_LIB_BUILD_INC_PATHS_TEMP} PARENT_SCOPE)

export_to_parent_intermediate()
if (DEFINED LWS_PLAT_UNIX)
	set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE)
	if (ILLUMOS)
		add_definitions("-D__illumos__")
	endif()
endif()
set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE)
set(LWS_HAVE_SSL_set_tlsext_host_name ${LWS_HAVE_SSL_set_tlsext_host_name} PARENT_SCOPE)
set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE)
set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols ${LWS_HAVE_mbedtls_ssl_conf_alpn_protocols} PARENT_SCOPE)
set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE)
set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE)
set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE)
set(LWS_HAVE_PIPE2 ${LWS_HAVE_PIPE2} PARENT_SCOPE)
set(LWS_HAVE_ACCEPT4 ${LWS_HAVE_ACCEPT4} PARENT_SCOPE)
set(LWS_LIBRARIES ${LWS_LIBRARIES} PARENT_SCOPE)
if (DEFINED WIN32_HELPERS_PATH)
	set(WIN32_HELPERS_PATH ${WIN32_HELPERS_PATH} PARENT_SCOPE)
endif()
if (DEFINED HDR_PRIVATE)
set(HDR_PRIVATE ${HDR_PRIVATE} PARENT_SCOPE)
endif()
if (DEFINED ZLIB_FOUND)
	set(ZLIB_FOUND ${ZLIB_FOUND} PARENT_SCOPE)
endif()
if (DEFINED LIB_LIST_AT_END)
set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE)
endif()
set(USE_WOLFSSL ${USE_WOLFSSL} PARENT_SCOPE)
set(LWS_DEP_LIB_PATHS ${LWS_DEP_LIB_PATHS} PARENT_SCOPE)

set(LWS_ROLE_QUIC ${LWS_ROLE_QUIC} PARENT_SCOPE)
set(LWS_WITH_HTTP3 ${LWS_WITH_HTTP3} PARENT_SCOPE)
set(LWS_ROLE_H3 ${LWS_ROLE_H3} PARENT_SCOPE)
set(LWS_ROLE_WT ${LWS_ROLE_WT} PARENT_SCOPE)
set(LWS_WITH_TLS_KEYLOG ${LWS_WITH_TLS_KEYLOG} PARENT_SCOPE)
