Add MinGW support

This commit is contained in:
Saikari
2025-12-17 14:36:03 +03:00
parent 94ee8751af
commit 2f7746caeb
5 changed files with 427 additions and 15 deletions

View File

@@ -53,7 +53,7 @@ jobs:
############################################################################## ##############################################################################
# 2) Windows MSVC / Ninja # 2) Windows x64 MSVC (x64-windows)
############################################################################## ##############################################################################
windows-build-and-test: windows-build-and-test:
name: Windows (MSVC) (x64-windows) name: Windows (MSVC) (x64-windows)
@@ -85,6 +85,43 @@ jobs:
shell: bash shell: bash
run: ./out/Release/unit_tests.exe run: ./out/Release/unit_tests.exe
##############################################################################
# 3) Windows x86 MSVC (x86-windows)
##############################################################################
windows-x86-build-and-test:
name: Windows (MSVC) (x86-windows)
runs-on: windows-latest
env:
OMATH_BUILD_VIA_VCPKG: ON
steps:
- name: Checkout repository (with sub-modules)
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Ninja
uses: seanmiddleditch/gha-setup-ninja@v4
- name: Set up MSVC developer command-prompt
uses: ilammy/msvc-dev-cmd@v1
with:
arch: amd64_x86
- name: Configure (cmake --preset)
shell: bash
run: cmake --preset windows-release-vcpkg-x86 -DOMATH_BUILD_TESTS=ON -DOMATH_BUILD_BENCHMARK=OFF -DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
- name: Build
shell: bash
run: cmake --build cmake-build/build/windows-release-vcpkg-x86 --target unit_tests omath
- name: Run unit_tests.exe
shell: bash
run: ./out/Release/unit_tests.exe
############################################################################## ##############################################################################
# 3) macOS AppleClang / Ninja # 3) macOS AppleClang / Ninja
############################################################################## ##############################################################################
@@ -307,3 +344,168 @@ jobs:
shell: bash shell: bash
run: | run: |
cmake --build cmake-build/build/wasm-release-vcpkg --target unit_tests omath cmake --build cmake-build/build/wasm-release-vcpkg --target unit_tests omath
##############################################################################
# 7) Windows MSYS2 MinGW GCC / Ninja / x64-mingw-dynamic
##############################################################################
mingw-build-and-test:
name: MINGW64 (MSYS2) (x64-mingw-dynamic)
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
env:
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
steps:
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-cmake
mingw-w64-x86_64-ninja
mingw-w64-x86_64-pkg-config
git
base-devel
- name: Checkout repository (with sub-modules)
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up vcpkg
run: |
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
cd "$VCPKG_ROOT"
./bootstrap-vcpkg.sh
- name: Configure (cmake --preset)
run: |
cmake --preset mingw-release-vcpkg \
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
-DOMATH_BUILD_TESTS=ON \
-DOMATH_BUILD_BENCHMARK=OFF \
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
- name: Build
run: |
cmake --build cmake-build/build/mingw-release-vcpkg --target unit_tests omath
- name: Run unit_tests.exe
run: |
./out/Release/unit_tests.exe
##############################################################################
# 8) Windows UCRT64 MSYS2 MinGW GCC / Ninja / x64-mingw-dynamic
##############################################################################
mingw-ucrt-build-and-test:
name: UCRT64 (MSYS2) (x64-mingw-dynamic)
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
env:
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
steps:
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: UCRT64
update: true
install: >-
mingw-w64-ucrt-x86_64-toolchain
mingw-w64-ucrt-x86_64-cmake
mingw-w64-ucrt-x86_64-ninja
mingw-w64-ucrt-x86_64-pkg-config
git
base-devel
- name: Checkout repository (with sub-modules)
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up vcpkg
run: |
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
cd "$VCPKG_ROOT"
./bootstrap-vcpkg.sh
- name: Configure (cmake --preset)
run: |
cmake --preset mingw-release-vcpkg \
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
-DOMATH_BUILD_TESTS=ON \
-DOMATH_BUILD_BENCHMARK=OFF \
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
- name: Build
run: |
cmake --build cmake-build/build/mingw-release-vcpkg --target unit_tests omath
- name: Run unit_tests.exe
run: |
./out/Release/unit_tests.exe
##############################################################################
# 9) Windows MSYS2 MinGW32 GCC / Ninja / x86-mingw-dynamic
##############################################################################
mingw32-build-and-test:
name: MINGW32 (MSYS2) (x86-mingw-dynamic)
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
env:
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
steps:
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW32
update: true
install: >-
mingw-w64-i686-toolchain
mingw-w64-i686-cmake
mingw-w64-i686-ninja
mingw-w64-i686-pkg-config
git
base-devel
- name: Checkout repository (with sub-modules)
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up vcpkg
run: |
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
cd "$VCPKG_ROOT"
./bootstrap-vcpkg.sh
- name: Configure (cmake --preset)
run: |
cmake --preset mingw32-release-vcpkg \
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
-DOMATH_BUILD_TESTS=ON \
-DOMATH_BUILD_BENCHMARK=OFF \
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
- name: Build
run: |
cmake --build cmake-build/build/mingw32-release-vcpkg --target unit_tests omath
- name: Run unit_tests.exe
run: |
./out/Release/unit_tests.exe

