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