mirror of
https://github.com/yhirose/cpp-httplib
synced 2024-11-21 06:26:02 -07:00
3e287b3a26
This allows disabling the use of C++ exceptions at CMake configure time. The value is encoded in the generated httplibTargets.cmake file and will be used by CMake projects that import it.
304 lines
13 KiB
CMake
304 lines
13 KiB
CMake
#[[
|
|
Build options:
|
|
* BUILD_SHARED_LIBS (default off) builds as a shared library (if HTTPLIB_COMPILE is ON)
|
|
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
|
|
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
|
|
* HTTPLIB_REQUIRE_OPENSSL (default off)
|
|
* HTTPLIB_REQUIRE_ZLIB (default off)
|
|
* HTTPLIB_USE_BROTLI_IF_AVAILABLE (default on)
|
|
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
|
|
* HTTPLIB_REQUIRE_BROTLI (default off)
|
|
* HTTPLIB_COMPILE (default off)
|
|
* HTTPLIB_INSTALL (default on)
|
|
* HTTPLIB_TEST (default off)
|
|
* BROTLI_USE_STATIC_LIBS - tells Cmake to use the static Brotli libs (only works if you have them installed).
|
|
* OPENSSL_USE_STATIC_LIBS - tells Cmake to use the static OpenSSL libs (only works if you have them installed).
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
After installation with Cmake, a find_package(httplib COMPONENTS OpenSSL ZLIB Brotli) is available.
|
|
This creates a httplib::httplib target (if found and if listed components are supported).
|
|
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 variables are available after you run find_package(httplib)
|
|
* HTTPLIB_HEADER_PATH - this is the full path to the installed header (e.g. /usr/include/httplib.h).
|
|
* HTTPLIB_IS_USING_OPENSSL - a bool for if OpenSSL support is enabled.
|
|
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled.
|
|
* HTTPLIB_IS_USING_BROTLI - a bool for if Brotli support is enabled.
|
|
* HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN - a bool for if support of loading system certs from the Apple Keychain is enabled.
|
|
* HTTPLIB_IS_COMPILED - a bool for if the library is compiled, or otherwise header-only.
|
|
* HTTPLIB_INCLUDE_DIR - the root path to httplib's header (e.g. /usr/include).
|
|
* HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so).
|
|
* httplib_VERSION or HTTPLIB_VERSION - the project's version string.
|
|
* HTTPLIB_FOUND - a bool for if the target was found.
|
|
|
|
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}")
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
FindPython3 requires Cmake v3.12
|
|
ARCH_INDEPENDENT option of write_basic_package_version_file() requires Cmake v3.14
|
|
]]
|
|
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
|
|
|
|
# Get the CPPHTTPLIB_VERSION value and use it as a version
|
|
# This gets the string with the CPPHTTPLIB_VERSION value from the header.
|
|
# This is so the maintainer doesn't actually need to update this manually.
|
|
file(STRINGS httplib.h _raw_version_string REGEX "CPPHTTPLIB_VERSION \"([0-9]+\\.[0-9]+\\.[0-9]+)\"")
|
|
|
|
# Needed since git tags have "v" prefixing them.
|
|
# Also used if the fallback to user agent string is being used.
|
|
string(REGEX MATCH "([0-9]+\\.?)+" _httplib_version "${_raw_version_string}")
|
|
|
|
project(httplib VERSION ${_httplib_version} LANGUAGES CXX)
|
|
|
|
# Lets you disable C++ exception during CMake configure time.
|
|
# The value is used in the install CMake config file.
|
|
option(HTTPLIB_NO_EXCEPTIONS "Disable the use of C++ exceptions" OFF)
|
|
|
|
# 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 silently 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 Zlib compression support." ON)
|
|
# Lets you compile the program as a regular library instead of header-only
|
|
option(HTTPLIB_COMPILE "If ON, uses a Python script to split the header into a compilable header & source file (requires Python v3)." OFF)
|
|
# Lets you disable the installation (useful when fetched from another CMake project)
|
|
option(HTTPLIB_INSTALL "Enables the installation target" ON)
|
|
# Just setting this variable here for people building in-tree
|
|
if(HTTPLIB_COMPILE)
|
|
set(HTTPLIB_IS_COMPILED TRUE)
|
|
endif()
|
|
option(HTTPLIB_TEST "Enables testing and builds tests" OFF)
|
|
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
|
|
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
|
|
option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON)
|
|
# Defaults to static library
|
|
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
|
|
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
|
|
# Necessary for Windows if building shared libs
|
|
# See https://stackoverflow.com/a/40743080
|
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
|
endif()
|
|
|
|
# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
|
|
set(THREADS_PREFER_PTHREAD_FLAG true)
|
|
find_package(Threads REQUIRED)
|
|
# Since Cmake v3.11, Crypto & SSL became optional when not specified as COMPONENTS.
|
|
if(HTTPLIB_REQUIRE_OPENSSL)
|
|
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL REQUIRED)
|
|
elseif(HTTPLIB_USE_OPENSSL_IF_AVAILABLE)
|
|
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL QUIET)
|
|
endif()
|
|
# Just setting this variable here for people building in-tree
|
|
if(OPENSSL_FOUND)
|
|
set(HTTPLIB_IS_USING_OPENSSL TRUE)
|
|
endif()
|
|
|
|
if(HTTPLIB_REQUIRE_ZLIB)
|
|
find_package(ZLIB REQUIRED)
|
|
elseif(HTTPLIB_USE_ZLIB_IF_AVAILABLE)
|
|
find_package(ZLIB QUIET)
|
|
endif()
|
|
# Just setting this variable here for people building in-tree
|
|
# FindZLIB doesn't have a ZLIB_FOUND variable, so check the target.
|
|
if(TARGET ZLIB::ZLIB)
|
|
set(HTTPLIB_IS_USING_ZLIB TRUE)
|
|
endif()
|
|
|
|
# Adds our cmake folder to the search path for find_package
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
if(HTTPLIB_REQUIRE_BROTLI)
|
|
find_package(Brotli COMPONENTS encoder decoder common REQUIRED)
|
|
elseif(HTTPLIB_USE_BROTLI_IF_AVAILABLE)
|
|
find_package(Brotli COMPONENTS encoder decoder common QUIET)
|
|
endif()
|
|
# Just setting this variable here for people building in-tree
|
|
if(Brotli_FOUND)
|
|
set(HTTPLIB_IS_USING_BROTLI TRUE)
|
|
endif()
|
|
|
|
if(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
|
|
set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN TRUE)
|
|
endif()
|
|
|
|
# Used for default, common dirs that the end-user can change (if needed)
|
|
# like CMAKE_INSTALL_INCLUDEDIR or CMAKE_INSTALL_DATADIR
|
|
include(GNUInstallDirs)
|
|
|
|
if(HTTPLIB_COMPILE)
|
|
# Put the split script into the build dir
|
|
configure_file(split.py "${CMAKE_CURRENT_BINARY_DIR}/split.py"
|
|
COPYONLY
|
|
)
|
|
# Needs to be in the same dir as the python script
|
|
configure_file(httplib.h "${CMAKE_CURRENT_BINARY_DIR}/httplib.h"
|
|
COPYONLY
|
|
)
|
|
|
|
# Used outside of this if-else
|
|
set(_INTERFACE_OR_PUBLIC PUBLIC)
|
|
# Brings in the Python3_EXECUTABLE path we can use.
|
|
find_package(Python3 REQUIRED)
|
|
# Actually split the file
|
|
# Keeps the output in the build dir to not pollute the main dir
|
|
execute_process(COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/split.py"
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
|
ERROR_VARIABLE _httplib_split_error
|
|
)
|
|
if(_httplib_split_error)
|
|
message(FATAL_ERROR "Failed when trying to split cpp-httplib with the Python script.\n${_httplib_split_error}")
|
|
endif()
|
|
|
|
# split.py puts output in "out"
|
|
set(_httplib_build_includedir "${CMAKE_CURRENT_BINARY_DIR}/out")
|
|
# This will automatically be either static or shared based on the value of BUILD_SHARED_LIBS
|
|
add_library(${PROJECT_NAME} "${_httplib_build_includedir}/httplib.cc")
|
|
target_sources(${PROJECT_NAME}
|
|
PUBLIC
|
|
$<BUILD_INTERFACE:${_httplib_build_includedir}/httplib.h>
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/httplib.h>
|
|
)
|
|
set_target_properties(${PROJECT_NAME}
|
|
PROPERTIES
|
|
VERSION ${${PROJECT_NAME}_VERSION}
|
|
SOVERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}"
|
|
)
|
|
else()
|
|
# This is for header-only.
|
|
set(_INTERFACE_OR_PUBLIC INTERFACE)
|
|
add_library(${PROJECT_NAME} INTERFACE)
|
|
set(_httplib_build_includedir "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
endif()
|
|
# 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})
|
|
|
|
# Require C++11
|
|
target_compile_features(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
|
cxx_std_11
|
|
)
|
|
|
|
target_include_directories(${PROJECT_NAME} SYSTEM ${_INTERFACE_OR_PUBLIC}
|
|
$<BUILD_INTERFACE:${_httplib_build_includedir}>
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
)
|
|
|
|
# Always require threads
|
|
target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
|
Threads::Threads
|
|
# Needed for Windows libs on Mingw, as the pragma comment(lib, "xyz") aren't triggered.
|
|
$<$<PLATFORM_ID:Windows>:ws2_32>
|
|
$<$<PLATFORM_ID:Windows>:crypt32>
|
|
$<$<PLATFORM_ID:Windows>:cryptui>
|
|
# Needed for API from MacOS Security framework
|
|
"$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN}>>:-framework CoreFoundation -framework Security>"
|
|
# Can't put multiple targets in a single generator expression or it bugs out.
|
|
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::common>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::encoder>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::decoder>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:ZLIB::ZLIB>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::SSL>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::Crypto>
|
|
)
|
|
|
|
# Set the definitions to enable optional features
|
|
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
|
|
$<$<BOOL:${HTTPLIB_NO_EXCEPTIONS}>:CPPHTTPLIB_NO_EXCEPTIONS>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:CPPHTTPLIB_BROTLI_SUPPORT>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
|
|
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
|
|
$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN}>>:CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN>
|
|
)
|
|
|
|
# CMake configuration files installation directory
|
|
set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
|
|
|
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
|
|
)
|
|
|
|
if(HTTPLIB_COMPILE)
|
|
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
|
# Example: if you find_package(httplib 0.5.4)
|
|
# then anything >= 0.5 and <= 1.0 is accepted
|
|
COMPATIBILITY SameMinorVersion
|
|
)
|
|
else()
|
|
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
|
# Example: if you find_package(httplib 0.5.4)
|
|
# then anything >= 0.5 and <= 1.0 is accepted
|
|
COMPATIBILITY SameMinorVersion
|
|
# Tells Cmake that it's a header-only lib
|
|
# Mildly useful for end-users :)
|
|
ARCH_INDEPENDENT
|
|
)
|
|
endif()
|
|
|
|
if(HTTPLIB_INSTALL)
|
|
# 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
|
|
)
|
|
|
|
install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)
|
|
|
|
install(FILES
|
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
|
# Install it so it can be used later by the httplibConfig.cmake file.
|
|
# Put it in the same dir as our config file instead of a global path so we don't potentially stomp on other packages.
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindBrotli.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}
|
|
)
|
|
endif()
|
|
|
|
if(HTTPLIB_TEST)
|
|
include(CTest)
|
|
add_subdirectory(test)
|
|
endif()
|