Unverified Commit 8628e790 authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #968

Enable C++17
parents 28caf0c3 3d1efcfc
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(caf C CXX) project(caf C CXX)
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
...@@ -8,6 +8,7 @@ include(CheckCSourceRuns) ...@@ -8,6 +8,7 @@ include(CheckCSourceRuns)
# See https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html # See https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
include(GNUInstallDirs) include(GNUInstallDirs)
# Check whether we are running as CMake subdirectory.
get_directory_property(_parent PARENT_DIRECTORY) get_directory_property(_parent PARENT_DIRECTORY)
if(_parent) if(_parent)
set(caf_is_subproject ON) set(caf_is_subproject ON)
...@@ -16,6 +17,38 @@ else() ...@@ -16,6 +17,38 @@ else()
endif() endif()
unset(_parent) unset(_parent)
if(NOT CMAKE_CROSSCOMPILING)
# Check whether the user already provided flags that enable C++ >= 17.
try_compile(caf_has_cxx_17
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/check-compiler-features.cpp")
# Try enabling C++17 mode if user-provided flags aren't sufficient.
if(NOT caf_has_cxx_17)
if(MSVC)
set(cxx_flag "/std:c++17")
else()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang"
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)
set(cxx_flag "-std=c++1z")
else()
set(cxx_flag "-std=c++17")
endif()
endif()
# Re-run compiler check.
try_compile(caf_has_cxx_17
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/check-compiler-features.cpp"
COMPILE_DEFINITIONS "${cxx_flag}"
OUTPUT_VARIABLE cxx_check_output)
if(NOT caf_has_cxx_17)
MESSAGE(FATAL_ERROR "\nFatal error: unable activate C++17 mode!\
\nPlease see README.md for supported compilers.\
\n\ntry_compile output:\n${cxx_check_output}")
endif()
add_compile_options("${cxx_flag}")
endif()
endif()
# Be nice to VIM users and Clang tools. # Be nice to VIM users and Clang tools.
set(CMAKE_EXPORT_COMPILE_COMMANDS 1) set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
...@@ -203,37 +236,12 @@ endif() ...@@ -203,37 +236,12 @@ endif()
# compiler setup # # compiler setup #
################################################################################ ################################################################################
# check for g++ >= 4.8 or clang++ > = 3.2
if(NOT WIN32 AND NOT CAF_NO_COMPILER_CHECK AND NOT CMAKE_CROSSCOMPILING)
try_run(ProgramResult
CompilationSucceeded
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/get_compiler_version.cpp"
RUN_OUTPUT_VARIABLE CompilerVersion)
if(NOT CompilationSucceeded OR NOT ProgramResult EQUAL 0)
message(FATAL_ERROR "Cannot determine compiler version")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(CompilerVersion VERSION_GREATER 4.7)
message(STATUS "Found g++ version ${CompilerVersion}")
else()
message(FATAL_ERROR "g++ >= 4.8 required (found: ${CompilerVersion})")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(CompilerVersion VERSION_GREATER 3.1)
message(STATUS "Found clang++ version ${CompilerVersion}")
else()
message(FATAL_ERROR "clang++ >= 3.2 required (found: ${CompilerVersion})")
endif()
else()
message(FATAL_ERROR "Your C++ compiler does not support C++11 "
"or is not supported")
endif()
endif()
# set optional build flags # set optional build flags
# increase max. template depth on GCC and Clang # increase max. template depth on GCC and Clang
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" if(CMAKE_CXX_COMPILER_ID MATCHES "Clang"
OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
build_string("EXTRA_FLAGS" "-ftemplate-depth=512 -ftemplate-backtrace-limit=0") add_compile_options("-ftemplate-depth=512"
"-ftemplate-backtrace-limit=0")
endif() endif()
# explicitly disable obnoxious GCC warnings # explicitly disable obnoxious GCC warnings
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
...@@ -304,42 +312,11 @@ else() ...@@ -304,42 +312,11 @@ else()
endif() endif()
endif() endif()
# add -stdlib=libc++ when using Clang if possible
if(NOT CAF_NO_AUTO_LIBCPP AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CXXFLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")
try_run(ProgramResult
CompilationSucceeded
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/get_compiler_version.cpp"
RUN_OUTPUT_VARIABLE CompilerVersion)
if(NOT CompilationSucceeded OR NOT ProgramResult EQUAL 0)
message(STATUS "Use clang with GCC' libstdc++")
else()
message(STATUS "Automatically added '-stdlib=libc++' flag "
"(CAF_NO_AUTO_LIBCPP not defined)")
build_string("EXTRA_FLAGS" "-stdlib=libc++")
endif()
# restore CXX flags
set(CMAKE_CXX_FLAGS "${CXXFLAGS_BACKUP}")
endif()
# enable address sanitizer if requested by the user # enable address sanitizer if requested by the user
if(CAF_ENABLE_ADDRESS_SANITIZER AND NOT WIN32) if(CAF_ENABLE_ADDRESS_SANITIZER AND NOT WIN32)
# check whether address sanitizer is available add_compile_options("-fsanitize=address"
set(CXXFLAGS_BACKUP "${CMAKE_CXX_FLAGS}") "-fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer") list(APPEND CAF_EXTRA_LDFLAGS "-fsanitize=address")
try_run(ProgramResult
CompilationSucceeded
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/get_compiler_version.cpp")
if(NOT CompilationSucceeded)
message(WARNING "Address Sanitizer is not available on selected compiler")
else()
message(STATUS "Enable Address Sanitizer")
build_string("EXTRA_FLAGS" "-fsanitize=address -fno-omit-frame-pointer")
endif()
# restore CXX flags
set(CMAKE_CXX_FLAGS "${CXXFLAGS_BACKUP}")
endif() endif()
# -pthread is ignored on MacOSX but required on other platforms # -pthread is ignored on MacOSX but required on other platforms
if(NOT APPLE AND NOT WIN32) if(NOT APPLE AND NOT WIN32)
...@@ -376,11 +353,7 @@ if(CAF_IOS_DEPLOYMENT_TARGET) ...@@ -376,11 +353,7 @@ if(CAF_IOS_DEPLOYMENT_TARGET)
endif() endif()
# check if the user provided CXXFLAGS, set defaults otherwise # check if the user provided CXXFLAGS, set defaults otherwise
if(NOT CMAKE_CXX_FLAGS) if(NOT CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wextra -Wall -pedantic ${EXTRA_FLAGS}") set(CMAKE_CXX_FLAGS "-Wextra -Wall -pedantic ${EXTRA_FLAGS}")
endif()
if (NOT "${CMAKE_CXX_FLAGS}" MATCHES "-std=")
message(STATUS "Supplied CXXFLAGS do not contain a C++ standard, setting std to c++11")
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
endif() endif()
if(NOT CMAKE_CXX_FLAGS_DEBUG) if(NOT CMAKE_CXX_FLAGS_DEBUG)
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
......
...@@ -29,19 +29,38 @@ config = [ ...@@ -29,19 +29,38 @@ config = [
], ],
// Our build matrix. Keys are the operating system labels and values are build configurations. // Our build matrix. Keys are the operating system labels and values are build configurations.
buildMatrix: [ buildMatrix: [
['Linux', [ // Various Linux builds for debug and release.
builds: ['debug'], ['debian-8', [
tools: ['gcc4.8', 'gcc4.9', 'gcc5', 'gcc6', 'gcc7'], builds: ['debug', 'release'],
tools: ['clang-4'],
]],
['centos-6', [
builds: ['debug', 'release'],
tools: ['gcc-7'],
]],
['centos-7', [
builds: ['debug', 'release'],
tools: ['gcc-7'],
]],
['ubuntu-16.04', [
builds: ['debug', 'release'],
tools: ['clang-4'],
]],
['ubuntu-18.04', [
builds: ['debug', 'release'],
tools: ['gcc-7'],
]], ]],
['Linux', [ // On Fedora 28, our debug build also produces the coverage report.
['fedora-28', [
builds: ['debug'], builds: ['debug'],
tools: ['gcc8'], tools: ['gcc-8'],
extraSteps: ['coverageReport'], extraSteps: ['coverageReport'],
]], ]],
['Linux', [ ['fedora-28', [
builds: ['release'], builds: ['release'],
tools: ['gcc8', 'clang'], tools: ['gcc-8'],
]], ]],
// Other UNIX systems.
['macOS', [ ['macOS', [
builds: ['debug', 'release'], builds: ['debug', 'release'],
tools: ['clang'], tools: ['clang'],
...@@ -50,6 +69,7 @@ config = [ ...@@ -50,6 +69,7 @@ config = [
builds: ['debug', 'release'], builds: ['debug', 'release'],
tools: ['clang'], tools: ['clang'],
]], ]],
// Non-UNIX systems.
['Windows', [ ['Windows', [
// TODO: debug build currently broken // TODO: debug build currently broken
//builds: ['debug', 'release'], //builds: ['debug', 'release'],
......
#ifndef __cpp_noexcept_function_type
# error "Noexcept not part of the type system (__cpp_noexcept_function_type)"
#endif
#ifndef __cpp_fold_expressions
# error "No support for fold expression (__cpp_fold_expressions)"
#endif
#ifndef __cpp_if_constexpr
# error "No support for 'if constexpr' (__cpp_if_constexpr)"
#endif
int main(int, char**) {
return 0;
}
#include <iostream>
using namespace std;
int main() {
# ifdef __clang__
cout << __clang_major__
<< "."
<< __clang_minor__;
# elif defined(__GNUC__)
cout << __GNUC__
<< "."
<< __GNUC_MINOR__;
# else
cout << "0.0";
# endif
return 0;
}
...@@ -448,6 +448,15 @@ struct callable_trait<R (Ts...)> { ...@@ -448,6 +448,15 @@ struct callable_trait<R (Ts...)> {
static constexpr size_t num_args = sizeof...(Ts); static constexpr size_t num_args = sizeof...(Ts);
}; };
// member noexcept const function pointer
template <class C, typename R, class... Ts>
struct callable_trait<R (C::*)(Ts...) const noexcept>
: callable_trait<R(Ts...)> {};
// member noexcept function pointer
template <class C, typename R, class... Ts>
struct callable_trait<R (C::*)(Ts...) noexcept> : callable_trait<R(Ts...)> {};
// member const function pointer // member const function pointer
template <class C, typename R, class... Ts> template <class C, typename R, class... Ts>
struct callable_trait<R (C::*)(Ts...) const> : callable_trait<R (Ts...)> {}; struct callable_trait<R (C::*)(Ts...) const> : callable_trait<R (Ts...)> {};
...@@ -456,6 +465,10 @@ struct callable_trait<R (C::*)(Ts...) const> : callable_trait<R (Ts...)> {}; ...@@ -456,6 +465,10 @@ struct callable_trait<R (C::*)(Ts...) const> : callable_trait<R (Ts...)> {};
template <class C, typename R, class... Ts> template <class C, typename R, class... Ts>
struct callable_trait<R (C::*)(Ts...)> : callable_trait<R (Ts...)> {}; struct callable_trait<R (C::*)(Ts...)> : callable_trait<R (Ts...)> {};
// good ol' noexcept function pointer
template <class R, class... Ts>
struct callable_trait<R (*)(Ts...) noexcept> : callable_trait<R(Ts...)> {};
// good ol' function pointer // good ol' function pointer
template <class R, class... Ts> template <class R, class... Ts>
struct callable_trait<R (*)(Ts...)> : callable_trait<R (Ts...)> {}; struct callable_trait<R (*)(Ts...)> : callable_trait<R (Ts...)> {};
......
...@@ -89,14 +89,10 @@ public: ...@@ -89,14 +89,10 @@ public:
CAF_LOG_TRACE(""); // serializing who would cause a deadlock CAF_LOG_TRACE(""); // serializing who would cause a deadlock
exclusive_guard guard(mtx_); exclusive_guard guard(mtx_);
auto e = subscribers_.end(); auto e = subscribers_.end();
#if __cplusplus > 201103L
auto i = subscribers_.find(who);
#else
auto cmp = [&](const strong_actor_ptr& lhs) { auto cmp = [&](const strong_actor_ptr& lhs) {
return lhs.get() == who; return lhs.get() == who;
}; };
auto i = std::find_if(subscribers_.begin(), e, cmp); auto i = std::find_if(subscribers_.begin(), e, cmp);
#endif
if(i == e) if(i == e)
return {false, subscribers_.size()}; return {false, subscribers_.size()};
subscribers_.erase(i); subscribers_.erase(i);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment