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