cmake_minimum_required(VERSION 3.19) option(TROMPELOEIL_CATCH2_PREBUILT "Major version of prebuilt catch2") option(TROMPELOEIL_CATCH2_PREFIX "Path to catch2 installation") if (${CXX_STANDARD}) set(CMAKE_CXX_STANDARD ${CXX_STANDARD}) else() set(CMAKE_CXX_STANDARD 14) endif() set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS OFF) if (${CMAKE_CXX_STANDARD} GREATER 11) find_package(Catch2 3 QUIET) endif() if (NOT Catch2_FOUND) find_package(Catch2 2...<3 QUIET) if (NOT Catch2_FOUND) set(CATCH_DIR ${CMAKE_CURRENT_BINARY_DIR}/catch) if (NOT EXISTS "${CATCH_DIR}/catch2/catch.hpp") if (NOT EXISTS ${CATCH_DIR}) FILE(MAKE_DIRECTORY "${CATCH_DIR}/catch2") endif() file( DOWNLOAD https://github.com/catchorg/Catch2/releases/download/v2.13.7/catch.hpp ${CATCH_DIR}/catch2/catch.hpp STATUS status LOG log ) list(GET status 0 status_code) list(GET status 1 status_string) if(NOT status_code EQUAL 0) message(FATAL_ERROR "error downloading catch: ${status_string}" "${log}") endif() endif() add_library(Catch2 INTERFACE) add_library(Catch2::Catch2 ALIAS Catch2) target_include_directories(Catch2 INTERFACE "${CATCH_DIR}") set(Catch2_VERSION_MAJOR 2) endif() endif() if (TARGET Catch2::Catch2WithMain) set(CATCH2_MAIN Catch2::Catch2WithMain) add_compile_definitions(CATCH2_MAIN) endif() add_compile_definitions(CATCH2_VERSION=${Catch2_VERSION_MAJOR}) # Assumptions: # Clang and GNU compilers run on Linux or Linux-like platforms. # MSVC compilers run on Windows platforms. if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") set( LIBCXX_PREFIX_PATH "/usr/lib/llvm-8" CACHE PATH "Path prefix to libc++" ) # Interpret CXX_STDLIB, if specified if (NOT "${CXX_STDLIB}" STREQUAL "") if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") # Emulate -stdlib for g++ if ("${CXX_STDLIB}" STREQUAL "libc++") # Disable standard library and # set include path to appropriate libc++ headers string(CONCAT LIBCXX_INCLUDE_PATH "-isystem" "${LIBCXX_PREFIX_PATH}" "/include/c++/v1") string(CONCAT STDLIB_COMPILE_FLAGS "-nostdinc++" " " "${LIBCXX_INCLUDE_PATH}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STDLIB_COMPILE_FLAGS}") elseif ("${CXX_STDLIB}" STREQUAL "libstdc++") # This is the default library for g++, nothing to do. else() # Unknown CXX_STDLIB option message(FATAL_ERROR "CXX_STDLIB only understands libc++ and libstdc++, not " "'${CXX_STDLIB}'") endif() elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (("${CXX_STDLIB}" STREQUAL "libc++") OR ("${CXX_STDLIB}" STREQUAL "libstdc++")) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${CXX_STDLIB}") else() # Unknown CXX_STDLIB option message(FATAL_ERROR "CXX_STDLIB only understands libc++ and libstdc++, not " "'${CXX_STDLIB}'") endif() else() message(FATAL_ERROR "Only g++ and Clang++ compilers support CXX_STDLIB") endif() endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") string(CONCAT WARN_FLAGS "-Weverything" " -Wno-c++98-compat-pedantic" " -Wno-padded" " -Wno-weak-vtables" " -Wno-exit-time-destructors" " -Wno-global-constructors") # Disable for Catch2. # See check_cxx_compiler_flag("-Wno-extra-semi-stmt" WARN_SEMI_STMT) if (WARN_SEMI_STMT) string(APPEND WARN_FLAGS " -Wno-extra-semi-stmt") endif() # Disable for Catch2. # See check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID) if (WARN_RESERVED_ID) string(APPEND WARN_FLAGS " -Wno-reserved-identifier") endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") string(CONCAT WARN_FLAGS "-Wall" " -Wextra" " -pedantic" " -Wshadow" " -Wconversion") check_cxx_compiler_flag("-Wnonnull" WARN_NONNULL) if (WARN_NONNULL) string(APPEND WARN_FLAGS " -Wnonnull") endif() endif() set(WARN_FLAGS "${WARN_FLAGS} -Werror") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARN_FLAGS}") # Default sanitizer target properties. set(TSAN "-fsanitize=undefined,thread") set(SSAN "-fsanitize=undefined,address") # Exceptions to sanitizer target properties based on compiler and compiler version. if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0")) set(SSAN "-fsanitize=undefined,address -fsanitize-address-use-after-scope") else() set(SSAN "-fsanitize=undefined,address") endif() elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU") if ((NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8")) AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9")) set(TSAN "-fsanitize=thread") set(SSAN "-fsanitize=address") endif() endif() endif() # Clang or GNU if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") add_compile_options(/W4) add_compile_options(/bigobj) add_compile_options(/EHsc) check_cxx_compiler_flag(/permissive HAS_PERMISSIVE_FLAG) if(HAS_PERMISSIVE_FLAG) add_compile_options(/permissive-) endif() add_compile_definitions(NOMINMAX) endif() # MSVC if (${CMAKE_CXX_STANDARD} GREATER_EQUAL 20) set(CXX20TESTS "test_co_mock.cpp") else () set(CXX20TESTS "") endif () add_executable( self_test compiling_tests.cpp compiling_tests_11.cpp compiling_tests_14.cpp ${CXX20TESTS}) if (SANITIZE AND NOT APPLE) set_target_properties( self_test PROPERTIES LINK_FLAGS ${SSAN} COMPILE_FLAGS ${SSAN} ) endif() target_link_libraries( self_test PUBLIC trompeloeil ${CATCH2_MAIN} Catch2::Catch2 ) find_package(Threads REQUIRED) add_executable( thread_terror thread_terror.cpp ) target_link_libraries( thread_terror PUBLIC trompeloeil Threads::Threads ) if (SANITIZE) set_target_properties( thread_terror PROPERTIES LINK_FLAGS ${TSAN} COMPILE_FLAGS ${TSAN} ) endif() add_executable( custom_recursive_mutex custom_recursive_mutex.cpp ) target_link_libraries( custom_recursive_mutex PUBLIC trompeloeil Threads::Threads ) if (SANITIZE AND NOT APPLE) set_target_properties( custom_recursive_mutex PROPERTIES LINK_FLAGS "${SSAN}" COMPILE_FLAGS ${SSAN} ) endif() # Linker support for CXX_STDLIB argument if (NOT ("${CXX_STDLIB}" STREQUAL "")) if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") if ("${CXX_STDLIB}" STREQUAL "libc++") set(LIBCXX_LIBRARY_PATH "${LIBCXX_PREFIX_PATH}/lib") set(STDLIB_LINK_FLAGS -nodefaultlibs -L${LIBCXX_LIBRARY_PATH} -Wl,-rpath,${LIBCXX_LIBRARY_PATH} ) set(STDLIB_LINK_LIBRARIES "-lc++" "-lc++abi" "-lm" "-lc" "-lgcc_s" "-lgcc" ) set_target_properties( self_test PROPERTIES LINK_FLAGS ${STDLIB_LINK_FLAGS} ) target_link_libraries( self_test PUBLIC ${STDLIB_LINK_LIBRARIES} ) set_target_properties( thread_terror PROPERTIES LINK_FLAGS ${STDLIB_LINK_FLAGS} ) target_link_libraries( thread_terror PUBLIC ${STDLIB_LINK_LIBRARIES} ) set_target_properties( custom_recursive_mutex PROPERTIES LINK_FLAGS ${STDLIB_LINK_FLAGS} ) target_link_libraries( custom_recursive_mutex PUBLIC ${STDLIB_LINK_LIBRARIES} ) endif() endif() endif()