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