[geos-commits] [SCM] GEOS branch main updated. ad73047bf08756f0786c920358059fe3b9c5fa02

git at osgeo.org git at osgeo.org
Sun Dec 7 13:54:47 PST 2025


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".

The branch, main has been updated
       via  ad73047bf08756f0786c920358059fe3b9c5fa02 (commit)
      from  cdc6dbd6def66a73ad89d2dcf4f01893afe1f94c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit ad73047bf08756f0786c920358059fe3b9c5fa02
Author: Mike Taves <mwtoews at gmail.com>
Date:   Mon Dec 8 10:53:37 2025 +1300

    Refactor FE_ macro checks for Emscripten; add CI job (#1333)
    
    * Refactor FE_ macro checks for Emscripten; add CI job
    * Re-introduce HAVE_FENV via opt-in MISSING_FENV define
    * Check for cfenv C++ header instead of fenv.h C header

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 69b0b8601..6a68e6351 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -485,6 +485,49 @@ jobs:
       working-directory: ./build
       run: ctest -V --output-on-failure -C ${{ matrix.build_type }}
 
+  emscripten:
+    name: Emscripten WASM build
+    runs-on: ubuntu-latest
+    steps:
+    - name: Install
+      run: |
+        set -e
+        sudo -E apt-get update
+        sudo -E apt-get autopurge -y needrestart
+        sudo -E apt-get -yq --no-install-suggests --no-install-recommends install make cmake emscripten ccache
+
+    - uses: actions/checkout at v5
+
+    - name: Retrieve build cache
+      uses: actions/cache/restore at v4
+      id: restore-cache
+      with:
+        path: .ccache
+        key: emscripten-${{ github.ref_name }}-${{ github.run_id }}
+        restore-keys: emscripten
+
+    - name: Build
+      run: |
+        set -e
+        mkdir build
+        cd build
+        cmake --version
+        emcmake cmake \
+          -D BUILD_SHARED_LIBS=OFF \
+          -D USE_CCACHE=ON \
+          ..
+        cmake --build . -j $(nproc)
+        ccache --show-stats
+
+    - name: Save build cache
+      uses: actions/cache/save at v4
+      with:
+        path: .ccache
+        key: ${{ steps.restore-cache.outputs.cache-primary-key }}
+
+#    - name: Test
+#      working-directory: ./build
+#      run: ctest --output-on-failure
 
   code-quality:
     name: Code quality checks
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 79d397efb..852c724ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -335,6 +335,12 @@ set(CMAKE_CXX_FLAGS_COVERAGE "-fprofile-arcs -ftest-coverage")
 include(CheckLibraryExists)
 check_library_exists(m pow "" HAVE_LIBM)
 
+#-----------------------------------------------------------------------------
+# Extra include
+#-----------------------------------------------------------------------------
+include(CheckIncludeFileCXX)
+check_include_file_cxx(cfenv HAVE_FENV_H)
+
 #-----------------------------------------------------------------------------
 # Target geos: C++ API library
 #-----------------------------------------------------------------------------
@@ -576,10 +582,3 @@ if(PROJECT_IS_TOP_LEVEL)
 
   unset(_is_multi_config_generator)
 endif()  # PROJECT_IS_TOP_LEVEL
-
-include(CheckIncludeFile)
-check_include_file(fenv.h HAVE_FENV_H)
-
-if(HAVE_FENV_H)
-    target_compile_definitions(geos_cxx_flags INTERFACE HAVE_FENV)
-endif()
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 063c408ff..ecaa63d2f 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -63,6 +63,11 @@ foreach(_testfile ${_testfiles})
     set_tests_properties(unit-${_cmake_testname} PROPERTIES TIMEOUT 30)
 endforeach()
 
+if(NOT HAVE_FENV_H)
+  # Used to set HAVE_FENV in test files
+  add_compile_definitions(MISSING_FENV)
+endif()
+
 # Run all the unit tests in one go, for faster memory checking
 # under valgrind. Restrict to one configuration so it is only
 # run with 'ctest -C Valgrind'
diff --git a/tests/unit/algorithm/distance/DiscreteHausdorffDistanceTest.cpp b/tests/unit/algorithm/distance/DiscreteHausdorffDistanceTest.cpp
index f50b58680..8e85bf0a4 100644
--- a/tests/unit/algorithm/distance/DiscreteHausdorffDistanceTest.cpp
+++ b/tests/unit/algorithm/distance/DiscreteHausdorffDistanceTest.cpp
@@ -16,7 +16,10 @@
 #include <cmath>
 #include <string>
 #include <memory>
+#if !defined(MISSING_FENV)
+#define HAVE_FENV
 #include <cfenv>
+#endif
 
 namespace geos {
 namespace geom {
@@ -191,13 +194,17 @@ template<>
 void object::test<6>
 ()
 {
+#ifdef HAVE_FENV
     std::feclearexcept(FE_ALL_EXCEPT);
+#endif
 
     runTest(
         "LINESTRING (0 0, 100 0, 10 100, 10 100)",
         "LINESTRING (0 100, 0 10, 80 10)", 0.001, 47.89);
 
+#ifdef FE_INVALID
     ensure("FE_INVALID raised", !std::fetestexcept(FE_INVALID));
+#endif
 }
 
 // Crash on collection with empty components
diff --git a/tests/unit/capi/GEOSDistanceTest.cpp b/tests/unit/capi/GEOSDistanceTest.cpp
index f5f5e1471..152aade8b 100644
--- a/tests/unit/capi/GEOSDistanceTest.cpp
+++ b/tests/unit/capi/GEOSDistanceTest.cpp
@@ -9,7 +9,10 @@
 #include <algorithm>
 #include <cstdio>
 #include <cstdlib>
+#if !defined(MISSING_FENV)
+#define HAVE_FENV
 #include <fenv.h>
+#endif
 #include <cmath>
 
 #include "capi_test_utils.h"
@@ -119,8 +122,10 @@ void object::test<4>
     geom1_ = fromWKT("POINT (0 0)");
     geom2_ = fromWKT("POINT (1 1)");
 
+#ifdef HAVE_FENV
     // clear all floating point exceptions
     feclearexcept (FE_ALL_EXCEPT);
+#endif
 
     double d;
     int status = GEOSDistance(geom1_, geom2_, &d);
@@ -128,9 +133,11 @@ void object::test<4>
     ensure_equals(status, 1);
     ensure_equals(d, std::sqrt(2));
 
+#ifdef FE_OVERFLOW
     // check for floating point overflow exceptions
     int raised = fetestexcept(FE_OVERFLOW);
     ensure_equals(raised & FE_OVERFLOW, 0);
+#endif
 }
 
 // same distance between boundables should not raise floating point exception
@@ -142,8 +149,10 @@ void object::test<5>
     geom1_ = fromWKT("LINESTRING (0 0, 1 1)");
     geom2_ = fromWKT("LINESTRING (2 1, 1 2)");
 
+#ifdef HAVE_FENV
     // clear all floating point exceptions
     feclearexcept (FE_ALL_EXCEPT);
+#endif
 
     double d;
     int status = GEOSDistance(geom1_, geom2_, &d);
@@ -151,9 +160,11 @@ void object::test<5>
     ensure_equals(status, 1);
     // ensure_equals(d, std::sqrt(2));
 
+#ifdef FE_OVERFLOW
     // check for floating point overflow exceptions
     int raised = fetestexcept(FE_OVERFLOW);
     ensure_equals(raised & FE_OVERFLOW, 0);
+#endif
 }
 
 template<>
diff --git a/tests/unit/capi/GEOSIntersectionTest.cpp b/tests/unit/capi/GEOSIntersectionTest.cpp
index c94b056a7..4a03845df 100644
--- a/tests/unit/capi/GEOSIntersectionTest.cpp
+++ b/tests/unit/capi/GEOSIntersectionTest.cpp
@@ -140,7 +140,9 @@ void object::test<7>
 
     result_ = GEOSIntersection(geom1_, geom2_);
 
+#ifdef FE_INVALID
     ensure(!std::fetestexcept(FE_INVALID));
+#endif
 }
 
 template<>
