Skip to content

Commit

Permalink
Add Windows MinGW tests (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
alugowski authored Nov 28, 2023
1 parent 04c54e9 commit af4c45f
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 20 deletions.
17 changes: 14 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ jobs:
- os: windows-latest
# uses MSVC

- os: windows-latest
mingw-version: "13.2.0"
description: "MinGW 13"
cmake-flags: '-G "MinGW Makefiles"'

steps:
- uses: actions/checkout@v4

Expand All @@ -58,6 +63,12 @@ jobs:
with:
version: ${{ matrix.gcc-version }}

- name: Setup MinGW
if: contains(matrix.os, 'windows') && matrix.mingw-version != ''
run: |
choco install --no-progress mingw --version ${{ matrix.mingw-version }}
Add-Content $env:GITHUB_PATH "C:\ProgramData\mingw64\mingw64\bin"
- name: Setup LLVM and Clang
uses: KyleMayes/install-llvm-action@v1
if: ${{ matrix.llvm-version != '' }}
Expand All @@ -73,7 +84,7 @@ jobs:

- name: Build and Test
run: |
cmake -S . -B build/ -DCMAKE_BUILD_TYPE=Debug -DPOOLSTL_TEST=ON -DPOOLSTL_TEST_COVERAGE=ON
cmake -S . -B build/ -DCMAKE_BUILD_TYPE=Debug -DPOOLSTL_TEST=ON -DPOOLSTL_TEST_COVERAGE=ON ${{ matrix.cmake-flags }}
cmake --build build/ --config Debug
cd build/tests
ctest -C Debug --output-on-failure --verbose
Expand All @@ -85,7 +96,7 @@ jobs:
# Earliest GCC with all benchmarked methods is 9
if: matrix.gcc-version != '7' && matrix.gcc-version != '8'
run: |
cmake -S . -B bench_build/ -DCMAKE_BUILD_TYPE=Release -DPOOLSTL_BENCH=ON
cmake -S . -B bench_build/ -DCMAKE_BUILD_TYPE=Release -DPOOLSTL_BENCH=ON ${{ matrix.cmake-flags }}
cmake --build bench_build/ --config Release
cd bench_build/benchmark/
./poolstl_bench || ./Release/poolstl_bench.exe
Expand All @@ -101,7 +112,7 @@ jobs:
cp tools/poolstl.hpp include/poolstl/
mkdir -p include/poolstl/internal
cp tools/poolstl.hpp include/poolstl/internal/utils.hpp
cmake -S . -B build/ -DCMAKE_BUILD_TYPE=Debug -DPOOLSTL_TEST=ON -DPOOLSTL_TEST_COVERAGE=OFF
cmake -S . -B build/ -DCMAKE_BUILD_TYPE=Debug -DPOOLSTL_TEST=ON -DPOOLSTL_TEST_COVERAGE=OFF ${{ matrix.cmake-flags }}
cmake --build build/ --config Debug
cd build/tests
ctest -C Debug --output-on-failure --verbose
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,5 +222,12 @@ If not found then poolSTL will alias its `poolstl::par` as `std::execution::par`

Now just use `std::execution::par` as normal, and poolSTL will fill in as necessary. See [supplement_test.cpp](tests/supplement_test.cpp).

Example use case: You *can* link against TBB, so you'll use native support on GCC 9+, Clang, MSVC, etc.
**Example use case:** You *can* link against TBB, so you'll use native support on GCC 9+, Clang, MSVC, etc.
PoolSTL will fill in automatically on GCC <9 and Apple Clang.

**Example use case 2:** You'd *prefer* to use the TBB version, but don't want to fail on systems that don't have it.
Simply use the supplement as above, but have your build system (CMake, meson, etc.) check for TBB.
If not found define `POOLSTL_STD_SUPPLEMENT_NO_INCLUDE`.

If defined, the supplement will not `#include <execution>` (and neither should your code!),
thus dropping the TBB link requirement. The poolSTL supplement fills in. See the supplement section of [tests/CMakeLists.txt](tests/CMakeLists.txt) for an example.
13 changes: 9 additions & 4 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STR
set(CMAKE_CXX_FLAGS_RELEASE "-g -O3 -DNDEBUG")
endif ()

if (MINGW AND WIN32)
# MinGW on GitHub Actions requires these.
# If omitted the executable crashes with 'Exit code 0xc0000139' which appears to mean a missing DLL.
add_link_options("-static-libstdc++" "-static-libgcc")
endif()

include(FetchContent)

# Add Google Benchmark
Expand Down Expand Up @@ -33,7 +39,7 @@ add_executable(poolstl_bench
target_link_libraries(poolstl_bench benchmark::benchmark poolSTL::poolSTL)
target_compile_features(poolstl_bench PUBLIC cxx_std_17)

if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT MINGW))
# GCC and Clang require TBB for native std::execution::par
find_package(TBB)
if (TBB_FOUND)
Expand All @@ -42,10 +48,9 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STR
target_compile_definitions(poolstl_bench PUBLIC POOLSTL_BENCH_STD_PAR)
else()
message("No TBB")
# No TBB means cannot use std::execution::par
unset(HAVE_STD_EXECUTION_PAR)
endif()
else()
# MSVC requires nothing
# MSVC requires nothing.
# MinGW also requires nothing to compile std::execution::par, but performance appears to be the same as sequential.
target_compile_definitions(poolstl_bench PUBLIC POOLSTL_BENCH_STD_PAR)
endif()
21 changes: 18 additions & 3 deletions include/poolstl/poolstl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,21 @@
*
* To use this define POOLSTL_STD_SUPPLEMENT=1 before including poolstl.hpp.
*
* This aliasing will not happen if native support exists. If this autodetection fails for you,
* define POOLSTL_ALLOW_SUPPLEMENT=0 to disable this feature.
* Attempts to autodetect native support by checking for <execution>, including it if it exists, and then checking for
* the __cpp_lib_parallel_algorithm feature macro.
*
* If native support is not found then the standard execution policies are declared as forwards to poolSTL.
*
* GCC and Clang: TBB is required if <execution> is #included. If you'd like to use the poolSTL supplement in cases
* that TBB is not available, have your build system define POOLSTL_STD_SUPPLEMENT_NO_INCLUDE if TBB is not found.
* PoolSTL will then not include <execution> and the supplement will kick in.
* Your code must not #include <execution>.
*
* MinGW: the compiler declares support, but actual performance is sequential (see poolSTL benchmark). To use
* the supplement anyway define POOLSTL_STD_SUPPLEMENT_FORCE to override the autodetection.
* Your code must not #include <execution>.
*
* Define POOLSTL_ALLOW_SUPPLEMENT=0 to override POOLSTL_STD_SUPPLEMENT and disable this feature.
*/
#ifndef POOLSTL_ALLOW_SUPPLEMENT
#define POOLSTL_ALLOW_SUPPLEMENT 1
Expand All @@ -38,11 +51,13 @@

