# =================================================================== # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # =================================================================== # =================================================================== # The following variables can be set to locate dependencies that # are not installed in standard paths. These variables are used # by the find_package() modules. # # APR_ROOT - Path to APR's install area # APRUtil_ROOT - Path to APR-Util's install area # OPENSSL_ROOT_DIR - Path to OpenSSL's install area # ZLIB_ROOT - Path to zlib's install area # =================================================================== cmake_minimum_required(VERSION 3.0) # Silence warnings about ${_ROOT} in CMake 3.12+ if((${CMAKE_MAJOR_VERSION} GREATER 3) OR (${CMAKE_MINOR_VERSION} GREATER 11)) cmake_policy(SET CMP0074 NEW) endif() set(SERF_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(CMAKE_MODULE_PATH "${SERF_SOURCE_DIR}/build") include(SerfVersion) project("Serf" VERSION ${SERF_VERSION} LANGUAGES C) message(WARNING "Serf's CMake build is considered EXPERIMENTAL. " "Some features are not supported and the build " "has not been tested on many supported platforms.") # Build options option(DEBUG "Enable debugging info and strict compile warnings" OFF) option(SKIP_SHARED "Disable building shared Serf libraries" OFF) option(SKIP_STATIC "Disable building static Serf libraries" OFF) option(LIBDIR "Install directory for architecture-dependent libraries" "") option(GSSAPI "Path to GSSAPI's install area" "") option(BROTLI "Path to Brotli's install area" "") option(DISABLE_LOGGING "Disable the logging framework at compile time" OFF) option(SKIP_TESTS "Disable building the unit tests and utilities" OFF) option(ENABLE_SLOW_TESTS "Enable long-running unit tests" OFF) # Platform-specific build options option(APR_STATIC "Windows: Link with static APR/-Util libraries" OFF) option(EXPAT "Windows: optional path to Expat's install area for APR_STATIC" "") option(RELATIVE_RPATH "macOS: Use @rpath in installed shared library" OFF) if(SKIP_SHARED AND SKIP_STATIC) message(FATAL_ERROR "You have disabled both shared and static library builds.") endif() # Initialize the build type if it was not set on the command line. if(NOT CMAKE_BUILD_TYPE) if(DEBUG) set(CMAKE_BUILD_TYPE DEBUG CACHE STRING "Default to debug build.") else() set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "Default to release build.") endif() endif() include(SerfPlatform) include(SerfWindowsToolkit) # Public headers list(APPEND HEADERS "serf.h" "serf_bucket_types.h" "serf_bucket_util.h" ) # List of symbols that should not be exported from the shared library. list(APPEND EXPORTS_BLACKLIST "serf_connection_switch_protocol" "serf_http_protocol_create" "serf_https_protocol_create" "serf_http_request_queue" ) # Serf library source files list(APPEND SOURCES "src/config_store.c" "src/context.c" "src/deprecated.c" "src/incoming.c" "src/logging.c" "src/outgoing.c" "src/outgoing_request.c" "src/pump.c" "src/ssltunnel.c" "auth/auth.c" "auth/auth_basic.c" "auth/auth_digest.c" "auth/auth_spnego.c" "auth/auth_spnego_gss.c" "auth/auth_spnego_sspi.c" "buckets/aggregate_buckets.c" "buckets/allocator.c" "buckets/barrier_buckets.c" "buckets/brotli_buckets.c" "buckets/buckets.c" "buckets/bwtp_buckets.c" "buckets/chunk_buckets.c" "buckets/copy_buckets.c" "buckets/dechunk_buckets.c" "buckets/deflate_buckets.c" "buckets/event_buckets.c" "buckets/fcgi_buckets.c" "buckets/file_buckets.c" "buckets/headers_buckets.c" "buckets/hpack_buckets.c" "buckets/http2_frame_buckets.c" "buckets/iovec_buckets.c" "buckets/limit_buckets.c" "buckets/log_wrapper_buckets.c" "buckets/mmap_buckets.c" "buckets/prefix_buckets.c" "buckets/request_buckets.c" "buckets/response_body_buckets.c" "buckets/response_buckets.c" "buckets/simple_buckets.c" "buckets/socket_buckets.c" "buckets/split_buckets.c" "buckets/ssl_buckets.c" "protocols/fcgi_protocol.c" "protocols/fcgi_stream.c" "protocols/http2_protocol.c" "protocols/http2_stream.c" ) if(SERF_WINDOWS) # Generate the .def file for the Windows DLL import library. set(SERF_DEF_FILE "${CMAKE_CURRENT_BINARY_DIR}/serf.def") add_custom_command( OUTPUT "${SERF_DEF_FILE}" DEPENDS ${HEADERS} COMMAND ${CMAKE_COMMAND} -DCMAKE_SYSTEM_NAME="${CMAKE_SYSTEM_NAME}" -DCMAKE_MODULE_PATH="${CMAKE_MODULE_PATH}" -DSERF_DEF_BLACKLIST="${EXPORTS_BLACKLIST}" -DSERF_DEF_HEADERS="${HEADERS}" -DSERF_DEF_FILE="${SERF_DEF_FILE}" -P "build/SerfWindowsGenDef.cmake" WORKING_DIRECTORY "${SERF_SOURCE_DIR}" ) set(SHARED_SOURCES "serf.rc" "${SERF_DEF_FILE}") # Static OpenSSL, APR and APR-Util need additional libraries that are not # linked by default by CMake. These will be ignored by the linker if they're # not actually used. set(SERF_STANDARD_LIBRARIES "crypt32.lib" "mswsock.lib" "rpcrt4.lib" "secur32.lib" "ws2_32.lib" ) endif(SERF_WINDOWS) # Process build options for dependency search if(GSSAPI) message(WARNING "option GSSAPI is not implemented") endif() if(BROTLI) message(WARNING "option BROTLI is not implemented") endif() if(SERF_WINDOWS) if(EXPAT) set(PC_EXPAT_INCLUDE_DIRS "${EXPAT}/include") set(PC_EXPAT_LIBRARY_DIRS "${EXPAT}/lib") endif(EXPAT) else(SERF_WINDOWS) if(EXPAT) message(WARNING "option EXPAT is not implemented on this platform") endif(EXPAT) endif(SERF_WINDOWS) # Find dependencies find_package(OpenSSL) find_package(ZLIB) find_package(APR) find_package(APRUtil) # Calculate the set of private and public targets set(SERF_PRIVATE_TARGETS OpenSSL::Crypto OpenSSL::SSL ZLIB::ZLIB) if(APR_STATIC) if(SERF_WINDOWS) list(APPEND SERF_PUBLIC_TARGETS APR::APR_static) if(NOT APR_CONTAINS_APRUTIL) list(APPEND SERF_PUBLIC_TARGETS APR::APRUTIL_static) endif() add_definitions("/DAPR_DECLARE_STATIC" "/DAPU_DECLARE_STATIC") else(SERF_WINDOWS) message(WARNING "option APR_STATIC is not implemented on this platform") endif(SERF_WINDOWS) else(APR_STATIC) list(APPEND SERF_PUBLIC_TARGETS APR::APR) if(NOT APR_CONTAINS_APRUTIL) list(APPEND SERF_PUBLIC_TARGETS APR::APRUTIL) endif() endif(APR_STATIC) # Feature tests include(SerfChecks) CheckNotFunction("BIO_set_init" "SERF_NO_SSL_BIO_WRAPPERS" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckNotFunction("X509_STORE_get0_param" "SERF_NO_SSL_X509_STORE_WRAPPERS" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckNotFunction("X509_get0_notBefore" "SERF_NO_SSL_X509_GET0_NOTBEFORE" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckNotFunction("X509_get0_notAfter" "SERF_NO_SSL_X509_GET0_NOTAFTER" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckNotFunction("X509_STORE_CTX_get0_chain" "SERF_NO_SSL_X509_GET0_CHAIN" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckNotFunction("ASN1_STRING_get0_data" "SERF_NO_SSL_ASN1_STRING_GET0_DATA" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckFunction("CRYPTO_set_locking_callback" "SERF_HAVE_SSL_LOCKING_CALLBACKS" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckFunction("OpenSSL_version_num" "SERF_HAVE_OPENSSL_VERSION_NUM" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckFunction("SSL_set_alpn_protos" "SERF_HAVE_OPENSSL_ALPN" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckFunctionMacro("OPENSSL_malloc_init" "SERF_HAVE_OPENSSL_MALLOC_INIT" "openssl/crypto.h" "${OPENSSL_INCLUDE_DIR}" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckFunctionMacro("SSL_library_init" "SERF_HAVE_OPENSSL_SSL_LIBRARY_INIT" "openssl/ssl.h" "${OPENSSL_INCLUDE_DIR}" ${OPENSSL_LIBRARIES} ${SERF_STANDARD_LIBRARIES}) CheckHeader("openssl/applink.c" "SERF_HAVE_OPENSSL_APPLINK_C" ${OPENSSL_INCLUDE_DIR}) CheckHeader("stdbool.h" "HAVE_STDBOOL_H=1") CheckType("OSSL_HANDSHAKE_STATE" "openssl/ssl.h" "SERF_HAVE_OSSL_HANDSHAKE_STATE" ${OPENSSL_INCLUDE_DIR}) if(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang")) set(CC_LIKE_GNUC TRUE) endif() # Process other build options if(LIBDIR) message(WARNING "option LIBDIR is not implemented yet") endif() if(DEBUG) add_definitions("-DDEBUG" "-D_DEBUG") endif() if(DISABLE_LOGGING) add_definitions("-DSERF_DISABLE_LOGGING") endif() if(ENABLE_SLOW_TESTS) add_definitions("-DSERF_TEST_DEFLATE_4GBPLUS_BUCKETS") endif() # Set common compiler flags if(NOT MSVC) if(CC_LIKE_GNUC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wdeclaration-after-statement") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c89") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0") endif() else() # Warning level 4, no unused argument warnings set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /wd4100") # Conditional expression is constant set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4127") # Assignment within conditional expression set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4706") add_definitions( "/DWIN32" "/DWIN32_LEAN_AND_MEAN" "/DNOUSER" "/DNOGDI" "/DNONLS" "/DNOCRYPT" "/D_CRT_SECURE_NO_WARNINGS" "/D_CRT_NONSTDC_NO_WARNINGS" ) if(SERF_WIN64) add_definitions("/DWIN64") endif() set(CMAKE_IMPORT_LIBRARY_PREFIX "lib") set(CMAKE_SHARED_LIBRARY_PREFIX "lib") endif(NOT MSVC) # Define all targets if(NOT SKIP_SHARED) add_library(serf_shared SHARED ${SOURCES} ${SHARED_SOURCES}) target_compile_options(serf_shared PUBLIC ${APR_CFLAGS}) target_include_directories(serf_shared PUBLIC ${SERF_SOURCE_DIR}) target_link_libraries(serf_shared PRIVATE ${SERF_PRIVATE_TARGETS} ${SERF_STANDARD_LIBRARIES} PUBLIC ${SERF_PUBLIC_TARGETS}) set_target_properties(serf_shared PROPERTIES VERSION ${SERF_VERSION} SOVERSION ${SERF_SOVERSION}) if(SERF_DARWIN AND NOT RELATIVE_RPATH) set_target_properties(serf_shared PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib") endif() set(SERF_TARGETS "serf_shared") if(SERF_WINDOWS) install(FILES $ DESTINATION "bin") endif() endif() if(NOT SKIP_STATIC) add_library(serf_static STATIC ${SOURCES}) target_compile_options(serf_static PUBLIC ${APR_CFLAGS}) target_include_directories(serf_static PUBLIC ${SERF_SOURCE_DIR}) target_link_libraries(serf_static ${SERF_PRIVATE_TARGETS} ${SERF_PUBLIC_TARGETS} ${SERF_STANDARD_LIBRARIES}) list(APPEND SERF_TARGETS "serf_static") endif() set_target_properties(${SERF_TARGETS} PROPERTIES OUTPUT_NAME "serf-${SERF_MAJOR_VERSION}") install(TARGETS ${SERF_TARGETS} ARCHIVE DESTINATION "lib" LIBRARY DESTINATION "lib" RUNTIME DESTINATION "bin") if(NOT SERF_WINDOWS) set(SERF_INCLUDE_SUBDIR "serf-${SERF_MAJOR_VERSION}") endif() install(FILES ${HEADERS} DESTINATION "include/${SERF_INCLUDE_SUBDIR}") # Generate the pkg-config module file. if(NOT SERF_WINDOWS) # Use a separate variable scope for the substitutions in serf.pc.in. function(make_pkgconfig) set(PREFIX ${CMAKE_INSTALL_PREFIX}) if(NOT LIBDIR) set(LIBDIR "\${prefix}/lib") endif() set(INCLUDE_SUBDIR ${SERF_INCLUDE_SUBDIR}) set(VERSION ${SERF_VERSION}) set(MAJOR ${SERF_MAJOR_VERSION}) set(SERF_INTERFACE_LIBS ${APR_LIBRARIES} ${APR_EXTRALIBS} ${APRUTIL_LIBRARIES} ${APRUTIL_EXTRALIBS} ) list(REMOVE_DUPLICATES SERF_INTERFACE_LIBS) unset(LIBS) foreach(DEPLIB ${SERF_INTERFACE_LIBS}) string(APPEND LIBS " ${DEPLIB}") endforeach() configure_file("build/serf.pc.in" "serf.pc" @ONLY) endfunction() make_pkgconfig() install(FILES "${CMAKE_CURRENT_BINARY_DIR}/serf.pc" DESTINATION "share/pkgconfig") endif() if(NOT SKIP_TESTS) if(SKIP_STATIC) message(WARNING "The tests depend on the Serf static library") message(STATUS "Skipping tests; to silence this message, either remove") message(STATUS "the SKIP_STATIC option or add the SKIP_TESTS option.") else() enable_testing() add_subdirectory(test) endif() endif()