Bladeren bron

CMake build

This implements the CMake build for the project using the extra CMake
modules that have previously been added to the project.
Matt Clarkson 10 jaren geleden
bovenliggende
commit
e03cf46867
3 gewijzigde bestanden met toevoegingen van 803 en 0 verwijderingen
  1. 406 0
      CMakeLists.txt
  2. 277 0
      src/CMakeLists.txt
  3. 120 0
      test/CMakeLists.txt

+ 406 - 0
CMakeLists.txt

@@ -0,0 +1,406 @@
+# Determines what CMake APIs we can rely on
+cmake_minimum_required (VERSION 2.8.11)
+if (${CMAKE_VERSION} VERSION_GREATER 3.2.2)
+  cmake_policy(VERSION 3.2.2)
+endif()
+if (${CMAKE_VERSION} VERSION_GREATER 3.1 OR
+    ${CMAKE_VERSION} VERSION_EQUAL 3.1)
+  cmake_policy(SET CMP0054 NEW)
+endif()
+
+# Do not allow in source builds
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
+
+# Make sure we can import out CMake functions
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+# Load in the needed CMake modules
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+include(AddCCompilerFlag)
+include(AddCXXCompilerFlag)
+include(DetermineTargetArchitecture)
+include(CMakeDependentOption)
+
+# Set up the project
+project (civetweb)
+set(CIVETWEB_VERSION "1.7.0" CACHE STRING "The version of the civetweb library")
+string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" CIVETWEB_VERSION_MATCH "${CIVETWEB_VERSION}")
+if ("${CIVETWEB_VERSION_MATCH}" STREQUAL "")
+  message(FATAL_ERROR "Must specify a semantic version: major.minor.patch")
+endif()
+set(CIVETWEB_VERSION_MAJOR "${CMAKE_MATCH_1}")
+set(CIVETWEB_VERSION_MINOR "${CMAKE_MATCH_2}")
+set(CIVETWEB_VERSION_PATCH "${CMAKE_MATCH_3}")
+determine_target_architecture(CIVETWEB_ARCHITECTURE)
+
+# Detect the platform reliably
+if(NOT MACOSX AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+   SET(DARWIN YES)
+elseif(NOT BSD AND ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+    SET(FREEBSD YES)
+elseif(NOT LINUX AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+    SET(LINUX YES)
+endif()
+
+# C++ wrappers
+option(CIVETWEB_ENABLE_THIRD_PARTY_OUTPUT "Shows the output of third party dependency processing" OFF)
+
+# Max Request Size
+set(CIVETWEB_MAX_REQUEST_SIZE 16384 CACHE STRING
+  "The largest amount of content bytes allowed in a request")
+set_property(CACHE CIVETWEB_MAX_REQUEST_SIZE PROPERTY VALUE ${CIVETWEB_MAX_REQUEST_SIZE})
+message(STATUS "Max Request Size - ${CIVETWEB_MAX_REQUEST_SIZE}")
+
+# Thread Stack Size
+set(CIVETWEB_THREAD_STACK_SIZE 102400 CACHE STRING
+  "The stack size in bytes for each thread created")
+set_property(CACHE CIVETWEB_THREAD_STACK_SIZE PROPERTY VALUE ${CIVETWEB_THREAD_STACK_SIZE})
+message(STATUS "Thread Stack Size - ${CIVETWEB_THREAD_STACK_SIZE}")
+
+# C++ wrappers
+option(CIVETWEB_ENABLE_CXX "Enables the C++ wrapper library" OFF)
+message(STATUS "C++ wrappers - ${CIVETWEB_ENABLE_CXX}")
+
+# IP Version 6
+option(CIVETWEB_ENABLE_IPV6 "Enables the IP version 6 support" OFF)
+message(STATUS "IP Version 6 - ${CIVETWEB_ENABLE_IPV6}")
+
+# Websocket support
+option(CIVETWEB_ENABLE_WEBSOCKETS "Enable websockets connections" OFF)
+message(STATUS "Websockets support - ${CIVETWEB_ENABLE_WEBSOCKETS}")
+
+# Memory debugging
+option(CIVETWEB_ENABLE_MEMORY_DEBUGGING "Enable the memory debugging features" OFF)
+message(STATUS "Memory Debugging - ${CIVETWEB_ENABLE_MEMORY_DEBUGGING}")
+
+# LUA CGI support
+option(CIVETWEB_ENABLE_LUA "Enable Lua CGIs" OFF)
+message(STATUS "Lua CGI support - ${CIVETWEB_ENABLE_LUA}")
+
+# Link to the shared LUA library
+cmake_dependent_option(
+  CIVETWEB_ENABLE_LUA_SHARED  "Link to the shared LUA system library" OFF
+ CIVETWEB_ENABLE_LUA OFF)
+if (CIVETWEB_ENABLE_LUA)
+  message(STATUS "Linking shared Lua library - ${CIVETWEB_ENABLE_LUA_SHARED}")
+endif()
+
+# Lua Third Party Settings
+if (CIVETWEB_ENABLE_LUA)
+  if (NOT CIVETWEB_ENABLE_LUA_SHARED)
+    # Lua Version
+    set(CIVETWEB_LUA_VERSION 5.3.0 CACHE STRING
+      "The version of Lua to build and include statically")
+    set_property(CACHE CIVETWEB_LUA_VERSION PROPERTY VALUE ${CIVETWEB_LUA_VERSION})
+    message(STATUS "Lua Version - ${CIVETWEB_LUA_VERSION}")
+    mark_as_advanced(CIVETWEB_LUA_VERSION)
+
+    # Lua Verification Hash
+    set(CIVETWEB_LUA_MD5_HASH a1b0a7e92d0c85bbff7a8d27bf29f8af CACHE STRING
+      "The hash of Lua archive to be downloaded")
+    set_property(CACHE CIVETWEB_LUA_MD5_HASH PROPERTY VALUE ${CIVETWEB_LUA_MD5_HASH})
+    mark_as_advanced(CIVETWEB_LUA_MD5_HASH)
+  endif()
+
+  # Lua Filesystem Version
+  set(CIVETWEB_LUA_FILESYSTEM_VERSION 1.6.3 CACHE STRING
+    "The version of Lua Filesystem to build and include statically")
+  set_property(CACHE CIVETWEB_LUA_FILESYSTEM_VERSION PROPERTY VALUE ${CIVETWEB_LUA_FILESYSTEM_VERSION})
+  message(STATUS "Lua Filesystem Version - ${CIVETWEB_LUA_FILESYSTEM_VERSION}")
+  mark_as_advanced(CIVETWEB_LUA_FILESYSTEM_VERSION)
+
+  # Lua Filesystem Verification Hash
+  set(CIVETWEB_LUA_FILESYSTEM_MD5_HASH d0552c7e5a082f5bb2865af63fb9dc95 CACHE STRING
+    "The hash of Lua Filesystem archive to be downloaded")
+  set_property(CACHE CIVETWEB_LUA_FILESYSTEM_MD5_HASH PROPERTY VALUE ${CIVETWEB_LUA_FILESYSTEM_MD5_HASH})
+  mark_as_advanced(CIVETWEB_LUA_FILESYSTEM_MD5_HASH)
+
+  # Lua SQLite Version
+  set(CIVETWEB_LUA_SQLITE_VERSION 0.9.3 CACHE STRING
+    "The version of Lua SQLite to build and include statically")
+  set_property(CACHE CIVETWEB_LUA_SQLITE_VERSION PROPERTY VALUE ${CIVETWEB_LUA_SQLITE_VERSION})
+  message(STATUS "Lua SQLite Version - ${CIVETWEB_LUA_SQLITE_VERSION}")
+  mark_as_advanced(CIVETWEB_LUA_SQLITE_VERSION)
+
+  # Lua SQLite Verification Hash
+  set(CIVETWEB_LUA_SQLITE_MD5_HASH 43234ae08197dfce6da02482ed14ec92 CACHE STRING
+    "The hash of Lua SQLite archive to be downloaded")
+  set_property(CACHE CIVETWEB_LUA_SQLITE_MD5_HASH PROPERTY VALUE ${CIVETWEB_LUA_SQLITE_MD5_HASH})
+  mark_as_advanced(CIVETWEB_LUA_SQLITE_MD5_HASH)
+
+  # Lua XML Version
+  set(CIVETWEB_LUA_XML_VERSION 1.8.0 CACHE STRING
+    "The version of Lua XML to build and include statically")
+  set_property(CACHE CIVETWEB_LUA_XML_VERSION PROPERTY VALUE ${CIVETWEB_LUA_XML_VERSION})
+  message(STATUS "Lua XML Version - ${CIVETWEB_LUA_XML_VERSION}")
+  mark_as_advanced(CIVETWEB_LUA_XML_VERSION)
+
+  # Lua XML Verification Hash
+  set(CIVETWEB_LUA_XML_MD5_HASH 25e4c276c5d8716af1de0c7853aec2b4 CACHE STRING
+    "The hash of Lua XML archive to be downloaded")
+  set_property(CACHE CIVETWEB_LUA_XML_MD5_HASH PROPERTY VALUE ${CIVETWEB_LUA_XML_MD5_HASH})
+  mark_as_advanced(CIVETWEB_LUA_XML_MD5_HASH)
+
+  # SQLite Version
+  set(CIVETWEB_SQLITE_VERSION 3.8.9 CACHE STRING
+    "The version of SQLite to build and include statically")
+  set_property(CACHE CIVETWEB_SQLITE_VERSION PROPERTY VALUE ${CIVETWEB_SQLITE_VERSION})
+  message(STATUS "SQLite Version - ${CIVETWEB_SQLITE_VERSION}")
+  mark_as_advanced(CIVETWEB_SQLITE_VERSION)
+
+  # SQLite Verification Hash
+  set(CIVETWEB_SQLITE_MD5_HASH 02e9c3a6daa8b8587cf6bef828c2e33f CACHE STRING
+    "The hash of SQLite archive to be downloaded")
+  set_property(CACHE CIVETWEB_SQLITE_MD5_HASH PROPERTY VALUE ${CIVETWEB_SQLITE_MD5_HASH})
+  mark_as_advanced(CIVETWEB_SQLITE_MD5_HASH)
+endif()
+
+# SSL support
+option(CIVETWEB_ENABLE_SSL "Enables the secure socket layer" ON)
+message(STATUS "SSL support - ${CIVETWEB_ENABLE_SSL}")
+
+# Dynamically load or link the SSL libraries
+cmake_dependent_option(
+  CIVETWEB_ENABLE_SSL_DYNAMIC_LOADING "Dynamically loads the SSL library rather than linking it" ON
+  CIVETWEB_ENABLE_SSL OFF)
+if (CIVETWEB_ENABLE_SSL)
+  message(STATUS "Dynamically load SSL libraries - ${CIVETWEB_ENABLE_SSL_DYNAMIC_LOADING}")
+endif()
+
+# Unix systems can define the dynamic library names to load
+if (CIVETWEB_ENABLE_SSL_DYNAMIC_LOADING AND NOT DARWIN AND UNIX)
+  # SSL library name
+  set(CIVETWEB_SSL_SSL_LIB "libssl.so" CACHE STRING
+    "The name of the SSL library to load")
+  set_property(CACHE CIVETWEB_SSL_SSL_LIB PROPERTY VALUE ${CIVETWEB_SSL_SSL_LIB})
+  message(STATUS "SSL Library Name - ${CIVETWEB_SSL_SSL_LIB}")
+
+  # Crytography library name
+  set(CIVETWEB_SSL_CRYPTO_LIB "libcrypto.so" CACHE STRING
+    "The name of the SSL Cryptography library to load")
+  set_property(CACHE CIVETWEB_SSL_CRYPTO_LIB PROPERTY VALUE ${CIVETWEB_SSL_CRYPTO_LIB})
+  message(STATUS "SSL Cryptography Library Name - ${CIVETWEB_SSL_CRYPTO_LIB}")
+endif()
+
+# The C and C++ standards to use
+set(CIVETWEB_C_STANDARD auto CACHE STRING
+  "The C standard to use; auto determines the latest supported by the compiler")
+set_property(CACHE CIVETWEB_C_STANDARD PROPERTY STRINGS auto c11 c99 c89)
+set(CIVETWEB_CXX_STANDARD auto CACHE STRING
+  "The C++ standard to use; auto determines the latest supported by the compiler")
+set_property(CACHE CIVETWEB_CXX_STANDARD PROPERTY STRINGS auto c++14 c++11 c++98)
+
+# Configure the linker
+if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
+  find_program(GCC_AR gcc-ar)
+  if (GCC_AR)
+    set(CMAKE_AR ${GCC_AR})
+  endif()
+  find_program(GCC_RANLIB gcc-ranlib)
+  if (GCC_RANLIB)
+    set(CMAKE_RANLIB ${GCC_RANLIB})
+  endif()
+endif()
+
+# Configure the C compiler
+message(STATUS "Configuring C Compiler")
+if ("${CIVETWEB_C_STANDARD}" STREQUAL "auto")
+  add_c_compiler_flag(-std=c11)
+  if (NOT HAVE_C_FLAG_STD_C11)
+    add_c_compiler_flag(-std=c99)
+    if (NOT HAVE_C_FLAG_STD_C99)
+      add_c_compiler_flag(-std=c89)
+    endif()
+  endif()
+else()
+  add_c_compiler_flag(-std=${CIVETWEB_C_STANDARD})
+endif()
+add_c_compiler_flag(-Wall)
+add_c_compiler_flag(-Wextra)
+add_c_compiler_flag(-Wshadow)
+add_c_compiler_flag(-Wsign-conversion)
+add_c_compiler_flag(-Wmissing-prototypes)
+add_c_compiler_flag(-Weverything)
+add_c_compiler_flag(/W4)
+add_c_compiler_flag(-Wno-padded)
+add_c_compiler_flag(/Wd4820) # padding
+add_c_compiler_flag(-Wno-unused-macros)
+add_c_compiler_flag(-Wno-format-nonliteral)
+if (MINGW)
+  add_c_compiler_flag(-Wno-format)
+endif()
+add_c_compiler_flag(-Werror)
+add_c_compiler_flag(/WX)
+add_c_compiler_flag(-pedantic-errors)
+add_c_compiler_flag(-fvisibility=hidden)
+add_c_compiler_flag(-fstack-protector-strong RELEASE)
+add_c_compiler_flag(-flto RELEASE)
+add_c_compiler_flag(-fsanitize=undefined DEBUG)
+add_c_compiler_flag(-fsanitize=address DEBUG)
+if (HAVE_C_FLAG_FSANITIZE_ADDRESS)
+  add_c_compiler_flag(-static-asan DEBUG)
+endif()
+add_c_compiler_flag(-fstack-protector-all DEBUG)
+add_c_compiler_flag(-mwindows)
+
+# Coverage build type
+set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING
+    "Flags used by the C compiler during coverage builds."
+    FORCE)
+set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
+    "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
+    "Flags used for linking binaries during coverage builds."
+    FORCE)
+set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
+    "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
+    "Flags used by the shared libraries linker during coverage builds."
+    FORCE)
+mark_as_advanced(
+    CMAKE_CXX_FLAGS_COVERAGE
+    CMAKE_C_FLAGS_COVERAGE
+    CMAKE_EXE_LINKER_FLAGS_COVERAGE
+    CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
+set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
+    "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
+    FORCE)
+add_c_compiler_flag(--coverage COVERAGE)
+
+# Configure the C++ compiler
+if (CIVETWEB_ENABLE_CXX)
+  message(STATUS "Configuring C++ Compiler")
+  if ("${CIVETWEB_CXX_STANDARD}" STREQUAL "auto")
+    add_cxx_compiler_flag(-std=c++14)
+    if (NOT HAVE_CXX_FLAG_STD_CXX14)
+      add_cxx_compiler_flag(-std=c++11)
+      if (NOT HAVE_CXX_FLAG_STD_CXX11)
+        add_cxx_compiler_flag(-std=c++98)
+      endif()
+    endif()
+  else()
+    add_cxx_compiler_flag(-std=${CIVETWEB_CXX_STANDARD})
+  endif()
+  add_cxx_compiler_flag(-Wall)
+  add_cxx_compiler_flag(-Wextra)
+  add_cxx_compiler_flag(-Wshadow)
+  add_cxx_compiler_flag(-Wsign-conversion)
+  add_cxx_compiler_flag(-Wmissing-prototypes)
+  add_cxx_compiler_flag(-Weverything)
+  add_cxx_compiler_flag(/W4)
+  add_cxx_compiler_flag(-Wno-padded)
+  add_cxx_compiler_flag(/Wd4820) # padding
+  add_cxx_compiler_flag(-Wno-unused-macros)
+  add_cxx_compiler_flag(-Wno-format-nonliteral)
+  if (MINGW)
+    add_cxx_compiler_flag(-Wno-format)
+  endif()
+  add_cxx_compiler_flag(-Werror)
+  add_cxx_compiler_flag(/WX)
+  add_cxx_compiler_flag(-pedantic-errors)
+  add_cxx_compiler_flag(-Wzero-as-null-pointer-constant)
+  add_cxx_compiler_flag(-fvisibility=hidden)
+  add_cxx_compiler_flag(-fstack-protector-strong RELEASE)
+  add_cxx_compiler_flag(-flto RELEASE)
+  add_cxx_compiler_flag(-fsanitize=undefined DEBUG)
+  add_cxx_compiler_flag(-fsanitize=address DEBUG)
+  if (HAVE_CXX_FLAG_FSANITIZE_ADDRESS)
+    add_cxx_compiler_flag(-static-asan DEBUG)
+  endif()
+  add_cxx_compiler_flag(-fstack-protector-all DEBUG)
+  add_cxx_compiler_flag(-mwindows)
+  set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
+      "Flags used by the C++ compiler during coverage builds."
+      FORCE)
+  add_cxx_compiler_flag(--coverage COVERAGE)
+endif()
+
+# Set up the definitions
+if (${CMAKE_BUILD_TYPE} MATCHES "[Dd]ebug")
+  add_definitions(-DDEBUG)
+endif()
+if (HAVE_STDINT)
+  add_definitions(-DHAVE_STDINT)
+endif()
+if (CIVETWEB_ENABLE_IPV6)
+  add_definitions(-DUSE_IPV6)
+endif()
+if (CIVETWEB_ENABLE_WEBSOCKETS)
+  add_definitions(-DUSE_WEBSOCKET)
+endif()
+if (CIVETWEB_ENABLE_LUA)
+  add_definitions(-DUSE_LUA)
+endif()
+if (CIVETWEB_ENABLE_MEMORY_DEBUGGING)
+  add_definitions(-DMEMORY_DEBUGGING)
+endif()
+if (NOT CIVETWEB_ENABLE_SSL)
+  add_definitions(-DNO_SSL)
+elseif (NOT CIVETWEB_ENABLE_SSL_DYNAMIC_LOADING)
+  add_definitions(-DNO_SSL_DL)
+else()
+  if(CIVETWEB_SSL_SSL_LIB)
+    add_definitions(-DSSL_LIB="${CIVETWEB_SSL_SSL_LIB}")
+  endif()
+  if(CIVETWEB_SSL_CRYPTO_LIB)
+    add_definitions(-DCRYPTO_LIB="${CIVETWEB_SSL_CRYPTO_LIB}")
+  endif()
+endif()
+add_definitions(-DUSE_STACK_SIZE=${CIVETWEB_THREAD_STACK_SIZE})
+add_definitions(-DMAX_REQUEST_SIZE=${CIVETWEB_MAX_REQUEST_SIZE})
+
+# Build the targets
+add_subdirectory(src)
+
+# Enable the testing of the library/executable
+include(CTest)
+if (BUILD_TESTING)
+  # Check unit testing framework Version
+  set(CIVETWEB_CHECK_VERSION 0.9.14 CACHE STRING
+    "The version of Check unit testing framework to build and include statically")
+  set_property(CACHE CIVETWEB_CHECK_VERSION PROPERTY VALUE ${CIVETWEB_CHECK_VERSION})
+  message(STATUS "Check Unit Testing Framework Version - ${CIVETWEB_CHECK_VERSION}")
+  mark_as_advanced(CIVETWEB_CHECK_VERSION)
+
+  # Check unit testing framework Verification Hash
+  set(CIVETWEB_CHECK_MD5_HASH 38263d115d784c17aa3b959ce94be8b8 CACHE STRING
+    "The hash of Check unit testing framework archive to be downloaded")
+  set_property(CACHE CIVETWEB_CHECK_MD5_HASH PROPERTY VALUE ${CIVETWEB_CHECK_MD5_HASH})
+  mark_as_advanced(CIVETWEB_CHECK_MD5_HASH)
+
+  # Build the testing
+  add_subdirectory(test)
+endif()
+
+# Set up CPack
+include(InstallRequiredSystemLibraries)
+set(CPACK_PACKAGE_VENDOR "civetweb Contributors")
+set(CPACK_PACKAGE_CONTACT "civetweb@github.com")
+set(CPACK_PACKAGE_VERSION_MAJOR "${CIVETWEB_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${CIVETWEB_VERSION_MINOR}")
+set(CPACK_PACKAGE_VERSION_PATCH "${CIVETWEB_VERSION_PATCH}")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A HTTP library and server")
+set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.md")
+set(CPACK_STRIP_FILES TRUE)
+set(CPACK_PACKAGE_DEPENDS "openssl")
+if (CIVETWEB_ENABLE_LUA_SHARED)
+  set(CPACK_PACKAGE_DEPENDS "lua, ${CPACK_PACKAGE_DEPENDS}")
+endif()
+
+# RPM Packaging
+set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
+set(CPACK_RPM_PACKAGE_LICENSE "MIT")
+set(CPACK_RPM_PACKAGE_ARCHITECTURE "${CIVETWEB_ARCHITECTURE}")
+set(CPACK_RPM_PACKAGE_REQUIRES "${CPACK_PACKAGE_DEPENDS}")
+
+# Debian Packaging
+set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CIVETWEB_ARCHITECTURE}")
+set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/bel2125/civetweb")
+set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_PACKAGE_DEPENDS}")
+
+# WiX Packaging
+# TODO: www.cmake.org/cmake/help/v3.0/module/CPackWIX.html
+
+# Finalize CPack settings
+include(CPack)