View File

@@ -53,6 +53,40 @@
"OMATH_BUILD_VIA_VCPKG": "ON" "OMATH_BUILD_VIA_VCPKG": "ON"
} }
}, },
{
"name": "windows-base-vcpkg-x86",
"hidden": true,
"inherits": "windows-base",
"architecture": {
"value": "x86",
"strategy": "external"
},
"cacheVariables": {
"OMATH_BUILD_VIA_VCPKG": "ON",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"VCPKG_TARGET_TRIPLET": "x86-windows",
"VCPKG_HOST_TRIPLET": "x64-windows",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
}
},
{
"name": "windows-debug-vcpkg-x86",
"displayName": "Windows Debug Vcpkg (x86)",
"inherits": "windows-base-vcpkg-x86",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "windows-release-vcpkg-x86",
"displayName": "Windows Release Vcpkg (x86)",
"inherits": "windows-base-vcpkg-x86",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"OMATH_BUILD_VIA_VCPKG": "ON"
}
},
{ {
"name": "windows-release", "name": "windows-release",
"displayName": "Release", "displayName": "Release",
@@ -365,6 +399,160 @@
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release" "CMAKE_BUILD_TYPE": "Release"
} }
},
{
"name": "mingw-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "g++",
"CMAKE_C_COMPILER": "gcc",
"CMAKE_MAKE_PROGRAM": "ninja"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "mingw-ucrt-base-vcpkg",
"hidden": true,
"inherits": "mingw-base",
"environment": {
"VCPKG_DEFAULT_HOST_TRIPLET": "x64-mingw-dynamic"
},
"cacheVariables": {
"OMATH_BUILD_VIA_VCPKG": "ON",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"VCPKG_TARGET_TRIPLET": "x64-mingw-dynamic",
"VCPKG_HOST_TRIPLET": "x64-mingw-dynamic",
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
}
},
{
"name": "mingw-ucrt-release-vcpkg",
"displayName": "MinGW UCRT64 Release Vcpkg",
"inherits": "mingw-ucrt-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "mingw-base-vcpkg",
"hidden": true,
"inherits": "mingw-base",
"environment": {
"VCPKG_DEFAULT_HOST_TRIPLET": "x64-mingw-dynamic"
},
"cacheVariables": {
"OMATH_BUILD_VIA_VCPKG": "ON",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"VCPKG_TARGET_TRIPLET": "x64-mingw-dynamic",
"VCPKG_HOST_TRIPLET": "x64-mingw-dynamic",
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
}
},
{
"name": "mingw-debug",
"displayName": "MinGW Debug",
"inherits": "mingw-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "mingw-debug-vcpkg",
"displayName": "MinGW Debug Vcpkg",
"inherits": "mingw-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "mingw-release",
"displayName": "MinGW Release",
"inherits": "mingw-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "mingw-release-vcpkg",
"displayName": "MinGW Release Vcpkg",
"inherits": "mingw-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "mingw32-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "g++",
"CMAKE_C_COMPILER": "gcc",
"CMAKE_MAKE_PROGRAM": "ninja"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "mingw32-base-vcpkg",
"hidden": true,
"inherits": "mingw32-base",
"environment": {
"VCPKG_DEFAULT_HOST_TRIPLET": "x86-mingw-dynamic"
},
"cacheVariables": {
"OMATH_BUILD_VIA_VCPKG": "ON",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"VCPKG_TARGET_TRIPLET": "x86-mingw-dynamic",
"VCPKG_HOST_TRIPLET": "x86-mingw-dynamic",
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
}
},
{
"name": "mingw32-debug",
"displayName": "MinGW32 Debug",
"inherits": "mingw32-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "mingw32-debug-vcpkg",
"displayName": "MinGW32 Debug Vcpkg",
"inherits": "mingw32-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "mingw32-release",
"displayName": "MinGW32 Release",
"inherits": "mingw32-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "mingw32-release-vcpkg",
"displayName": "MinGW32 Release Vcpkg",
"inherits": "mingw32-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
} }
] ]
} }

View File

