Browse Source

[Project] Modernize cmake

pull/5412/head
Vsevolod Stakhov 7 months ago
parent
commit
39caa76911
No known key found for this signature in database GPG Key ID: 7647B6790081437
  1. 803
      CMakeLists.txt
  2. 114
      cmake/AddDependencySubdirectories.cmake
  3. 146
      cmake/CheckSymbols.cmake
  4. 207
      cmake/CheckSystemFeatures.cmake
  5. 139
      cmake/CheckSystemHeaders.cmake
  6. 51
      cmake/CheckURLInclude.cmake
  7. 104
      cmake/InstallRspamdFiles.cmake
  8. 56
      cmake/SetupPVSStudio.cmake
  9. 18
      contrib/xxhash/CMakeLists.txt
  10. 532
      src/CMakeLists.txt
  11. 4
      src/rspamadm/lua_repl.c

803
CMakeLists.txt

@ -5,107 +5,116 @@
#
############################# INITIAL SECTION #############################################
CMAKE_MINIMUM_REQUIRED(VERSION 3.15 FATAL_ERROR)
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
SET(RSPAMD_VERSION_MAJOR 3)
SET(RSPAMD_VERSION_MINOR 11)
SET(RSPAMD_VERSION_PATCH 2)
# Define version variables
set(RSPAMD_VERSION_MAJOR 3)
set(RSPAMD_VERSION_MINOR 11)
set(RSPAMD_VERSION_PATCH 2)
# Keep two digits all the time
SET(RSPAMD_VERSION_MAJOR_NUM ${RSPAMD_VERSION_MAJOR}0)
SET(RSPAMD_VERSION_MINOR_NUM ${RSPAMD_VERSION_MINOR}0)
SET(RSPAMD_VERSION_PATCH_NUM ${RSPAMD_VERSION_PATCH}0)
set(RSPAMD_VERSION_MAJOR_NUM ${RSPAMD_VERSION_MAJOR}0)
set(RSPAMD_VERSION_MINOR_NUM ${RSPAMD_VERSION_MINOR}0)
set(RSPAMD_VERSION_PATCH_NUM ${RSPAMD_VERSION_PATCH}0)
IF (GIT_ID)
SET(GIT_VERSION 1)
SET(RSPAMD_ID "${GIT_ID}")
ENDIF ()
if (GIT_ID)
set(GIT_VERSION 1)
set(RSPAMD_ID "${GIT_ID}")
endif ()
set(RSPAMD_VERSION "${RSPAMD_VERSION_MAJOR}.${RSPAMD_VERSION_MINOR}.${RSPAMD_VERSION_PATCH}")
SET(RSPAMD_VERSION "${RSPAMD_VERSION_MAJOR}.${RSPAMD_VERSION_MINOR}.${RSPAMD_VERSION_PATCH}")
project(rspamd
VERSION "${RSPAMD_VERSION}"
LANGUAGES C CXX ASM
DESCRIPTION "Rapid spam filtering system"
HOMEPAGE_URL "https://rspamd.com"
)
PROJECT(rspamd VERSION "${RSPAMD_VERSION}" LANGUAGES C CXX ASM)
cmake_policy(SET CMP0075 NEW)
CMAKE_POLICY(SET CMP0075 NEW)
# Language standards
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# This is supported merely with cmake 3.1
SET(CMAKE_C_STANDARD 11)
SET(CMAKE_CXX_STANDARD 20)
SET(CMAKE_C_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/")
SET(RSPAMD_MASTER_SITE_URL "https://rspamd.com")
set(RSPAMD_MASTER_SITE_URL "https://rspamd.com")
IF (NOT RSPAMD_USER)
SET(RSPAMD_USER "nobody")
SET(RSPAMD_GROUP "nobody")
ENDIF (NOT RSPAMD_USER)
if (NOT RSPAMD_USER)
set(RSPAMD_USER "nobody")
set(RSPAMD_GROUP "nobody")
endif ()
# Default for SysV Init
SET(RSPAMD_WORKER_NORMAL "*:11333")
SET(RSPAMD_WORKER_CONTROLLER "*:11334")
set(RSPAMD_WORKER_NORMAL "*:11333")
set(RSPAMD_WORKER_CONTROLLER "*:11334")
############################# OPTIONS SECTION #############################################
OPTION(ENABLE_LUAJIT "Link with libluajit [default: ON]" ON)
OPTION(ENABLE_URL_INCLUDE "Enable urls in ucl includes (requires libcurl or libfetch) [default: OFF]" OFF)
OPTION(NO_SHARED "Build internal libs static [default: ON]" ON)
OPTION(INSTALL_WEBUI "Install web interface [default: ON]" ON)
OPTION(INSTALL_EXAMPLES "Install examples of the configuration and Lua [default: ON]" ON)
OPTION(WANT_SYSTEMD_UNITS "Install systemd unit files on Linux [default: OFF]" OFF)
OPTION(ENABLE_SNOWBALL "Enable snowball stemmer [default: ON]" ON)
OPTION(ENABLE_CLANG_PLUGIN "Enable clang static analysing plugin [default: OFF]" OFF)
OPTION(ENABLE_PCRE2 "Enable pcre2 instead of pcre [default: ON]" ON)
OPTION(ENABLE_JEMALLOC "Build rspamd with jemalloc allocator [default: OFF]" OFF)
OPTION(ENABLE_UTILS "Build rspamd internal utils [default: OFF]" OFF)
OPTION(ENABLE_LIBUNWIND "Obsoleted [default: OFF]" OFF)
OPTION(ENABLE_LUA_TRACE "Trace all Lua C API invocations [default: OFF]" OFF)
OPTION(ENABLE_LUA_REPL "Enables Lua repl (requires C++11 compiler) [default: ON]" ON)
OPTION(ENABLE_FASTTEXT "Link with FastText library [default: OFF]" OFF)
OPTION(ENABLE_BACKWARD "Build rspamd with backward-cpp stacktrace [default: ON]" ON)
OPTION(SYSTEM_ZSTD "Use system zstd instead of bundled one [default: OFF]" OFF)
OPTION(SYSTEM_DOCTEST "Use system doctest instead of bundled one [default: OFF]" OFF)
OPTION(SYSTEM_XXHASH "Use system xxhash instead of bundled one [default: OFF]" OFF)
option(ENABLE_LUAJIT "Link with libluajit" ON)
option(ENABLE_URL_INCLUDE "Enable URLs in UCL includes (requires libcurl or libfetch)" OFF)
option(NO_SHARED "Build internal libs static" ON)
option(INSTALL_WEBUI "Install web interface" ON)
option(INSTALL_EXAMPLES "Install examples of the configuration and Lua" ON)
option(WANT_SYSTEMD_UNITS "Install systemd unit files on Linux" OFF)
option(ENABLE_SNOWBALL "Enable snowball stemmer" ON)
option(ENABLE_CLANG_PLUGIN "Enable clang static analysing plugin" OFF)
option(ENABLE_PCRE2 "Enable pcre2 instead of pcre" ON)
option(ENABLE_JEMALLOC "Build rspamd with jemalloc allocator" OFF)
option(ENABLE_UTILS "Build rspamd internal utils" OFF)
option(ENABLE_LIBUNWIND "Obsoleted" OFF) # Deprecated option
option(ENABLE_LUA_TRACE "Trace all Lua C API invocations" OFF)
option(ENABLE_FASTTEXT "Link with FastText library" OFF)
option(ENABLE_BACKWARD "Build rspamd with backward-cpp stacktrace" ON)
option(SYSTEM_ZSTD "Use system zstd instead of bundled one" OFF)
option(SYSTEM_DOCTEST "Use system doctest instead of bundled one" OFF)
option(SYSTEM_XXHASH "Use system xxhash instead of bundled one" OFF)
############################# INCLUDE SECTION #############################################
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckFunctionExists)
INCLUDE(CheckSymbolExists)
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckCSourceRuns)
INCLUDE(CheckLibraryExists)
INCLUDE(CheckCCompilerFlag)
INCLUDE(CMakeParseArguments)
INCLUDE(FindArch)
INCLUDE(AsmOp)
INCLUDE(FindRagel)
INCLUDE(ProcessPackage)
IF (NOT RAGEL_FOUND)
MESSAGE(FATAL_ERROR "Ragel is required to build rspamd")
ENDIF ()
FIND_PACKAGE(PkgConfig REQUIRED)
FIND_PACKAGE(Perl REQUIRED)
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckCSourceCompiles)
include(CheckCSourceRuns)
include(CheckLibraryExists)
include(CheckCCompilerFlag)
include(CMakeParseArguments)
include(FindArch)
include(AsmOp)
include(FindRagel)
include(ProcessPackage)
if (NOT RAGEL_FOUND)
message(FATAL_ERROR "Ragel is required to build rspamd")
endif ()
# Find required packages
find_package(PkgConfig REQUIRED)
find_package(Perl REQUIRED)
# Sanitizer setup
option(SANITIZE "Enable sanitizer: address, memory, undefined, leak (comma separated list)" "")
INCLUDE(Toolset)
INCLUDE(Sanitizer)
include(Toolset)
include(Sanitizer)
INCLUDE(ArchDep)
INCLUDE(Paths)
include(ArchDep)
include(Paths)
IF (ENABLE_PCRE2 MATCHES "ON")
SET(WITH_PCRE2 1)
if (ENABLE_PCRE2)
set(WITH_PCRE2 1)
# For utf8 API
LIST(APPEND CMAKE_REQUIRED_DEFINITIONS "-DPCRE2_CODE_UNIT_WIDTH=8")
ENDIF ()
############################# CONFIG SECTION #############################################
# Initial set
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DPCRE2_CODE_UNIT_WIDTH=8")
endif ()
############################# CONFIG SECTION #############################################
# Include directories
# Prefer local include dirs to system ones
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/"
include_directories(
"${CMAKE_SOURCE_DIR}/"
"${CMAKE_SOURCE_DIR}/src"
"${CMAKE_SOURCE_DIR}/src/libutil"
"${CMAKE_SOURCE_DIR}/src/libserver"
@ -126,17 +135,19 @@ INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/"
"${CMAKE_SOURCE_DIR}/contrib/lua-lpeg"
"${CMAKE_SOURCE_DIR}/contrib/frozen/include"
"${CMAKE_SOURCE_DIR}/contrib/fu2/include"
"${CMAKE_BINARY_DIR}/src" #Stored in the binary dir
"${CMAKE_BINARY_DIR}/src/libcryptobox")
"${CMAKE_BINARY_DIR}/src" # Stored in the binary dir
"${CMAKE_BINARY_DIR}/src/libcryptobox"
)
SET(TAR "tar")
INCLUDE(OSDep)
set(TAR "tar")
include(OSDep)
# Now find libraries and headers
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES "m")
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES "pthread")
list(APPEND RSPAMD_REQUIRED_LIBRARIES "m")
list(APPEND RSPAMD_REQUIRED_LIBRARIES "pthread")
IF (ENABLE_LUAJIT MATCHES "ON")
# Lua setup
if (ENABLE_LUAJIT)
ProcessPackage(LIBLUAJIT LIBRARY "luajit"
"luajit-2.1"
"luajit2.1"
@ -149,9 +160,9 @@ IF (ENABLE_LUAJIT MATCHES "ON")
"include/luajit"
ROOT ${LUA_ROOT}
MODULES luajit)
SET(WITH_LUAJIT 1)
ELSE (ENABLE_LUAJIT MATCHES "ON")
set(WITH_LUAJIT 1)
else ()
# Try to find Lua (5.3, 5.4, 5.2, or 5.1 in that order)
ProcessPackage(LIBLUA LIBRARY "lua"
"lua-5.3"
LIB_SUFFIXES "lua5.3"
@ -164,7 +175,7 @@ ELSE (ENABLE_LUAJIT MATCHES "ON")
MODULES lua53
OPTIONAL)
IF (NOT WITH_LIBLUA)
if (NOT WITH_LIBLUA)
ProcessPackage(LIBLUA LIBRARY "lua"
"lua-5.4"
LIB_SUFFIXES "lua5.4"
@ -176,7 +187,7 @@ ELSE (ENABLE_LUAJIT MATCHES "ON")
ROOT ${LUA_ROOT}
MODULES lua54
OPTIONAL)
IF (NOT WITH_LIBLUA)
if (NOT WITH_LIBLUA)
ProcessPackage(LIBLUA LIBRARY "lua"
"lua-5.2"
LIB_SUFFIXES "lua5.2"
@ -189,7 +200,7 @@ ELSE (ENABLE_LUAJIT MATCHES "ON")
MODULES lua52
OPTIONAL)
IF (NOT WITH_LIBLUA)
if (NOT WITH_LIBLUA)
ProcessPackage(LIBLUA LIBRARY "lua"
"lua-5.1"
INCLUDE lua.h INCLUDE_SUFFIXES
@ -199,29 +210,33 @@ ELSE (ENABLE_LUAJIT MATCHES "ON")
"include/lua"
ROOT ${LUA_ROOT}
MODULES lua51)
ENDIF ()
ENDIF ()
ENDIF ()
ENDIF (ENABLE_LUAJIT MATCHES "ON")
endif ()
endif ()
endif ()
endif ()
IF (ENABLE_JEMALLOC MATCHES "ON" AND NOT SANITIZE)
# Memory allocator
if (ENABLE_JEMALLOC AND NOT SANITIZE)
ProcessPackage(JEMALLOC LIBRARY jemalloc_pic jemalloc INCLUDE jemalloc/jemalloc.h
ROOT ${JEMALLOC_ROOT_DIR})
SET(WITH_JEMALLOC "1")
ENDIF ()
set(WITH_JEMALLOC "1")
endif ()
# Required libraries
ProcessPackage(GLIB2 LIBRARY glib-2.0 INCLUDE glib.h
INCLUDE_SUFFIXES include/glib include/glib-2.0
ROOT ${GLIB_ROOT_DIR} MODULES glib-2.0>=2.28)
IF (ENABLE_PCRE2 MATCHES "ON")
# PCRE setup
if (ENABLE_PCRE2)
ProcessPackage(PCRE LIBRARY pcre2 pcre2-8 INCLUDE pcre2.h INCLUDE_SUFFIXES include/pcre2
ROOT ${PCRE_ROOT_DIR} MODULES pcre2 pcre2-8 libpcre2 libpcre2-8)
ELSE ()
else ()
ProcessPackage(PCRE LIBRARY pcre INCLUDE pcre.h INCLUDE_SUFFIXES include/pcre
ROOT ${PCRE_ROOT_DIR} MODULES pcre libpcre pcre3 libpcre3)
ENDIF ()
endif ()
# Other dependencies
ProcessPackage(SQLITE3 LIBRARY sqlite3 INCLUDE sqlite3.h INCLUDE_SUFFIXES include/sqlite3 include/sqlite
ROOT ${SQLITE3_ROOT_DIR} MODULES sqlite3 sqlite)
ProcessPackage(ICUDATA LIBRARY icudata INCLUDE unicode/ucnv.h
@ -244,573 +259,89 @@ ProcessPackage(SODIUM LIBRARY sodium INCLUDE sodium.h
ProcessPackage(LIBARCHIVE LIBRARY archive INCLUDE archive.h
ROOT ${LIBARCHIVE_ROOT_DIR} MODULES libarchive>=3.0.0)
if (ENABLE_FASTTEXT MATCHES "ON")
if (ENABLE_FASTTEXT)
ProcessPackage(FASTTEXT LIBRARY fasttext INCLUDE fasttext/fasttext.h
ROOT ${FASTTEXT_ROOT_DIR} MODULES fasttext)
SET(WITH_FASTTEXT "1")
set(WITH_FASTTEXT "1")
endif ()
# Include common compiler and platform specific configurations
include(CompilerWarnings)
include(Hyperscan)
include(Openblas)
IF (ENABLE_LUA_TRACE)
SET(WITH_LUA_TRACE 1)
ENDIF (ENABLE_LUA_TRACE)
# Lua tracing
if (ENABLE_LUA_TRACE)
set(WITH_LUA_TRACE 1)
endif ()
SET(CMAKE_C_FLAGS "${CMAKE_C_OPT_FLAGS} ${CMAKE_C_FLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_C_OPT_FLAGS} ${CMAKE_CXX_FLAGS}")
# Configure compiler flags
set(CMAKE_C_FLAGS "${CMAKE_C_OPT_FLAGS} ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_C_OPT_FLAGS} ${CMAKE_CXX_FLAGS}")
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
ADD_DEFINITIONS(-DDOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS)
ADD_DEFINITIONS(-DFMT_HEADER_ONLY)
# Define macros for compilation
add_definitions(-DHAVE_CONFIG_H)
add_definitions(-DDOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS)
add_definitions(-DFMT_HEADER_ONLY)
# Workaround for https://github.com/onqtam/doctest/issues/356
ADD_DEFINITIONS(-DDOCTEST_CONFIG_USE_STD_HEADERS)
ADD_DEFINITIONS(-DU_CHARSET_IS_UTF8)
add_definitions(-DDOCTEST_CONFIG_USE_STD_HEADERS)
add_definitions(-DU_CHARSET_IS_UTF8)
# Disable zstd deprecation warnings, as they are not relevant for us
ADD_DEFINITIONS(-DZSTD_DISABLE_DEPRECATE_WARNINGS)
add_definitions(-DZSTD_DISABLE_DEPRECATE_WARNINGS)
# Check platform specific includes
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILES(sys/uio.h HAVE_SYS_UIO_H)
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)
CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H)
CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H)
CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H)
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)
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)
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)
CHECK_INCLUDE_FILES(syslog.h HAVE_SYSLOG_H)
CHECK_INCLUDE_FILES(siginfo.h HAVE_SIGINFO_H)
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)
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)
CHECK_INCLUDE_FILES(ctype.h HAVE_CTYPE_H)
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES(cpuid.h HAVE_CPUID_H)
CHECK_INCLUDE_FILES(dirent.h HAVE_DIRENT_H)
CHECK_INCLUDE_FILES(ucontext.h HAVE_UCONTEXT_H)
CHECK_INCLUDE_FILES(sys/ucontext.h HAVE_SYS_UCONTEXT_H) # OSX specific
# Check platform API
IF (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
# setproctitle is broken badly in Linux, never try it
CHECK_FUNCTION_EXISTS(setproctitle HAVE_SETPROCTITLE)
ENDIF ()
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
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)
IF (ENABLE_PCRE2 MATCHES "ON")
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 ()
CHECK_SYMBOL_EXISTS(SOCK_SEQPACKET "sys/types.h;sys/socket.h" HAVE_SOCK_SEQPACKET)
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)
CHECK_SYMBOL_EXISTS(dirfd "sys/types.h;unistd.h;dirent.h" HAVE_DIRFD)
CHECK_SYMBOL_EXISTS(fpathconf "sys/types.h;unistd.h" HAVE_FPATHCONF)
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)
IF (ENABLE_PCRE2 MATCHES "ON")
IF (HAVE_PCRE_JIT)
SET(HAVE_PCRE_JIT_FAST 1)
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 (PCRE_LIBRARY_PATH)
SET(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};-lpcre")
ENDIF (PCRE_LIBRARY_PATH)
# Some PCRE implementations are lacking of pcre_jit_exec 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 (HAVE_PCRE_JIT_FAST)
MESSAGE(STATUS "pcre_jit_exec is -NOT- supported")
ENDIF (HAVE_PCRE_JIT_FAST)
ENDIF ()
CHECK_C_COMPILER_FLAG(-fPIC SUPPORT_FPIC)
IF (SUPPORT_FPIC)
ADD_COMPILE_OPTIONS("-fPIC")
ENDIF (SUPPORT_FPIC)
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 (_CAN_RUN EQUAL 1)
IF (HAVE_PTHREAD_PROCESS_SHARED)
MESSAGE(STATUS "pthread_mutexattr_setpshared is supported")
ELSE (HAVE_PTHREAD_PROCESS_SHARED)
MESSAGE(STATUS "pthread_mutexattr_setpshared is -NOT- supported")
ENDIF (HAVE_PTHREAD_PROCESS_SHARED)
IF (NOT HAVE_GETADDRINFO)
MESSAGE(FATAL_ERROR "Your system does not support getaddrinfo call, please consider upgrading it to run rspamd")
ENDIF (NOT HAVE_GETADDRINFO)
IF (HAVE_SIGINFO_H)
CHECK_SYMBOL_EXISTS(SA_SIGINFO "signal.h;siginfo.h" HAVE_SA_SIGINFO)
ELSE (HAVE_SIGINFO_H)
CHECK_SYMBOL_EXISTS(SA_SIGINFO "signal.h" HAVE_SA_SIGINFO)
ENDIF (HAVE_SIGINFO_H)
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 (HAVE_CLOCK_GETTIME)
CHECK_INCLUDE_FILES(sys/timeb.h HAVE_SYS_TIMEB_H)
ENDIF (HAVE_CLOCK_GETTIME)
ENDIF (NOT CMAKE_SYSTEM_NAME STREQUAL "SunOS")
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)
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 (NOT HAVE_ATOMIC_BUILTINS)
MESSAGE(STATUS "atomic builtins are -NOT- supported")
ELSE ()
MESSAGE(STATUS "atomic builtins are supported")
ENDIF ()
CHECK_LIBRARY_EXISTS(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
IF (HAVE_LIBATOMIC)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
endif ()
include(CheckSystemHeaders)
# Check macros, functions, and features
include(CheckSystemFeatures)
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 ()
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)
ELSE ()
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 ()
IF (ENABLE_URL_INCLUDE MATCHES "ON")
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)
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")
ELSE (LIBFETCH_LIBRARY)
# Try to find libcurl
ProcessPackage(CURL LIBRARY curl INCLUDE curl.h INCLUDE_SUFFIXES include/curl
ROOT ${CURL_ROOT})
IF (NOT WITH_CURL)
MESSAGE(WARNING "Neither libcurl nor libfetch were found, no support of URL includes in configuration")
ENDIF (NOT WITH_CURL)
ENDIF (LIBFETCH_LIBRARY)
ENDIF (ENABLE_URL_INCLUDE MATCHES "ON")
IF (NOT DESTDIR)
SET(DESTDIR $ENV{DESTDIR})
ENDIF (NOT DESTDIR)
# Check symbols and functions
include(CheckSymbols)
# Configure PIC support
check_c_compiler_flag(-fPIC SUPPORT_FPIC)
if (SUPPORT_FPIC)
add_compile_options("-fPIC")
endif ()
# Support for URL includes
include(CheckURLInclude)
if (ENABLE_URL_INCLUDE)
CheckURLIncludeSupport()
endif ()
# Ensure DESTDIR is set
if (NOT DESTDIR)
set(DESTDIR $ENV{DESTDIR})
endif ()
################################ SUBDIRS SECTION ###########################
ADD_SUBDIRECTORY(contrib/hiredis)
INCLUDE_DIRECTORIES(BEFORE "${CMAKE_SOURCE_DIR}/contrib/hiredis")
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
IF (HAVE_FETCH_H)
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES fetch)
ENDIF (HAVE_FETCH_H)
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES "${LUA_LIBRARY}")
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES ucl)
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES rdns)
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES ottery)
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES 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_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")
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 ()
IF (ENABLE_SNOWBALL MATCHES "ON")
ADD_SUBDIRECTORY(contrib/snowball)
SET(WITH_SNOWBALL 1)
ENDIF ()
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)
IF (ENABLE_BACKWARD MATCHES "ON")
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 ()
IF (SYSTEM_DOCTEST MATCHES "OFF")
ADD_SUBDIRECTORY(contrib/doctest)
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/contrib/doctest")
ELSE ()
find_package(doctest)
ENDIF ()
IF (NOT WITH_LUAJIT)
ADD_SUBDIRECTORY(contrib/lua-bit)
ENDIF ()
IF (ENABLE_LUA_REPL MATCHES "ON")
ADD_SUBDIRECTORY(contrib/replxx)
SET(WITH_LUA_REPL 1)
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES rspamd-replxx)
ENDIF ()
IF (ENABLE_SNOWBALL MATCHES "ON")
LIST(APPEND RSPAMD_REQUIRED_LIBRARIES stemmer)
ENDIF ()
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)
IF (ENABLE_CLANG_PLUGIN MATCHES "ON")
ADD_SUBDIRECTORY(clang-plugin)
ENDIF ()
ADD_SUBDIRECTORY(src)
enable_testing()
ADD_SUBDIRECTORY(test)
ADD_SUBDIRECTORY(utils)
# Add required subdirectories for dependencies
include(AddDependencySubdirectories)
AddDependencySubdirectories()
############################ TARGETS SECTION ###############################
CONFIGURE_FILE(config.h.in src/config.h)
# Generate config.h
configure_file(config.h.in src/config.h)
##################### INSTALLATION ##########################################
# Setup installation targets
include(InstallRspamdFiles)
InstallRspamdFiles()
# Binaries
# Configs
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 configs only if they are unchanged
LIST(LENGTH CONFFILES CONFLIST_COUNT)
MATH(EXPR CONFLIST_MAX ${CONFLIST_COUNT}-1)
SET(GLOB_PATTERNS "${CMAKE_SOURCE_DIR}/conf/*.conf;${CMAKE_SOURCE_DIR}/conf/*.inc")
IF (INSTALL_EXAMPLES MATCHES "ON")
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 (CONF_FILE)
# 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 (LUA_PLUGIN)
# Install TLD list
INSTALL(FILES "contrib/publicsuffix/effective_tld_names.dat" DESTINATION
"${SHAREDIR}")
# Install languages 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)
# Lua config
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 (LUA_CONF)
# Lua libs
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 (LUA_LIB)
# Install lua fun library
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})
# systemd unit
IF (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND WANT_SYSTEMD_UNITS MATCHES "ON")
INSTALL(FILES "rspamd.service" DESTINATION ${SYSTEMDDIR})
ENDIF (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND WANT_SYSTEMD_UNITS MATCHES "ON")
# Manual 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)
# Utils
INSTALL(PROGRAMS "utils/rspamd_stats.pl" RENAME rspamd_stats DESTINATION bin)
# Install webui
IF (INSTALL_WEBUI MATCHES "ON")
INSTALL(DIRECTORY "interface/" DESTINATION ${WWWDIR} PATTERN ".git" EXCLUDE)
ENDIF (INSTALL_WEBUI MATCHES "ON")
ADD_CUSTOM_TARGET(dist ${CMAKE_SOURCE_DIR}/dist.sh
# Build distribution and testing targets
add_custom_target(dist ${CMAKE_SOURCE_DIR}/dist.sh
"${CMAKE_BINARY_DIR}/rspamd-${RSPAMD_VERSION}.tar.xz" "${TAR}"
COMMENT "Create source distribution"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
ADD_CUSTOM_TARGET(check DEPENDS rspamd-test-cxx rspamd-test)
ADD_CUSTOM_TARGET(run-test DEPENDS check
add_custom_target(check DEPENDS rspamd-test-cxx rspamd-test)
add_custom_target(run-test DEPENDS check
COMMAND test/rspamd-test-cxx
COMMAND sh -c 'LUA_PATH="${CMAKE_SOURCE_DIR}/lualib/?.lua\;${CMAKE_SOURCE_DIR}/lualib/?/?.lua\;${CMAKE_SOURCE_DIR}/lualib/?/init.lua\;${CMAKE_SOURCE_DIR}/contrib/lua-?/?.lua"
test/rspamd-test -p /rspamd/lua')
# PVS Studio
find_program(_PVS_STUDIO "pvs-studio-analyzer")
if (_PVS_STUDIO)
include(PVS-Studio)
pvs_studio_add_target(TARGET ${PROJECT_NAME}.analyze
ANALYZE ${PROJECT_NAME} rspamd-server rspamadm rspamc
OUTPUT FORMAT errorfile
LOG target_${PROJECT_NAME}.err)
endif ()
# Setup PVS Studio if available
include(SetupPVSStudio)
SetupPVSStudio()

114
cmake/AddDependencySubdirectories.cmake

@ -0,0 +1,114 @@
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)
set(WITH_LUA_REPL 1 PARENT_SCOPE)
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)
# Enable testing
enable_testing()
add_subdirectory(test)
# Utilities
add_subdirectory(utils)
# Propagate variables to parent scope
set(RSPAMD_REQUIRED_LIBRARIES ${RSPAMD_REQUIRED_LIBRARIES} PARENT_SCOPE)
set(WITH_SNOWBALL ${WITH_SNOWBALL} PARENT_SCOPE)
set(WITH_LUA_REPL ${WITH_LUA_REPL} PARENT_SCOPE)
endfunction()

146
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()

207
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()

139
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()

51
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()

104
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()

56
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()

18
contrib/xxhash/CMakeLists.txt

@ -1,13 +1,13 @@
SET(XXHASHSRC xxhash.c)
ADD_LIBRARY(xxhash STATIC ${XXHASHSRC})
ADD_LIBRARY(rspamd-xxhash STATIC ${XXHASHSRC})
IF(ENABLE_FULL_DEBUG MATCHES "OFF")
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
SET_TARGET_PROPERTIES(xxhash PROPERTIES COMPILE_FLAGS "-O3")
endif ()
else()
ADD_DEFINITIONS(-DXXH_NO_INLINE_HINTS=1)
ENDIF()
IF (ENABLE_FULL_DEBUG MATCHES "OFF")
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
SET_TARGET_PROPERTIES(rspamd-xxhash PROPERTIES COMPILE_FLAGS "-O3")
endif ()
else ()
ADD_DEFINITIONS(-DXXH_NO_INLINE_HINTS=1)
ENDIF ()
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DXXH_NO_INLINE_HINTS=1" PARENT_SCOPE)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DXXH_NO_INLINE_HINTS=1" PARENT_SCOPE)

532
src/CMakeLists.txt

@ -1,246 +1,286 @@
MACRO(_AddModulesForced MLIST)
# Generate unique string for this build
SET(MODULES_C "${CMAKE_CURRENT_BINARY_DIR}/modules.c")
FILE(WRITE "${MODULES_C}"
"#include \"rspamd.h\"\n")
# Handle even old cmake
LIST(LENGTH ${MLIST} MLIST_COUNT)
MATH(EXPR MLIST_MAX ${MLIST_COUNT}-1)
FOREACH(MOD_IDX RANGE ${MLIST_MAX})
LIST(GET ${MLIST} ${MOD_IDX} MOD)
FILE(APPEND "${MODULES_C}" "extern module_t ${MOD}_module;\n")
ENDFOREACH(MOD_IDX RANGE ${MLIST_MAX})
FILE(APPEND "${MODULES_C}" "\n\nmodule_t *modules[] = {\n")
FOREACH(MOD_IDX RANGE ${MLIST_MAX})
LIST(GET ${MLIST} ${MOD_IDX} MOD)
FILE(APPEND "${MODULES_C}" "&${MOD}_module,\n")
ENDFOREACH(MOD_IDX RANGE ${MLIST_MAX})
FILE(APPEND "${MODULES_C}" "NULL\n};\n")
ENDMACRO(_AddModulesForced MLIST)
MACRO(_AddWorkersForced WLIST)
SET(WORKERS_C "${CMAKE_CURRENT_BINARY_DIR}/workers.c")
FILE(WRITE "${WORKERS_C}"
"#include \"rspamd.h\"\n")
# Handle even old cmake
LIST(LENGTH ${WLIST} WLIST_COUNT)
MATH(EXPR WLIST_MAX ${WLIST_COUNT}-1)
FOREACH(MOD_IDX RANGE ${WLIST_MAX})
LIST(GET ${WLIST} ${MOD_IDX} WRK)
FILE(APPEND "${WORKERS_C}" "extern worker_t ${WRK}_worker;\n")
ENDFOREACH(MOD_IDX RANGE ${WLIST_MAX})
FILE(APPEND "${WORKERS_C}" "\n\nworker_t *workers[] = {\n")
FOREACH(MOD_IDX RANGE ${WLIST_MAX})
LIST(GET ${WLIST} ${MOD_IDX} WRK)
FILE(APPEND "${WORKERS_C}" "&${WRK}_worker,\n")
ENDFOREACH(MOD_IDX RANGE ${WLIST_MAX})
FILE(APPEND "${WORKERS_C}" "NULL\n};\n")
ENDMACRO(_AddWorkersForced WLIST)
MACRO(AddModules MLIST WLIST)
_AddModulesForced(${MLIST})
_AddWorkersForced(${WLIST})
#IF(NOT EXISTS "modules.c")
# _AddModulesForced(${MLIST} ${WLIST})
#ELSE(NOT EXISTS "modules.c")
# FILE(STRINGS "modules.c" FILE_ID_RAW REGEX "^/.*[a-zA-Z0-9]+.*/$")
# STRING(REGEX MATCH "[a-zA-Z0-9]+" FILE_ID "${FILE_ID_RAW}")
# IF(NOT FILE_ID STREQUAL MODULES_ID)
# MESSAGE("Regenerate modules info")
# _AddModulesForced(${MLIST} ${WLIST})
# ENDIF(NOT FILE_ID STREQUAL MODULES_ID)
#ENDIF(NOT EXISTS "modules.c")
ENDMACRO(AddModules MLIST WLIST)
# Rspamd core components
IF (ENABLE_CLANG_PLUGIN MATCHES "ON")
SET(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -Xclang -load -Xclang ${CMAKE_CURRENT_BINARY_DIR}/../clang-plugin/librspamd-clang${CMAKE_SHARED_LIBRARY_SUFFIX} -Xclang -add-plugin -Xclang rspamd-ast")
IF(CLANG_EXTRA_PLUGINS_LIBS)
FOREACH(_lib ${CLANG_EXTRA_PLUGINS_LIBS})
SET(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -Xclang -load -Xclang ${_lib}")
SET(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Xclang -load -Xclang ${_lib}")
ENDFOREACH()
ENDIF()
IF(CLANG_EXTRA_PLUGINS)
FOREACH(_plug ${CLANG_EXTRA_PLUGINS})
SET(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -Xclang -add-plugin -Xclang ${_plug}")
SET(CMAKE_CXX_FLAGS
"${CMAKE_C_FLAGS} -Xclang -add-plugin -Xclang ${_plug}")
ENDFOREACH()
ENDIF()
ENDIF ()
ADD_SUBDIRECTORY(lua)
ADD_SUBDIRECTORY(libcryptobox)
ADD_SUBDIRECTORY(libutil)
ADD_SUBDIRECTORY(libserver)
ADD_SUBDIRECTORY(libmime)
ADD_SUBDIRECTORY(libstat)
ADD_SUBDIRECTORY(client)
ADD_SUBDIRECTORY(rspamadm)
SET(RSPAMDSRC controller.c
fuzzy_storage.c
rspamd.c
worker.c
rspamd_proxy.c)
SET(PLUGINSSRC plugins/regexp.c
plugins/chartable.cxx
plugins/fuzzy_check.c
plugins/dkim_check.c
libserver/rspamd_control.c)
SET(MODULES_LIST regexp chartable fuzzy_check dkim)
SET(WORKERS_LIST normal controller fuzzy rspamd_proxy)
IF (ENABLE_HYPERSCAN MATCHES "ON")
LIST(APPEND WORKERS_LIST "hs_helper")
LIST(APPEND RSPAMDSRC "hs_helper.c")
ENDIF()
AddModules(MODULES_LIST WORKERS_LIST)
LIST(LENGTH PLUGINSSRC RSPAMD_MODULES_NUM)
SET(RAGEL_DEPENDS "${CMAKE_SOURCE_DIR}/src/ragel/smtp_address.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/smtp_date.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/smtp_ip.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/smtp_base.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/content_disposition.rl")
RAGEL_TARGET(ragel_smtp_addr
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/smtp_addr_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -T1
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/smtp_addr_parser.rl.c)
RAGEL_TARGET(ragel_content_disposition
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/content_disposition_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/content_disposition.rl.c)
RAGEL_TARGET(ragel_rfc2047
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/rfc2047_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/rfc2047.rl.c)
RAGEL_TARGET(ragel_smtp_date
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/smtp_date_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/date_parser.rl.c)
RAGEL_TARGET(ragel_smtp_ip
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/smtp_ip_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ip_parser.rl.c)
# Fucking cmake...
FOREACH(_GEN ${LIBSERVER_GENERATED})
set_source_files_properties(${_GEN} PROPERTIES GENERATED TRUE)
ENDFOREACH()
######################### LINK SECTION ###############################
IF(ENABLE_STATIC MATCHES "ON")
ADD_LIBRARY(rspamd-server STATIC
${RSPAMD_CRYPTOBOX}
${RSPAMD_UTIL}
${RSPAMD_LUA}
${RSPAMD_SERVER}
${RSPAMD_STAT}
${RSPAMD_MIME}
${CMAKE_CURRENT_BINARY_DIR}/modules.c
${PLUGINSSRC}
"${RAGEL_ragel_smtp_addr_OUTPUTS}"
"${RAGEL_ragel_newlines_strip_OUTPUTS}"
"${RAGEL_ragel_content_type_OUTPUTS}"
"${RAGEL_ragel_content_disposition_OUTPUTS}"
"${RAGEL_ragel_rfc2047_OUTPUTS}"
"${RAGEL_ragel_smtp_date_OUTPUTS}"
"${RAGEL_ragel_smtp_ip_OUTPUTS}"
${BACKWARD_ENABLE})
ELSE()
ADD_LIBRARY(rspamd-server SHARED
${RSPAMD_CRYPTOBOX}
${RSPAMD_UTIL}
${RSPAMD_SERVER}
${RSPAMD_STAT}
${RSPAMD_MIME}
${RSPAMD_LUA}
${CMAKE_CURRENT_BINARY_DIR}/modules.c
${PLUGINSSRC}
"${RAGEL_ragel_smtp_addr_OUTPUTS}"
"${RAGEL_ragel_newlines_strip_OUTPUTS}"
"${RAGEL_ragel_content_type_OUTPUTS}"
"${RAGEL_ragel_content_disposition_OUTPUTS}"
"${RAGEL_ragel_rfc2047_OUTPUTS}"
"${RAGEL_ragel_smtp_date_OUTPUTS}"
"${RAGEL_ragel_smtp_ip_OUTPUTS}"
${BACKWARD_ENABLE})
ENDIF()
FOREACH(_DEP ${LIBSERVER_DEPENDS})
ADD_DEPENDENCIES(rspamd-server "${_DEP}")
ENDFOREACH()
TARGET_LINK_LIBRARIES(rspamd-server rspamd-http-parser)
TARGET_LINK_LIBRARIES(rspamd-server rspamd-fpconv)
TARGET_LINK_LIBRARIES(rspamd-server rspamd-cdb)
TARGET_LINK_LIBRARIES(rspamd-server rspamd-lpeg)
TARGET_LINK_LIBRARIES(rspamd-server lcbtrie)
IF(SYSTEM_ZSTD MATCHES "OFF")
TARGET_LINK_LIBRARIES(rspamd-server rspamd-zstd)
ELSE()
TARGET_LINK_LIBRARIES(rspamd-server zstd)
ENDIF()
TARGET_LINK_LIBRARIES(rspamd-server rspamd-simdutf)
IF (ENABLE_CLANG_PLUGIN MATCHES "ON")
ADD_DEPENDENCIES(rspamd-server rspamd-clang)
ENDIF()
IF (NOT WITH_LUAJIT)
TARGET_LINK_LIBRARIES(rspamd-server rspamd-bit)
ENDIF()
IF (ENABLE_SNOWBALL MATCHES "ON")
TARGET_LINK_LIBRARIES(rspamd-server stemmer)
ENDIF()
TARGET_LINK_LIBRARIES(rspamd-server rspamd-hiredis)
IF (ENABLE_FANN MATCHES "ON")
TARGET_LINK_LIBRARIES(rspamd-server fann)
ENDIF ()
IF (ENABLE_HYPERSCAN MATCHES "ON")
TARGET_LINK_LIBRARIES(rspamd-server hs)
ENDIF()
IF(WITH_BLAS)
TARGET_LINK_LIBRARIES(rspamd-server ${BLAS_REQUIRED_LIBRARIES})
ENDIF()
TARGET_LINK_LIBRARIES(rspamd-server ${RSPAMD_REQUIRED_LIBRARIES})
ADD_BACKWARD(rspamd-server)
ADD_EXECUTABLE(rspamd ${RSPAMDSRC} ${CMAKE_CURRENT_BINARY_DIR}/workers.c ${CMAKE_CURRENT_BINARY_DIR}/config.h)
ADD_BACKWARD(rspamd)
SET_TARGET_PROPERTIES(rspamd PROPERTIES LINKER_LANGUAGE CXX)
SET_TARGET_PROPERTIES(rspamd-server PROPERTIES LINKER_LANGUAGE CXX)
IF(NOT NO_TARGET_VERSIONS)
SET_TARGET_PROPERTIES(rspamd PROPERTIES VERSION ${RSPAMD_VERSION})
ENDIF()
#TARGET_LINK_LIBRARIES(rspamd ${RSPAMD_REQUIRED_LIBRARIES})
TARGET_LINK_LIBRARIES(rspamd rspamd-server)
INSTALL(TARGETS rspamd RUNTIME DESTINATION bin)
INSTALL(TARGETS rspamd-server LIBRARY DESTINATION ${RSPAMD_LIBDIR})
# Function to generate module registrations
function(generate_modules_list MODULE_LIST)
# Generate unique string for this build
set(MODULES_C "${CMAKE_CURRENT_BINARY_DIR}/modules.c")
file(WRITE "${MODULES_C}"
"#include \"rspamd.h\"\n")
# Process each module
foreach (MOD IN LISTS ${MODULE_LIST})
file(APPEND "${MODULES_C}" "extern module_t ${MOD}_module;\n")
endforeach ()
file(APPEND "${MODULES_C}" "\n\nmodule_t *modules[] = {\n")
foreach (MOD IN LISTS ${MODULE_LIST})
file(APPEND "${MODULES_C}" "&${MOD}_module,\n")
endforeach ()
file(APPEND "${MODULES_C}" "NULL\n};\n")
# Return the generated file path
set(MODULES_C_PATH "${MODULES_C}" PARENT_SCOPE)
endfunction()
# Function to generate worker registrations
function(generate_workers_list WORKER_LIST)
set(WORKERS_C "${CMAKE_CURRENT_BINARY_DIR}/workers.c")
file(WRITE "${WORKERS_C}"
"#include \"rspamd.h\"\n")
# Process each worker
foreach (WRK IN LISTS ${WORKER_LIST})
file(APPEND "${WORKERS_C}" "extern worker_t ${WRK}_worker;\n")
endforeach ()
file(APPEND "${WORKERS_C}" "\n\nworker_t *workers[] = {\n")
foreach (WRK IN LISTS ${WORKER_LIST})
file(APPEND "${WORKERS_C}" "&${WRK}_worker,\n")
endforeach ()
file(APPEND "${WORKERS_C}" "NULL\n};\n")
# Return the generated file path
set(WORKERS_C_PATH "${WORKERS_C}" PARENT_SCOPE)
endfunction()
# Function to generate both modules and workers
function(generate_registration_code MODULE_LIST WORKER_LIST)
generate_modules_list(${MODULE_LIST})
generate_workers_list(${WORKER_LIST})
# Set parent scope variables
set(MODULES_C_PATH ${MODULES_C_PATH} PARENT_SCOPE)
set(WORKERS_C_PATH ${WORKERS_C_PATH} PARENT_SCOPE)
endfunction()
# Configure Clang Plugin if enabled
if (ENABLE_CLANG_PLUGIN)
set(CLANG_PLUGIN_FLAGS "-Xclang -load -Xclang ${CMAKE_CURRENT_BINARY_DIR}/../clang-plugin/librspamd-clang${CMAKE_SHARED_LIBRARY_SUFFIX} -Xclang -add-plugin -Xclang rspamd-ast")
# Apply to both C and C++ compiler flags
add_compile_options(${CLANG_PLUGIN_FLAGS})
# Add any extra clang plugins
if (CLANG_EXTRA_PLUGINS_LIBS)
foreach (lib ${CLANG_EXTRA_PLUGINS_LIBS})
add_compile_options("-Xclang" "-load" "-Xclang" "${lib}")
endforeach ()
endif ()
if (CLANG_EXTRA_PLUGINS)
foreach (plug ${CLANG_EXTRA_PLUGINS})
add_compile_options("-Xclang" "-add-plugin" "-Xclang" "${plug}")
endforeach ()
endif ()
endif ()
# Add subdirectories for components
add_subdirectory(lua)
add_subdirectory(libcryptobox)
add_subdirectory(libutil)
add_subdirectory(libserver)
add_subdirectory(libmime)
add_subdirectory(libstat)
add_subdirectory(client)
add_subdirectory(rspamadm)
# Define source files
set(RSPAMD_SOURCES
controller.c
fuzzy_storage.c
rspamd.c
worker.c
rspamd_proxy.c)
set(PLUGIN_SOURCES
plugins/regexp.c
plugins/chartable.cxx
plugins/fuzzy_check.c
plugins/dkim_check.c
libserver/rspamd_control.c)
# Define module and worker lists
set(MODULES_LIST regexp chartable fuzzy_check dkim)
set(WORKERS_LIST normal controller fuzzy rspamd_proxy)
# Add hyperscan worker if enabled
if (ENABLE_HYPERSCAN)
list(APPEND WORKERS_LIST hs_helper)
list(APPEND RSPAMD_SOURCES hs_helper.c)
endif ()
# Generate modules and workers registration code
generate_registration_code(MODULES_LIST WORKERS_LIST)
# Count the number of modules
list(LENGTH PLUGIN_SOURCES RSPAMD_MODULES_NUM)
# Configure Ragel for parsers
set(RAGEL_DEPENDS
"${CMAKE_SOURCE_DIR}/src/ragel/smtp_address.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/smtp_date.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/smtp_ip.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/smtp_base.rl"
"${CMAKE_SOURCE_DIR}/src/ragel/content_disposition.rl")
# Generate parsers with Ragel
ragel_target(ragel_smtp_addr
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/smtp_addr_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -T1
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/smtp_addr_parser.rl.c)
ragel_target(ragel_content_disposition
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/content_disposition_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/content_disposition.rl.c)
ragel_target(ragel_rfc2047
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/rfc2047_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/rfc2047.rl.c)
ragel_target(ragel_smtp_date
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/smtp_date_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/date_parser.rl.c)
ragel_target(ragel_smtp_ip
INPUTS ${CMAKE_SOURCE_DIR}/src/ragel/smtp_ip_parser.rl
DEPENDS ${RAGEL_DEPENDS}
COMPILE_FLAGS -G2
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ip_parser.rl.c)
# Mark generated files correctly
foreach (_gen ${LIBSERVER_GENERATED})
set_source_files_properties(${_gen} PROPERTIES GENERATED TRUE)
endforeach ()
# Collection of all generated Ragel outputs
set(RAGEL_OUTPUTS
${RAGEL_ragel_smtp_addr_OUTPUTS}
${RAGEL_ragel_newlines_strip_OUTPUTS}
${RAGEL_ragel_content_type_OUTPUTS}
${RAGEL_ragel_content_disposition_OUTPUTS}
${RAGEL_ragel_rfc2047_OUTPUTS}
${RAGEL_ragel_smtp_date_OUTPUTS}
${RAGEL_ragel_smtp_ip_OUTPUTS})
# Common sources for rspamd-server
set(SERVER_COMMON_SOURCES
${RSPAMD_CRYPTOBOX}
${RSPAMD_UTIL}
${RSPAMD_LUA}
${RSPAMD_SERVER}
${RSPAMD_STAT}
${RSPAMD_MIME}
${MODULES_C_PATH}
${PLUGIN_SOURCES}
${RAGEL_OUTPUTS}
${BACKWARD_ENABLE})
# Build rspamd-server as static or shared library based on configuration
if (ENABLE_STATIC)
add_library(rspamd-server STATIC ${SERVER_COMMON_SOURCES})
else ()
add_library(rspamd-server SHARED ${SERVER_COMMON_SOURCES})
endif ()
# Set dependencies for rspamd-server
foreach (_dep ${LIBSERVER_DEPENDS})
add_dependencies(rspamd-server "${_dep}")
endforeach ()
# Link dependencies
target_link_libraries(rspamd-server
PRIVATE
rspamd-http-parser
rspamd-fpconv
rspamd-cdb
rspamd-lpeg
ottery
lcbtrie
rspamd-simdutf
rdns
ucl)
# Handle xxhash dependency
if (SYSTEM_XXHASH)
target_link_libraries(rspamd-server PUBLIC xxhash)
else ()
target_link_libraries(rspamd-server PRIVATE rspamd-xxhash)
endif ()
# Handle zstd dependency
if (SYSTEM_ZSTD)
target_link_libraries(rspamd-server PUBLIC zstd)
else ()
target_link_libraries(rspamd-server PRIVATE rspamd-zstd)
endif ()
# Handle clang plugin dependency
if (ENABLE_CLANG_PLUGIN)
add_dependencies(rspamd-server rspamd-clang)
endif ()
# Handle Lua JIT/Lua dependency
if (NOT WITH_LUAJIT)
target_link_libraries(rspamd-server PRIVATE rspamd-bit)
endif ()
# Link additional optional dependencies
if (ENABLE_SNOWBALL)
target_link_libraries(rspamd-server PRIVATE stemmer)
endif ()
target_link_libraries(rspamd-server PRIVATE rspamd-hiredis)
if (ENABLE_FANN)
target_link_libraries(rspamd-server PRIVATE fann)
endif ()
if (ENABLE_HYPERSCAN)
target_link_libraries(rspamd-server PUBLIC hs)
endif ()
if (WITH_BLAS)
target_link_libraries(rspamd-server PRIVATE ${BLAS_REQUIRED_LIBRARIES})
endif ()
# Link all required system libraries
target_link_libraries(rspamd-server PUBLIC ${RSPAMD_REQUIRED_LIBRARIES})
# Add Backward support for stacktrace
add_backward(rspamd-server)
# Build main rspamd executable
add_executable(rspamd
${RSPAMD_SOURCES}
${WORKERS_C_PATH}
${CMAKE_CURRENT_BINARY_DIR}/config.h)
# Configure rspamd executable
add_backward(rspamd)
set_target_properties(rspamd PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(rspamd-server PROPERTIES LINKER_LANGUAGE CXX)
if (NOT NO_TARGET_VERSIONS)
set_target_properties(rspamd PROPERTIES VERSION ${RSPAMD_VERSION})
endif ()
# Link rspamd executable with the server library
target_link_libraries(rspamd PRIVATE rspamd-server)
# Install targets
install(TARGETS rspamd
RUNTIME
DESTINATION bin)
install(TARGETS rspamd-server
LIBRARY
DESTINATION ${RSPAMD_LIBDIR})

4
src/rspamadm/lua_repl.c

@ -1,5 +1,5 @@
/*
* Copyright 2024 Vsevolod Stakhov
* Copyright 2025 Vsevolod Stakhov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -701,8 +701,8 @@ rspamadm_lua_run_repl(lua_State *L, bool is_batch)
g_string_append(tb, " \n");
}
}
}
#endif
}
}
}

Loading…
Cancel
Save