CMakeLists.txt revision fb3e20e0
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    SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Werror")
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 (NOT DEFINED BORINGSSL_INCLUDE AND DEFINED BORINGSSL_DIR)
127    FIND_PATH(BORINGSSL_INCLUDE NAMES openssl/ssl.h
128                PATHS ${BORINGSSL_DIR}/include
129                NO_DEFAULT_PATH)
130ENDIF()
131# This must be done before adding other include directories to take
132# precedence over header files from other SSL installs.
133
134IF (BORINGSSL_INCLUDE)
135    MESSAGE(STATUS "BoringSSL include directory ${BORINGSSL_INCLUDE}")
136    INCLUDE_DIRECTORIES(${BORINGSSL_INCLUDE})
137ELSE()
138    MESSAGE(FATAL_ERROR "BoringSSL headers not found")
139ENDIF()
140
141IF (NOT DEFINED BORINGSSL_LIB AND DEFINED BORINGSSL_DIR)
142    FOREACH(LIB_NAME ssl crypto decrepit)
143        IF (CMAKE_SYSTEM_NAME STREQUAL Windows)
144            FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME}
145                NAMES ${LIB_NAME}
146                PATHS ${BORINGSSL_DIR}/${LIB_NAME}
147		PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
148                NO_DEFAULT_PATH)
149        ELSE()
150            FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME}
151                NAMES lib${LIB_NAME}.a
152                PATHS ${BORINGSSL_DIR}/${LIB_NAME}
153                NO_DEFAULT_PATH)
154        ENDIF()
155        IF(BORINGSSL_LIB_${LIB_NAME})
156            MESSAGE(STATUS "Found ${LIB_NAME} library: ${BORINGSSL_LIB_${LIB_NAME}}")
157        ELSE()
158            MESSAGE(STATUS "${LIB_NAME} library not found")
159        ENDIF()
160    ENDFOREACH()
161
162ELSE()
163
164
165    FOREACH(LIB_NAME ssl crypto decrepit)
166        IF (CMAKE_SYSTEM_NAME STREQUAL Windows)
167            FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME}
168                NAMES ${LIB_NAME}
169                PATHS ${BORINGSSL_LIB}
170                PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
171                NO_DEFAULT_PATH)
172        ELSE()
173            FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME}
174                NAMES lib${LIB_NAME}.a
175                PATHS ${BORINGSSL_LIB}
176                PATH_SUFFIXES ${LIB_NAME}
177                NO_DEFAULT_PATH)
178        ENDIF()
179        IF(BORINGSSL_LIB_${LIB_NAME})
180            MESSAGE(STATUS "Found ${BORINGSSL_LIB} library: ${BORINGSSL_LIB_${LIB_NAME}}")
181        ELSE()
182            MESSAGE(STATUS "${BORINGSSL_LIB} library not found")
183        ENDIF()
184    ENDFOREACH()
185
186ENDIF()
187
188SET(CMAKE_INCLUDE_CURRENT_DIR ON)
189INCLUDE_DIRECTORIES(include)
190IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
191    # Find libevent on FreeBSD:
192    include_directories( /usr/local/include )
193    link_directories( /usr/local/lib )
194ENDIF()
195
196# Find zlib and libevent header files and library files
197# TODO: libevent is not strictly necessary to build the library.
198FIND_PATH(ZLIB_INCLUDE_DIR NAMES zlib.h)
199IF (ZLIB_INCLUDE_DIR)
200    INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
201ELSE()
202    MESSAGE(FATAL_ERROR "zlib.h was not found")
203ENDIF()
204IF (CMAKE_SYSTEM_NAME STREQUAL Windows)
205    FIND_LIBRARY(ZLIB_LIB zlib)
206ELSEIF(CMAKE_SYSTEM_NAME STREQUAL Darwin)
207    # XXX somehow FIND_LIBRARY() does not find zlib on Travis?
208    SET(ZLIB_LIB z)
209ELSE()
210    FIND_LIBRARY(ZLIB_LIB libz.a)
211ENDIF()
212IF(ZLIB_LIB)
213    MESSAGE(STATUS "Found zlib: ${ZLIB_LIB}")
214ELSE()
215    MESSAGE(STATUS "zlib not found")
216ENDIF()
217
218IF (LSQUIC_BIN OR LSQUIC_TESTS)
219FIND_PATH(EVENT_INCLUDE_DIR NAMES event2/event.h)
220IF (EVENT_INCLUDE_DIR)
221    INCLUDE_DIRECTORIES(${EVENT_INCLUDE_DIR})
222ELSE()
223    MESSAGE(FATAL_ERROR "event2/event.h was not found")
224ENDIF()
225IF (CMAKE_SYSTEM_NAME STREQUAL Windows)
226    FIND_LIBRARY(EVENT_LIB event)
227ELSE()
228    FIND_LIBRARY(EVENT_LIB libevent.a)
229    IF(NOT EVENT_LIB)
230        FIND_LIBRARY(EVENT_LIB libevent.so)
231    ENDIF()
232ENDIF()
233IF(EVENT_LIB)
234    MESSAGE(STATUS "Found event: ${EVENT_LIB}")
235ELSE()
236    MESSAGE(STATUS "libevent not found")
237ENDIF()
238SET(LIBS lsquic ${EVENT_LIB} ${BORINGSSL_LIB_ssl} ${BORINGSSL_LIB_crypto} ${ZLIB_LIB} ${LIBS})
239IF(MSVC)
240FIND_LIBRARY(PCRE_LIB pcre)
241IF(PCRE_LIB)
242    MESSAGE(STATUS "Found pcre: ${PCRE_LIB}")
243    LIST(APPEND LIBS ${PCRE_LIB})
244ELSE()
245    MESSAGE(STATUS "pcre not found: http_server won't work")
246ENDIF()
247FIND_LIBRARY(PCREPOSIX_LIB pcreposix)
248IF(PCREPOSIX_LIB)
249    MESSAGE(STATUS "Found pcreposix: ${PCREPOSIX_LIB}")
250    LIST(APPEND LIBS ${PCREPOSIX_LIB})
251ELSE()
252    MESSAGE(STATUS "pcreposix not found: http_server won't work")
253ENDIF()
254LIST(APPEND LIBS ws2_32)
255ENDIF()
256ENDIF()	# LSQUIC_BIN OR LSQUIC_TESTS
257
258IF(LSQUIC_BIN)
259IF(MSVC)
260    SET(GETOPT_C wincompat/getopt.c)
261ENDIF()
262add_executable(http_server bin/http_server.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
263IF(NOT MSVC)   #   TODO: port MD5 server and client to Windows
264add_executable(md5_server bin/md5_server.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
265add_executable(md5_client bin/md5_client.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
266ENDIF()
267add_executable(echo_server bin/echo_server.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
268add_executable(echo_client bin/echo_client.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
269
270
271IF (NOT MSVC)
272
273add_executable(http_client
274    bin/http_client.c
275    bin/prog.c
276    bin/test_common.c
277    bin/test_cert.c
278)
279LIST(APPEND LIBS pthread m)
280
281#MSVC
282ELSE()
283
284add_executable(http_client
285    bin/http_client.c
286    bin/prog.c
287    bin/test_common.c
288    bin/test_cert.c
289    wincompat/getopt.c
290    wincompat/getopt1.c
291)
292LIST(APPEND LIBS ws2_32)
293
294ENDIF()
295
296TARGET_LINK_LIBRARIES(http_client ${LIBS})
297TARGET_LINK_LIBRARIES(http_server ${LIBS})
298IF(NOT MSVC)
299TARGET_LINK_LIBRARIES(md5_server  ${LIBS})
300TARGET_LINK_LIBRARIES(md5_client  ${LIBS})
301ENDIF()
302TARGET_LINK_LIBRARIES(echo_server ${LIBS})
303TARGET_LINK_LIBRARIES(echo_client ${LIBS})
304
305add_subdirectory(bin)
306ENDIF() # LSQUIC_BIN
307
308add_subdirectory(src)
309
310IF(LSQUIC_TESTS AND CMAKE_BUILD_TYPE STREQUAL "Debug")
311    # Our test framework relies on assertions, only compile if assertions are
312    # enabled.
313    #
314    enable_testing()
315    add_subdirectory(tests)
316ENDIF()
317
318
319FIND_PROGRAM(SPHINX NAMES sphinx-build)
320IF(SPHINX)
321    ADD_CUSTOM_TARGET(docs
322        ${SPHINX} -b html
323        docs
324        docs/_build
325    )
326ELSE()
327    MESSAGE(STATUS "sphinx-build not found: docs won't be made")
328ENDIF()
329