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