diff options
Diffstat (limited to '')
-rw-r--r-- | cmake/ArchDep.cmake | 102 | ||||
-rw-r--r-- | cmake/AsmOp.cmake | 19 | ||||
-rw-r--r-- | cmake/CompilerWarnings.cmake | 89 | ||||
-rw-r--r-- | cmake/FindArch.cmake | 127 | ||||
-rw-r--r-- | cmake/FindRagel.cmake | 103 | ||||
-rw-r--r-- | cmake/Hyperscan.cmake | 8 | ||||
-rw-r--r-- | cmake/OSDep.cmake | 65 | ||||
-rw-r--r-- | cmake/Openblas.cmake | 119 | ||||
-rw-r--r-- | cmake/PVS-Studio.cmake | 547 | ||||
-rw-r--r-- | cmake/Paths.cmake | 72 | ||||
-rw-r--r-- | cmake/ProcessPackage.cmake | 122 | ||||
-rw-r--r-- | cmake/Sanitizer.cmake | 75 | ||||
-rw-r--r-- | cmake/Toolset.cmake | 252 |
13 files changed, 1700 insertions, 0 deletions
diff --git a/cmake/ArchDep.cmake b/cmake/ArchDep.cmake new file mode 100644 index 0000000..8271709 --- /dev/null +++ b/cmake/ArchDep.cmake @@ -0,0 +1,102 @@ +TARGET_ARCHITECTURE(ARCH) + +SET(ASM_CODE " + .macro TEST1 op + \\op %eax, %eax + .endm + TEST1 xorl + ") +ASM_OP(HAVE_SLASHMACRO "slash macro convention") + +SET(ASM_CODE " + .macro TEST1 op + $0 %eax, %eax + .endm + TEST1 xorl + ") +ASM_OP(HAVE_DOLLARMACRO "dollar macro convention") + +# For now we support only x86_64/i386 architecture with optimizations +IF("${ARCH}" STREQUAL "x86_64" OR "${ARCH}" STREQUAL "i386") + IF(NOT HAVE_SLASHMACRO AND NOT HAVE_DOLLARMACRO) + MESSAGE(FATAL_ERROR "Your assembler cannot compile macros, please check your CMakeFiles/CMakeError.log") + ENDIF() + + SET(ASM_CODE "vpaddq %ymm0, %ymm0, %ymm0") + ASM_OP(HAVE_AVX2 "avx2") + # Handle broken compilers, sigh... + IF(HAVE_AVX2) + CHECK_C_SOURCE_COMPILES( + " +#include <stddef.h> +#pragma GCC push_options +#pragma GCC target(\"avx2\") +#ifndef __SSE2__ +#define __SSE2__ +#endif +#ifndef __SSE__ +#define __SSE__ +#endif +#ifndef __SSE4_2__ +#define __SSE4_2__ +#endif +#ifndef __SSE4_1__ +#define __SSE4_1__ +#endif +#ifndef __SSEE3__ +#define __SSEE3__ +#endif +#ifndef __AVX__ +#define __AVX__ +#endif +#ifndef __AVX2__ +#define __AVX2__ +#endif + +#ifndef __clang__ +#if __GNUC__ < 6 +#error Broken due to compiler bug +#endif +#endif + +#include <immintrin.h> +static void foo(const char* a) __attribute__((__target__(\"avx2\"))); +static void foo(const char* a) +{ + __m256i str = _mm256_loadu_si256((__m256i *)a); + __m256i t = _mm256_loadu_si256((__m256i *)a + 1); + _mm256_add_epi8(str, t); +} +int main(int argc, char** argv) { + foo(argv[0]); +}" HAVE_AVX2_C_COMPILER) + IF(NOT HAVE_AVX2_C_COMPILER) + MESSAGE(STATUS "Your compiler has broken AVX2 support") + UNSET(HAVE_AVX2 CACHE) + ENDIF() + ENDIF() + SET(ASM_CODE "vpaddq %xmm0, %xmm0, %xmm0") + ASM_OP(HAVE_AVX "avx") + SET(ASM_CODE "pmuludq %xmm0, %xmm0") + ASM_OP(HAVE_SSE2 "sse2") + SET(ASM_CODE "lddqu 0(%esi), %xmm0") + ASM_OP(HAVE_SSE3 "sse3") + SET(ASM_CODE "pshufb %xmm0, %xmm0") + ASM_OP(HAVE_SSSE3 "ssse3") + SET(ASM_CODE "pblendw \$0, %xmm0, %xmm0") + ASM_OP(HAVE_SSE41 "sse41") + SET(ASM_CODE "crc32 %eax, %eax") + ASM_OP(HAVE_SSE42 "sse42") +ENDIF() + +IF ("${ARCH}" STREQUAL "x86_64") + MESSAGE(STATUS "Enable sse2 on x86_64 architecture") + IF((CMAKE_C_COMPILER_ID MATCHES "GNU") OR (CMAKE_C_COMPILER_ID MATCHES "Clang")) + ADD_COMPILE_OPTIONS(-msse2) + ADD_COMPILE_OPTIONS(-m64) + ELSEIF(CMAKE_C_COMPILER_ID MATCHES "Intel") + ADD_COMPILE_OPTIONS(/QxSSE2) + ELSEIF((CMAKE_C_COMPILER_ID MATCHES "MSVC")) + ADD_COMPILE_OPTIONS(/arch:SSE2) + ENDIF() +ENDIF() diff --git a/cmake/AsmOp.cmake b/cmake/AsmOp.cmake new file mode 100644 index 0000000..bcf9d99 --- /dev/null +++ b/cmake/AsmOp.cmake @@ -0,0 +1,19 @@ +# Check for assembler option specified + +MACRO(asm_op output_var description) + IF(NOT ${output_var}) + file(WRITE "${CMAKE_BINARY_DIR}/asm.S" "${ASM_CODE}") + try_compile(HAVE_OP + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/asm.S" + CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo not linking now...'") + + if(HAVE_OP) + MESSAGE(STATUS "Compilation of ${description} asm set is supported") + else() + MESSAGE(STATUS "Compilation of ${description} asm set is -NOT- supported") + endif() + + set(${output_var} "${HAVE_OP}" CACHE INTERNAL "${description}") + ENDIF() +ENDMACRO() diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake new file mode 100644 index 0000000..9092457 --- /dev/null +++ b/cmake/CompilerWarnings.cmake @@ -0,0 +1,89 @@ +CHECK_C_COMPILER_FLAG(-Wall SUPPORT_WALL) +CHECK_C_COMPILER_FLAG(-Wextra SUPPORT_WEXTRA) +CHECK_C_COMPILER_FLAG(-Wpointer-arith SUPPORT_WPOINTER) +CHECK_C_COMPILER_FLAG(-Wno-unused-parameter SUPPORT_WPARAM) +CHECK_C_COMPILER_FLAG(-Wno-unused-function SUPPORT_WFUNCTION) +CHECK_C_COMPILER_FLAG(-Wno-strict-aliasing SUPPORT_WSTRICT_ALIASING) +CHECK_C_COMPILER_FLAG(-Wunused-variable SUPPORT_WUNUSED_VAR) +CHECK_C_COMPILER_FLAG(-Wno-pointer-sign SUPPORT_WPOINTER_SIGN) +CHECK_C_COMPILER_FLAG(-Wno-sign-compare SUPPORT_WSIGN_COMPARE) +CHECK_C_COMPILER_FLAG(-Wstrict-prototypes SUPPORT_WSTRICT_PROTOTYPES) +CHECK_C_COMPILER_FLAG(-pedantic SUPPORT_PEDANTIC_FLAG) +CHECK_C_COMPILER_FLAG(-Wno-unused-const-variable SUPPORT_WNO_UNUSED_CONST) +CHECK_C_COMPILER_FLAG(-Wmissing-noreturn SUPPORT_WMISSING_NORETURN) +CHECK_C_COMPILER_FLAG(-Wmissing-format-attribute SUPPORT_WMISSING_FORMAT_ATTRIBUTE) +# GCC 6 specific +CHECK_C_COMPILER_FLAG(-Wnull-dereference SUPPORT_WNULL_DEREFERENCE) +CHECK_C_COMPILER_FLAG(-Wduplicated-cond SUPPORT_WDUPLICATED_COND) +# GCC 7 specific +CHECK_C_COMPILER_FLAG(-Wimplicit-fallthrough SUPPORT_WIMPLICIT_FALLTHROUGH) +# Special check for deprecated declarations, as since OpenSSL 3.0 they +# just poison output for no good reason +CHECK_C_COMPILER_FLAG(-Wdeprecated-declarations SUPPORT_WDEPRECATED_DECLARATIONS) +# Disable -Wsuggest-attribute=format: it is too noisy with FPs around fmt C++ library +CHECK_C_COMPILER_FLAG(-Wsuggest-attribute SUPPORT_WSUGGEST_ATTRIBUTE) + +IF(SUPPORT_WEXTRA) + ADD_COMPILE_OPTIONS("-Wextra") +ENDIF(SUPPORT_WEXTRA) +IF(SUPPORT_WALL) + ADD_COMPILE_OPTIONS("-Wall") +ENDIF(SUPPORT_WALL) +IF(SUPPORT_WPOINTER) + ADD_COMPILE_OPTIONS("-Wpointer-arith") +ENDIF(SUPPORT_WPOINTER) +IF(SUPPORT_WPARAM) + ADD_COMPILE_OPTIONS("-Wno-unused-parameter") +ENDIF(SUPPORT_WPARAM) +IF(SUPPORT_WFUNCTION) + ADD_COMPILE_OPTIONS("-Wno-unused-function") +ENDIF(SUPPORT_WFUNCTION) +IF(SUPPORT_WUNUSED_VAR) + ADD_COMPILE_OPTIONS("-Wunused-variable") +ENDIF(SUPPORT_WUNUSED_VAR) +IF(SUPPORT_WPOINTER_SIGN) + # only valid for C + ADD_COMPILE_OPTIONS($<$<COMPILE_LANGUAGE:C>:-Wno-pointer-sign>) +ENDIF(SUPPORT_WPOINTER_SIGN) +IF(SUPPORT_WSTRICT_PROTOTYPES) + # only valid for C + ADD_COMPILE_OPTIONS($<$<COMPILE_LANGUAGE:C>:-Wstrict-prototypes>) +ENDIF(SUPPORT_WSTRICT_PROTOTYPES) +IF(SUPPORT_WSTRICT_ALIASING) + ADD_COMPILE_OPTIONS("-Wno-strict-aliasing") + ADD_COMPILE_OPTIONS("-fno-strict-aliasing") +ENDIF(SUPPORT_WSTRICT_ALIASING) +#IF(SUPPORT_PEDANTIC_FLAG) +# SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -pedantic") +#ENDIF(SUPPORT_PEDANTIC_FLAG) +IF(SUPPORT_WNULL_DEREFERENCE) + ADD_COMPILE_OPTIONS("-Wnull-dereference") +ENDIF() +IF(SUPPORT_WDUPLICATED_COND) + ADD_COMPILE_OPTIONS("-Wduplicated-cond") +ENDIF() +IF(SUPPORT_WLOGICAL_OP) + ADD_COMPILE_OPTIONS("-Wlogical-op") +ENDIF() +IF(SUPPORT_WNO_UNUSED_CONST) + ADD_COMPILE_OPTIONS("-Wno-unused-const-variable") +ENDIF() +IF(SUPPORT_WSIGN_COMPARE) + ADD_COMPILE_OPTIONS("-Wno-sign-compare") +ENDIF() +IF(SUPPORT_WIMPLICIT_FALLTHROUGH) + ADD_COMPILE_OPTIONS("-Wno-implicit-fallthrough") +ENDIF(SUPPORT_WIMPLICIT_FALLTHROUGH) +IF(SUPPORT_WMISSING_NORETURN) + ADD_COMPILE_OPTIONS("-Wmissing-noreturn") +ENDIF(SUPPORT_WMISSING_NORETURN) +IF(SUPPORT_WMISSING_FORMAT_ATTRIBUTE) + ADD_COMPILE_OPTIONS("-Wmissing-format-attribute") +ENDIF(SUPPORT_WMISSING_FORMAT_ATTRIBUTE) +IF(SUPPORT_WSUGGEST_ATTRIBUTE) + ADD_COMPILE_OPTIONS("-Wno-suggest-attribute=format") +ENDIF() + +IF(SUPPORT_WDEPRECATED_DECLARATIONS) + ADD_COMPILE_OPTIONS("-Wno-deprecated-declarations") +ENDIF() diff --git a/cmake/FindArch.cmake b/cmake/FindArch.cmake new file mode 100644 index 0000000..e172207 --- /dev/null +++ b/cmake/FindArch.cmake @@ -0,0 +1,127 @@ +set(archdetect_c_code " +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) + #if defined(__ARM_ARCH_7__) \\ + || defined(__ARM_ARCH_7A__) \\ + || defined(__ARM_ARCH_7R__) \\ + || defined(__ARM_ARCH_7M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) + #error cmake_ARCH armv7 + #elif defined(__ARM_ARCH_6__) \\ + || defined(__ARM_ARCH_6J__) \\ + || defined(__ARM_ARCH_6T2__) \\ + || defined(__ARM_ARCH_6Z__) \\ + || defined(__ARM_ARCH_6K__) \\ + || defined(__ARM_ARCH_6ZK__) \\ + || defined(__ARM_ARCH_6M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) + #error cmake_ARCH armv6 + #elif defined(__ARM_ARCH_5TEJ__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) + #error cmake_ARCH armv5 + #else + #error cmake_ARCH arm + #endif +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) + #error cmake_ARCH i386 +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) + #error cmake_ARCH x86_64 +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) + #error cmake_ARCH ia64 +#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\ + || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\ + || defined(_M_MPPC) || defined(_M_PPC) + #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) + #error cmake_ARCH ppc64 + #else + #error cmake_ARCH ppc + #endif +#elif defined(__loongarch__) || defined(__loongarch64) + #error cmake_ARCH loongarch64 +#endif + +#error cmake_ARCH unknown +") + +# Set ppc_support to TRUE before including this file or ppc and ppc64 +# will be treated as invalid architectures since they are no longer supported by Apple + +function(target_architecture output_var) + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + # On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set + # First let's normalize the order of the values + + # Note that it's not possible to compile PowerPC applications if you are using + # the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we + # disable it by default + # See this page for more information: + # http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4 + + # Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime. + # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise. + + foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) + if("${osx_arch}" STREQUAL "ppc" AND ppc_support) + set(osx_arch_ppc TRUE) + elseif("${osx_arch}" STREQUAL "i386") + set(osx_arch_i386 TRUE) + elseif("${osx_arch}" STREQUAL "x86_64") + set(osx_arch_x86_64 TRUE) + elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support) + set(osx_arch_ppc64 TRUE) + else() + message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}") + endif() + endforeach() + + # Now add all the architectures in our normalized order + if(osx_arch_ppc) + list(APPEND ARCH ppc) + endif() + + if(osx_arch_i386) + list(APPEND ARCH i386) + endif() + + if(osx_arch_x86_64) + list(APPEND ARCH x86_64) + endif() + + if(osx_arch_ppc64) + list(APPEND ARCH ppc64) + endif() + else() + file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}") + + # Detect the architecture in a rather creative way... + # This compiles a small C program which is a series of ifdefs that selects a + # particular #error preprocessor directive whose message string contains the + # target architecture. The program will always fail to compile (both because + # file is not a valid C program, and obviously because of the presence of the + # #error preprocessor directives... but by exploiting the preprocessor in this + # way, we can detect the correct target architecture even when cross-compiling, + # since the program itself never needs to be run (only the compiler/preprocessor) + try_run( + run_result_unused + compile_result_unused + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/arch.c" + COMPILE_OUTPUT_VARIABLE ARCH + CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} + ) + + # Parse the architecture name from the compiler output + string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}") + + # Get rid of the value marker leaving just the architecture name + string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}") + + # If we are compiling with an unknown architecture this variable should + # already be set to "unknown" but in the case that it's empty (i.e. due + # to a typo in the code), then set it to unknown + if (NOT ARCH) + set(ARCH unknown) + endif() + endif() + + set(${output_var} "${ARCH}" PARENT_SCOPE) +endfunction() diff --git a/cmake/FindRagel.cmake b/cmake/FindRagel.cmake new file mode 100644 index 0000000..f43298e --- /dev/null +++ b/cmake/FindRagel.cmake @@ -0,0 +1,103 @@ +# - Find Ragel executable and provides macros to generate custom build rules +# The module defines the following variables: +# +# RAGEL_EXECUTABLE - path to the ragel program +# RAGEL_VERSION - version of ragel +# RAGEL_FOUND - true if the program was found +# +# If ragel is found, the module defines the macros: +# +# RAGEL_TARGET(<Name> INPUTS <inputs> OUTPUT <output> +# [COMPILE_FLAGS <string>] [DEPENDS <depends>]) +# +# which will create a custom rule to generate a state machine. <RagelInp> is +# the path to a Ragel file. <CodeOutput> is the name of the source file +# generated by ragel. If COMPILE_FLAGS option is specified, the next +# parameter is added in the ragel command line. +# +# The macro defines a set of variables: +# RAGEL_${Name}_DEFINED - true is the macro ran successfully +# RAGEL_${Name}_INPUT - The input source file, an alias for <RagelInp> +# RAGEL_${Name}_OUTPUT_SOURCE - The source file generated by ragel +# RAGEL_${Name}_OUTPUT_HEADER - The header file generated by ragel +# RAGEL_${Name}_OUTPUTS - The sources files generated by ragel +# RAGEL_${Name}_COMPILE_FLAGS - Options used in the ragel command line +# +# ==================================================================== +# Example: +# +# find_package(RAGEL) # or e.g.: find_package(RAGEL 6.6 REQUIRED) +# RAGEL_TARGET(MyMachine machine.rl ${CMAKE_CURRENT_BINARY_DIR}/machine.cc) +# add_executable(Foo main.cc ${RAGEL_MyMachine_OUTPUTS}) +# ==================================================================== + +# 2014-02-09, Georg Sauthoff <mail@georg.so> +# +# I don't think that these few lines are even copyrightable material, +# but I am fine with using the BSD/MIT/GPL license on it ... +# +# I've used following references: +# http://www.cmake.org/cmake/help/v2.8.12/cmake.html +# /usr/share/cmake/Modules/FindFLEX.cmake +# /usr/share/cmake/Modules/FindBISON.cmake + +find_program(RAGEL_EXECUTABLE NAMES ragel DOC "path to the ragel executable") +mark_as_advanced(RAGEL_EXECUTABLE) + +if(RAGEL_EXECUTABLE) + + execute_process(COMMAND ${RAGEL_EXECUTABLE} --version + OUTPUT_VARIABLE RAGEL_version_output + ERROR_VARIABLE RAGEL_version_error + RESULT_VARIABLE RAGEL_version_result + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(${RAGEL_version_result} EQUAL 0) + string(REGEX REPLACE "^Ragel State Machine Compiler version ([^ ]+) .*$" + "\\1" + RAGEL_VERSION "${RAGEL_version_output}") + else() + message(SEND_ERROR + "Command \"${RAGEL_EXECUTABLE} --version\" failed with output: +${RAGEL_version_error}") + endif() + + #============================================================ + # RAGEL_TARGET (public macro) + #============================================================ + # + macro(RAGEL_TARGET Name) + CMAKE_PARSE_ARGUMENTS(RAGEL "" "OUTPUT" + "INPUTS;DEPENDS;COMPILE_FLAGS" ${ARGN}) + + file(RELATIVE_PATH RAGEL_OUTPUT_RELATIVE "${CMAKE_CURRENT_BINARY_DIR}" + "${RAGEL_OUTPUT}") + file(RELATIVE_PATH RAGEL_INPUTS_RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + "${RAGEL_INPUTS}") + + add_custom_command(OUTPUT ${RAGEL_OUTPUT} + COMMAND ${RAGEL_EXECUTABLE} + ARGS ${RAGEL_COMPILE_FLAGS} + -o${RAGEL_OUTPUT} ${RAGEL_INPUTS} + DEPENDS ${RAGEL_INPUTS} ${RAGEL_DEPENDS} + COMMENT + "[RAGEL][${Name}] Compiling state machine with Ragel ${RAGEL_VERSION} -> ${RAGEL_OUTPUT}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + get_filename_component(src_target ${RAGEL_INPUTS} NAME_WE) + add_custom_target(ragel_${src_target} DEPENDS ${RAGEL_OUTPUT}) + set_source_files_properties(${RAGEL_OUTPUT} PROPERTIES GENERATED TRUE) + + set(RAGEL_${Name}_DEFINED TRUE) + set(RAGEL_${Name}_OUTPUTS ${RAGEL_OUTPUT}) + set(RAGEL_${Name}_INPUT ${RAGEL_INPUTS}) + set(RAGEL_${Name}_COMPILE_FLAGS ${RAGEL_COMPILE_FLAGS}) + endmacro() + +endif() + +# use this include when module file is located under /usr/share/cmake/Modules +#include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +# use this include when module file is located in build tree +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(RAGEL REQUIRED_VARS RAGEL_EXECUTABLE + VERSION_VAR RAGEL_VERSION) diff --git a/cmake/Hyperscan.cmake b/cmake/Hyperscan.cmake new file mode 100644 index 0000000..dc19f49 --- /dev/null +++ b/cmake/Hyperscan.cmake @@ -0,0 +1,8 @@ +option (ENABLE_HYPERSCAN "Enable hyperscan for fast regexp processing [default: OFF]" OFF) + +if (ENABLE_HYPERSCAN MATCHES "ON") + ProcessPackage (HYPERSCAN LIBRARY hs INCLUDE hs.h INCLUDE_SUFFIXES + hs include/hs + ROOT ${HYPERSCAN_ROOT_DIR} MODULES libhs) + set (WITH_HYPERSCAN 1) +endif () diff --git a/cmake/OSDep.cmake b/cmake/OSDep.cmake new file mode 100644 index 0000000..78f6549 --- /dev/null +++ b/cmake/OSDep.cmake @@ -0,0 +1,65 @@ +# 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") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 10000 -image_base 100000000") + 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 diff --git a/cmake/Openblas.cmake b/cmake/Openblas.cmake new file mode 100644 index 0000000..da62363 --- /dev/null +++ b/cmake/Openblas.cmake @@ -0,0 +1,119 @@ +option (ENABLE_BLAS "Enable openblas for fast neural network processing [default: OFF]" OFF) + +IF(ENABLE_BLAS MATCHES "ON") + ProcessPackage(BLAS OPTIONAL_INCLUDE LIBRARY openblas blas blis + INCLUDE cblas.h INCLUDE_SUFFIXES include/openblas + include/blas + include/blis + ROOT ${BLAS_ROOT_DIR} + LIB_OUTPUT BLAS_REQUIRED_LIBRARIES) + ProcessPackage(BLAS_LAPACK OPTIONAL_INCLUDE LIBRARY lapack + INCLUDE cblas.h INCLUDE_SUFFIXES include/openblas + include/blas + include/blis + ROOT ${BLAS_ROOT_DIR} + LIB_OUTPUT BLAS_REQUIRED_LIBRARIES) +ENDIF() + +IF(WITH_BLAS) + MESSAGE(STATUS "Use openblas to accelerate kann") + IF(NOT BLAS_INCLUDE) + FIND_FILE(HAVE_CBLAS_H HINTS "${RSPAMD_SEARCH_PATH}" + NAMES cblas.h + DOC "Path to cblas.h header") + IF(NOT HAVE_CBLAS_H) + MESSAGE(STATUS "Blas header cblas.h has not been found, use internal workaround") + ELSE() + SET(HAVE_CBLAS_H 1) + ENDIF() + ELSE() + SET(HAVE_CBLAS_H 1) + ENDIF() + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sgemm.c" " +#include <stddef.h> +enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102 }; +enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112 }; +extern void cblas_sgemm(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TA, + const enum CBLAS_TRANSPOSE TB, + const int M, const int N, const int K, + const float alpha, const float *A, const int lda, + const float *B, const int ldb, const float beta, + float *C, const int ldc); +int main(int argc, char **argv) +{ + cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0, NULL, 0); + return 0; +} +") + try_compile(HAVE_CBLAS_SGEMM + ${CMAKE_CURRENT_BINARY_DIR} + "${CMAKE_CURRENT_BINARY_DIR}/sgemm.c" + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + LINK_LIBRARIES ${BLAS_REQUIRED_LIBRARIES} + OUTPUT_VARIABLE SGEMM_ERR) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/saxpy.c" " +#include <stddef.h> +extern void cblas_saxpy(const int __N, + const float __alpha, const float *__X, const int __incX, float *__Y, const int __incY); +int main(int argc, char **argv) +{ + cblas_saxpy(0, 0, NULL, 0, NULL, 0); + return 0; +} +") + try_compile(HAVE_CBLAS_SAXPY + ${CMAKE_CURRENT_BINARY_DIR} + "${CMAKE_CURRENT_BINARY_DIR}/saxpy.c" + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + LINK_LIBRARIES ${BLAS_REQUIRED_LIBRARIES} + OUTPUT_VARIABLE SAXPY_ERR) + + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/openblas_set_num_threads.c" " +#include <stddef.h> +extern void openblas_set_num_threads(int num_threads); +int main(int argc, char **argv) +{ + openblas_set_num_threads(1); + return 0; +} +") + try_compile(HAVE_OPENBLAS_SET_NUM_THREADS + ${CMAKE_CURRENT_BINARY_DIR} + "${CMAKE_CURRENT_BINARY_DIR}/openblas_set_num_threads.c" + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + LINK_LIBRARIES ${BLAS_REQUIRED_LIBRARIES} + OUTPUT_VARIABLE OPENBLAS_SET_NUM_THREADS_ERR) + + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/bli_thread_set_num_threads.c" " +#include <stddef.h> +extern void bli_thread_set_num_threads(int num_threads); +int main(int argc, char **argv) +{ + bli_thread_set_num_threads(1); + return 0; +} +") + try_compile(HAVE_BLI_THREAD_SET_NUM_THREADS + ${CMAKE_CURRENT_BINARY_DIR} + "${CMAKE_CURRENT_BINARY_DIR}/bli_thread_set_num_threads.c" + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + LINK_LIBRARIES ${BLAS_REQUIRED_LIBRARIES} + OUTPUT_VARIABLE BLI_SET_NUM_THREADS_ERR) + # Cmake is just brain damaged + #CHECK_LIBRARY_EXISTS(${BLAS_REQUIRED_LIBRARIES} cblas_sgemm "" HAVE_CBLAS_SGEMM) + if(HAVE_CBLAS_SGEMM) + MESSAGE(STATUS "Blas has CBLAS sgemm") + else() + MESSAGE(STATUS "Blas has -NOT- CBLAS sgemm, use internal workaround: ${SGEMM_ERR}") + endif() + if(HAVE_CBLAS_SAXPY) + MESSAGE(STATUS "Blas has CBLAS saxpy") + else() + MESSAGE(STATUS "Blas has -NOT- CBLAS saxpy, use internal workaround: ${SAXPY_ERR}") + endif() + SET(HAVE_CBLAS 1) +ENDIF(WITH_BLAS) + +CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/blas-config.h.in" "${CMAKE_BINARY_DIR}/src/blas-config.h")
\ No newline at end of file diff --git a/cmake/PVS-Studio.cmake b/cmake/PVS-Studio.cmake new file mode 100644 index 0000000..6001f33 --- /dev/null +++ b/cmake/PVS-Studio.cmake @@ -0,0 +1,547 @@ +# 2006-2008 (c) Viva64.com Team +# 2008-2018 (c) OOO "Program Verification Systems" +# +# Version 12 +# Apache 2.0 license + +cmake_minimum_required(VERSION 2.8.12) +cmake_policy(SET CMP0054 NEW) + +if (PVS_STUDIO_AS_SCRIPT) + # This code runs at build time. + # It executes pvs-studio-analyzer and propagates its return value. + + set(in_cl_params FALSE) + set(additional_args) + + foreach (arg ${PVS_STUDIO_COMMAND}) + if (NOT in_cl_params) + if ("${arg}" STREQUAL "--cl-params") + set(in_cl_params TRUE) + endif () + else () + # A workaround for macOS frameworks (e.g. QtWidgets.framework) + # You can test this workaround on this project: https://github.com/easyaspi314/MidiEditor/tree/gba + if (APPLE AND "${arg}" MATCHES "^-I(.*)\\.framework$") + STRING(REGEX REPLACE "^-I(.*)\\.framework$" "\\1.framework" framework "${arg}") + if (IS_ABSOLUTE "${framework}") + get_filename_component(framework "${framework}" DIRECTORY) + list(APPEND additional_args "-iframework") + list(APPEND additional_args "${framework}") + endif () + endif () + endif () + endforeach () + + execute_process(COMMAND ${PVS_STUDIO_COMMAND} ${additional_args} + ERROR_VARIABLE error + RESULT_VARIABLE result) + + set(stderr_type "") + + if (result) + set(stderr_type FATAL_ERROR) + endif () + + if (result OR error) + message(${stderr_type} "${error}") + endif () + + return() +endif () + +if(__PVS_STUDIO_INCLUDED) + return() +endif() +set(__PVS_STUDIO_INCLUDED TRUE) + +set(PVS_STUDIO_SCRIPT "${CMAKE_CURRENT_LIST_FILE}") + +function (pvs_studio_log TEXT) + if (PVS_STUDIO_DEBUG) + message("PVS-Studio: ${TEXT}") + endif () +endfunction () + +function (pvs_studio_relative_path VAR ROOT FILEPATH) + set("${VAR}" "${FILEPATH}" PARENT_SCOPE) + if ("${FILEPATH}" MATCHES "^/.*$" OR "${FILEPATH}" MATCHES "^.:/.*$") + file(RELATIVE_PATH RPATH "${ROOT}" "${FILEPATH}") + if (NOT "${RPATH}" MATCHES "^\\.\\..*$") + set("${VAR}" "${RPATH}" PARENT_SCOPE) + endif () + endif () +endfunction () + +function (pvs_studio_join_path VAR DIR1 DIR2) + if ("${DIR2}" MATCHES "^(/|~|.:/).*$" OR "${DIR1}" STREQUAL "") + set("${VAR}" "${DIR2}" PARENT_SCOPE) + else () + set("${VAR}" "${DIR1}/${DIR2}" PARENT_SCOPE) + endif () +endfunction () + +macro (pvs_studio_append_flags_from_property CXX C DIR PREFIX) + if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND") + foreach (PROP ${PROPERTY}) + pvs_studio_join_path(PROP "${DIR}" "${PROP}") + + if (APPLE AND "${PREFIX}" STREQUAL "-I" AND IS_ABSOLUTE "${PROP}" AND "${PROP}" MATCHES "\\.framework$") + get_filename_component(FRAMEWORK "${PROP}" DIRECTORY) + list(APPEND "${CXX}" "-iframework") + list(APPEND "${CXX}" "${FRAMEWORK}") + list(APPEND "${C}" "-iframework") + list(APPEND "${C}" "${FRAMEWORK}") + pvs_studio_log("framework: ${FRAMEWORK}") + elseif (NOT "${PROP}" STREQUAL "") + list(APPEND "${CXX}" "${PREFIX}${PROP}") + list(APPEND "${C}" "${PREFIX}${PROP}") + endif() + endforeach () + endif () +endmacro () + +macro (pvs_studio_append_standard_flag FLAGS STANDARD) + if ("${STANDARD}" MATCHES "^(99|11|14|17)$") + if ("${PVS_STUDIO_PREPROCESSOR}" MATCHES "gcc|clang") + list(APPEND "${FLAGS}" "-std=c++${STANDARD}") + endif () + endif () +endmacro () + +function (pvs_studio_set_directory_flags DIRECTORY CXX C) + set(CXX_FLAGS "${${CXX}}") + set(C_FLAGS "${${C}}") + + get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" INCLUDE_DIRECTORIES) + pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "${DIRECTORY}" "-I") + + get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" COMPILE_DEFINITIONS) + pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "" "-D") + + set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE) + set("${C}" "${C_FLAGS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_set_target_flags TARGET CXX C) + set(CXX_FLAGS "${${CXX}}") + set(C_FLAGS "${${C}}") + + set(prop_incdirs "$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>") + list(APPEND CXX_FLAGS "$<$<BOOL:${prop_incdirs}>:-I$<JOIN:${prop_incdirs},$<SEMICOLON>-I>>") + list(APPEND C_FLAGS "$<$<BOOL:${prop_incdirs}>:-I$<JOIN:${prop_incdirs},$<SEMICOLON>-I>>") + + set(prop_compdefs "$<TARGET_PROPERTY:${TARGET},COMPILE_DEFINITIONS>") + list(APPEND CXX_FLAGS "$<$<BOOL:${prop_compdefs}>:-D$<JOIN:${prop_compdefs},$<SEMICOLON>-D>>") + list(APPEND C_FLAGS "$<$<BOOL:${prop_compdefs}>:-D$<JOIN:${prop_compdefs},$<SEMICOLON>-D>>") + + set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE) + set("${C}" "${C_FLAGS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_set_source_file_flags SOURCE) + set(LANGUAGE "") + + string(TOLOWER "${SOURCE}" SOURCE_LOWER) + if ("${LANGUAGE}" STREQUAL "" AND "${SOURCE_LOWER}" MATCHES "^.*\\.(c|cpp|cc|cx|cxx|cp|c\\+\\+)$") + if ("${SOURCE}" MATCHES "^.*\\.c$") + set(LANGUAGE C) + else () + set(LANGUAGE CXX) + endif () + endif () + + if ("${LANGUAGE}" STREQUAL "C") + set(CL_PARAMS ${PVS_STUDIO_C_FLAGS} ${PVS_STUDIO_TARGET_C_FLAGS} -DPVS_STUDIO) + elseif ("${LANGUAGE}" STREQUAL "CXX") + set(CL_PARAMS ${PVS_STUDIO_CXX_FLAGS} ${PVS_STUDIO_TARGET_CXX_FLAGS} -DPVS_STUDIO) + endif () + + set(PVS_STUDIO_LANGUAGE "${LANGUAGE}" PARENT_SCOPE) + set(PVS_STUDIO_CL_PARAMS "${CL_PARAMS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_analyze_file SOURCE SOURCE_DIR BINARY_DIR) + set(PLOGS ${PVS_STUDIO_PLOGS}) + pvs_studio_set_source_file_flags("${SOURCE}") + + get_filename_component(SOURCE "${SOURCE}" REALPATH) + + get_source_file_property(PROPERTY "${SOURCE}" HEADER_FILE_ONLY) + if (PROPERTY) + return() + endif () + + pvs_studio_relative_path(SOURCE_RELATIVE "${SOURCE_DIR}" "${SOURCE}") + pvs_studio_join_path(SOURCE "${SOURCE_DIR}" "${SOURCE}") + + set(LOG "${BINARY_DIR}/PVS-Studio/${SOURCE_RELATIVE}.plog") + get_filename_component(LOG "${LOG}" REALPATH) + get_filename_component(PARENT_DIR "${LOG}" DIRECTORY) + + if (EXISTS "${SOURCE}" AND NOT TARGET "${LOG}" AND NOT "${PVS_STUDIO_LANGUAGE}" STREQUAL "") + # A workaround to support implicit dependencies for ninja generators. + set(depPvsArg) + set(depCommandArg) + if (CMAKE_VERSION VERSION_GREATER 3.6 AND "${CMAKE_GENERATOR}" STREQUAL "Ninja") + pvs_studio_relative_path(relLog "${CMAKE_BINARY_DIR}" "${LOG}") + set(depPvsArg --dep-file "${LOG}.d" --dep-file-target "${relLog}") + set(depCommandArg DEPFILE "${LOG}.d") + endif () + + # https://public.kitware.com/Bug/print_bug_page.php?bug_id=14353 + # https://public.kitware.com/Bug/file/5436/expand_command.cmake + # + # It is a workaround to expand generator expressions. + set(cmdline "${PVS_STUDIO_BIN}" analyze + --output-file "${LOG}" + --source-file "${SOURCE}" + ${depPvsArg} + ${PVS_STUDIO_ARGS} + --cl-params "${PVS_STUDIO_CL_PARAMS}" "${SOURCE}") + + string(REPLACE ";" "$<SEMICOLON>" cmdline "${cmdline}") + set(pvscmd "${CMAKE_COMMAND}" + -D PVS_STUDIO_AS_SCRIPT=TRUE + -D "PVS_STUDIO_COMMAND=${cmdline}" + -P "${PVS_STUDIO_SCRIPT}" + ) + + add_custom_command(OUTPUT "${LOG}" + COMMAND "${CMAKE_COMMAND}" -E make_directory "${PARENT_DIR}" + COMMAND "${CMAKE_COMMAND}" -E remove_directory "${LOG}" + COMMAND ${pvscmd} + WORKING_DIRECTORY "${BINARY_DIR}" + DEPENDS "${SOURCE}" "${PVS_STUDIO_CONFIG}" + IMPLICIT_DEPENDS "${PVS_STUDIO_LANGUAGE}" "${SOURCE}" + ${depCommandArg} + VERBATIM + COMMENT "Analyzing ${PVS_STUDIO_LANGUAGE} file ${SOURCE_RELATIVE}") + list(APPEND PLOGS "${LOG}") + endif () + set(PVS_STUDIO_PLOGS "${PLOGS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_analyze_target TARGET DIR) + set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}") + set(PVS_STUDIO_TARGET_CXX_FLAGS "") + set(PVS_STUDIO_TARGET_C_FLAGS "") + + get_target_property(PROPERTY "${TARGET}" SOURCES) + pvs_studio_relative_path(BINARY_DIR "${CMAKE_SOURCE_DIR}" "${DIR}") + if ("${BINARY_DIR}" MATCHES "^/.*$") + pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "PVS-Studio/__${BINARY_DIR}") + else () + pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "${BINARY_DIR}") + endif () + + file(MAKE_DIRECTORY "${BINARY_DIR}") + + pvs_studio_set_directory_flags("${DIR}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS) + pvs_studio_set_target_flags("${TARGET}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS) + + if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND") + foreach (SOURCE ${PROPERTY}) + pvs_studio_join_path(SOURCE "${DIR}" "${SOURCE}") + pvs_studio_analyze_file("${SOURCE}" "${DIR}" "${BINARY_DIR}") + endforeach () + endif () + + set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}" PARENT_SCOPE) +endfunction () + +set(PVS_STUDIO_RECURSIVE_TARGETS) +set(PVS_STUDIO_RECURSIVE_TARGETS_NEW) + +macro(pvs_studio_get_recursive_targets TARGET) + get_target_property(libs "${TARGET}" LINK_LIBRARIES) + foreach (lib IN LISTS libs) + list(FIND PVS_STUDIO_RECURSIVE_TARGETS "${lib}" index) + if (TARGET "${lib}" AND "${index}" STREQUAL -1) + get_target_property(target_type "${lib}" TYPE) + if (NOT "${target_type}" STREQUAL "INTERFACE_LIBRARY") + list(APPEND PVS_STUDIO_RECURSIVE_TARGETS "${lib}") + list(APPEND PVS_STUDIO_RECURSIVE_TARGETS_NEW "${lib}") + pvs_studio_get_recursive_targets("${lib}") + endif () + endif () + endforeach () +endmacro() + +option(PVS_STUDIO_DISABLE OFF "Disable PVS-Studio targets") +option(PVS_STUDIO_DEBUG OFF "Add debug info") + +# pvs_studio_add_target +# Target options: +# ALL add PVS-Studio target to default build (default: off) +# TARGET target name of analysis target (default: pvs) +# ANALYZE targets... targets to analyze +# RECURSIVE analyze target's dependencies (requires CMake 3.5+) +# COMPILE_COMMANDS use compile_commands.json instead of targets (specified by the 'ANALYZE' option) to determine files for analysis +# (set CMAKE_EXPORT_COMPILE_COMMANDS, available only for Makefile and Ninja generators) +# +# Output options: +# OUTPUT prints report to stdout +# LOG path path to report (default: ${CMAKE_CURRENT_BINARY_DIR}/PVS-Studio.log) +# FORMAT format format of report +# MODE mode analyzers/levels filter (default: GA:1,2) +# HIDE_HELP do not print help message +# +# Analyzer options: +# PLATFORM name linux32/linux64 (default: linux64) +# PREPROCESSOR name preprocessor type: gcc/clang (default: auto detected) +# LICENSE path path to PVS-Studio.lic (default: ~/.config/PVS-Studio/PVS-Studio.lic) +# CONFIG path path to PVS-Studio.cfg +# CFG_TEXT text embedded PVS-Studio.cfg +# KEEP_COMBINED_PLOG do not delete combined plog file *.pvs.raw for further processing with plog-converter +# +# Misc options: +# DEPENDS targets.. additional target dependencies +# SOURCES path... list of source files to analyze +# BIN path path to pvs-studio-analyzer (Unix) or CompilerCommandsAnalyzer.exe (Windows) +# CONVERTER path path to plog-converter (Unix) or HtmlGenerator.exe (Windows) +# C_FLAGS flags... additional C_FLAGS +# CXX_FLAGS flags... additional CXX_FLAGS +# ARGS args... additional pvs-studio-analyzer/CompilerCommandsAnalyzer.exe flags +function (pvs_studio_add_target) + macro (default VAR VALUE) + if ("${${VAR}}" STREQUAL "") + set("${VAR}" "${VALUE}") + endif () + endmacro () + + set(PVS_STUDIO_SUPPORTED_PREPROCESSORS "gcc|clang|visualcpp") + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(DEFAULT_PREPROCESSOR "clang") + elseif (MSVC) + set(DEFAULT_PREPROCESSOR "visualcpp") + else () + set(DEFAULT_PREPROCESSOR "gcc") + endif () + + set(OPTIONAL OUTPUT ALL RECURSIVE HIDE_HELP KEEP_COMBINED_PLOG COMPILE_COMMANDS) + set(SINGLE LICENSE CONFIG TARGET LOG FORMAT BIN CONVERTER PLATFORM PREPROCESSOR CFG_TEXT) + set(MULTI SOURCES C_FLAGS CXX_FLAGS ARGS DEPENDS ANALYZE MODE) + cmake_parse_arguments(PVS_STUDIO "${OPTIONAL}" "${SINGLE}" "${MULTI}" ${ARGN}) + + if ("${PVS_STUDIO_CONFIG}" STREQUAL "" OR NOT "${PVS_STUDIO_CFG_TEXT}" STREQUAL "") + set(PVS_STUDIO_EMPTY_CONFIG ON) + else () + set(PVS_STUDIO_EMPTY_CONFIG OFF) + endif () + + default(PVS_STUDIO_CFG_TEXT "analysis-mode=31") + default(PVS_STUDIO_CONFIG "${CMAKE_BINARY_DIR}/PVS-Studio.cfg") + default(PVS_STUDIO_C_FLAGS "") + default(PVS_STUDIO_CXX_FLAGS "") + default(PVS_STUDIO_TARGET "pvs") + default(PVS_STUDIO_LOG "PVS-Studio.log") + + set(PATHS) + if (WIN32) + set(ROOT "PROGRAMFILES(X86)") + set(ROOT "$ENV{${ROOT}}/PVS-Studio") + string(REPLACE \\ / ROOT "${ROOT}") + + if (EXISTS "${ROOT}") + set(PATHS "${ROOT}") + endif () + + default(PVS_STUDIO_BIN "CompilerCommandsAnalyzer.exe") + default(PVS_STUDIO_CONVERTER "HtmlGenerator.exe") + else () + default(PVS_STUDIO_BIN "pvs-studio-analyzer") + default(PVS_STUDIO_CONVERTER "plog-converter") + endif () + + find_program(PVS_STUDIO_BIN_PATH "${PVS_STUDIO_BIN}" ${PATHS}) + set(PVS_STUDIO_BIN "${PVS_STUDIO_BIN_PATH}") + + if (NOT EXISTS "${PVS_STUDIO_BIN}") + message(FATAL_ERROR "pvs-studio-analyzer is not found") + endif () + + find_program(PVS_STUDIO_CONVERTER_PATH "${PVS_STUDIO_CONVERTER}" ${PATHS}) + set(PVS_STUDIO_CONVERTER "${PVS_STUDIO_CONVERTER_PATH}") + + if (NOT EXISTS "${PVS_STUDIO_CONVERTER}") + message(FATAL_ERROR "plog-converter is not found") + endif () + + default(PVS_STUDIO_MODE "GA:1,2") + default(PVS_STUDIO_PREPROCESSOR "${DEFAULT_PREPROCESSOR}") + if (WIN32) + default(PVS_STUDIO_PLATFORM "x64") + else () + default(PVS_STUDIO_PLATFORM "linux64") + endif () + + string(REPLACE ";" "+" PVS_STUDIO_MODE "${PVS_STUDIO_MODE}") + + if (PVS_STUDIO_EMPTY_CONFIG) + set(PVS_STUDIO_CONFIG_COMMAND "${CMAKE_COMMAND}" -E echo "${PVS_STUDIO_CFG_TEXT}" > "${PVS_STUDIO_CONFIG}") + else () + set(PVS_STUDIO_CONFIG_COMMAND "${CMAKE_COMMAND}" -E touch "${PVS_STUDIO_CONFIG}") + endif () + + add_custom_command(OUTPUT "${PVS_STUDIO_CONFIG}" + COMMAND ${PVS_STUDIO_CONFIG_COMMAND} + WORKING_DIRECTORY "${BINARY_DIR}" + COMMENT "Generating PVS-Studio.cfg") + + if (NOT "${PVS_STUDIO_PREPROCESSOR}" MATCHES "^${PVS_STUDIO_SUPPORTED_PREPROCESSORS}$") + message(FATAL_ERROR "Preprocessor ${PVS_STUDIO_PREPROCESSOR} isn't supported. Available options: ${PVS_STUDIO_SUPPORTED_PREPROCESSORS}.") + endif () + + pvs_studio_append_standard_flag(PVS_STUDIO_CXX_FLAGS "${CMAKE_CXX_STANDARD}") + pvs_studio_set_directory_flags("${CMAKE_CURRENT_SOURCE_DIR}" PVS_STUDIO_CXX_FLAGS PVS_STUDIO_C_FLAGS) + + if (NOT "${PVS_STUDIO_LICENSE}" STREQUAL "") + pvs_studio_join_path(PVS_STUDIO_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}" "${PVS_STUDIO_LICENSE}") + list(APPEND PVS_STUDIO_ARGS --lic-file "${PVS_STUDIO_LICENSE}") + endif () + + list(APPEND PVS_STUDIO_ARGS --cfg "${PVS_STUDIO_CONFIG}" + --platform "${PVS_STUDIO_PLATFORM}" + --preprocessor "${PVS_STUDIO_PREPROCESSOR}") + + if (NOT "${CMAKE_CXX_COMPILER}" STREQUAL "") + list(APPEND PVS_STUDIO_ARGS --cxx "${CMAKE_CXX_COMPILER}") + endif () + + if (NOT "${CMAKE_C_COMPILER}" STREQUAL "") + list(APPEND PVS_STUDIO_ARGS --cc "${CMAKE_C_COMPILER}") + endif () + + set(PVS_STUDIO_PLOGS "") + + set(PVS_STUDIO_RECURSIVE_TARGETS_NEW) + if (${PVS_STUDIO_RECURSIVE}) + foreach (TARGET IN LISTS PVS_STUDIO_ANALYZE) + list(APPEND PVS_STUDIO_RECURSIVE_TARGETS_NEW "${TARGET}") + pvs_studio_get_recursive_targets("${TARGET}") + endforeach () + endif () + + set(inc_path) + + foreach (TARGET ${PVS_STUDIO_ANALYZE}) + set(DIR "${CMAKE_CURRENT_SOURCE_DIR}") + string(FIND "${TARGET}" ":" DELIM) + if ("${DELIM}" GREATER "-1") + math(EXPR DELIMI "${DELIM}+1") + string(SUBSTRING "${TARGET}" "${DELIMI}" "-1" DIR) + string(SUBSTRING "${TARGET}" "0" "${DELIM}" TARGET) + pvs_studio_join_path(DIR "${CMAKE_CURRENT_SOURCE_DIR}" "${DIR}") + else () + get_target_property(TARGET_SOURCE_DIR "${TARGET}" SOURCE_DIR) + if (EXISTS "${TARGET_SOURCE_DIR}") + set(DIR "${TARGET_SOURCE_DIR}") + endif () + endif () + pvs_studio_analyze_target("${TARGET}" "${DIR}") + list(APPEND PVS_STUDIO_DEPENDS "${TARGET}") + + if ("${inc_path}" STREQUAL "") + set(inc_path "$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>") + else () + set(inc_path "${inc_path}$<SEMICOLON>$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>") + endif () + endforeach () + + foreach (TARGET ${PVS_STUDIO_RECURSIVE_TARGETS_NEW}) + set(DIR "${CMAKE_CURRENT_SOURCE_DIR}") + get_target_property(TARGET_SOURCE_DIR "${TARGET}" SOURCE_DIR) + if (EXISTS "${TARGET_SOURCE_DIR}") + set(DIR "${TARGET_SOURCE_DIR}") + endif () + pvs_studio_analyze_target("${TARGET}" "${DIR}") + list(APPEND PVS_STUDIO_DEPENDS "${TARGET}") + endforeach () + + set(PVS_STUDIO_TARGET_CXX_FLAGS "") + set(PVS_STUDIO_TARGET_C_FLAGS "") + foreach (SOURCE ${PVS_STUDIO_SOURCES}) + pvs_studio_analyze_file("${SOURCE}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") + endforeach () + + if (PVS_STUDIO_COMPILE_COMMANDS) + set(COMPILE_COMMANDS_LOG "${PVS_STUDIO_LOG}.pvs.analyzer.raw") + if (NOT CMAKE_EXPORT_COMPILE_COMMANDS) + message(FATAL_ERROR "You should set CMAKE_EXPORT_COMPILE_COMMANDS to TRUE") + endif () + add_custom_command( + OUTPUT "${COMPILE_COMMANDS_LOG}" + COMMAND "${PVS_STUDIO_BIN}" analyze -i + --output-file "${COMPILE_COMMANDS_LOG}.always" + ${PVS_STUDIO_ARGS} + COMMENT "Analyzing with PVS-Studio" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + DEPENDS "${PVS_STUDIO_CONFIG}" + ) + list(APPEND PVS_STUDIO_PLOGS_LOGS "${COMPILE_COMMANDS_LOG}.always") + list(APPEND PVS_STUDIO_PLOGS_DEPENDENCIES "${COMPILE_COMMANDS_LOG}") + endif () + + pvs_studio_relative_path(LOG_RELATIVE "${CMAKE_BINARY_DIR}" "${PVS_STUDIO_LOG}") + if (PVS_STUDIO_PLOGS OR PVS_STUDIO_COMPILE_COMMANDS) + if (WIN32) + string(REPLACE / \\ PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}") + endif () + if (WIN32) + set(COMMANDS COMMAND type ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_LOGS} > "${PVS_STUDIO_LOG}" 2>nul) + else () + set(COMMANDS COMMAND cat ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_LOGS} > "${PVS_STUDIO_LOG}") + endif () + set(COMMENT "Generating ${LOG_RELATIVE}") + if (NOT "${PVS_STUDIO_FORMAT}" STREQUAL "" OR PVS_STUDIO_OUTPUT) + if ("${PVS_STUDIO_FORMAT}" STREQUAL "") + set(PVS_STUDIO_FORMAT "errorfile") + endif () + list(APPEND COMMANDS + COMMAND "${CMAKE_COMMAND}" -E remove -f "${PVS_STUDIO_LOG}.pvs.raw" + COMMAND "${CMAKE_COMMAND}" -E rename "${PVS_STUDIO_LOG}" "${PVS_STUDIO_LOG}.pvs.raw" + COMMAND "${PVS_STUDIO_CONVERTER}" -t "${PVS_STUDIO_FORMAT}" "${PVS_STUDIO_LOG}.pvs.raw" -o "${PVS_STUDIO_LOG}" -a "${PVS_STUDIO_MODE}" + ) + if(NOT PVS_STUDIO_KEEP_COMBINED_PLOG) + list(APPEND COMMANDS COMMAND "${CMAKE_COMMAND}" -E remove -f "${PVS_STUDIO_LOG}.pvs.raw") + endif() + endif () + else () + set(COMMANDS COMMAND "${CMAKE_COMMAND}" -E touch "${PVS_STUDIO_LOG}") + set(COMMENT "Generating ${LOG_RELATIVE}: no sources found") + endif () + + if (WIN32) + string(REPLACE / \\ PVS_STUDIO_LOG "${PVS_STUDIO_LOG}") + endif () + + add_custom_command(OUTPUT "${PVS_STUDIO_LOG}" + ${COMMANDS} + COMMENT "${COMMENT}" + DEPENDS ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_DEPENDENCIES} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") + + if (PVS_STUDIO_ALL) + set(ALL "ALL") + else () + set(ALL "") + endif () + + if (PVS_STUDIO_OUTPUT) + if (PVS_STUDIO_HIDE_HELP AND NOT WIN32) + set(COMMANDS COMMAND grep -v " error: Help:" ${PVS_STUDIO_LOG} 1>&2 || exit 0) + elseif (WIN32) + set(COMMANDS COMMAND type "${PVS_STUDIO_LOG}" 1>&2) + else () + set(COMMANDS COMMAND cat "${PVS_STUDIO_LOG}" 1>&2) + endif() + else () + set(COMMANDS "") + endif () + + add_custom_target("${PVS_STUDIO_TARGET}" ${ALL} ${COMMANDS} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" DEPENDS ${PVS_STUDIO_DEPENDS} "${PVS_STUDIO_LOG}") + + # A workaround to add implicit dependencies of source files from include directories + set_target_properties("${PVS_STUDIO_TARGET}" PROPERTIES INCLUDE_DIRECTORIES "${inc_path}") +endfunction ()
\ No newline at end of file diff --git a/cmake/Paths.cmake b/cmake/Paths.cmake new file mode 100644 index 0000000..858cdc2 --- /dev/null +++ b/cmake/Paths.cmake @@ -0,0 +1,72 @@ +# Now CMAKE_INSTALL_PREFIX is a base prefix for everything +# CONFDIR - for configuration +# LOCAL_CONFDIR - for local configuration +# MANDIR - for manual pages +# RUNDIR - for runtime files +# DBDIR - for static files +# LOGDIR - for log files + +IF(NOT CONFDIR) + SET(CONFDIR "${CMAKE_INSTALL_PREFIX}/etc/rspamd") +ENDIF(NOT CONFDIR) + +IF(NOT LOCAL_CONFDIR) + SET(LOCAL_CONFDIR "${CONFDIR}") +ENDIF(NOT LOCAL_CONFDIR) + +IF(NOT MANDIR) + SET(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man") +ENDIF(NOT MANDIR) + +IF(NOT RUNDIR) + SET(RUNDIR "/var/run/rspamd") +ENDIF(NOT RUNDIR) + +IF(NOT DBDIR) + SET(DBDIR "/var/lib/rspamd") +ENDIF(NOT DBDIR) + +IF(NOT LOGDIR) + SET(LOGDIR "/var/log/rspamd") +ENDIF(NOT LOGDIR) + +IF(NOT SHAREDIR) + SET(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share/rspamd") +ENDIF(NOT SHAREDIR) + +IF(NOT LUALIBDIR) + SET(LUALIBDIR "${SHAREDIR}/lualib") +ENDIF(NOT LUALIBDIR) + +IF(NOT PLUGINSDIR) + SET(PLUGINSDIR "${SHAREDIR}/plugins") +ENDIF(NOT PLUGINSDIR) + +IF(NOT RULESDIR) + SET(RULESDIR "${SHAREDIR}/rules") +ENDIF(NOT RULESDIR) + +IF(NOT WWWDIR) + SET(WWWDIR "${SHAREDIR}/www") +ENDIF(NOT WWWDIR) + +# Set libdir +IF(NOT LIBDIR) + SET(RSPAMD_LIBDIR "${CMAKE_INSTALL_PREFIX}/lib/rspamd") +ELSE(NOT LIBDIR) + SET(RSPAMD_LIBDIR "${LIBDIR}") +ENDIF(NOT LIBDIR) +SET(CMAKE_MACOSX_RPATH ON) +SET(CMAKE_INSTALL_RPATH "${RSPAMD_LIBDIR}") + +# Set includedir +IF(NOT INCLUDEDIR) + SET(INCLUDEDIR include/rspamd) +ENDIF(NOT INCLUDEDIR) + +IF(NOT SYSTEMDDIR) + SET(SYSTEMDDIR ${CMAKE_INSTALL_PREFIX}/lib/systemd/system) +ENDIF(NOT SYSTEMDDIR) + +SET(RSPAMD_DEFAULT_INCLUDE_PATHS "/opt;/usr;/usr/local;/opt/local;/usr/pkg;/opt/csw;/sw") +SET(RSPAMD_DEFAULT_LIBRARY_PATHS "/usr/local;/usr/pkg;/usr;/Library/Frameworks;/sw;/opt/local;/opt/csw;/opt") diff --git a/cmake/ProcessPackage.cmake b/cmake/ProcessPackage.cmake new file mode 100644 index 0000000..a46fd85 --- /dev/null +++ b/cmake/ProcessPackage.cmake @@ -0,0 +1,122 @@ +# Process required package by using FindPackage and calling for INCLUDE_DIRECTORIES and +# setting list of required libraries +# Usage: +# ProcessPackage(VAR [OPTIONAL] [ROOT path] [INCLUDE path] +# [LIBRARY path] [INCLUDE_SUFFIXES path1 path2 ...] [LIB_SUFFIXES path1 path2 ...] +# [MODULES module1 module2 ...]) +# params: +# OPTIONAL - do not fail if a package has not been found +# ROOT - defines root directory for a package +# INCLUDE - name of the include file to check +# LIBRARY - name of the library to check +# INCLUDE_SUFFIXES - list of include suffixes (relative to ROOT) +# LIB_SUFFIXES - list of library suffixes +# MODULES - modules to search using pkg_config +MACRO(ProcessPackage PKG_NAME) + + CMAKE_PARSE_ARGUMENTS(PKG "OPTIONAL;OPTIONAL_INCLUDE" "ROOT;INCLUDE" + "LIBRARY;INCLUDE_SUFFIXES;LIB_SUFFIXES;MODULES;LIB_OUTPUT" ${ARGN}) + + IF(NOT PKG_LIBRARY) + SET(PKG_LIBRARY "${PKG_NAME}") + ENDIF() + IF(NOT PKG_INCLUDE) + SET(PKG_INCLUDE "${PKG_NAME}.h") + ENDIF() + IF(NOT PKG_LIB_OUTPUT) + SET(PKG_LIB_OUTPUT RSPAMD_REQUIRED_LIBRARIES) + ENDIF() + + IF(NOT PKG_ROOT AND PKG_MODULES) + PKG_SEARCH_MODULE(${PKG_NAME} ${PKG_MODULES}) + ENDIF() + + IF(${PKG_NAME}_FOUND) + MESSAGE(STATUS "Found package ${PKG_NAME} in pkg-config modules ${PKG_MODULES}") + SET(WITH_${PKG_NAME} 1 CACHE INTERNAL "") + IF(ENABLE_STATIC MATCHES "ON") + SET(_XPREFIX "${PKG_NAME}_STATIC") + ELSE(ENABLE_STATIC MATCHES "ON") + SET(_XPREFIX "${PKG_NAME}") + ENDIF(ENABLE_STATIC MATCHES "ON") + FOREACH(_arg ${${_XPREFIX}_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES("${_arg}") + SET(${PKG_NAME}_INCLUDE "${_arg}" CACHE INTERNAL "") + ENDFOREACH(_arg ${${_XPREFIX}_INCLUDE_DIRS}) + FOREACH(_arg ${${_XPREFIX}_LIBRARY_DIRS}) + LINK_DIRECTORIES("${_arg}") + SET(${PKG_NAME}_LIBRARY_PATH "${_arg}" CACHE INTERNAL "") + ENDFOREACH(_arg ${${_XPREFIX}_LIBRARY_DIRS}) + # Handle other CFLAGS and LDFLAGS + FOREACH(_arg ${${_XPREFIX}_CFLAGS_OTHER}) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_arg}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_arg}") + ENDFOREACH(_arg ${${_XPREFIX}_CFLAGS_OTHER}) + FOREACH(_arg ${${_XPREFIX}_LDFLAGS_OTHER}) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_arg}") + ENDFOREACH(_arg ${${_XPREFIX}_LDFLAGS_OTHER}) + LIST(APPEND ${PKG_LIB_OUTPUT} "${${_XPREFIX}_LIBRARIES}") + INCLUDE_DIRECTORIES(${${_XPREFIX}_INCLUDEDIR}) + ELSE() + IF(NOT ${PKG_NAME}_GUESSED) + # Try some more heuristic + FIND_LIBRARY(_lib NAMES ${PKG_LIBRARY} + HINTS ${PKG_ROOT} ${RSPAMD_SEARCH_PATH} + PATH_SUFFIXES ${PKG_LIB_SUFFIXES} lib64 lib + PATHS ${RSPAMD_DEFAULT_LIBRARY_PATHS}) + IF(NOT _lib) + IF(PKG_OPTIONAL) + MESSAGE(STATUS "Cannot find library ${PKG_LIBRARY} for package ${PKG_NAME}, ignoring") + ELSE() + MESSAGE(FATAL_ERROR "Cannot find library ${PKG_LIBRARY} for package ${PKG_NAME}") + ENDIF() + ENDIF(NOT _lib) + + FIND_PATH(_incl ${PKG_INCLUDE} + HINTS ${PKG_ROOT} ${RSPAMD_SEARCH_PATH} + PATH_SUFFIXES ${PKG_INCLUDE_SUFFIXES} include + PATHS {RSPAMD_DEFAULT_INCLUDE_PATHS}) + IF(NOT _incl) + IF(PKG_OPTIONAL OR PKG_OPTIONAL_INCLUDE) + MESSAGE(STATUS "Cannot find header ${PKG_INCLUDE} for package ${PKG_NAME}") + ELSE() + MESSAGE(FATAL_ERROR "Cannot find header ${PKG_INCLUDE} for package ${PKG_NAME}") + ENDIF() + ELSE() + STRING(REGEX REPLACE "/[^/]+$" "" _incl_path "${PKG_INCLUDE}") + STRING(REGEX REPLACE "${_incl_path}/$" "" _stripped_incl "${_incl}") + INCLUDE_DIRECTORIES("${_stripped_incl}") + SET(${PKG_NAME}_INCLUDE "${_stripped_incl}" CACHE INTERNAL "") + ENDIF(NOT _incl) + + IF(_lib) + # We need to apply heuristic to find the real dir name + GET_FILENAME_COMPONENT(_lib_path "${_lib}" PATH) + LINK_DIRECTORIES("${_lib_path}") + LIST(APPEND ${PKG_LIB_OUTPUT} ${_lib}) + SET(${PKG_NAME}_LIBRARY_PATH "${_lib_path}" CACHE INTERNAL "") + SET(${PKG_NAME}_LIBRARY "${_lib}" CACHE INTERNAL "") + ENDIF() + + IF(_incl AND _lib) + MESSAGE(STATUS "Found package ${PKG_NAME} in '${_lib_path}' (${_lib}) and '${_stripped_incl}' (${PKG_INCLUDE}).") + SET(${PKG_NAME}_GUESSED 1 CACHE INTERNAL "") + SET(WITH_${PKG_NAME} 1 CACHE INTERNAL "") + ELSEIF(_lib) + IF(PKG_OPTIONAL_INCLUDE) + SET(${PKG_NAME}_GUESSED 1 INTERNAL "") + SET(WITH_${PKG_NAME} 1 INTERNAL "") + ENDIF() + MESSAGE(STATUS "Found incomplete package ${PKG_NAME} in '${_lib_path}' (${_lib}); no includes.") + ENDIF() + ELSE() + MESSAGE(STATUS "Found package ${PKG_NAME} (cached)") + INCLUDE_DIRECTORIES("${${PKG_NAME}_INCLUDE}") + LINK_DIRECTORIES("${${PKG_NAME}_LIBRARY_PATH}") + LIST(APPEND ${PKG_LIB_OUTPUT} "${${PKG_NAME}_LIBRARY}") + ENDIF() + ENDIF(${PKG_NAME}_FOUND) + + UNSET(_lib CACHE) + UNSET(_incl CACHE) +ENDMACRO(ProcessPackage name)
\ No newline at end of file diff --git a/cmake/Sanitizer.cmake b/cmake/Sanitizer.cmake new file mode 100644 index 0000000..c258706 --- /dev/null +++ b/cmake/Sanitizer.cmake @@ -0,0 +1,75 @@ +# 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") + 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 () + + 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") + + elseif (SANITIZE STREQUAL "memory") + set (MSAN_FLAGS "-fsanitize=memory -fsanitize-memory-track-origins -fno-optimize-sibling-calls") + + 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 (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") + 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") + + 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") + endif () + else () + message (FATAL_ERROR "Unknown sanitizer type: ${SANITIZE}") + endif () + 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 diff --git a/cmake/Toolset.cmake b/cmake/Toolset.cmake new file mode 100644 index 0000000..4e7017d --- /dev/null +++ b/cmake/Toolset.cmake @@ -0,0 +1,252 @@ +option (ENABLE_FAST_MATH "Build rspamd with fast math compiler flag [default: ON]" ON) +option (ENABLE_ANALYZER "Build rspamd with static analyzer [default: OFF]" OFF) +option (ENABLE_STATIC_LIBCXX "Build rspamd with static lib(std)c++ [default: OFF]" OFF) +option (ENABLE_COMPILE_TIME "Show compile time [default: OFF]" OFF) +option (ENABLE_LIBCXX "Use libc++ instead of libstdc++" OFF) + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + SET (COMPILER_GCC 1) +elseif(CMAKE_C_COMPILER_ID MATCHES "Clang|AppleClang") + SET (COMPILER_CLANG 1) +endif() + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +SET (COMPILER_FAST_MATH "") +if (ENABLE_FAST_MATH MATCHES "ON") + # We need to keep nans and infinities, so cannot keep all fast math there + IF (COMPILER_CLANG) + SET (COMPILER_FAST_MATH "-fassociative-math -freciprocal-math -fno-signed-zeros -ffp-contract=fast") + ELSE() + SET (COMPILER_FAST_MATH "-funsafe-math-optimizations -fno-math-errno") + ENDIF () +endif () + +if (CMAKE_GENERATOR STREQUAL "Ninja") + # Turn on colored output. https://github.com/ninja-build/ninja/wiki/FAQ + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always") +endif () + +if (COMPILER_GCC) + # Require minimum version of gcc + set (GCC_MINIMUM_VERSION 8) + if (CMAKE_C_COMPILER_VERSION VERSION_LESS ${GCC_MINIMUM_VERSION} AND NOT CMAKE_VERSION VERSION_LESS 2.8.9) + message (FATAL_ERROR "GCC version must be at least ${GCC_MINIMUM_VERSION}.") + endif () + if (ENABLE_LIBCXX MATCHES "ON") + # XXX: too complicated to implement for now + endif () +elseif (COMPILER_CLANG) + # Require minimum version of clang + set (CLANG_MINIMUM_VERSION 7) + if (CMAKE_C_COMPILER_VERSION VERSION_LESS ${CLANG_MINIMUM_VERSION}) + message (FATAL_ERROR "Clang version must be at least ${CLANG_MINIMUM_VERSION}.") + endif () + # Hack to fix try_compile + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-ignored-optimization-argument") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-ignored-optimization-argument") + if (ENABLE_LIBCXX MATCHES "AUTO") + include(CheckCXXSourceCompiles) + set(OLD_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + check_cxx_source_compiles(" +#include <version> +int main() { return 0; } + " HAVE_LIBCXX ) + if (HAVE_LIBCXX) + SET(ENABLE_LIBCXX "ON") + else() + SET(ENABLE_LIBCXX "OFF") + endif() + set(CMAKE_CXX_FLAGS "${OLD_CMAKE_CXX_FLAGS}") + endif() + if (ENABLE_LIBCXX MATCHES "ON") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CLANG_DEFAULT_CXX_STDLIB "libc++") + endif () +else () + message (WARNING "You are using an unsupported compiler ${CMAKE_C_COMPILER_ID}. Compilation has only been tested with Clang 4+ and GCC 4+.") +endif () + +option(LINKER_NAME "Linker name or full path") + +find_program(LLD_PATH NAMES "ld.lld" "lld") +find_program(GOLD_PATH NAMES "ld.gold" "gold") + +if(NOT LINKER_NAME) + if(LLD_PATH) + if (COMPILER_CLANG) + set(LINKER_NAME "lld") + elseif(NOT SANITIZE) + if(GOLD_PATH) + set(LINKER_NAME "gold") + else() + message(STATUS "Use generic 'ld' as a linker: gold not found") + endif() + else() + message(STATUS "Use generic 'ld' as a linker: sanitizers are enabled") + endif() + elseif(GOLD_PATH) + set(LINKER_NAME "gold") + else() + message(STATUS "Use generic 'ld' as a linker") + endif() +endif() + +if(LINKER_NAME) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}") + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=${LINKER_NAME}") + + message(STATUS "Using custom linker by name: ${LINKER_NAME}") +endif () + +option (ENABLE_STATIC "Enable static compiling [default: OFF]" OFF) + +if (ENABLE_STATIC MATCHES "ON") + MESSAGE(STATUS "Static build of rspamd implies that the target binary will be *GPL* licensed") + SET(GPL_RSPAMD_BINARY 1) + SET(CMAKE_SKIP_INSTALL_RPATH ON) + SET(BUILD_STATIC 1) + SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + SET(BUILD_SHARED_LIBS OFF) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + SET(LINK_TYPE "STATIC") + SET(NO_SHARED "ON") + # Dirty hack for cmake + SET(CMAKE_EXE_LINK_DYNAMIC_C_FLAGS) # remove -Wl,-Bdynamic + SET(CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS) + SET(CMAKE_SHARED_LIBRARY_C_FLAGS) # remove -fPIC + SET(CMAKE_SHARED_LIBRARY_CXX_FLAGS) + SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) # remove -rdynamic + SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) +else () + if (NO_SHARED MATCHES "OFF") + SET(LINK_TYPE "SHARED") + else () + SET(LINK_TYPE "STATIC") + endif () +endif () + + +# Legacy options support +option (ENABLE_COVERAGE "Build rspamd with code coverage options [default: OFF]" OFF) +option (ENABLE_OPTIMIZATION "Enable extra optimizations [default: OFF]" OFF) +option (SKIP_RELINK_RPATH "Skip relinking and full RPATH for the install tree" OFF) +option (ENABLE_FULL_DEBUG "Build rspamd with all possible debug [default: OFF]" OFF) + +if(NOT CMAKE_BUILD_TYPE) + if (ENABLE_FULL_DEBUG MATCHES "ON") + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) + endif() + if (ENABLE_COVERAGE MATCHES "ON") + set(CMAKE_BUILD_TYPE Coverage CACHE STRING "" FORCE) + endif() + if (ENABLE_OPTIMIZATION MATCHES "ON") + set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE) + endif() +endif() + +if (CMAKE_CONFIGURATION_TYPES) # multiconfig generator? + set (CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo;Release;Coverage" CACHE STRING "" FORCE) +else() + if (NOT CMAKE_BUILD_TYPE) + if (NOT SANITIZE) + message(STATUS "Defaulting to release build.") + set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE) + else () + message(STATUS "Defaulting to debug build due to sanitizers being enabled.") + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) + endif () + endif() + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING "Choose the type of build") + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;Coverage") +endif() + +string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC) +message (STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE_UC}") +set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS} -O1 --coverage -fno-inline -fno-default-inline -fno-inline-small-functions ${COMPILER_FAST_MATH}") +set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS} -O1 --coverage -fno-inline -fno-default-inline -fno-inline-small-functions ${COMPILER_FAST_MATH}") + +if (COMPILER_GCC) + # GCC flags + set (COMPILER_DEBUG_FLAGS "-g -ggdb -g3 -ggdb3") + set (CXX_COMMON_FLAGS "") + set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} -O2 ${COMPILER_FAST_MATH} ${COMPILER_DEBUG_FLAGS}") + set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -O2 ${COMPILER_FAST_MATH} ${COMPILER_DEBUG_FLAGS} ${CXX_COMMON_FLAGS}") + + set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 ${COMPILER_FAST_MATH} -fomit-frame-pointer") + set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 ${COMPILER_FAST_MATH} -fomit-frame-pointer ${CXX_COMMON_FLAGS}") + + if (ENABLE_FULL_DEBUG MATCHES "ON") + if (ENABLE_ANALYZER MATCHES "ON") + # Check support of -fanalyzer + CHECK_C_COMPILER_FLAG(-fanalyzer SUPPORT_FANALYZER) + if (SUPPORT_FANALYZER) + set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fanalyzer") + #set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fanalyzer") + endif() + endif () + set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 ${COMPILER_DEBUG_FLAGS}") + set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 ${COMPILER_DEBUG_FLAGS} ${CXX_COMMON_FLAGS}") + else() + set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Og ${COMPILER_DEBUG_FLAGS}") + set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og ${COMPILER_DEBUG_FLAGS} ${CXX_COMMON_FLAGS}") + endif() +elseif (COMPILER_CLANG) + # Clang flags + set (COMPILER_DEBUG_FLAGS "-g -glldb -gdwarf-aranges -gdwarf-4") + set (CXX_COMMON_FLAGS "") + set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2 -fomit-frame-pointer ${COMPILER_FAST_MATH}") + set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -fomit-frame-pointer ${COMPILER_FAST_MATH} ${CXX_COMMON_FLAGS}") + + set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} -O2 ${COMPILER_FAST_MATH} ${COMPILER_DEBUG_FLAGS}") + set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -O2 ${COMPILER_FAST_MATH} ${COMPILER_DEBUG_FLAGS} ${CXX_COMMON_FLAGS}") + + set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 ${COMPILER_DEBUG_FLAGS}") + set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 ${COMPILER_DEBUG_FLAGS} ${CXX_COMMON_FLAGS}") +endif() + + +if (CMAKE_BUILD_TYPE_UC MATCHES "RELEASE|RELWITHDEBINFO") + set(ENABLE_LTO_INIT ON) +else() + set(ENABLE_LTO_INIT OFF) +endif() +option(ENABLE_LTO "Build rspamd with Link Time Optimization if supported [default: ${ENABLE_LTO_INIT}]" ${ENABLE_LTO_INIT}) + +if (CMAKE_BUILD_TYPE_UC MATCHES "COVERAGE") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") + message (STATUS "IPO not enabled for COVERAGE build") +elseif (ENABLE_LTO) + if (${CMAKE_VERSION} VERSION_GREATER "3.9.0") + cmake_policy (SET CMP0069 NEW) + include (CheckIPOSupported) + check_ipo_supported (RESULT SUPPORT_LTO OUTPUT LTO_DIAG ) + if (SUPPORT_LTO) + set (CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) + message (STATUS "Enable IPO for the ${CMAKE_BUILD_TYPE} build") + else () + message(WARNING "IPO is not supported: ${LTO_DIAG}") + endif () + endif () +else () + message (STATUS "IPO not enabled for the ${CMAKE_BUILD_TYPE} build") +endif () + +if (ENABLE_STATIC_LIBCXX MATCHES "ON") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++") + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++") +endif() + +if (ENABLE_COMPILE_TIME MATCHES "ON") + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "/usr/bin/time") +endif() + +message (STATUS "Final CFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}") +message (STATUS "Final CXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}") +message (STATUS "Final link flags for shlib: ${CMAKE_SHARED_LINKER_FLAGS}") +message (STATUS "Final link flags for exe: ${CMAKE_EXE_LINKER_FLAGS}") + |