From 9505a764910a2ebdffbe9ec63f5a2a569fa511fb Mon Sep 17 00:00:00 2001 From: KTGH Date: Tue, 19 May 2020 19:07:18 -0400 Subject: [PATCH] Bringing Cmake back (#470) * Revert "Removed CMakeLists.txt. (Fix #421)" This reverts commit 8674555b88f3b1eb9721eafdf690eeb8e99491af. * Fail if cmake version too old Previous behaviour is just a warning. * Improve CMakeLists Adds automatic dependency finding (if they were used). Adds a way to require a specific version in the find_package(httplib) call. You should link against the httplib::httplib IMPORTED target, which is created automatically. Add options to allow for strictly requiring OpenSSL/ZLIB HTTPLIB_REQUIRE_OPENSSL & HTTPLIB_REQUIRE_ZLIB require the libs be found, or the build fails. HTTPLIB_USE_OPENSSL_IF_AVAILABLE & HTTPLIB_USE_ZLIB_IF_AVAILABLE silently search for the libs. If they aren't found, the build still continues, but shuts off support for those features. * Add documentation to CMakeLists.txt Has info on all the available options and what targets are produced. Also put some things about installation on certain platforms. --- CMakeLists.txt | 160 +++++++++++++++++++++++++++++++++++++++++ httplibConfig.cmake.in | 38 ++++++++++ 2 files changed, 198 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 httplibConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2a3c9d4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,160 @@ +#[[ + Build options: + * HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on) + * HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on) + * HTTPLIB_REQUIRE_OPENSSL (default off) + * HTTPLIB_REQUIRE_ZLIB (default off) + + After installation with Cmake, a find_package(httplib) is available. + This creates a httplib::httplib target (if found). + It can be linked like so: + + target_link_libraries(your_exe httplib::httplib) + + The following will build & install for later use. + + Linux/macOS: + + mkdir -p build + cd build + cmake -DCMAKE_BUILD_TYPE=Release .. + sudo cmake --build . --target install + + Windows: + + mkdir build + cd build + cmake .. + runas /user:Administrator "cmake --build . --config Release --target install" + + These three variables are available after you run find_package(httplib) + * HTTPLIB_HEADER_PATH - this is the full path to the installed header. + * HTTPLIB_IS_USING_OPENSSL - a bool for if OpenSSL support is enabled. + * HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled. + + Want to use precompiled headers (Cmake feature since v3.16)? + It's as simple as doing the following (before linking): + + target_precompile_headers(httplib::httplib INTERFACE "${HTTPLIB_HEADER_PATH}") +]] +cmake_minimum_required(VERSION 3.7.0 FATAL_ERROR) +project(httplib LANGUAGES CXX) + +# Change as needed to set an OpenSSL minimum version. +# This is used in the installed Cmake config file. +set(_HTTPLIB_OPENSSL_MIN_VER "1.1.1") + +# Allow for a build to require OpenSSL to pass, instead of just being optional +option(HTTPLIB_REQUIRE_OPENSSL "Requires OpenSSL to be found & linked, or fails build." OFF) +option(HTTPLIB_REQUIRE_ZLIB "Requires ZLIB to be found & linked, or fails build." OFF) +# Allow for a build to casually enable OpenSSL/ZLIB support, but silenty continue if not found. +# Make these options so their automatic use can be specifically disabled (as needed) +option(HTTPLIB_USE_OPENSSL_IF_AVAILABLE "Uses OpenSSL (if available) to enable HTTPS support." ON) +option(HTTPLIB_USE_ZLIB_IF_AVAILABLE "Uses ZLIB (if available) to enable compression support." ON) + +# TODO: implement the option of option to correctly split, building, and export with the split.py script. +# option(HTTPLIB_SPLIT "Uses a Python script to split the header into a header & source file." OFF) + +# Threads needed for on some systems, and for on Linux +find_package(Threads REQUIRED) +if(HTTPLIB_REQUIRE_OPENSSL) + find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} REQUIRED) +elseif(HTTPLIB_USE_OPENSSL_IF_AVAILABLE) + # Look quietly since it's optional are optional + find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} QUIET) +endif() +if(HTTPLIB_REQUIRE_ZLIB) + find_package(ZLIB REQUIRED) +elseif(HTTPLIB_USE_ZLIB_IF_AVAILABLE) + find_package(ZLIB QUIET) +endif() + +# Used for default, common dirs that the end-user can change (if needed) +# like CMAKE_INSTALL_INCLUDEDIR or CMAKE_INSTALL_DATADIR +include(GNUInstallDirs) + +add_library(${PROJECT_NAME} INTERFACE) +# Lets you address the target with httplib::httplib +# Only useful if building in-tree, versus using it from an installation. +add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + +# Might be missing some, but this list is somewhat comprehensive +target_compile_features(${PROJECT_NAME} INTERFACE + cxx_std_11 + cxx_nullptr + cxx_noexcept + cxx_lambdas + cxx_override + cxx_defaulted_functions + cxx_attribute_deprecated + cxx_auto_type + cxx_decltype + cxx_deleted_functions + cxx_range_for + cxx_sizeof_member +) + +target_include_directories(${PROJECT_NAME} INTERFACE + $ + $) + + +target_link_libraries(${PROJECT_NAME} INTERFACE + # Always require threads + Threads::Threads + # Only link zlib & openssl if they're found + $<$:ZLIB::ZLIB> + $<$:OpenSSL::SSL OpenSSL::Crypto> +) + +# Auto-define the optional support if those packages were found +target_compile_definitions(${PROJECT_NAME} INTERFACE + $<$:CPPHTTPLIB_ZLIB_SUPPORT> + $<$:CPPHTTPLIB_OPENSSL_SUPPORT> +) + +# Cmake's find_package search path is different based on the system +# See https://cmake.org/cmake/help/latest/command/find_package.html for the list +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/cmake/${PROJECT_NAME}") +else() + # On Non-Windows, it should be /usr/lib/cmake//Config.cmake + # NOTE: This may or may not work for macOS... + set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +endif() + +include(CMakePackageConfigHelpers) + +# Configures the meta-file httplibConfig.cmake.in to replace variables with paths/values/etc. +configure_package_config_file("${PROJECT_NAME}Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${_TARGET_INSTALL_CMAKEDIR}" + # Passes the includedir install path + PATH_VARS CMAKE_INSTALL_FULL_INCLUDEDIR + # There aren't any components, so don't use the macro + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) + +# Creates the export httplibTargets.cmake +# This is strictly what holds compilation requirements +# and linkage information (doesn't find deps though). +install(TARGETS ${PROJECT_NAME} + EXPORT httplibTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +install(FILES httplib.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION ${_TARGET_INSTALL_CMAKEDIR} +) + +# NOTE: This path changes depending on if it's on Windows or Linux +install(EXPORT httplibTargets + # Puts the targets into the httplib namespace + # So this makes httplib::httplib linkable after doing find_package(httplib) + NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${_TARGET_INSTALL_CMAKEDIR} +) diff --git a/httplibConfig.cmake.in b/httplibConfig.cmake.in new file mode 100644 index 0000000..c2494e0 --- /dev/null +++ b/httplibConfig.cmake.in @@ -0,0 +1,38 @@ +# Generates a macro to auto-configure everything +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +# We add find_dependency calls here to not make the end-user have to call them. +find_dependency(Threads REQUIRED) +if(@HTTPLIB_REQUIRE_OPENSSL@) + find_dependency(OpenSSL @_HTTPLIB_OPENSSL_MIN_VER@ REQUIRED) + # Lets you check if these options were correctly enabled for your install + set(HTTPLIB_IS_USING_OPENSSL TRUE) +elseif(@HTTPLIB_USE_OPENSSL_IF_AVAILABLE@) + # Look quietly since it's optional + find_dependency(OpenSSL @_HTTPLIB_OPENSSL_MIN_VER@ QUIET) + # Lets you check if these options were correctly enabled for your install + set(HTTPLIB_IS_USING_OPENSSL @OPENSSL_FOUND@) +else() + set(HTTPLIB_IS_USING_OPENSSL FALSE) +endif() +if(@HTTPLIB_REQUIRE_ZLIB@) + find_dependency(ZLIB REQUIRED) + # Lets you check if these options were correctly enabled for your install + set(HTTPLIB_IS_USING_ZLIB TRUE) +elseif(@HTTPLIB_USE_ZLIB_IF_AVAILABLE@) + # Look quietly since it's optional + find_dependency(ZLIB QUIET) + # Lets you check if these options were correctly enabled for your install + set(HTTPLIB_IS_USING_ZLIB @ZLIB_FOUND@) +else() + set(HTTPLIB_IS_USING_ZLIB FALSE) +endif() + +# Lets the end-user find the header path if needed +# This is helpful if you're using Cmake's pre-compiled header feature +set_and_check(HTTPLIB_HEADER_PATH "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@/httplib.h") + +# Brings in the target library +include("${CMAKE_CURRENT_LIST_DIR}/httplibTargets.cmake")