@@ -380,7 +380,9 @@ namespace omath
{ {
const auto det = determinant(); const auto det = determinant();
if (det == 0) constexpr Type det_epsilon = static_cast<Type>(1e-6);
if (std::abs(det) < det_epsilon)
return std::nullopt; return std::nullopt;
const auto transposed_mat = transposed(); const auto transposed_mat = transposed();

View File

@@ -8,6 +8,7 @@
#include "omath/linear_algebra/triangle.hpp" #include "omath/linear_algebra/triangle.hpp"
#include "omath/linear_algebra/vector3.hpp" #include "omath/linear_algebra/vector3.hpp"
#include "omath/projection/error_codes.hpp" #include "omath/projection/error_codes.hpp"
#include <cmath>
#include <expected> #include <expected>
#include <omath/trigonometry/angle.hpp> #include <omath/trigonometry/angle.hpp>
#include <type_traits> #include <type_traits>
@@ -229,13 +230,17 @@ namespace omath::projection
auto projected = get_view_projection_matrix() auto projected = get_view_projection_matrix()
* mat_column_from_vector<float, Mat4X4Type::get_store_ordering()>(world_position); * mat_column_from_vector<float, Mat4X4Type::get_store_ordering()>(world_position);
if (projected.at(3, 0) == 0.0f) constexpr float w_epsilon = 1e-6f;
const auto w = projected.at(3, 0);
if (w <= w_epsilon) {
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
}
projected /= projected.at(3, 0); projected /= w;
if (is_ndc_out_of_bounds(projected)) if (is_ndc_out_of_bounds(projected)) {
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
}
return Vector3<float>{projected.at(0, 0), projected.at(1, 0), projected.at(2, 0)}; return Vector3<float>{projected.at(0, 0), projected.at(1, 0), projected.at(2, 0)};
} }
@@ -244,19 +249,33 @@ namespace omath::projection
{ {
const auto inv_view_proj = get_view_projection_matrix().inverted(); const auto inv_view_proj = get_view_projection_matrix().inverted();
if (!inv_view_proj) if (!inv_view_proj) {
return std::unexpected(Error::INV_VIEW_PROJ_MAT_DET_EQ_ZERO); return std::unexpected(Error::INV_VIEW_PROJ_MAT_DET_EQ_ZERO);
}
auto inverted_projection = auto inverted_projection =
inv_view_proj.value() * mat_column_from_vector<float, Mat4X4Type::get_store_ordering()>(ndc); inv_view_proj.value() * mat_column_from_vector<float, Mat4X4Type::get_store_ordering()>(ndc);
if (!inverted_projection.at(3, 0)) constexpr float w_epsilon = 1e-6f;
const auto w = inverted_projection.at(3, 0);
if (std::abs(w) < w_epsilon) {
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
}
inverted_projection /= inverted_projection.at(3, 0); inverted_projection /= w;
return Vector3<float>{inverted_projection.at(0, 0), inverted_projection.at(1, 0), const Vector3<float> world_pos{inverted_projection.at(0, 0), inverted_projection.at(1, 0),
inverted_projection.at(2, 0)}; inverted_projection.at(2, 0)};
// Validate that the computed world position is reasonable
constexpr float max_reasonable_component = 1e6f;
if (!std::isfinite(world_pos.x) || !std::isfinite(world_pos.y)
|| !std::isfinite(world_pos.z) || std::abs(world_pos.x) > max_reasonable_component
|| std::abs(world_pos.y) > max_reasonable_component || std::abs(world_pos.z) > max_reasonable_component) {
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
}
return world_pos;
} }
template<ScreenStart screen_start = ScreenStart::TOP_LEFT_CORNER> template<ScreenStart screen_start = ScreenStart::TOP_LEFT_CORNER>
@@ -290,7 +309,8 @@ namespace omath::projection
template<class Type> template<class Type>
[[nodiscard]] constexpr static bool is_ndc_out_of_bounds(const Type& ndc) noexcept [[nodiscard]] constexpr static bool is_ndc_out_of_bounds(const Type& ndc) noexcept
{ {
return std::ranges::any_of(ndc.raw_array(), [](const auto& val) { return val < -1 || val > 1; }); constexpr float eps = 1e-5f;
return std::ranges::any_of(ndc.raw_array(), [](const auto& val) { return val < -1.0f - eps || val > 1.0f + eps; });
} }
// NDC REPRESENTATION: // NDC REPRESENTATION:
@@ -347,7 +367,7 @@ namespace omath::projection
if constexpr (screen_start == ScreenStart::TOP_LEFT_CORNER) if constexpr (screen_start == ScreenStart::TOP_LEFT_CORNER)
return {screen_pos.x / m_view_port.m_width * 2.f - 1.f, 1.f - screen_pos.y / m_view_port.m_height * 2.f, return {screen_pos.x / m_view_port.m_width * 2.f - 1.f, 1.f - screen_pos.y / m_view_port.m_height * 2.f,
screen_pos.z}; screen_pos.z};
else if (screen_start == ScreenStart::BOTTOM_LEFT_CORNER) else if constexpr (screen_start == ScreenStart::BOTTOM_LEFT_CORNER)
return {screen_pos.x / m_view_port.m_width * 2.f - 1.f, return {screen_pos.x / m_view_port.m_width * 2.f - 1.f,
(screen_pos.y / m_view_port.m_height - 0.5f) * 2.f, screen_pos.z}; (screen_pos.y / m_view_port.m_height - 0.5f) * 2.f, screen_pos.z};
else else

View File

@@ -23,7 +23,7 @@ else() # GTest is being linked as vcpkg package
target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest GTest::gtest_main omath::omath) target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest GTest::gtest_main omath::omath)
endif() endif()
# Skip test discovery for Android builds - binaries cannot run on host # Skip test discovery for Android/iOS builds or when cross-compiling - binaries cannot run on host
if (NOT (CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME STREQUAL "iOS")) if (NOT (ANDROID OR IOS))
gtest_discover_tests(${PROJECT_NAME}) gtest_discover_tests(${PROJECT_NAME})
endif() endif()