cmake_minimum_required(VERSION 3.20) message(STATUS "CMake version: ${CMAKE_VERSION}") project(fortuna LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) OPTION(TIDY "Run clang-tidy" OFF) OPTION(VALGRIND "Run valgrind" OFF) OPTION(SAN "Build with sanitize flags" OFF) if(DEFINED ENV{CI}) if($ENV{CI} MATCHES "true") message(STATUS "We're in CI!") OPTION(IS_CI "Are we in CI?" ON) endif() else() OPTION(IS_CI "Are we in CI?" OFF) endif() find_package(Git QUIET) if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") if(IS_CI) # there seems to be a race condition so the submodules are simply # initialized/updated in a separate step and therefore this is not needed option(GIT_SUBMODULE "Check submodules during build" OFF) else() option(GIT_SUBMODULE "Check submodules during build" ON) endif() if(GIT_SUBMODULE) message(STATUS "Update submodule(s)") message(STATUS "Current source dir: ${CMAKE_CURRENT_SOURCE_DIR}") execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULT_VARIABLE GIT_SUBMOD_RESULT) if(NOT GIT_SUBMOD_RESULT EQUAL "0") message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") endif() endif() endif() add_subdirectory(lib/fmt EXCLUDE_FROM_ALL) add_subdirectory(lib/fmtlog EXCLUDE_FROM_ALL) add_subdirectory(lib/da_threading EXCLUDE_FROM_ALL) if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wall") if(CMAKE_BUILD_TYPE MATCHES "Debug") if(TIDY) message(STATUS "TIDY=ON, running clang-tidy") set(CMAKE_CXX_CLANG_TIDY clang-tidy -p ${CMAKE_CURRENT_BINARY_DIR} --checks=-*,clang-diagnostic-*,clang-analyzer-*,google-*,bugprone-* --header-filter= --use-color=true) message(STATUS "CMAKE_CXX_CLANG_TIDY: ${CMAKE_CXX_CLANG_TIDY}") endif() if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -grecord-gcc-switches") endif() # Produce debugging information in the operating system's native format. # Level 3 includes extra information, such as all the macro definitions # present in the program. Some debuggers support macro expansion when you # use -g3 if(NOT CMAKE_CXX_FLAGS MATCHES "-g") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") endif(NOT CMAKE_CXX_FLAGS MATCHES "-g") # Optimize debugging experience. -Og should be the optimization level of # choice for the standard edit-compile-debug cycle, offering a reasonable # level of optimization while maintaining fast compilation and a good # debugging experience. It is a better choice than -O0 for producing # debuggable code because some compiler passes that collect debug # information are disabled at -O0. if(NOT CMAKE_CXX_FLAGS MATCHES "-Og") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Og") if(NOT VALGRIND) if(SAN) message(STATUS "SAN=ON, building with sanitize flags") # this needs {libasan,liblsan,libubsan} on fedora, gcc-libs on arch set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak") # issue with gdb set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=pointer-compare") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=pointer-subtract") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=vla-bound") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-address-use-after-scope") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-clash-protection") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=bounds") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=vptr") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=pointer-overflow") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=enum") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=signed-integer-overflow") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=null") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=return") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=integer-divide-by-zero") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=float-cast-overflow") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=unreachable") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=alignment") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=object-size") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if(NOT CMAKE_CXX_FLAGS MATCHES "-fsanitize=address" OR "-fsanitize=leak") # clang-only atm # also doesn't like asan, leaksan et al. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=safe-stack") endif() endif() endif(SAN) # If DWARF debugging information is enabled, separate as much debugging # information as possible into a separate output file with the extension # .dwo. This option allows the build system to avoid linking files with # debug information. if(NOT CMAKE_CXX_FLAGS MATCHES "-gsplit-dwarf") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -gsplit-dwarf") endif(NOT CMAKE_CXX_FLAGS MATCHES "-gsplit-dwarf") else() message(STATUS "VALGRIND=ON, not setting '-gsplit-dwarf'") endif(NOT VALGRIND) if(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra") if(NOT CMAKE_CXX_FLAGS MATCHES "-Wpedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wpedantic") endif(CMAKE_BUILD_TYPE MATCHES "Debug") if(CMAKE_BUILD_TYPE MATCHES "Release") # Optimize yet more. if(NOT CMAKE_CXX_FLAGS MATCHES "-O3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") endif(NOT CMAKE_CXX_FLAGS MATCHES "-O3") if(NOT CMAKE_CXX_FLAGS MATCHES "-DNDEBUG") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG") endif(NOT CMAKE_CXX_FLAGS MATCHES "-DNDEBUG") if(NOT CMAKE_CXX_FLAGS MATCHES "-fstack-protector-all") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all") endif(NOT CMAKE_CXX_FLAGS MATCHES "-fstack-protector-all") if(NOT CMAKE_CXX_FLAGS MATCHES "-fdelete-null-pointer-checks") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdelete-null-pointer-checks") endif(NOT CMAKE_CXX_FLAGS MATCHES "-fdelete-null-pointer-checks") if(NOT CMAKE_CXX_FLAGS MATCHES "-fisolate-erroneous-paths-dereference") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fisolate-erroneous-paths-dereference") endif(NOT CMAKE_CXX_FLAGS MATCHES "-fisolate-erroneous-paths-dereference") if(NOT CMAKE_CXX_FLAGS MATCHES "-ftree-loop-if-convert") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftree-loop-if-convert") endif(NOT CMAKE_CXX_FLAGS MATCHES "-ftree-loop-if-convert") if(NOT CMAKE_CXX_FLAGS MATCHES "-funwind-tables") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funwind-tables") endif(NOT CMAKE_CXX_FLAGS MATCHES "-funwind-tables") if(NOT CMAKE_CXX_FLAGS MATCHES "-fasynchronous-unwind-tables") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fasynchronous-unwind-tables") endif(NOT CMAKE_CXX_FLAGS MATCHES "-fasynchronous-unwind-tables") if(NOT CMAKE_CXX_FLAGS MATCHES "-Wp,-D_FORTIFY_SOURCE=2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wp,-D_FORTIFY_SOURCE=2") endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wp,-D_FORTIFY_SOURCE=2") endif(CMAKE_BUILD_TYPE MATCHES "Release") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsplit-stack") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=generic -pipe -fno-plt") if(NOT CMAKE_CXX_FLAGS MATCHES "-fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif(NOT CMAKE_CXX_FLAGS MATCHES "-fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcf-protection") add_compile_options (-fdiagnostics-show-location=once) if(CMAKE_BUILD_TYPE MATCHES "Debug") set(LDFLAGS "${LDFLAGS} -Wl,-Og,–sort-common,–as-needed,-z,now,-pic,-pie") elseif(CMAKE_BUILD_TYPE MATCHES "Release") set(LDFLAGS "${LDFLAGS} -Wl,-O1,–sort-common,–as-needed,-z,relro,-z,now,-pic,-pie,-flto") endif() # inspired by https://medium.com/@alasher/colored-c-compiler-output-with-ninja-clang-gcc-10bfe7f2b949 option (COLORS_FOREVER "Always produce ANSI-colored output (GNU/Clang only)." TRUE) if (${COLORS_FOREVER}) message(STATUS "COLORS_FOREVER: ${COLORS_FOREVER}") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") add_compile_options (-fdiagnostics-color=always) elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") add_compile_options (-fcolor-diagnostics) endif () endif () message(STATUS "Compiler ID: ${CMAKE_CXX_COMPILER_ID}") message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") message(STATUS "LDFLAGS: ${LDFLAGS}") find_program(LLD lld) if(LLD) if(NOT CMAKE_EXE_LINKER_FLAGS MATCHES "-fuse-ld=lld") message(STATUS "Linker: lld: ${LLD}") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld") endif(NOT CMAKE_EXE_LINKER_FLAGS MATCHES "-fuse-ld=lld") endif() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_CXX_FLAGS}") set(FORTUNA_SOURCES main.cpp fortuna.cpp generator.cpp accumulator.cpp pool.cpp do_task.cpp seed_file_management.cpp) set(FORTUNA_HEADERS fortuna.h generator.h accumulator.h pool.h do_task.h event_adder.h event_adder_impl.h event_scheduler.h entropy_src.h urandom_entropy_src.h util.h seed_file_management.h) add_executable(fortuna ${FORTUNA_SOURCES} ${FORTUNA_HEADERS}) target_include_directories(fortuna PRIVATE .) target_compile_features(fortuna PUBLIC cxx_std_20) if(CMAKE_BUILD_TYPE MATCHES "Debug") message(STATUS "Looking for iwyu...") find_program(iwyu NAMES include-what-you-use iwyu) if(iwyu) message(STATUS "iwyu found at: ${iwyu}") set(iwyu_and_options ${iwyu} -Xiwyu -p . --verbose=3) set_property(TARGET fortuna PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${iwyu_and_options}) else() message(STATUS "iwyu, not found") endif() endif() # add_executable(fortuna main.cpp generator.cpp generator.h fortuna.cpp fortuna.h accumulator.cpp accumulator.h pool.cpp pool.h event_adder.h event_adder_impl.h event_scheduler.h entropy_src.h urandom_entropy_src.h do_task.cpp do_task.h util.h seed_file_management.cpp seed_file_management.h) # ref: https://cmake.org/pipermail/cmake/2016-May/063400.html target_link_libraries(fortuna PRIVATE cryptopp fmt::fmt PRIVATE fmtlog::fmtlog PRIVATE da_threading::da_threading PRIVATE pthread) # vim: ft=cmake ff=unix softtabstop=2