MinGW: Update mingw-std-threads
Remove requirement for MinGW-specific includeswip-string
parent
916676998f
commit
ba7d2c92d2
@ -1,7 +1,24 @@
|
||||
add_files(
|
||||
mingw.condition_variable.h
|
||||
mingw.invoke.h
|
||||
mingw.mutex.h
|
||||
mingw.shared_mutex.h
|
||||
mingw.thread.h
|
||||
CONDITION MINGW
|
||||
)
|
||||
|
||||
if (MINGW)
|
||||
string(CONCAT mingw_stdthreads_dir_docstring
|
||||
"Optional. When generating std-like headers , this variable can be set"
|
||||
"to manually specify the path to mingw-stdthreads directory containing"
|
||||
"original library headers.")
|
||||
set(MINGW_STDTHREADS_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
CACHE PATH ${mingw_stdthreads_dir_docstring})
|
||||
|
||||
# mingw-stdthreads is a header-only library, so make it a INTERFACE target
|
||||
add_library(mingw_stdthreads INTERFACE)
|
||||
target_include_directories(mingw_stdthreads INTERFACE "${PROJECT_SOURCE_DIR}")
|
||||
|
||||
add_subdirectory(cmake_stdheaders_generator)
|
||||
target_link_libraries(mingw_stdthreads INTERFACE cmake_stdheaders_generator)
|
||||
endif()
|
||||
|
@ -0,0 +1,78 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(cmake_stdheaders_generator)
|
||||
|
||||
set(output_include_path "${PROJECT_BINARY_DIR}/${PROJECT_NAME}")
|
||||
message("${PROJECT_NAME}: output_include_path set to ${output_include_path}")
|
||||
|
||||
function(generate_mingw_stdthreads_header header_file_name
|
||||
mingw_stdthreads_folder)
|
||||
set(template_file_path "${PROJECT_SOURCE_DIR}/template.cpp")
|
||||
set(destination_file_path "${output_include_path}/${header_file_name}")
|
||||
|
||||
# Check if compiler is gcc or clang
|
||||
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
||||
# Actually this should never happen because it should have already
|
||||
# been checked in the parent CMakeLists.txt
|
||||
message(FATAL_ERROR "Unsupported compiler")
|
||||
endif()
|
||||
|
||||
# Call g++ to retrieve header path
|
||||
# The -H option will let g++ outputs header dependencies to stderr, and the
|
||||
# content of stderr is saved to variable compiler_output.
|
||||
try_compile(unused_compiler_exit_code ${CMAKE_CURRENT_BINARY_DIR}
|
||||
"${template_file_path}"
|
||||
COMPILE_DEFINITIONS
|
||||
-H "-DMINGW_STDTHREADS_DETECTING_SYSTEM_HEADER=<${header_file_name}>"
|
||||
OUTPUT_VARIABLE compiler_output)
|
||||
|
||||
# Get full path to system header
|
||||
string(REGEX MATCH "[.] ([^\r\n]*)" _ "${compiler_output}")
|
||||
set(mingw_stdthreads_headers_generator_system_header "${CMAKE_MATCH_1}")
|
||||
message("Matched: <${mingw_stdthreads_headers_generator_system_header}>")
|
||||
|
||||
# Ensure file exists
|
||||
if(NOT EXISTS "${mingw_stdthreads_headers_generator_system_header}")
|
||||
message(FATAL_ERROR "<${header_file_name}>'s path not found, "
|
||||
"compiler output was:\n${compiler_output}")
|
||||
endif()
|
||||
|
||||
# Get full path to mingw-stdthreads header
|
||||
set(mingw_stdthreads_headers_generator_library_header
|
||||
"${mingw_stdthreads_folder}/mingw.${header_file_name}.h")
|
||||
|
||||
# Normalize paths
|
||||
file(TO_CMAKE_PATH "${mingw_stdthreads_headers_generator_system_header}"
|
||||
mingw_stdthreads_headers_generator_system_header)
|
||||
file(TO_CMAKE_PATH "${mingw_stdthreads_headers_generator_library_header}"
|
||||
mingw_stdthreads_headers_generator_library_header)
|
||||
|
||||
configure_file("${template_file_path}" "${destination_file_path}")
|
||||
endfunction()
|
||||
|
||||
if(EXISTS "${MINGW_STDTHREADS_DIR}")
|
||||
message("${PROJECT_NAME}: MINGW_STDTHREADS_DIR: "
|
||||
"${MINGW_STDTHREADS_DIR}")
|
||||
else()
|
||||
message(FATAL_ERROR "${PROECT_NAME}: MINGW_STDTHREADS_DIR does not "
|
||||
"exist: ${MINGW_STDTHREADS_DIR}")
|
||||
endif()
|
||||
|
||||
# <condition_variable>
|
||||
generate_mingw_stdthreads_header(condition_variable "${MINGW_STDTHREADS_DIR}")
|
||||
# <future>
|
||||
#generate_mingw_stdthreads_header(future "${MINGW_STDTHREADS_DIR}")
|
||||
# <latch>
|
||||
#generate_mingw_stdthreads_header(latch "${MINGW_STDTHREADS_DIR}")
|
||||
# <mutex>
|
||||
generate_mingw_stdthreads_header(mutex "${MINGW_STDTHREADS_DIR}")
|
||||
# <shared_mutex>
|
||||
generate_mingw_stdthreads_header(shared_mutex "${MINGW_STDTHREADS_DIR}")
|
||||
# <thread>
|
||||
generate_mingw_stdthreads_header(thread "${MINGW_STDTHREADS_DIR}")
|
||||
|
||||
# the generated headers are to be considered as a header only library
|
||||
# so we create an interface target
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE
|
||||
MINGW_STDTHREADS_GENERATED_STDHEADERS)
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE "${output_include_path}")
|
@ -0,0 +1,11 @@
|
||||
#ifdef MINGW_STDTHREADS_DETECTING_SYSTEM_HEADER
|
||||
#include MINGW_STDTHREADS_DETECTING_SYSTEM_HEADER
|
||||
static_assert(false, "Prevent compilation")
|
||||
#else
|
||||
#pragma once
|
||||
// both system header and mignw-stdthreads header should already have include
|
||||
// guards. But we still add a #pragma once just to be safe.
|
||||
|
||||
#include "${mingw_stdthreads_headers_generator_system_header}"
|
||||
#include "${mingw_stdthreads_headers_generator_library_header}"
|
||||
#endif
|
@ -0,0 +1,109 @@
|
||||
/// \file mingw.invoke.h
|
||||
/// \brief Lightweight `invoke` implementation, for C++11 and C++14.
|
||||
///
|
||||
/// (c) 2018-2019 by Nathaniel J. McClatchey, San Jose, CA, United States
|
||||
/// \author Nathaniel J. McClatchey, PhD
|
||||
///
|
||||
/// \copyright Simplified (2-clause) BSD License.
|
||||
///
|
||||
/// \note This file may become part of the mingw-w64 runtime package. If/when
|
||||
/// this happens, the appropriate license will be added, i.e. this code will
|
||||
/// become dual-licensed, and the current BSD 2-clause license will stay.
|
||||
|
||||
#ifndef MINGW_INVOKE_H_
|
||||
#define MINGW_INVOKE_H_
|
||||
|
||||
#include <type_traits> // For std::result_of, etc.
|
||||
#include <utility> // For std::forward
|
||||
#include <functional> // For std::reference_wrapper
|
||||
|
||||
namespace mingw_stdthread
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// For compatibility, implement std::invoke for C++11 and C++14
|
||||
#if __cplusplus < 201703L
|
||||
template<bool PMemFunc, bool PMemData>
|
||||
struct Invoker
|
||||
{
|
||||
template<class F, class... Args>
|
||||
inline static typename std::result_of<F(Args...)>::type invoke (F&& f, Args&&... args)
|
||||
{
|
||||
return std::forward<F>(f)(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
template<bool>
|
||||
struct InvokerHelper;
|
||||
|
||||
template<>
|
||||
struct InvokerHelper<false>
|
||||
{
|
||||
template<class T1>
|
||||
inline static auto get (T1&& t1) -> decltype(*std::forward<T1>(t1))
|
||||
{
|
||||
return *std::forward<T1>(t1);
|
||||
}
|
||||
|
||||
template<class T1>
|
||||
inline static auto get (const std::reference_wrapper<T1>& t1) -> decltype(t1.get())
|
||||
{
|
||||
return t1.get();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct InvokerHelper<true>
|
||||
{
|
||||
template<class T1>
|
||||
inline static auto get (T1&& t1) -> decltype(std::forward<T1>(t1))
|
||||
{
|
||||
return std::forward<T1>(t1);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Invoker<true, false>
|
||||
{
|
||||
template<class T, class F, class T1, class... Args>
|
||||
inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
|
||||
decltype((InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...))
|
||||
{
|
||||
return (InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Invoker<false, true>
|
||||
{
|
||||
template<class T, class F, class T1, class... Args>
|
||||
inline static auto invoke (F T::* f, T1&& t1, Args&&... args) ->\
|
||||
decltype(InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f)
|
||||
{
|
||||
return InvokerHelper<std::is_base_of<T,typename std::decay<T1>::type>::value>::get(t1).*f;
|
||||
}
|
||||
};
|
||||
|
||||
template<class F, class... Args>
|
||||
struct InvokeResult
|
||||
{
|
||||
typedef Invoker<std::is_member_function_pointer<typename std::remove_reference<F>::type>::value,
|
||||
std::is_member_object_pointer<typename std::remove_reference<F>::type>::value &&
|
||||
(sizeof...(Args) == 1)> invoker;
|
||||
inline static auto invoke (F&& f, Args&&... args) -> decltype(invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...))
|
||||
{
|
||||
return invoker::invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<class F, class...Args>
|
||||
auto invoke (F&& f, Args&&... args) -> decltype(InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...))
|
||||
{
|
||||
return InvokeResult<F, Args...>::invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
#else
|
||||
using std::invoke;
|
||||
#endif
|
||||
} // Namespace "detail"
|
||||
} // Namespace "mingw_stdthread"
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue