1#
2# Libevent CMake project
3#
4# Based on initial work by:
5#    Alexey Ozeritsky
6#
7# Additional changes:
8#   Brodie Thiesfield
9#   Joakim Soderberg
10#   Trond Norbye
11#   Sergei Nikulov
12#
13#   Build example:
14#
15#       cd libevent
16#       md build
17#       cd build
18#       cmake -G "Visual Studio 10" ..
19#       start libevent.sln
20#
21
22cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
23
24if (POLICY CMP0054)
25    cmake_policy(SET CMP0054 NEW)
26endif()
27if (POLICY CMP0074)
28    cmake_policy(SET CMP0074 NEW)
29endif()
30if (POLICY CMP0075)
31    cmake_policy(SET CMP0075 NEW)
32endif()
33
34if(NOT CMAKE_BUILD_TYPE)
35    set(CMAKE_BUILD_TYPE Release
36        CACHE STRING "Set build type to Debug o Release (default Release)" FORCE)
37endif()
38string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
39
40# get rid of the extra default configurations
41# what? why would you get id of other useful build types? - Ellzey
42set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Limited configurations" FORCE)
43
44set(EVENT__LIBRARY_TYPE DEFAULT CACHE STRING
45    "Set library type to SHARED/STATIC/BOTH (default SHARED for MSVC, otherwise BOTH)")
46
47project(libevent C)
48
49list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
50string(REGEX MATCH "SunOS" SOLARIS "${CMAKE_SYSTEM_NAME}")
51
52
53include(CheckTypeSize)
54include(CheckFileOffsetBits)
55include(Macros)
56include(CheckVariableExists)
57include(CheckSymbolExists)
58include(CheckStructHasMember)
59include(CheckCSourceCompiles)
60include(CheckPrototypeDefinition)
61include(CheckFunctionKeywords)
62include(CheckConstExists)
63include(AddCompilerFlags)
64include(VersionViaGit)
65
66event_fuzzy_version_from_git()
67
68set(EVENT_VERSION_MAJOR ${EVENT_GIT___VERSION_MAJOR})
69set(EVENT_VERSION_MINOR ${EVENT_GIT___VERSION_MINOR})
70set(EVENT_VERSION_PATCH ${EVENT_GIT___VERSION_PATCH})
71set(EVENT_VERSION_STAGE ${EVENT_GIT___VERSION_STAGE})
72
73
74set(EVENT_ABI_MAJOR ${EVENT_VERSION_MAJOR})
75set(EVENT_ABI_MINOR ${EVENT_VERSION_MINOR})
76set(EVENT_ABI_PATCH ${EVENT_VERSION_PATCH})
77
78set(EVENT_ABI_LIBVERSION
79    "${EVENT_ABI_MAJOR}.${EVENT_ABI_MINOR}.${EVENT_ABI_PATCH}")
80
81set(EVENT_PACKAGE_VERSION
82    "${EVENT_VERSION_MAJOR}.${EVENT_VERSION_MINOR}.${EVENT_VERSION_PATCH}")
83
84set(EVENT_NUMERIC_VERSION 0x02010c00)
85# equals to VERSION_INFO in Makefile.am
86set(EVENT_ABI_LIBVERSION_CURRENT   7)
87set(EVENT_ABI_LIBVERSION_REVISION  1)
88set(EVENT_ABI_LIBVERSION_AGE       0)
89
90# equals to RELEASE in Makefile.am
91set(EVENT_PACKAGE_RELEASE 2.1)
92
93# only a subset of names can be used, defaults to "beta"
94set(EVENT_STAGE_NAME ${EVENT_VERSION_STAGE})
95
96# a list that defines what can set for EVENT_STAGE_VERSION
97set(EVENT__ALLOWED_STAGE_NAMES
98	rc
99	beta
100	alpha
101	alpha-dev
102	release
103	stable
104)
105list(
106	FIND EVENT__ALLOWED_STAGE_NAMES
107	"${EVENT_STAGE_NAME}"
108	EVENT__STAGE_RET
109)
110if (EVENT__STAGE_RET EQUAL -1)
111	message(WARNING
112		"stage ${EVENT_STAGE_NAME} is not allowed, reset to beta")
113	set(EVENT_STAGE_NAME beta)
114endif()
115
116set(EVENT_VERSION
117	"${EVENT_VERSION_MAJOR}.${EVENT_VERSION_MINOR}.${EVENT_VERSION_PATCH}-${EVENT_STAGE_NAME}")
118
119option(EVENT__DISABLE_DEBUG_MODE
120    "Define if libevent should build without support for a debug mode" OFF)
121
122option(EVENT__ENABLE_VERBOSE_DEBUG
123    "Enables verbose debugging" OFF)
124
125option(EVENT__DISABLE_MM_REPLACEMENT
126    "Define if libevent should not allow replacing the mm functions" OFF)
127
128option(EVENT__DISABLE_THREAD_SUPPORT
129    "Define if libevent should not be compiled with thread support" OFF)
130
131option(EVENT__DISABLE_OPENSSL
132    "Define if libevent should build without support for OpenSSL encryption" OFF)
133
134option(EVENT__DISABLE_BENCHMARK
135    "Defines if libevent should build without the benchmark executables" OFF)
136
137option(EVENT__DISABLE_TESTS
138    "If tests should be compiled or not" OFF)
139
140option(EVENT__DISABLE_REGRESS
141    "Disable the regress tests" OFF)
142
143option(EVENT__DISABLE_SAMPLES
144    "Disable sample files" OFF)
145
146option(EVENT__DISABLE_CLOCK_GETTIME
147    "Do not use clock_gettime even if it is available" OFF)
148
149option(EVENT__FORCE_KQUEUE_CHECK
150    "When crosscompiling forces running a test program that verifies that Kqueue works with pipes. Note that this requires you to manually run the test program on the cross compilation target to verify that it works. See cmake documentation for try_run for more details" OFF)
151
152# TODO: Add --disable-largefile     omit support for large files
153option(EVENT__COVERAGE
154"Enable running gcov to get a test coverage report (only works with GCC/CLang). Make sure to enable -DCMAKE_BUILD_TYPE=Debug as well." OFF)
155
156# Put the libaries and binaries that get built into directories at the
157# top of the build tree rather than in hard-to-find leaf directories.
158#
159# But only if this variables are not defined yet
160# (i.e. libevent is used via add_subdirectory())
161if (NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
162    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
163endif()
164if (NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
165    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
166endif()
167if (NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
168    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
169endif()
170
171if (EVENT__ENABLE_VERBOSE_DEBUG)
172    add_definitions(-DUSE_DEBUG=1)
173endif()
174
175# make it colorful under ninja-build
176if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
177    add_compiler_flags(-fdiagnostics-color=always)
178endif()
179
180# Setup compiler flags for coverage.
181if (EVENT__COVERAGE)
182    if (NOT "${CMAKE_BUILD_TYPE_LOWER}" STREQUAL "debug")
183        message(FATAL_ERROR "Coverage requires -DCMAKE_BUILD_TYPE=Debug")
184    endif()
185
186    message(STATUS "Setting coverage compiler flags")
187
188    set(CMAKE_REQUIRED_LIBRARIES "--coverage")
189    add_compiler_flags(-g -O0 --coverage)
190    set(CMAKE_REQUIRED_LIBRARIES "")
191endif()
192
193set(GNUC 0)
194set(CLANG 0)
195set(MSVC 0)
196if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR
197    ("${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang"))
198    set(CLANG 1)
199endif()
200if (("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR (${CLANG}))
201    set(GNUC 1)
202endif()
203if (("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") OR (${CLANG}))
204    set(MSVC 1)
205endif()
206
207# Detect library type
208set(EVENT_LIBRARY_TYPE)
209if ("${EVENT__LIBRARY_TYPE}" STREQUAL "DEFAULT")
210    if (${MSVC})
211        set(EVENT_LIBRARY_TYPE SHARED)
212    else()
213        set(EVENT_LIBRARY_TYPE BOTH)
214    endif()
215else()
216    string(TOUPPER "${EVENT__LIBRARY_TYPE}" EVENT_LIBRARY_TYPE)
217endif()
218if ((${MSVC}) AND ("${EVENT_LIBRARY_TYPE}" STREQUAL "BOTH"))
219    message(WARNING
220      "Building SHARED and STATIC is not supported for MSVC "
221      "(due to conflicts in library name"
222      " between STATIC library and IMPORTED library for SHARED libraries)")
223endif()
224set(EVENT_LIBRARY_STATIC OFF)
225set(EVENT_LIBRARY_SHARED OFF)
226if ("${EVENT_LIBRARY_TYPE}" STREQUAL "BOTH")
227    set(EVENT_LIBRARY_STATIC ON)
228    set(EVENT_LIBRARY_SHARED ON)
229elseif ("${EVENT_LIBRARY_TYPE}" STREQUAL "STATIC")
230    set(EVENT_LIBRARY_STATIC ON)
231elseif ("${EVENT_LIBRARY_TYPE}" STREQUAL "SHARED")
232    set(EVENT_LIBRARY_SHARED ON)
233else()
234    message(FATAL_ERROR "${EVENT_LIBRARY_TYPE} is not supported")
235endif()
236
237if (${MSVC})
238    set(msvc_static_runtime OFF)
239    if ("${EVENT_LIBRARY_TYPE}" STREQUAL "STATIC")
240        set(msvc_static_runtime ON)
241    endif()
242
243    # For more info:
244    # - https://docs.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=vs-2017
245    # - https://gitlab.kitware.com/cmake/community/wikis/FAQ#how-can-i-build-my-msvc-application-with-a-static-runtime
246    option(EVENT__MSVC_STATIC_RUNTIME
247           "Link static runtime libraries"
248           ${msvc_static_runtime})
249
250    if (EVENT__MSVC_STATIC_RUNTIME)
251        foreach (flag_var
252                 CMAKE_C_FLAGS_DEBUG
253                 CMAKE_C_FLAGS_RELEASE
254                 CMAKE_C_FLAGS_MINSIZEREL
255                 CMAKE_C_FLAGS_RELWITHDEBINFO
256        )
257            if (${flag_var} MATCHES "/MD")
258                string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
259            endif()
260        endforeach()
261    endif()
262endif()
263
264# GNUC specific options.
265if (${GNUC})
266    option(EVENT__DISABLE_GCC_WARNINGS "Disable verbose warnings with GCC" OFF)
267    option(EVENT__ENABLE_GCC_HARDENING "Enable compiler security checks" OFF)
268    option(EVENT__ENABLE_GCC_FUNCTION_SECTIONS "Enable gcc function sections" OFF)
269    option(EVENT__ENABLE_GCC_WARNINGS "Make all GCC warnings into errors" OFF)
270
271    set(GCC_V ${CMAKE_C_COMPILER_VERSION})
272
273    list(APPEND __FLAGS
274         -Wall -Wextra -Wno-unused-parameter -Wstrict-aliasing -Wstrict-prototypes
275
276         -fno-strict-aliasing # gcc 2.9.5+
277         -Wmissing-prototypes
278
279         # gcc 4
280         -Winit-self
281         -Wmissing-field-initializers
282         -Wdeclaration-after-statement
283
284         # gcc 4.2
285         -Waddress
286         -Wnormalized=id
287         -Woverride-init
288
289         # gcc 4.5
290         -Wlogical-op
291
292         -Wwrite-strings
293    )
294
295    if (${CLANG})
296        list(APPEND __FLAGS -Wno-unused-function)
297    endif()
298
299    if (EVENT__DISABLE_GCC_WARNINGS)
300        list(APPEND __FLAGS -w)
301    endif()
302
303    if (EVENT__ENABLE_GCC_HARDENING)
304        list(APPEND __FLAGS
305             -fstack-protector-all
306             -fwrapv
307             -fPIE
308             -Wstack-protector
309             "--param ssp-buffer-size=1")
310
311        add_definitions(-D_FORTIFY_SOURCE=2)
312    endif()
313
314    if (EVENT__ENABLE_GCC_FUNCTION_SECTIONS)
315        list(APPEND __FLAGS -ffunction-sections)
316        # TODO: Add --gc-sections support. We need some checks for NetBSD to ensure this works.
317    endif()
318
319    if (EVENT__ENABLE_GCC_WARNINGS)
320        list(APPEND __FLAGS -Werror)
321    endif()
322
323    add_compiler_flags(${__FLAGS})
324endif()
325
326if (APPLE)
327    # Get rid of deprecated warnings for OpenSSL on OSX 10.7 and greater.
328    add_compiler_flags(
329        -Wno-error=deprecated-declarations
330        -Qunused-arguments
331    )
332endif()
333
334if (MINGW OR CYGWIN)
335    set(WIN32 TRUE)
336endif()
337
338# Winsock.
339if(WIN32)
340    set(CMAKE_REQUIRED_LIBRARIES  ws2_32 shell32 advapi32)
341    set(CMAKE_REQUIRED_DEFINITIONS -FIwinsock2.h -FIws2tcpip.h -D_WIN32_WINNT=0x0600)
342endif()
343if (SOLARIS)
344    set(CMAKE_REQUIRED_LIBRARIES socket nsl)
345endif()
346
347# Check if _GNU_SOURCE is available.
348if (NOT DEFINED _GNU_SOURCE)
349  CHECK_SYMBOL_EXISTS(__GNU_LIBRARY__ "features.h" _GNU_SOURCE)
350
351  if (NOT _GNU_SOURCE)
352    unset(_GNU_SOURCE CACHE)
353    CHECK_SYMBOL_EXISTS(_GNU_SOURCE "features.h" _GNU_SOURCE)
354  endif()
355
356  if (ANDROID)
357    set(_GNU_SOURCE TRUE)
358  endif()
359endif()
360
361if (_GNU_SOURCE)
362    add_definitions(-D_GNU_SOURCE=1)
363    set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
364endif()
365
366# Check if header files exist
367list(APPEND FILES_TO_CHECK
368    fcntl.h
369    inttypes.h
370    memory.h
371    signal.h
372    stdarg.h
373    stddef.h
374    stdint.h
375    stdlib.h
376    string.h
377    errno.h
378    unistd.h
379    time.h
380    sys/types.h
381    sys/stat.h
382    sys/time.h
383    sys/param.h
384)
385if (WIN32)
386    list(APPEND FILES_TO_CHECK
387        io.h
388        winsock2.h
389        ws2tcpip.h
390        afunix.h
391    )
392else()
393    list(APPEND FILES_TO_CHECK
394        netdb.h
395        dlfcn.h
396        arpa/inet.h
397        poll.h
398        port.h
399        sys/socket.h
400        sys/random.h
401        sys/un.h
402        sys/devpoll.h
403        sys/epoll.h
404        sys/eventfd.h
405        sys/event.h
406        sys/ioctl.h
407        sys/mman.h
408        sys/queue.h
409        sys/select.h
410        sys/sendfile.h
411        sys/uio.h
412        sys/wait.h
413        sys/resource.h
414        sys/timerfd.h
415        netinet/in.h
416        netinet/in6.h
417        netinet/tcp.h
418        ifaddrs.h
419    )
420endif()
421
422if (NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux")
423    list(APPEND FILES_TO_CHECK sys/sysctl.h)
424endif()
425
426if (APPLE)
427    list(APPEND FILES_TO_CHECK
428        mach/mach_time.h
429        mach/mach.h
430    )
431endif()
432
433foreach(FILE ${FILES_TO_CHECK})
434    CHECK_INCLUDE_FILE_CONCAT(${FILE} "EVENT")
435endforeach()
436unset(FILES_TO_CHECK)
437
438# Check if functions exist
439list(APPEND SYMBOLS_TO_CHECK
440    getaddrinfo
441    getnameinfo
442    getprotobynumber
443    getservbyname
444    gethostbyname
445    inet_ntop
446    inet_pton
447    gettimeofday
448    signal
449    strtoll
450    splice
451    strlcpy
452    strsep
453    strtok_r
454    vasprintf
455    timerclear
456    timercmp
457    timerisset
458    timeradd
459    nanosleep
460    putenv
461    umask
462)
463if (NOT EVENT__DISABLE_CLOCK_GETTIME)
464    list(APPEND SYMBOLS_TO_CHECK clock_gettime)
465endif()
466
467if (WIN32)
468    list(APPEND SYMBOLS_TO_CHECK
469        _gmtime64_s
470        _gmtime64
471    )
472else()
473    list(APPEND SYMBOLS_TO_CHECK
474        getifaddrs
475        select
476        epoll_create
477        epoll_create1
478        epoll_ctl
479        eventfd
480        poll
481        port_create
482        kqueue
483        fcntl
484        mmap
485        pipe
486        pipe2
487        sendfile
488        sigaction
489        strsignal
490        sysctl
491        accept4
492        arc4random
493        arc4random_buf
494        arc4random_addrandom
495        getrandom
496        getegid
497        geteuid
498        issetugid
499        usleep
500        timerfd_create
501        setenv
502        unsetenv
503        setrlimit
504        gethostbyname_r
505    )
506    if (APPLE)
507        list(APPEND SYMBOLS_TO_CHECK mach_absolute_time)
508    endif()
509endif()
510
511# Add stdio.h for vasprintf
512set(EVENT_INCLUDES ${EVENT_INCLUDES} stdio.h)
513CHECK_SYMBOLS_EXIST("${SYMBOLS_TO_CHECK}" "${EVENT_INCLUDES}" "EVENT")
514unset(SYMBOLS_TO_CHECK)
515set(EVENT__HAVE_EPOLL ${EVENT__HAVE_EPOLL_CREATE})
516
517# Get the gethostbyname_r prototype.
518if(EVENT__HAVE_GETHOSTBYNAME_R)
519    CHECK_PROTOTYPE_DEFINITION(gethostbyname_r
520        "int gethostbyname_r(const char *name, struct hostent *hp, struct hostent_data *hdata)"
521        "0"
522        "netdb.h"
523        EVENT__HAVE_GETHOSTBYNAME_R_3_ARG)
524
525    CHECK_PROTOTYPE_DEFINITION(gethostbyname_r
526        "struct hostent *gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, int *herr)"
527        "NULL"
528        "netdb.h"
529        EVENT__HAVE_GETHOSTBYNAME_R_5_ARG)
530
531    CHECK_PROTOTYPE_DEFINITION(gethostbyname_r
532        "int gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, struct hostent **result, int *herr)"
533        "0"
534        "netdb.h"
535        EVENT__HAVE_GETHOSTBYNAME_R_6_ARG)
536endif()
537
538if(HAVE_PORT_H AND HAVE_PORT_CREATE)
539    set(EVENT__HAVE_EVENT_PORTS 1)
540endif()
541
542# Only `CHECK_TYPE_SIZE()' will use `CMAKE_EXTRA_INCLUDE_FILES'
543set(CMAKE_EXTRA_INCLUDE_FILES ${EVENT_INCLUDES})
544
545CHECK_TYPE_SIZE("struct sockaddr_un" EVENT__HAVE_STRUCT_SOCKADDR_UN)
546CHECK_TYPE_SIZE("uint8_t" EVENT__HAVE_UINT8_T)
547CHECK_TYPE_SIZE("uint16_t" EVENT__HAVE_UINT16_T)
548CHECK_TYPE_SIZE("uint32_t" EVENT__HAVE_UINT32_T)
549CHECK_TYPE_SIZE("uint64_t" EVENT__HAVE_UINT64_T)
550CHECK_TYPE_SIZE("short" EVENT__SIZEOF_SHORT BUILTIN_TYPES_ONLY)
551CHECK_TYPE_SIZE("int" EVENT__SIZEOF_INT BUILTIN_TYPES_ONLY)
552CHECK_TYPE_SIZE("unsigned" EVENT__SIZEOF_UNSIGNED BUILTIN_TYPES_ONLY)
553CHECK_TYPE_SIZE("unsigned int" EVENT__SIZEOF_UNSIGNED_INT BUILTIN_TYPES_ONLY)
554CHECK_TYPE_SIZE("long" EVENT__SIZEOF_LONG BUILTIN_TYPES_ONLY)
555CHECK_TYPE_SIZE("long long" EVENT__SIZEOF_LONG_LONG BUILTIN_TYPES_ONLY)
556
557if(WIN32)
558    # These aren't available until Windows Vista.
559    # But you can still link them. They just won't be found when running the exe.
560    set(EVENT__HAVE_INET_NTOP 0)
561    set(EVENT__HAVE_INET_PTON 0)
562endif()
563
564# Check for different inline keyword versions.
565check_function_keywords("inline" "__inline" "__inline__")
566
567if (HAVE_INLINE)
568    set(EVENT__inline inline)
569elseif (HAVE___INLINE)
570    set(EVENT__inline __inline)
571elseif(HAVE___INLINE__)
572    set(EVENT__inline __inline__)
573else()
574    set(EVENT__inline)
575endif()
576
577# __func__/__FUNCTION__ is not a macros in general
578CHECK_SYMBOL_EXISTS("__func__"     "" EVENT__HAVE___func__)
579CHECK_SYMBOL_EXISTS("__FUNCTION__" "" EVENT__HAVE___FUNCTION__)
580
581CHECK_SYMBOL_EXISTS(TAILQ_FOREACH sys/queue.h EVENT__HAVE_TAILQFOREACH)
582CHECK_CONST_EXISTS(CTL_KERN sys/sysctl.h EVENT__HAVE_DECL_CTL_KERN)
583CHECK_CONST_EXISTS(KERN_ARND sys/sysctl.h EVENT__HAVE_DECL_KERN_ARND)
584CHECK_SYMBOL_EXISTS(F_SETFD fcntl.h EVENT__HAVE_SETFD)
585
586CHECK_TYPE_SIZE(fd_mask EVENT__HAVE_FD_MASK)
587
588CHECK_TYPE_SIZE(size_t EVENT__SIZEOF_SIZE_T)
589if(NOT EVENT__SIZEOF_SIZE_T)
590  set(EVENT__size_t "unsigned")
591  set(EVENT__SIZEOF_SIZE_T ${EVENT__SIZEOF_UNSIGNED})
592else()
593    set(EVENT__size_t size_t)
594endif()
595
596CHECK_TYPE_SIZE("off_t" EVENT__SIZEOF_OFF_T LANGUAGE C)
597
598
599# XXX we should functionalize these size and type sets. --elley
600
601# Winssck.
602if (_MSC_VER)
603    list(APPEND CMAKE_EXTRA_INCLUDE_FILES BaseTsd.h)
604endif()
605CHECK_TYPE_SIZE("ssize_t" EVENT__SIZEOF_SSIZE_T_LOWER LANGUAGE C)
606CHECK_TYPE_SIZE("SSIZE_T" EVENT__SIZEOF_SSIZE_T_UPPER LANGUAGE C)
607
608if (EVENT__SIZEOF_SSIZE_T_LOWER)
609    set(EVENT__ssize_t "ssize_t")
610    set(EVENT__SIZEOF_SSIZE_T ${EVENT__SIZEOF_SSIZE_T_LOWER})
611elseif (EVENT__SIZEOF_SSIZE_T_UPPER)
612    set(EVENT__ssize_t "SSIZE_T")
613    set(EVENT__SIZEOF_SSIZE_T ${EVENT__SIZEOF_SSIZE_T_UPPER})
614else()
615    set(EVENT__ssize_t "int")
616    set(EVENT__SIZEOF_SSIZE_T ${EVENT__SIZEOF_INT})
617endif()
618
619CHECK_TYPE_SIZE(socklen_t EVENT__SIZEOF_SOCKLEN_T)
620if(NOT EVENT__SIZEOF_SOCKLEN_T)
621  set(EVENT__socklen_t "unsigned int")
622  set(EVENT__SIZEOF_SOCKLEN_T ${EVENT__SIZEOF_UNSIGNED_INT})
623else()
624    set(EVENT__socklen_t "socklen_t")
625endif()
626
627CHECK_TYPE_SIZE(pid_t EVENT__SIZEOF_PID_T)
628if(NOT EVENT__SIZEOF_PID_T)
629  set(EVENT__SIZEOF_PID_T ${EVENT__SIZEOF_INT})
630else()
631	set(EVENT__SIZEOF_PID_T EVENT__SIZEOF_PID_T)
632endif()
633
634if (NOT EVENT__DISABLE_THREAD_SUPPORT)
635    if (NOT WIN32)
636        list(APPEND CMAKE_EXTRA_INCLUDE_FILES pthread.h)
637    endif()
638    CHECK_TYPE_SIZE(pthread_t EVENT__SIZEOF_PTHREAD_T)
639endif()
640
641if(EVENT__HAVE_CLOCK_GETTIME)
642  set(EVENT__DNS_USE_CPU_CLOCK_FOR_ID 1)
643endif()
644
645# we're just getting lazy now.
646CHECK_TYPE_SIZE("uintptr_t" EVENT__HAVE_UINTPTR_T)
647CHECK_TYPE_SIZE("void *" EVENT__SIZEOF_VOID_P)
648CHECK_TYPE_SIZE("time_t" EVENT__SIZEOF_TIME_T)
649
650# Tests file offset bits.
651# TODO: Add AIX test for if -D_LARGE_FILES is needed.
652
653# XXX: Why is this here? we don't even use it. Well, we don't even use it
654#      on top of that, why is it set in the config.h?! IT_MAKES_NO_SENSE
655#      I'm commenting it out for now.
656#      - ellzey
657
658#CHECK_FILE_OFFSET_BITS()
659
660# Verify kqueue works with pipes.
661if (EVENT__HAVE_KQUEUE)
662    if ((CMAKE_CROSSCOMPILING OR APPLE) AND NOT EVENT__FORCE_KQUEUE_CHECK)
663        message(WARNING "Cannot check if kqueue works with pipes when crosscompiling, use EVENT__FORCE_KQUEUE_CHECK to be sure (this requires manually running a test program on the cross compilation target)")
664        set(EVENT__HAVE_WORKING_KQUEUE 1)
665    else()
666        message(STATUS "Checking if kqueue works with pipes...")
667        include(CheckWorkingKqueue)
668    endif()
669endif()
670
671if(EVENT__HAVE_NETDB_H)
672    list(APPEND CMAKE_EXTRA_INCLUDE_FILES netdb.h)
673    CHECK_TYPE_SIZE("struct addrinfo" EVENT__HAVE_STRUCT_ADDRINFO)
674elseif(WIN32)
675    list(APPEND CMAKE_EXTRA_INCLUDE_FILES ws2tcpip.h)
676    CHECK_TYPE_SIZE("struct addrinfo" EVENT__HAVE_STRUCT_ADDRINFO)
677endif()
678
679# Check for sockaddr structure sizes.
680set(SOCKADDR_HEADERS)
681if (WIN32)
682    set(CMAKE_REQUIRED_DEFINITIONS "-DWIN32_LEAN_AND_MEAN")
683    if (_MSC_VER LESS 1300)
684        set(SOCKADDR_HEADERS winsock.h)
685    else()
686        set(SOCKADDR_HEADERS winsock2.h ws2tcpip.h)
687    endif()
688else()
689    if (EVENT__HAVE_NETINET_IN_H)
690        set(SOCKADDR_HEADERS ${SOCKADDR_HEADERS} netinet/in.h)
691    endif()
692
693    if (EVENT__HAVE_NETINET_IN6_H)
694        set(SOCKADDR_HEADERS ${SOCKADDR_HEADERS} netinet/in6.h)
695    endif()
696
697    if (EVENT__HAVE_SYS_SOCKET_H)
698        set(SOCKADDR_HEADERS ${SOCKADDR_HEADERS} sys/socket.h)
699    endif()
700
701    if (EVENT__HAVE_NETDB_H)
702        set(SOCKADDR_HEADERS ${SOCKADDR_HEADERS} netdb.h)
703    endif()
704endif()
705
706CHECK_TYPE_SIZE("struct in6_addr" EVENT__HAVE_STRUCT_IN6_ADDR)
707if(EVENT__HAVE_STRUCT_IN6_ADDR)
708    CHECK_STRUCT_HAS_MEMBER("struct in6_addr"
709            s6_addr16 "${SOCKADDR_HEADERS}"
710            EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16)
711
712    CHECK_STRUCT_HAS_MEMBER("struct in6_addr"
713            s6_addr32 "${SOCKADDR_HEADERS}"
714            EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32)
715endif()
716
717CHECK_TYPE_SIZE("sa_family_t" EVENT__HAVE_SA_FAMILY_T)
718CHECK_TYPE_SIZE("struct sockaddr_in6" EVENT__HAVE_STRUCT_SOCKADDR_IN6)
719
720if(EVENT__HAVE_STRUCT_SOCKADDR_IN6)
721    CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in6"
722            sin6_len "${SOCKADDR_HEADERS}"
723            EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN)
724
725    CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in6"
726            sin_len "${SOCKADDR_HEADERS}"
727            EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN)
728endif()
729
730CHECK_TYPE_SIZE("struct sockaddr_storage" EVENT__HAVE_STRUCT_SOCKADDR_STORAGE)
731if(EVENT__HAVE_STRUCT_SOCKADDR_STORAGE)
732    CHECK_STRUCT_HAS_MEMBER("struct sockaddr_storage"
733            ss_family "${SOCKADDR_HEADERS}"
734            EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY)
735
736    CHECK_STRUCT_HAS_MEMBER("struct sockaddr_storage"
737            __ss_family "${SOCKADDR_HEADERS}" EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY)
738endif()
739
740CHECK_TYPE_SIZE("struct linger" EVENT__HAVE_STRUCT_LINGER)
741
742# Group the source files.
743set(HDR_PRIVATE
744    bufferevent-internal.h
745    changelist-internal.h
746    defer-internal.h
747    epolltable-internal.h
748    evbuffer-internal.h
749    event-internal.h
750    evmap-internal.h
751    evrpc-internal.h
752    evsignal-internal.h
753    evthread-internal.h
754    ht-internal.h
755    http-internal.h
756    iocp-internal.h
757    ipv6-internal.h
758    log-internal.h
759    minheap-internal.h
760    mm-internal.h
761    ratelim-internal.h
762    strlcpy-internal.h
763    util-internal.h
764    evconfig-private.h
765    compat/sys/queue.h)
766
767set(HDR_COMPAT
768    include/evdns.h
769    include/evrpc.h
770    include/event.h
771    include/evhttp.h
772    include/evutil.h)
773
774set(HDR_PUBLIC
775    include/event2/buffer.h
776    include/event2/bufferevent.h
777    include/event2/bufferevent_compat.h
778    include/event2/bufferevent_struct.h
779    include/event2/buffer_compat.h
780    include/event2/dns.h
781    include/event2/dns_compat.h
782    include/event2/dns_struct.h
783    include/event2/event.h
784    include/event2/event_compat.h
785    include/event2/event_struct.h
786    include/event2/http.h
787    include/event2/http_compat.h
788    include/event2/http_struct.h
789    include/event2/keyvalq_struct.h
790    include/event2/listener.h
791    include/event2/rpc.h
792    include/event2/rpc_compat.h
793    include/event2/rpc_struct.h
794    include/event2/tag.h
795    include/event2/tag_compat.h
796    include/event2/thread.h
797    include/event2/util.h
798    include/event2/visibility.h
799    ${PROJECT_BINARY_DIR}/include/event2/event-config.h)
800
801set(SRC_CORE
802    buffer.c
803    bufferevent.c
804    bufferevent_filter.c
805    bufferevent_pair.c
806    bufferevent_ratelim.c
807    bufferevent_sock.c
808    event.c
809    evmap.c
810    evthread.c
811    evutil.c
812    evutil_rand.c
813    evutil_time.c
814    listener.c
815    log.c
816    signal.c
817    strlcpy.c)
818
819if(EVENT__HAVE_SELECT)
820    list(APPEND SRC_CORE select.c)
821endif()
822
823if(EVENT__HAVE_POLL)
824    list(APPEND SRC_CORE poll.c)
825endif()
826
827if(EVENT__HAVE_KQUEUE)
828    list(APPEND SRC_CORE kqueue.c)
829endif()
830
831if(EVENT__HAVE_DEVPOLL)
832    list(APPEND SRC_CORE devpoll.c)
833endif()
834
835if(EVENT__HAVE_EPOLL)
836    list(APPEND SRC_CORE epoll.c)
837endif()
838
839if(EVENT__HAVE_EVENT_PORTS)
840    list(APPEND SRC_CORE evport.c)
841endif()
842
843if (NOT EVENT__DISABLE_OPENSSL)
844    find_package(OpenSSL REQUIRED)
845
846    set(EVENT__HAVE_OPENSSL 1)
847
848    message(STATUS "OpenSSL include: ${OPENSSL_INCLUDE_DIR}")
849    message(STATUS "OpenSSL lib: ${OPENSSL_LIBRARIES}")
850
851    include_directories(${OPENSSL_INCLUDE_DIR})
852
853    list(APPEND SRC_OPENSSL bufferevent_openssl.c)
854    list(APPEND HDR_PUBLIC include/event2/bufferevent_ssl.h)
855    list(APPEND LIB_APPS ${OPENSSL_LIBRARIES})
856endif()
857
858if (NOT EVENT__DISABLE_THREAD_SUPPORT)
859    if (WIN32)
860        list(APPEND SRC_CORE evthread_win32.c)
861    else()
862        find_package(Threads REQUIRED)
863        if (NOT CMAKE_USE_PTHREADS_INIT)
864            message(FATAL_ERROR
865                    "Failed to find Pthreads, set EVENT__DISABLE_THREAD_SUPPORT to disable")
866        endif()
867
868        set(EVENT__HAVE_PTHREADS 1)
869        list(APPEND LIB_APPS ${CMAKE_THREAD_LIBS_INIT})
870    endif()
871endif()
872
873if (NOT EVENT__DISABLE_TESTS)
874    # Zlib is only used for testing.
875    find_package(ZLIB)
876
877    if (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
878        include_directories(${ZLIB_INCLUDE_DIRS})
879
880        set(EVENT__HAVE_LIBZ 1)
881        list(APPEND LIB_APPS ${ZLIB_LIBRARIES})
882    endif()
883endif()
884
885set(SRC_EXTRA
886    event_tagging.c
887    http.c
888    evdns.c
889    evrpc.c)
890
891add_definitions(-DHAVE_CONFIG_H)
892
893# We use BEFORE here so we don't accidentally look in system directories
894# first for some previous versions of the headers that are installed.
895include_directories(BEFORE ${PROJECT_SOURCE_DIR}
896    ${PROJECT_SOURCE_DIR}/compat
897    ${PROJECT_SOURCE_DIR}/include)
898
899if(WIN32)
900    list(APPEND SRC_CORE
901        buffer_iocp.c
902        bufferevent_async.c
903        event_iocp.c
904        win32select.c)
905
906    list(APPEND HDR_PRIVATE WIN32-Code/getopt.h)
907
908    set(EVENT__DNS_USE_FTIME_FOR_ID 1)
909    set(LIB_PLATFORM ws2_32 shell32 advapi32)
910    add_definitions(
911            -D_CRT_SECURE_NO_WARNINGS
912            -D_CRT_NONSTDC_NO_DEPRECATE)
913
914    include_directories(./WIN32-Code)
915endif()
916
917if (SOLARIS)
918    list(APPEND LIB_PLATFORM socket nsl)
919endif()
920
921source_group("Headers Private"  FILES ${HDR_PRIVATE})
922source_group("Header Compat"    FILES ${HDR_COMPAT})
923source_group("Headers Public"   FILES ${HDR_PUBLIC})
924source_group("Source Core"      FILES ${SRC_CORE})
925source_group("Source Extra"     FILES ${SRC_EXTRA})
926
927# Generate the configure headers.
928# (Place them in the build dir so we don't polute the source tree with generated files).
929include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include)
930
931if (${GNUC})
932    set(EVENT_SHARED_FLAGS -fvisibility=hidden)
933elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "SunPro")
934    set(EVENT_SHARED_FLAGS -xldscope=hidden)
935endif()
936
937configure_file(
938    ${CMAKE_CURRENT_SOURCE_DIR}/event-config.h.cmake
939    ${CMAKE_CURRENT_BINARY_DIR}/include/event2/event-config.h
940        NEWLINE_STYLE UNIX)
941
942configure_file(
943    ${CMAKE_CURRENT_SOURCE_DIR}/evconfig-private.h.cmake
944    ${CMAKE_CURRENT_BINARY_DIR}/include/evconfig-private.h)
945
946#
947# Create the libraries.
948#
949include(AddEventLibrary)
950add_event_library(event_core SOURCES ${SRC_CORE})
951add_event_library(event_extra
952    INNER_LIBRARIES event_core
953    SOURCES ${SRC_EXTRA})
954
955if (NOT EVENT__DISABLE_OPENSSL)
956    add_event_library(event_openssl
957        INNER_LIBRARIES event_core
958        OUTER_INCLUDES ${OPENSSL_INCLUDE_DIR}
959        LIBRARIES ${OPENSSL_LIBRARIES}
960        SOURCES ${SRC_OPENSSL})
961endif()
962
963if (EVENT__HAVE_PTHREADS)
964    set(SRC_PTHREADS evthread_pthread.c)
965    add_event_library(event_pthreads
966        INNER_LIBRARIES event_core
967        SOURCES ${SRC_PTHREADS})
968endif()
969
970# library exists for historical reasons; it contains the contents of
971# both libevent_core and libevent_extra. You shouldn’t use it; it may
972# go away in a future version of Libevent.
973add_event_library(event SOURCES ${SRC_CORE} ${SRC_EXTRA})
974
975set(WIN32_GETOPT)
976if (WIN32)
977    set(_TMPLIBS)
978    if (${EVENT_LIBRARY_STATIC})
979        list(APPEND _TMPLIBS event_core_static event_static)
980    endif()
981    if (${EVENT_LIBRARY_SHARED})
982        list(APPEND _TMPLIBS event_core_shared event_shared)
983    endif()
984    foreach(lib ${_TMPLIBS})
985        target_link_libraries(${lib} iphlpapi)
986    endforeach()
987    unset(_TMPLIBS)
988
989    list(APPEND WIN32_GETOPT
990         WIN32-Code/getopt.c
991         WIN32-Code/getopt_long.c)
992endif()
993
994#
995# Samples.
996#
997macro(add_sample_prog ssl name)
998    add_executable(${name} ${ARGN})
999
1000    target_link_libraries(${name}
1001                          event_extra
1002                          event_core
1003                          ${LIB_APPS}
1004                          ${LIB_PLATFORM})
1005
1006    if (${ssl})
1007        target_link_libraries(${name} event_openssl)
1008        if(WIN32)
1009            target_link_libraries(${name} crypt32)
1010        endif()
1011    endif()
1012endmacro()
1013if (NOT EVENT__DISABLE_SAMPLES)
1014    set(SAMPLES
1015        event-read-fifo
1016        hello-world
1017        signal-test
1018        http-connect
1019        time-test)
1020
1021    foreach(SAMPLE ${SAMPLES})
1022        add_sample_prog(OFF ${SAMPLE} sample/${SAMPLE}.c)
1023    endforeach()
1024
1025    if (NOT EVENT__DISABLE_OPENSSL)
1026        add_sample_prog(ON https-client
1027                        sample/https-client.c
1028                        sample/openssl_hostname_validation.c
1029                        sample/hostcheck.c)
1030        add_sample_prog(ON le-proxy
1031                        sample/le-proxy.c)
1032    endif()
1033
1034    set(SAMPLES_WOPT
1035        dns-example
1036        http-server
1037    )
1038    foreach (SAMPLE ${SAMPLES_WOPT})
1039        add_sample_prog(OFF ${SAMPLE} sample/${SAMPLE}.c ${WIN32_GETOPT})
1040    endforeach()
1041endif()
1042
1043#
1044# Benchmarks
1045#
1046macro(add_bench_prog prog)
1047    add_executable(${prog} ${ARGN})
1048    target_link_libraries(${prog}
1049                          event_extra
1050                          event_core
1051                          ${LIB_APPS}
1052                          ${LIB_PLATFORM})
1053endmacro()
1054if (NOT EVENT__DISABLE_BENCHMARK)
1055    foreach (BENCHMARK bench_http bench_httpclient)
1056        add_bench_prog(${BENCHMARK} test/${BENCHMARK}.c)
1057    endforeach()
1058
1059    add_bench_prog(bench test/bench.c ${WIN32_GETOPT})
1060    add_bench_prog(bench_cascade test/bench_cascade.c ${WIN32_GETOPT})
1061endif()
1062
1063#
1064# Tests
1065#
1066macro(add_test_prog prog)
1067    add_executable(${prog} test/${prog}.c)
1068    target_link_libraries(${prog}
1069                          ${LIB_APPS}
1070                          ${LIB_PLATFORM}
1071                          event_core
1072                          event_extra
1073                          ${ARGN})
1074endmacro()
1075if (NOT EVENT__DISABLE_TESTS)
1076    #
1077    # Generate Regress tests.
1078    #
1079    if (NOT EVENT__DISABLE_REGRESS)
1080        # (We require python to generate the regress tests)
1081        find_package(PythonInterp 3)
1082
1083        if (PYTHONINTERP_FOUND)
1084            set(__FOUND_USABLE_PYTHON 1)
1085        else()
1086            find_package(PythonInterp 2)
1087            if (PYTHONINTERP_FOUND)
1088                set(__FOUND_USABLE_PYTHON 1)
1089            else()
1090                message(ERROR "No suitable Python version found, bailing...")
1091            endif()
1092        endif()
1093
1094        if (__FOUND_USABLE_PYTHON)
1095            message(STATUS "Generating regress tests...")
1096
1097            add_definitions(-DTINYTEST_LOCAL)
1098
1099            add_custom_command(
1100                OUTPUT
1101                    ${CMAKE_CURRENT_SOURCE_DIR}/test/regress.gen.c
1102                    ${CMAKE_CURRENT_SOURCE_DIR}/test/regress.gen.h
1103                DEPENDS
1104                    event_rpcgen.py
1105                    test/regress.rpc
1106                COMMAND ${PYTHON_EXECUTABLE} ../event_rpcgen.py --quiet regress.rpc
1107                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test)
1108
1109            list(APPEND SRC_REGRESS
1110                 test/regress.c
1111                 test/regress.gen.c
1112                 test/regress.gen.h
1113                 test/regress_buffer.c
1114                 test/regress_bufferevent.c
1115                 test/regress_dns.c
1116                 test/regress_et.c
1117                 test/regress_finalize.c
1118                 test/regress_http.c
1119                 test/regress_listener.c
1120                 test/regress_main.c
1121                 test/regress_minheap.c
1122                 test/regress_rpc.c
1123                 test/regress_testutils.c
1124                 test/regress_testutils.h
1125                 test/regress_util.c
1126                 test/tinytest.c)
1127
1128            if (WIN32)
1129                list(APPEND SRC_REGRESS test/regress_iocp.c)
1130                if (NOT EVENT__DISABLE_THREAD_SUPPORT)
1131                    list(APPEND SRC_REGRESS test/regress_thread.c)
1132                endif()
1133            elseif (EVENT__HAVE_PTHREADS)
1134                list(APPEND SRC_REGRESS test/regress_thread.c)
1135            endif()
1136
1137            if (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
1138                list(APPEND SRC_REGRESS test/regress_zlib.c)
1139            endif()
1140
1141            if (NOT EVENT__DISABLE_OPENSSL)
1142                list(APPEND SRC_REGRESS test/regress_ssl.c)
1143            endif()
1144
1145            add_executable(regress ${SRC_REGRESS})
1146
1147            target_link_libraries(regress
1148                                  ${LIB_APPS}
1149                                  ${LIB_PLATFORM}
1150                                  event_core
1151                                  event_extra)
1152            if (NOT EVENT__DISABLE_OPENSSL)
1153                target_link_libraries(regress event_openssl)
1154            endif()
1155            if (CMAKE_USE_PTHREADS_INIT)
1156                target_link_libraries(regress event_pthreads)
1157            endif()
1158        else()
1159            message(WARNING "No suitable Python interpreter found, cannot generate regress tests!")
1160        endif()
1161    endif()
1162
1163    #
1164    # Test programs.
1165    #
1166    # all of these, including the cmakelists.txt should be moved
1167    # into the dirctory 'tests' first.
1168    #
1169    # doing this, we can remove all the DISABLE_TESTS stuff, and simply
1170    # do something like:
1171    #
1172    # add_custom_targets(tests)
1173    # add_executable(... EXCLUDE_FROM_ALL ...c)
1174    # add_dependencis(tests testa testb testc)
1175    # add_test(....)
1176    #
1177    # then you can just run 'make tests' instead of them all
1178    # auto-compile|running
1179    # - ellzey
1180    set(TESTPROGS test-changelist
1181                  test-eof
1182                  test-closed
1183                  test-fdleak
1184                  test-init
1185                  test-time
1186                  test-weof)
1187
1188    foreach (TESTPROG ${TESTPROGS} test-dumpevents)
1189        add_test_prog(${TESTPROG})
1190    endforeach()
1191    if (UNIX)
1192        add_test_prog(test-ratelim m)
1193    else()
1194        add_test_prog(test-ratelim)
1195    endif()
1196
1197    set(ALL_TESTPROGS
1198        ${TESTPROGS}
1199        test-dumpevents
1200        test-ratelim
1201    )
1202
1203    #
1204    # We run all tests with the different backends turned on one at a time.
1205    #
1206
1207    # Add event backends based on system introspection result.
1208    set(BACKENDS "")
1209
1210    if (EVENT__HAVE_EPOLL)
1211        list(APPEND BACKENDS EPOLL)
1212    endif()
1213
1214    if (EVENT__HAVE_SELECT)
1215        list(APPEND BACKENDS SELECT)
1216    endif()
1217
1218    if (EVENT__HAVE_POLL)
1219        list(APPEND BACKENDS POLL)
1220    endif()
1221
1222    if (EVENT__HAVE_KQUEUE)
1223        list(APPEND BACKENDS KQUEUE)
1224    endif()
1225
1226    if (EVENT__HAVE_EVENT_PORTS)
1227        list(APPEND BACKENDS EVPORT)
1228    endif()
1229
1230    if (EVENT__HAVE_DEVPOLL)
1231        list(APPEND BACKENDS DEVPOLL)
1232    endif()
1233
1234    if (WIN32)
1235        list(APPEND BACKENDS WIN32)
1236    endif()
1237
1238
1239    # Default environment variables turns off all event systems,
1240    # then we enable each one, one at a time when creating the tests.
1241    set(DEFAULT_TEST_ENV_VARS)
1242    foreach(BACKEND ${BACKENDS})
1243        set(BACKEND_ENV_VAR "EVENT_NO${BACKEND}=1")
1244        list(APPEND DEFAULT_TEST_ENV_VARS "${BACKEND_ENV_VAR}")
1245    endforeach()
1246
1247    # Macro that creates the ctest test for a backend.
1248    macro(add_backend_test BACKEND_TEST_NAME ENV_VARS)
1249        set(TEST_NAMES "")
1250
1251        foreach (TESTPROG ${TESTPROGS})
1252            set(TEST_NAME ${TESTPROG}__${BACKEND_TEST_NAME})
1253
1254            add_test(${TEST_NAME}
1255                     ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTPROG})
1256
1257            list(APPEND TEST_NAMES ${TEST_NAME})
1258
1259            set_tests_properties(${TEST_NAME}
1260                                 PROPERTIES ENVIRONMENT "${ENV_VARS}")
1261        endforeach()
1262
1263        # Dump events test.
1264        if (__FOUND_USABLE_PYTHON)
1265            set(TEST_NAME test-dumpevents__${BACKEND_TEST_NAME})
1266
1267            add_test(${TEST_NAME}
1268                     ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-dumpevents |
1269                     ${PYTHON_EXECUTABLE}
1270                     ${CMAKE_CURRENT_SOURCE_DIR}/test/check-dumpevents.py)
1271
1272            set_tests_properties(${TEST_NAME}
1273                                 PROPERTIES ENVIRONMENT "${ENV_VARS}")
1274        else()
1275            message(WARNING "test-dumpevents will be run without output check since python was not found!")
1276            set(TEST_NAME test-dumpevents__${BACKEND_TEST_NAME}_no_check)
1277
1278            add_test(${TEST_NAME}
1279                     ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-dumpevents)
1280
1281            set_tests_properties(${TEST_NAME}
1282                                 PROPERTIES ENVIRONMENT "${ENV_VARS}")
1283        endif()
1284
1285        # Regress tests.
1286        if (NOT EVENT__DISABLE_REGRESS AND __FOUND_USABLE_PYTHON)
1287            set(TEST_NAME regress__${BACKEND_TEST_NAME})
1288
1289            add_test(${TEST_NAME}
1290                     ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress --quiet)
1291
1292            set_tests_properties(${TEST_NAME}
1293                                 PROPERTIES ENVIRONMENT "${ENV_VARS}")
1294
1295            add_test(${TEST_NAME}_debug
1296                     ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress --quiet)
1297
1298            set_tests_properties(${TEST_NAME}_debug
1299                                 PROPERTIES ENVIRONMENT "${ENV_VARS};EVENT_DEBUG_MODE=1")
1300        endif()
1301    endmacro()
1302
1303    # Add the tests for each backend.
1304    foreach(BACKEND ${BACKENDS})
1305        # Enable this backend only.
1306        set(BACKEND_ENV_VARS ${DEFAULT_TEST_ENV_VARS})
1307        list(REMOVE_ITEM BACKEND_ENV_VARS EVENT_NO${BACKEND}=1)
1308
1309        # Epoll has some extra settings.
1310        if (${BACKEND} STREQUAL "EPOLL")
1311            add_backend_test(timerfd_${BACKEND}
1312                            "${BACKEND_ENV_VARS};EVENT_PRECISE_TIMER=1")
1313
1314            add_backend_test(changelist_${BACKEND}
1315                            "${BACKEND_ENV_VARS};EVENT_EPOLL_USE_CHANGELIST=yes")
1316
1317            add_backend_test(timerfd_changelist_${BACKEND}
1318                            "${BACKEND_ENV_VARS};EVENT_EPOLL_USE_CHANGELIST=yes;EVENT_PRECISE_TIMER=1")
1319        else()
1320            add_backend_test(${BACKEND} "${BACKEND_ENV_VARS}")
1321        endif()
1322    endforeach()
1323
1324    #
1325    # Rate limiter tests.
1326    #
1327
1328    # Group limits, no connection limit.
1329    set(RL_BIN ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-ratelim)
1330
1331    add_test(test-ratelim__group_lim
1332             ${RL_BIN}
1333             -g 30000
1334             -n 30
1335             -t 100
1336             --check-grouplimit 1000
1337             --check-stddev 100)
1338
1339    # Connection limit, no group limit.
1340    add_test(test-ratelim__con_lim
1341             ${RL_BIN}
1342             -c 1000
1343             -n 30
1344             -t 100
1345             --check-connlimit 50
1346             --check-stddev 50)
1347
1348    # Connection limit and group limit.
1349    add_test(test-ratelim__group_con_lim
1350             ${RL_BIN}
1351             -c 1000
1352             -g 30000
1353             -n 30
1354             -t 100
1355             --check-grouplimit 1000
1356             --check-connlimit 50
1357             --check-stddev 50)
1358
1359    # Connection limit and group limit with independent drain.
1360    add_test(test-ratelim__group_con_lim_drain
1361             ${RL_BIN}
1362             -c 1000
1363             -g 35000
1364             -n 30
1365             -t 100
1366             -G 500
1367             --check-grouplimit 1000
1368             --check-connlimit 50
1369             --check-stddev 50)
1370
1371    # Add a "make verify" target, same as for autoconf.
1372    # (Important! This will unset all EVENT_NO* environment variables.
1373    #  If they are set in the shell the tests are running using simply "ctest" or "make test" will fail)
1374    if (WIN32)
1375        # Windows doesn't have "unset". But you can use "set VAR=" instead.
1376        # We need to guard against the possibility taht EVENT_NOWIN32 is set, and all test failing
1377        # since no event backend being available.
1378        file(TO_NATIVE_PATH ${CMAKE_CTEST_COMMAND} WINDOWS_CTEST_COMMAND)
1379
1380        file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/tmp/verify_tests.bat
1381            "
1382            set EVENT_NOWIN32=
1383            \"${WINDOWS_CTEST_COMMAND}\"
1384            ")
1385
1386        message(STATUS "${WINDOWS_CTEST_COMMAND}")
1387
1388        file(COPY ${CMAKE_CURRENT_BINARY_DIR}/tmp/verify_tests.bat
1389             DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
1390             FILE_PERMISSIONS
1391                             OWNER_READ
1392                             OWNER_WRITE
1393                             OWNER_EXECUTE
1394                             GROUP_READ
1395                             GROUP_EXECUTE
1396                             WORLD_READ WORLD_EXECUTE)
1397
1398        file(TO_NATIVE_PATH
1399                    "${CMAKE_CURRENT_BINARY_DIR}/verify_tests.bat" VERIFY_PATH)
1400
1401        add_custom_target(verify COMMAND "${VERIFY_PATH}"
1402                          DEPENDS event ${ALL_TESTPROGS})
1403    else()
1404        # On some platforms doing exec(unset) as CMake does won't work, so make sure
1405        # we run the unset command in a shell instead.
1406        # First we write the script contents.
1407        file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/tmp/verify_tests.sh
1408            "
1409            #!/bin/bash
1410            unset EVENT_NOEPOLL; unset EVENT_NOPOLL; unset EVENT_NOSELECT; unset EVENT_NOWIN32; unset EVENT_NOEVPORT; unset EVENT_NOKQUEUE; unset EVENT_NODEVPOLL
1411            ${CMAKE_CTEST_COMMAND}
1412            ")
1413
1414        # Then we copy the file (this allows us to set execute permission on it)
1415        file(COPY ${CMAKE_CURRENT_BINARY_DIR}/tmp/verify_tests.sh
1416             DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
1417             FILE_PERMISSIONS
1418                             OWNER_READ
1419                             OWNER_WRITE
1420                             OWNER_EXECUTE
1421                             GROUP_READ
1422                             GROUP_EXECUTE
1423                             WORLD_READ
1424                             WORLD_EXECUTE)
1425
1426        # Create the target that runs the script.
1427        add_custom_target(verify
1428                          COMMAND ${CMAKE_CURRENT_BINARY_DIR}/verify_tests.sh
1429                          DEPENDS event ${ALL_TESTPROGS})
1430    endif()
1431
1432    if (NOT EVENT__DISABLE_REGRESS AND __FOUND_USABLE_PYTHON)
1433        add_dependencies(verify regress)
1434    endif()
1435
1436    if (EVENT__COVERAGE)
1437        include(CodeCoverage)
1438
1439        setup_target_for_coverage(
1440            verify_coverage # Coverage target name "make verify_coverage"
1441            make            # Test runner.
1442            coverage        # Output directory.
1443            verify)         # Arguments passed to test runner. "make verify"
1444    endif()
1445
1446    enable_testing()
1447
1448    include(CTest)
1449endif()
1450
1451#
1452# Installation preparation.
1453#
1454
1455set(EVENT_INSTALL_CMAKE_DIR
1456    "${CMAKE_INSTALL_PREFIX}/lib/cmake/libevent")
1457
1458export(PACKAGE libevent)
1459
1460function(gen_package_config forinstall)
1461    if(${forinstall})
1462        set(CONFIG_FOR_INSTALL_TREE 1)
1463        set(dir "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}")
1464    else()
1465        set(CONFIG_FOR_INSTALL_TREE 0)
1466        set(dir "${PROJECT_BINARY_DIR}")
1467    endif()
1468    configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfig.cmake.in
1469                "${dir}/LibeventConfig.cmake"
1470                @ONLY)
1471endfunction()
1472
1473# Generate the config file for the build-tree.
1474set(EVENT__INCLUDE_DIRS
1475    "${PROJECT_SOURCE_DIR}/include"
1476    "${PROJECT_BINARY_DIR}/include")
1477
1478set(LIBEVENT_INCLUDE_DIRS
1479    ${EVENT__INCLUDE_DIRS}
1480    CACHE PATH "Libevent include directories")
1481
1482gen_package_config(0)
1483
1484# Generate the config file for the installation tree.
1485gen_package_config(1)
1486
1487# Generate version info for both build-tree and install-tree.
1488configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfigVersion.cmake.in
1489               ${PROJECT_BINARY_DIR}/LibeventConfigVersion.cmake
1490               @ONLY)
1491
1492# Install compat headers
1493install(FILES ${HDR_COMPAT}
1494        DESTINATION "include"
1495        COMPONENT dev)
1496
1497# Install public headers
1498install(FILES ${HDR_PUBLIC}
1499        DESTINATION "include/event2"
1500        COMPONENT dev)
1501
1502# Install the configs.
1503install(FILES
1504        ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake
1505        ${PROJECT_BINARY_DIR}/LibeventConfigVersion.cmake
1506        DESTINATION "${EVENT_INSTALL_CMAKE_DIR}"
1507        COMPONENT dev)
1508
1509# Install exports for the install-tree.
1510macro(install_export type)
1511    install(EXPORT LibeventTargets-${type}
1512        NAMESPACE ${PROJECT_NAME}::
1513        DESTINATION "${EVENT_INSTALL_CMAKE_DIR}"
1514        COMPONENT dev)
1515endmacro()
1516
1517if (${EVENT_LIBRARY_STATIC})
1518    install_export(static)
1519endif()
1520if (${EVENT_LIBRARY_SHARED})
1521    install_export(shared)
1522endif()
1523
1524# Install the scripts.
1525install(PROGRAMS
1526       ${CMAKE_CURRENT_SOURCE_DIR}/event_rpcgen.py
1527       DESTINATION "bin"
1528       COMPONENT runtime)
1529
1530# Create documents with doxygen.
1531option(EVENT__DOXYGEN
1532    "Enables doxygen documentation" OFF)
1533if (EVENT__DOXYGEN)
1534    include(UseDoxygen)
1535    UseDoxygen()
1536endif()
1537
1538
1539if (NOT TARGET uninstall)
1540	# Create the uninstall target.
1541	# https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake
1542	configure_file(${PROJECT_SOURCE_DIR}/cmake/Uninstall.cmake.in
1543				   ${PROJECT_BINARY_DIR}/Uninstall.cmake
1544				   @ONLY)
1545
1546	add_custom_target(uninstall
1547					  COMMAND ${CMAKE_COMMAND} -P ${PROJECT_BINARY_DIR}/Uninstall.cmake)
1548endif()
1549
1550message(STATUS "")
1551message(STATUS "        ---( Libevent " ${EVENT_VERSION} " )---")
1552message(STATUS "")
1553message(STATUS "Available event backends: ${BACKENDS}")
1554message(STATUS "CMAKE_BINARY_DIR:         ${CMAKE_BINARY_DIR}")
1555message(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")
1556message(STATUS "CMAKE_SOURCE_DIR:         ${CMAKE_SOURCE_DIR}")
1557message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
1558message(STATUS "PROJECT_BINARY_DIR:       ${PROJECT_BINARY_DIR}")
1559message(STATUS "PROJECT_SOURCE_DIR:       ${PROJECT_SOURCE_DIR}")
1560message(STATUS "CMAKE_MODULE_PATH:        ${CMAKE_MODULE_PATH}")
1561message(STATUS "CMAKE_COMMAND:            ${CMAKE_COMMAND}")
1562message(STATUS "CMAKE_ROOT:               ${CMAKE_ROOT}")
1563message(STATUS "CMAKE_SYSTEM:             ${CMAKE_SYSTEM}")
1564message(STATUS "CMAKE_SYSTEM_NAME:        ${CMAKE_SYSTEM_NAME}")
1565message(STATUS "CMAKE_SYSTEM_VERSION:     ${CMAKE_SYSTEM_VERSION}")
1566message(STATUS "CMAKE_SYSTEM_PROCESSOR:   ${CMAKE_SYSTEM_PROCESSOR}")
1567message(STATUS "CMAKE_SKIP_RPATH:         ${CMAKE_SKIP_RPATH}")
1568message(STATUS "CMAKE_VERBOSE_MAKEFILE:   ${CMAKE_VERBOSE_MAKEFILE}")
1569message(STATUS "CMAKE_C_FLAGS:            ${CMAKE_C_FLAGS}")
1570message(STATUS "CMAKE_BUILD_TYPE:         ${CMAKE_BUILD_TYPE}")
1571message(STATUS "CMAKE_C_COMPILER:         ${CMAKE_C_COMPILER} (id ${CMAKE_C_COMPILER_ID}, clang ${CLANG}, GNUC ${GNUC})")
1572message(STATUS "CMAKE_AR:                 ${CMAKE_AR}")
1573message(STATUS "CMAKE_RANLIB:             ${CMAKE_RANLIB}")
1574message(STATUS "")
1575
1576