#if __cplusplus >= 201603L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201603L)
#if __has_include(<execution>)
#ifndef POOLSTL_STD_SUPPLEMENT_NO_INCLUDE
#include <execution>
#endif
#endif
#endif

#if !defined(__cpp_lib_parallel_algorithm)
#if !defined(__cpp_lib_parallel_algorithm) || defined(POOLSTL_STD_SUPPLEMENT_FORCE)
namespace std {
namespace execution {
using ::poolstl::execution::sequenced_policy;
Expand Down
39 changes: 31 additions & 8 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,25 @@
cmake_minimum_required(VERSION 3.11...3.26)
enable_testing()

# Be pedantic for clean code
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra -pedantic")
if (WIN32)
# Need bigobj because some tests use lots of templates
if (MSVC)
add_compile_options("/bigobj")
elseif(MINGW)
# Also add -Os to reduce maximum filesize
add_compile_options("-Wa,-mbig-obj" "-Os")
endif()
else()
# Be pedantic for clean code
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options("-g" "-Wall" "-Wextra" "-pedantic")
endif()
endif()

if (MINGW AND WIN32)
# The MinGW on GitHub Actions requires these.
# If omitted some executables crash with 'Exit code 0xc0000139' which appears to mean a missing DLL.
add_link_options("-static-libstdc++" "-static-libgcc")
endif()

# Code Coverage
Expand Down Expand Up @@ -55,19 +71,26 @@ add_executable(cpp11_test cpp11_test.cpp)
target_link_libraries(cpp11_test PUBLIC poolSTL::poolSTL)
target_compile_features(cpp11_test PUBLIC cxx_std_11)

# Test std::execution supplementation
# This uses only std::execution::par. On compilers with support this should result in a poolSTL no-op,
# and on ones without support it should use fallback to poolstl::par.
# Test std::execution supplementation.
# The test code uses only std::execution::par, seq, and par_unseq.
# On compilers with support poolSTL does nothing, else poolSTL creates a fallback using poolstl::par.
add_executable(supplement_test supplement_test.cpp)
target_link_libraries(supplement_test PUBLIC poolSTL::poolSTL)
target_compile_features(supplement_test PUBLIC cxx_std_17)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# GCC and Clang require TBB for std::execution::par
# GCC and Clang require TBB for std::execution::par.
# MinGW will compile std::execution::par without TBB, but performance is sequential.
find_package(TBB)
if (TBB_FOUND)
target_link_libraries(supplement_test PUBLIC TBB::tbb)
else()
message("No TBB")
target_compile_definitions(supplement_test PUBLIC POOLSTL_MISSING_NEEDED_TBB)
# Prevent including <execution>, as doing that requires linking against TBB on newer GCC/Clang.
target_compile_definitions(supplement_test PUBLIC POOLSTL_STD_SUPPLEMENT_NO_INCLUDE)
if (MINGW)
# extra hack!
# MinGW declares support, so must override poolSTL's auto-detection to enable the supplement.
target_compile_definitions(supplement_test PUBLIC POOLSTL_STD_SUPPLEMENT_FORCE)
endif()
endif()
endif()
4 changes: 3 additions & 1 deletion tests/supplement_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
// The <execution> header defines compiler-provided execution policies, but is not always present.
#if __cplusplus >= 201603L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201603L)
#if __has_include(<execution>)
#ifndef POOLSTL_MISSING_NEEDED_TBB
#ifndef POOLSTL_STD_SUPPLEMENT_NO_INCLUDE
// On GCC and Clang simply including <execution> requires linking with TBB.
// MinGW does not require TBB, but performance may be sequential. To keep parallel performance fallback to poolSTL.
#include <execution>
#endif
#endif
Expand Down

0 comments on commit af4c45f

Please sign in to comment.