CMakeLists.txt revision d755d26e
1# Copyright (c) 2017 - 2021 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
340if(WIN32)
341    # The other file in wincompat is not used in installed headers
342    INSTALL(FILES
343        wincompat/vc_compat.h
344        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lsquic
345    )
346endif()
347