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