diff options
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/AddDependencySubdirectories.cmake | 107 | ||||
-rw-r--r-- | cmake/CheckSymbols.cmake | 146 | ||||
-rw-r--r-- | cmake/CheckSystemFeatures.cmake | 207 | ||||
-rw-r--r-- | cmake/CheckSystemHeaders.cmake | 139 | ||||
-rw-r--r-- | cmake/CheckURLInclude.cmake | 51 | ||||
-rw-r--r-- | cmake/InstallRspamdFiles.cmake | 104 | ||||
-rw-r--r-- | cmake/OSDep.cmake | 175 | ||||
-rw-r--r-- | cmake/Sanitizer.cmake | 145 | ||||
-rw-r--r-- | cmake/SetupPVSStudio.cmake | 56 |
9 files changed, 1003 insertions, 127 deletions
diff --git a/cmake/AddDependencySubdirectories.cmake b/cmake/AddDependencySubdirectories.cmake new file mode 100644 index 000000000..866204ff5 --- /dev/null +++ b/cmake/AddDependencySubdirectories.cmake @@ -0,0 +1,107 @@ +function(AddDependencySubdirectories) + # Core dependencies + add_subdirectory(contrib/hiredis) + include_directories(BEFORE "${CMAKE_SOURCE_DIR}/contrib/hiredis") + + # Configure xxhash + if (SYSTEM_XXHASH MATCHES "OFF") + add_subdirectory(contrib/xxhash) + include_directories("${CMAKE_SOURCE_DIR}/contrib/xxhash") + else () + ProcessPackage(XXHASH LIBRARY xxhash INCLUDE xxhash.h + ROOT ${LIBXXHASH_ROOT_DIR} MODULES xxhash libxxhash) + endif () + + # Add essential dependencies + add_subdirectory(contrib/cdb) + add_subdirectory(contrib/http-parser) + add_subdirectory(contrib/fpconv) + add_subdirectory(contrib/lc-btrie) + add_subdirectory(contrib/libottery) + add_subdirectory(contrib/simdutf) + include_directories("${CMAKE_SOURCE_DIR}/contrib/simdutf/include") + + # Configure zstd + if (SYSTEM_ZSTD MATCHES "OFF") + add_subdirectory(contrib/zstd) + else () + ProcessPackage(LIBZSTD LIBRARY zstd INCLUDE zstd.h + ROOT ${LIBZSTD_ROOT_DIR} MODULES zstd libzstd) + add_definitions(-DSYS_ZSTD) + endif () + + # Optional dependencies based on configuration + if (ENABLE_SNOWBALL) + add_subdirectory(contrib/snowball) + set(WITH_SNOWBALL 1 PARENT_SCOPE) + endif () + + # Core libraries + add_subdirectory(contrib/libucl) + add_subdirectory(contrib/librdns) + add_subdirectory(contrib/aho-corasick) + add_subdirectory(contrib/lua-lpeg) + add_subdirectory(contrib/t1ha) + add_subdirectory(contrib/libev) + add_subdirectory(contrib/kann) + add_subdirectory(contrib/google-ced) + + # Backward-cpp for stacktraces + if (ENABLE_BACKWARD) + add_subdirectory(contrib/backward-cpp) + message(STATUS "Backward-cpp config: ${BACKWARD_DEFINITIONS}") + else () + set(BACKWARD_ENABLE) + macro(add_backward target) + # do nothing + endmacro() + endif () + + if (BACKWARD_LIBRARIES) + message(STATUS "Backward-cpp libraries: ${BACKWARD_LIBRARIES}") + endif () + + # Doctest for testing + if (SYSTEM_DOCTEST MATCHES "OFF") + add_subdirectory(contrib/doctest) + include_directories("${CMAKE_SOURCE_DIR}/contrib/doctest") + else () + find_package(doctest) + endif () + + # Lua-specific dependencies + if (NOT WITH_LUAJIT) + add_subdirectory(contrib/lua-bit) + endif () + + # Lua REPL support + add_subdirectory(contrib/replxx) + list(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-replxx) + + # Update the required libraries list based on dependencies + if (ENABLE_SNOWBALL) + list(APPEND RSPAMD_REQUIRED_LIBRARIES stemmer) + endif () + + # Add core required libraries + list(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-hiredis) + list(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-actrie) + list(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-t1ha) + list(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-ev) + list(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-kann) + list(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-ced) + + # Clang plugin (optional) + if (ENABLE_CLANG_PLUGIN) + add_subdirectory(clang-plugin) + endif () + + # Main source code + add_subdirectory(src) + + # Utilities + add_subdirectory(utils) + + # Propagate variables to parent scope + set(RSPAMD_REQUIRED_LIBRARIES ${RSPAMD_REQUIRED_LIBRARIES} PARENT_SCOPE) +endfunction() diff --git a/cmake/CheckSymbols.cmake b/cmake/CheckSymbols.cmake new file mode 100644 index 000000000..10207dd5b --- /dev/null +++ b/cmake/CheckSymbols.cmake @@ -0,0 +1,146 @@ +# Function to check for atomic builtins, CPU features, and other specialized symbols +function(CheckSymbols) + # Check for atomic builtins + check_c_source_runs(" + #include <stdbool.h> + int main(int argc, char **argv) { + int a = 0, b = 0; + if (__atomic_compare_exchange_n(&a, &b, 1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)) { + return 0; + } + return -1; + } + " HAVE_ATOMIC_BUILTINS) + + if (NOT HAVE_ATOMIC_BUILTINS) + message(STATUS "atomic builtins are -NOT- supported") + else () + message(STATUS "atomic builtins are supported") + endif () + + # Check for libatomic + check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) + if (HAVE_LIBATOMIC) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + list(APPEND RSPAMD_REQUIRED_LIBRARIES "atomic") + set(RSPAMD_REQUIRED_LIBRARIES "${RSPAMD_REQUIRED_LIBRARIES}" PARENT_SCOPE) + endif () + + # Check for CPU feature intrinsics + check_c_source_runs(" + #include <stdio.h> + int main() { + __builtin_cpu_init(); + printf(\"%d\", __builtin_cpu_supports(\"avx\")); + return 0; + }" HAVE_BUILTIN_CPU_SUPPORTS) + + if (HAVE_BUILTIN_CPU_SUPPORTS) + message(STATUS "CPU feature detection via __builtin_cpu_supports is supported") + else () + message(STATUS "CPU feature detection via __builtin_cpu_supports is NOT supported") + endif () + + # Check for RDTSC + check_c_source_runs(" + #include <x86intrin.h> + int main(int argc, char **argv) { + __builtin_ia32_lfence(); + if (__builtin_ia32_rdtsc()) { + return 0; + } + return -1; + } + " HAVE_RDTSC) + + if (NOT HAVE_RDTSC) + message(STATUS "rdtsc intrinsic is -NOT- supported") + else () + message(STATUS "rdtsc intrinsic is supported") + endif () + + # Check for POSIX shared memory support + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + # For non-Linux systems, test shmem capability + check_c_source_runs(" + #include <sys/mman.h> + #include <fcntl.h> + #include <unistd.h> + #define TEST_NAME \"/test-shmem-work\" + int + main(int argc, char **argv) + { + int fd; + + fd = shm_open(TEST_NAME, O_RDWR | O_CREAT | O_EXCL, 00600); + if (fd == -1) { + return -1; + } + if (ftruncate(fd, 100) == -1) { + shm_unlink(TEST_NAME); + close(fd); + return -1; + } + + if (ftruncate(fd, 200) == -1) { + shm_unlink(TEST_NAME); + close(fd); + return -1; + } + if (ftruncate(fd, 300) == -1) { + shm_unlink(TEST_NAME); + close(fd); + return -1; + } + + close(fd); + shm_unlink(TEST_NAME); + return 0; + } + " HAVE_SANE_SHMEM) + + if (NOT HAVE_SANE_SHMEM) + message(STATUS "shmem support is NOT compatible with POSIX") + else () + message(STATUS "shmem support is compatible with POSIX") + endif () + endif () + + # Check for pthread shared mutexes and robust mutexes + file(WRITE ${CMAKE_BINARY_DIR}/pthread_setpshared.c " + #include <pthread.h> + #include <stdlib.h> + int main(void) + { + pthread_mutexattr_t mattr; + if (pthread_mutexattr_init(&mattr) != 0) return 0; + if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED) != 0) return 0; + if (pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST) != 0) return 0; + return 1; + } + ") + + try_run(_CAN_RUN _CAN_COMPILE + "${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}/pthread_setpshared.c" + CMAKE_FLAGS CMAKE_C_FLAGS="-pthread") + + if (_CAN_RUN EQUAL 1) + set(HAVE_PTHREAD_PROCESS_SHARED 1 CACHE INTERNAL "") + endif () + + if (HAVE_PTHREAD_PROCESS_SHARED) + message(STATUS "pthread_mutexattr_setpshared is supported") + else () + message(STATUS "pthread_mutexattr_setpshared is -NOT- supported") + endif () + + # Propagate variables to parent scope + set(HAVE_ATOMIC_BUILTINS ${HAVE_ATOMIC_BUILTINS} PARENT_SCOPE) + set(HAVE_LIBATOMIC ${HAVE_LIBATOMIC} PARENT_SCOPE) + set(HAVE_BUILTIN_CPU_SUPPORTS ${HAVE_BUILTIN_CPU_SUPPORTS} PARENT_SCOPE) + set(HAVE_RDTSC ${HAVE_RDTSC} PARENT_SCOPE) + set(HAVE_SANE_SHMEM ${HAVE_SANE_SHMEM} PARENT_SCOPE) + set(HAVE_PTHREAD_PROCESS_SHARED ${HAVE_PTHREAD_PROCESS_SHARED} PARENT_SCOPE) +endfunction() + +CheckSymbols()
\ No newline at end of file diff --git a/cmake/CheckSystemFeatures.cmake b/cmake/CheckSystemFeatures.cmake new file mode 100644 index 000000000..0a15749fd --- /dev/null +++ b/cmake/CheckSystemFeatures.cmake @@ -0,0 +1,207 @@ +# CheckSystemFeatures.cmake +# Checks for various system features, functions, and functionality + +# Check platform API and features +function(CheckSystemFeatures) + # Process-related functions + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + # setproctitle is broken badly in Linux, never try it + check_function_exists(setproctitle HAVE_SETPROCTITLE) + endif () + + # Memory and file management + check_function_exists(getpagesize HAVE_GETPAGESIZE) + check_function_exists(nanosleep HAVE_NANOSLEEP) + check_function_exists(flock HAVE_FLOCK) + check_library_exists(m tanh "" HAVE_TANH) + check_function_exists(mkstemp HAVE_MKSTEMP) + check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) + + # Check macros and constants + check_symbol_exists(PATH_MAX limits.h HAVE_PATH_MAX) + check_symbol_exists(MAXPATHLEN sys/param.h HAVE_MAXPATHLEN) + check_symbol_exists(MAP_ANON sys/mman.h HAVE_MMAP_ANON) + check_symbol_exists(IPV6_V6ONLY "sys/socket.h;netinet/in.h" HAVE_IPV6_V6ONLY) + check_symbol_exists(posix_fallocate fcntl.h HAVE_POSIX_FALLOCATE) + check_symbol_exists(fallocate fcntl.h HAVE_FALLOCATE) + check_symbol_exists(_SC_NPROCESSORS_ONLN unistd.h HAVE_SC_NPROCESSORS_ONLN) + check_symbol_exists(setbit sys/param.h PARAM_H_HAS_BITSET) + check_symbol_exists(getaddrinfo "sys/types.h;sys/socket.h;netdb.h" HAVE_GETADDRINFO) + check_symbol_exists(sched_yield "sched.h" HAVE_SCHED_YIELD) + check_symbol_exists(nftw "sys/types.h;ftw.h" HAVE_NFTW) + check_symbol_exists(memrchr "string.h" HAVE_MEMRCHR) + + # Check if PCRE has JIT support + if (ENABLE_PCRE2) + list(APPEND CMAKE_REQUIRED_INCLUDES "${PCRE_INCLUDE}") + check_symbol_exists(PCRE2_CONFIG_JIT "pcre2.h" HAVE_PCRE_JIT) + else () + list(APPEND CMAKE_REQUIRED_INCLUDES "${PCRE_INCLUDE}") + check_symbol_exists(PCRE_CONFIG_JIT "pcre.h" HAVE_PCRE_JIT) + endif () + + # Socket features + check_symbol_exists(SOCK_SEQPACKET "sys/types.h;sys/socket.h" HAVE_SOCK_SEQPACKET) + + # File handling features + check_symbol_exists(O_NOFOLLOW "sys/types.h;sys/fcntl.h" HAVE_ONOFOLLOW) + check_symbol_exists(O_CLOEXEC "sys/types.h;sys/fcntl.h" HAVE_OCLOEXEC) + + # OpenSSL specific stuff + list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSL_INCLUDE}") + if (LIBCRYPT_LIBRARY_PATH) + set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};-L${LIBCRYPT_LIBRARY_PATH};${LIBCRYPT_LIBRARY}") + set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};-L${LIBSSL_LIBRARY_PATH};${LIBSSL_LIBRARY}") + else () + set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};-lcrypt;-lssl") + endif () + + check_symbol_exists(SSL_set_tlsext_host_name "openssl/ssl.h" HAVE_SSL_TLSEXT_HOSTNAME) + check_symbol_exists(FIPS_mode "openssl/crypto.h" HAVE_FIPS_MODE) + + # Directory and file path operations + check_symbol_exists(dirfd "sys/types.h;unistd.h;dirent.h" HAVE_DIRFD) + check_symbol_exists(fpathconf "sys/types.h;unistd.h" HAVE_FPATHCONF) + + # Signal handling and memory operations + check_symbol_exists(sigaltstack "signal.h" HAVE_SIGALTSTACK) + check_symbol_exists(open_memstream "stdio.h" HAVE_OPENMEMSTREAM) + check_symbol_exists(fmemopen "stdio.h" HAVE_FMEMOPEN) + check_symbol_exists(clock_getcpuclockid "sys/types.h;time.h" HAVE_CLOCK_GETCPUCLOCKID) + check_symbol_exists(RUSAGE_SELF "sys/types.h;sys/resource.h" HAVE_RUSAGE_SELF) + check_symbol_exists(ffsll "strings.h" HAVE_FFSLL) + + # Check for PCRE JIT fast path + if (ENABLE_PCRE2) + if (HAVE_PCRE_JIT) + set(HAVE_PCRE_JIT_FAST 1) + message(STATUS "PCRE2 JIT is supported") + else () + message(STATUS "PCRE2 JIT is NOT supported") + endif () + else () + list(APPEND CMAKE_REQUIRED_INCLUDES "${PCRE_INCLUDE}") + if (PCRE_LIBRARY_PATH) + set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};-L${PCRE_LIBRARY_PATH};${PCRE_LIBRARY}") + else () + set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};-lpcre") + endif () + + # Check for PCRE JIT fast path + set(_PCRE_FAST_TEST " +#include \"pcre.h\" +int main (void) +{ + int rc; + int ovector[30]; + pcre *re; + pcre_extra *extra; + pcre_jit_stack *jit_stack; + + re = pcre_compile(\"abc\", 0, NULL, NULL, NULL); + extra = pcre_study(re, PCRE_STUDY_JIT_COMPILE, NULL); + jit_stack = pcre_jit_stack_alloc(32*1024, 512*1024); + pcre_assign_jit_stack(extra, NULL, jit_stack); + rc = pcre_jit_exec(re, extra, \"abc\", 3, 0, 0, ovector, 30, jit_stack); + + return rc; +} +") + check_c_source_compiles("${_PCRE_FAST_TEST}" HAVE_PCRE_JIT_FAST) + if (HAVE_PCRE_JIT_FAST) + message(STATUS "pcre_jit_exec is supported") + else () + message(STATUS "pcre_jit_exec is NOT supported") + endif () + endif () + + # Critical checks + if (NOT HAVE_GETADDRINFO) + message(FATAL_ERROR "Your system does not support getaddrinfo call, please consider upgrading it to run rspamd") + endif () + + # Check for signal information + if (HAVE_SIGINFO_H) + check_symbol_exists(SA_SIGINFO "signal.h;siginfo.h" HAVE_SA_SIGINFO) + else () + check_symbol_exists(SA_SIGINFO "signal.h" HAVE_SA_SIGINFO) + endif () + + # Clock and timer features + if (NOT CMAKE_SYSTEM_NAME STREQUAL "SunOS") + if (HAVE_CLOCK_GETTIME) + check_symbol_exists(CLOCK_PROCESS_CPUTIME_ID time.h HAVE_CLOCK_PROCESS_CPUTIME_ID) + check_symbol_exists(CLOCK_VIRTUAL time.h HAVE_CLOCK_VIRTUAL) + else () + check_include_files(sys/timeb.h HAVE_SYS_TIMEB_H) + endif () + endif () + + # Linux-specific features + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # In linux, we need to mount /run/shm to test which could be unavailable + # on a build system. On the other hand, we know that linux has stupid + # but compatible shmem support, so we assume this macro as true + set(HAVE_SANE_SHMEM 1) + + check_c_source_compiles("#define _GNU_SOURCE + #include <sys/socket.h> + int main (int argc, char **argv) { + return ((int*)(&recvmmsg))[argc]; + }" HAVE_RECVMMSG) + + check_c_source_compiles("#define _GNU_SOURCE + #include <fcntl.h> + int main (int argc, char **argv) { + return ((int*)(&readahead))[argc]; + }" HAVE_READAHEAD) + endif () + + # Propagate variables to parent scope + set(HAVE_PCRE_JIT_FAST ${HAVE_PCRE_JIT_FAST} PARENT_SCOPE) + set(HAVE_SANE_SHMEM ${HAVE_SANE_SHMEM} PARENT_SCOPE) + set(HAVE_GETPAGESIZE ${HAVE_GETPAGESIZE} PARENT_SCOPE) + set(HAVE_NANOSLEEP ${HAVE_NANOSLEEP} PARENT_SCOPE) + set(HAVE_FLOCK ${HAVE_FLOCK} PARENT_SCOPE) + set(HAVE_TANH ${HAVE_TANH} PARENT_SCOPE) + set(HAVE_MKSTEMP ${HAVE_MKSTEMP} PARENT_SCOPE) + set(HAVE_CLOCK_GETTIME ${HAVE_CLOCK_GETTIME} PARENT_SCOPE) + set(HAVE_PATH_MAX ${HAVE_PATH_MAX} PARENT_SCOPE) + set(HAVE_MAXPATHLEN ${HAVE_MAXPATHLEN} PARENT_SCOPE) + set(HAVE_MMAP_ANON ${HAVE_MMAP_ANON} PARENT_SCOPE) + set(HAVE_IPV6_V6ONLY ${HAVE_IPV6_V6ONLY} PARENT_SCOPE) + set(HAVE_POSIX_FALLOCATE ${HAVE_POSIX_FALLOCATE} PARENT_SCOPE) + set(HAVE_FALLOCATE ${HAVE_FALLOCATE} PARENT_SCOPE) + set(HAVE_SC_NPROCESSORS_ONLN ${HAVE_SC_NPROCESSORS_ONLN} PARENT_SCOPE) + set(PARAM_H_HAS_BITSET ${PARAM_H_HAS_BITSET} PARENT_SCOPE) + set(HAVE_GETADDRINFO ${HAVE_GETADDRINFO} PARENT_SCOPE) + set(HAVE_SCHED_YIELD ${HAVE_SCHED_YIELD} PARENT_SCOPE) + set(HAVE_NFTW ${HAVE_NFTW} PARENT_SCOPE) + set(HAVE_MEMRCHR ${HAVE_MEMRCHR} PARENT_SCOPE) + set(HAVE_PCRE_JIT ${HAVE_PCRE_JIT} PARENT_SCOPE) + set(HAVE_SOCK_SEQPACKET ${HAVE_SOCK_SEQPACKET} PARENT_SCOPE) + set(HAVE_ONOFOLLOW ${HAVE_ONOFOLLOW} PARENT_SCOPE) + set(HAVE_OCLOEXEC ${HAVE_OCLOEXEC} PARENT_SCOPE) + set(HAVE_SSL_TLSEXT_HOSTNAME ${HAVE_SSL_TLSEXT_HOSTNAME} PARENT_SCOPE) + set(HAVE_FIPS_MODE ${HAVE_FIPS_MODE} PARENT_SCOPE) + set(HAVE_DIRFD ${HAVE_DIRFD} PARENT_SCOPE) + set(HAVE_FPATHCONF ${HAVE_FPATHCONF} PARENT_SCOPE) + set(HAVE_SIGALTSTACK ${HAVE_SIGALTSTACK} PARENT_SCOPE) + set(HAVE_OPENMEMSTREAM ${HAVE_OPENMEMSTREAM} PARENT_SCOPE) + set(HAVE_FMEMOPEN ${HAVE_FMEMOPEN} PARENT_SCOPE) + set(HAVE_CLOCK_GETCPUCLOCKID ${HAVE_CLOCK_GETCPUCLOCKID} PARENT_SCOPE) + set(HAVE_RUSAGE_SELF ${HAVE_RUSAGE_SELF} PARENT_SCOPE) + set(HAVE_FFSLL ${HAVE_FFSLL} PARENT_SCOPE) + set(HAVE_SA_SIGINFO ${HAVE_SA_SIGINFO} PARENT_SCOPE) + set(HAVE_CLOCK_PROCESS_CPUTIME_ID ${HAVE_CLOCK_PROCESS_CPUTIME_ID} PARENT_SCOPE) + set(HAVE_CLOCK_VIRTUAL ${HAVE_CLOCK_VIRTUAL} PARENT_SCOPE) + + # Linux-specific features propagation + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(HAVE_RECVMMSG ${HAVE_RECVMMSG} PARENT_SCOPE) + set(HAVE_READAHEAD ${HAVE_READAHEAD} PARENT_SCOPE) + endif () +endfunction() + +# Execute the function +CheckSystemFeatures() diff --git a/cmake/CheckSystemHeaders.cmake b/cmake/CheckSystemHeaders.cmake new file mode 100644 index 000000000..232814eba --- /dev/null +++ b/cmake/CheckSystemHeaders.cmake @@ -0,0 +1,139 @@ +# CheckSystemHeaders.cmake +# Checks for the existence of system headers + +# Check platform specific includes +function(CheckSystemHeaders) + # Basic system headers + check_include_files(sys/types.h HAVE_SYS_TYPES_H) + check_include_files(sys/uio.h HAVE_SYS_UIO_H) + + # Standard C headers + check_include_files(fcntl.h HAVE_FCNTL_H) + check_include_files(math.h HAVE_MATH_H) + check_include_files(stdio.h HAVE_STDIO_H) + check_include_files(stdlib.h HAVE_STDLIB_H) + check_include_files(string.h HAVE_STRING_H) + check_include_files(strings.h HAVE_STRINGS_H) + check_include_files(time.h HAVE_TIME_H) + check_include_files(unistd.h HAVE_UNISTD_H) + + # Data type headers + check_include_files(stdint.h HAVE_STDINT_H) + check_include_files(inttypes.h HAVE_INTTYPES_H) + check_include_files(stdbool.h HAVE_STDBOOL_H) + + # Endian-related headers + check_include_files(endian.h HAVE_ENDIAN_H) + check_include_files(sys/endian.h HAVE_SYS_ENDIAN_H) + check_include_files(machine/endian.h HAVE_MACHINE_ENDIAN_H) + + # System utility headers + check_include_files(sys/socket.h HAVE_SYS_SOCKET_H) + check_include_files(sys/mman.h HAVE_SYS_MMAN_H) + check_include_files(sys/un.h HAVE_SYS_UN_H) + check_include_files(sys/stat.h HAVE_SYS_STAT_H) + check_include_files(sys/wait.h HAVE_SYS_WAIT_H) + check_include_files(sys/param.h HAVE_SYS_PARAM_H) + check_include_files(sys/file.h HAVE_SYS_FILE_H) + check_include_files(sys/resource.h HAVE_SYS_RESOURCE_H) + + # Network-related headers + check_include_files(netinet/in.h HAVE_NETINET_IN_H) + check_include_files(netinet/tcp.h HAVE_NETINET_TCP_H) + check_include_files(arpa/inet.h HAVE_ARPA_INET_H) + check_include_files(netdb.h HAVE_NETDB_H) + + # System logging and signal handling + check_include_files(syslog.h HAVE_SYSLOG_H) + check_include_files(siginfo.h HAVE_SIGINFO_H) + + # Internationalization and user/groups + check_include_files(locale.h HAVE_LOCALE_H) + check_include_files(libgen.h HAVE_LIBGEN_H) + check_include_files(pwd.h HAVE_PWD_H) + check_include_files(grp.h HAVE_GRP_H) + + # File and path handling + check_include_files(glob.h HAVE_GLOB_H) + check_include_files(poll.h HAVE_POLL_H) + check_include_files(readpassphrase.h HAVE_READPASSPHRASE_H) + check_include_files(termios.h HAVE_TERMIOS_H) + check_include_files(paths.h HAVE_PATHS_H) + + # Other utilities + check_include_files(ctype.h HAVE_CTYPE_H) + check_include_files(cpuid.h HAVE_CPUID_H) + check_include_files(dirent.h HAVE_DIRENT_H) + + # Context-related headers + check_include_files(ucontext.h HAVE_UCONTEXT_H) + check_include_files(sys/ucontext.h HAVE_SYS_UCONTEXT_H) # OSX specific + + # Time and memory + check_include_files(sys/timeb.h HAVE_SYS_TIMEB_H) + + # Log the results for important headers + if (NOT HAVE_SYS_TYPES_H) + message(WARNING "sys/types.h not found - this may cause problems") + endif () + + if (NOT HAVE_SYS_SOCKET_H) + message(WARNING "sys/socket.h not found - networking functionality may be limited") + endif () + + # Return results to parent scope + foreach (var + HAVE_SYS_TYPES_H + HAVE_SYS_UIO_H + HAVE_FCNTL_H + HAVE_MATH_H + HAVE_STDIO_H + HAVE_STDLIB_H + HAVE_STRING_H + HAVE_STRINGS_H + HAVE_TIME_H + HAVE_UNISTD_H + HAVE_STDINT_H + HAVE_INTTYPES_H + HAVE_STDBOOL_H + HAVE_ENDIAN_H + HAVE_SYS_ENDIAN_H + HAVE_MACHINE_ENDIAN_H + HAVE_SYS_SOCKET_H + HAVE_SYS_MMAN_H + HAVE_SYS_UN_H + HAVE_SYS_STAT_H + HAVE_SYS_WAIT_H + HAVE_SYS_PARAM_H + HAVE_SYS_FILE_H + HAVE_SYS_RESOURCE_H + HAVE_NETINET_IN_H + HAVE_NETINET_TCP_H + HAVE_ARPA_INET_H + HAVE_NETDB_H + HAVE_SYSLOG_H + HAVE_SIGINFO_H + HAVE_LOCALE_H + HAVE_LIBGEN_H + HAVE_PWD_H + HAVE_GRP_H + HAVE_GLOB_H + HAVE_POLL_H + HAVE_READPASSPHRASE_H + HAVE_TERMIOS_H + HAVE_PATHS_H + HAVE_CTYPE_H + HAVE_UNISTD_H + HAVE_CPUID_H + HAVE_DIRENT_H + HAVE_UCONTEXT_H + HAVE_SYS_UCONTEXT_H + HAVE_SYS_TIMEB_H) + if (${var}) + set(${var} ${${var}} PARENT_SCOPE) + endif () + endforeach () +endfunction() + +# Execute the function +CheckSystemHeaders() diff --git a/cmake/CheckURLInclude.cmake b/cmake/CheckURLInclude.cmake new file mode 100644 index 000000000..12cecacd9 --- /dev/null +++ b/cmake/CheckURLInclude.cmake @@ -0,0 +1,51 @@ +include(CheckIncludeFiles) +include(CheckLibraryExists) + +# Function to check for URL include support (libcurl or libfetch) +function(CheckURLIncludeSupport) + # First try to find libfetch + find_library(LIBFETCH_LIBRARY HINTS "${RSPAMD_SEARCH_PATH}" + NAMES fetch PATHS PATH_SUFFIXES lib64 lib + PATHS ${RSPAMD_DEFAULT_LIBRARY_PATHS} + DOC "Path where the libfetch library can be found") + + if (LIBFETCH_LIBRARY) + # Found libfetch library, now check for header + find_file(HAVE_FETCH_H HINTS "${RSPAMD_SEARCH_PATH}" + NAMES fetch.h + PATH_SUFFIXES include + PATHS ${RSPAMD_DEFAULT_INCLUDE_PATHS} + DOC "Path to libfetch header") + + if (HAVE_FETCH_H) + message(STATUS "Found libfetch: ${LIBFETCH_LIBRARY}") + list(APPEND RSPAMD_REQUIRED_LIBRARIES "fetch") + set(WITH_FETCH 1) + set(WITH_FETCH ${WITH_FETCH} PARENT_SCOPE) + else () + message(STATUS "Found libfetch library but missing fetch.h header") + endif () + else () + # Try to find libcurl as an alternative + ProcessPackage(CURL LIBRARY curl INCLUDE curl.h INCLUDE_SUFFIXES include/curl + ROOT ${CURL_ROOT}) + + if (WITH_CURL) + message(STATUS "Found libcurl for URL includes") + set(WITH_CURL ${WITH_CURL} PARENT_SCOPE) + else () + message(WARNING "Neither libcurl nor libfetch were found, no support of URL includes in configuration") + endif () + endif () + + # Propagate variables to parent scope + if (HAVE_FETCH_H) + set(HAVE_FETCH_H ${HAVE_FETCH_H} PARENT_SCOPE) + set(LIBFETCH_LIBRARY ${LIBFETCH_LIBRARY} PARENT_SCOPE) + endif () + + # Update the global RSPAMD_REQUIRED_LIBRARIES list + if (HAVE_FETCH_H) + set(RSPAMD_REQUIRED_LIBRARIES ${RSPAMD_REQUIRED_LIBRARIES} PARENT_SCOPE) + endif () +endfunction() diff --git a/cmake/InstallRspamdFiles.cmake b/cmake/InstallRspamdFiles.cmake new file mode 100644 index 000000000..b6b631cdc --- /dev/null +++ b/cmake/InstallRspamdFiles.cmake @@ -0,0 +1,104 @@ +# InstallRspamdFiles.cmake +# Manages the installation of Rspamd files, configurations, and components + +function(InstallRspamdFiles) + # Create necessary directories + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${CONFDIR})") + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${SHAREDIR})") + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${LUALIBDIR})") + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${PLUGINSDIR})") + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${RULESDIR})") + + # Install configuration files + set(GLOB_PATTERNS "${CMAKE_SOURCE_DIR}/conf/*.conf;${CMAKE_SOURCE_DIR}/conf/*.inc") + if (INSTALL_EXAMPLES) + list(APPEND GLOB_PATTERNS "${CMAKE_SOURCE_DIR}/conf/*.lua.example") + list(APPEND GLOB_PATTERNS "${CMAKE_SOURCE_DIR}/conf/*.conf.example") + endif () + + file(GLOB_RECURSE CONF_FILES RELATIVE "${CMAKE_SOURCE_DIR}/conf" CONFIGURE_DEPENDS + ${GLOB_PATTERNS}) + foreach (CONF_FILE ${CONF_FILES}) + get_filename_component(_rp ${CONF_FILE} PATH) + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${CONFDIR}/${_rp})") + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/conf/${CONF_FILE}" + DESTINATION ${CONFDIR}/${_rp}) + endforeach () + + # Install Lua plugins + file(GLOB LUA_PLUGINS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/plugins/lua" CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/src/plugins/lua/*.lua") + foreach (LUA_PLUGIN ${LUA_PLUGINS}) + get_filename_component(_rp ${LUA_PLUGIN} PATH) + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${PLUGINSDIR}/${_rp})") + install(FILES "src/plugins/lua/${LUA_PLUGIN}" DESTINATION ${PLUGINSDIR}/${_rp}) + endforeach () + + # Install TLD list + install(FILES "contrib/publicsuffix/effective_tld_names.dat" DESTINATION + "${SHAREDIR}") + + # Install language data + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${SHAREDIR}/languages)") + file(GLOB LANGUAGES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/languages-data/*.json") + foreach (_LANG ${LANGUAGES}) + install(FILES "${_LANG}" DESTINATION ${SHAREDIR}/languages) + endforeach () + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/languages-data/stop_words" + DESTINATION ${SHAREDIR}/languages) + + # Install Lua rules + file(GLOB_RECURSE LUA_CONFIGS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/rules" CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/rules/*.lua") + foreach (LUA_CONF ${LUA_CONFIGS}) + get_filename_component(_rp ${LUA_CONF} PATH) + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${RULESDIR}/${_rp})") + install(FILES "rules/${LUA_CONF}" DESTINATION ${RULESDIR}/${_rp}) + endforeach () + + # Install Lua libraries + file(GLOB_RECURSE LUA_LIBS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/lualib" CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/lualib/*.lua") + foreach (LUA_LIB ${LUA_LIBS}) + get_filename_component(_rp ${LUA_LIB} PATH) + install(CODE "FILE(MAKE_DIRECTORY \$ENV{DESTDIR}${LUALIBDIR}/${_rp})") + install(FILES "lualib/${LUA_LIB}" DESTINATION ${LUALIBDIR}/${_rp}) + endforeach () + + # Install third-party Lua libraries + install(FILES "contrib/lua-fun/fun.lua" DESTINATION ${LUALIBDIR}) + install(FILES "contrib/lua-argparse/argparse.lua" DESTINATION ${LUALIBDIR}) + install(FILES "contrib/lua-tableshape/tableshape.lua" DESTINATION ${LUALIBDIR}) + install(FILES "contrib/lua-lupa/lupa.lua" DESTINATION ${LUALIBDIR}) + install(FILES "contrib/lua-lpeg/lpegre.lua" DESTINATION ${LUALIBDIR}) + + # Install systemd unit if on Linux and requested + if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND WANT_SYSTEMD_UNITS) + install(FILES "rspamd.service" DESTINATION ${SYSTEMDDIR}) + endif () + + # Install man pages + install(FILES "doc/rspamd.8" DESTINATION ${MANDIR}/man8) + install(FILES "doc/rspamc.1" DESTINATION ${MANDIR}/man1) + install(FILES "doc/rspamadm.1" DESTINATION ${MANDIR}/man1) + + # Install utilities + install(PROGRAMS "utils/rspamd_stats.pl" RENAME rspamd_stats DESTINATION bin) + + # Install web UI if requested + if (INSTALL_WEBUI) + install(DIRECTORY "interface/" DESTINATION ${WWWDIR} PATTERN ".git" EXCLUDE) + endif () + + # Log installation paths + message(STATUS "Rspamd will be installed in the following directories:") + message(STATUS " - Binaries: ${CMAKE_INSTALL_PREFIX}/bin") + message(STATUS " - Configuration: ${CONFDIR}") + message(STATUS " - Rules: ${RULESDIR}") + message(STATUS " - Lua libraries: ${LUALIBDIR}") + message(STATUS " - Plugins: ${PLUGINSDIR}") + message(STATUS " - Shared data: ${SHAREDIR}") + if (INSTALL_WEBUI) + message(STATUS " - Web UI: ${WWWDIR}") + endif () +endfunction() diff --git a/cmake/OSDep.cmake b/cmake/OSDep.cmake index f2bd56cec..2f23ada4b 100644 --- a/cmake/OSDep.cmake +++ b/cmake/OSDep.cmake @@ -1,67 +1,108 @@ -# Platform specific configuration -IF(CMAKE_SYSTEM_NAME MATCHES "^.*BSD$|DragonFly") - ADD_COMPILE_OPTIONS(-DFREEBSD -D_BSD_SOURCE) - SET(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_BSD_SOURCE") - CONFIGURE_FILE(freebsd/rspamd.sh.in freebsd/rspamd @ONLY) - MESSAGE(STATUS "Configuring for BSD system") - # Find util library - ProcessPackage(LIBUTIL LIBRARY util INCLUDE libutil.h - ROOT ${LIBUTIL_ROOT_DIR} OPTIONAL) - IF(WITH_LIBUTIL) - SET(HAVE_LIBUTIL_H 1) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES util) - CHECK_FUNCTION_EXISTS(pidfile_open HAVE_PIDFILE) - CHECK_FUNCTION_EXISTS(pidfile_fileno HAVE_PIDFILE_FILENO) - ENDIF() - IF(CMAKE_SYSTEM_NAME MATCHES "^NetBSD$") - LIST(APPEND CMAKE_REQUIRED_LIBRARIES rt) - ENDIF() - SET(TAR "gtar") -ENDIF() - -IF(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - ADD_COMPILE_OPTIONS(-D_BSD_SOURCE -DDARWIN) - SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS} -undefined dynamic_lookup") - IF(ENABLE_LUAJIT MATCHES "ON") - IF ("${ARCH}" STREQUAL "x86_64") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 10000 -image_base 100000000") - ENDIF() - ENDIF(ENABLE_LUAJIT MATCHES "ON") - MESSAGE(STATUS "Configuring for Darwin") - SET(TAR "gnutar") - SET(CMAKE_FIND_FRAMEWORK "NEVER") -ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - -IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") - ADD_COMPILE_OPTIONS(-D_GNU_SOURCE -DLINUX) - SET(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE") - # Workaround with architecture specific includes - #IF(IS_DIRECTORY "/usr/include/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu/") - # INCLUDE_DIRECTORIES("/usr/include/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu/") - # LIST(APPEND CMAKE_REQUIRED_INCLUDES "/usr/include/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu/") - #ENDIF(IS_DIRECTORY "/usr/include/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu/") - - LIST(APPEND CMAKE_REQUIRED_LIBRARIES rt) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES dl) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES resolv) - MESSAGE(STATUS "Configuring for Linux") - IF(EXISTS "/etc/debian_version") - SET(LINUX_START_SCRIPT "rspamd_debian.in") - ELSE(EXISTS "/etc/debian_version") - SET(LINUX_START_SCRIPT "rspamd_rh.in") - ENDIF(EXISTS "/etc/debian_version") -ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") - -IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") - ADD_COMPILE_OPTIONS(-D__EXTENSIONS__ -DSOLARIS -D_POSIX_SOURCE -D_POSIX_C_SOURCE=200112) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES rt) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES dl) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES resolv) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES nsl) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES socket) - LIST(APPEND CMAKE_REQUIRED_LIBRARIES umem) - # Ugly hack, but FindOpenSSL on Solaris does not link with libcrypto - SET(CMAKE_VERBOSE_MAKEFILE ON) - SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) - SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:${RSPAMD_LIBDIR}") -ENDIF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
\ No newline at end of file +# OSDep.cmake - Platform-specific configuration as a function + +function(ConfigurePlatformSpecifics) + # Configure for BSD systems + if (CMAKE_SYSTEM_NAME MATCHES "^.*BSD$|DragonFly") + # Add BSD-specific compiler flags + add_compile_definitions(FREEBSD _BSD_SOURCE) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_BSD_SOURCE" PARENT_SCOPE) + + # Configure FreeBSD startup script + configure_file(freebsd/rspamd.sh.in freebsd/rspamd @ONLY) + message(STATUS "Configuring for BSD system") + + # Find util library + ProcessPackage(LIBUTIL LIBRARY util INCLUDE libutil.h + ROOT ${LIBUTIL_ROOT_DIR} OPTIONAL) + + if (WITH_LIBUTIL) + set(HAVE_LIBUTIL_H 1) + list(APPEND CMAKE_REQUIRED_LIBRARIES util) + list(APPEND RSPAMD_REQUIRED_LIBRARIES util) + + # Check for pidfile functions + check_function_exists(pidfile_open HAVE_PIDFILE) + check_function_exists(pidfile_fileno HAVE_PIDFILE_FILENO) + + # Propagate variables to parent scope + set(HAVE_PIDFILE ${HAVE_PIDFILE} PARENT_SCOPE) + set(HAVE_PIDFILE_FILENO ${HAVE_PIDFILE_FILENO} PARENT_SCOPE) + set(HAVE_LIBUTIL_H ${HAVE_LIBUTIL_H} PARENT_SCOPE) + endif () + + # NetBSD-specific libraries + if (CMAKE_SYSTEM_NAME MATCHES "^NetBSD$") + list(APPEND CMAKE_REQUIRED_LIBRARIES rt) + list(APPEND RSPAMD_REQUIRED_LIBRARIES rt) + endif () + + set(TAR "gtar" PARENT_SCOPE) + endif () + + # Configure for macOS (Darwin) + if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + # Add macOS-specific compiler flags + add_compile_definitions(_BSD_SOURCE DARWIN) + + # Configure dynamic linking behavior + set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS} -undefined dynamic_lookup" PARENT_SCOPE) + + # Special handling for LUAJIT on x86_64 macOS + if (ENABLE_LUAJIT AND "${ARCH}" STREQUAL "x86_64") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 10000 -image_base 100000000" PARENT_SCOPE) + endif () + + message(STATUS "Configuring for Darwin") + set(TAR "gnutar" PARENT_SCOPE) + set(CMAKE_FIND_FRAMEWORK "NEVER" PARENT_SCOPE) + endif () + + # Configure for Linux systems + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Add Linux-specific compiler flags + add_compile_definitions(_GNU_SOURCE LINUX) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE" PARENT_SCOPE) + + # Required Linux libraries + set(LINUX_REQUIRED_LIBS dl rt resolv) + foreach (lib ${LINUX_REQUIRED_LIBS}) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${lib}) + list(APPEND RSPAMD_REQUIRED_LIBRARIES ${lib}) + endforeach () + + message(STATUS "Configuring for Linux") + + # Determine init script based on distribution + if (EXISTS "/etc/debian_version") + set(LINUX_START_SCRIPT "rspamd_debian.in" PARENT_SCOPE) + else () + set(LINUX_START_SCRIPT "rspamd_rh.in" PARENT_SCOPE) + endif () + endif () + + # Configure for Solaris systems + if (CMAKE_SYSTEM_NAME STREQUAL "SunOS") + # Add Solaris-specific compiler flags + add_compile_definitions(__EXTENSIONS__ SOLARIS _POSIX_SOURCE _POSIX_C_SOURCE=200112) + + # Required Solaris libraries + set(SOLARIS_REQUIRED_LIBS rt dl resolv nsl socket umem) + foreach (lib ${SOLARIS_REQUIRED_LIBS}) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${lib}) + list(APPEND RSPAMD_REQUIRED_LIBRARIES ${lib}) + endforeach () + + # Configure Solaris-specific build settings + set(CMAKE_VERBOSE_MAKEFILE ON PARENT_SCOPE) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE PARENT_SCOPE) + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:${RSPAMD_LIBDIR}" PARENT_SCOPE) + endif () + + # Always propagate required libraries to parent scope + set(RSPAMD_REQUIRED_LIBRARIES ${RSPAMD_REQUIRED_LIBRARIES} PARENT_SCOPE) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} PARENT_SCOPE) + + # Log platform-specific configuration + message(STATUS "Platform: ${CMAKE_SYSTEM_NAME}") + message(STATUS "Platform-specific required libraries: ${RSPAMD_REQUIRED_LIBRARIES}") +endfunction() diff --git a/cmake/Sanitizer.cmake b/cmake/Sanitizer.cmake index c2587066f..79ee3f686 100644 --- a/cmake/Sanitizer.cmake +++ b/cmake/Sanitizer.cmake @@ -1,75 +1,100 @@ +# Sanitizer configuration # Ported from Clickhouse: https://github.com/ClickHouse/ClickHouse/blob/master/cmake/sanitize.cmake -set (SAN_FLAGS "${SAN_FLAGS} -g -fno-omit-frame-pointer -DSANITIZER") -# O1 is normally set by clang, and -Og by gcc -if (COMPILER_GCC) - if (ENABLE_FULL_DEBUG MATCHES "ON") - set (SAN_FLAGS "${SAN_FLAGS} -O0") - else() - set (SAN_FLAGS "${SAN_FLAGS} -Og") - endif() -else () - if (ENABLE_FULL_DEBUG MATCHES "ON") - set (SAN_FLAGS "${SAN_FLAGS} -O0") - else() - set (SAN_FLAGS "${SAN_FLAGS} -O1") - endif() -endif () -if (SANITIZE) - if (ENABLE_JEMALLOC MATCHES "ON") - message (STATUS "Jemalloc support is useless in case of build with sanitizers") - set (ENABLE_JEMALLOC "OFF") +# Define a function to configure sanitizers +function(configure_sanitizers) + # Skip configuration if no sanitizer is specified + if (NOT SANITIZE) + return() endif () - string(REPLACE "," ";" SANITIZE_LIST ${SANITIZE}) - foreach(SANITIZE ${SANITIZE_LIST}) - if (SANITIZE STREQUAL "address") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") - if (COMPILER_GCC) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libasan") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libasan") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan") - endif () + # Base sanitizer flags + add_compile_options(-g -fno-omit-frame-pointer) + add_compile_definitions(SANITIZER) + + # Set optimization level based on compiler and debug settings + if (CMAKE_C_COMPILER_ID MATCHES "GNU") + if (ENABLE_FULL_DEBUG) + add_compile_options(-O0) + else () + add_compile_options(-Og) + endif () + else () + if (ENABLE_FULL_DEBUG) + add_compile_options(-O0) + else () + add_compile_options(-O1) + endif () + endif () + + # Jemalloc conflicts with sanitizers + if (ENABLE_JEMALLOC) + message(STATUS "Disabling jemalloc as it's incompatible with sanitizers") + set(ENABLE_JEMALLOC OFF PARENT_SCOPE) + endif () - elseif (SANITIZE STREQUAL "leak") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=leak") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=leak") + # Process the specified sanitizers + string(REPLACE "," ";" SANITIZE_LIST "${SANITIZE}") - elseif (SANITIZE STREQUAL "memory") - set (MSAN_FLAGS "-fsanitize=memory -fsanitize-memory-track-origins -fno-optimize-sibling-calls") + foreach (SANITIZER_TYPE IN LISTS SANITIZE_LIST) + if (SANITIZER_TYPE STREQUAL "address") + # Address Sanitizer (ASan) + add_compile_options(-fsanitize=address -fsanitize-address-use-after-scope) + add_link_options(-fsanitize=address -fsanitize-address-use-after-scope) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MSAN_FLAGS}") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MSAN_FLAGS}") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory") + if (CMAKE_C_COMPILER_ID MATCHES "GNU") + add_compile_options(-static-libasan) + add_link_options(-static-libasan) + endif () + + elseif (SANITIZER_TYPE STREQUAL "leak") + # Leak Sanitizer (LSan) + add_compile_options(-fsanitize=leak) + add_link_options(-fsanitize=leak) + + elseif (SANITIZER_TYPE STREQUAL "memory") + # Memory Sanitizer (MSan) + add_compile_options( + -fsanitize=memory + -fsanitize-memory-track-origins + -fno-optimize-sibling-calls + ) + add_link_options(-fsanitize=memory) - if (COMPILER_GCC) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libmsan") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libmsan") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libmsan") + if (CMAKE_C_COMPILER_ID MATCHES "GNU") + add_compile_options(-static-libmsan) + add_link_options(-static-libmsan) endif () - elseif (SANITIZE STREQUAL "undefined") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined") + elseif (SANITIZER_TYPE STREQUAL "undefined") + # Undefined Behavior Sanitizer (UBSan) + add_compile_options(-fsanitize=undefined -fno-sanitize-recover=all) + add_link_options(-fsanitize=undefined) - if (COMPILER_GCC) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libubsan") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libubsan") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libubsan") + if (CMAKE_C_COMPILER_ID MATCHES "GNU") + add_compile_options(-static-libubsan) + add_link_options(-static-libubsan) endif () + else () - message (FATAL_ERROR "Unknown sanitizer type: ${SANITIZE}") + message(FATAL_ERROR "Unknown sanitizer type: ${SANITIZER_TYPE}") endif () + + message(STATUS "Configured sanitizer: ${SANITIZER_TYPE}") endforeach () - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS}") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS}") - message (STATUS "Add sanitizer: ${SANITIZE}") - # Disable sanitizing on make stage e.g. for snowball compiler - set (ENV{ASAN_OPTIONS} "detect_leaks=0") - message (STATUS "Sanitizer CFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}") - message (STATUS "Sanitizer CXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}") -endif()
\ No newline at end of file + + # Set environment variable to disable leak detection during the build phase + set(ENV{ASAN_OPTIONS} "detect_leaks=0") + + # Log the final configuration + get_directory_property(COMPILE_OPTIONS COMPILE_OPTIONS) + get_directory_property(LINK_OPTIONS LINK_OPTIONS) + message(STATUS "Sanitizer compile options: ${COMPILE_OPTIONS}") + message(STATUS "Sanitizer link options: ${LINK_OPTIONS}") + + # Propagate the modified variable to parent scope + set(ENABLE_JEMALLOC ${ENABLE_JEMALLOC} PARENT_SCOPE) +endfunction() + +# Execute the configuration +configure_sanitizers() diff --git a/cmake/SetupPVSStudio.cmake b/cmake/SetupPVSStudio.cmake new file mode 100644 index 000000000..92fa560f0 --- /dev/null +++ b/cmake/SetupPVSStudio.cmake @@ -0,0 +1,56 @@ +# SetupPVSStudio.cmake +# Configures PVS-Studio static code analysis if available + +function(SetupPVSStudio) + # Try to find PVS-Studio analyzer + find_program(_PVS_STUDIO "pvs-studio-analyzer") + + if (_PVS_STUDIO) + message(STATUS "Found PVS-Studio analyzer: ${_PVS_STUDIO}") + + # Include the PVS-Studio module + include(PVS-Studio) + + # Get a list of source directories to analyze + set(_ANALYZE_TARGETS + ${PROJECT_NAME} # Main project + rspamd-server # Server component + rspamadm # Admin utility + rspamc # Client utility + ) + + # Setup analysis target + pvs_studio_add_target( + TARGET ${PROJECT_NAME}.analyze # Target name for running analysis + ANALYZE ${_ANALYZE_TARGETS} # What to analyze + OUTPUT FORMAT errorfile # Output format + LOG target_${PROJECT_NAME}.err # Log file path + ARGS + # Additional pvs-studio-analyzer arguments + --exclude-path "${CMAKE_SOURCE_DIR}/contrib" # Exclude third-party code + ) + + # Add a help message for the target + add_custom_command( + TARGET ${PROJECT_NAME}.analyze + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "PVS-Studio analysis complete. Results in target_${PROJECT_NAME}.err" + ) + + # Create a report target that converts the error file to a more readable format + add_custom_target(${PROJECT_NAME}.analyze-report + COMMAND ${CMAKE_COMMAND} -E echo "Generating HTML report from PVS-Studio results..." + COMMAND plog-converter -a GA:1,2,3 -t fullhtml -o pvs-report target_${PROJECT_NAME}.err + COMMAND ${CMAKE_COMMAND} -E echo "Report generated in pvs-report/ directory" + DEPENDS ${PROJECT_NAME}.analyze + COMMENT "Converting PVS-Studio output to HTML report" + VERBATIM + ) + + message(STATUS "PVS-Studio targets added:") + message(STATUS " - ${PROJECT_NAME}.analyze: Run the analysis") + message(STATUS " - ${PROJECT_NAME}.analyze-report: Generate HTML report from analysis results") + else () + message(STATUS "PVS-Studio analyzer not found. Static analysis disabled.") + endif () +endfunction() |