1# Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. 2cmake_minimum_required(VERSION 3.0...3.23) 3 4 5PROJECT(lsquic C) 6 7OPTION(LSQUIC_FIU "Use Fault Injection in Userspace (FIU)" OFF) 8OPTION(LSQUIC_BIN "Compile example binaries that use the library" ON) 9OPTION(LSQUIC_TESTS "Compile library unit tests" ON) 10OPTION(LSQUIC_SHARED_LIB "Compile as shared librarry" OFF) 11OPTION(LSQUIC_DEVEL "Compile in development mode" OFF) 12 13INCLUDE(GNUInstallDirs) 14 15MESSAGE(STATUS "CMake v${CMAKE_VERSION}") 16 17IF (CMAKE_SYSTEM_NAME STREQUAL "Linux") 18 # If using older glibc, need to link with -lrt. See clock_getres(2). 19 include(CheckSymbolExists) 20 check_symbol_exists(clock_getres "time.h" HAS_clock_getres_WITHOUT_LIBRT) 21 22 if(NOT HAS_clock_getres_WITHOUT_LIBRT) 23 find_library(RT_LIBRARY rt) 24 set(NEED_LIBRT_FOR_clock_getres ON) 25 endif() 26ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Android") 27 # for android-ndk >= r19b 28 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "BOTH") 29 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "BOTH") 30 set(CMAKE_FIND_ROOT_PATH_MODE_PATH "BOTH") 31ENDIF() 32 33IF("${CMAKE_BUILD_TYPE}" STREQUAL "") 34 SET(CMAKE_BUILD_TYPE Debug) 35ENDIF() 36 37MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 38 39IF (NOT "$ENV{EXTRA_CFLAGS}" MATCHES "-DLSQUIC_DEBUG_NEXT_ADV_TICK") 40 SET(MY_CMAKE_FLAGS "-DLSQUIC_DEBUG_NEXT_ADV_TICK=1") 41ENDIF() 42 43IF (NOT "$ENV{EXTRA_CFLAGS}" MATCHES "-DLSQUIC_CONN_STATS=") 44 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DLSQUIC_CONN_STATS=1") 45ENDIF() 46 47IF (NOT MSVC) 48 49SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Wall -Wextra -Wno-unused-parameter") 50SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -fno-omit-frame-pointer") 51 52IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.3) 53 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Wno-missing-field-initializers") 54ENDIF() 55 56IF(LSQUIC_FIU) 57 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DFIU_ENABLE=1") 58 SET(LIBS ${LIBS} fiu) 59ENDIF() 60 61IF(CMAKE_BUILD_TYPE STREQUAL "Debug") 62 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -O0 -g3") 63 IF(CMAKE_C_COMPILER MATCHES "clang" AND 64 NOT "$ENV{TRAVIS}" MATCHES "^true$" AND 65 NOT "$ENV{EXTRA_CFLAGS}" MATCHES "-fsanitize") 66 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -fsanitize=address") 67 SET(LIBS ${LIBS} -fsanitize=address) 68 ENDIF() 69 # Uncomment to enable cleartext protocol mode (no crypto): 70 #SET (MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DLSQUIC_ENABLE_HANDSHAKE_DISABLE=1") 71ELSE() 72 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -O3 -g0") 73 # Comment out the following line to compile out debug messages: 74 #SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DLSQUIC_LOWEST_LOG_LEVEL=LSQ_LOG_INFO") 75ENDIF() 76 77IF (LSQUIC_DEVEL) 78 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DLSQUIC_DEVEL=1") 79ENDIF() 80 81IF(LSQUIC_PROFILE EQUAL 1) 82 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -g -pg") 83ENDIF() 84 85IF(LSQUIC_COVERAGE EQUAL 1) 86 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -fprofile-arcs -ftest-coverage") 87ENDIF() 88 89IF(MY_CMAKE_FLAGS MATCHES "fsanitize=address") 90 MESSAGE(STATUS "AddressSanitizer is ON") 91ELSE() 92 MESSAGE(STATUS "AddressSanitizer is OFF") 93ENDIF() 94 95#MSVC 96ELSE() 97SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4100") # unreferenced formal parameter 98SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4115") # unnamed type definition in parentheses 99SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4116") # named type definition in parentheses 100SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4146") # unary minus operator applied to unsigned type, result still unsigned 101SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4132") # const initialization 102SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4200") # zero-sized array 103SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4204") # non-constant aggregate initializer 104SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4244") # integer conversion 105SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4245") # conversion from 'int' to 'unsigned int', signed/unsigned mismatch 106SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4267") # integer conversion 107SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4214") # nonstandard extension used: bit field types other than int 108SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4295") # array is too small to include a terminating null character 109SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4334") # result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?) 110SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4456") # hide previous local declaration 111SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4459") # hide global declaration 112SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4706") # assignment within conditional expression 113SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4090") # different 'const' qualifier (TODO: debug ls-sfparser.c) 114SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4305") # truncation from double to float 115SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -W4 -WX -Zi -DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS -I${CMAKE_CURRENT_SOURCE_DIR}/wincompat") 116IF(LSQUIC_SHARED_LIB) 117 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DLSQUIC_SHARED_LIB") 118ENDIF() 119IF(CMAKE_BUILD_TYPE STREQUAL "Debug") 120 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Od") 121 #SET (MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DFIU_ENABLE=1") 122 #SET(LIBS ${LIBS} fiu) 123ELSE() 124 SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Ox") 125 # Comment out the following line to compile out debug messages: 126 #SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DLSQUIC_LOWEST_LOG_LEVEL=LSQ_LOG_INFO") 127ENDIF() 128 129ENDIF() #MSVC 130 131set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MY_CMAKE_FLAGS} $ENV{EXTRA_CFLAGS}") 132 133MESSAGE(STATUS "Compiler flags: ${CMAKE_C_FLAGS}") 134 135find_package(Perl) 136IF(NOT PERL_FOUND) 137 MESSAGE(FATAL_ERROR "Perl not found -- need it to generate source code") 138ENDIF() 139 140IF (MSVC) 141 IF(LSQUIC_SHARED_LIB) 142 set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS YES CACHE BOOL "Export all symbols") 143 SET(LIB_SUFFIX .dll) 144 ELSE() 145 SET(LIB_SUFFIX .lib) 146 ENDIF() 147ELSE() 148 IF(LSQUIC_SHARED_LIB) 149 SET(LIB_SUFFIX .so) 150 ELSE() 151 SET(LIB_SUFFIX .a) 152 ENDIF() 153ENDIF() 154 155IF (NOT DEFINED BORINGSSL_INCLUDE AND DEFINED BORINGSSL_DIR) 156 FIND_PATH(BORINGSSL_INCLUDE NAMES openssl/ssl.h 157 PATHS ${BORINGSSL_DIR}/include 158 NO_DEFAULT_PATH) 159ENDIF() 160# This must be done before adding other include directories to take 161# precedence over header files from other SSL installs. 162 163IF (BORINGSSL_INCLUDE) 164 MESSAGE(STATUS "BoringSSL include directory ${BORINGSSL_INCLUDE}") 165 INCLUDE_DIRECTORIES(${BORINGSSL_INCLUDE}) 166ELSE() 167 MESSAGE(FATAL_ERROR "BoringSSL headers not found") 168ENDIF() 169 170IF (NOT DEFINED BORINGSSL_LIB AND DEFINED BORINGSSL_DIR) 171 FOREACH(LIB_NAME ssl crypto) 172 IF (CMAKE_SYSTEM_NAME STREQUAL Windows) 173 FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME} 174 NAMES ${LIB_NAME} 175 PATHS ${BORINGSSL_DIR}/${LIB_NAME} 176 PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo 177 NO_DEFAULT_PATH) 178 ELSE() 179 FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME} 180 NAMES lib${LIB_NAME}${LIB_SUFFIX} 181 PATHS ${BORINGSSL_DIR}/${LIB_NAME} 182 NO_DEFAULT_PATH) 183 ENDIF() 184 IF(BORINGSSL_LIB_${LIB_NAME}) 185 MESSAGE(STATUS "Found ${LIB_NAME} library: ${BORINGSSL_LIB_${LIB_NAME}}") 186 ELSE() 187 MESSAGE(STATUS "${LIB_NAME} library not found") 188 ENDIF() 189 ENDFOREACH() 190 191ELSE() 192 193 194 FOREACH(LIB_NAME ssl crypto) 195 # If BORINGSSL_LIB is defined, try find each lib. Otherwise, user should define BORINGSSL_LIB_ssl, 196 # BORINGSSL_LIB_crypto and so on explicitly. For example, including boringssl and lsquic both via 197 # add_subdirectory: 198 # add_subdirectory(third_party/boringssl) 199 # set(BORINGSSL_LIB_ssl ssl) 200 # set(BORINGSSL_LIB_crypto crypto) 201 # add_subdirectory(third_party/lsquic) 202 IF (DEFINED BORINGSSL_LIB) 203 IF (CMAKE_SYSTEM_NAME STREQUAL Windows) 204 FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME} 205 NAMES ${LIB_NAME} 206 PATHS ${BORINGSSL_LIB} 207 PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo 208 NO_DEFAULT_PATH) 209 ELSE() 210 FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME} 211 NAMES lib${LIB_NAME}${LIB_SUFFIX} 212 PATHS ${BORINGSSL_LIB} 213 PATH_SUFFIXES ${LIB_NAME} 214 NO_DEFAULT_PATH) 215 ENDIF() 216 ENDIF() 217 IF(BORINGSSL_LIB_${LIB_NAME}) 218 MESSAGE(STATUS "Found ${LIB_NAME} library: ${BORINGSSL_LIB_${LIB_NAME}}") 219 ELSE() 220 MESSAGE(FATAL_ERROR "BORINGSSL_LIB_${LIB_NAME} library not found") 221 ENDIF() 222 ENDFOREACH() 223 224ENDIF() 225 226SET(CMAKE_INCLUDE_CURRENT_DIR ON) 227INCLUDE_DIRECTORIES(include) 228IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") 229 # Find libevent on FreeBSD: 230 include_directories( /usr/local/include ) 231 link_directories( /usr/local/lib ) 232ENDIF() 233 234IF (CMAKE_SYSTEM_NAME STREQUAL Windows) 235 FIND_PATH(GETOPT_INCLUDE_DIR NAMES getopt.h) 236 IF (GETOPT_INCLUDE_DIR) 237 INCLUDE_DIRECTORIES(${GETOPT_INCLUDE_DIR}) 238 ELSE() 239 MESSAGE(FATAL_ERROR "getopt.h was not found") 240 ENDIF() 241 FIND_LIBRARY(GETOPT_LIB getopt) 242 IF(GETOPT_LIB) 243 MESSAGE(STATUS "Found getopt: ${GETOPT_LIB}") 244 ELSE() 245 MESSAGE(STATUS "getopt not found") 246 ENDIF() 247ENDIF() 248 249# Find zlib and libevent header files and library files 250# TODO: libevent is not strictly necessary to build the library. 251FIND_PATH(ZLIB_INCLUDE_DIR NAMES zlib.h) 252IF (ZLIB_INCLUDE_DIR) 253 INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) 254ELSE() 255 MESSAGE(FATAL_ERROR "zlib.h was not found") 256ENDIF() 257IF (CMAKE_SYSTEM_NAME STREQUAL Windows) 258 FIND_LIBRARY(ZLIB_LIB zlib) 259ELSEIF(CMAKE_SYSTEM_NAME STREQUAL Darwin) 260 # XXX somehow FIND_LIBRARY() does not find zlib on Travis? 261 SET(ZLIB_LIB z) 262ELSE() 263 FIND_LIBRARY(ZLIB_LIB libz${LIB_SUFFIX}) 264ENDIF() 265IF(ZLIB_LIB) 266 MESSAGE(STATUS "Found zlib: ${ZLIB_LIB}") 267ELSE() 268 MESSAGE(STATUS "zlib not found") 269ENDIF() 270 271SET(LIBS lsquic ${BORINGSSL_LIB_ssl} ${BORINGSSL_LIB_crypto} ${ZLIB_LIB} ${LIBS}) 272 273IF (LSQUIC_BIN) 274 FIND_PATH(EVENT_INCLUDE_DIR NAMES event2/event.h) 275 IF (EVENT_INCLUDE_DIR) 276 INCLUDE_DIRECTORIES(${EVENT_INCLUDE_DIR}) 277 ELSE() 278 MESSAGE(WARNING "event2/event.h was not found: binaries won't be built") 279 SET(LSQUIC_BIN OFF) 280 ENDIF() 281ENDIF() 282 283IF (LSQUIC_BIN) 284 IF (CMAKE_SYSTEM_NAME STREQUAL Windows) 285 FIND_LIBRARY(EVENT_LIB event) 286 ELSE() 287 FIND_LIBRARY(EVENT_LIB libevent${LIB_SUFFIX}) 288 IF(NOT EVENT_LIB) 289 FIND_LIBRARY(EVENT_LIB libevent.so) 290 ENDIF() 291 ENDIF() 292 IF(EVENT_LIB) 293 MESSAGE(STATUS "Found event: ${EVENT_LIB}") 294 ELSE() 295 MESSAGE(WARNING "libevent not found: binaries won't be built") 296 SET(LSQUIC_BIN OFF) 297 ENDIF() 298ENDIF() 299 300 301IF (NOT MSVC) 302 LIST(APPEND LIBS pthread m) 303ELSE() 304 LIST(APPEND LIBS ws2_32) 305ENDIF() 306 307IF (LSQUIC_BIN) 308 ADD_SUBDIRECTORY(bin) 309ENDIF() 310 311add_subdirectory(src) 312 313IF(LSQUIC_TESTS AND CMAKE_BUILD_TYPE STREQUAL "Debug") 314 # Our test framework relies on assertions, only compile if assertions are 315 # enabled. 316 # 317 enable_testing() 318 add_subdirectory(tests) 319ENDIF() 320 321 322FIND_PROGRAM(SPHINX NAMES sphinx-build) 323IF(SPHINX) 324 ADD_CUSTOM_TARGET(docs 325 ${SPHINX} -b html 326 docs 327 docs/_build 328 ) 329ELSE() 330 MESSAGE(STATUS "sphinx-build not found: docs won't be made") 331ENDIF() 332 333INSTALL(FILES 334 include/lsquic.h 335 include/lsquic_types.h 336 include/lsxpack_header.h 337 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lsquic 338) 339