diff --git a/tests/unit/capi/GEOSProjectTest.cpp b/tests/unit/capi/GEOSProjectTest.cpp
index af8640f8b..d2556a897 100644
--- a/tests/unit/capi/GEOSProjectTest.cpp
+++ b/tests/unit/capi/GEOSProjectTest.cpp
@@ -100,14 +100,22 @@ void object::test<5>
     geom1_ = GEOSGeomFromWKT("LINESTRING (0 0, 1 1, 1 1, 2 2)");
     geom2_ = GEOSGeomFromWKT("POINT (0 1)");
 
+#ifdef HAVE_FENV
     std::feclearexcept(FE_ALL_EXCEPT);
+#endif
     double dist = GEOSProject(geom1_, geom2_);
+#ifdef FE_INVALID
     ensure("FE_INVALID raised", !std::fetestexcept(FE_INVALID));
+#endif
     ensure_equals("GEOSProject", dist, 0.7071, 0.0001);
 
+#ifdef HAVE_FENV
     std::feclearexcept(FE_ALL_EXCEPT);
+#endif
     double dist_norm = GEOSProjectNormalized(geom1_, geom2_);
+#ifdef FE_INVALID
     ensure("FE_INVALID raised", !std::fetestexcept(FE_INVALID));
+#endif
     ensure_equals("GEOSProjectNormalized", dist_norm, 0.25);
 }
 