+ 277 - 0
src/CMakeLists.txt

@@ -0,0 +1,277 @@
+# Check the headers we need
+include(CheckIncludeFiles)
+check_include_files(stdint.h HAVE_STDINT)
+
+# The C API library
+add_library(c-library civetweb.c)
+set_target_properties(c-library PROPERTIES
+  OUTPUT_NAME "civetweb"
+  VERSION ${CIVETWEB_VERSION}
+  SOVERSION ${CIVETWEB_VERSION}
+)
+if (BUILD_SHARED_LIBS)
+  target_compile_definitions(c-library PRIVATE CIVETWEB_DLL_EXPORTS)
+endif()
+target_include_directories(
+  c-library PUBLIC
+  ${PROJECT_SOURCE_DIR}/include)
+install(
+  TARGETS c-library
+  ARCHIVE DESTINATION lib
+  LIBRARY DESTINATION lib
+  RUNTIME DESTINATION bin
+  COMPONENT c-library)
+install(FILES
+  ${PROJECT_SOURCE_DIR}/include/civetweb.h
+  DESTINATION include
+  COMPONENT c-library)
+
+# Need Windows sockets if available
+find_package(WinSock)
+if (WINSOCK_FOUND)
+  target_link_libraries(c-library WINSOCK::WINSOCK)
+endif()
+
+# We need threading
+find_package(Threads)
+target_link_libraries(c-library ${CMAKE_THREAD_LIBS_INIT})
+
+# Need the realtime library if we're using timers
+find_package(LibRt)
+if (CIVETWEB_ENABLE_WEBSOCKETS AND CIVETWEB_ENABLE_LUA AND LIBRT_FOUND)
+  target_link_libraries(c-library LIBRT::LIBRT)
+endif()
+
+# We need to link OpenSSL if not dynamically loading
+if (CIVETWEB_ENABLE_SLL AND NOT CIVETWEB_ENABLE_OPENSLL_DYNAMIC_LOADING)
+  find_package(OpenSSL)
+  target_link_libraries(c-library ${OPENSSL_LIBRARIES})
+else()
+  find_package(LibDl)
+  if (LIBDL_FOUND)
+    target_link_libraries(c-library LIBDL::LIBDL)
+  endif()
+endif()
+
+# If Lua support is needed we build some extra Lua libraries
+if (CIVETWEB_ENABLE_LUA)
+  include(ExternalProject)
+
+  # Determine if we should print to the output
+  if (CIVETWEB_ENABLE_THIRD_PARTY_OUTPUT)
+    set(THIRD_PARTY_LOGGING 0)
+  else()
+    set(THIRD_PARTY_LOGGING 1)
+  endif()
+
+  # If Lua is static we must build it from source
+  if (NOT CIVETWEB_ENABLE_LUA_SHARED)
+    if (LINUX)
+      set(LUA_MAKE_TARGET linux)
+    elseif(DARWIN)
+      set(LUA_MAKE_TARGET macosx)
+    elseif(FREEBSD)
+      set(LUA_MAKE_TARGET freebsd)
+    elseif(WINDOWS)
+      set(LUA_MAKE_TARGET mingw)
+    elseif(UNIX)
+      set(LUA_MAKE_TARGET posix)
+    else()
+      set(LUA_MAKE_TARGET generic)
+    endif()
+    set(LUA_BUILD_COMMAND "${CMAKE_MAKE_PROGRAM};${LUA_MAKE_TARGET}")
+    if (BUILD_SHARED_LIBS)
+      set(LUA_BUILD_COMMAND "${LUA_BUILD_COMMAND};MYCFLAGS=-fPIC")
+    endif()
+    ExternalProject_Add(lua
+      URL "http://www.lua.org/ftp/lua-${CIVETWEB_LUA_VERSION}.tar.gz"
+      URL_MD5 ${CIVETWEB_LUA_MD5_HASH}
+      PREFIX "${CMAKE_BINARY_DIR}/third_party"
+      CONFIGURE_COMMAND ""
+      BUILD_COMMAND ${LUA_BUILD_COMMAND}
+      BUILD_IN_SOURCE 1
+      INSTALL_COMMAND make install "INSTALL_TOP=<INSTALL_DIR>"
+      LOG_DOWNLOAD ${THIRD_PARTY_LOGGING}
+      LOG_UPDATE ${THIRD_PARTY_LOGGING}
+      LOG_CONFIGURE ${THIRD_PARTY_LOGGING}
+      LOG_BUILD ${THIRD_PARTY_LOGGING}
+      LOG_TEST ${THIRD_PARTY_LOGGING}
+      LOG_INSTALL ${THIRD_PARTY_LOGGING})
+    ExternalProject_Get_Property(lua INSTALL_DIR)
+    set(LUA_INSTALL_DIR ${INSTALL_DIR})
+    unset(INSTALL_DIR)
+    link_directories("${LUA_INSTALL_DIR}/lib")
+    include_directories("${LUA_INSTALL_DIR}/include")
+    set(LUA_LIBRARIES "${LUA_INSTALL_DIR}/lib/liblua.a")
+    add_dependencies(c-library lua)
+  else()
+    find_package(Lua)
+  endif()
+
+  # Lua Filesystem Support
+  string(REPLACE "." "_" LUA_FILESYSTEM_VERSION_UNDERSCORE ${CIVETWEB_LUA_FILESYSTEM_VERSION})
+  ExternalProject_Add(luafilesystem
+    URL "https://github.com/keplerproject/luafilesystem/archive/v_${LUA_FILESYSTEM_VERSION_UNDERSCORE}.tar.gz"
+    URL_MD5 ${CIVETWEB_LUA_FILESYSTEM_MD5_HASH}
+    PREFIX "${CMAKE_BINARY_DIR}/third_party"
+    PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+      "${CMAKE_SOURCE_DIR}/cmake/luafilesystem/CMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
+    CMAKE_ARGS
+      "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
+      "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>"
+    LOG_DOWNLOAD ${THIRD_PARTY_LOGGING}
+    LOG_UPDATE ${THIRD_PARTY_LOGGING}
+    LOG_CONFIGURE ${THIRD_PARTY_LOGGING}
+    LOG_BUILD ${THIRD_PARTY_LOGGING}
+    LOG_TEST ${THIRD_PARTY_LOGGING}
+    LOG_INSTALL ${THIRD_PARTY_LOGGING})
+  ExternalProject_Get_Property(luafilesystem INSTALL_DIR)
+  set(LUA_FILESYSTEM_INSTALL_DIR ${INSTALL_DIR})
+  unset(INSTALL_DIR)
+  link_directories("${LUA_FILESYSTEM_INSTALL_DIR}/lib")
+  include_directories("${LUA_FILESYSTEM_INSTALL_DIR}/include")
+  set(LUA_LIBRARIES "${LUA_LIBRARIES};${LUA_FILESYSTEM_INSTALL_DIR}/lib/libluafilesystem.a")
+  add_dependencies(c-library luafilesystem)
+
+  # Lua SQLite Support
+  if (${CIVETWEB_LUA_SQLITE_VERSION} VERSION_EQUAL "0.9.3")
+    set(LUA_SQLITE_FILENAME lsqlite3_fsl09w.zip)
+  elseif (${CIVETWEB_LUA_SQLITE_VERSION} VERSION_EQUAL "0.9.2")
+    set(LUA_SQLITE_FILENAME lsqlite3_fsl09v.zip)
+  elseif (${CIVETWEB_LUA_SQLITE_VERSION} VERSION_EQUAL "0.9.1")
+    set(LUA_SQLITE_FILENAME lsqlite3_fsl09t.zip)
+  else()
+    message(FATAL_ERROR "The Lua SQLite archive filename is unknown for version ${CIVETWEB_LUA_SQLITE_VERSION}")
+  endif()
+  ExternalProject_Add(luasqlite
+    URL "http://lua.sqlite.org/index.cgi/zip/${LUA_SQLITE_FILENAME}"
+    URL_MD5 ${CIVETWEB_LUA_SQLITE_MD5_HASH}
+    PREFIX "${CMAKE_BINARY_DIR}/third_party"
+    PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+      "${CMAKE_SOURCE_DIR}/cmake/luasqlite/CMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
+    CMAKE_ARGS
+      "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
+      "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>"
+    LOG_DOWNLOAD ${THIRD_PARTY_LOGGING}
+    LOG_UPDATE ${THIRD_PARTY_LOGGING}
+    LOG_CONFIGURE ${THIRD_PARTY_LOGGING}
+    LOG_BUILD ${THIRD_PARTY_LOGGING}
+    LOG_TEST ${THIRD_PARTY_LOGGING}
+    LOG_INSTALL ${THIRD_PARTY_LOGGING})
+  ExternalProject_Get_Property(luasqlite INSTALL_DIR)
+  set(LUA_SQLITE_INSTALL_DIR ${INSTALL_DIR})
+  unset(INSTALL_DIR)
+  link_directories("${LUA_SQLITE_INSTALL_DIR}/lib")
+  set(LUA_LIBRARIES "${LUA_LIBRARIES};${LUA_SQLITE_INSTALL_DIR}/lib/libluasqlite.a")
+  add_dependencies(c-library luasqlite)
+
+  # Lua XML Support
+  if (${CIVETWEB_LUA_XML_VERSION} VERSION_EQUAL "1.8.0")
+    set(LUA_XML_FILENAME LuaXML_130610.zip)
+  elseif (${CIVETWEB_LUA_XML_VERSION} VERSION_EQUAL "1.7.4")
+    set(LUA_XML_FILENAME LuaXML_101012.zip)
+  else()
+    message(FATAL_ERROR "The Lua XML archive filename is unknown for version ${CIVETWEB_LUA_XML_VERSION}")
+  endif()
+  ExternalProject_Add(luaxml
+    URL "http://viremo.eludi.net/LuaXML/${LUA_XML_FILENAME}"
+    URL_MD5 ${CIVETWEB_LUA_XML_MD5_HASH}
+    PREFIX "${CMAKE_BINARY_DIR}/third_party"
+    PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+      "${CMAKE_SOURCE_DIR}/cmake/luaxml/CMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
+    CMAKE_ARGS
+      "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
+      "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>"
+    LOG_DOWNLOAD ${THIRD_PARTY_LOGGING}
+    LOG_UPDATE ${THIRD_PARTY_LOGGING}
+    LOG_CONFIGURE ${THIRD_PARTY_LOGGING}
+    LOG_BUILD ${THIRD_PARTY_LOGGING}
+    LOG_TEST ${THIRD_PARTY_LOGGING}
+    LOG_INSTALL ${THIRD_PARTY_LOGGING})
+  ExternalProject_Get_Property(luaxml INSTALL_DIR)
+  set(LUA_XML_INSTALL_DIR ${INSTALL_DIR})
+  unset(INSTALL_DIR)
+  link_directories("${LUA_XML_INSTALL_DIR}/lib")
+  set(LUA_LIBRARIES "${LUA_LIBRARIES};${LUA_XML_INSTALL_DIR}/lib/libluaxml.a")
+  add_dependencies(c-library luaxml)
+
+  # SQLite Support
+  string (REGEX MATCHALL "[0-9]+" SQLITE_VERSION_MATCHES ${CIVETWEB_SQLITE_VERSION})
+  list(GET SQLITE_VERSION_MATCHES 0 SQLITE_VERSION_MAJOR)
+  list(GET SQLITE_VERSION_MATCHES 1 SQLITE_VERSION_MINOR)
+  list(GET SQLITE_VERSION_MATCHES 2 SQLITE_VERSION_PATCH)
+  set(SQLITE_FILE_VERSION ${SQLITE_VERSION_MAJOR}0${SQLITE_VERSION_MINOR}0${SQLITE_VERSION_PATCH}00)
+  ExternalProject_Add(sqlite
+    URL "http://www.sqlite.org/2015/sqlite-amalgamation-${SQLITE_FILE_VERSION}.zip"
+    URL_MD5 ${CIVETWEB_SQLITE_MD5_HASH}
+    PREFIX "${CMAKE_BINARY_DIR}/third_party"
+    PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+      "${CMAKE_SOURCE_DIR}/cmake/sqlite/CMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
+    CMAKE_ARGS
+      "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
+      "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>"
+    LOG_DOWNLOAD ${THIRD_PARTY_LOGGING}
+    LOG_UPDATE ${THIRD_PARTY_LOGGING}
+    LOG_CONFIGURE ${THIRD_PARTY_LOGGING}
+    LOG_BUILD ${THIRD_PARTY_LOGGING}
+    LOG_TEST ${THIRD_PARTY_LOGGING}
+    LOG_INSTALL ${THIRD_PARTY_LOGGING})
+  ExternalProject_Get_Property(sqlite INSTALL_DIR)
+  set(SQLITE_INSTALL_DIR ${INSTALL_DIR})
+  unset(INSTALL_DIR)
+  link_directories("${SQLITE_INSTALL_DIR}/lib")
+  include_directories("${SQLITE_INSTALL_DIR}/include")
+  set(LUA_LIBRARIES "${LUA_LIBRARIES};${SQLITE_INSTALL_DIR}/lib/libsqlite.a")
+  add_dependencies(c-library sqlite)
+
+  # Link all the Lua libraries
+  target_link_libraries(c-library ${LUA_LIBRARIES})
+endif()
+
+# The web server executable
+add_executable(c-executable main.c)
+set_target_properties(c-executable PROPERTIES
+  OUTPUT_NAME "civetweb"
+)
+install(
+  TARGETS c-executable
+  ARCHIVE DESTINATION lib
+  LIBRARY DESTINATION lib
+  RUNTIME DESTINATION bin
+  COMPONENT server)
+if (BUILD_SHARED_LIBS)
+  target_compile_definitions(c-executable PRIVATE CIVETWEB_DLL_IMPORTS)
+endif()
+target_include_directories(
+  c-executable PUBLIC
+  ${PROJECT_SOURCE_DIR}/include)
+target_link_libraries(c-executable c-library)
+if (LIBRT_FOUND)
+  target_link_libraries(c-executable LIBRT::LIBRT)
+endif()
+
+# The C++ API library
+if (CIVETWEB_ENABLE_CXX)
+  add_library(cxx-library CivetServer.cpp)
+  set_target_properties(cxx-library PROPERTIES
+    OUTPUT_NAME "cxx-library"
+    VERSION ${CIVETWEB_VERSION}
+    SOVERSION ${CIVETWEB_VERSION}
+  )
+  if (BUILD_SHARED_LIBS)
+    target_compile_definitions(cxx-library PRIVATE CIVETWEB_DLL_EXPORTS)
+  endif()
+  target_include_directories(
+    cxx-library PUBLIC
+    ${PROJECT_SOURCE_DIR}/include)
+  install(
+    TARGETS cxx-library
+    ARCHIVE DESTINATION lib
+    LIBRARY DESTINATION lib
+    RUNTIME DESTINATION bin
+    COMPONENT cxx-library)
+  install(FILES
+    ${PROJECT_SOURCE_DIR}/include/CivetServer.h
+    DESTINATION include
+    COMPONENT cxx-library)
+endif()