diff --git a/tests/unit/capi/GEOSVoronoiDiagramTest.cpp b/tests/unit/capi/GEOSVoronoiDiagramTest.cpp
index 7c5b05bcd..d79181351 100644
--- a/tests/unit/capi/GEOSVoronoiDiagramTest.cpp
+++ b/tests/unit/capi/GEOSVoronoiDiagramTest.cpp
@@ -5,7 +5,10 @@
 // geos
 #include <geos_c.h>
 // std
+#if !defined(MISSING_FENV)
+#define HAVE_FENV
 #include <cfenv>
+#endif
 
 #include "capi_test_utils.h"
 
@@ -57,7 +60,9 @@ template<>
 void object::test<1>
 ()
 {
+#ifdef HAVE_FENV
     std::feclearexcept(FE_ALL_EXCEPT);
+#endif
 
     geom1_ = GEOSGeomFromWKT("POINT(10 20)");
 
@@ -69,7 +74,9 @@ void object::test<1>
     geom2_ = GEOSVoronoiDiagram(geom1_, nullptr, 0, 1);
     ensure_geometry_equals(geom2_, "MULTILINESTRING EMPTY");
 
+#ifdef FE_INVALID
     ensure("FE_INVALID raised", !std::fetestexcept(FE_INVALID));
+#endif
 }
 
 //More points:
diff --git a/tests/unit/capi/capi_test_utils.h b/tests/unit/capi/capi_test_utils.h
index 67818d6a1..0b8d03284 100644
--- a/tests/unit/capi/capi_test_utils.h
+++ b/tests/unit/capi/capi_test_utils.h
@@ -7,7 +7,10 @@
 
 #include <cstdarg>
 #include <cstdio>
+#if !defined(MISSING_FENV)
+#define HAVE_FENV
 #include <cfenv>
+#endif
 
 
 namespace capitest {
@@ -29,7 +32,9 @@ namespace capitest {
             wktw_ = GEOSWKTWriter_create();
             GEOSWKTWriter_setRoundingPrecision(wktw_, 10);
 
+#ifdef HAVE_FENV
             std::feclearexcept(FE_ALL_EXCEPT);
+#endif
         }
 
         ~utility()
diff --git a/tests/unit/geom/EnvelopeTest.cpp b/tests/unit/geom/EnvelopeTest.cpp
index a816f84f3..1e9385e81 100644
--- a/tests/unit/geom/EnvelopeTest.cpp
+++ b/tests/unit/geom/EnvelopeTest.cpp
@@ -8,7 +8,10 @@
 #include <geos/geom/Coordinate.h>
 
 #include <array>
+#if !defined(MISSING_FENV)
+#define HAVE_FENV
 #include <cfenv>
+#endif
 #include <unordered_set>
 
 namespace tut {
@@ -23,7 +26,9 @@ using geos::geom::Envelope;
 struct test_envelope_data {
     test_envelope_data()
     {
+#ifdef HAVE_FENV
         std::feclearexcept(FE_ALL_EXCEPT);
+#endif
     }
 
     static std::size_t
@@ -91,11 +96,21 @@ struct test_envelope_data {
     static void
     ensure_no_fp_except()
     {
+#ifdef FE_DIVBYZERO
         ensure("FE_DIVBYZERO raised", !std::fetestexcept(FE_DIVBYZERO));
+#endif
+//#ifdef FE_INEXACT
         //ensure("FE_INEXACT raised", !std::fetestexcept(FE_INEXACT));
+//#endif
+#ifdef FE_INVALID
         ensure("FE_INVALID raised", !std::fetestexcept(FE_INVALID));
+#endif
+#ifdef FE_OVERFLOW
         ensure("FE_OVERFLOW raised", !std::fetestexcept(FE_OVERFLOW));
+#endif
+#ifdef FE_UNDERFLOW
         ensure("FE_UNDERFLOW raised", !std::fetestexcept(FE_UNDERFLOW));
+#endif
     }
 };
 
diff --git a/tests/unit/operation/overlayng/CoverageUnionNGTest.cpp b/tests/unit/operation/overlayng/CoverageUnionNGTest.cpp
index 27279708e..66865b349 100644
--- a/tests/unit/operation/overlayng/CoverageUnionNGTest.cpp
+++ b/tests/unit/operation/overlayng/CoverageUnionNGTest.cpp
@@ -9,7 +9,10 @@
 #include <geos/util.h>
 
 // std
+#if !defined(MISSING_FENV)
+#define HAVE_FENV
 #include <cfenv>
+#endif
 #include <memory>
 
 using namespace geos::geom;
@@ -33,9 +36,13 @@ struct test_coverageunionng_data {
     {
         std::unique_ptr<Geometry> geom = r.read(wkt);
         std::unique_ptr<Geometry> expected = r.read(wktExpected);
+#ifdef HAVE_FENV
         std::feclearexcept(FE_ALL_EXCEPT);
+#endif
         std::unique_ptr<Geometry> result = CoverageUnion::geomunion(geom.get());
+#ifdef FE_INVALID
         ensure("FE_INVALID raised", !std::fetestexcept(FE_INVALID));
+#endif
 
         try {
             ensure_equals_geometry_xyzm(result.get(), expected.get());
diff --git a/util/geosop/CMakeLists.txt b/util/geosop/CMakeLists.txt
index 165727460..2351fc6ff 100644
--- a/util/geosop/CMakeLists.txt
+++ b/util/geosop/CMakeLists.txt
@@ -16,6 +16,10 @@ add_executable(geosop
 
 target_link_libraries(geosop PRIVATE geos geos_c)
 
+if(NOT HAVE_FENV_H)
+  target_compile_definitions(geosop PRIVATE MISSING_FENV)
+endif()
+
 install(TARGETS geosop
   DESTINATION ${CMAKE_INSTALL_BINDIR}
 )
diff --git a/util/geosop/GeosOp.cpp b/util/geosop/GeosOp.cpp
index 97db2c3f8..b6c0d0a9f 100644
--- a/util/geosop/GeosOp.cpp
+++ b/util/geosop/GeosOp.cpp
@@ -26,7 +26,8 @@
 #include <geos/io/WKBStreamReader.h>
 #include <geos/io/WKBWriter.h>
 
-#if defined(HAVE_FENV)
+#if !defined(MISSING_FENV)
+#define HAVE_FENV
 #include <cfenv>
 #endif
 #include <fstream>
@@ -399,30 +400,44 @@ void GeosOp::run(OpArguments& opArgs) {
     //------------------------
 
     try {
-#if defined(HAVE_FENV)
+#ifdef HAVE_FENV
         std::feclearexcept(FE_ALL_EXCEPT); // clear floating-point status flags
-#endif
 
         execute(op, opArgs);
 
-#if defined(HAVE_FENV)
+#ifdef FE_INEXACT
         // Catch everything except for FE_INEXACT, which is usually harmless
         const int fpexp = std::fetestexcept(FE_ALL_EXCEPT ^ FE_INEXACT);
+#else
+        const int fpexp = std::fetestexcept(FE_ALL_EXCEPT);
+#endif
         if (args.isVerbose && (fpexp != 0)) {
             std::cerr << "Operation raised floating-point environment flag(s):";
+#ifdef FE_DIVBYZERO
             if (fpexp & FE_DIVBYZERO)
                 std::cerr << " FE_DIVBYZERO";
+#endif
+#ifdef FE_INEXACT
             if (fpexp & FE_INEXACT)
                 std::cerr << " FE_INEXACT";
+#endif
+#ifdef FE_INVALID
             if (fpexp & FE_INVALID)
                 std::cerr << " FE_INVALID";
+#endif
+#ifdef FE_OVERFLOW
             if (fpexp & FE_OVERFLOW)
                 std::cerr << " FE_OVERFLOW";
+#endif
+#ifdef FE_UNDERFLOW
             if (fpexp & FE_UNDERFLOW)
                 std::cerr << " FE_UNDERFLOW";
+#endif
             std::cerr << std::endl;
         }
-#endif
+#else  // MISSING_FENV
+        execute(op, opArgs);
+#endif  // HAVE_FENV
     }
     catch (std::exception &e) {
         std::cerr << "Run-time exception: " << e.what() << std::endl;

-----------------------------------------------------------------------

Summary of changes:
 .github/workflows/ci.yml                           | 43 ++++++++++++++++++++++
 CMakeLists.txt                                     | 13 +++----
 tests/unit/CMakeLists.txt                          |  5 +++
 .../distance/DiscreteHausdorffDistanceTest.cpp     |  7 ++++
 tests/unit/capi/GEOSDistanceTest.cpp               | 11 ++++++
 tests/unit/capi/GEOSIntersectionTest.cpp           |  2 +
 tests/unit/capi/GEOSProjectTest.cpp                |  8 ++++
 tests/unit/capi/GEOSVoronoiDiagramTest.cpp         |  7 ++++
 tests/unit/capi/capi_test_utils.h                  |  5 +++
 tests/unit/geom/EnvelopeTest.cpp                   | 15 ++++++++
 .../operation/overlayng/CoverageUnionNGTest.cpp    |  7 ++++
 util/geosop/CMakeLists.txt                         |  4 ++
 util/geosop/GeosOp.cpp                             | 25 ++++++++++---
 13 files changed, 140 insertions(+), 12 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list