+ 120 - 0
test/CMakeLists.txt

@@ -0,0 +1,120 @@
+# Determine if we should print to the output
+if (CIVETWEB_ENABLE_THIRD_PARTY_OUTPUT)
+  set(THIRD_PARTY_LOGGING 0)
+else()
+  set(THIRD_PARTY_LOGGING 1)
+endif()
+
+# We use the check unit testing framework for our C unit tests
+include(ExternalProject)
+ExternalProject_Add(check
+  DEPENDS c-library
+  URL "https://downloads.sourceforge.net/project/check/check/${CIVETWEB_CHECK_VERSION}/check-${CIVETWEB_CHECK_VERSION}.tar.gz"
+  URL_MD5 ${CIVETWEB_CHECK_MD5_HASH}
+  PREFIX "${CMAKE_BINARY_DIR}/third_party"
+  BUILD_IN_SOURCE 1
+  PATCH_COMMAND ${CMAKE_COMMAND}
+    -DSOURCE_DIR=<SOURCE_DIR>
+    -DBINARY_DIR=<BINARY_DIR>
+    -DINSTALL_DIR=<INSTALL_DIR>
+    -DVERSION=${CIVETWEB_CHECK_VERSION}
+    -P ${CMAKE_SOURCE_DIR}/cmake/check/patch.cmake
+  CMAKE_ARGS
+    "-DCMAKE_BUILD_TYPE=Release"
+    "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
+    "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>"
+  LOG_DOWNLOAD ${THIRD_PARTY_LOGGING}
+  LOG_UPDATE ${THIRD_PARTY_LOGGING}
+  LOG_CONFIGURE ${THIRD_PARTY_LOGGING}
+  LOG_BUILD ${THIRD_PARTY_LOGGING}
+  LOG_TEST ${THIRD_PARTY_LOGGING}
+  LOG_INSTALL ${THIRD_PARTY_LOGGING})
+ExternalProject_Get_Property(check INSTALL_DIR)
+set(CHECK_INSTALL_DIR ${INSTALL_DIR})
+unset(INSTALL_DIR)
+link_directories("${CHECK_INSTALL_DIR}/lib")
+include_directories("${CHECK_INSTALL_DIR}/include")
+if (WIN32 AND MINGW)
+  set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/libcheck.a")
+  set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/libcompat.a")
+elseif (WIN32)
+  set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/check.lib")
+  set(CHECK_LIBRARIES "${CHECK_LIBRARIES};${CHECK_INSTALL_DIR}/lib/compat.lib")
+else()
+  set(CHECK_LIBRARIES "${CHECK_INSTALL_DIR}/lib/libcheck.a")
+endif()
+find_package(LibM)
+if (LIBM_FOUND)
+  set(CHECK_LIBRARIES "${CHECK_LIBRARIES};LIBM::LIBM")
+endif()
+find_package(LibRt)
+if (LIBRT_FOUND)
+  set(CHECK_LIBRARIES "${CHECK_LIBRARIES};LIBRT::LIBRT")
+endif()
+
+# Build the C unit tests
+add_library(public-c-unit-tests STATIC public.c)
+if (BUILD_SHARED_LIBS)
+  target_compile_definitions(public-c-unit-tests PRIVATE CIVETWEB_DLL_IMPORTS)
+endif()
+target_include_directories(
+  public-c-unit-tests PUBLIC
+  ${PROJECT_SOURCE_DIR}/include)
+target_link_libraries(public-c-unit-tests c-library ${CHECK_LIBRARIES})
+add_dependencies(public-c-unit-tests check)
+add_library(private-c-unit-tests STATIC private.c)
+target_include_directories(
+  private-c-unit-tests PUBLIC
+  ${PROJECT_SOURCE_DIR}/include)
+target_link_libraries(private-c-unit-tests ${CHECK_LIBRARIES})
+add_dependencies(private-c-unit-tests check)
+add_executable(civetweb-c-unit-test main.c)
+target_link_libraries(civetweb-c-unit-test public-c-unit-tests private-c-unit-tests ${CHECK_LIBRARIES})
+add_dependencies(civetweb-c-unit-test check)
+
+# Public API tests
+add_test(test-public-cookie civetweb-c-unit-test --suite=Public --test-case=Cookies)
+
+# Private API tests
+add_test(test-private-http-message civetweb-c-unit-test --suite=Private "--test-case=HTTP Message")
+
+# Add the coverage command(s)
+if (${CMAKE_BUILD_TYPE} MATCHES "[Cc]overage")
+  find_program(GCOV_EXECUTABLE gcov)
+  find_program(LCOV_EXECUTABLE lcov)
+  find_program(GENHTML_EXECUTABLE genhtml)
+  find_program(CTEST_EXECUTABLE ctest)
+  if (GCOV_EXECUTABLE AND LCOV_EXECUTABLE AND GENHTML_EXECUTABLE AND CTEST_EXECUTABLE AND HAVE_C_FLAG_COVERAGE)
+    add_custom_command(
+      OUTPUT ${CMAKE_BINARY_DIR}/lcov/index.html
+      COMMAND ${LCOV_EXECUTABLE} -q -z -d .
+      COMMAND ${LCOV_EXECUTABLE} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o before.lcov -i
+      COMMAND ${CTEST_EXECUTABLE} --force-new-ctest-process
+      COMMAND ${LCOV_EXECUTABLE} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o after.lcov
+      COMMAND ${LCOV_EXECUTABLE} -q -a before.lcov -a after.lcov --output-file final.lcov
+      COMMAND ${LCOV_EXECUTABLE} -q -r final.lcov "'${CMAKE_SOURCE_DIR}/test/*'" -o final.lcov
+      COMMAND ${GENHTML_EXECUTABLE} final.lcov -o lcov --demangle-cpp --sort -p "${CMAKE_SOURCE_DIR}" -t benchmark
+      DEPENDS civetweb-c-unit-test
+      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+      COMMENT "Running LCOV"
+    )
+    add_custom_target(coverage
+      DEPENDS ${CMAKE_BINARY_DIR}/lcov/index.html
+      COMMENT "LCOV report at lcov/index.html"
+    )
+    message(STATUS "Coverage command added")
+  else()
+    if (HAVE_C_FLAG_COVERAGE)
+      set(C_FLAG_COVERAGE_MESSAGE supported)
+    else()
+      set(C_FLAG_COVERAGE_MESSAGE unavailable)
+    endif()
+    message(WARNING
+      "Coverage command not available:\n"
+      "  gcov: ${GCOV_EXECUTABLE}\n"
+      "  lcov: ${LCOV_EXECUTABLE}\n"
+      "  genhtml: ${GENHTML_EXECUTABLE}\n"
+      "  ctest: ${CTEST_EXECUTABLE}\n"
+      "  --coverage flag: ${C_FLAG_COVERAGE_MESSAGE}")
+  endif()
+endif()