From ac2a14e885fce5a6d3e1144f8d45137bf84e8383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 25 Jun 2025 15:31:54 -0700 Subject: [PATCH 01/79] Update runner images --- .github/workflows/continuous.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 435d0fe9..7c1653e1 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-13, macos-14] + os: [ubuntu-24.04, macos-13, macos-15] config: [RelwithDebInfo, Debug] compiler: [gcc, apple, llvm] sanitizer: ["Address", "Thread"] # TODO: Add Memory+Undefined Sanitizer @@ -35,9 +35,9 @@ jobs: sanitizer: Thread - os: macos-13 config: Debug - - os: macos-14 + - os: macos-15 compiler: gcc - - os: ubuntu-22.04 + - os: ubuntu-24.04 compiler: apple steps: - name: Free Disk Space @@ -140,8 +140,8 @@ jobs: #################### Windows: - name: windows-2022 (${{ matrix.config }}) - runs-on: windows-2022 + name: windows-2025 (${{ matrix.config }}) + runs-on: windows-2025 strategy: fail-fast: false matrix: From b79cc2111fe7d96e51a9821a994f771e4cfb9fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 25 Jun 2025 15:47:20 -0700 Subject: [PATCH 02/79] Update runner images --- .github/workflows/continuous.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 7c1653e1..2ed10f58 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -91,11 +91,17 @@ jobs: fi - name: Setup Xcode version - if: runner.os == 'macOS' + if: matrix.os == 'macos-13' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '15.2' + - name: Setup Xcode version + if: matrix.os == 'macos-15' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '16.4' + - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores From 456453eb9c49edd0f7fdc2f4cd0c0927ed82f484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 25 Jun 2025 15:59:13 -0700 Subject: [PATCH 03/79] Update runner images --- .github/workflows/wheel.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index 5302ee97..e44be880 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-13, macos-14, windows-2022] + os: [ubuntu-24.04, macos-13, macos-15, windows-2025] name: ${{matrix.os}} runs-on: ${{matrix.os}} @@ -23,11 +23,17 @@ jobs: uses: actions/checkout@v4 - name: Setup Xcode version - if: runner.os == 'macOS' + if: matrix.os == 'macos-13' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '15.2' + - name: Setup Xcode version + if: matrix.os == 'macos-15' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '16.4' + - name: Setup MSVC if: runner.os == 'windows' uses: ilammy/msvc-dev-cmd@v1 From afe5925b0cc1adff564083e4a2874bb7b9042dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 07:49:35 -0800 Subject: [PATCH 04/79] Silence gcc warning. --- modules/core/src/compute_area.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/core/src/compute_area.cpp b/modules/core/src/compute_area.cpp index 9c77ffff..0ba79d8b 100644 --- a/modules/core/src/compute_area.cpp +++ b/modules/core/src/compute_area.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include // clang-format off @@ -348,8 +349,10 @@ AttributeId compute_facet_vector_area( auto f = mesh.get_facet_vertices(fid); for (Index lv = 0; lv < f_size; lv++) { Index lv_next = (lv + 1) % f_size; + LA_IGNORE_ARRAY_BOUNDS_BEGIN vector_area.row(fid) += vertices.row(f[lv]).template head<3>().cross( vertices.row(f[lv_next]).template head<3>()); + LA_IGNORE_ARRAY_BOUNDS_END } }); vector_area /= 2; From 4c69226f8ea89a3e7613392f4c1b3a560a6db5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Thu, 13 Nov 2025 08:29:46 -0800 Subject: [PATCH 05/79] Sync with 96afce5 (#76) --- cmake/lagrange/lagrange_cpm_cache.cmake | 3 ++- cmake/lagrange/lagrange_tbb_sanitizers.cmake | 7 ++++-- cmake/recipes/external/assimp.cmake | 4 ++- cmake/recipes/external/assimp.patch | 25 +++++++++++++++---- .../testing/include/lagrange/testing/common.h | 4 ++- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/cmake/lagrange/lagrange_cpm_cache.cmake b/cmake/lagrange/lagrange_cpm_cache.cmake index 6c34f303..4b2953dd 100644 --- a/cmake/lagrange/lagrange_cpm_cache.cmake +++ b/cmake/lagrange/lagrange_cpm_cache.cmake @@ -14,7 +14,8 @@ if(DEFINED ENV{CPM_SOURCE_CACHE}) set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) else() # Set CPM cache folder if unset - file(REAL_PATH "~/.cache/CPM" CPM_SOURCE_CACHE_DEFAULT EXPAND_TILDE) + file(REAL_PATH "~" HOME_DIR EXPAND_TILDE) + cmake_path(APPEND HOME_DIR ".cache/CPM" OUTPUT_VARIABLE CPM_SOURCE_CACHE_DEFAULT) endif() set(CPM_SOURCE_CACHE diff --git a/cmake/lagrange/lagrange_tbb_sanitizers.cmake b/cmake/lagrange/lagrange_tbb_sanitizers.cmake index 66a23381..1ee91815 100644 --- a/cmake/lagrange/lagrange_tbb_sanitizers.cmake +++ b/cmake/lagrange/lagrange_tbb_sanitizers.cmake @@ -10,7 +10,11 @@ # governing permissions and limitations under the License. # -# Set TBB_SANITIZE based on the USE_SANITIZER option +# Set TBB_SANITIZE based on the USE_SANITIZER option. Even though global options are already enabled +# by our sanitizers.cmake script, setting the TBB_SANITIZE option will let OneTBB disable elements +# incompatible with TSan, such as ITT notifications and LTO: +# https://github.com/uxlfoundation/oneTBB/blob/0cd32ab10a84eabf780bb699b17430deb028c0a4/src/tbbmalloc/CMakeLists.txt#L42 +# https://github.com/uxlfoundation/oneTBB/blob/0cd32ab10a84eabf780bb699b17430deb028c0a4/CMakeLists.txt#L254 set(TBB_SANITIZE "") if(USE_SANITIZER) if(UNIX) @@ -29,7 +33,6 @@ if(USE_SANITIZER) elseif(MSVC) if(USE_SANITIZER MATCHES "([Aa]ddress)") set(TBB_SANITIZE "address -fno-omit-frame-pointer") - else() endif() endif() endif() diff --git a/cmake/recipes/external/assimp.cmake b/cmake/recipes/external/assimp.cmake index a453ea97..74214b2c 100644 --- a/cmake/recipes/external/assimp.cmake +++ b/cmake/recipes/external/assimp.cmake @@ -43,12 +43,14 @@ include(CPM) CPMAddPackage( NAME assimp GITHUB_REPOSITORY assimp/assimp - GIT_TAG 2f3e72413f25897c1903e883a94fa5cf4293e26b + GIT_TAG v6.0.2 PATCHES # Prevent Assimp from meddling with compiler flags in debug mode. # See internal lagrange-lib/#1303 for more details. # Remember to update this patch when updating Assimp. + # This patch also fixes the compilation issue related to contrib/zlib. + # See https://github.com/assimp/assimp/issues/6118 assimp.patch ) diff --git a/cmake/recipes/external/assimp.patch b/cmake/recipes/external/assimp.patch index cf73bd92..4ece804b 100644 --- a/cmake/recipes/external/assimp.patch +++ b/cmake/recipes/external/assimp.patch @@ -1,8 +1,8 @@ -diff --git i/CMakeLists.txt w/CMakeLists.txt -index 517a957f4..0f8594369 100644 ---- i/CMakeLists.txt -+++ w/CMakeLists.txt -@@ -339,7 +339,6 @@ ELSEIF(MSVC) +diff --git a/CMakeLists.txt b/CMakeLists.txt +index cd8f515..90b782a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -343,7 +343,6 @@ ELSEIF(MSVC) ENDIF() # supress warning for double to float conversion if Double precision is activated ADD_COMPILE_OPTIONS(/wd4244) @@ -10,3 +10,18 @@ index 517a957f4..0f8594369 100644 # Allow user to disable PDBs if(ASSIMP_INSTALL_PDB) SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") +diff --git a/contrib/zlib/zutil.h b/contrib/zlib/zutil.h +index 0bc7f4e..e93e4bf 100644 +--- a/contrib/zlib/zutil.h ++++ b/contrib/zlib/zutil.h +@@ -142,10 +142,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + # ifndef Z_SOLO + # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os + # include /* for fdopen */ +-# else +-# ifndef fdopen +-# define fdopen(fd,mode) NULL /* No fdopen() */ +-# endif + # endif + # endif + #endif diff --git a/modules/testing/include/lagrange/testing/common.h b/modules/testing/include/lagrange/testing/common.h index ee494bd5..238ab632 100644 --- a/modules/testing/include/lagrange/testing/common.h +++ b/modules/testing/include/lagrange/testing/common.h @@ -164,7 +164,9 @@ SurfaceMesh load_surface_mesh(const fs::path& relative_path) { auto full_path = get_data_path(relative_path); REQUIRE(lagrange::fs::exists(full_path)); - return lagrange::io::load_mesh>(full_path); + io::LoadOptions options; + options.quiet = true; + return lagrange::io::load_mesh>(full_path, options); } /// From 5828f000f6b0cc6aab2b05c2998c8066a28442c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 09:13:36 -0800 Subject: [PATCH 06/79] Update Eigen to patch release. --- cmake/recipes/external/Eigen3.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index cdbcca7b..bc86f2ae 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -26,7 +26,7 @@ else() CPMAddPackage( NAME eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git - GIT_TAG 3.4.0 + GIT_TAG 3.4.1 DOWNLOAD_ONLY ON ) set(EIGEN_INCLUDE_DIRS ${eigen_SOURCE_DIR}) From 1629c366ab91080ee1793e606b6ceb569d6d6477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 10:59:17 -0800 Subject: [PATCH 07/79] Try to use /Zi with sccache... --- .github/workflows/continuous.yaml | 1 + CMakeLists.txt | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index eb0ea024..114b9e24 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -202,6 +202,7 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ + -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=$<$:ProgramDatabase> ^ -B "C:/build" ^ -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 9729fde7..a433ffd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,9 @@ set_property(CACHE LAGRANGE_CCACHE_PROGRAM PROPERTY STRINGS ${LAGRANGE_CCACHE_PR # Enable sscache if available if((LAGRANGE_CCACHE_PROGRAM STREQUAL "sccache") AND SCCACHE_PROGRAM) message(STATUS "Using sccache: ${SCCACHE_PROGRAM}") - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") + if(NOT DEFINED CMAKE_MSVC_DEBUG_INFORMATION_FORMAT) + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") + endif() foreach(lang IN ITEMS C CXX) set(CMAKE_${lang}_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env ${ccacheEnv} ${SCCACHE_PROGRAM} @@ -79,6 +81,8 @@ if((LAGRANGE_CCACHE_PROGRAM STREQUAL "ccache") AND CCACHE_PROGRAM) CCACHE_SLOPPINESS=clang_index_store,include_file_ctime,include_file_mtime,locale,pch_defines,time_macros ) message(STATUS "Using ccache: ${CCACHE_PROGRAM}") + # ccache does not yet support /Zi on Windows: + # https://github.com/ccache/ccache/issues/1040 set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") foreach(lang IN ITEMS C CXX) set(CMAKE_${lang}_COMPILER_LAUNCHER From bd96fdd2d0be07ebc2694f52c32b05d854b2d7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 11:39:17 -0800 Subject: [PATCH 08/79] Fix syntax. --- .github/workflows/continuous.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 114b9e24..ac8cb6e9 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -193,6 +193,9 @@ jobs: # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) + # windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 + # https://github.com/actions/runner-images/issues/12609 + # https://github.com/actions/runner-images/issues/12199 - name: Configure and build shell: cmd run: | @@ -202,7 +205,7 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=$<$:ProgramDatabase> ^ + -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT='$<$:ProgramDatabase>' ^ -B "C:/build" ^ -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} From 79a5175cc6dd6626bd8d8206b85eee62bf06c1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 11:51:00 -0800 Subject: [PATCH 09/79] Fix syntax again. --- .github/workflows/continuous.yaml | 4 ---- CMakeLists.txt | 8 ++++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index ac8cb6e9..eb0ea024 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -193,9 +193,6 @@ jobs: # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - # windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 - # https://github.com/actions/runner-images/issues/12609 - # https://github.com/actions/runner-images/issues/12199 - name: Configure and build shell: cmd run: | @@ -205,7 +202,6 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT='$<$:ProgramDatabase>' ^ -B "C:/build" ^ -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index a433ffd5..55e7e82c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,14 @@ endif() set(LAGRANGE_CCACHE_PROGRAMS none ccache sccache) set_property(CACHE LAGRANGE_CCACHE_PROGRAM PROPERTY STRINGS ${LAGRANGE_CCACHE_PROGRAMS}) +# windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 +# https://github.com/actions/runner-images/issues/12609 +# https://github.com/actions/runner-images/issues/12199 +if($ENV{GITHUB_ACTIONS}) + message(STATUS "GitHub Runner detected: setting /Zi on Windows to save disk space") + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") +endif() + # Enable sscache if available if((LAGRANGE_CCACHE_PROGRAM STREQUAL "sccache") AND SCCACHE_PROGRAM) message(STATUS "Using sccache: ${SCCACHE_PROGRAM}") From fe6f41c623118c641c7dc0485ff02b6acd464657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 11:53:58 -0800 Subject: [PATCH 10/79] Update OneTBB version. --- cmake/recipes/external/onetbb.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/onetbb.cmake b/cmake/recipes/external/onetbb.cmake index f7a3911b..9bb4ddf4 100644 --- a/cmake/recipes/external/onetbb.cmake +++ b/cmake/recipes/external/onetbb.cmake @@ -72,7 +72,7 @@ function(onetbb_import_target) CPMAddPackage( NAME tbb GITHUB_REPOSITORY oneapi-src/oneTBB - GIT_TAG v2021.13.0 + GIT_TAG v2022.3.0 ) # TODO: This might break with future versions of onetbb. Onetbb should eventually add a proper cmake option to turn wasm threads on/off. From fc3e6f89d434d7d3d13f2672e6f8a95caf307b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 14:05:43 -0800 Subject: [PATCH 11/79] Run ncdu after build --- .github/workflows/continuous.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index eb0ea024..9d730271 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -206,5 +206,20 @@ jobs: -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} + - name: Run ncdu + shell: msys2 {0} + if: always() + run: | + ncdu -0 -o ${{ matrix.config }}-C.json /C + ncdu -0 -o ${{ matrix.config }}-D.json /D + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.config }} + path: | + ${{ matrix.config }}-C.json + ${{ matrix.config }}-D.json + - name: Tests run: cd "C:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} From f2e40ab17710474ba1e31cab1dd81c658ac985d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 14:11:13 -0800 Subject: [PATCH 12/79] Print disk usage. --- .github/workflows/continuous.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 9d730271..58e9fcc9 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -191,6 +191,11 @@ jobs: # Scoop modifies the PATH so we make it available for the next steps of the job echo "${env:PATH}" >> ${env:GITHUB_PATH} + - name: Print disk usage + run: | + echo "disk usage:" + df -h + # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - name: Configure and build @@ -206,6 +211,12 @@ jobs: -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} + - name: Print disk usage + if: always() + run: | + echo "disk usage:" + df -h + - name: Run ncdu shell: msys2 {0} if: always() From 86db1de98895ab1e9170d7d07d586c7414b20d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 15:00:42 -0800 Subject: [PATCH 13/79] Move build folder to D:/ on Windows. --- .github/workflows/continuous.yaml | 43 ++++++++++++------------------- CMakeLists.txt | 12 +-------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 58e9fcc9..e910bf7e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -57,6 +57,11 @@ jobs: docker-images: true swap-storage: true + - name: Show disk space + run: | + echo "disk usage:" + df -h + - name: Checkout repository uses: actions/checkout@v4 with: @@ -138,6 +143,12 @@ jobs: cmake --build build -j ${{ steps.cpu-cores.outputs.count }} ccache --show-stats + - name: Show disk space + if: always() + run: | + echo "disk usage:" + df -h + - name: Tests run: cd build; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} @@ -191,11 +202,6 @@ jobs: # Scoop modifies the PATH so we make it available for the next steps of the job echo "${env:PATH}" >> ${env:GITHUB_PATH} - - name: Print disk usage - run: | - echo "disk usage:" - df -h - # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - name: Configure and build @@ -207,30 +213,13 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -B "C:/build" ^ + -B "D:/build" ^ -S . - cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} - - - name: Print disk usage - if: always() - run: | - echo "disk usage:" - df -h + cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} - - name: Run ncdu - shell: msys2 {0} + - name: Show disk space if: always() - run: | - ncdu -0 -o ${{ matrix.config }}-C.json /C - ncdu -0 -o ${{ matrix.config }}-D.json /D - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.config }} - path: | - ${{ matrix.config }}-C.json - ${{ matrix.config }}-D.json + run: Get-PSDrive - name: Tests - run: cd "C:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + run: cd "D:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 55e7e82c..a89f00d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,20 +61,10 @@ endif() set(LAGRANGE_CCACHE_PROGRAMS none ccache sccache) set_property(CACHE LAGRANGE_CCACHE_PROGRAM PROPERTY STRINGS ${LAGRANGE_CCACHE_PROGRAMS}) -# windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 -# https://github.com/actions/runner-images/issues/12609 -# https://github.com/actions/runner-images/issues/12199 -if($ENV{GITHUB_ACTIONS}) - message(STATUS "GitHub Runner detected: setting /Zi on Windows to save disk space") - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") -endif() - # Enable sscache if available if((LAGRANGE_CCACHE_PROGRAM STREQUAL "sccache") AND SCCACHE_PROGRAM) message(STATUS "Using sccache: ${SCCACHE_PROGRAM}") - if(NOT DEFINED CMAKE_MSVC_DEBUG_INFORMATION_FORMAT) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") - endif() + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") foreach(lang IN ITEMS C CXX) set(CMAKE_${lang}_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env ${ccacheEnv} ${SCCACHE_PROGRAM} From bbff5152c30c1bccfa63fa8cd2cde4ed1e98d1c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 16:04:35 -0800 Subject: [PATCH 14/79] Hide eigen warnings. --- cmake/recipes/external/Eigen3.cmake | 2 +- modules/core/include/lagrange/utils/warning.h | 7 +++++++ modules/polyddg/src/DifferentialOperators.cpp | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index bc86f2ae..cdbcca7b 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -26,7 +26,7 @@ else() CPMAddPackage( NAME eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git - GIT_TAG 3.4.1 + GIT_TAG 3.4.0 DOWNLOAD_ONLY ON ) set(EIGEN_INCLUDE_DIRS ${eigen_SOURCE_DIR}) diff --git a/modules/core/include/lagrange/utils/warning.h b/modules/core/include/lagrange/utils/warning.h index de45d4c4..482affc3 100644 --- a/modules/core/include/lagrange/utils/warning.h +++ b/modules/core/include/lagrange/utils/warning.h @@ -160,6 +160,13 @@ /// @hideinitializer #define LA_IGNORE_ARRAY_BOUNDS_END LA_DISABLE_WARNING_END +/// Ignore maybe uninitialized warnings (e.g. when instancing third-party code) +/// @hideinitializer +#define LA_IGNORE_MAYBE_UNINITIALIZED_START LA_DISABLE_WARNING_BEGIN \ + LA_DISABLE_WARNING_CLANG(-Wmaybe-uninitialized) +/// @hideinitializer +#define LA_IGNORE_MAYBE_UNINITIALIZED_END LA_DISABLE_WARNING_END + // clang-format on /// @} diff --git a/modules/polyddg/src/DifferentialOperators.cpp b/modules/polyddg/src/DifferentialOperators.cpp index 726b1e8e..27a67681 100644 --- a/modules/polyddg/src/DifferentialOperators.cpp +++ b/modules/polyddg/src/DifferentialOperators.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1024,7 +1025,9 @@ DifferentialOperators::levi_civita_nrosy(Index fid, Index lv, Ind Vector nf = vec_area.row(fid); // No need to normalize Vector nv = vertex_normal.row(vid); + LA_IGNORE_MAYBE_UNINITIALIZED_START auto Q = Eigen::Quaternion::FromTwoVectors(nv, nf).matrix(); + LA_IGNORE_MAYBE_UNINITIALIZED_END if (n != 1) { la_debug_assert(n > 1, "n should be positive."); From 63d511ba2cdec5588abfb21ef2a4f689c3eee82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 01:35:03 +0000 Subject: [PATCH 15/79] Update macro. --- modules/core/include/lagrange/utils/warning.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/lagrange/utils/warning.h b/modules/core/include/lagrange/utils/warning.h index 482affc3..54b97b17 100644 --- a/modules/core/include/lagrange/utils/warning.h +++ b/modules/core/include/lagrange/utils/warning.h @@ -163,7 +163,7 @@ /// Ignore maybe uninitialized warnings (e.g. when instancing third-party code) /// @hideinitializer #define LA_IGNORE_MAYBE_UNINITIALIZED_START LA_DISABLE_WARNING_BEGIN \ - LA_DISABLE_WARNING_CLANG(-Wmaybe-uninitialized) + LA_DISABLE_WARNING_GCC(-Wmaybe-uninitialized) /// @hideinitializer #define LA_IGNORE_MAYBE_UNINITIALIZED_END LA_DISABLE_WARNING_END From 51d2c111e6ae512e6df1dcce26ca731410e81112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 01:46:06 +0000 Subject: [PATCH 16/79] Update Eigen warnings. --- modules/polyddg/src/DifferentialOperators.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/polyddg/src/DifferentialOperators.cpp b/modules/polyddg/src/DifferentialOperators.cpp index 27a67681..9e40eecf 100644 --- a/modules/polyddg/src/DifferentialOperators.cpp +++ b/modules/polyddg/src/DifferentialOperators.cpp @@ -9,20 +9,26 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ +#include + +#include + +// Include early so we can explicitly silence warnings from Eigen. +// Note: This warning only shows up with GCC 13, even though we include Eigen headers via -isystem. +// It seems that with GCC 14+ -isystem also silences -Wmaybe-uninitialized. +LA_IGNORE_MAYBE_UNINITIALIZED_START +#include +LA_IGNORE_MAYBE_UNINITIALIZED_END #include #include #include #include -#include #include #include #include -#include #include -#include - #include #include @@ -1025,9 +1031,7 @@ DifferentialOperators::levi_civita_nrosy(Index fid, Index lv, Ind Vector nf = vec_area.row(fid); // No need to normalize Vector nv = vertex_normal.row(vid); - LA_IGNORE_MAYBE_UNINITIALIZED_START auto Q = Eigen::Quaternion::FromTwoVectors(nv, nf).matrix(); - LA_IGNORE_MAYBE_UNINITIALIZED_END if (n != 1) { la_debug_assert(n > 1, "n should be positive."); From bf621e76d3cd174557970566367b1689ad5c1940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:14:08 +0000 Subject: [PATCH 17/79] Update Eigen warnings. --- modules/core/tests/test_mesh_convert.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/core/tests/test_mesh_convert.cpp b/modules/core/tests/test_mesh_convert.cpp index 94ad5c3e..f9ea96dd 100644 --- a/modules/core/tests/test_mesh_convert.cpp +++ b/modules/core/tests/test_mesh_convert.cpp @@ -9,11 +9,19 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ +#include + +// Include early so we can explicitly silence warnings from Eigen. +// Note: This warning only shows up with GCC 13 when ASan is enabled, even though we include Eigen +// headers via -isystem. It seems that with GCC 14+ -isystem also silences -Wmaybe-uninitialized. +LA_IGNORE_MAYBE_UNINITIALIZED_START +#include +LA_IGNORE_MAYBE_UNINITIALIZED_END + #include #include #include - // clang-format off #include #include From 604f0a77ca6a928bf04e0533c80072aa7b443cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:21:07 +0000 Subject: [PATCH 18/79] Update macOS images and Xcode versions. --- .github/workflows/continuous.yaml | 14 +++++++------- .github/workflows/wheel.yaml | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index e910bf7e..b161d57c 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -24,16 +24,16 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-13, macos-15] + os: [ubuntu-24.04, macos-15-intel, macos-15] config: [RelwithDebInfo, Debug] compiler: [gcc, apple, llvm] sanitizer: ["Address", "Thread"] # TODO: Add Memory+Undefined Sanitizer exclude: - - os: macos-13 + - os: macos-15-intel compiler: gcc - - os: macos-13 + - os: macos-15-intel sanitizer: Thread - - os: macos-13 + - os: macos-15-intel config: Debug - os: macos-15 compiler: gcc @@ -96,16 +96,16 @@ jobs: fi - name: Setup Xcode version - if: matrix.os == 'macos-13' + if: matrix.os == 'macos-15-intel' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '15.2' + xcode-version: '16.4' - name: Setup Xcode version if: matrix.os == 'macos-15' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.4' + xcode-version: '26.0.1' - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index e44be880..47da0999 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-13, macos-15, windows-2025] + os: [ubuntu-24.04, macos-15-intel, macos-15, windows-2025] name: ${{matrix.os}} runs-on: ${{matrix.os}} @@ -23,16 +23,16 @@ jobs: uses: actions/checkout@v4 - name: Setup Xcode version - if: matrix.os == 'macos-13' + if: matrix.os == 'macos-15-intel' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '15.2' + xcode-version: '16.4' - name: Setup Xcode version if: matrix.os == 'macos-15' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.4' + xcode-version: '26.0.1' - name: Setup MSVC if: runner.os == 'windows' From b561bcfc95aba7d5d4083e50cb1f7600cc7d2411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:15:04 -0800 Subject: [PATCH 19/79] Switch to Embree4 by default and add WinArm GH runner. --- .github/workflows/continuous.yaml | 1 + cmake/lagrange/lagrange_find_package.cmake | 26 + .../external/{embree.cmake => embree3.cmake} | 8 +- .../external/{embree.patch => embree3.patch} | 0 cmake/recipes/external/embree4.cmake | 157 ++++++ cmake/recipes/external/embree4.patch | 491 ++++++++++++++++++ modules/raycasting/CMakeLists.txt | 12 +- .../lagrange/raycasting/EmbreeHelper.h | 8 +- .../lagrange/raycasting/EmbreeRayCaster.h | 63 ++- .../raycasting/embree_closest_point.h | 15 +- modules/raycasting/src/EmbreeHelper.cpp | 8 +- 11 files changed, 756 insertions(+), 33 deletions(-) rename cmake/recipes/external/{embree.cmake => embree3.cmake} (97%) rename cmake/recipes/external/{embree.patch => embree3.patch} (100%) create mode 100644 cmake/recipes/external/embree4.cmake create mode 100644 cmake/recipes/external/embree4.patch diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index b161d57c..e7dd456e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -162,6 +162,7 @@ jobs: strategy: fail-fast: false matrix: + os: [windows-2025, windows-11-arm] config: [Release, Debug] steps: - name: Show disk space diff --git a/cmake/lagrange/lagrange_find_package.cmake b/cmake/lagrange/lagrange_find_package.cmake index 185d6b37..000b893e 100644 --- a/cmake/lagrange/lagrange_find_package.cmake +++ b/cmake/lagrange/lagrange_find_package.cmake @@ -50,6 +50,19 @@ function(lagrange_find_package name) elseif(${name} STREQUAL algcmake) find_package(${name} ${ARGN}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) + elseif(${name} STREQUAL embree) + if(${ARGC} LESS 2) + message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") + endif() + if(${ARGV1} EQUAL 3) + # Defer to vcpkg port + find_package(${name} ${ARGN}) + elseif(${ARGV1} EQUAL 4) + # Use internal embree4.cmake recipe + include(embree4) + else() + message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") + endif() else() find_package(${name} ${ARGN}) endif() @@ -74,6 +87,19 @@ function(lagrange_find_package name) ${algcmake_SOURCE_DIR}/modules ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) + elseif(${name} STREQUAL embree) + if(${ARGC} LESS 2) + message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") + endif() + if(${ARGV1} EQUAL 3) + # Redirect to embree3.cmake + include(embree3) + elseif(${ARGV1} EQUAL 4) + # Redirect to embree4.cmake + include(embree4) + else() + message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") + endif() else() include(${name}) endif() diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree3.cmake similarity index 97% rename from cmake/recipes/external/embree.cmake rename to cmake/recipes/external/embree3.cmake index 3c6cf57b..5e2d862a 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree3.cmake @@ -89,8 +89,10 @@ function(embree_import_target) lagrange_find_package(TBB CONFIG REQUIRED) ignore_package(TBB) get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) - add_library(TBB INTERFACE) - target_link_libraries(TBB INTERFACE TBB::tbb) + if(NOT TARGET TBB) + add_library(TBB INTERFACE) + target_link_libraries(TBB INTERFACE TBB::tbb) + endif() set(TBB_LIBRARIES TBB) # Ready to include embree's atrocious CMake @@ -105,7 +107,7 @@ function(embree_import_target) # Patch for emscripten compatibility. Fix available upstream in Embree 4+. # https://github.com/RenderKit/embree/pull/365 # https://github.com/RenderKit/embree/issues/486 - embree.patch + embree3.patch ) unignore_package(TBB) diff --git a/cmake/recipes/external/embree.patch b/cmake/recipes/external/embree3.patch similarity index 100% rename from cmake/recipes/external/embree.patch rename to cmake/recipes/external/embree3.patch diff --git a/cmake/recipes/external/embree4.cmake b/cmake/recipes/external/embree4.cmake new file mode 100644 index 00000000..8ff3c553 --- /dev/null +++ b/cmake/recipes/external/embree4.cmake @@ -0,0 +1,157 @@ +# +# Copyright 2019 Adobe. All rights reserved. +# This file is licensed to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +# OF ANY KIND, either express or implied. See the License for the specific language +# governing permissions and limitations under the License. +# +if(TARGET embree::embree4) + return() +endif() + +message(STATUS "Third-party (external): creating target 'embree::embree4'") + +# Set Embree's default options +option(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." OFF) +option(EMBREE_TUTORIALS "Enable to build Embree tutorials" OFF) +option(EMBREE_STATIC_LIB "Build Embree as a static library." ON) +set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing.") +set(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") +option(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." OFF) + +# Set C++ namespace to avoid symbol collisions when compiling with embree3 side-by-side +set(EMBREE_API_NAMESPACE "embree4" CACHE STRING "C++ namespace to put API symbols into.") + +# The following options are necessary to ensure packed-ray support +option(EMBREE_RAY_MASK "Enable the usage of mask for packed ray." ON) +option(EMBREE_RAY_PACKETS "Enable the usage packed ray." ON) + +if(APPLE) + set(EMBREE_MAX_ISA "NEON" CACHE STRING "Selects highest ISA to support.") +elseif(EMSCRIPTEN) + set(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.") + set(FLAGS_SSE2 "-msse -msse2 -msimd128") # set to non-empty to prevent embree from using incorrect flags +else() + set(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.") +endif() + +# We want to compile Embree with TBB support, so we need to overwrite Embree's +# `find_package()` and provide variables. The following discussion provide some +# context on how to achieve this: +# - https://gitlab.kitware.com/cmake/cmake/issues/17735 +# - https://crascit.com/2018/09/14/do-not-redefine-cmake-commands/ +function(embree4_import_target) + macro(push_variable var value) + if(DEFINED CACHE{${var}}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE CACHE_TYPE) + elseif(DEFINED ${var}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE NORMAL_TYPE) + else() + set(LAGRANGE_OLD_${var}_TYPE NONE_TYPE) + endif() + set(${var} "${value}") + endmacro() + + macro(pop_variable var) + if(LAGRANGE_OLD_${var}_TYPE STREQUAL CACHE_TYPE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}" CACHE PATH "" FORCE) + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NORMAL_TYPE) + unset(${var} CACHE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}") + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NONE_TYPE) + unset(${var} CACHE) + else() + message(FATAL_ERROR "Trying to pop a variable that has not been pushed: ${var}") + endif() + endmacro() + + macro(ignore_package NAME) + set(LAGRANGE_DUMMY_DIR "${CMAKE_CURRENT_BINARY_DIR}/embree_cmake/${NAME}") + file(WRITE ${LAGRANGE_DUMMY_DIR}/${NAME}Config.cmake "") + push_variable(${NAME}_DIR ${LAGRANGE_DUMMY_DIR}) + push_variable(${NAME}_ROOT ${LAGRANGE_DUMMY_DIR}) + endmacro() + + macro(unignore_package NAME) + pop_variable(${NAME}_DIR) + pop_variable(${NAME}_ROOT) + endmacro() + + # Prefer Config mode before Module mode to prevent embree from loading its own FindTBB.cmake + set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) + + # Embree wants to be able to export() its target, and expects a target named `TBB` to exist. + # Somehow we stil need to define `TBB_INCLUDE_DIRS`, and linking against `TBB` isn't sufficient + # to compile embree targets properly. + lagrange_find_package(TBB CONFIG REQUIRED) + ignore_package(TBB) + get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) + if(NOT TARGET TBB) + add_library(TBB INTERFACE) + target_link_libraries(TBB INTERFACE TBB::tbb) + endif() + set(TBB_LIBRARIES TBB) + + # Ready to include embree's atrocious CMake + include(CPM) + CPMAddPackage( + NAME embree4 + GITHUB_REPOSITORY RenderKit/embree + GIT_TAG v4.4.0 + + # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 + # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching + ) + + unignore_package(TBB) + + # Disable warnings + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # Embree's subgrid.h is known for causing array subscript out of bound + # warning. Embree dev claim the code is correct and it is a GCC bug + # for misfiring warnings. See https://github.com/embree/embree/issues/271 + # + # The issue should be fixed for gcc 9.2.1 and later. + target_compile_options(embree4_embree PRIVATE "-Wno-array-bounds") + endif() + + # Warning setting + set(unix_compilers "AppleClang;Clang;GNU") + if(CMAKE_CXX_COMPILER_ID IN_LIST unix_compilers) # IN_LIST wants the second arg to be a var + target_compile_options(embree4_embree PRIVATE "-Wno-unused-private-field") + target_compile_options(embree4_embree PRIVATE "-Wno-unused-but-set-variable") + endif() + + # Now we need to do some juggling to propagate the include directory properties + # along with the `embree` target + add_library(embree::embree4 INTERFACE IMPORTED GLOBAL) + target_include_directories(embree::embree4 SYSTEM INTERFACE ${embree4_SOURCE_DIR}/include) + target_link_libraries(embree::embree4 INTERFACE embree4_embree) + + # Generate a dummy .cpp for embree's math library, to workaround a weird link issue with + # LLVM-Clang on macOS + # Generate implementation file + file(WRITE "${embree4_BINARY_DIR}/embree_math_dummy.cpp.in" [[ + namespace embree { + void math_dummy() {} + } + ]]) + configure_file(${embree4_BINARY_DIR}/embree_math_dummy.cpp.in ${embree4_BINARY_DIR}/embree_math_dummy.cpp COPYONLY) + target_sources(embree4_math PRIVATE ${embree4_BINARY_DIR}/embree_math_dummy.cpp) +endfunction() + +# Call via a proper function in order to scope variables such as CMAKE_FIND_PACKAGE_PREFER_CONFIG and TBB_DIR +embree4_import_target() + +# Cleanup for IDEs +foreach(name IN ITEMS embree algorithms lexers math simd sys tasking uninstall) + if(TARGET ${name}) + set_target_properties(embree4_${name} PROPERTIES FOLDER "third_party//embree4") + endif() +endforeach() diff --git a/cmake/recipes/external/embree4.patch b/cmake/recipes/external/embree4.patch new file mode 100644 index 00000000..75c28184 --- /dev/null +++ b/cmake/recipes/external/embree4.patch @@ -0,0 +1,491 @@ +diff --git i/CMakeLists.txt w/CMakeLists.txt +index 1292e265..f386ecb5 100644 +--- i/CMakeLists.txt ++++ w/CMakeLists.txt +@@ -691,16 +691,16 @@ ENDIF() + # Uninstall + ############################################################## + +-IF (NOT TARGET uninstall) ++IF (NOT TARGET embree4_uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake/uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" + IMMEDIATE @ONLY) + +- add_custom_target(uninstall ++ add_custom_target(embree4_uninstall + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake") + +- SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets) ++ SET_PROPERTY(TARGET embree4_uninstall PROPERTY FOLDER CMakePredefinedTargets) + ENDIF() + + ############################################################## +diff --git i/common/lexers/CMakeLists.txt w/common/lexers/CMakeLists.txt +index 1e2452cd..5d060c7a 100644 +--- i/common/lexers/CMakeLists.txt ++++ w/common/lexers/CMakeLists.txt +@@ -1,16 +1,16 @@ + ## Copyright 2009-2021 Intel Corporation + ## SPDX-License-Identifier: Apache-2.0 + +-ADD_LIBRARY(lexers STATIC ++ADD_LIBRARY(embree4_lexers STATIC + stringstream.cpp + tokenstream.cpp + ) +-TARGET_LINK_LIBRARIES(lexers sys math) +-SET_PROPERTY(TARGET lexers PROPERTY FOLDER common) +-SET_PROPERTY(TARGET lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++TARGET_LINK_LIBRARIES(embree4_lexers embree4_sys embree4_math) ++SET_PROPERTY(TARGET embree4_lexers PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT lexers-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + +diff --git i/common/math/CMakeLists.txt w/common/math/CMakeLists.txt +index fcfa4559..6cfed20e 100644 +--- i/common/math/CMakeLists.txt ++++ w/common/math/CMakeLists.txt +@@ -1,12 +1,12 @@ + ## Copyright 2009-2021 Intel Corporation + ## SPDX-License-Identifier: Apache-2.0 + +-ADD_LIBRARY(math STATIC constants.cpp) +-SET_PROPERTY(TARGET math PROPERTY FOLDER common) +-SET_PROPERTY(TARGET math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++ADD_LIBRARY(embree4_math STATIC constants.cpp) ++SET_PROPERTY(TARGET embree4_math PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT math-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + +diff --git i/common/simd/CMakeLists.txt w/common/simd/CMakeLists.txt +index 989a00d6..742b885d 100644 +--- i/common/simd/CMakeLists.txt ++++ w/common/simd/CMakeLists.txt +@@ -1,11 +1,11 @@ + ## Copyright 2009-2021 Intel Corporation + ## SPDX-License-Identifier: Apache-2.0 + +-ADD_LIBRARY(simd STATIC sse.cpp) +-SET_PROPERTY(TARGET simd PROPERTY FOLDER common) +-SET_PROPERTY(TARGET simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++ADD_LIBRARY(embree4_simd STATIC sse.cpp) ++SET_PROPERTY(TARGET embree4_simd PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT simd-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() +diff --git i/common/sys/CMakeLists.txt w/common/sys/CMakeLists.txt +index 66fc7083..d0e16cde 100644 +--- i/common/sys/CMakeLists.txt ++++ w/common/sys/CMakeLists.txt +@@ -4,7 +4,7 @@ + SET(CMAKE_THREAD_PREFER_PTHREAD TRUE) + FIND_PACKAGE(Threads REQUIRED) + +-ADD_LIBRARY(sys STATIC ++ADD_LIBRARY(embree4_sys STATIC + sysinfo.cpp + alloc.cpp + filename.cpp +@@ -17,16 +17,16 @@ ADD_LIBRARY(sys STATIC + barrier.cpp + ) + +-SET_PROPERTY(TARGET sys PROPERTY FOLDER common) +-SET_PROPERTY(TARGET sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++SET_PROPERTY(TARGET embree4_sys PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + +-TARGET_LINK_LIBRARIES(sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) ++TARGET_LINK_LIBRARIES(embree4_sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) + IF (EMBREE_SYCL_SUPPORT) +- TARGET_LINK_LIBRARIES(sys ${SYCL_LIB_NAME}) ++ TARGET_LINK_LIBRARIES(embree4_sys ${SYCL_LIB_NAME}) + ENDIF() + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT sys-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + +diff --git i/common/tasking/CMakeLists.txt w/common/tasking/CMakeLists.txt +index bf790ef6..e2768e98 100644 +--- i/common/tasking/CMakeLists.txt ++++ w/common/tasking/CMakeLists.txt +@@ -2,7 +2,7 @@ + ## SPDX-License-Identifier: Apache-2.0 + + IF (TASKING_INTERNAL) +- ADD_LIBRARY(tasking STATIC taskschedulerinternal.cpp) ++ ADD_LIBRARY(embree4_tasking STATIC taskschedulerinternal.cpp) + ELSEIF (TASKING_TBB) + ############################################################## + # Find TBB +@@ -13,16 +13,16 @@ ELSEIF (TASKING_TBB) + list(APPEND CMAKE_PREFIX_PATH ${EMBREE_TBB_ROOT}) + endif() + +- ADD_LIBRARY(tasking STATIC taskschedulertbb.cpp) ++ ADD_LIBRARY(embree4_tasking STATIC taskschedulertbb.cpp) + + if (TARGET TBB::${EMBREE_TBB_COMPONENT}) + message("-- TBB: reuse existing TBB::${TBB_COMPONENT} target") +- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) + else() + # Try getting TBB via config first + find_package(TBB 2020 COMPONENTS ${EMBREE_TBB_COMPONENT} CONFIG ${TBB_FIND_PACKAGE_OPTION}) + if (TBB_FOUND) +- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) + message("-- Found TBB: ${TBB_VERSION} at ${TBB_DIR} via TBBConfig.cmake") + else() + +@@ -32,8 +32,8 @@ ELSEIF (TASKING_TBB) + unset(TBB_DIR CACHE) + find_package(TBB 4.1 REQUIRED ${EMBREE_TBB_COMPONENT}) + if (TBB_FOUND) +- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB) +- TARGET_INCLUDE_DIRECTORIES(tasking PUBLIC $) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB) ++ TARGET_INCLUDE_DIRECTORIES(embree4_tasking PUBLIC $) + + IF (EMBREE_STATIC_LIB) + INSTALL(TARGETS TBB EXPORT TBB-targets) +@@ -50,8 +50,8 @@ ELSEIF (TASKING_TBB) + IF(WIN32) + GET_TARGET_PROPERTY(DLL_PATH TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_RELEASE) + GET_TARGET_PROPERTY(DLL_PATH_DEBUG TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_DEBUG) +- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) +- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) ++ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) ++ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) + ENDIF() + + ############################################################### +@@ -65,14 +65,14 @@ ELSEIF (TASKING_TBB) + include(installTBB) + + ELSEIF (TASKING_PPL) +- ADD_LIBRARY(tasking STATIC taskschedulerppl.cpp) +- TARGET_LINK_LIBRARIES(tasking PUBLIC ${PPL_LIBRARIES}) ++ ADD_LIBRARY(embree4_tasking STATIC taskschedulerppl.cpp) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC ${PPL_LIBRARIES}) + ENDIF() + +-SET_PROPERTY(TARGET tasking PROPERTY FOLDER common) +-SET_PROPERTY(TARGET tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++SET_PROPERTY(TARGET embree4_tasking PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT tasking-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() +diff --git i/kernels/CMakeLists.txt w/kernels/CMakeLists.txt +index b8278079..da9824f3 100644 +--- i/kernels/CMakeLists.txt ++++ w/kernels/CMakeLists.txt +@@ -31,7 +31,7 @@ SOURCE_GROUP("Source Files\\algorithms" "/algorithms/") + SOURCE_GROUP("" FILES embree.rc) + + SET(EMBREE_LIBRARY_FILES +- ++ + embree.rc + + common/device.cpp +@@ -105,7 +105,7 @@ IF (EMBREE_GEOMETRY_SUBDIVISION) + subdiv/tessellation_cache.cpp + subdiv/subdivpatch1base.cpp + subdiv/catmullclark_coefficients.cpp +- geometry/grid_soa.cpp ++ geometry/grid_soa.cpp + subdiv/subdivpatch1base_eval.cpp + bvh/bvh_builder_subdiv.cpp) + ENDIF() +@@ -116,7 +116,7 @@ IF (EMBREE_RAY_PACKETS) + ENDIF() + + MACRO(embree_files TARGET ISA) +- ++ + SET(${TARGET} + geometry/instance_intersector.cpp + geometry/instance_array_intersector.cpp +@@ -130,16 +130,16 @@ MACRO(embree_files TARGET ISA) + + IF (${ISA} EQUAL ${ISA_LOWEST_AVX}) + LIST(APPEND ${TARGET} geometry/primitive8.cpp) +- ENDIF() ++ ENDIF() + + IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA} EQUAL ${AVX512} OR ${ISA_LOWEST} EQUAL ${ISA}) +- ++ + LIST(APPEND ${TARGET} + common/scene_user_geometry.cpp + common/scene_instance.cpp + common/scene_instance_array.cpp + common/scene_triangle_mesh.cpp +- common/scene_quad_mesh.cpp ++ common/scene_quad_mesh.cpp + common/scene_curves.cpp + common/scene_line_segments.cpp + common/scene_grid_mesh.cpp +@@ -166,7 +166,7 @@ MACRO(embree_files TARGET ISA) + bvh/bvh_rotate.cpp + builders/primrefgen.cpp) + ENDIF() +- ++ + IF (${ISA} GREATER ${SSE42}) + LIST(APPEND ${TARGET} bvh/bvh_intersector1_bvh8.cpp) + ENDIF() +@@ -183,7 +183,7 @@ MACRO(embree_files TARGET ISA) + geometry/grid_soa.cpp + subdiv/subdivpatch1base_eval.cpp) + ENDIF() +- ++ + IF (EMBREE_RAY_PACKETS) + LIST(APPEND ${TARGET} + bvh/bvh_intersector_hybrid4_bvh4.cpp) +@@ -201,7 +201,7 @@ MACRO(embree_files TARGET ISA) + bvh/bvh_intersector_hybrid16_bvh4.cpp) + ENDIF() + ENDIF() +- ++ + ENDMACRO() + + #embree_files(EMBREE_LIBRARY_FILES_SSE2 ${SSE2}) +@@ -225,7 +225,7 @@ MACRO (CreateISADummyFiles list isa) + SET(dst_file "${CMAKE_BINARY_DIR}/${src}.${isa}.cpp") + SET(${list} ${${list}} ${dst_file}) + ADD_CUSTOM_COMMAND(OUTPUT ${dst_file} +- COMMAND ${CMAKE_COMMAND} ++ COMMAND ${CMAKE_COMMAND} + -D src=${src_file} + -D dst=${dst_file} + -P "${PROJECT_SOURCE_DIR}/common/cmake/create_isa_dummy_file.cmake" +@@ -243,40 +243,40 @@ MACRO (CheckGlobals library) + ADD_CUSTOM_TARGET(${library}_check_globals ALL COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_globals.cmake" DEPENDS ${library}) + ENDIF() + ENDMACRO() +- ++ + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES}) +-ADD_LIBRARY(embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) ++ADD_LIBRARY(embree4_embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) + + IF (EMBREE_SYCL_SUPPORT) + # add link flag '-fsycl' here to include the kernel for USM prefetch from + # scene_sycl.cpp in embree4.dll/embree4.so +- TARGET_LINK_OPTIONS(embree PRIVATE "-fsycl") ++ TARGET_LINK_OPTIONS(embree4_embree PRIVATE "-fsycl") + +- ADD_LIBRARY(embree_sycl STATIC ++ ADD_LIBRARY(embree4_embree_sycl STATIC + sycl/rtcore_sycl.cpp + sycl/rthwif_embree.cpp) + +- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) ++ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) + IF (EMBREE_SYCL_RT_VALIDATION_API) +- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE embree_rthwif_sycl) ++ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE embree_rthwif_sycl) + ENDIF() + + IF (EMBREE_SYCL_RT_SIMULATION) +- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE rtcore) ++ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE rtcore) + ENDIF() + +- INSTALL(TARGETS embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) + INSTALL(EXPORT embree_sycl-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + +- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) ++ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) + + ENDIF() + +-SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") +-SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") +-SET_PROPERTY(TARGET embree PROPERTY FOLDER kernels) ++SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") ++SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") ++SET_PROPERTY(TARGET embree4_embree PROPERTY FOLDER kernels) + IF (NOT WIN32 AND NOT APPLE) +- ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree) ++ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) + ENDIF() + + #IF (EMBREE_ISA_SSE2 AND EMBREE_LIBRARY_FILES_SSE2) +@@ -292,68 +292,68 @@ ENDIF() + + IF (EMBREE_ISA_SSE42 AND EMBREE_LIBRARY_FILES_SSE42) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_SSE42}) +- ADD_LIBRARY(embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) +- TARGET_LINK_LIBRARIES(embree_sse42 PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") +- SET_PROPERTY(TARGET embree_sse42 PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_sse42) +- CheckGlobals(embree_sse42) ++ ADD_LIBRARY(embree4_embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) ++ TARGET_LINK_LIBRARIES(embree4_embree_sse42 PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") ++ SET_PROPERTY(TARGET embree4_embree_sse42 PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_sse42) ++ CheckGlobals(embree4_embree_sse42) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_sse42-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF () + + IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX}) +- ADD_LIBRARY(embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) +- TARGET_LINK_LIBRARIES(embree_avx PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") +- SET_PROPERTY(TARGET embree_avx PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx) +- CheckGlobals(embree_avx) ++ ADD_LIBRARY(embree4_embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) ++ TARGET_LINK_LIBRARIES(embree4_embree_avx PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") ++ SET_PROPERTY(TARGET embree4_embree_avx PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx) ++ CheckGlobals(embree4_embree_avx) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF() + + IF (EMBREE_ISA_AVX2 AND EMBREE_LIBRARY_FILES_AVX2) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2}) +- ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) +- TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") +- SET_PROPERTY(TARGET embree_avx2 PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx2) +- CheckGlobals(embree_avx2) ++ ADD_LIBRARY(embree4_embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) ++ TARGET_LINK_LIBRARIES(embree4_embree_avx2 PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") ++ SET_PROPERTY(TARGET embree4_embree_avx2 PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx2) ++ CheckGlobals(embree4_embree_avx2) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx2-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF() + + IF (EMBREE_ISA_AVX512 AND EMBREE_LIBRARY_FILES_AVX512) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX512}) +- ADD_LIBRARY(embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) +- TARGET_LINK_LIBRARIES(embree_avx512 PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") +- SET_PROPERTY(TARGET embree_avx512 PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx512) +- CheckGlobals(embree_avx512) ++ ADD_LIBRARY(embree4_embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) ++ TARGET_LINK_LIBRARIES(embree4_embree_avx512 PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") ++ SET_PROPERTY(TARGET embree4_embree_avx512 PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx512) ++ CheckGlobals(embree4_embree_avx512) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx512-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF() + +-TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking) ++TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${EMBREE_LIBRARIES} embree4_sys embree4_math embree4_simd embree4_lexers embree4_tasking) + IF (EMBREE_SYCL_SUPPORT) +- TARGET_LINK_LIBRARIES(embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree_sycl) ++ TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree4_embree_sycl) + ENDIF() + + #TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking ${CMAKE_LINK_FLAGS_SYCL}) # FIXME: enable this line +-SET_TARGET_PROPERTIES(embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) +-target_include_directories(embree PUBLIC ++SET_TARGET_PROPERTIES(embree4_embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) ++target_include_directories(embree4_embree PUBLIC + $ + $) + +@@ -361,27 +361,27 @@ target_include_directories(embree PUBLIC + # libtbb is located in same install folder as libembree + IF(WIN32) + ELSEIF(APPLE) +- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed + ELSE() +- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. + ENDIF() + + IF (WIN32) + ELSEIF (APPLE) +- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") +- SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") ++ SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") + ELSE() +- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") + SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.linux.map") + ENDIF() + + IF (EMBREE_ZIP_MODE) +- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) + ELSE() +- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) + ENDIF() + +-INSTALL(TARGETS embree EXPORT embree-targets ++INSTALL(TARGETS embree4_embree EXPORT embree-targets + LIBRARY NAMELINK_SKIP DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib + # on Windows put the dlls into bin + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples +@@ -394,9 +394,9 @@ INSTALL(EXPORT embree-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT + + # installs libembree4.so link + IF (NOT EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree ++ INSTALL(TARGETS embree4_embree + LIBRARY NAMELINK_ONLY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel + ) + ENDIF() + +-SIGN_TARGET(embree) ++SIGN_TARGET(embree4_embree) diff --git a/modules/raycasting/CMakeLists.txt b/modules/raycasting/CMakeLists.txt index 0c719a4f..703be955 100644 --- a/modules/raycasting/CMakeLists.txt +++ b/modules/raycasting/CMakeLists.txt @@ -13,14 +13,22 @@ lagrange_add_module() # 2. dependencies -lagrange_find_package(embree 3 CONFIG REQUIRED) lagrange_include_modules(bvh) target_link_libraries(lagrange_raycasting PUBLIC lagrange::core lagrange::bvh - embree::embree ) +option(LAGRANGE_WITH_EMBREE_4 "Use Embree4 with Lagrange" ON) +if(LAGRANGE_WITH_EMBREE_4) + lagrange_find_package(embree 4 CONFIG REQUIRED) + target_compile_definitions(lagrange_raycasting PUBLIC LAGRANGE_WITH_EMBREE_4) + target_link_libraries(lagrange_raycasting PUBLIC embree::embree4) +else() + lagrange_find_package(embree 3 CONFIG REQUIRED) + target_link_libraries(lagrange_raycasting PUBLIC embree::embree) +endif() + option(LAGRANGE_EMBREE_DEBUG "Perform error-checking when performing each single Embree call" OFF) if(LAGRANGE_EMBREE_DEBUG) target_compile_definitions(lagrange_raycasting PUBLIC LAGRANGE_EMBREE_DEBUG) diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h index c3793877..8e2d0626 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h @@ -11,9 +11,15 @@ */ #pragma once -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include +#else + #include +#endif #include +RTC_NAMESPACE_USE + namespace lagrange { namespace raycasting { namespace EmbreeHelper { diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h index 31cb0bbf..7ad6dbfe 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h @@ -11,9 +11,16 @@ */ #pragma once -#include -#include -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include + #include + #include +#else + #include + #include + #include +#endif + #include #include #include @@ -33,6 +40,8 @@ #include #include +RTC_NAMESPACE_USE + namespace lagrange { namespace raycasting { @@ -472,11 +481,13 @@ class EmbreeRayCaster for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcIntersect4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); +#endif ensure_no_errors_internal(); uint32_t is_hits = 0; @@ -582,11 +593,13 @@ class EmbreeRayCaster for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcOccluded4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); +#endif ensure_no_errors_internal(); // If hit, the tfar field will be set to -inf. @@ -634,11 +647,13 @@ class EmbreeRayCaster embree_rayhit.ray.id = 0; embree_rayhit.ray.flags = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcIntersect1(m_embree_world_scene, &embree_rayhit); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit); +#endif ensure_no_errors_internal(); if (embree_rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) { @@ -722,11 +737,13 @@ class EmbreeRayCaster embree_ray.flags = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded1(m_embree_world_scene, &context, &embree_ray); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcOccluded1(m_embree_world_scene, &embree_ray); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcOccluded1(m_embree_world_scene, &context, &embree_ray); +#endif ensure_no_errors_internal(); // If hit, the tfar field will be set to -inf. diff --git a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h index 241135b8..a8be6833 100644 --- a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h +++ b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h @@ -11,11 +11,20 @@ #include -#include -#include -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include + #include + #include +#else + #include + #include + #include +#endif + #include +RTC_NAMESPACE_USE + namespace lagrange { namespace raycasting { diff --git a/modules/raycasting/src/EmbreeHelper.cpp b/modules/raycasting/src/EmbreeHelper.cpp index 25b983f5..9a3bde91 100644 --- a/modules/raycasting/src/EmbreeHelper.cpp +++ b/modules/raycasting/src/EmbreeHelper.cpp @@ -9,7 +9,12 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include +#else + #include +#endif + #include #include @@ -18,6 +23,7 @@ #include #include +RTC_NAMESPACE_USE void lagrange::raycasting::EmbreeHelper::ensure_no_errors(const RTCDevice& device) { From c89e2602537c2d58502db9fcd01cacca55c35b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:17:02 -0800 Subject: [PATCH 20/79] Run CI check on all target branches --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index e7dd456e..4d06d8b2 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -3,7 +3,7 @@ name: Build on: pull_request: branches: - - main + - '*' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} From 83ec15126afed1ac70294fc795b793a8c7636e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:18:05 -0800 Subject: [PATCH 21/79] Revert. --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 4d06d8b2..e7dd456e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -3,7 +3,7 @@ name: Build on: pull_request: branches: - - '*' + - main concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} From 4312983a1637c97e93c324dd4eb4d8c8c2a29f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:37:00 -0800 Subject: [PATCH 22/79] Update build type. --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index e7dd456e..45c614e4 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -25,7 +25,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-24.04, macos-15-intel, macos-15] - config: [RelwithDebInfo, Debug] + config: [RelWithDebInfo, Debug] compiler: [gcc, apple, llvm] sanitizer: ["Address", "Thread"] # TODO: Add Memory+Undefined Sanitizer exclude: From 5109ac32592da5447f5d3f7c6bddbbad0ca6353a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:50:20 -0800 Subject: [PATCH 23/79] Update config. --- .github/workflows/continuous.yaml | 4 ++-- cmake/recipes/external/embree4.cmake | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 45c614e4..a9a13565 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -157,8 +157,8 @@ jobs: #################### Windows: - name: windows-2025 (${{ matrix.config }}) - runs-on: windows-2025 + name: ${{ matrix.os }} (${{ matrix.config }}) + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: diff --git a/cmake/recipes/external/embree4.cmake b/cmake/recipes/external/embree4.cmake index 8ff3c553..5175b431 100644 --- a/cmake/recipes/external/embree4.cmake +++ b/cmake/recipes/external/embree4.cmake @@ -105,8 +105,10 @@ function(embree4_import_target) GITHUB_REPOSITORY RenderKit/embree GIT_TAG v4.4.0 - # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 - # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching + PATCHES + # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 + # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching. + embree4.patch ) unignore_package(TBB) From 727aa72f7c9cf6ab1da6b681622fff84c46b3019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 16:09:35 -0800 Subject: [PATCH 24/79] Update sccache setup. --- .github/workflows/continuous.yaml | 20 ++++---------------- cmake/recipes/external/embree4.patch | 4 ++-- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index a9a13565..5d42ed36 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -180,28 +180,15 @@ jobs: - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@master - - name: Set env variable for sccache - run: | - echo "appdata=$env:LOCALAPPDATA" >> ${env:GITHUB_ENV} - - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores - - name: Cache build - id: cache-build - uses: actions/cache@v3 - with: - path: ${{ env.appdata }}\Mozilla\sccache - key: ${{ runner.os }}-${{ matrix.config }}-cache + - name: Configure sccache + run: echo "SCCACHE_GHA_ENABLED=true" >> ${env:GITHUB_ENV} - name: Prepare sccache - run: | - iwr -useb 'https://raw.githubusercontent.com/scoopinstaller/install/master/install.ps1' -outfile 'install.ps1' - .\install.ps1 -RunAsAdmin - scoop install sccache --global - # Scoop modifies the PATH so we make it available for the next steps of the job - echo "${env:PATH}" >> ${env:GITHUB_PATH} + uses: mozilla-actions/sccache-action@v0.0.9 # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) @@ -217,6 +204,7 @@ jobs: -B "D:/build" ^ -S . cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} + sccache --show-stats - name: Show disk space if: always() diff --git a/cmake/recipes/external/embree4.patch b/cmake/recipes/external/embree4.patch index 75c28184..b2e14a91 100644 --- a/cmake/recipes/external/embree4.patch +++ b/cmake/recipes/external/embree4.patch @@ -200,7 +200,7 @@ index bf790ef6..e2768e98 100644 INSTALL(EXPORT tasking-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() diff --git i/kernels/CMakeLists.txt w/kernels/CMakeLists.txt -index b8278079..da9824f3 100644 +index b8278079..33e8a3c6 100644 --- i/kernels/CMakeLists.txt +++ w/kernels/CMakeLists.txt @@ -31,7 +31,7 @@ SOURCE_GROUP("Source Files\\algorithms" "/algorithms/") @@ -336,7 +336,7 @@ index b8278079..da9824f3 100644 +SET_PROPERTY(TARGET embree4_embree PROPERTY FOLDER kernels) IF (NOT WIN32 AND NOT APPLE) - ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree) -+ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) ++ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) ENDIF() #IF (EMBREE_ISA_SSE2 AND EMBREE_LIBRARY_FILES_SSE2) From 99acb1dafa629f139f99a63dab913bdba5b7e783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 16:25:53 -0800 Subject: [PATCH 25/79] Update sscache winarm action. --- .github/workflows/continuous.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 5d42ed36..abcbeda3 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -188,7 +188,9 @@ jobs: run: echo "SCCACHE_GHA_ENABLED=true" >> ${env:GITHUB_ENV} - name: Prepare sccache - uses: mozilla-actions/sccache-action@v0.0.9 + # Re-enable official action one https://github.com/Mozilla-Actions/sccache-action/pull/225 is merged + # uses: mozilla-actions/sccache-action@v0.0.9 + uses: Vee99BR/sccache-action@v0.0.1 # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) @@ -204,7 +206,6 @@ jobs: -B "D:/build" ^ -S . cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} - sccache --show-stats - name: Show disk space if: always() From d4c0c3dead631d2aa4563dbaeb38d8d60ddfa5f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 16:48:36 -0800 Subject: [PATCH 26/79] Set build dir for winarm --- .github/workflows/continuous.yaml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index abcbeda3..6d319bef 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -192,6 +192,14 @@ jobs: # uses: mozilla-actions/sccache-action@v0.0.9 uses: Vee99BR/sccache-action@v0.0.1 + - name: Set build folder + run: | + if ("${{ matrix.os }}" -eq "windows-2025") { + echo "BUILD_DIR=D:/build" >> ${env:GITHUB_ENV} + } else { + echo "BUILD_DIR=C:/build" >> ${env:GITHUB_ENV} + } + # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - name: Configure and build @@ -203,13 +211,14 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -B "D:/build" ^ + -B %BUILD_DIR% ^ -S . - cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} + cmake --build %BUILD_DIR% -j ${{ steps.cpu-cores.outputs.count }} - name: Show disk space if: always() run: Get-PSDrive - name: Tests - run: cd "D:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + run: cd %BUILD_DIR%; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + shell: cmd From 8010e9e96340a21c4fe5bb41ca268c638620ab9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:14:55 -0800 Subject: [PATCH 27/79] Patch boost context for winarm. --- cmake/recipes/external/Boost.cmake | 9 ++++++--- cmake/recipes/external/Boost.winarm.patch | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 cmake/recipes/external/Boost.winarm.patch diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index fba630f0..1c88d522 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -84,12 +84,15 @@ if(SKBUILD) set(BUILD_SHARED_LIBS ON) endif() -set(BOOST_PATCHES "") +set(BOOST_PATCHES) if(EMSCRIPTEN) # Wasm doesn't have rounding mode control yet, so we trick Boost::interval into thinking it has. # https://github.com/WebAssembly/rounding-mode-control # https://github.com/boostorg/interval/issues/44 - set(BOOST_PATCHES PATCHES Boost.wasm.patch) + list(APPEND BOOST_PATCHES Boost.wasm.patch) +endif() +if(WIN32) + list(APPEND BOOST_PATCHES Boost.winarm.patch) endif() # Modern CMake target support was added in Boost 1.82.0 @@ -101,7 +104,7 @@ CPMAddPackage( GITHUB_REPOSITORY "boostorg/boost" GIT_TAG "boost-1.84.0" EXCLUDE_FROM_ALL ON - ${BOOST_PATCHES} + PATCHES ${BOOST_PATCHES} ) if(SKBUILD) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch new file mode 100644 index 00000000..907e8220 --- /dev/null +++ b/cmake/recipes/external/Boost.winarm.patch @@ -0,0 +1 @@ +Submodule libs/context contains modified content From 9512ca537dde9132a24ab36a02a2e1c98509ae21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:29:36 -0800 Subject: [PATCH 28/79] Fix patch. --- cmake/recipes/external/Boost.winarm.patch | 134 ++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch index 907e8220..b788d7d5 100644 --- a/cmake/recipes/external/Boost.winarm.patch +++ b/cmake/recipes/external/Boost.winarm.patch @@ -1 +1,135 @@ Submodule libs/context contains modified content +diff --git i/libs/context/CMakeLists.txt w/libs/context/CMakeLists.txt +index dca5349..089592f 100644 +--- i/libs/context/CMakeLists.txt ++++ w/libs/context/CMakeLists.txt +@@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${boost_context_SOURCE_DIR}/cmake) + + ## Binary format + +-if(WIN32) ++if(WIN32 OR CYGWIN) + set(_default_binfmt pe) + elseif(APPLE) + set(_default_binfmt mach-o) +@@ -31,7 +31,7 @@ math(EXPR _bits "${CMAKE_SIZEOF_VOID_P}*8") + + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(_default_abi aapcs) +-elseif(WIN32) ++elseif(WIN32 OR CYGWIN) + set(_default_abi ms) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + if(_bits EQUAL 32) +@@ -60,6 +60,8 @@ elseif(_bits EQUAL 32) + set(_default_arch arm) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(_default_arch mips32) ++ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc32)") ++ set(_default_arch ppc32) + else() + set(_default_arch i386) + endif() +@@ -69,6 +71,8 @@ else() + set(_default_arch arm64) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(_default_arch mips64) ++ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc64)") ++ set(_default_arch ppc64) + else() + set(_default_arch x86_64) + endif() +@@ -89,18 +93,22 @@ if(MSVC) + else() + set(_default_asm masm) + endif() ++elseif(BOOST_CONTEXT_ARCHITECTURE STREQUAL arm64 AND MINGW) ++ set(_default_asm armclang) + else() + set(_default_asm gas) + endif() + +-set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm)") +-set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm) ++set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm, armclang)") ++set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm armclang) + + unset(_default_asm) + + ## Assembler source suffix + +-if(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) ++if(BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) ++ set(_default_ext .S) ++elseif(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) + set(_default_ext .asm) + elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) + set(_default_ext .S) +@@ -133,18 +141,22 @@ message(STATUS "Boost.Context: " + "implementation ${BOOST_CONTEXT_IMPLEMENTATION}") + + # Enable the right assembler +- ++set(ASM_LANGUAGE) + if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") +- if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) ++ if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas OR BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) + if(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") +- enable_language(ASM-ATT) ++ set(ASM_LANGUAGE ASM-ATT) + else() +- enable_language(ASM) ++ set(ASM_LANGUAGE ASM) + endif() + elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) +- enable_language(ASM_ARMASM) ++ if(MSVC) ++ set(ASM_LANGUAGE ASM_MARMASM) ++ else() ++ set(ASM_LANGUAGE ASM_ARMASM) ++ endif() + else() +- enable_language(ASM_MASM) ++ set(ASM_LANGUAGE ASM_MASM) + endif() + endif() + +@@ -168,15 +180,31 @@ unset(_asm_suffix) + + if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") + +- set(IMPL_SOURCES ${ASM_SOURCES}) ++ set(IMPL_SOURCES ${ASM_SOURCES} src/fcontext.cpp) + +- if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) +- set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh") +- endif() ++ if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm) + +- if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +- set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") +- endif() ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/nologo") ++ ++ if(MSVC AND NOT(MSVC_VERSION LESS 1936) AND NOT(CMAKE_CXX_SIMULATE_VERSION)) ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/quiet") ++ endif() ++ ++ if(BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/safeseh") ++ endif() ++ ++ # armasm doesn't support most of these options ++ elseif(NOT BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) # masm ++ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") ++ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-Wno-unused-command-line-argument") ++ endif() ++ endif() # masm ++ ++ enable_language(${ASM_LANGUAGE}) ++ set_source_files_properties(${ASM_SOURCES} PROPERTIES LANGUAGE ${ASM_LANGUAGE}) + else() + set(IMPL_SOURCES + src/continuation.cpp From 38a0c32fff8bcbf154750db06c1a662587dfb77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:42:15 -0800 Subject: [PATCH 29/79] Update patch. --- cmake/recipes/external/Boost.winarm.patch | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch index b788d7d5..fc6681aa 100644 --- a/cmake/recipes/external/Boost.winarm.patch +++ b/cmake/recipes/external/Boost.winarm.patch @@ -1,6 +1,6 @@ Submodule libs/context contains modified content diff --git i/libs/context/CMakeLists.txt w/libs/context/CMakeLists.txt -index dca5349..089592f 100644 +index dca5349..bd064b1 100644 --- i/libs/context/CMakeLists.txt +++ w/libs/context/CMakeLists.txt @@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${boost_context_SOURCE_DIR}/cmake) @@ -94,12 +94,9 @@ index dca5349..089592f 100644 endif() endif() -@@ -168,15 +180,31 @@ unset(_asm_suffix) +@@ -170,13 +182,29 @@ if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") - if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") - -- set(IMPL_SOURCES ${ASM_SOURCES}) -+ set(IMPL_SOURCES ${ASM_SOURCES} src/fcontext.cpp) + set(IMPL_SOURCES ${ASM_SOURCES}) - if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) - set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh") From 25e206a225640886731701d1490a82bf97de0baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 21:01:35 -0800 Subject: [PATCH 30/79] Update vs dev prompt setup. --- .github/workflows/continuous.yaml | 44 ++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 6d319bef..4b7ebf1f 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -192,33 +192,41 @@ jobs: # uses: mozilla-actions/sccache-action@v0.0.9 uses: Vee99BR/sccache-action@v0.0.1 - - name: Set build folder + - name: Set x64 vars + if: runner.os == 'windows-2025' run: | - if ("${{ matrix.os }}" -eq "windows-2025") { echo "BUILD_DIR=D:/build" >> ${env:GITHUB_ENV} - } else { + echo "ARCH=x64" >> ${env:GITHUB_ENV} + + - name: Set arm64 vars + if: runner.os == 'windows-11-arm' + run: | echo "BUILD_DIR=C:/build" >> ${env:GITHUB_ENV} - } + echo "ARCH=arm64" >> ${env:GITHUB_ENV} - # We run configure + build in the same step, since they both need to call VsDevCmd - # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - - name: Configure and build - shell: cmd + - name: Setup MSVC Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ env.ARCH }} + + # Cmd uses ^ to break commands into multiple lines, powershell uses ` + - name: Configure run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 - cmake --version - cmake -G Ninja ^ - -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ - -DLAGRANGE_JENKINS=ON ^ - -DLAGRANGE_ALL=ON ^ - -B %BUILD_DIR% ^ + cmake --version ` + cmake -G Ninja ` + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` + -DLAGRANGE_JENKINS=ON ` + -DLAGRANGE_ALL=ON ` + -B ${{ env.BUILD_DIR }} ` -S . - cmake --build %BUILD_DIR% -j ${{ steps.cpu-cores.outputs.count }} + + - name: Build + run: | + cmake --build ${{ env.BUILD_DIR }} -j ${{ steps.cpu-cores.outputs.count }} - name: Show disk space if: always() run: Get-PSDrive - name: Tests - run: cd %BUILD_DIR%; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} - shell: cmd + run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} From 7afbec68eb1009e93feadae7e330026ecb871631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 21:27:22 -0800 Subject: [PATCH 31/79] Fix line break. --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 4b7ebf1f..593c7b4d 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -212,7 +212,7 @@ jobs: # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure run: | - cmake --version ` + cmake --version cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` From c0593e99cc03d00af05d108d064a4bf5c5293458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 22:07:55 -0800 Subject: [PATCH 32/79] Update config. --- .github/workflows/continuous.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 593c7b4d..7f8e6937 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -193,13 +193,13 @@ jobs: uses: Vee99BR/sccache-action@v0.0.1 - name: Set x64 vars - if: runner.os == 'windows-2025' + if: matrix.os == 'windows-2025' run: | echo "BUILD_DIR=D:/build" >> ${env:GITHUB_ENV} echo "ARCH=x64" >> ${env:GITHUB_ENV} - name: Set arm64 vars - if: runner.os == 'windows-11-arm' + if: matrix.os == 'windows-11-arm' run: | echo "BUILD_DIR=C:/build" >> ${env:GITHUB_ENV} echo "ARCH=arm64" >> ${env:GITHUB_ENV} From 31d6d1599ec11c8aaf9ea39a76c224dc8ca6e7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 20 Feb 2026 08:12:28 -0800 Subject: [PATCH 33/79] Update sscache action. --- .github/workflows/continuous.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index fe8680a4..231895ef 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -214,9 +214,7 @@ jobs: run: echo "SCCACHE_GHA_ENABLED=true" >> ${env:GITHUB_ENV} - name: Prepare sccache - # Re-enable official action one https://github.com/Mozilla-Actions/sccache-action/pull/225 is merged - # uses: mozilla-actions/sccache-action@v0.0.9 - uses: Vee99BR/sccache-action@v0.0.1 + uses: mozilla-actions/sccache-action@v0.0.9 - name: Set x64 vars if: matrix.os == 'windows-2025' From b2cd3331d9d56e0c5074c528796f128bec020a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Fri, 20 Feb 2026 11:47:36 -0800 Subject: [PATCH 34/79] Change LAGRANGE_RAYCASTING to LAGRANGE_MODULE_RAYCASTING --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 231895ef..050c5700 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -240,7 +240,7 @@ jobs: cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_RAYCASTING=ON ` + -DLAGRANGE_MODULE_RAYCASTING=ON ` -B ${{ env.BUILD_DIR }} ` -S . From d82459b04926c526f2c77354a83b4b0345603b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 9 Mar 2026 10:14:46 -0700 Subject: [PATCH 35/79] Cleanup. --- cmake/lagrange/lagrange_find_package.cmake | 26 - cmake/recipes/external/embree4.cmake | 159 --- cmake/recipes/external/embree4.patch | 491 ------- modules/raycasting/CMakeLists.txt | 18 - .../lagrange/raycasting/EmbreeHelper.h | 22 - .../lagrange/raycasting/EmbreeRayCaster.h | 1153 ----------------- .../raycasting/embree_closest_point.h | 99 -- .../raycasting/src/legacy/EmbreeHelper.cpp | 7 - 8 files changed, 1975 deletions(-) delete mode 100644 cmake/recipes/external/embree4.cmake delete mode 100644 cmake/recipes/external/embree4.patch diff --git a/cmake/lagrange/lagrange_find_package.cmake b/cmake/lagrange/lagrange_find_package.cmake index b916b2ad..fc82db97 100644 --- a/cmake/lagrange/lagrange_find_package.cmake +++ b/cmake/lagrange/lagrange_find_package.cmake @@ -43,19 +43,6 @@ function(lagrange_find_package name) elseif(${name} STREQUAL algcmake) find_package(${name} ${ARGN}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) - elseif(${name} STREQUAL embree) - if(${ARGC} LESS 2) - message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") - endif() - if(${ARGV1} EQUAL 3) - # Defer to vcpkg port - find_package(${name} ${ARGN}) - elseif(${ARGV1} EQUAL 4) - # Use internal embree4.cmake recipe - include(embree4) - else() - message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") - endif() else() find_package(${name} ${ARGN}) endif() @@ -80,19 +67,6 @@ function(lagrange_find_package name) ${algcmake_SOURCE_DIR}/modules ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) - elseif(${name} STREQUAL embree) - if(${ARGC} LESS 2) - message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") - endif() - if(${ARGV1} EQUAL 3) - # Redirect to embree3.cmake - include(embree3) - elseif(${ARGV1} EQUAL 4) - # Redirect to embree4.cmake - include(embree4) - else() - message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") - endif() else() include(${name}) endif() diff --git a/cmake/recipes/external/embree4.cmake b/cmake/recipes/external/embree4.cmake deleted file mode 100644 index 5175b431..00000000 --- a/cmake/recipes/external/embree4.cmake +++ /dev/null @@ -1,159 +0,0 @@ -# -# Copyright 2019 Adobe. All rights reserved. -# This file is licensed to you under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. You may obtain a copy -# of the License at http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under -# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -# OF ANY KIND, either express or implied. See the License for the specific language -# governing permissions and limitations under the License. -# -if(TARGET embree::embree4) - return() -endif() - -message(STATUS "Third-party (external): creating target 'embree::embree4'") - -# Set Embree's default options -option(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." OFF) -option(EMBREE_TUTORIALS "Enable to build Embree tutorials" OFF) -option(EMBREE_STATIC_LIB "Build Embree as a static library." ON) -set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing.") -set(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") -option(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." OFF) - -# Set C++ namespace to avoid symbol collisions when compiling with embree3 side-by-side -set(EMBREE_API_NAMESPACE "embree4" CACHE STRING "C++ namespace to put API symbols into.") - -# The following options are necessary to ensure packed-ray support -option(EMBREE_RAY_MASK "Enable the usage of mask for packed ray." ON) -option(EMBREE_RAY_PACKETS "Enable the usage packed ray." ON) - -if(APPLE) - set(EMBREE_MAX_ISA "NEON" CACHE STRING "Selects highest ISA to support.") -elseif(EMSCRIPTEN) - set(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.") - set(FLAGS_SSE2 "-msse -msse2 -msimd128") # set to non-empty to prevent embree from using incorrect flags -else() - set(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.") -endif() - -# We want to compile Embree with TBB support, so we need to overwrite Embree's -# `find_package()` and provide variables. The following discussion provide some -# context on how to achieve this: -# - https://gitlab.kitware.com/cmake/cmake/issues/17735 -# - https://crascit.com/2018/09/14/do-not-redefine-cmake-commands/ -function(embree4_import_target) - macro(push_variable var value) - if(DEFINED CACHE{${var}}) - set(LAGRANGE_OLD_${var}_VALUE "${${var}}") - set(LAGRANGE_OLD_${var}_TYPE CACHE_TYPE) - elseif(DEFINED ${var}) - set(LAGRANGE_OLD_${var}_VALUE "${${var}}") - set(LAGRANGE_OLD_${var}_TYPE NORMAL_TYPE) - else() - set(LAGRANGE_OLD_${var}_TYPE NONE_TYPE) - endif() - set(${var} "${value}") - endmacro() - - macro(pop_variable var) - if(LAGRANGE_OLD_${var}_TYPE STREQUAL CACHE_TYPE) - set(${var} "${LAGRANGE_OLD_${var}_VALUE}" CACHE PATH "" FORCE) - elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NORMAL_TYPE) - unset(${var} CACHE) - set(${var} "${LAGRANGE_OLD_${var}_VALUE}") - elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NONE_TYPE) - unset(${var} CACHE) - else() - message(FATAL_ERROR "Trying to pop a variable that has not been pushed: ${var}") - endif() - endmacro() - - macro(ignore_package NAME) - set(LAGRANGE_DUMMY_DIR "${CMAKE_CURRENT_BINARY_DIR}/embree_cmake/${NAME}") - file(WRITE ${LAGRANGE_DUMMY_DIR}/${NAME}Config.cmake "") - push_variable(${NAME}_DIR ${LAGRANGE_DUMMY_DIR}) - push_variable(${NAME}_ROOT ${LAGRANGE_DUMMY_DIR}) - endmacro() - - macro(unignore_package NAME) - pop_variable(${NAME}_DIR) - pop_variable(${NAME}_ROOT) - endmacro() - - # Prefer Config mode before Module mode to prevent embree from loading its own FindTBB.cmake - set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) - - # Embree wants to be able to export() its target, and expects a target named `TBB` to exist. - # Somehow we stil need to define `TBB_INCLUDE_DIRS`, and linking against `TBB` isn't sufficient - # to compile embree targets properly. - lagrange_find_package(TBB CONFIG REQUIRED) - ignore_package(TBB) - get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) - if(NOT TARGET TBB) - add_library(TBB INTERFACE) - target_link_libraries(TBB INTERFACE TBB::tbb) - endif() - set(TBB_LIBRARIES TBB) - - # Ready to include embree's atrocious CMake - include(CPM) - CPMAddPackage( - NAME embree4 - GITHUB_REPOSITORY RenderKit/embree - GIT_TAG v4.4.0 - - PATCHES - # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 - # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching. - embree4.patch - ) - - unignore_package(TBB) - - # Disable warnings - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # Embree's subgrid.h is known for causing array subscript out of bound - # warning. Embree dev claim the code is correct and it is a GCC bug - # for misfiring warnings. See https://github.com/embree/embree/issues/271 - # - # The issue should be fixed for gcc 9.2.1 and later. - target_compile_options(embree4_embree PRIVATE "-Wno-array-bounds") - endif() - - # Warning setting - set(unix_compilers "AppleClang;Clang;GNU") - if(CMAKE_CXX_COMPILER_ID IN_LIST unix_compilers) # IN_LIST wants the second arg to be a var - target_compile_options(embree4_embree PRIVATE "-Wno-unused-private-field") - target_compile_options(embree4_embree PRIVATE "-Wno-unused-but-set-variable") - endif() - - # Now we need to do some juggling to propagate the include directory properties - # along with the `embree` target - add_library(embree::embree4 INTERFACE IMPORTED GLOBAL) - target_include_directories(embree::embree4 SYSTEM INTERFACE ${embree4_SOURCE_DIR}/include) - target_link_libraries(embree::embree4 INTERFACE embree4_embree) - - # Generate a dummy .cpp for embree's math library, to workaround a weird link issue with - # LLVM-Clang on macOS - # Generate implementation file - file(WRITE "${embree4_BINARY_DIR}/embree_math_dummy.cpp.in" [[ - namespace embree { - void math_dummy() {} - } - ]]) - configure_file(${embree4_BINARY_DIR}/embree_math_dummy.cpp.in ${embree4_BINARY_DIR}/embree_math_dummy.cpp COPYONLY) - target_sources(embree4_math PRIVATE ${embree4_BINARY_DIR}/embree_math_dummy.cpp) -endfunction() - -# Call via a proper function in order to scope variables such as CMAKE_FIND_PACKAGE_PREFER_CONFIG and TBB_DIR -embree4_import_target() - -# Cleanup for IDEs -foreach(name IN ITEMS embree algorithms lexers math simd sys tasking uninstall) - if(TARGET ${name}) - set_target_properties(embree4_${name} PROPERTIES FOLDER "third_party//embree4") - endif() -endforeach() diff --git a/cmake/recipes/external/embree4.patch b/cmake/recipes/external/embree4.patch deleted file mode 100644 index b2e14a91..00000000 --- a/cmake/recipes/external/embree4.patch +++ /dev/null @@ -1,491 +0,0 @@ -diff --git i/CMakeLists.txt w/CMakeLists.txt -index 1292e265..f386ecb5 100644 ---- i/CMakeLists.txt -+++ w/CMakeLists.txt -@@ -691,16 +691,16 @@ ENDIF() - # Uninstall - ############################################################## - --IF (NOT TARGET uninstall) -+IF (NOT TARGET embree4_uninstall) - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake/uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" - IMMEDIATE @ONLY) - -- add_custom_target(uninstall -+ add_custom_target(embree4_uninstall - COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake") - -- SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets) -+ SET_PROPERTY(TARGET embree4_uninstall PROPERTY FOLDER CMakePredefinedTargets) - ENDIF() - - ############################################################## -diff --git i/common/lexers/CMakeLists.txt w/common/lexers/CMakeLists.txt -index 1e2452cd..5d060c7a 100644 ---- i/common/lexers/CMakeLists.txt -+++ w/common/lexers/CMakeLists.txt -@@ -1,16 +1,16 @@ - ## Copyright 2009-2021 Intel Corporation - ## SPDX-License-Identifier: Apache-2.0 - --ADD_LIBRARY(lexers STATIC -+ADD_LIBRARY(embree4_lexers STATIC - stringstream.cpp - tokenstream.cpp - ) --TARGET_LINK_LIBRARIES(lexers sys math) --SET_PROPERTY(TARGET lexers PROPERTY FOLDER common) --SET_PROPERTY(TARGET lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+TARGET_LINK_LIBRARIES(embree4_lexers embree4_sys embree4_math) -+SET_PROPERTY(TARGET embree4_lexers PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT lexers-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - -diff --git i/common/math/CMakeLists.txt w/common/math/CMakeLists.txt -index fcfa4559..6cfed20e 100644 ---- i/common/math/CMakeLists.txt -+++ w/common/math/CMakeLists.txt -@@ -1,12 +1,12 @@ - ## Copyright 2009-2021 Intel Corporation - ## SPDX-License-Identifier: Apache-2.0 - --ADD_LIBRARY(math STATIC constants.cpp) --SET_PROPERTY(TARGET math PROPERTY FOLDER common) --SET_PROPERTY(TARGET math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+ADD_LIBRARY(embree4_math STATIC constants.cpp) -+SET_PROPERTY(TARGET embree4_math PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT math-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - -diff --git i/common/simd/CMakeLists.txt w/common/simd/CMakeLists.txt -index 989a00d6..742b885d 100644 ---- i/common/simd/CMakeLists.txt -+++ w/common/simd/CMakeLists.txt -@@ -1,11 +1,11 @@ - ## Copyright 2009-2021 Intel Corporation - ## SPDX-License-Identifier: Apache-2.0 - --ADD_LIBRARY(simd STATIC sse.cpp) --SET_PROPERTY(TARGET simd PROPERTY FOLDER common) --SET_PROPERTY(TARGET simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+ADD_LIBRARY(embree4_simd STATIC sse.cpp) -+SET_PROPERTY(TARGET embree4_simd PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT simd-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() -diff --git i/common/sys/CMakeLists.txt w/common/sys/CMakeLists.txt -index 66fc7083..d0e16cde 100644 ---- i/common/sys/CMakeLists.txt -+++ w/common/sys/CMakeLists.txt -@@ -4,7 +4,7 @@ - SET(CMAKE_THREAD_PREFER_PTHREAD TRUE) - FIND_PACKAGE(Threads REQUIRED) - --ADD_LIBRARY(sys STATIC -+ADD_LIBRARY(embree4_sys STATIC - sysinfo.cpp - alloc.cpp - filename.cpp -@@ -17,16 +17,16 @@ ADD_LIBRARY(sys STATIC - barrier.cpp - ) - --SET_PROPERTY(TARGET sys PROPERTY FOLDER common) --SET_PROPERTY(TARGET sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+SET_PROPERTY(TARGET embree4_sys PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - --TARGET_LINK_LIBRARIES(sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) -+TARGET_LINK_LIBRARIES(embree4_sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) - IF (EMBREE_SYCL_SUPPORT) -- TARGET_LINK_LIBRARIES(sys ${SYCL_LIB_NAME}) -+ TARGET_LINK_LIBRARIES(embree4_sys ${SYCL_LIB_NAME}) - ENDIF() - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT sys-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - -diff --git i/common/tasking/CMakeLists.txt w/common/tasking/CMakeLists.txt -index bf790ef6..e2768e98 100644 ---- i/common/tasking/CMakeLists.txt -+++ w/common/tasking/CMakeLists.txt -@@ -2,7 +2,7 @@ - ## SPDX-License-Identifier: Apache-2.0 - - IF (TASKING_INTERNAL) -- ADD_LIBRARY(tasking STATIC taskschedulerinternal.cpp) -+ ADD_LIBRARY(embree4_tasking STATIC taskschedulerinternal.cpp) - ELSEIF (TASKING_TBB) - ############################################################## - # Find TBB -@@ -13,16 +13,16 @@ ELSEIF (TASKING_TBB) - list(APPEND CMAKE_PREFIX_PATH ${EMBREE_TBB_ROOT}) - endif() - -- ADD_LIBRARY(tasking STATIC taskschedulertbb.cpp) -+ ADD_LIBRARY(embree4_tasking STATIC taskschedulertbb.cpp) - - if (TARGET TBB::${EMBREE_TBB_COMPONENT}) - message("-- TBB: reuse existing TBB::${TBB_COMPONENT} target") -- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) - else() - # Try getting TBB via config first - find_package(TBB 2020 COMPONENTS ${EMBREE_TBB_COMPONENT} CONFIG ${TBB_FIND_PACKAGE_OPTION}) - if (TBB_FOUND) -- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) - message("-- Found TBB: ${TBB_VERSION} at ${TBB_DIR} via TBBConfig.cmake") - else() - -@@ -32,8 +32,8 @@ ELSEIF (TASKING_TBB) - unset(TBB_DIR CACHE) - find_package(TBB 4.1 REQUIRED ${EMBREE_TBB_COMPONENT}) - if (TBB_FOUND) -- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB) -- TARGET_INCLUDE_DIRECTORIES(tasking PUBLIC $) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB) -+ TARGET_INCLUDE_DIRECTORIES(embree4_tasking PUBLIC $) - - IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS TBB EXPORT TBB-targets) -@@ -50,8 +50,8 @@ ELSEIF (TASKING_TBB) - IF(WIN32) - GET_TARGET_PROPERTY(DLL_PATH TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_RELEASE) - GET_TARGET_PROPERTY(DLL_PATH_DEBUG TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_DEBUG) -- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) -- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) -+ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) -+ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) - ENDIF() - - ############################################################### -@@ -65,14 +65,14 @@ ELSEIF (TASKING_TBB) - include(installTBB) - - ELSEIF (TASKING_PPL) -- ADD_LIBRARY(tasking STATIC taskschedulerppl.cpp) -- TARGET_LINK_LIBRARIES(tasking PUBLIC ${PPL_LIBRARIES}) -+ ADD_LIBRARY(embree4_tasking STATIC taskschedulerppl.cpp) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC ${PPL_LIBRARIES}) - ENDIF() - --SET_PROPERTY(TARGET tasking PROPERTY FOLDER common) --SET_PROPERTY(TARGET tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+SET_PROPERTY(TARGET embree4_tasking PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT tasking-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() -diff --git i/kernels/CMakeLists.txt w/kernels/CMakeLists.txt -index b8278079..33e8a3c6 100644 ---- i/kernels/CMakeLists.txt -+++ w/kernels/CMakeLists.txt -@@ -31,7 +31,7 @@ SOURCE_GROUP("Source Files\\algorithms" "/algorithms/") - SOURCE_GROUP("" FILES embree.rc) - - SET(EMBREE_LIBRARY_FILES -- -+ - embree.rc - - common/device.cpp -@@ -105,7 +105,7 @@ IF (EMBREE_GEOMETRY_SUBDIVISION) - subdiv/tessellation_cache.cpp - subdiv/subdivpatch1base.cpp - subdiv/catmullclark_coefficients.cpp -- geometry/grid_soa.cpp -+ geometry/grid_soa.cpp - subdiv/subdivpatch1base_eval.cpp - bvh/bvh_builder_subdiv.cpp) - ENDIF() -@@ -116,7 +116,7 @@ IF (EMBREE_RAY_PACKETS) - ENDIF() - - MACRO(embree_files TARGET ISA) -- -+ - SET(${TARGET} - geometry/instance_intersector.cpp - geometry/instance_array_intersector.cpp -@@ -130,16 +130,16 @@ MACRO(embree_files TARGET ISA) - - IF (${ISA} EQUAL ${ISA_LOWEST_AVX}) - LIST(APPEND ${TARGET} geometry/primitive8.cpp) -- ENDIF() -+ ENDIF() - - IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA} EQUAL ${AVX512} OR ${ISA_LOWEST} EQUAL ${ISA}) -- -+ - LIST(APPEND ${TARGET} - common/scene_user_geometry.cpp - common/scene_instance.cpp - common/scene_instance_array.cpp - common/scene_triangle_mesh.cpp -- common/scene_quad_mesh.cpp -+ common/scene_quad_mesh.cpp - common/scene_curves.cpp - common/scene_line_segments.cpp - common/scene_grid_mesh.cpp -@@ -166,7 +166,7 @@ MACRO(embree_files TARGET ISA) - bvh/bvh_rotate.cpp - builders/primrefgen.cpp) - ENDIF() -- -+ - IF (${ISA} GREATER ${SSE42}) - LIST(APPEND ${TARGET} bvh/bvh_intersector1_bvh8.cpp) - ENDIF() -@@ -183,7 +183,7 @@ MACRO(embree_files TARGET ISA) - geometry/grid_soa.cpp - subdiv/subdivpatch1base_eval.cpp) - ENDIF() -- -+ - IF (EMBREE_RAY_PACKETS) - LIST(APPEND ${TARGET} - bvh/bvh_intersector_hybrid4_bvh4.cpp) -@@ -201,7 +201,7 @@ MACRO(embree_files TARGET ISA) - bvh/bvh_intersector_hybrid16_bvh4.cpp) - ENDIF() - ENDIF() -- -+ - ENDMACRO() - - #embree_files(EMBREE_LIBRARY_FILES_SSE2 ${SSE2}) -@@ -225,7 +225,7 @@ MACRO (CreateISADummyFiles list isa) - SET(dst_file "${CMAKE_BINARY_DIR}/${src}.${isa}.cpp") - SET(${list} ${${list}} ${dst_file}) - ADD_CUSTOM_COMMAND(OUTPUT ${dst_file} -- COMMAND ${CMAKE_COMMAND} -+ COMMAND ${CMAKE_COMMAND} - -D src=${src_file} - -D dst=${dst_file} - -P "${PROJECT_SOURCE_DIR}/common/cmake/create_isa_dummy_file.cmake" -@@ -243,40 +243,40 @@ MACRO (CheckGlobals library) - ADD_CUSTOM_TARGET(${library}_check_globals ALL COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_globals.cmake" DEPENDS ${library}) - ENDIF() - ENDMACRO() -- -+ - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES}) --ADD_LIBRARY(embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) -+ADD_LIBRARY(embree4_embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) - - IF (EMBREE_SYCL_SUPPORT) - # add link flag '-fsycl' here to include the kernel for USM prefetch from - # scene_sycl.cpp in embree4.dll/embree4.so -- TARGET_LINK_OPTIONS(embree PRIVATE "-fsycl") -+ TARGET_LINK_OPTIONS(embree4_embree PRIVATE "-fsycl") - -- ADD_LIBRARY(embree_sycl STATIC -+ ADD_LIBRARY(embree4_embree_sycl STATIC - sycl/rtcore_sycl.cpp - sycl/rthwif_embree.cpp) - -- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) -+ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) - IF (EMBREE_SYCL_RT_VALIDATION_API) -- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE embree_rthwif_sycl) -+ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE embree_rthwif_sycl) - ENDIF() - - IF (EMBREE_SYCL_RT_SIMULATION) -- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE rtcore) -+ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE rtcore) - ENDIF() - -- INSTALL(TARGETS embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT embree_sycl-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) - -- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) -+ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) - - ENDIF() - --SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") --SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") --SET_PROPERTY(TARGET embree PROPERTY FOLDER kernels) -+SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") -+SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") -+SET_PROPERTY(TARGET embree4_embree PROPERTY FOLDER kernels) - IF (NOT WIN32 AND NOT APPLE) -- ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree) -+ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) - ENDIF() - - #IF (EMBREE_ISA_SSE2 AND EMBREE_LIBRARY_FILES_SSE2) -@@ -292,68 +292,68 @@ ENDIF() - - IF (EMBREE_ISA_SSE42 AND EMBREE_LIBRARY_FILES_SSE42) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_SSE42}) -- ADD_LIBRARY(embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) -- TARGET_LINK_LIBRARIES(embree_sse42 PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") -- SET_PROPERTY(TARGET embree_sse42 PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_sse42) -- CheckGlobals(embree_sse42) -+ ADD_LIBRARY(embree4_embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) -+ TARGET_LINK_LIBRARIES(embree4_embree_sse42 PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") -+ SET_PROPERTY(TARGET embree4_embree_sse42 PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_sse42) -+ CheckGlobals(embree4_embree_sse42) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_sse42-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF () - - IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX}) -- ADD_LIBRARY(embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) -- TARGET_LINK_LIBRARIES(embree_avx PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") -- SET_PROPERTY(TARGET embree_avx PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx) -- CheckGlobals(embree_avx) -+ ADD_LIBRARY(embree4_embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) -+ TARGET_LINK_LIBRARIES(embree4_embree_avx PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") -+ SET_PROPERTY(TARGET embree4_embree_avx PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx) -+ CheckGlobals(embree4_embree_avx) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_avx-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF() - - IF (EMBREE_ISA_AVX2 AND EMBREE_LIBRARY_FILES_AVX2) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2}) -- ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) -- TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") -- SET_PROPERTY(TARGET embree_avx2 PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx2) -- CheckGlobals(embree_avx2) -+ ADD_LIBRARY(embree4_embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) -+ TARGET_LINK_LIBRARIES(embree4_embree_avx2 PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") -+ SET_PROPERTY(TARGET embree4_embree_avx2 PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx2) -+ CheckGlobals(embree4_embree_avx2) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_avx2-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF() - - IF (EMBREE_ISA_AVX512 AND EMBREE_LIBRARY_FILES_AVX512) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX512}) -- ADD_LIBRARY(embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) -- TARGET_LINK_LIBRARIES(embree_avx512 PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") -- SET_PROPERTY(TARGET embree_avx512 PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx512) -- CheckGlobals(embree_avx512) -+ ADD_LIBRARY(embree4_embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) -+ TARGET_LINK_LIBRARIES(embree4_embree_avx512 PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") -+ SET_PROPERTY(TARGET embree4_embree_avx512 PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx512) -+ CheckGlobals(embree4_embree_avx512) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_avx512-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF() - --TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking) -+TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${EMBREE_LIBRARIES} embree4_sys embree4_math embree4_simd embree4_lexers embree4_tasking) - IF (EMBREE_SYCL_SUPPORT) -- TARGET_LINK_LIBRARIES(embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree_sycl) -+ TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree4_embree_sycl) - ENDIF() - - #TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking ${CMAKE_LINK_FLAGS_SYCL}) # FIXME: enable this line --SET_TARGET_PROPERTIES(embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) --target_include_directories(embree PUBLIC -+SET_TARGET_PROPERTIES(embree4_embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) -+target_include_directories(embree4_embree PUBLIC - $ - $) - -@@ -361,27 +361,27 @@ target_include_directories(embree PUBLIC - # libtbb is located in same install folder as libembree - IF(WIN32) - ELSEIF(APPLE) -- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed - ELSE() -- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. - ENDIF() - - IF (WIN32) - ELSEIF (APPLE) -- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") -- SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") -+ SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") - ELSE() -- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") - SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.linux.map") - ENDIF() - - IF (EMBREE_ZIP_MODE) -- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) - ELSE() -- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) - ENDIF() - --INSTALL(TARGETS embree EXPORT embree-targets -+INSTALL(TARGETS embree4_embree EXPORT embree-targets - LIBRARY NAMELINK_SKIP DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib - # on Windows put the dlls into bin - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples -@@ -394,9 +394,9 @@ INSTALL(EXPORT embree-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT - - # installs libembree4.so link - IF (NOT EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree -+ INSTALL(TARGETS embree4_embree - LIBRARY NAMELINK_ONLY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel - ) - ENDIF() - --SIGN_TARGET(embree) -+SIGN_TARGET(embree4_embree) diff --git a/modules/raycasting/CMakeLists.txt b/modules/raycasting/CMakeLists.txt index 29a3d836..7659f647 100644 --- a/modules/raycasting/CMakeLists.txt +++ b/modules/raycasting/CMakeLists.txt @@ -13,23 +13,6 @@ lagrange_add_module() # 2. dependencies -<<<<<<< HEAD -lagrange_include_modules(bvh) -target_link_libraries(lagrange_raycasting PUBLIC - lagrange::core - lagrange::bvh -) - -option(LAGRANGE_WITH_EMBREE_4 "Use Embree4 with Lagrange" ON) -if(LAGRANGE_WITH_EMBREE_4) - lagrange_find_package(embree 4 CONFIG REQUIRED) - target_compile_definitions(lagrange_raycasting PUBLIC LAGRANGE_WITH_EMBREE_4) - target_link_libraries(lagrange_raycasting PUBLIC embree::embree4) -else() - lagrange_find_package(embree 3 CONFIG REQUIRED) - target_link_libraries(lagrange_raycasting PUBLIC embree::embree) -endif() -======= lagrange_include_modules(bvh scene) target_link_libraries(lagrange_raycasting PUBLIC lagrange::core @@ -44,7 +27,6 @@ else() lagrange_find_package(embree 4 CONFIG REQUIRED) endif() target_link_libraries(lagrange_raycasting PUBLIC embree::embree) ->>>>>>> origin/main option(LAGRANGE_EMBREE_DEBUG "Perform error-checking when performing each single Embree call" OFF) if(LAGRANGE_EMBREE_DEBUG) diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h index 91f2edf6..fe405adf 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h @@ -11,28 +11,6 @@ */ #pragma once -<<<<<<< HEAD -#ifdef LAGRANGE_WITH_EMBREE_4 - #include -#else - #include -#endif -#include - -RTC_NAMESPACE_USE - -namespace lagrange { -namespace raycasting { -namespace EmbreeHelper { - -LA_RAYCASTING_API -void ensure_no_errors(const RTCDevice& device); - -} // namespace EmbreeHelper -} // namespace raycasting -} // namespace lagrange -======= #ifdef LAGRANGE_ENABLE_LEGACY_FUNCTIONS #include #endif ->>>>>>> origin/main diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h index 8ebd0909..350a4e20 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h @@ -11,1159 +11,6 @@ */ #pragma once -<<<<<<< HEAD -#ifdef LAGRANGE_WITH_EMBREE_4 - #include - #include - #include -#else - #include - #include - #include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -RTC_NAMESPACE_USE - -namespace lagrange { -namespace raycasting { - -/** - * A wrapper for Embree's raycasting API to compute ray intersections with (instances of) meshes. - * Supports intersection and occlusion queries on single rays and ray packets (currently only - * packets of size at most 4 are supported). Filters may be specified (per mesh, not per instance) - * to process each individual hit event during any of these queries. - */ -template -class EmbreeRayCaster -{ -public: - using Scalar = ScalarType; - using Transform = Eigen::Matrix; - using Point = Eigen::Matrix; - using Direction = Eigen::Matrix; - using Index = size_t; - using ClosestPoint = ClosestPointResult; - using TransformVector = std::vector; - - using Point4 = Eigen::Matrix; - using Direction4 = Eigen::Matrix; - using Index4 = Eigen::Matrix; - using Scalar4 = Eigen::Matrix; - using Mask4 = Eigen::Matrix; - - using FloatData = std::vector; - using IntData = std::vector; - - /** - * Interface for a hit filter function. Most information in `RTCFilterFunctionNArguments` maps - * directly to elements of the EmbreeRayCaster class, but the mesh and instance IDs need special - * conversion. `mesh_index` is an array of `args->N` EmbreeRayCaster mesh indices, and - * `instance_index` is an array of `args->N` EmbreeRayCaster instance indices, one for each - * ray/hit. For the other elements of `args`, the mappings are: - * - * @code - * facet_index <-- primID - * ray_depth <-- tfar - * barycentric_coord <-- [u, v, 1 - u - v] - * normal <-- Ng - * @endcode - */ - using FilterFunction = std::function; - -private: - /** Select between two sets of filters stored in the object. */ - enum { FILTER_INTERSECT = 0, FILTER_OCCLUDED = 1 }; - -public: - /** Constructor. */ - EmbreeRayCaster( - RTCSceneFlags scene_flags = RTC_SCENE_FLAG_DYNAMIC, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_LOW) - { -// Embree strongly recommend to have the Flush to Zero and -// Denormals are Zero mode of the MXCSR control and status -// register enabled for each thread before calling the -// rtcIntersect and rtcOccluded functions. -#ifdef _MM_SET_FLUSH_ZERO_MODE - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); -#endif -#ifdef _MM_SET_DENORMALS_ZERO_MODE - _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); -#endif - - m_scene_flags = scene_flags; - m_build_quality = build_quality; - m_device = rtcNewDevice(NULL); - ensure_no_errors_internal(); - m_embree_world_scene = rtcNewScene(m_device); - ensure_no_errors_internal(); - m_instance_index_ranges.push_back(safe_cast(0)); - - m_need_rebuild = true; - m_need_commit = false; - } - - /** Destructor. */ - virtual ~EmbreeRayCaster() - { - release_scenes(); - rtcReleaseDevice(m_device); - } - - EmbreeRayCaster(const EmbreeRayCaster&) = delete; - void operator=(const EmbreeRayCaster&) = delete; - -public: - /** Get the total number of meshes (not instances). */ - Index get_num_meshes() const { return safe_cast(m_meshes.size()); } - - /** Get the total number of mesh instances. */ - Index get_num_instances() const { return m_instance_index_ranges.back(); } - - /** Get the number of instances of a particular mesh. */ - Index get_num_instances(Index mesh_index) const - { - la_debug_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - return safe_cast( - m_instance_index_ranges[mesh_index + 1] - m_instance_index_ranges[mesh_index]); - } - - /** - * Get the mesh with a given index. Requires the caller to know the original type of the mesh - * (@a MeshType) in advance. - */ - template - std::shared_ptr get_mesh(Index index) const - { - la_runtime_assert(index < safe_cast(m_meshes.size())); - la_runtime_assert(m_meshes[index] != nullptr); - return dynamic_cast&>(*m_meshes[index]).get_mesh_ptr(); - } - - /** - * Get the index of the mesh corresponding to a given instance, where the instances are indexed - * sequentially starting from the instances of the first mesh, then the instances of the second - * mesh, and so on. Use get_mesh() to map the returned index to an actual mesh. - * - * @param cumulative_instance_index An integer in the range `0` to `get_num_instances() - 1` - * (both inclusive). - */ - Index get_mesh_for_instance(Index cumulative_instance_index) const - { - la_runtime_assert(cumulative_instance_index < get_num_instances()); - return m_instance_to_user_mesh[cumulative_instance_index]; - } - - /** - * Add an instance of a mesh to the scene, with a given transformation. If another instance of - * the same mesh has been previously added to the scene, the two instances will NOT be - * considered to share the same mesh, but will be treated as separate instances of separate - * meshes. To add multiple instances of the same mesh, use add_meshes(). - */ - template - Index add_mesh( - std::shared_ptr mesh, - const Transform& trans = Transform::Identity(), - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - return add_raycasting_mesh( - std::make_unique>(mesh), - trans, - build_quality); - } - - /** - * Add multiple instances of a single mesh to the scene, with given transformations. If another - * instance of the same mesh has been previously added to the scene, the new instances will NOT - * be considered to share the same mesh as the old instance, but will be treated as instances of - * a new mesh. Add all instances in a single add_meshes() call if you want to avoid this. - */ - template - Index add_meshes( - std::shared_ptr mesh, - const TransformVector& trans_vector, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - m_meshes.push_back(std::move(std::make_unique>(mesh))); - m_transforms.insert(m_transforms.end(), trans_vector.begin(), trans_vector.end()); - m_mesh_build_qualities.push_back(build_quality); - m_visibility.resize(m_visibility.size() + trans_vector.size(), true); - for (auto& f : m_filters) { // per-mesh, not per-instance - f.push_back(nullptr); - } - Index mesh_index = safe_cast(m_meshes.size() - 1); - la_runtime_assert(m_instance_index_ranges.size() > 0); - Index instance_index = m_instance_index_ranges.back(); - la_runtime_assert(instance_index == safe_cast(m_instance_to_user_mesh.size())); - Index new_instance_size = instance_index + trans_vector.size(); - m_instance_index_ranges.push_back(new_instance_size); - m_instance_to_user_mesh.resize(new_instance_size, mesh_index); - m_need_rebuild = true; - return mesh_index; - } - - /** - * Update a particular mesh with a new mesh object. All its instances will be affected. - * - * @note If you have changed the vertices of a mesh already in the scene, and just want the - * object to reflect that, then call update_mesh_vertices() instead. - */ - template - void update_mesh( - Index index, - std::shared_ptr mesh, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - update_raycasting_mesh( - index, - std::make_unique>(mesh), - build_quality); - } - - /** - * Update the object to reflect external changes to the vertices of a particular mesh which is - * already in the scene. All its instances will be affected. The number of vertices in the mesh, - * and their order in the vertex array, must not change. - */ - void update_mesh_vertices(Index index) - { - la_runtime_assert(index < safe_cast(m_meshes.size())); - if (m_need_rebuild) return; - - la_runtime_assert(index < safe_cast(m_embree_mesh_scenes.size())); - auto geom = rtcGetGeometry(m_embree_mesh_scenes[index], 0); - - // Update the vertex buffer in Embree - auto const& mesh = m_meshes[index]; - la_runtime_assert( - safe_cast(mesh->get_num_vertices()) == m_mesh_vertex_counts[index]); - - auto vbuf = - reinterpret_cast(rtcGetGeometryBufferData(geom, RTC_BUFFER_TYPE_VERTEX, 0)); - la_runtime_assert(vbuf); - mesh->vertices_to_float(vbuf); - rtcUpdateGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0); - - // Re-commit the mesh geometry and scene - rtcCommitGeometry(geom); - rtcCommitScene(m_embree_mesh_scenes[index]); - - // Re-commit every instance of the mesh - for (Index instance_index = m_instance_index_ranges[index]; - instance_index < m_instance_index_ranges[index + 1]; - ++instance_index) { - Index rtc_inst_id = m_instance_index_ranges[index] + instance_index; - auto geom_inst = - rtcGetGeometry(m_embree_world_scene, static_cast(rtc_inst_id)); - rtcCommitGeometry(geom_inst); - } - - // Mark the world scene as needing a re-commit (will be called lazily) - m_need_commit = true; - } - - /** Get the transform applied to a given mesh instance. */ - Transform get_transform(Index mesh_index, Index instance_index) const - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_transforms.size())); - return m_transforms[index]; - } - - /** Update the transform applied to a given mesh instance. */ - void update_transformation(Index mesh_index, Index instance_index, const Transform& trans) - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_transforms.size())); - m_transforms[index] = trans; - if (!m_need_rebuild) { - auto geom = rtcGetGeometry(m_embree_world_scene, static_cast(index)); - Eigen::Matrix T = trans.template cast(); - rtcSetGeometryTransform(geom, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.eval().data()); - rtcCommitGeometry(geom); - m_need_commit = true; - } - } - - /** Get the visibility flag of a given mesh instance. */ - bool get_visibility(Index mesh_index, Index instance_index) const - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_visibility.size())); - return m_visibility[index]; - } - - /** Update the visibility of a given mesh index (true for visible, false for invisible). */ - void update_visibility(Index mesh_index, Index instance_index, bool visible) - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_visibility.size())); - m_visibility[index] = visible; - if (!m_need_rebuild && - rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED)) { - // ^^^ else, visibility will be checked by the already bound filter - - auto geom = rtcGetGeometry(m_embree_world_scene, static_cast(index)); - rtcSetGeometryMask(geom, visible ? 0xFFFFFFFF : 0x00000000); - rtcCommitGeometry(geom); - m_need_commit = true; - } - } - - /** - * Set an intersection filter that is called for every hit on (every instance of) a mesh during - * an intersection query. The @a filter function must be callable as: - * - * @code - * void filter(const EmbreeRayCaster* obj, const Index* mesh_index, const Index* instance_index, - * const RTCFilterFunctionNArguments* args); - * @endcode - * - * It functions exactly like Embree's `rtcSetGeometryIntersectFilterFunction`, except it also - * receives a handle to this object, and mesh and instance indices specific to this object. A - * null @a filter disables intersection filtering for this mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - void set_intersection_filter(Index mesh_index, FilterFunction filter) - { - la_runtime_assert(mesh_index < m_filters[FILTER_INTERSECT].size()); - m_filters[FILTER_INTERSECT][mesh_index] = filter; - m_need_rebuild = true; - } - - /** - * Get the intersection filter function currently bound to a given mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - FilterFunction get_intersection_filter(Index mesh_index) const - { - la_runtime_assert(mesh_index < m_filters[FILTER_INTERSECT].size()); - return m_filters[FILTER_INTERSECT][mesh_index]; - } - - /** - * Set an occlusion filter that is called for every hit on (every instance of) a mesh during an - * occlusion query. The @a filter function must be callable as: - * - * @code - * void filter(const EmbreeRayCaster* obj, const Index* mesh_index, const Index* instance_index, - * const RTCFilterFunctionNArguments* args); - * @endcode - * - * It functions exactly like Embree's `rtcSetGeometryOccludedFilterFunction`, except it also - * receives a handle to this object, and mesh and instance indices specific to this object. A - * null @a filter disables occlusion filtering for this mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - void set_occlusion_filter(Index mesh_index, FilterFunction filter) - { - la_runtime_assert(mesh_index < m_filters[FILTER_OCCLUDED].size()); - m_filters[FILTER_OCCLUDED][mesh_index] = filter; - m_need_rebuild = true; - } - - /** - * Get the occlusion filter function currently bound to a given mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - FilterFunction get_occlusion_filter(Index mesh_index) const - { - la_runtime_assert(mesh_index < m_filters[FILTER_OCCLUDED].size()); - return m_filters[FILTER_OCCLUDED][mesh_index]; - } - - /** - * Call `rtcCommitScene()` on the overall scene, if it has been marked as modified. - * - * @todo Now that this is automatically called by update_internal() based on a dirty flag, can - * we make this a protected/private function? That would break the API so maybe reserve it - * for a major version. - */ - void commit_scene_changes() - { - if (!m_need_commit) return; - - rtcCommitScene(m_embree_world_scene); - m_need_commit = false; - } - - /** Throw an exception if an Embree error has occurred.*/ - void ensure_no_errors() const { EmbreeHelper::ensure_no_errors(m_device); } - - /** - * Cast a packet of up to 4 rays through the scene, returning full data of the closest - * intersections including normals and instance indices. - */ - uint32_t cast4( - uint32_t batch_size, - const Point4& origin, - const Direction4& direction, - const Mask4& mask, - Index4& mesh_index, - Index4& instance_index, - Index4& facet_index, - Scalar4& ray_depth, - Point4& barycentric_coord, - Point4& normal, - const Scalar4& tmin = Scalar4::Zero(), - const Scalar4& tmax = Scalar4::Constant(std::numeric_limits::infinity())) - { - la_debug_assert(batch_size <= 4); - - update_internal(); - - RTCRayHit4 embree_raypacket; - for (int i = 0; i < static_cast(batch_size); ++i) { - // Set ray origins - embree_raypacket.ray.org_x[i] = static_cast(origin(i, 0)); - embree_raypacket.ray.org_y[i] = static_cast(origin(i, 1)); - embree_raypacket.ray.org_z[i] = static_cast(origin(i, 2)); - - // Set ray directions - embree_raypacket.ray.dir_x[i] = static_cast(direction(i, 0)); - embree_raypacket.ray.dir_y[i] = static_cast(direction(i, 1)); - embree_raypacket.ray.dir_z[i] = static_cast(direction(i, 2)); - - // Misc - embree_raypacket.ray.tnear[i] = static_cast(tmin[i]); - embree_raypacket.ray.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits::max() - : static_cast(tmax[i]); - embree_raypacket.ray.mask[i] = 0xFFFFFFFF; - embree_raypacket.ray.id[i] = static_cast(i); - embree_raypacket.ray.flags[i] = 0; - - // Required initialization of the hit substructure - embree_raypacket.hit.geomID[i] = RTC_INVALID_GEOMETRY_ID; - embree_raypacket.hit.primID[i] = RTC_INVALID_GEOMETRY_ID; - embree_raypacket.hit.instID[0][i] = RTC_INVALID_GEOMETRY_ID; - } - - // Modify the mask to make 100% sure extra rays in the packet will be ignored - auto packet_mask = mask; - for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; - - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcIntersect4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); -#endif - ensure_no_errors_internal(); - - uint32_t is_hits = 0; - for (int i = 0; i < static_cast(batch_size); ++i) { - if (embree_raypacket.hit.geomID[i] != RTC_INVALID_GEOMETRY_ID) { - Index rtc_inst_id = embree_raypacket.hit.instID[0][i]; - Index rtc_mesh_id = (rtc_inst_id == RTC_INVALID_GEOMETRY_ID) - ? embree_raypacket.hit.geomID[i] - : rtc_inst_id; - assert(rtc_mesh_id < m_instance_to_user_mesh.size()); - assert(m_visibility[rtc_mesh_id]); - mesh_index[i] = m_instance_to_user_mesh[rtc_mesh_id]; - assert(mesh_index[i] + 1 < m_instance_index_ranges.size()); - assert(mesh_index[i] < safe_cast(m_meshes.size())); - instance_index[i] = rtc_mesh_id - m_instance_index_ranges[mesh_index[i]]; - facet_index[i] = embree_raypacket.hit.primID[i]; - ray_depth[i] = embree_raypacket.ray.tfar[i]; - barycentric_coord(i, 0) = - 1.0f - embree_raypacket.hit.u[i] - embree_raypacket.hit.v[i]; - barycentric_coord(i, 1) = embree_raypacket.hit.u[i]; - barycentric_coord(i, 2) = embree_raypacket.hit.v[i]; - normal(i, 0) = embree_raypacket.hit.Ng_x[i]; - normal(i, 1) = embree_raypacket.hit.Ng_y[i]; - normal(i, 2) = embree_raypacket.hit.Ng_z[i]; - is_hits = is_hits | (1 << i); - } - } - - return is_hits; - } - - /** - * Cast a packet of up to 4 rays through the scene, returning data of the closest intersections - * excluding normals and instance indices. - */ - uint32_t cast4( - uint32_t batch_size, - const Point4& origin, - const Direction4& direction, - const Mask4& mask, - Index4& mesh_index, - Index4& facet_index, - Scalar4& ray_depth, - Point4& barycentric_coord, - const Scalar4& tmin = Scalar4::Zero(), - const Scalar4& tmax = Scalar4::Constant(std::numeric_limits::infinity())) - { - Index4 instance_index; - Point4 normal; - return cast4( - batch_size, - origin, - direction, - mask, - mesh_index, - instance_index, - facet_index, - ray_depth, - barycentric_coord, - normal, - tmin, - tmax); - } - - /** - * Cast a packet of up to 4 rays through the scene and check whether they hit anything or not. - */ - uint32_t cast4( - uint32_t batch_size, - const Point4& origin, - const Direction4& direction, - const Mask4& mask, - const Scalar4& tmin = Scalar4::Zero(), - const Scalar4& tmax = Scalar4::Constant(std::numeric_limits::infinity())) - { - la_debug_assert(batch_size <= 4); - - update_internal(); - - RTCRay4 embree_raypacket; - for (int i = 0; i < static_cast(batch_size); ++i) { - // Set ray origins - embree_raypacket.org_x[i] = static_cast(origin(i, 0)); - embree_raypacket.org_y[i] = static_cast(origin(i, 1)); - embree_raypacket.org_z[i] = static_cast(origin(i, 2)); - - // Set ray directions - embree_raypacket.dir_x[i] = static_cast(direction(i, 0)); - embree_raypacket.dir_y[i] = static_cast(direction(i, 1)); - embree_raypacket.dir_z[i] = static_cast(direction(i, 2)); - - // Misc - embree_raypacket.tnear[i] = static_cast(tmin[i]); - embree_raypacket.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits::max() - : static_cast(tmax[i]); - embree_raypacket.mask[i] = 0xFFFFFFFF; - embree_raypacket.id[i] = static_cast(i); - embree_raypacket.flags[i] = 0; - } - - // Modify the mask to make 100% sure extra rays in the packet will be ignored - auto packet_mask = mask; - for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; - - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcOccluded4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); -#endif - ensure_no_errors_internal(); - - // If hit, the tfar field will be set to -inf. - uint32_t is_hits = 0; - for (uint32_t i = 0; i < batch_size; ++i) - if (!std::isfinite(embree_raypacket.tfar[i])) is_hits = is_hits | (1 << i); - - return is_hits; - } - - /** - * Cast a single ray through the scene, returning full data of the closest intersection - * including the normal and the instance index. - */ - bool cast( - const Point& origin, - const Direction& direction, - Index& mesh_index, - Index& instance_index, - Index& facet_index, - Scalar& ray_depth, - Point& barycentric_coord, - Point& normal, - Scalar tmin = 0, - Scalar tmax = std::numeric_limits::infinity()) - { - // Overloaded when specializing tnear and tfar - - update_internal(); - - RTCRayHit embree_rayhit; - embree_rayhit.ray.org_x = static_cast(origin.x()); - embree_rayhit.ray.org_y = static_cast(origin.y()); - embree_rayhit.ray.org_z = static_cast(origin.z()); - embree_rayhit.ray.dir_x = static_cast(direction.x()); - embree_rayhit.ray.dir_y = static_cast(direction.y()); - embree_rayhit.ray.dir_z = static_cast(direction.z()); - embree_rayhit.ray.tnear = static_cast(tmin); - embree_rayhit.ray.tfar = - std::isinf(tmax) ? std::numeric_limits::max() : static_cast(tmax); - embree_rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID; - embree_rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID; - embree_rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; - embree_rayhit.ray.mask = 0xFFFFFFFF; - embree_rayhit.ray.id = 0; - embree_rayhit.ray.flags = 0; - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcIntersect1(m_embree_world_scene, &embree_rayhit); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit); -#endif - ensure_no_errors_internal(); - - if (embree_rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) { - Index rtc_inst_id = embree_rayhit.hit.instID[0]; - Index rtc_mesh_id = - (rtc_inst_id == RTC_INVALID_GEOMETRY_ID) ? embree_rayhit.hit.geomID : rtc_inst_id; - assert(rtc_mesh_id < m_instance_to_user_mesh.size()); - assert(m_visibility[rtc_mesh_id]); - mesh_index = m_instance_to_user_mesh[rtc_mesh_id]; - assert(mesh_index + 1 < m_instance_index_ranges.size()); - assert(mesh_index < safe_cast(m_meshes.size())); - instance_index = rtc_mesh_id - m_instance_index_ranges[mesh_index]; - facet_index = embree_rayhit.hit.primID; - ray_depth = embree_rayhit.ray.tfar; - barycentric_coord[0] = 1.0f - embree_rayhit.hit.u - embree_rayhit.hit.v; - barycentric_coord[1] = embree_rayhit.hit.u; - barycentric_coord[2] = embree_rayhit.hit.v; - normal[0] = embree_rayhit.hit.Ng_x; - normal[1] = embree_rayhit.hit.Ng_y; - normal[2] = embree_rayhit.hit.Ng_z; - return true; - } else { - // Ray missed. - mesh_index = invalid(); - instance_index = invalid(); - facet_index = invalid(); - return false; - } - } - - /** - * Cast a single ray through the scene, returning data of the closest intersection excluding the - * normal and the instance index. - */ - bool cast( - const Point& origin, - const Direction& direction, - Index& mesh_index, - Index& facet_index, - Scalar& ray_depth, - Point& barycentric_coord, - Scalar tmin = 0, - Scalar tmax = std::numeric_limits::infinity()) - { - Index instance_index; - Point normal; - return cast( - origin, - direction, - mesh_index, - instance_index, - facet_index, - ray_depth, - barycentric_coord, - normal, - tmin, - tmax); - } - - /** Cast a single ray through the scene and check whether it hits anything or not. */ - bool cast( - const Point& origin, - const Direction& direction, - Scalar tmin = 0, - Scalar tmax = std::numeric_limits::infinity()) - { - update_internal(); - - RTCRay embree_ray; - embree_ray.org_x = static_cast(origin.x()); - embree_ray.org_y = static_cast(origin.y()); - embree_ray.org_z = static_cast(origin.z()); - embree_ray.dir_x = static_cast(direction.x()); - embree_ray.dir_y = static_cast(direction.y()); - embree_ray.dir_z = static_cast(direction.z()); - embree_ray.tnear = static_cast(tmin); - embree_ray.tfar = - std::isinf(tmax) ? std::numeric_limits::max() : static_cast(tmax); - embree_ray.mask = 0xFFFFFFFF; - embree_ray.id = 0; - embree_ray.flags = 0; - - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcOccluded1(m_embree_world_scene, &embree_ray); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded1(m_embree_world_scene, &context, &embree_ray); -#endif - ensure_no_errors_internal(); - - // If hit, the tfar field will be set to -inf. - return !std::isfinite(embree_ray.tfar); - } - - /** Use the underlying BVH to find the point closest to a query point. */ - ClosestPoint query_closest_point(const Point& p) const; - - /** Add raycasting utilities **/ - Index add_raycasting_mesh( - std::unique_ptr mesh, - const Transform& trans = Transform::Identity(), - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - m_meshes.push_back(std::move(mesh)); - m_transforms.push_back(trans); - m_mesh_build_qualities.push_back(build_quality); - m_visibility.push_back(true); - for (auto& f : m_filters) { // per-mesh, not per-instance - f.push_back(nullptr); - } - Index mesh_index = safe_cast(m_meshes.size() - 1); - la_runtime_assert(m_instance_index_ranges.size() > 0); - Index instance_index = m_instance_index_ranges.back(); - la_runtime_assert(instance_index == safe_cast(m_instance_to_user_mesh.size())); - m_instance_index_ranges.push_back(instance_index + 1); - m_instance_to_user_mesh.resize(instance_index + 1, mesh_index); - m_need_rebuild = true; - return mesh_index; - } - - void update_raycasting_mesh( - Index index, - std::unique_ptr mesh, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - la_runtime_assert(mesh->get_dim() == 3); - la_runtime_assert(mesh->get_vertex_per_facet() == 3); - la_runtime_assert(index < safe_cast(m_meshes.size())); - m_meshes[index] = std::move(mesh); - m_mesh_build_qualities[index] = build_quality; - m_need_rebuild = true; // TODO: Make this more fine-grained so only the affected part of - // the Embree scene is updated - } - -protected: - /** Release internal Embree scenes */ - void release_scenes() - { - for (auto& s : m_embree_mesh_scenes) { - rtcReleaseScene(s); - } - rtcReleaseScene(m_embree_world_scene); - } - - /** Get the Embree scene flags. */ - virtual RTCSceneFlags get_scene_flags() const { return m_scene_flags; } - - /** Get the Embree geometry build quality. */ - virtual RTCBuildQuality get_scene_build_quality() const { return m_build_quality; } - - /** Update all internal structures based on the current dirty flags. */ - void update_internal() - { - if (m_need_rebuild) - generate_scene(); // full rebuild - else if (m_need_commit) - commit_scene_changes(); // just call rtcCommitScene() - } - - /** - * Build the whole Embree scene from the specified meshes, instances, etc. - * - * @todo Make the dirty flags more fine-grained so that only the changed meshes are re-sent to - * Embree. - */ - void generate_scene() - { - if (!m_need_rebuild) return; - - // Scene needs to be updated - release_scenes(); - m_embree_world_scene = rtcNewScene(m_device); - auto scene_flags = get_scene_flags(); // FIXME: or just m_scene_flags? - auto scene_build_quality = get_scene_build_quality(); // FIXME: or just m_build_quality? - rtcSetSceneFlags( - m_embree_world_scene, - scene_flags); // TODO: maybe also set RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION - rtcSetSceneBuildQuality(m_embree_world_scene, scene_build_quality); - m_float_data.clear(); - m_int_data.clear(); - const auto num_meshes = m_meshes.size(); - la_runtime_assert(num_meshes + 1 == m_instance_index_ranges.size()); - m_embree_mesh_scenes.resize(num_meshes); - m_mesh_vertex_counts.resize(num_meshes); - ensure_no_errors_internal(); - - bool is_mask_supported = - rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED); - for (size_t i = 0; i < num_meshes; i++) { - // Initialize RTC meshes - const auto& mesh = m_meshes[i]; - // const auto& vertices = mesh->get_vertices(); - // const auto& facets = mesh->get_facets(); - const Index num_vertices = m_mesh_vertex_counts[i] = - safe_cast(mesh->get_num_vertices()); - const Index num_facets = safe_cast(mesh->get_num_facets()); - - auto& embree_mesh_scene = m_embree_mesh_scenes[i]; - embree_mesh_scene = rtcNewScene(m_device); - - rtcSetSceneFlags(embree_mesh_scene, scene_flags); - rtcSetSceneBuildQuality(embree_mesh_scene, scene_build_quality); - ensure_no_errors_internal(); - - RTCGeometry geom = rtcNewGeometry( - m_device, - RTC_GEOMETRY_TYPE_TRIANGLE); // EMBREE_FIXME: check if geometry gets properly - // committed - rtcSetGeometryBuildQuality(geom, m_mesh_build_qualities[i]); - // rtcSetGeometryTimeStepCount(geom, 1); - - const float* vertex_data = extract_float_data(*mesh); - const unsigned* facet_data = extract_int_data(*mesh); - - rtcSetSharedGeometryBuffer( - geom, - RTC_BUFFER_TYPE_VERTEX, - 0, - RTC_FORMAT_FLOAT3, - vertex_data, - 0, - sizeof(float) * 3, - num_vertices); - rtcSetSharedGeometryBuffer( - geom, - RTC_BUFFER_TYPE_INDEX, - 0, - RTC_FORMAT_UINT3, - facet_data, - 0, - sizeof(int) * 3, - num_facets); - - set_intersection_filter(geom, m_filters[FILTER_INTERSECT][i], is_mask_supported); - set_occlusion_filter(geom, m_filters[FILTER_OCCLUDED][i], is_mask_supported); - - rtcCommitGeometry(geom); - rtcAttachGeometry(embree_mesh_scene, geom); - rtcReleaseGeometry(geom); - ensure_no_errors_internal(); - - // Initialize RTC instances - for (Index instance_index = m_instance_index_ranges[i]; - instance_index < m_instance_index_ranges[i + 1]; - ++instance_index) { - const auto& trans = m_transforms[instance_index]; - - RTCGeometry geom_inst = rtcNewGeometry( - m_device, - RTC_GEOMETRY_TYPE_INSTANCE); // EMBREE_FIXME: check if geometry gets properly - // committed - rtcSetGeometryInstancedScene(geom_inst, embree_mesh_scene); - rtcSetGeometryTimeStepCount(geom_inst, 1); - - Eigen::Matrix T = trans.template cast(); - rtcSetGeometryTransform(geom_inst, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.data()); - ensure_no_errors_internal(); - - if (is_mask_supported) { - rtcSetGeometryMask( - geom_inst, - m_visibility[instance_index] ? 0xFFFFFFFF : 0x00000000); - } - ensure_no_errors_internal(); - - rtcCommitGeometry(geom_inst); - unsigned rtc_instance_id = rtcAttachGeometry(m_embree_world_scene, geom_inst); - rtcReleaseGeometry(geom_inst); - la_runtime_assert(safe_cast(rtc_instance_id) == instance_index); - ensure_no_errors_internal(); - } - - rtcCommitScene(embree_mesh_scene); - ensure_no_errors_internal(); - } - rtcCommitScene(m_embree_world_scene); - ensure_no_errors_internal(); - - m_need_rebuild = m_need_commit = false; - } - - /** Get the vertex data of a mesh as an array of floats. */ - const float* extract_float_data(const RaycasterMesh& mesh) - { - auto float_data = mesh.vertices_to_float(); - // Due to Embree bug, we have to have at least one more entry - // after the bound. Sigh... - // See https://github.com/embree/embree/issues/124 - float_data.push_back(0.0); - m_float_data.emplace_back(std::move(float_data)); - return m_float_data.back().data(); - } - - /** Get the index data of a mesh as an array of integers. */ - const unsigned* extract_int_data(const RaycasterMesh& mesh) - { - auto int_data = mesh.indices_to_int(); - // Due to Embree bug, we have to have at least one more entry - // after the bound. Sigh... - // See https://github.com/embree/embree/issues/124 - int_data.push_back(0); - m_int_data.emplace_back(std::move(int_data)); - return m_int_data.back().data(); - } - -private: - /** - * Helper function for setting intersection filters. Does NOT commit the geometry. The caller - * must explicitly call `rtcCommitGeometry()` afterwards. - */ - void set_intersection_filter(RTCGeometry geom, FilterFunction filter, bool is_mask_supported) - { - if (is_mask_supported) { - if (filter) { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter); - } else { - rtcSetGeometryIntersectFilterFunction(geom, nullptr); - } - } else { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter_and_mask); - } - } - - /** - * Helper function for setting occlusion filters. Does NOT commit the geometry. The caller must - * explicitly call `rtcCommitGeometry()` afterwards. - */ - void set_occlusion_filter(RTCGeometry geom, FilterFunction filter, bool is_mask_supported) - { - if (is_mask_supported) { - if (filter) { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter); - } else { - rtcSetGeometryOccludedFilterFunction(geom, nullptr); - } - } else { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter_and_mask); - } - } - - /** - * Embree-compatible callback function that computes indices specific to this object and then - * delegates to the user-specified filter function. - */ - template // 0: intersection, 1: occlusion - static void wrap_filter(const RTCFilterFunctionNArguments* args) - { - // Embree never actually calls a filter callback with different geometry or instance IDs - // So we can assume they are the same for all the hits in this batch. Also, every single - // mesh in this class is instanced (never used raw), so we can ignore geomID. - const auto* obj = reinterpret_cast(args->geometryUserPtr); - auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0); - assert(rtc_inst_id < obj->m_instance_to_user_mesh.size()); - - auto filter = obj->m_filters[IntersectionOrOcclusion][rtc_inst_id]; - if (!filter) { - return; - } - - Index mesh_index = obj->m_instance_to_user_mesh[rtc_inst_id]; - assert(mesh_index + 1 < obj->m_instance_index_ranges.size()); - assert(mesh_index < safe_cast(obj->m_meshes.size())); - Index instance_index = rtc_inst_id - obj->m_instance_index_ranges[mesh_index]; - - // In case Embree's implementation changes in the future, the callback should be written - // generally, without assuming the single geometry/instance condition above. - Index4 mesh_index4; - mesh_index4.fill(mesh_index); - Index4 instance_index4; - instance_index4.fill(instance_index); - - // Call the wrapped filter with the indices specific to this object - filter(obj, mesh_index4.data(), instance_index4.data(), args); - } - - /** - * Embree-compatible callback function that checks if the intersected object is visible or not, - * computes indices specific to this object, and then delegates to the user-specified filter - * function. - */ - template // 0: intersection, 1: occlusion - static void wrap_filter_and_mask(const RTCFilterFunctionNArguments* args) - { - // Embree never actually calls a filter callback with different geometry or instance IDs - // So we can assume they are the same for all the hits in this batch. Also, every single - // mesh in this class is instanced (never used raw), so we can ignore geomID. - const auto* obj = reinterpret_cast(args->geometryUserPtr); - auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0); - if (!obj->m_visibility[rtc_inst_id]) { - // Object is invisible. Make the hits of all the rays with this object invalid. - std::fill(args->valid, args->valid + args->N, 0); - return; - } - - // Delegate to the regular filtering after having checked visibility - wrap_filter(args); - } - -protected: - RTCSceneFlags m_scene_flags; - RTCBuildQuality m_build_quality; - RTCDevice m_device; - RTCScene m_embree_world_scene; - bool m_need_rebuild; // full rebuild of the scene? - bool m_need_commit; // just call rtcCommitScene() on the scene? - - // Data reservoirs for holding temporary/casted/per-geometry data. - // Length = Number of polygonal meshes - std::vector m_float_data; - std::vector m_int_data; - std::vector> m_meshes; - std::vector m_mesh_build_qualities; - std::vector m_embree_mesh_scenes; - std::vector m_mesh_vertex_counts; // for bounds-checking of buffer updates - std::vector m_filters[2]; // 0: intersection filters, 1: occlusion filters - - // Ranges of instance indices corresponding to a specific - // Mesh. For example, in a scenario with 3 meshes each of - // which has 1, 2, 5 instances, this array would be - // [0, 1, 3, 8]. - // Length = Number of user meshes + 1 - std::vector m_instance_index_ranges; - - // Mapping from (RTC-)instanced mesh to user mesh. For - // example, in a scenario with 3 meshes each of - // which has 1, 2, 5 instances, this array would be - // [0, 1, 1, 2, 2, 2, 2, 2] - // Length = Number of instanced meshes - // Note: This array is only used internally. We shouldn't - // allow the users to access anything with the indices - // used in those RTC functions. - std::vector m_instance_to_user_mesh; - - // Data reservoirs for holding instanced mesh data - // Length = Number of (world-space) instanced meshes - std::vector m_transforms; - std::vector m_visibility; - - // error checking function used internally - void ensure_no_errors_internal() const - { -#ifdef LAGRANGE_EMBREE_DEBUG - EmbreeHelper::ensure_no_errors(m_device); -#endif - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// IMPLEMENTATION -//////////////////////////////////////////////////////////////////////////////// - -template -auto EmbreeRayCaster::query_closest_point(const Point& p) const -> ClosestPoint -{ - RTCPointQuery query; - query.x = (float)(p.x()); - query.y = (float)(p.y()); - query.z = (float)(p.z()); - query.radius = std::numeric_limits::max(); - query.time = 0.f; - ensure_no_errors_internal(); - - ClosestPoint result; - - // Callback to retrieve triangle corner positions - result.populate_triangle = - [&](unsigned mesh_index, unsigned facet_index, Point& v0, Point& v1, Point& v2) { - // TODO: There's no way to call this->get_mesh<> since we need to template the function - // by the (derived) type, which we don't know here... This means our only choice is so - // use the float data instead of the (maybe) double point coordinate if available. Note - // that we could also call rtcSetGeometryPointQueryFunction() when we register our mesh, - // since we know the derived type at this point. - const unsigned* face = m_int_data[mesh_index].data() + 3 * facet_index; - const float* vertices = m_float_data[mesh_index].data(); - v0 = Point(vertices[3 * face[0]], vertices[3 * face[0] + 1], vertices[3 * face[0] + 2]); - v1 = Point(vertices[3 * face[1]], vertices[3 * face[1] + 1], vertices[3 * face[1] + 2]); - v2 = Point(vertices[3 * face[2]], vertices[3 * face[2] + 1], vertices[3 * face[2] + 2]); - }; - - { - RTCPointQueryContext context; - rtcInitPointQueryContext(&context); - rtcPointQuery( - m_embree_world_scene, - &query, - &context, - &embree_closest_point, - reinterpret_cast(&result)); - assert( - result.mesh_index != RTC_INVALID_GEOMETRY_ID || - result.facet_index != RTC_INVALID_GEOMETRY_ID); - assert( - result.mesh_index != invalid() || result.facet_index != invalid()); - } - ensure_no_errors_internal(); - - return result; -} - -} // namespace raycasting -} // namespace lagrange -======= #ifdef LAGRANGE_ENABLE_LEGACY_FUNCTIONS #include #endif ->>>>>>> origin/main diff --git a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h index 1c70701f..65bd2561 100644 --- a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h +++ b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h @@ -11,105 +11,6 @@ */ #pragma once -<<<<<<< HEAD -#include - -#include - -#ifdef LAGRANGE_WITH_EMBREE_4 - #include - #include - #include -#else - #include - #include - #include -#endif - -#include - -RTC_NAMESPACE_USE - -namespace lagrange { -namespace raycasting { - -template -bool embree_closest_point(RTCPointQueryFunctionArguments* args) -{ - using Point = typename ClosestPointResult::Point; - using MapType = Eigen::Map; - using AffineMat = Eigen::Transform; - - assert(args->userPtr); - auto result = reinterpret_cast*>(args->userPtr); - - const unsigned int geomID = args->geomID; - const unsigned int primID = args->primID; - - RTCPointQueryContext* context = args->context; - const unsigned int stack_size = args->context->instStackSize; - const unsigned int stack_ptr = stack_size - 1; - - AffineMat inst2world = - (stack_size > 0 ? AffineMat(MapType(context->inst2world[stack_ptr]).template cast()) - : AffineMat::Identity()); - - // Query position in world space - Point q(args->query->x, args->query->y, args->query->z); - - // Get triangle information in local space - Point v0, v1, v2; - assert(result->populate_triangle); - result->populate_triangle(geomID, primID, v0, v1, v2); - - // Bring query and primitive data in the same space if necessary. - if (stack_size > 0 && args->similarityScale > 0) { - // Instance transform is a similarity transform, therefore we - // can compute distance information in instance space. Therefore, - // transform query position into local instance space. - AffineMat world2inst(MapType(context->world2inst[stack_ptr]).template cast()); - q = world2inst * q; - } else if (stack_size > 0) { - // Instance transform is not a similarity tranform. We have to transform the - // primitive data into world space and perform distance computations in - // world space to ensure correctness. - v0 = inst2world * v0; - v1 = inst2world * v1; - v2 = inst2world * v2; - } else { - // Primitive is not instanced, therefore point query and primitive are - // already in the same space. - } - - // Determine distance to closest point on triangle, and transform in - // world space if necessary. - Point p; - Scalar l1, l2, l3; - Scalar d2 = point_triangle_squared_distance(q, v0, v1, v2, p, l1, l2, l3); - float d = std::sqrt(static_cast(d2)); - if (args->similarityScale > 0) { - d = d / args->similarityScale; - } - - // Store result in userPtr and update the query radius if we found a point - // closer to the query position. This is optional but allows for faster - // traversal (due to better culling). - if (d < args->query->radius) { - args->query->radius = d; - result->closest_point = (args->similarityScale > 0 ? (inst2world * p).eval() : p); - result->mesh_index = geomID; - result->facet_index = primID; - result->barycentric_coord = Point(l1, l2, l3); - return true; // Return true to indicate that the query radius changed. - } - - return false; -} - -} // namespace raycasting -} // namespace lagrange -======= #ifdef LAGRANGE_ENABLE_LEGACY_FUNCTIONS #include #endif ->>>>>>> origin/main diff --git a/modules/raycasting/src/legacy/EmbreeHelper.cpp b/modules/raycasting/src/legacy/EmbreeHelper.cpp index f8e872af..9ad36768 100644 --- a/modules/raycasting/src/legacy/EmbreeHelper.cpp +++ b/modules/raycasting/src/legacy/EmbreeHelper.cpp @@ -9,17 +9,10 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -<<<<<<< HEAD:modules/raycasting/src/EmbreeHelper.cpp -#ifdef LAGRANGE_WITH_EMBREE_4 - #include -#else - #include -======= #ifdef LAGRANGE_WITH_EMBREE_3 #include #else #include ->>>>>>> origin/main:modules/raycasting/src/legacy/EmbreeHelper.cpp #endif #include From 1385250f11e6807a9f73e77040618f8bdcb5c993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 9 Mar 2026 10:16:28 -0700 Subject: [PATCH 36/79] Cleanup. --- cmake/recipes/external/embree.cmake | 175 ++++++++++++++++++ .../external/{embree3.patch => embree.patch} | 0 2 files changed, 175 insertions(+) create mode 100644 cmake/recipes/external/embree.cmake rename cmake/recipes/external/{embree3.patch => embree.patch} (100%) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake new file mode 100644 index 00000000..a323f51c --- /dev/null +++ b/cmake/recipes/external/embree.cmake @@ -0,0 +1,175 @@ +# +# Copyright 2019 Adobe. All rights reserved. +# This file is licensed to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +# OF ANY KIND, either express or implied. See the License for the specific language +# governing permissions and limitations under the License. +# +if(TARGET embree::embree) + return() +endif() + +message(STATUS "Third-party (external): creating target 'embree::embree'") + +# Set Embree's default options +option(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." OFF) +option(EMBREE_TUTORIALS "Enable to build Embree tutorials" OFF) +option(EMBREE_STATIC_LIB "Build Embree as a static library." ON) +set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing.") +set(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") +option(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." OFF) + +# Set C++ namespace to ensure support for user-defined namespaces +# TODO: Not supported yet by other internal dependencies. +# set(EMBREE_API_NAMESPACE "embree" CACHE STRING "C++ namespace to put API symbols into.") + +# The following options are necessary to ensure packed-ray support +option(EMBREE_RAY_MASK "Enable the usage of mask for packed ray." ON) +option(EMBREE_RAY_PACKETS "Enable the usage packed ray." ON) + +# Match embree's platform detection logic for arm +if(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "") OR ("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES)) + set(EMBREE_ARM ON) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + set(EMBREE_ARM ON) +endif() + +if(EMSCRIPTEN) + set(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.") + set(FLAGS_SSE2 "-msse -msse2 -msimd128") # set to non-empty to prevent embree from using incorrect flags +else() + if(APPLE AND NOT EMBREE_ARM) + set(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.") + else() + set(EMBREE_MAX_ISA "NONE" CACHE STRING "Selects highest ISA to support.") + endif() +endif() + +# We want to compile Embree with TBB support, so we need to overwrite Embree's +# `find_package()` and provide variables. The following discussion provide some +# context on how to achieve this: +# - https://gitlab.kitware.com/cmake/cmake/issues/17735 +# - https://crascit.com/2018/09/14/do-not-redefine-cmake-commands/ +function(embree_import_target) + macro(push_variable var value) + if(DEFINED CACHE{${var}}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE CACHE_TYPE) + elseif(DEFINED ${var}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE NORMAL_TYPE) + else() + set(LAGRANGE_OLD_${var}_TYPE NONE_TYPE) + endif() + set(${var} "${value}") + endmacro() + + macro(pop_variable var) + if(LAGRANGE_OLD_${var}_TYPE STREQUAL CACHE_TYPE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}" CACHE PATH "" FORCE) + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NORMAL_TYPE) + unset(${var} CACHE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}") + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NONE_TYPE) + unset(${var} CACHE) + else() + message(FATAL_ERROR "Trying to pop a variable that has not been pushed: ${var}") + endif() + endmacro() + + macro(ignore_package NAME) + set(LAGRANGE_DUMMY_DIR "${CMAKE_CURRENT_BINARY_DIR}/embree_cmake/${NAME}") + file(WRITE ${LAGRANGE_DUMMY_DIR}/${NAME}Config.cmake "") + push_variable(${NAME}_DIR ${LAGRANGE_DUMMY_DIR}) + push_variable(${NAME}_ROOT ${LAGRANGE_DUMMY_DIR}) + endmacro() + + macro(unignore_package NAME) + pop_variable(${NAME}_DIR) + pop_variable(${NAME}_ROOT) + endmacro() + + # Prefer Config mode before Module mode to prevent embree from loading its own FindTBB.cmake + set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) + + # Embree wants to be able to export() its target, and expects a target named `TBB` to exist. + # Somehow we stil need to define `TBB_INCLUDE_DIRS`, and linking against `TBB` isn't sufficient + # to compile embree targets properly. + lagrange_find_package(TBB CONFIG REQUIRED) + ignore_package(TBB) + get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) + if(NOT TARGET TBB) + add_library(TBB INTERFACE) + target_link_libraries(TBB INTERFACE TBB::tbb) + endif() + set(TBB_LIBRARIES TBB) + + # Ready to include embree's atrocious CMake + include(CPM) + set(EMBREE_VERSION v4.4.0) + set(EMBREE_PATCHES "") + if(LAGRANGE_WITH_EMBREE_3) + set(CMAKE_POLICY_VERSION_MINIMUM 3.5) + set(EMBREE_VERSION v3.13.5) + # Patch for emscripten compatibility. Fix available upstream in Embree 4+. + # https://github.com/RenderKit/embree/pull/365 + # https://github.com/RenderKit/embree/issues/486 + set(EMBREE_PATCHES PATCHES embree.patch) + endif() + CPMAddPackage( + NAME embree + GITHUB_REPOSITORY RenderKit/embree + GIT_TAG ${EMBREE_VERSION} + ${EMBREE_PATCHES} + ) + + unignore_package(TBB) + + # Disable warnings + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # Embree's subgrid.h is known for causing array subscript out of bound + # warning. Embree dev claim the code is correct and it is a GCC bug + # for misfiring warnings. See https://github.com/embree/embree/issues/271 + # + # The issue should be fixed for gcc 9.2.1 and later. + target_compile_options(embree PRIVATE "-Wno-array-bounds") + endif() + + # Warning setting + set(unix_compilers "AppleClang;Clang;GNU") + if(CMAKE_CXX_COMPILER_ID IN_LIST unix_compilers) # IN_LIST wants the second arg to be a var + target_compile_options(embree PRIVATE "-Wno-unused-private-field") + target_compile_options(embree PRIVATE "-Wno-unused-but-set-variable") + endif() + + # Now we need to do some juggling to propagate the include directory properties + # along with the `embree` target + add_library(embree::embree INTERFACE IMPORTED GLOBAL) + target_include_directories(embree::embree SYSTEM INTERFACE ${embree_SOURCE_DIR}/include) + target_link_libraries(embree::embree INTERFACE embree) + + # Generate a dummy .cpp for embree's math library, to workaround a weird link issue with + # LLVM-Clang on macOS + # Generate implementation file + file(WRITE "${embree_BINARY_DIR}/embree_math_dummy.cpp.in" [[ + namespace embree { + void math_dummy() {} + } + ]]) + configure_file(${embree_BINARY_DIR}/embree_math_dummy.cpp.in ${embree_BINARY_DIR}/embree_math_dummy.cpp COPYONLY) + target_sources(math PRIVATE ${embree_BINARY_DIR}/embree_math_dummy.cpp) +endfunction() + +# Call via a proper function in order to scope variables such as CMAKE_FIND_PACKAGE_PREFER_CONFIG and TBB_DIR +embree_import_target() + +# Cleanup for IDEs +foreach(name IN ITEMS embree algorithms lexers math simd sys tasking uninstall) + if(TARGET ${name}) + set_target_properties(${name} PROPERTIES FOLDER "third_party//embree") + endif() +endforeach() diff --git a/cmake/recipes/external/embree3.patch b/cmake/recipes/external/embree.patch similarity index 100% rename from cmake/recipes/external/embree3.patch rename to cmake/recipes/external/embree.patch From be33f2e13cbfe3dcf3f6b31eda91f6d62ed67fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 4 May 2026 08:21:54 -0700 Subject: [PATCH 37/79] Testing Adobe fork for embree winarm. --- cmake/recipes/external/embree.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index a323f51c..c66399f8 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -120,9 +120,14 @@ function(embree_import_target) # https://github.com/RenderKit/embree/issues/486 set(EMBREE_PATCHES PATCHES embree.patch) endif() + set(EMBREE_URL RenderKit/embree) + if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND EMBREE_VERSION STREQUAL "v4.4.0") + set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) + set(EMBREE_URL dousse-adobe/embree) + endif() CPMAddPackage( NAME embree - GITHUB_REPOSITORY RenderKit/embree + GITHUB_REPOSITORY ${EMBREE_URL} GIT_TAG ${EMBREE_VERSION} ${EMBREE_PATCHES} ) From 650921bf71a070e19fed1b03e4a4a34c314072d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 4 May 2026 08:54:19 -0700 Subject: [PATCH 38/79] Add debug message. --- cmake/recipes/external/embree.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index c66399f8..50376be7 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -122,6 +122,7 @@ function(embree_import_target) endif() set(EMBREE_URL RenderKit/embree) if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND EMBREE_VERSION STREQUAL "v4.4.0") + message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) endif() From b353250e91dc803b843e73d4753c519740ec38a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 07:24:08 -0700 Subject: [PATCH 39/79] Don't set embree isa manually. --- .github/workflows/continuous.yaml | 18 ------------------ cmake/recipes/external/embree.cmake | 2 ++ 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index dd16c58a..f88adfdb 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -147,18 +147,6 @@ jobs: with: xcode-version: '26.0.1' - - name: Select embree isa (Linux) - if: runner.os == 'Linux' - run: echo "embree_max_isa=SSE2" >> $GITHUB_ENV - - - name: Select embree isa (macOS x64) - if: runner.os == 'macOS' && runner.arch == 'X64' - run: echo "embree_max_isa=DEFAULT" >> $GITHUB_ENV - - - name: Select embree isa (macOS arm64) - if: runner.os == 'macOS' && runner.arch == 'ARM64' - run: echo "embree_max_isa=NONE" >> $GITHUB_ENV - - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores @@ -175,7 +163,6 @@ jobs: -DOPENVDB_CORE_STATIC=OFF \ -DUSE_EXPLICIT_INSTANTIATION=OFF \ -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON \ - -DEMBREE_MAX_ISA=${{ env.embree_max_isa }} \ -DUSE_SANITIZER="${{ matrix.sanitizer }}" - name: Build @@ -228,10 +215,6 @@ jobs: # starving sccache of requests until the default 600s timeout kills the server. echo "SCCACHE_IDLE_TIMEOUT=0" >> ${env:GITHUB_ENV} - - name: Select embree isa (Windows) - if: runner.os == 'Windows' - run: echo "embree_max_isa=AVX2" >> ${env:GITHUB_ENV} - - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores @@ -265,7 +248,6 @@ jobs: -DLAGRANGE_JENKINS=ON ` -DLAGRANGE_ALL=ON ` -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` - -DEMBREE_MAX_ISA=${{ env.embree_max_isa }} ` -B ${{ env.BUILD_DIR }} ` -S . diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 50376be7..5646bc38 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -33,8 +33,10 @@ option(EMBREE_RAY_PACKETS "Enable the usage packed ray." # Match embree's platform detection logic for arm if(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "") OR ("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES)) + message(STATUS "Setting arm version of Embree") set(EMBREE_ARM ON) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + message(STATUS "Setting arm version of Embree") set(EMBREE_ARM ON) endif() From de35c0166a1d7660431cabcd38f197def06ab40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 13:16:14 -0700 Subject: [PATCH 40/79] Update gklib version. --- cmake/recipes/external/gklib.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/gklib.cmake b/cmake/recipes/external/gklib.cmake index d62b7ad5..3d0cfee7 100644 --- a/cmake/recipes/external/gklib.cmake +++ b/cmake/recipes/external/gklib.cmake @@ -19,7 +19,7 @@ include(CPM) CPMAddPackage( NAME gklib GITHUB_REPOSITORY KarypisLab/GKlib - GIT_TAG 67c6e4322bb326a04727995775c3eafc47d7a252 + GIT_TAG e2856c2f595b153ca1ce9258c5301dbabc4f39f5 DOWNLOAD_ONLY ON ) From 7d44b9c513ffb767935e91d111e751836f51156e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 17:15:32 -0700 Subject: [PATCH 41/79] Update gklib cmake. --- cmake/recipes/external/gklib.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/recipes/external/gklib.cmake b/cmake/recipes/external/gklib.cmake index 3d0cfee7..4b9a109c 100644 --- a/cmake/recipes/external/gklib.cmake +++ b/cmake/recipes/external/gklib.cmake @@ -23,10 +23,10 @@ CPMAddPackage( DOWNLOAD_ONLY ON ) -file(GLOB INC_FILES "${gklib_SOURCE_DIR}/*.h" ) -file(GLOB SRC_FILES "${gklib_SOURCE_DIR}/*.c" ) +file(GLOB INC_FILES "${gklib_SOURCE_DIR}/include/*.h" ) +file(GLOB SRC_FILES "${gklib_SOURCE_DIR}/src/*.c" ) if(NOT MSVC) - list(REMOVE_ITEM SRC_FILES "${gklib_SOURCE_DIR}/gkregex.c") + list(REMOVE_ITEM SRC_FILES "${gklib_SOURCE_DIR}/src/gkregex.c") endif() add_library(GKlib STATIC ${INC_FILES} ${SRC_FILES}) @@ -39,7 +39,7 @@ endif() include(GNUInstallDirs) target_include_directories(GKlib SYSTEM PUBLIC - "$" + "$" "$" ) From d0e3f340ed1417355ed4f27e66da5f2d53cbc263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 20:08:17 -0700 Subject: [PATCH 42/79] Restore isa selection on unix platforms. --- .github/workflows/continuous.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index f88adfdb..f802e308 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -147,6 +147,18 @@ jobs: with: xcode-version: '26.0.1' + - name: Select embree isa (Linux) + if: runner.os == 'Linux' + run: echo "embree_max_isa=SSE2" >> $GITHUB_ENV + + - name: Select embree isa (macOS x64) + if: runner.os == 'macOS' && runner.arch == 'X64' + run: echo "embree_max_isa=DEFAULT" >> $GITHUB_ENV + + - name: Select embree isa (macOS arm64) + if: runner.os == 'macOS' && runner.arch == 'ARM64' + run: echo "embree_max_isa=NONE" >> $GITHUB_ENV + - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores @@ -163,6 +175,7 @@ jobs: -DOPENVDB_CORE_STATIC=OFF \ -DUSE_EXPLICIT_INSTANTIATION=OFF \ -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON \ + -DEMBREE_MAX_ISA=${{ env.embree_max_isa }} \ -DUSE_SANITIZER="${{ matrix.sanitizer }}" - name: Build From 1933a58e94951d2974d21ae65bb73fc543eada60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 22:36:17 -0700 Subject: [PATCH 43/79] Fix for winarm gklib. --- cmake/recipes/external/gklib.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmake/recipes/external/gklib.cmake b/cmake/recipes/external/gklib.cmake index 4b9a109c..322eb070 100644 --- a/cmake/recipes/external/gklib.cmake +++ b/cmake/recipes/external/gklib.cmake @@ -35,6 +35,13 @@ add_library(GKlib::GKlib ALIAS GKlib) if(MSVC) target_compile_definitions(GKlib PUBLIC USE_GKREGEX) target_compile_definitions(GKlib PUBLIC "__thread=__declspec(thread)") + # gk_ms_stdint.h / gk_ms_inttypes.h are 2006-era polyfills for pre-VS2010 MSVC. + # Modern MSVC (VS2010+) ships natively, but on ARM64 it defines + # int_fast16_t as 'int' (32-bit) while the polyfill defines it as 'int16_t', + # causing a redefinition error. Suppress the polyfills via their include guards + # and force-include the real system header so the types are still available. + target_compile_definitions(GKlib PUBLIC _MSC_STDINT_H_ _MSC_INTTYPES_H_) + target_compile_options(GKlib PUBLIC "/FIstdint.h" "/FIinttypes.h") endif() include(GNUInstallDirs) From 95c2ad6b0fe9b9ab31dfb9a1993fa18a9cedea35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 23:03:40 -0700 Subject: [PATCH 44/79] Update simde. --- cmake/recipes/external/simde.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index cffa746e..fa658f06 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -19,7 +19,7 @@ include(CPM) CPMAddPackage( NAME simde GITHUB_REPOSITORY simd-everywhere/simde - GIT_TAG 48edfa906d835525e2061fbf6062b7c326d66840 + GIT_TAG 1747b2482589fe894d49989159421da08c2a8bcd ) add_library(simde::simde INTERFACE IMPORTED GLOBAL) From cf508503ba827bb81b6f432222ffda8a3f5623f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 07:41:25 -0700 Subject: [PATCH 45/79] Update simde. --- cmake/recipes/external/simde.cmake | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index fa658f06..f7e86de6 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -22,11 +22,8 @@ CPMAddPackage( GIT_TAG 1747b2482589fe894d49989159421da08c2a8bcd ) -add_library(simde::simde INTERFACE IMPORTED GLOBAL) -target_include_directories(simde::simde INTERFACE "${simde_SOURCE_DIR}") - # Enables native aliases. Not ideal but makes it easier to convert old code. -target_compile_definitions(simde::simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) +target_compile_definitions(simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) # Uncomment this line to ensure code can be compiled without native SIMD (i.e. emulates everything) -# target_compile_definitions(simde::simde INTERFACE SIMDE_NO_NATIVE) +# target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) From 6a8ecec90e8ea4c3027d875cd405b1e72a6c1892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 11:45:06 -0700 Subject: [PATCH 46/79] Winarm patch. --- cmake/recipes/external/embree.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 5646bc38..d6d01927 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -127,6 +127,9 @@ function(embree_import_target) message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) + # intrinsics.h guards x86 BMI/LZCNT intrinsics with !defined(__aarch64__) but misses + # _M_ARM64 (the MSVC macro for ARM64), causing build failures on Windows ARM64. + set(EMBREE_PATCHES PATCHES embree-winarm.patch) endif() CPMAddPackage( NAME embree From ca6ad6873a0de4202e7aa38778f41860de0fddce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 11:55:51 -0700 Subject: [PATCH 47/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Windows=20ARM64=20bu?= =?UTF-8?q?ild:=20Embree=20intrinsics=20patch=20+=20SIMDe=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add embree-winarm.patch: guards _tzcnt_u64, _lzcnt_u64, _pext_u32/_pdep_u32 with !defined(_M_ARM64) (MSVC ARM64 macro, missing alongside __aarch64__) - simde.cmake: disable SIMDE native NEON on MSVC ARM64 to avoid __m128/__m128i being the same underlying __n128 type, which breaks WindingNumber overloads Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree-winarm.patch | 24 ++++++++++++++++++++++ cmake/recipes/external/simde.cmake | 9 ++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 cmake/recipes/external/embree-winarm.patch diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch new file mode 100644 index 00000000..f2a534e9 --- /dev/null +++ b/cmake/recipes/external/embree-winarm.patch @@ -0,0 +1,24 @@ +diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h +--- i/common/sys/intrinsics.h ++++ w/common/sys/intrinsics.h +@@ -91,7 +91,7 @@ + #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) + __forceinline size_t bsf(size_t v) { +-#if defined(__AVX2__) ++#if defined(__AVX2__) && !defined(_M_ARM64) + return _tzcnt_u64(v); + #else + unsigned long r = 0; _BitScanForward64(&r,v); return r; +@@ -141,7 +141,7 @@ + __forceinline size_t bsr(size_t v) { +-#if defined(__AVX2__) ++#if defined(__AVX2__) && !defined(_M_ARM64) + return 63 -_lzcnt_u64(v); + #else + unsigned long r = 0; _BitScanReverse64(&r, v); return r; +@@ -534,7 +534,7 @@ +-#if defined(__AVX2__) && !defined(__aarch64__) ++#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64) + __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); } + __forceinline unsigned int pdep(unsigned int a, unsigned int b) { return _pdep_u32(a, b); } + #if defined(__X86_64__) diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index f7e86de6..a989990b 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -25,5 +25,10 @@ CPMAddPackage( # Enables native aliases. Not ideal but makes it easier to convert old code. target_compile_definitions(simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) -# Uncomment this line to ensure code can be compiled without native SIMD (i.e. emulates everything) -# target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) +# On MSVC ARM64, all NEON vector types (float32x4_t, int64x2_t, ...) are typedefs of the same +# __n128 type, so simde__m128 and simde__m128i would be identical to the type system. This breaks +# code that overloads on __m128 vs __m128i (e.g. WindingNumber's VM_SSEFunc.h). Disabling native +# NEON forces SIMDe to use its own distinct union types instead. +if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) +endif() From f92d2f8e2b001ea1844fa3b8f6c003c738453ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 12:12:07 -0700 Subject: [PATCH 48/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20embree-winarm.patch?= =?UTF-8?q?=20hunk=20line=20counts=20for=20strict=20patch.exe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree-winarm.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch index f2a534e9..cba735a0 100644 --- a/cmake/recipes/external/embree-winarm.patch +++ b/cmake/recipes/external/embree-winarm.patch @@ -1,7 +1,7 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h --- i/common/sys/intrinsics.h +++ w/common/sys/intrinsics.h -@@ -91,7 +91,7 @@ +@@ -91,6 +91,6 @@ #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) __forceinline size_t bsf(size_t v) { -#if defined(__AVX2__) @@ -9,14 +9,14 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h return _tzcnt_u64(v); #else unsigned long r = 0; _BitScanForward64(&r,v); return r; -@@ -141,7 +141,7 @@ +@@ -141,5 +141,5 @@ __forceinline size_t bsr(size_t v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return 63 -_lzcnt_u64(v); #else unsigned long r = 0; _BitScanReverse64(&r, v); return r; -@@ -534,7 +534,7 @@ +@@ -534,4 +534,4 @@ -#if defined(__AVX2__) && !defined(__aarch64__) +#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64) __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); } From 645a118fd59c513cc412f42492301aa60835052b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 12:29:01 -0700 Subject: [PATCH 49/79] =?UTF-8?q?=F0=9F=90=9B=20Replace=20patch-file=20app?= =?UTF-8?q?roach=20with=20CMake=20string=20replacement=20for=20embree=20AR?= =?UTF-8?q?M64=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Strawberry patch.exe is strict about hunk line counts and running offsets, causing hunk 3 to search at the wrong line. Use file(READ)+string(REGEX REPLACE)+file(WRITE) instead to apply _M_ARM64 guards in intrinsics.h. Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree.cmake | 32 ++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index d6d01927..16a587ba 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -127,9 +127,6 @@ function(embree_import_target) message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) - # intrinsics.h guards x86 BMI/LZCNT intrinsics with !defined(__aarch64__) but misses - # _M_ARM64 (the MSVC macro for ARM64), causing build failures on Windows ARM64. - set(EMBREE_PATCHES PATCHES embree-winarm.patch) endif() CPMAddPackage( NAME embree @@ -138,6 +135,35 @@ function(embree_import_target) ${EMBREE_PATCHES} ) + # Fix intrinsics.h for MSVC ARM64: the dousse-adobe fork defines __AVX2__ on ARM64 to trigger + # SIMDe, but uses !defined(__aarch64__) (GCC/Clang) instead of !defined(_M_ARM64) (MSVC) to + # guard x86 BMI/LZCNT/PEXT intrinsics, causing build failures. We apply this fix via CMake + # string replacement rather than a patch file to avoid dependency on Strawberry's patch.exe, + # which is strict about unified-diff line counts and offsets. + if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND DEFINED embree_SOURCE_DIR) + set(_intrinsics "${embree_SOURCE_DIR}/common/sys/intrinsics.h") + if(EXISTS "${_intrinsics}") + file(READ "${_intrinsics}" _content) + string(ASCII 13 _cr) + string(ASCII 10 _lf) + # Two bsf/bsr instances end with a trailing space before the newline. + string(REGEX REPLACE + "#if defined\\(__AVX2__\\) ([${_cr}${_lf}])" + "#if defined(__AVX2__) && !defined(_M_ARM64)\\1" + _content "${_content}") + # pext/pdep instance uses the __aarch64__ guard without the trailing space. + string(REPLACE + "#if defined(__AVX2__) && !defined(__aarch64__)" + "#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64)" + _content "${_content}") + file(WRITE "${_intrinsics}" "${_content}") + unset(_content) + endif() + unset(_intrinsics) + unset(_cr) + unset(_lf) + endif() + unignore_package(TBB) # Disable warnings From 2b4ca1ebbabdd65400d310adf632e4cf23166cc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 13:34:58 -0700 Subject: [PATCH 50/79] =?UTF-8?q?=F0=9F=90=9B=20Disable=20Python=20binding?= =?UTF-8?q?s=20on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ARM64 Python on GitHub Actions hostedtoolcache lacks development files (headers + import lib). CMake falls back to x64 Python's Development.Module, but MSVC in ARM64 mode cannot link against the x64 python313.lib, producing hundreds of unresolved __imp_Py* linker errors. Fix: split the Windows configure step to pass -DLAGRANGE_MODULE_PYTHON=OFF for windows-11-arm, and update CMakeLists.txt to honor an explicit -DLAGRANGE_MODULE_PYTHON=OFF even when LAGRANGE_ALL=ON. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/continuous.yaml | 17 +++++++++++++++++ CMakeLists.txt | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index f802e308..7eed5845 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -254,6 +254,7 @@ jobs: # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure + if: matrix.os != 'windows-11-arm' run: | cmake --version cmake -G Ninja ` @@ -264,6 +265,22 @@ jobs: -B ${{ env.BUILD_DIR }} ` -S . + # Python bindings are disabled on ARM64: the hostedtoolcache ARM64 Python lacks + # development files, causing CMake to fall back to x64 Python headers that the + # ARM64 MSVC toolchain cannot link against. + - name: Configure (ARM64) + if: matrix.os == 'windows-11-arm' + run: | + cmake --version + cmake -G Ninja ` + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` + -DLAGRANGE_JENKINS=ON ` + -DLAGRANGE_ALL=ON ` + -DLAGRANGE_MODULE_PYTHON=OFF ` + -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -B ${{ env.BUILD_DIR }} ` + -S . + - name: Build run: cmake --build ${{ env.BUILD_DIR }} -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index c34b82cc..81361c2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,8 +269,8 @@ if(BUILD_SHARED_LIBS) ) endif() -# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set -if(LAGRANGE_ALL) +# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set (unless explicitly disabled via -D) +if(LAGRANGE_ALL AND NOT (DEFINED CACHE{LAGRANGE_MODULE_PYTHON} AND NOT LAGRANGE_MODULE_PYTHON)) set(LAGRANGE_MODULE_PYTHON ON) endif() From 41a38ab1254a7b6d08bdbd842a9a9a5c910c56ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 14:38:59 -0700 Subject: [PATCH 51/79] =?UTF-8?q?=F0=9F=90=9B=20Allow=20-DLAGRANGE=5FMODUL?= =?UTF-8?q?E=5FX=3DOFF=20to=20override=20LAGRANGE=5FALL=3DON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The module-inclusion loop unconditionally honored LAGRANGE_ALL, so passing -DLAGRANGE_MODULE_PYTHON=OFF together with -DLAGRANGE_ALL=ON still pulled modules/python into the build. Capture the cache state before option() materializes the default value, then skip modules the user explicitly disabled even when LAGRANGE_ALL is set. Co-Authored-By: Claude Sonnet 4.6 --- modules/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 6aeda78e..56c1ae65 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -48,6 +48,14 @@ foreach(name IN ITEMS ${module_names}) string(TOUPPER ${name} MODULE_FLAG) set(MODULE_OPTION LAGRANGE_MODULE_${MODULE_FLAG}) + # Capture whether the user explicitly disabled this module before option() materializes + # the cache variable (the default-OFF cache value would otherwise be indistinguishable + # from an explicit -DLAGRANGE_MODULE_X=OFF on the command line). + set(_user_disabled_module FALSE) + if(DEFINED CACHE{${MODULE_OPTION}} AND NOT ${${MODULE_OPTION}}) + set(_user_disabled_module TRUE) + endif() + # Allows setting the option option(${MODULE_OPTION} "Build module lagrange::${name}" OFF) @@ -61,7 +69,7 @@ foreach(name IN ITEMS ${module_names}) "Please use the helper function lagrange_include_modules() instead.") endif() - if(${MODULE_OPTION} OR LAGRANGE_ALL) + if(${MODULE_OPTION} OR (LAGRANGE_ALL AND NOT _user_disabled_module)) lagrange_include_modules(${name}) endif() endforeach() From 7ca8b10babcb551f94bfb3a076a469a5d52a88bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 14:48:23 -0700 Subject: [PATCH 52/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Python=20bindings=20?= =?UTF-8?q?on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of disabling Python, install the ARM64 Python with its full development files by passing architecture: arm64 to setup-python. Without this, setup-python only installs the ARM64 interpreter (no python313.lib or headers), causing CMake FindPython to fall back to the x64 Python for Development.Module -- which the ARM64 MSVC toolchain cannot link against. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/continuous.yaml | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 7eed5845..33838785 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -215,9 +215,20 @@ jobs: fetch-depth: 0 - uses: actions/setup-python@v5 + if: matrix.os != 'windows-11-arm' with: python-version: 3.13 + # Explicitly request arm64 architecture so that the Python dev files + # (headers + python313.lib) are installed for ARM64, not just the interpreter. + # Without this, CMake falls back to the x64 Python for Development.Module, + # which the ARM64 MSVC toolchain cannot link against. + - uses: actions/setup-python@v5 + if: matrix.os == 'windows-11-arm' + with: + python-version: 3.13 + architecture: arm64 + - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@master @@ -254,29 +265,12 @@ jobs: # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure - if: matrix.os != 'windows-11-arm' - run: | - cmake --version - cmake -G Ninja ` - -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` - -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_ALL=ON ` - -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` - -B ${{ env.BUILD_DIR }} ` - -S . - - # Python bindings are disabled on ARM64: the hostedtoolcache ARM64 Python lacks - # development files, causing CMake to fall back to x64 Python headers that the - # ARM64 MSVC toolchain cannot link against. - - name: Configure (ARM64) - if: matrix.os == 'windows-11-arm' run: | cmake --version cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` -DLAGRANGE_ALL=ON ` - -DLAGRANGE_MODULE_PYTHON=OFF ` -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` -B ${{ env.BUILD_DIR }} ` -S . From 5bd94896f82b46713c87716a1aa4eceb4bedb7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 16:02:13 -0700 Subject: [PATCH 53/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Python=20bindings=20?= =?UTF-8?q?on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The windows-11-arm hostedtoolcache Python only ships the interpreter; it lacks python3XX.lib and headers needed for extension module linking. After MSVC dev-cmd setup, synthesize the ARM64 import library from the ARM64 python3XX.dll using lib.exe /DEF /MACHINE:ARM64, and copy the architecture-neutral headers from the x64 Python install if absent. Then pass -DPython_EXECUTABLE and -DPython_FIND_REGISTRY=NEVER to CMake so FindPython uses the now-complete ARM64 Python rather than falling back to the x64 install (which the ARM64 MSVC toolchain cannot link). Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 33838785..327ea64e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -263,8 +263,68 @@ jobs: with: arch: ${{ env.ARCH }} + # The windows-11-arm hostedtoolcache Python ships only the interpreter; it lacks + # python3XX.lib and headers. We synthesize the import library from the ARM64 DLL + # using MSVC lib.exe (available after msvc-dev-cmd), and copy arch-neutral headers + # from the x64 Python if the arm64 install doesn't have them. + - name: Fix Python ARM64 development files + if: matrix.os == 'windows-11-arm' + shell: pwsh + run: | + $pyDir = $env:pythonLocation + + # Locate the Python DLL (e.g. python313.dll) + $dll = Get-ChildItem -Path $pyDir -Filter "python3*.dll" | Select-Object -First 1 + if (-not $dll) { Write-Error "No python3*.dll in $pyDir"; exit 1 } + $dllBase = $dll.BaseName + + # Generate ARM64 import library if missing + $libsDir = Join-Path $pyDir "libs" + $libFile = Join-Path $libsDir "$dllBase.lib" + if (-not (Test-Path $libFile)) { + New-Item -ItemType Directory -Force -Path $libsDir | Out-Null + $raw = & dumpbin /EXPORTS $dll.FullName 2>&1 + $exports = $raw | Where-Object { $_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+\w' } | + ForEach-Object { if ($_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+(\S+)') { $Matches[1] } } + $defPath = "$env:TEMP\$dllBase.def" + @("LIBRARY $dllBase", "EXPORTS") + $exports | Set-Content $defPath -Encoding ASCII + & lib /DEF:$defPath /MACHINE:ARM64 /OUT:$libFile + if ($LASTEXITCODE -ne 0) { Write-Error "lib.exe failed"; exit 1 } + Write-Host "Generated $libFile" + } else { Write-Host "$libFile already present" } + + # Ensure Python headers exist (they are architecture-neutral) + $includeDir = Join-Path $pyDir "include" + if (-not (Test-Path $includeDir)) { + $ver = Split-Path (Split-Path $pyDir -Parent) -Leaf + $x64Include = "C:\hostedtoolcache\windows\Python\$ver\x64\include" + if (Test-Path $x64Include) { + Copy-Item -Recurse $x64Include $includeDir + Write-Host "Copied headers from x64 to $includeDir" + } else { Write-Error "No Python headers found at $x64Include"; exit 1 } + } else { Write-Host "Headers already present at $includeDir" } + + # Expose the ARM64 Python executable path for the CMake configure step + $exePath = (Join-Path $pyDir "python.exe") -replace "\\", "/" + echo "PYTHON_ARM64_EXE=$exePath" >> $env:GITHUB_ENV + # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure + if: matrix.os != 'windows-11-arm' + run: | + cmake --version + cmake -G Ninja ` + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` + -DLAGRANGE_JENKINS=ON ` + -DLAGRANGE_ALL=ON ` + -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -B ${{ env.BUILD_DIR }} ` + -S . + + # Force CMake to use the ARM64 Python (now complete with dev files) + # and skip the Windows registry so it doesn't fall back to x64 Python. + - name: Configure (ARM64) + if: matrix.os == 'windows-11-arm' run: | cmake --version cmake -G Ninja ` @@ -272,6 +332,8 @@ jobs: -DLAGRANGE_JENKINS=ON ` -DLAGRANGE_ALL=ON ` -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -DPython_EXECUTABLE="$env:PYTHON_ARM64_EXE" ` + -DPython_FIND_REGISTRY=NEVER ` -B ${{ env.BUILD_DIR }} ` -S . From 7dd8ddbd5c93e81869c0029b28b3bc0f57852a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 16:16:10 -0700 Subject: [PATCH 54/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Python=20bindings=20?= =?UTF-8?q?on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The windows-11-arm hostedtoolcache Python ships only the interpreter binary — no include/ headers and no libs/python3XX.lib — so CMake's FindPython falls back to x64 Python for Development.Module, which the ARM64 MSVC toolchain cannot link against. Use astral-sh/setup-uv + uv python install to pull a python-build-standalone distribution instead. These distributions include full dev files. uv intentionally defaults to x64-emulated Python on Windows ARM64 runners (uv PR #13724), so we pin the cpython-3.13-windows-aarch64 specifier to get the native build. Pass -DPython_EXECUTABLE and -DPython_FIND_REGISTRY=NEVER to CMake so FindPython uses the uv-managed ARM64 Python and does not fall back to the registry-registered x64 Python. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 67 +++++++------------------------ 1 file changed, 14 insertions(+), 53 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 327ea64e..504829ae 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -219,15 +219,21 @@ jobs: with: python-version: 3.13 - # Explicitly request arm64 architecture so that the Python dev files - # (headers + python313.lib) are installed for ARM64, not just the interpreter. - # Without this, CMake falls back to the x64 Python for Development.Module, - # which the ARM64 MSVC toolchain cannot link against. - - uses: actions/setup-python@v5 + # On windows-11-arm the hostedtoolcache Python ships only the interpreter binary; + # it lacks include/ headers and libs/python3XX.lib, so CMake cannot satisfy the + # Development.Module component. Use uv instead: it pulls python-build-standalone + # distributions which include full dev files. uv defaults to x64-emulated Python + # on ARM64 Windows (uv PR #13724), so we must pin the aarch64 specifier. + - uses: astral-sh/setup-uv@v6 if: matrix.os == 'windows-11-arm' - with: - python-version: 3.13 - architecture: arm64 + + - name: Install native ARM64 Python via uv + if: matrix.os == 'windows-11-arm' + shell: pwsh + run: | + uv python install cpython-3.13-windows-aarch64 + $pyExe = (uv python find cpython-3.13-windows-aarch64).Trim() + echo "PYTHON_ARM64_EXE=$($pyExe -replace '\\', '/')" >> $env:GITHUB_ENV - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@master @@ -263,51 +269,6 @@ jobs: with: arch: ${{ env.ARCH }} - # The windows-11-arm hostedtoolcache Python ships only the interpreter; it lacks - # python3XX.lib and headers. We synthesize the import library from the ARM64 DLL - # using MSVC lib.exe (available after msvc-dev-cmd), and copy arch-neutral headers - # from the x64 Python if the arm64 install doesn't have them. - - name: Fix Python ARM64 development files - if: matrix.os == 'windows-11-arm' - shell: pwsh - run: | - $pyDir = $env:pythonLocation - - # Locate the Python DLL (e.g. python313.dll) - $dll = Get-ChildItem -Path $pyDir -Filter "python3*.dll" | Select-Object -First 1 - if (-not $dll) { Write-Error "No python3*.dll in $pyDir"; exit 1 } - $dllBase = $dll.BaseName - - # Generate ARM64 import library if missing - $libsDir = Join-Path $pyDir "libs" - $libFile = Join-Path $libsDir "$dllBase.lib" - if (-not (Test-Path $libFile)) { - New-Item -ItemType Directory -Force -Path $libsDir | Out-Null - $raw = & dumpbin /EXPORTS $dll.FullName 2>&1 - $exports = $raw | Where-Object { $_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+\w' } | - ForEach-Object { if ($_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+(\S+)') { $Matches[1] } } - $defPath = "$env:TEMP\$dllBase.def" - @("LIBRARY $dllBase", "EXPORTS") + $exports | Set-Content $defPath -Encoding ASCII - & lib /DEF:$defPath /MACHINE:ARM64 /OUT:$libFile - if ($LASTEXITCODE -ne 0) { Write-Error "lib.exe failed"; exit 1 } - Write-Host "Generated $libFile" - } else { Write-Host "$libFile already present" } - - # Ensure Python headers exist (they are architecture-neutral) - $includeDir = Join-Path $pyDir "include" - if (-not (Test-Path $includeDir)) { - $ver = Split-Path (Split-Path $pyDir -Parent) -Leaf - $x64Include = "C:\hostedtoolcache\windows\Python\$ver\x64\include" - if (Test-Path $x64Include) { - Copy-Item -Recurse $x64Include $includeDir - Write-Host "Copied headers from x64 to $includeDir" - } else { Write-Error "No Python headers found at $x64Include"; exit 1 } - } else { Write-Host "Headers already present at $includeDir" } - - # Expose the ARM64 Python executable path for the CMake configure step - $exePath = (Join-Path $pyDir "python.exe") -replace "\\", "/" - echo "PYTHON_ARM64_EXE=$exePath" >> $env:GITHUB_ENV - # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure if: matrix.os != 'windows-11-arm' From 2f03d2d71bf4b2fba612d04e8647869ddf6e62f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 17:23:23 -0700 Subject: [PATCH 55/79] =?UTF-8?q?=F0=9F=90=9B=20Use=20Eigen=20solver=20on?= =?UTF-8?q?=20Windows=20ARM64=20(no=20MKL=20support)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel MKL has no Windows ARM64 support — skip MKL/BLAS setup on that platform. DirectSolver.h already falls back to Eigen::SimplicialLDLT when LA_SOLVER_MKL is not defined, so no header changes are needed. Co-Authored-By: Claude Opus 4.7 --- modules/solver/CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/solver/CMakeLists.txt b/modules/solver/CMakeLists.txt index f7a2dd56..8c6a65e1 100644 --- a/modules/solver/CMakeLists.txt +++ b/modules/solver/CMakeLists.txt @@ -21,13 +21,17 @@ if(NOT EMSCRIPTEN AND (NOT LAGRANGE_NO_INTERNAL OR NOT SKBUILD)) # Note: For now we avoid using MKL in our open-source Python bindings, to avoid bloating up the size of # the uploaded wheels. The long-term solution is to depend on the PyPI package for MKL at build-time. - include(blas) # Accelerate on macOS, MKL on other platforms - if(APPLE) - target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_ACCELERATE) - else() - target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_MKL) + # Intel MKL has no Windows ARM64 support; fall back to Eigen's SimplicialLDLT on that platform + # (DirectSolver.h uses SimplicialLDLT when LA_SOLVER_MKL is not defined). + if(NOT (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")) + include(blas) # Accelerate on macOS, MKL on other platforms + if(APPLE) + target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_ACCELERATE) + else() + target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_MKL) + endif() + target_link_libraries(lagrange_solver INTERFACE BLAS::BLAS) endif() - target_link_libraries(lagrange_solver INTERFACE BLAS::BLAS) endif() if(USE_SANITIZER MATCHES "([Tt]hread)") From 5d520a30e1b4a6d0329a541b89627c02fda6ead7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 19:01:21 -0700 Subject: [PATCH 56/79] =?UTF-8?q?=F0=9F=8E=A8=20Cleanup=20WinARM=20fixes:?= =?UTF-8?q?=20proper=20patches,=20no=20hacks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - modules/CMakeLists.txt: revert _user_disabled_module mechanism; the Eigen solver fix means no modules need explicit ARM64 exclusions - CMakeLists.txt: revert LAGRANGE_MODULE_PYTHON guard back to the simple LAGRANGE_ALL check (same motivation) - embree.cmake: replace string(REPLACE) hack with git apply on a corrected embree-winarm.patch (fixed hunk offsets 91→92, 141→142); use --ignore-whitespace to handle CRLF from git-cloned sources on Windows - simde.cmake: remove global SIMDE_NO_NATIVE for MSVC ARM64; the issue was specific to WindingNumber, not all simde consumers - winding_number.cmake + winding-number-winarm.patch: fix VM_SSEFunc.h at source level — on MSVC ARM64, simde__m128 and simde__m128i are both __n128, making plain typedefs identical and breaking all overloaded functions (vm_shuffle, vm_extract, vm_v4sf/vm_v4si). Replace typedefs with distinct wrapper structs that carry implicit conversions, and guard the union-based MSVC cast functions with !defined(_M_ARM64) Co-Authored-By: Claude Opus 4.7 --- CMakeLists.txt | 4 +- cmake/recipes/external/embree-winarm.patch | 8 ++-- cmake/recipes/external/embree.cmake | 36 ++++------------ cmake/recipes/external/simde.cmake | 8 ---- .../external/winding-number-winarm.patch | 42 +++++++++++++++++++ cmake/recipes/external/winding_number.cmake | 10 +++++ modules/CMakeLists.txt | 10 +---- 7 files changed, 66 insertions(+), 52 deletions(-) create mode 100644 cmake/recipes/external/winding-number-winarm.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 81361c2b..c34b82cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,8 +269,8 @@ if(BUILD_SHARED_LIBS) ) endif() -# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set (unless explicitly disabled via -D) -if(LAGRANGE_ALL AND NOT (DEFINED CACHE{LAGRANGE_MODULE_PYTHON} AND NOT LAGRANGE_MODULE_PYTHON)) +# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set +if(LAGRANGE_ALL) set(LAGRANGE_MODULE_PYTHON ON) endif() diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch index cba735a0..5357af1a 100644 --- a/cmake/recipes/external/embree-winarm.patch +++ b/cmake/recipes/external/embree-winarm.patch @@ -1,17 +1,17 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h --- i/common/sys/intrinsics.h +++ w/common/sys/intrinsics.h -@@ -91,6 +91,6 @@ +@@ -92,6 +92,6 @@ #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) __forceinline size_t bsf(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return _tzcnt_u64(v); #else unsigned long r = 0; _BitScanForward64(&r,v); return r; -@@ -141,5 +141,5 @@ +@@ -142,5 +142,5 @@ __forceinline size_t bsr(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return 63 -_lzcnt_u64(v); #else diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 16a587ba..129c9b90 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -127,6 +127,13 @@ function(embree_import_target) message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) + # The dousse-adobe fork guards x86 BMI/LZCNT/PEXT intrinsics with !defined(__aarch64__) + # (GCC/Clang macro) but misses _M_ARM64 (MSVC macro), causing build failures on Windows + # ARM64. We use git apply --ignore-whitespace instead of CPM's PATCHES (patch -p1) because + # git-cloned files may have CRLF line endings on Windows, which confuses patch.exe. + find_package(Git REQUIRED QUIET) + set(EMBREE_ARM64_PATCH "${CMAKE_CURRENT_LIST_DIR}/embree-winarm.patch") + set(EMBREE_PATCHES PATCH_COMMAND "${GIT_EXECUTABLE}" apply --ignore-whitespace "${EMBREE_ARM64_PATCH}") endif() CPMAddPackage( NAME embree @@ -135,35 +142,6 @@ function(embree_import_target) ${EMBREE_PATCHES} ) - # Fix intrinsics.h for MSVC ARM64: the dousse-adobe fork defines __AVX2__ on ARM64 to trigger - # SIMDe, but uses !defined(__aarch64__) (GCC/Clang) instead of !defined(_M_ARM64) (MSVC) to - # guard x86 BMI/LZCNT/PEXT intrinsics, causing build failures. We apply this fix via CMake - # string replacement rather than a patch file to avoid dependency on Strawberry's patch.exe, - # which is strict about unified-diff line counts and offsets. - if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND DEFINED embree_SOURCE_DIR) - set(_intrinsics "${embree_SOURCE_DIR}/common/sys/intrinsics.h") - if(EXISTS "${_intrinsics}") - file(READ "${_intrinsics}" _content) - string(ASCII 13 _cr) - string(ASCII 10 _lf) - # Two bsf/bsr instances end with a trailing space before the newline. - string(REGEX REPLACE - "#if defined\\(__AVX2__\\) ([${_cr}${_lf}])" - "#if defined(__AVX2__) && !defined(_M_ARM64)\\1" - _content "${_content}") - # pext/pdep instance uses the __aarch64__ guard without the trailing space. - string(REPLACE - "#if defined(__AVX2__) && !defined(__aarch64__)" - "#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64)" - _content "${_content}") - file(WRITE "${_intrinsics}" "${_content}") - unset(_content) - endif() - unset(_intrinsics) - unset(_cr) - unset(_lf) - endif() - unignore_package(TBB) # Disable warnings diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index a989990b..9a5f6cae 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -24,11 +24,3 @@ CPMAddPackage( # Enables native aliases. Not ideal but makes it easier to convert old code. target_compile_definitions(simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) - -# On MSVC ARM64, all NEON vector types (float32x4_t, int64x2_t, ...) are typedefs of the same -# __n128 type, so simde__m128 and simde__m128i would be identical to the type system. This breaks -# code that overloads on __m128 vs __m128i (e.g. WindingNumber's VM_SSEFunc.h). Disabling native -# NEON forces SIMDe to use its own distinct union types instead. -if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") - target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) -endif() diff --git a/cmake/recipes/external/winding-number-winarm.patch b/cmake/recipes/external/winding-number-winarm.patch new file mode 100644 index 00000000..50099b2d --- /dev/null +++ b/cmake/recipes/external/winding-number-winarm.patch @@ -0,0 +1,42 @@ +diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h +--- i/VM_SSEFunc.h ++++ w/VM_SSEFunc.h +@@ -39,8 +39,26 @@ + #include + #include + +-typedef simde__m128 v4sf; +-typedef simde__m128i v4si; ++#if defined(_MSC_VER) && defined(_M_ARM64) ++// On MSVC ARM64, simde__m128 and simde__m128i are both __n128 (the native NEON type). ++// Plain typedefs make v4sf==v4si, breaking all overloaded functions (vm_shuffle, vm_extract, ++// etc.). Use distinct wrapper structs with implicit conversions to/from the simde types. ++struct v4sf { ++ simde__m128 _v; ++ v4sf() = default; ++ SYS_FORCE_INLINE v4sf(simde__m128 v) noexcept : _v(v) {} ++ SYS_FORCE_INLINE operator simde__m128() const noexcept { return _v; } ++}; ++struct v4si { ++ simde__m128i _v; ++ v4si() = default; ++ SYS_FORCE_INLINE v4si(simde__m128i v) noexcept : _v(v) {} ++ SYS_FORCE_INLINE operator simde__m128i() const noexcept { return _v; } ++}; ++#else ++typedef simde__m128 v4sf; ++typedef simde__m128i v4si; ++#endif + + #define CPU_HAS_SIMD_INSTR 1 + #define VM_SSE_STYLE 1 +@@ -59,7 +77,7 @@ + // Plain casting (no conversion) + // MSVC has problems casting between __m128 and __m128i, so we implement a + // custom casting routine specifically for windows. + +-#if defined(_MSC_VER) ++#if defined(_MSC_VER) && !defined(_M_ARM64) + + static SYS_FORCE_INLINE v4sf + vm_v4sf(const v4si &a) diff --git a/cmake/recipes/external/winding_number.cmake b/cmake/recipes/external/winding_number.cmake index 970709f4..7e703d4c 100644 --- a/cmake/recipes/external/winding_number.cmake +++ b/cmake/recipes/external/winding_number.cmake @@ -19,10 +19,20 @@ lagrange_find_package(TBB CONFIG REQUIRED) include(simde) include(CPM) +set(WINDINGNUMBER_PATCHES "") +if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + # On MSVC ARM64, simde__m128 and simde__m128i are both __n128, making plain typedefs + # identical and breaking all overloaded functions. Patch VM_SSEFunc.h to use distinct + # wrapper structs instead. Use git apply --ignore-whitespace for robust CRLF handling. + find_package(Git REQUIRED QUIET) + set(_wn_patch "${CMAKE_CURRENT_LIST_DIR}/winding-number-winarm.patch") + set(WINDINGNUMBER_PATCHES PATCH_COMMAND "${GIT_EXECUTABLE}" apply --ignore-whitespace "${_wn_patch}") +endif() CPMAddPackage( NAME WindingNumber GITHUB_REPOSITORY jdumas/WindingNumber GIT_TAG a48b8f555b490afe7aab9159c7daaf83fa2cdf8e + ${WINDINGNUMBER_PATCHES} ) set_target_properties(WindingNumber PROPERTIES FOLDER third_party) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 56c1ae65..6aeda78e 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -48,14 +48,6 @@ foreach(name IN ITEMS ${module_names}) string(TOUPPER ${name} MODULE_FLAG) set(MODULE_OPTION LAGRANGE_MODULE_${MODULE_FLAG}) - # Capture whether the user explicitly disabled this module before option() materializes - # the cache variable (the default-OFF cache value would otherwise be indistinguishable - # from an explicit -DLAGRANGE_MODULE_X=OFF on the command line). - set(_user_disabled_module FALSE) - if(DEFINED CACHE{${MODULE_OPTION}} AND NOT ${${MODULE_OPTION}}) - set(_user_disabled_module TRUE) - endif() - # Allows setting the option option(${MODULE_OPTION} "Build module lagrange::${name}" OFF) @@ -69,7 +61,7 @@ foreach(name IN ITEMS ${module_names}) "Please use the helper function lagrange_include_modules() instead.") endif() - if(${MODULE_OPTION} OR (LAGRANGE_ALL AND NOT _user_disabled_module)) + if(${MODULE_OPTION} OR LAGRANGE_ALL) lagrange_include_modules(${name}) endif() endforeach() From 286cc6619852a6725d0d3acc9712bcee6f799a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 19:28:28 -0700 Subject: [PATCH 57/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20embree-winarm.patch?= =?UTF-8?q?=20minus=20lines=20to=20match=20trailing=20spaces=20in=20dousse?= =?UTF-8?q?-adobe=20fork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dousse-adobe fork's intrinsics.h has trailing spaces on the AVX2 preprocessor guards at lines 94 and 143. The patch's minus lines must match exactly (git apply --ignore-whitespace only ignores trailing whitespace in context lines, not in minus lines). Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree-winarm.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch index 5357af1a..9102a25b 100644 --- a/cmake/recipes/external/embree-winarm.patch +++ b/cmake/recipes/external/embree-winarm.patch @@ -4,14 +4,14 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h @@ -92,6 +92,6 @@ #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) __forceinline size_t bsf(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return _tzcnt_u64(v); #else unsigned long r = 0; _BitScanForward64(&r,v); return r; @@ -142,5 +142,5 @@ __forceinline size_t bsr(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return 63 -_lzcnt_u64(v); #else From b3ff8471361ffe0f6db5a48807f11e3fc144661e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 06:59:16 -0700 Subject: [PATCH 58/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20winding-number-winar?= =?UTF-8?q?m.patch:=20use=20space=20for=20empty=20context=20lines,=20fix?= =?UTF-8?q?=20hunk=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/winding-number-winarm.patch | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmake/recipes/external/winding-number-winarm.patch b/cmake/recipes/external/winding-number-winarm.patch index 50099b2d..a765d38a 100644 --- a/cmake/recipes/external/winding-number-winarm.patch +++ b/cmake/recipes/external/winding-number-winarm.patch @@ -4,7 +4,7 @@ diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h @@ -39,8 +39,26 @@ #include #include - + -typedef simde__m128 v4sf; -typedef simde__m128i v4si; +#if defined(_MSC_VER) && defined(_M_ARM64) @@ -27,16 +27,15 @@ diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h +typedef simde__m128 v4sf; +typedef simde__m128i v4si; +#endif - + #define CPU_HAS_SIMD_INSTR 1 #define VM_SSE_STYLE 1 @@ -59,7 +77,7 @@ - // Plain casting (no conversion) // MSVC has problems casting between __m128 and __m128i, so we implement a // custom casting routine specifically for windows. - + -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(_M_ARM64) - + static SYS_FORCE_INLINE v4sf vm_v4sf(const v4si &a) From f5b8d57e3c4892c4923d52f09cd304d499b0c0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 07:37:04 -0700 Subject: [PATCH 59/79] =?UTF-8?q?=F0=9F=90=9B=20Fix=20vm=5Fshuffle=20ambig?= =?UTF-8?q?uity:=20add=20explicit=20V4SF()=20casts=20at=20ambiguous=20call?= =?UTF-8?q?=20sites?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/winding-number-winarm.patch | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmake/recipes/external/winding-number-winarm.patch b/cmake/recipes/external/winding-number-winarm.patch index a765d38a..23d22d36 100644 --- a/cmake/recipes/external/winding-number-winarm.patch +++ b/cmake/recipes/external/winding-number-winarm.patch @@ -39,3 +39,12 @@ diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h static SYS_FORCE_INLINE v4sf vm_v4sf(const v4si &a) +@@ -249,6 +267,6 @@ + vm_splats(float a, float b, float c, float d) + { + return vm_shuffle<0,2,0,2>( +- vm_shuffle<0>(simde_mm_set_ss(a), simde_mm_set_ss(b)), +- vm_shuffle<0>(simde_mm_set_ss(c), simde_mm_set_ss(d))); ++ vm_shuffle<0>(V4SF(simde_mm_set_ss(a)), V4SF(simde_mm_set_ss(b))), ++ vm_shuffle<0>(V4SF(simde_mm_set_ss(c)), V4SF(simde_mm_set_ss(d)))); + } From 694fa212f980ec179d204dfbfb02c54f80701987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 12:46:33 -0700 Subject: [PATCH 60/79] =?UTF-8?q?=F0=9F=94=8D=20[TEMP]=20Diagnose=20Eigen?= =?UTF-8?q?=20alignment=20assert=20on=20Windows=20ARM64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Force-include a non-fatal eigen_assert override that logs each alignment failure to stderr (first 30 hits) instead of aborting/popping a CRT dialog. Disable Unix and non-ARM64 Windows jobs to iterate fast on the only failing config. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 6 ++- cmake/recipes/external/Eigen3.cmake | 9 +++++ cmake/recipes/external/eigen_alignment_diag.h | 39 +++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 cmake/recipes/external/eigen_alignment_diag.h diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 504829ae..8dea8875 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -21,6 +21,7 @@ jobs: Unix: name: ${{ matrix.os }} (${{ matrix.compiler }}, ${{ matrix.config }}, ${{ matrix.sanitizer }}Sanitizer) runs-on: ${{ matrix.os }} + if: false # TEMPORARY: disabled while iterating on Windows ARM64 Eigen alignment diagnostics strategy: fail-fast: false matrix: @@ -202,8 +203,9 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-2025, windows-11-arm] - config: [Release, Debug] + # TEMPORARY: only windows-11-arm Debug while iterating on Eigen alignment diagnostics + os: [windows-11-arm] + config: [Debug] steps: - name: Show disk space run: Get-PSDrive diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index 726e6053..c1aa125b 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -46,6 +46,15 @@ if(EIGEN_DONT_VECTORIZE) target_compile_definitions(Eigen3_Eigen INTERFACE EIGEN_DONT_VECTORIZE) endif() +# Diagnostic only — TEMPORARY: force-include a header that replaces eigen_assert with a +# non-fatal logger so we can capture every Eigen alignment failure on Windows ARM64 Debug +# (the runtime dialog otherwise hangs CI). Remove once the underlying issue is fixed. +if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC) + set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") + target_compile_options(Eigen3_Eigen INTERFACE "/FI${_lagrange_eigen_diag_header}") + target_compile_definitions(Eigen3_Eigen INTERFACE LAGRANGE_DIAG_EIGEN_ALIGN=1) +endif() + if(EIGEN_WITH_MKL) # TODO: Checks that, on 64bits systems, `MKL::MKL` is using the LP64 interface # (by looking at the compile definition of the target) diff --git a/cmake/recipes/external/eigen_alignment_diag.h b/cmake/recipes/external/eigen_alignment_diag.h new file mode 100644 index 00000000..83362957 --- /dev/null +++ b/cmake/recipes/external/eigen_alignment_diag.h @@ -0,0 +1,39 @@ +// Diagnostic eigen_assert override for Windows ARM64 investigation. +// Prints the address, alignment, and call site, then continues so we can see +// every misaligned construction without aborting the process. +#pragma once + +#ifdef LAGRANGE_DIAG_EIGEN_ALIGN + +#include +#include +#include +#include + +namespace lagrange_diag { +inline std::atomic& eigen_diag_count() +{ + static std::atomic n{0}; + return n; +} + +inline void log_eigen_assert(const char* expr, const char* file, int line) +{ + int n = eigen_diag_count().fetch_add(1); + if (n < 30) { + std::fprintf(stderr, "[EIGEN_DIAG #%d] %s:%d %s\n", n, file, line, expr); + std::fflush(stderr); + } +} +} // namespace lagrange_diag + +// Replace eigen_assert with a non-fatal diagnostic version. We must define this BEFORE +// any Eigen header is included; this file is force-included via /FI on MSVC and -include on GCC/Clang. +#define eigen_assert(x) \ + do { \ + if (!(x)) { \ + ::lagrange_diag::log_eigen_assert(#x, __FILE__, __LINE__); \ + } \ + } while (0) + +#endif // LAGRANGE_DIAG_EIGEN_ALIGN From a6b32dbdcc876f37af1e588dc40563a87ab27951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:12:28 -0700 Subject: [PATCH 61/79] =?UTF-8?q?=F0=9F=94=8D=20Diagnose=20Eigen=20alignme?= =?UTF-8?q?nt=20assert=20with=20cpptrace=20on=20Win=20ARM64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the temporary EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT workaround with a non-fatal eigen_assert override that uses cpptrace::generate_trace() to print a full stack trace whenever the failing assertion originates from DenseStorage.h (the plain_array<> alignment check). All other eigen_assert failures still abort to keep unrelated invariants surfaced. Trim CI to the smallest possible reproducer: - Disable Unix matrix. - Windows matrix reduced to windows-11-arm Debug only. - Configure only LAGRANGE_MODULE_SERIALIZATION2 (no LAGRANGE_ALL, no Python). - Scope ctest to -R 'serialization2|serialize_'. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 21 +++--- cmake/recipes/external/Eigen3.cmake | 24 +++++-- .../recipes/external/eigen_alignment_diag.cpp | 68 +++++++++++++++++++ cmake/recipes/external/eigen_alignment_diag.h | 44 ++++-------- 4 files changed, 115 insertions(+), 42 deletions(-) create mode 100644 cmake/recipes/external/eigen_alignment_diag.cpp diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 8dea8875..f532ae2c 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -19,9 +19,9 @@ jobs: #################### Unix: + if: false # DIAGNOSTIC: temporarily disabled to iterate fast on Windows ARM64 Debug Eigen alignment investigation name: ${{ matrix.os }} (${{ matrix.compiler }}, ${{ matrix.config }}, ${{ matrix.sanitizer }}Sanitizer) runs-on: ${{ matrix.os }} - if: false # TEMPORARY: disabled while iterating on Windows ARM64 Eigen alignment diagnostics strategy: fail-fast: false matrix: @@ -203,7 +203,8 @@ jobs: strategy: fail-fast: false matrix: - # TEMPORARY: only windows-11-arm Debug while iterating on Eigen alignment diagnostics + # DIAGNOSTIC: only the failing config (Win ARM64 Debug) while we hunt the + # Eigen alignment issue in serialization2. os: [windows-11-arm] config: [Debug] steps: @@ -284,8 +285,9 @@ jobs: -B ${{ env.BUILD_DIR }} ` -S . - # Force CMake to use the ARM64 Python (now complete with dev files) - # and skip the Windows registry so it doesn't fall back to x64 Python. + # DIAGNOSTIC: minimal configure for Win ARM64 — enable only the failing module + # (serialization2) so we get a fast iteration loop while we capture cpptrace + # stack traces for the Eigen alignment assertion. LAGRANGE_ALL=OFF, no Python. - name: Configure (ARM64) if: matrix.os == 'windows-11-arm' run: | @@ -293,10 +295,9 @@ jobs: cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_ALL=ON ` - -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` - -DPython_EXECUTABLE="$env:PYTHON_ARM64_EXE" ` - -DPython_FIND_REGISTRY=NEVER ` + -DLAGRANGE_ALL=OFF ` + -DLAGRANGE_MODULE_SERIALIZATION2=ON ` + -DLAGRANGE_MODULE_PYTHON=OFF ` -B ${{ env.BUILD_DIR }} ` -S . @@ -313,4 +314,6 @@ jobs: run: Get-PSDrive - name: Tests - run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + # DIAGNOSTIC: scope ctest to the serialization2 suite (the only one firing the assert). + # --verbose is critical: cpptrace writes to stderr and we need it captured in the log. + run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} -R "serialization2|serialize_" diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index c1aa125b..398686dd 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -46,13 +46,29 @@ if(EIGEN_DONT_VECTORIZE) target_compile_definitions(Eigen3_Eigen INTERFACE EIGEN_DONT_VECTORIZE) endif() -# Diagnostic only — TEMPORARY: force-include a header that replaces eigen_assert with a -# non-fatal logger so we can capture every Eigen alignment failure on Windows ARM64 Debug -# (the runtime dialog otherwise hangs CI). Remove once the underlying issue is fixed. -if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC) +# Diagnostic only — TEMPORARY: on Windows ARM64 Debug, force-include a header that overrides +# eigen_assert with a non-fatal handler. When the assertion comes from DenseStorage.h (i.e. the +# plain_array<> alignment check) we capture a cpptrace stack trace so we can pinpoint the call +# site that constructs a misaligned fixed-size Eigen object. All other eigen_assert failures +# still abort, so unrelated invariants are not masked. +# +# The cpptrace dependency stays in a separate static library (lagrange_eigen_align_diag) so it +# does not leak into every Eigen consumer's interface. +if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") + include(cpptrace) + add_library(lagrange_eigen_align_diag STATIC + ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.cpp + ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h + ) + target_include_directories(lagrange_eigen_align_diag PUBLIC ${CMAKE_CURRENT_LIST_DIR}) + target_compile_definitions(lagrange_eigen_align_diag PUBLIC LAGRANGE_DIAG_EIGEN_ALIGN=1) + target_link_libraries(lagrange_eigen_align_diag PRIVATE cpptrace::cpptrace) + set_target_properties(lagrange_eigen_align_diag PROPERTIES FOLDER third_party) + set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") target_compile_options(Eigen3_Eigen INTERFACE "/FI${_lagrange_eigen_diag_header}") target_compile_definitions(Eigen3_Eigen INTERFACE LAGRANGE_DIAG_EIGEN_ALIGN=1) + target_link_libraries(Eigen3_Eigen INTERFACE lagrange_eigen_align_diag) endif() if(EIGEN_WITH_MKL) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp new file mode 100644 index 00000000..a70944eb --- /dev/null +++ b/cmake/recipes/external/eigen_alignment_diag.cpp @@ -0,0 +1,68 @@ +// See eigen_alignment_diag.h. Defined in a separate translation unit so the +// cpptrace dependency stays private to this static library and does not leak +// into every consumer of Eigen3::Eigen. +#include "eigen_alignment_diag.h" + +#ifdef LAGRANGE_DIAG_EIGEN_ALIGN + +#include + +#include +#include +#include +#include +#include + +namespace lagrange_diag { + +namespace { +std::atomic& trace_count() +{ + static std::atomic n{0}; + return n; +} + +std::mutex& trace_mutex() +{ + static std::mutex m; + return m; +} + +bool is_alignment_assert(const char* file) +{ + if (!file) return false; + return std::strstr(file, "DenseStorage") != nullptr; +} +} // namespace + +void eigen_assert_handler(const char* expr, const char* file, int line) +{ + if (is_alignment_assert(file)) { + // Alignment assertion: log + capture trace, but DO NOT abort. ARM64 NEON + // tolerates unaligned access; we only need to find where the misaligned + // plain_array<> is being constructed. + int n = trace_count().fetch_add(1); + if (n < 30) { + std::lock_guard lock(trace_mutex()); + std::fprintf( + stderr, + "\n[EIGEN_DIAG #%d] %s:%d %s\n", + n, + file, + line, + expr ? expr : "(null)"); + cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64).print(std::cerr); + std::fflush(stderr); + } + return; + } + // Any other Eigen invariant violation: preserve original assert() behavior + // so unrelated bugs still surface (and tests fail) rather than being masked. + std::fprintf(stderr, "Eigen assertion failed: %s at %s:%d\n", expr, file, line); + std::fflush(stderr); + std::abort(); +} + +} // namespace lagrange_diag + +#endif // LAGRANGE_DIAG_EIGEN_ALIGN diff --git a/cmake/recipes/external/eigen_alignment_diag.h b/cmake/recipes/external/eigen_alignment_diag.h index 83362957..f14bb931 100644 --- a/cmake/recipes/external/eigen_alignment_diag.h +++ b/cmake/recipes/external/eigen_alignment_diag.h @@ -1,39 +1,25 @@ -// Diagnostic eigen_assert override for Windows ARM64 investigation. -// Prints the address, alignment, and call site, then continues so we can see -// every misaligned construction without aborting the process. +// Diagnostic Eigen assertion override for Windows ARM64 Debug investigation. +// Replaces eigen_assert with a non-fatal handler that captures a stack trace +// via cpptrace whenever the failing call originates from DenseStorage.h (i.e. +// the alignment check on plain_array<>). The actual cpptrace call lives in +// eigen_alignment_diag.cpp so this header has no dependency on cpptrace. +// +// Force-included via /FI on MSVC (see cmake/recipes/external/Eigen3.cmake). +// Pre-defining eigen_assert here works because Eigen/src/Core/util/Macros.h +// guards its own definition with #ifndef eigen_assert. #pragma once #ifdef LAGRANGE_DIAG_EIGEN_ALIGN -#include -#include -#include -#include - namespace lagrange_diag { -inline std::atomic& eigen_diag_count() -{ - static std::atomic n{0}; - return n; -} - -inline void log_eigen_assert(const char* expr, const char* file, int line) -{ - int n = eigen_diag_count().fetch_add(1); - if (n < 30) { - std::fprintf(stderr, "[EIGEN_DIAG #%d] %s:%d %s\n", n, file, line, expr); - std::fflush(stderr); - } -} +void eigen_assert_handler(const char* expr, const char* file, int line); } // namespace lagrange_diag -// Replace eigen_assert with a non-fatal diagnostic version. We must define this BEFORE -// any Eigen header is included; this file is force-included via /FI on MSVC and -include on GCC/Clang. -#define eigen_assert(x) \ - do { \ - if (!(x)) { \ - ::lagrange_diag::log_eigen_assert(#x, __FILE__, __LINE__); \ - } \ +#define eigen_assert(x) \ + do { \ + if (!(x)) { \ + ::lagrange_diag::eigen_assert_handler(#x, __FILE__, __LINE__); \ + } \ } while (0) #endif // LAGRANGE_DIAG_EIGEN_ALIGN From 00661ba8b1f5e0266118a59d7883ed4f7b4f7308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:17:47 -0700 Subject: [PATCH 62/79] =?UTF-8?q?=F0=9F=94=A7=20Diag:=20scope=20Eigen3=20l?= =?UTF-8?q?ink=20to=20lagrange=5Feigen=5Falign=5Fdiag=20with=20BUILD=5FINT?= =?UTF-8?q?ERFACE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit install(EXPORT Eigen_Targets ...) was failing because Eigen3_Eigen INTERFACE linked a target outside the export set. Wrap the diagnostic compile options, defines, and link with $ so they only apply during the local build and are stripped from the install/export. Co-Authored-By: Claude Opus 4.7 --- cmake/recipes/external/Eigen3.cmake | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index 398686dd..d328b5d6 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -66,9 +66,14 @@ if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC AND CMAKE_BUILD_TY set_target_properties(lagrange_eigen_align_diag PROPERTIES FOLDER third_party) set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") - target_compile_options(Eigen3_Eigen INTERFACE "/FI${_lagrange_eigen_diag_header}") - target_compile_definitions(Eigen3_Eigen INTERFACE LAGRANGE_DIAG_EIGEN_ALIGN=1) - target_link_libraries(Eigen3_Eigen INTERFACE lagrange_eigen_align_diag) + # Wrap with $ so install(EXPORT Eigen_Targets) does not see the + # diagnostic target (which is intentionally not part of the export set). + target_compile_options(Eigen3_Eigen INTERFACE + "$") + target_compile_definitions(Eigen3_Eigen INTERFACE + $) + target_link_libraries(Eigen3_Eigen INTERFACE + $) endif() if(EIGEN_WITH_MKL) From ff4ad3b266f3467d5ea48581d7bbf47c0a8e837f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:29:14 -0700 Subject: [PATCH 63/79] =?UTF-8?q?=F0=9F=94=A7=20Diag:=20add=20missing=20=20for=20std::cerr=20in=20eigen=5Falignment=5Fdiag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- cmake/recipes/external/eigen_alignment_diag.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp index a70944eb..26f1ac1c 100644 --- a/cmake/recipes/external/eigen_alignment_diag.cpp +++ b/cmake/recipes/external/eigen_alignment_diag.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace lagrange_diag { From 5028be8ad3cd126a0ed23e16c44469dc027ebf48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:58:19 -0700 Subject: [PATCH 64/79] =?UTF-8?q?=F0=9F=94=8D=20Diag:=20route=20cpptrace?= =?UTF-8?q?=20through=20fprintf=20with=20frame=20count=20+=20exception=20g?= =?UTF-8?q?uard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last run produced [EIGEN_DIAG #N] header lines but no cpptrace frames followed. Switch to to_string(false) + fprintf(stderr) so output uses the same C stream as the header, log frame count, and catch exceptions in case symbol resolution or unwinding fails on Win ARM64. Co-Authored-By: Claude Opus 4.7 --- cmake/recipes/external/eigen_alignment_diag.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp index 26f1ac1c..7a64c885 100644 --- a/cmake/recipes/external/eigen_alignment_diag.cpp +++ b/cmake/recipes/external/eigen_alignment_diag.cpp @@ -11,8 +11,9 @@ #include #include #include -#include +#include #include +#include namespace lagrange_diag { @@ -52,7 +53,17 @@ void eigen_assert_handler(const char* expr, const char* file, int line) file, line, expr ? expr : "(null)"); - cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64).print(std::cerr); + std::fflush(stderr); + try { + auto trace = cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64); + std::string s = trace.to_string(/*color*/ false); + std::fprintf(stderr, "%s\n", s.c_str()); + std::fprintf(stderr, "[EIGEN_DIAG #%d] frames=%zu\n", n, trace.frames.size()); + } catch (const std::exception& e) { + std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace exception: %s\n", n, e.what()); + } catch (...) { + std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace unknown exception\n", n); + } std::fflush(stderr); } return; From e7717453c548ef487ca73bd7727122de4ecc7a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Sun, 17 May 2026 16:42:26 -0700 Subject: [PATCH 65/79] =?UTF-8?q?=F0=9F=90=9B=20Pass-by-const-ref=20Eigen?= =?UTF-8?q?=20fixed-size=20parameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MSVC ARM64 Debug does not guarantee 16-byte alignment for parameter slots on the stack. Passing fixed-size vectorizable Eigen objects (alignof >= 16: Vector2d, Vector4f, Matrix4f, Matrix, etc.) by value triggers the plain_array<> alignment assertion at the call site, before the function body even runs. Switch the following public APIs to const-ref parameters, which sidesteps the issue and matches the rest of the codebase: - internal::point_on_segment_2d / 3d - mesh_cleanup unflip_uv_triangles 'update_uv' lambda - ui::ShaderValue::operator= overloads (Vec/Mat/Affine/Projective) - ui::Camera::set_ortho_viewport / rotate_turntable / get_frustum - ui::AABB::intersects_ray - ui::utils::render::compute_perpendicular_plane - python transform_mesh binding lambda Also drop the temporary Win ARM64 Debug eigen_assert override diagnostic introduced to chase this bug (Eigen3.cmake block plus eigen_alignment_diag.{h,cpp}). --- cmake/recipes/external/Eigen3.cmake | 30 ------- .../recipes/external/eigen_alignment_diag.cpp | 80 ------------------- cmake/recipes/external/eigen_alignment_diag.h | 25 ------ .../include/lagrange/utils/point_on_segment.h | 10 ++- modules/core/python/src/bind_utilities.h | 2 +- .../src/mesh_cleanup/unflip_uv_triangles.cpp | 2 +- modules/core/src/utils/point_on_segment.cpp | 23 ++++-- modules/primitive/src/primitive_utils.h | 4 +- modules/ui/include/lagrange/ui/types/AABB.h | 4 +- modules/ui/include/lagrange/ui/types/Camera.h | 6 +- modules/ui/include/lagrange/ui/types/Shader.h | 18 ++--- modules/ui/include/lagrange/ui/utils/render.h | 2 +- modules/ui/src/types/AABB.cpp | 4 +- modules/ui/src/types/Camera.cpp | 9 ++- modules/ui/src/types/Shader.cpp | 16 ++-- modules/ui/src/utils/render.cpp | 5 +- 16 files changed, 61 insertions(+), 179 deletions(-) delete mode 100644 cmake/recipes/external/eigen_alignment_diag.cpp delete mode 100644 cmake/recipes/external/eigen_alignment_diag.h diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index d328b5d6..726e6053 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -46,36 +46,6 @@ if(EIGEN_DONT_VECTORIZE) target_compile_definitions(Eigen3_Eigen INTERFACE EIGEN_DONT_VECTORIZE) endif() -# Diagnostic only — TEMPORARY: on Windows ARM64 Debug, force-include a header that overrides -# eigen_assert with a non-fatal handler. When the assertion comes from DenseStorage.h (i.e. the -# plain_array<> alignment check) we capture a cpptrace stack trace so we can pinpoint the call -# site that constructs a misaligned fixed-size Eigen object. All other eigen_assert failures -# still abort, so unrelated invariants are not masked. -# -# The cpptrace dependency stays in a separate static library (lagrange_eigen_align_diag) so it -# does not leak into every Eigen consumer's interface. -if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") - include(cpptrace) - add_library(lagrange_eigen_align_diag STATIC - ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.cpp - ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h - ) - target_include_directories(lagrange_eigen_align_diag PUBLIC ${CMAKE_CURRENT_LIST_DIR}) - target_compile_definitions(lagrange_eigen_align_diag PUBLIC LAGRANGE_DIAG_EIGEN_ALIGN=1) - target_link_libraries(lagrange_eigen_align_diag PRIVATE cpptrace::cpptrace) - set_target_properties(lagrange_eigen_align_diag PROPERTIES FOLDER third_party) - - set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") - # Wrap with $ so install(EXPORT Eigen_Targets) does not see the - # diagnostic target (which is intentionally not part of the export set). - target_compile_options(Eigen3_Eigen INTERFACE - "$") - target_compile_definitions(Eigen3_Eigen INTERFACE - $) - target_link_libraries(Eigen3_Eigen INTERFACE - $) -endif() - if(EIGEN_WITH_MKL) # TODO: Checks that, on 64bits systems, `MKL::MKL` is using the LP64 interface # (by looking at the compile definition of the target) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp deleted file mode 100644 index 7a64c885..00000000 --- a/cmake/recipes/external/eigen_alignment_diag.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// See eigen_alignment_diag.h. Defined in a separate translation unit so the -// cpptrace dependency stays private to this static library and does not leak -// into every consumer of Eigen3::Eigen. -#include "eigen_alignment_diag.h" - -#ifdef LAGRANGE_DIAG_EIGEN_ALIGN - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace lagrange_diag { - -namespace { -std::atomic& trace_count() -{ - static std::atomic n{0}; - return n; -} - -std::mutex& trace_mutex() -{ - static std::mutex m; - return m; -} - -bool is_alignment_assert(const char* file) -{ - if (!file) return false; - return std::strstr(file, "DenseStorage") != nullptr; -} -} // namespace - -void eigen_assert_handler(const char* expr, const char* file, int line) -{ - if (is_alignment_assert(file)) { - // Alignment assertion: log + capture trace, but DO NOT abort. ARM64 NEON - // tolerates unaligned access; we only need to find where the misaligned - // plain_array<> is being constructed. - int n = trace_count().fetch_add(1); - if (n < 30) { - std::lock_guard lock(trace_mutex()); - std::fprintf( - stderr, - "\n[EIGEN_DIAG #%d] %s:%d %s\n", - n, - file, - line, - expr ? expr : "(null)"); - std::fflush(stderr); - try { - auto trace = cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64); - std::string s = trace.to_string(/*color*/ false); - std::fprintf(stderr, "%s\n", s.c_str()); - std::fprintf(stderr, "[EIGEN_DIAG #%d] frames=%zu\n", n, trace.frames.size()); - } catch (const std::exception& e) { - std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace exception: %s\n", n, e.what()); - } catch (...) { - std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace unknown exception\n", n); - } - std::fflush(stderr); - } - return; - } - // Any other Eigen invariant violation: preserve original assert() behavior - // so unrelated bugs still surface (and tests fail) rather than being masked. - std::fprintf(stderr, "Eigen assertion failed: %s at %s:%d\n", expr, file, line); - std::fflush(stderr); - std::abort(); -} - -} // namespace lagrange_diag - -#endif // LAGRANGE_DIAG_EIGEN_ALIGN diff --git a/cmake/recipes/external/eigen_alignment_diag.h b/cmake/recipes/external/eigen_alignment_diag.h deleted file mode 100644 index f14bb931..00000000 --- a/cmake/recipes/external/eigen_alignment_diag.h +++ /dev/null @@ -1,25 +0,0 @@ -// Diagnostic Eigen assertion override for Windows ARM64 Debug investigation. -// Replaces eigen_assert with a non-fatal handler that captures a stack trace -// via cpptrace whenever the failing call originates from DenseStorage.h (i.e. -// the alignment check on plain_array<>). The actual cpptrace call lives in -// eigen_alignment_diag.cpp so this header has no dependency on cpptrace. -// -// Force-included via /FI on MSVC (see cmake/recipes/external/Eigen3.cmake). -// Pre-defining eigen_assert here works because Eigen/src/Core/util/Macros.h -// guards its own definition with #ifndef eigen_assert. -#pragma once - -#ifdef LAGRANGE_DIAG_EIGEN_ALIGN - -namespace lagrange_diag { -void eigen_assert_handler(const char* expr, const char* file, int line); -} // namespace lagrange_diag - -#define eigen_assert(x) \ - do { \ - if (!(x)) { \ - ::lagrange_diag::eigen_assert_handler(#x, __FILE__, __LINE__); \ - } \ - } while (0) - -#endif // LAGRANGE_DIAG_EIGEN_ALIGN diff --git a/modules/core/include/lagrange/utils/point_on_segment.h b/modules/core/include/lagrange/utils/point_on_segment.h index ed768115..ae68e81d 100644 --- a/modules/core/include/lagrange/utils/point_on_segment.h +++ b/modules/core/include/lagrange/utils/point_on_segment.h @@ -19,10 +19,16 @@ namespace lagrange { namespace internal { /// @internal -bool LA_CORE_API point_on_segment_2d(Eigen::Vector2d p, Eigen::Vector2d a, Eigen::Vector2d b); +bool LA_CORE_API point_on_segment_2d( + const Eigen::Vector2d& p, + const Eigen::Vector2d& a, + const Eigen::Vector2d& b); /// @internal -bool LA_CORE_API point_on_segment_3d(Eigen::Vector3d p, Eigen::Vector3d a, Eigen::Vector3d b); +bool LA_CORE_API point_on_segment_3d( + const Eigen::Vector3d& p, + const Eigen::Vector3d& a, + const Eigen::Vector3d& b); } // namespace internal diff --git a/modules/core/python/src/bind_utilities.h b/modules/core/python/src/bind_utilities.h index 8a372d54..40bced17 100644 --- a/modules/core/python/src/bind_utilities.h +++ b/modules/core/python/src/bind_utilities.h @@ -1620,7 +1620,7 @@ oriented. m.def( "transform_mesh", [](MeshType& mesh, - Eigen::Matrix affine_transform, + const Eigen::Matrix& affine_transform, bool normalize_normals, bool normalize_tangents_bitangents, bool in_place) -> std::optional { diff --git a/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp b/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp index fe3cef9e..3b7969ef 100644 --- a/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp +++ b/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp @@ -59,7 +59,7 @@ void unflip_uv_triangles(SurfaceMesh& mesh, const UnflipUVOptions }; std::vector additional_uv_values; - auto update_uv = [&](Index fid, Index lv, Eigen::Matrix new_uv) { + auto update_uv = [&](Index fid, Index lv, const Eigen::Matrix& new_uv) { additional_uv_values.insert(additional_uv_values.end(), new_uv.data(), new_uv.data() + 2); Index old_id = uv_indices(fid, lv); uv_indices(fid, lv) = static_cast(uv_values_attr.get_num_elements()) + diff --git a/modules/core/src/utils/point_on_segment.cpp b/modules/core/src/utils/point_on_segment.cpp index 1cca2b4f..ad8bba26 100644 --- a/modules/core/src/utils/point_on_segment.cpp +++ b/modules/core/src/utils/point_on_segment.cpp @@ -17,24 +17,31 @@ namespace lagrange { namespace internal { -bool point_on_segment_2d(Eigen::Vector2d p, Eigen::Vector2d a, Eigen::Vector2d b) +bool point_on_segment_2d( + const Eigen::Vector2d& p, + const Eigen::Vector2d& a, + const Eigen::Vector2d& b) { ExactPredicatesShewchuk pred; auto res = pred.orient2D(p.data(), a.data(), b.data()); if (res != 0) { return false; } - if (a.x() > b.x()) { - std::swap(a.x(), b.x()); + double ax = a.x(), ay = a.y(); + double bx = b.x(), by = b.y(); + if (ax > bx) { + std::swap(ax, bx); } - if (a.y() > b.y()) { - std::swap(a.y(), b.y()); + if (ay > by) { + std::swap(ay, by); } - auto ret = (a.x() <= p.x() && p.x() <= b.x() && a.y() <= p.y() && p.y() <= b.y()); - return ret; + return (ax <= p.x() && p.x() <= bx && ay <= p.y() && p.y() <= by); } -bool point_on_segment_3d(Eigen::Vector3d p, Eigen::Vector3d a, Eigen::Vector3d b) +bool point_on_segment_3d( + const Eigen::Vector3d& p, + const Eigen::Vector3d& a, + const Eigen::Vector3d& b) { for (int d = 0; d < 3; ++d) { Eigen::Vector2d p2d(p(d), p((d + 1) % 3)); diff --git a/modules/primitive/src/primitive_utils.h b/modules/primitive/src/primitive_utils.h index d16a1e85..125d0fe1 100644 --- a/modules/primitive/src/primitive_utils.h +++ b/modules/primitive/src/primitive_utils.h @@ -92,8 +92,8 @@ void add_semantic_label( template void normalize_uv( SurfaceMesh& mesh, - Eigen::Matrix min_uv, - Eigen::Matrix max_uv) + const Eigen::Matrix& min_uv, + const Eigen::Matrix& max_uv) { auto uv_mesh = uv_mesh_ref(mesh); auto uvs = vertex_ref(uv_mesh); diff --git a/modules/ui/include/lagrange/ui/types/AABB.h b/modules/ui/include/lagrange/ui/types/AABB.h index a66f7132..6d2b2ec9 100644 --- a/modules/ui/include/lagrange/ui/types/AABB.h +++ b/modules/ui/include/lagrange/ui/types/AABB.h @@ -61,8 +61,8 @@ class LA_UI_API AABB : public Eigen::AlignedBox3f AABB transformed(const Eigen::Affine3f& transform) const; bool intersects_ray( - Eigen::Vector3f origin, - Eigen::Vector3f dir, + const Eigen::Vector3f& origin, + const Eigen::Vector3f& dir, float* tmin_out = nullptr, float* tmax_out = nullptr) const; diff --git a/modules/ui/include/lagrange/ui/types/Camera.h b/modules/ui/include/lagrange/ui/types/Camera.h index 3e518b38..e1e7a1a9 100644 --- a/modules/ui/include/lagrange/ui/types/Camera.h +++ b/modules/ui/include/lagrange/ui/types/Camera.h @@ -199,7 +199,7 @@ class LA_UI_API Camera void rotate_turntable( float yaw_delta, float pitch_delta, - Eigen::Vector3f primary_axis = Eigen::Vector3f::Zero()); + const Eigen::Vector3f& primary_axis = Eigen::Vector3f::Zero()); void rotate_arcball( @@ -227,7 +227,7 @@ class LA_UI_API Camera /// /// @param viewport Orthographic rectangle /// - void set_ortho_viewport(Eigen::Vector4f viewport); + void set_ortho_viewport(const Eigen::Vector4f& viewport); Eigen::Vector4f get_ortho_viewport() const; @@ -314,7 +314,7 @@ class LA_UI_API Camera /// /// @return Frustum planes of a region /// - Frustum get_frustum(Eigen::Vector2f min, Eigen::Vector2f max) const; + Frustum get_frustum(const Eigen::Vector2f& min, const Eigen::Vector2f& max) const; protected: void update_view(); diff --git a/modules/ui/include/lagrange/ui/types/Shader.h b/modules/ui/include/lagrange/ui/types/Shader.h index 9eab156d..f3c5628c 100644 --- a/modules/ui/include/lagrange/ui/types/Shader.h +++ b/modules/ui/include/lagrange/ui/types/Shader.h @@ -153,15 +153,15 @@ struct LA_UI_API ShaderValue int size; GLenum type; ShaderInterface shaderInterface; - const ShaderValue& operator=(Eigen::Vector2f val) const; - const ShaderValue& operator=(Eigen::Vector3f val) const; - const ShaderValue& operator=(Eigen::Vector4f val) const; - - const ShaderValue& operator=(Eigen::Matrix2f val) const; - const ShaderValue& operator=(Eigen::Matrix3f val) const; - const ShaderValue& operator=(Eigen::Matrix4f val) const; - const ShaderValue& operator=(Eigen::Affine3f val) const; - const ShaderValue& operator=(Eigen::Projective3f val) const; + const ShaderValue& operator=(const Eigen::Vector2f& val) const; + const ShaderValue& operator=(const Eigen::Vector3f& val) const; + const ShaderValue& operator=(const Eigen::Vector4f& val) const; + + const ShaderValue& operator=(const Eigen::Matrix2f& val) const; + const ShaderValue& operator=(const Eigen::Matrix3f& val) const; + const ShaderValue& operator=(const Eigen::Matrix4f& val) const; + const ShaderValue& operator=(const Eigen::Affine3f& val) const; + const ShaderValue& operator=(const Eigen::Projective3f& val) const; const ShaderValue& operator=(double val) const; diff --git a/modules/ui/include/lagrange/ui/utils/render.h b/modules/ui/include/lagrange/ui/utils/render.h index 426f72e9..4cd421dc 100644 --- a/modules/ui/include/lagrange/ui/utils/render.h +++ b/modules/ui/include/lagrange/ui/utils/render.h @@ -54,7 +54,7 @@ LA_UI_API void set_render_pass_defaults(GLScope& scope); /// /// Returns a pair of orthogonal directions, that together with direction form a orthogonal basis LA_UI_API std::pair compute_perpendicular_plane( - Eigen::Vector3f direction); + const Eigen::Vector3f& direction); } // namespace render diff --git a/modules/ui/src/types/AABB.cpp b/modules/ui/src/types/AABB.cpp index 158d657f..6093919d 100644 --- a/modules/ui/src/types/AABB.cpp +++ b/modules/ui/src/types/AABB.cpp @@ -43,8 +43,8 @@ Eigen::Affine3f AABB::get_normalization_transform(bool preserve_aspect) const } bool AABB::intersects_ray( - Eigen::Vector3f origin, - Eigen::Vector3f dir, + const Eigen::Vector3f& origin, + const Eigen::Vector3f& dir, float* tmin_out /* = nullptr*/, float* tmax_out /* = nullptr*/) const { diff --git a/modules/ui/src/types/Camera.cpp b/modules/ui/src/types/Camera.cpp index c8ce0f7a..4ce4c85a 100644 --- a/modules/ui/src/types/Camera.cpp +++ b/modules/ui/src/types/Camera.cpp @@ -311,7 +311,10 @@ void Camera::rotate_tumble(float yaw_delta, float pitch_delta) } -void Camera::rotate_turntable(float yaw_delta, float pitch_delta, Eigen::Vector3f primary_axis) +void Camera::rotate_turntable( + float yaw_delta, + float pitch_delta, + const Eigen::Vector3f& primary_axis) { if (primary_axis.x() != 0 || primary_axis.y() != 0 || primary_axis.z() != 0) { set_up(primary_axis); @@ -400,7 +403,7 @@ void Camera::move_up(float delta) update_view(); } -void Camera::set_ortho_viewport(Eigen::Vector4f viewport) +void Camera::set_ortho_viewport(const Eigen::Vector4f& viewport) { if (std::isnan(viewport.x()) || std::isnan(viewport.y()) || std::isnan(viewport.z()) || std::isnan(viewport.w())) @@ -514,7 +517,7 @@ Frustum Camera::get_frustum() const return get_frustum(Eigen::Vector2f(0), Eigen::Vector2f(get_window_size())); } -Frustum Camera::get_frustum(Eigen::Vector2f min, Eigen::Vector2f max) const +Frustum Camera::get_frustum(const Eigen::Vector2f& min, const Eigen::Vector2f& max) const { auto ray_bottom_left = cast_ray(min); auto ray_top_left = cast_ray({min.x(), max.y()}); diff --git a/modules/ui/src/types/Shader.cpp b/modules/ui/src/types/Shader.cpp index 4c4b9c4a..c0ae2009 100644 --- a/modules/ui/src/types/Shader.cpp +++ b/modules/ui/src/types/Shader.cpp @@ -783,7 +783,7 @@ ShaderValue::set_matrices(const Eigen::Affine3f* data, int n, bool transpose /*= ShaderValue ShaderValue::none = {-1, 0, 0, SHADER_INTERFACE_NONE}; -const ShaderValue& ShaderValue::operator=(Eigen::Vector2f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Vector2f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_VEC2); @@ -797,7 +797,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Vector2f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Vector3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Vector3f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_VEC3); @@ -811,7 +811,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Vector3f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Vector4f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Vector4f& val) const { if (location == -1) return *this; @@ -837,7 +837,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Vector4f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Matrix2f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Matrix2f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_MAT2 && shaderInterface == SHADER_INTERFACE_UNIFORM); @@ -845,7 +845,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Matrix2f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Matrix3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Matrix3f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_MAT3 && shaderInterface == SHADER_INTERFACE_UNIFORM); @@ -853,7 +853,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Matrix3f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Matrix4f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Matrix4f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_MAT4 && shaderInterface == SHADER_INTERFACE_UNIFORM); @@ -861,13 +861,13 @@ const ShaderValue& ShaderValue::operator=(Eigen::Matrix4f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Affine3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Affine3f& val) const { // defer to Matrix4f return ((*this) = val.matrix()); } -const ShaderValue& ShaderValue::operator=(Eigen::Projective3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Projective3f& val) const { // defer to Matrix4f return ((*this) = val.matrix()); diff --git a/modules/ui/src/utils/render.cpp b/modules/ui/src/utils/render.cpp index f0d80bc7..720b548e 100644 --- a/modules/ui/src/utils/render.cpp +++ b/modules/ui/src/utils/render.cpp @@ -25,9 +25,10 @@ namespace ui { namespace utils { namespace render { -std::pair compute_perpendicular_plane(Eigen::Vector3f direction) +std::pair compute_perpendicular_plane( + const Eigen::Vector3f& direction) { - Eigen::Vector3f& u1 = direction; + const Eigen::Vector3f& u1 = direction; Eigen::Vector3f v2; if (std::abs(direction.x()) == 1.0f && direction.y() == 0.0f && direction.z() == 0.0f) { From 74e03835f881ba0c0114ddf440a7230ecfe3b336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Sun, 17 May 2026 17:17:53 -0700 Subject: [PATCH 66/79] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Restore=20full=20CI?= =?UTF-8?q?=20matrix=20after=20Eigen=20alignment=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the underlying root cause (pass-by-value of fixed-size vectorizable Eigen types on MSVC ARM64 Debug) is fixed in e771745, restore the diagnostic-trimmed CI configuration to its full matrix: - Re-enable the Unix job (Linux + macOS, all compilers + sanitizers). - Restore Windows matrix to [windows-2025, windows-11-arm] x [Release, Debug]. - Restore LAGRANGE_ALL=ON + Python on windows-11-arm (uv-managed ARM64 Python pinned via Python_EXECUTABLE / Python_FIND_REGISTRY=NEVER). - Run full ctest suite (drop the serialization2-only -R filter). Verified by run 26006218827 (windows-11-arm Debug, serialization2 only) which passed cleanly after the const-ref refactor. --- .github/workflows/continuous.yaml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index f532ae2c..504829ae 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -19,7 +19,6 @@ jobs: #################### Unix: - if: false # DIAGNOSTIC: temporarily disabled to iterate fast on Windows ARM64 Debug Eigen alignment investigation name: ${{ matrix.os }} (${{ matrix.compiler }}, ${{ matrix.config }}, ${{ matrix.sanitizer }}Sanitizer) runs-on: ${{ matrix.os }} strategy: @@ -203,10 +202,8 @@ jobs: strategy: fail-fast: false matrix: - # DIAGNOSTIC: only the failing config (Win ARM64 Debug) while we hunt the - # Eigen alignment issue in serialization2. - os: [windows-11-arm] - config: [Debug] + os: [windows-2025, windows-11-arm] + config: [Release, Debug] steps: - name: Show disk space run: Get-PSDrive @@ -285,9 +282,8 @@ jobs: -B ${{ env.BUILD_DIR }} ` -S . - # DIAGNOSTIC: minimal configure for Win ARM64 — enable only the failing module - # (serialization2) so we get a fast iteration loop while we capture cpptrace - # stack traces for the Eigen alignment assertion. LAGRANGE_ALL=OFF, no Python. + # Force CMake to use the ARM64 Python (now complete with dev files) + # and skip the Windows registry so it doesn't fall back to x64 Python. - name: Configure (ARM64) if: matrix.os == 'windows-11-arm' run: | @@ -295,9 +291,10 @@ jobs: cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_ALL=OFF ` - -DLAGRANGE_MODULE_SERIALIZATION2=ON ` - -DLAGRANGE_MODULE_PYTHON=OFF ` + -DLAGRANGE_ALL=ON ` + -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -DPython_EXECUTABLE="$env:PYTHON_ARM64_EXE" ` + -DPython_FIND_REGISTRY=NEVER ` -B ${{ env.BUILD_DIR }} ` -S . @@ -314,6 +311,4 @@ jobs: run: Get-PSDrive - name: Tests - # DIAGNOSTIC: scope ctest to the serialization2 suite (the only one firing the assert). - # --verbose is critical: cpptrace writes to stderr and we need it captured in the log. - run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} -R "serialization2|serialize_" + run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} From 9b92a7c8936092ed35563eed1c2dc5d2e4b3ee26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 29 May 2026 08:44:40 -0700 Subject: [PATCH 67/79] =?UTF-8?q?=F0=9F=90=9B=20Cap=20embree=20ISA=20to=20?= =?UTF-8?q?SSE2=20on=20macos-15-intel=20to=20avoid=20OOM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macos-15-intel runner has only 14.3 GB RAM / 4 cores. With EMBREE_MAX_ISA=DEFAULT, embree compiles every ISA codepath (SSE2..AVX512); those AVX translation units, built with ASan + RelWithDebInfo under llvm@17, exceed available memory when run 4-wide. The host then kills the runner (reporting "lost communication with the server"), which surfaced only on the llvm config -- apple-clang's lower per-TU footprint stayed under the limit. Cap macOS x64 at SSE2, matching the Linux x64 ISA selection. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/continuous.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 504829ae..e243f364 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -153,7 +153,8 @@ jobs: - name: Select embree isa (macOS x64) if: runner.os == 'macOS' && runner.arch == 'X64' - run: echo "embree_max_isa=DEFAULT" >> $GITHUB_ENV + # Cap at SSE2: DEFAULT builds all ISAs, OOM-killing the 14 GB intel runner. + run: echo "embree_max_isa=SSE2" >> $GITHUB_ENV - name: Select embree isa (macOS arm64) if: runner.os == 'macOS' && runner.arch == 'ARM64' From 08ee2336c05f67ddd2756d933b9e56fd23a6e5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Thu, 25 Jun 2026 11:20:50 -0700 Subject: [PATCH 68/79] Update gklib.cmake --- cmake/recipes/external/gklib.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/recipes/external/gklib.cmake b/cmake/recipes/external/gklib.cmake index 322eb070..ac26186d 100644 --- a/cmake/recipes/external/gklib.cmake +++ b/cmake/recipes/external/gklib.cmake @@ -40,6 +40,8 @@ if(MSVC) # int_fast16_t as 'int' (32-bit) while the polyfill defines it as 'int16_t', # causing a redefinition error. Suppress the polyfills via their include guards # and force-include the real system header so the types are still available. + # Upstream fix: https://github.com/KarypisLab/GKlib/pull/59 + # (remove this workaround once it lands in our pinned GIT_TAG above). target_compile_definitions(GKlib PUBLIC _MSC_STDINT_H_ _MSC_INTTYPES_H_) target_compile_options(GKlib PUBLIC "/FIstdint.h" "/FIinttypes.h") endif() From e96c6e5146d5224bf5c1be97070a389510462ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Thu, 25 Jun 2026 11:21:28 -0700 Subject: [PATCH 69/79] Delete cmake/recipes/external/winding-number-winarm.patch --- .../external/winding-number-winarm.patch | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 cmake/recipes/external/winding-number-winarm.patch diff --git a/cmake/recipes/external/winding-number-winarm.patch b/cmake/recipes/external/winding-number-winarm.patch deleted file mode 100644 index 23d22d36..00000000 --- a/cmake/recipes/external/winding-number-winarm.patch +++ /dev/null @@ -1,50 +0,0 @@ -diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h ---- i/VM_SSEFunc.h -+++ w/VM_SSEFunc.h -@@ -39,8 +39,26 @@ - #include - #include - --typedef simde__m128 v4sf; --typedef simde__m128i v4si; -+#if defined(_MSC_VER) && defined(_M_ARM64) -+// On MSVC ARM64, simde__m128 and simde__m128i are both __n128 (the native NEON type). -+// Plain typedefs make v4sf==v4si, breaking all overloaded functions (vm_shuffle, vm_extract, -+// etc.). Use distinct wrapper structs with implicit conversions to/from the simde types. -+struct v4sf { -+ simde__m128 _v; -+ v4sf() = default; -+ SYS_FORCE_INLINE v4sf(simde__m128 v) noexcept : _v(v) {} -+ SYS_FORCE_INLINE operator simde__m128() const noexcept { return _v; } -+}; -+struct v4si { -+ simde__m128i _v; -+ v4si() = default; -+ SYS_FORCE_INLINE v4si(simde__m128i v) noexcept : _v(v) {} -+ SYS_FORCE_INLINE operator simde__m128i() const noexcept { return _v; } -+}; -+#else -+typedef simde__m128 v4sf; -+typedef simde__m128i v4si; -+#endif - - #define CPU_HAS_SIMD_INSTR 1 - #define VM_SSE_STYLE 1 -@@ -59,7 +77,7 @@ - // MSVC has problems casting between __m128 and __m128i, so we implement a - // custom casting routine specifically for windows. - --#if defined(_MSC_VER) -+#if defined(_MSC_VER) && !defined(_M_ARM64) - - static SYS_FORCE_INLINE v4sf - vm_v4sf(const v4si &a) -@@ -249,6 +267,6 @@ - vm_splats(float a, float b, float c, float d) - { - return vm_shuffle<0,2,0,2>( -- vm_shuffle<0>(simde_mm_set_ss(a), simde_mm_set_ss(b)), -- vm_shuffle<0>(simde_mm_set_ss(c), simde_mm_set_ss(d))); -+ vm_shuffle<0>(V4SF(simde_mm_set_ss(a)), V4SF(simde_mm_set_ss(b))), -+ vm_shuffle<0>(V4SF(simde_mm_set_ss(c)), V4SF(simde_mm_set_ss(d)))); - } From 169de9793ae982bf53a5907156867ce916513e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Thu, 25 Jun 2026 11:21:52 -0700 Subject: [PATCH 70/79] Remove MSVC ARM64 patch handling from CMake --- cmake/recipes/external/winding_number.cmake | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cmake/recipes/external/winding_number.cmake b/cmake/recipes/external/winding_number.cmake index 737a1674..93753f9e 100644 --- a/cmake/recipes/external/winding_number.cmake +++ b/cmake/recipes/external/winding_number.cmake @@ -19,15 +19,6 @@ lagrange_find_package(TBB CONFIG REQUIRED) include(simde) include(CPM) -set(WINDINGNUMBER_PATCHES "") -if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") - # On MSVC ARM64, simde__m128 and simde__m128i are both __n128, making plain typedefs - # identical and breaking all overloaded functions. Patch VM_SSEFunc.h to use distinct - # wrapper structs instead. Use git apply --ignore-whitespace for robust CRLF handling. - find_package(Git REQUIRED QUIET) - set(_wn_patch "${CMAKE_CURRENT_LIST_DIR}/winding-number-winarm.patch") - set(WINDINGNUMBER_PATCHES PATCH_COMMAND "${GIT_EXECUTABLE}" apply --ignore-whitespace "${_wn_patch}") -endif() CPMAddPackage( NAME WindingNumber GITHUB_REPOSITORY jdumas/WindingNumber From 6f6bd0a946bc0e2e6e76aaaa6f174f54ca92af48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 28 Jul 2026 16:04:11 -0700 Subject: [PATCH 71/79] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20dousse-adob?= =?UTF-8?q?e/embree=20fork=20to=20latest,=20drop=20local=20winarm=20patch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dousse/arm-forreal branch now upstreams the Windows ARM64 (_M_ARM64) intrinsic guards for BMI/LZCNT/PEXT that were previously applied via embree-winarm.patch. Bump the pinned commit from 03d8ec8 to c5a6207 and remove the now-redundant local patch and its git-apply plumbing. --- cmake/recipes/external/embree-winarm.patch | 24 ---------------------- cmake/recipes/external/embree.cmake | 14 +++++-------- 2 files changed, 5 insertions(+), 33 deletions(-) delete mode 100644 cmake/recipes/external/embree-winarm.patch diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch deleted file mode 100644 index 9102a25b..00000000 --- a/cmake/recipes/external/embree-winarm.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h ---- i/common/sys/intrinsics.h -+++ w/common/sys/intrinsics.h -@@ -92,6 +92,6 @@ - #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) - __forceinline size_t bsf(size_t v) { --#if defined(__AVX2__) -+#if defined(__AVX2__) && !defined(_M_ARM64) - return _tzcnt_u64(v); - #else - unsigned long r = 0; _BitScanForward64(&r,v); return r; -@@ -142,5 +142,5 @@ - __forceinline size_t bsr(size_t v) { --#if defined(__AVX2__) -+#if defined(__AVX2__) && !defined(_M_ARM64) - return 63 -_lzcnt_u64(v); - #else - unsigned long r = 0; _BitScanReverse64(&r, v); return r; -@@ -534,4 +534,4 @@ --#if defined(__AVX2__) && !defined(__aarch64__) -+#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64) - __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); } - __forceinline unsigned int pdep(unsigned int a, unsigned int b) { return _pdep_u32(a, b); } - #if defined(__X86_64__) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 129c9b90..a912ac71 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -124,16 +124,12 @@ function(embree_import_target) endif() set(EMBREE_URL RenderKit/embree) if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND EMBREE_VERSION STREQUAL "v4.4.0") - message(STATUS "Testing winarm version of embree 4") - set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) + message(STATUS "Using winarm-compatible fork of embree 4") + # The dousse-adobe fork adds Windows ARM64 (_M_ARM64) support, guarding x86 BMI/LZCNT/PEXT + # intrinsics that are unavailable on MSVC ARM64. These fixes now live upstream in the + # fork's dousse/arm-forreal branch, so no local patch is required anymore. + set(EMBREE_VERSION c5a62076608e3e70471f4d64355e17d0e3be6619) set(EMBREE_URL dousse-adobe/embree) - # The dousse-adobe fork guards x86 BMI/LZCNT/PEXT intrinsics with !defined(__aarch64__) - # (GCC/Clang macro) but misses _M_ARM64 (MSVC macro), causing build failures on Windows - # ARM64. We use git apply --ignore-whitespace instead of CPM's PATCHES (patch -p1) because - # git-cloned files may have CRLF line endings on Windows, which confuses patch.exe. - find_package(Git REQUIRED QUIET) - set(EMBREE_ARM64_PATCH "${CMAKE_CURRENT_LIST_DIR}/embree-winarm.patch") - set(EMBREE_PATCHES PATCH_COMMAND "${GIT_EXECUTABLE}" apply --ignore-whitespace "${EMBREE_ARM64_PATCH}") endif() CPMAddPackage( NAME embree From ec88f5ce8e0ace07d1cfc7cf711990a25eec0684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 28 Jul 2026 16:12:36 -0700 Subject: [PATCH 72/79] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20Boost=20to?= =?UTF-8?q?=201.91.0-1,=20drop=20local=20winarm=20patch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boost.Context's Windows ARM64 CMake support (armclang assembler, ASM_LANGUAGE refactor, MSVC ARM64 masm handling) that we backported via Boost.winarm.patch has been upstream since Boost 1.89.0, so the patch is now redundant. Bump from 1.84.0 to 1.91.0-1 (using the -cmake release variant) and remove the patch. The EMSCRIPTEN Boost.wasm.patch is kept, as BOOST_NO_FENV_H is still defined upstream. --- cmake/recipes/external/Boost.cmake | 9 +- cmake/recipes/external/Boost.winarm.patch | 132 ---------------------- 2 files changed, 4 insertions(+), 137 deletions(-) delete mode 100644 cmake/recipes/external/Boost.winarm.patch diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index fe826840..0d7a3b3e 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -86,17 +86,16 @@ if(EMSCRIPTEN) # https://github.com/boostorg/interval/issues/44 list(APPEND BOOST_PATCHES Boost.wasm.patch) endif() -if(WIN32) - list(APPEND BOOST_PATCHES Boost.winarm.patch) -endif() # Modern CMake target support was added in Boost 1.82.0 # CMake support for boost::numeric_ublas was added in Boost 1.84.0 +# Windows ARM64 support in Boost.Context (formerly carried in Boost.winarm.patch) is upstream as of +# Boost 1.89.0, so no local patch is needed anymore for that platform. include(CPM) CPMAddPackage( NAME Boost - URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz - URL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0e + URL https://github.com/boostorg/boost/releases/download/boost-1.91.0-1/boost-1.91.0-1-cmake.tar.xz + URL_HASH SHA256=cc5dc5006ecbdf0051f90979be31b4eee5987d9ae14ae9fb9c03cfa43fa3cdad EXCLUDE_FROM_ALL ON PATCHES ${BOOST_PATCHES} ) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch deleted file mode 100644 index fc6681aa..00000000 --- a/cmake/recipes/external/Boost.winarm.patch +++ /dev/null @@ -1,132 +0,0 @@ -Submodule libs/context contains modified content -diff --git i/libs/context/CMakeLists.txt w/libs/context/CMakeLists.txt -index dca5349..bd064b1 100644 ---- i/libs/context/CMakeLists.txt -+++ w/libs/context/CMakeLists.txt -@@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${boost_context_SOURCE_DIR}/cmake) - - ## Binary format - --if(WIN32) -+if(WIN32 OR CYGWIN) - set(_default_binfmt pe) - elseif(APPLE) - set(_default_binfmt mach-o) -@@ -31,7 +31,7 @@ math(EXPR _bits "${CMAKE_SIZEOF_VOID_P}*8") - - if(CMAKE_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(_default_abi aapcs) --elseif(WIN32) -+elseif(WIN32 OR CYGWIN) - set(_default_abi ms) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") - if(_bits EQUAL 32) -@@ -60,6 +60,8 @@ elseif(_bits EQUAL 32) - set(_default_arch arm) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") - set(_default_arch mips32) -+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc32)") -+ set(_default_arch ppc32) - else() - set(_default_arch i386) - endif() -@@ -69,6 +71,8 @@ else() - set(_default_arch arm64) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") - set(_default_arch mips64) -+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc64)") -+ set(_default_arch ppc64) - else() - set(_default_arch x86_64) - endif() -@@ -89,18 +93,22 @@ if(MSVC) - else() - set(_default_asm masm) - endif() -+elseif(BOOST_CONTEXT_ARCHITECTURE STREQUAL arm64 AND MINGW) -+ set(_default_asm armclang) - else() - set(_default_asm gas) - endif() - --set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm)") --set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm) -+set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm, armclang)") -+set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm armclang) - - unset(_default_asm) - - ## Assembler source suffix - --if(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) -+if(BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) -+ set(_default_ext .S) -+elseif(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) - set(_default_ext .asm) - elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) - set(_default_ext .S) -@@ -133,18 +141,22 @@ message(STATUS "Boost.Context: " - "implementation ${BOOST_CONTEXT_IMPLEMENTATION}") - - # Enable the right assembler -- -+set(ASM_LANGUAGE) - if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") -- if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) -+ if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas OR BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) - if(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") -- enable_language(ASM-ATT) -+ set(ASM_LANGUAGE ASM-ATT) - else() -- enable_language(ASM) -+ set(ASM_LANGUAGE ASM) - endif() - elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) -- enable_language(ASM_ARMASM) -+ if(MSVC) -+ set(ASM_LANGUAGE ASM_MARMASM) -+ else() -+ set(ASM_LANGUAGE ASM_ARMASM) -+ endif() - else() -- enable_language(ASM_MASM) -+ set(ASM_LANGUAGE ASM_MASM) - endif() - endif() - -@@ -170,13 +182,29 @@ if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") - - set(IMPL_SOURCES ${ASM_SOURCES}) - -- if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) -- set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh") -- endif() -+ if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm) - -- if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -- set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") -- endif() -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/nologo") -+ -+ if(MSVC AND NOT(MSVC_VERSION LESS 1936) AND NOT(CMAKE_CXX_SIMULATE_VERSION)) -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/quiet") -+ endif() -+ -+ if(BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/safeseh") -+ endif() -+ -+ # armasm doesn't support most of these options -+ elseif(NOT BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) # masm -+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") -+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-Wno-unused-command-line-argument") -+ endif() -+ endif() # masm -+ -+ enable_language(${ASM_LANGUAGE}) -+ set_source_files_properties(${ASM_SOURCES} PROPERTIES LANGUAGE ${ASM_LANGUAGE}) - else() - set(IMPL_SOURCES - src/continuation.cpp From 1dde2a4069e9cb4c9e781ce8b2da2f03fc2ed406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Fri, 31 Jul 2026 08:11:20 -0700 Subject: [PATCH 73/79] Update embree.cmake --- cmake/recipes/external/embree.cmake | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index a912ac71..01f657b3 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -125,11 +125,7 @@ function(embree_import_target) set(EMBREE_URL RenderKit/embree) if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND EMBREE_VERSION STREQUAL "v4.4.0") message(STATUS "Using winarm-compatible fork of embree 4") - # The dousse-adobe fork adds Windows ARM64 (_M_ARM64) support, guarding x86 BMI/LZCNT/PEXT - # intrinsics that are unavailable on MSVC ARM64. These fixes now live upstream in the - # fork's dousse/arm-forreal branch, so no local patch is required anymore. - set(EMBREE_VERSION c5a62076608e3e70471f4d64355e17d0e3be6619) - set(EMBREE_URL dousse-adobe/embree) + set(EMBREE_VERSION 958014331b95bc6f23a82b8f2ea284ce7410febb) endif() CPMAddPackage( NAME embree From 3c4e47678475715d2e50ac063f62d634b0aaa0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 18 Aug 2026 10:31:52 -0700 Subject: [PATCH 74/79] update to embree main. --- cmake/recipes/external/embree.cmake | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 01f657b3..e18cfc1e 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -112,7 +112,7 @@ function(embree_import_target) # Ready to include embree's atrocious CMake include(CPM) - set(EMBREE_VERSION v4.4.0) + set(EMBREE_VERSION bb93949614c9fcfa1b850cb9ac79b3d9e4f1d2ec) # ahead of 4.4.1 set(EMBREE_PATCHES "") if(LAGRANGE_WITH_EMBREE_3) set(CMAKE_POLICY_VERSION_MINIMUM 3.5) @@ -122,14 +122,9 @@ function(embree_import_target) # https://github.com/RenderKit/embree/issues/486 set(EMBREE_PATCHES PATCHES embree.patch) endif() - set(EMBREE_URL RenderKit/embree) - if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND EMBREE_VERSION STREQUAL "v4.4.0") - message(STATUS "Using winarm-compatible fork of embree 4") - set(EMBREE_VERSION 958014331b95bc6f23a82b8f2ea284ce7410febb) - endif() CPMAddPackage( NAME embree - GITHUB_REPOSITORY ${EMBREE_URL} + GITHUB_REPOSITORY RenderKit/embree GIT_TAG ${EMBREE_VERSION} ${EMBREE_PATCHES} ) From 4b0cb2614b239904b7f27bbb70e98c95936e2109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 9 Oct 2026 23:03:48 +0000 Subject: [PATCH 75/79] Keep Boost 1.84 and retain Windows x64 Embree ISA cap --- .github/workflows/continuous.yaml | 1 + cmake/recipes/external/Boost.cmake | 10 +- cmake/recipes/external/Boost.winarm.patch | 132 ++++++++++++++++++++++ 3 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 cmake/recipes/external/Boost.winarm.patch diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 3f386d9f..237fb8a4 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -334,6 +334,7 @@ jobs: -DLAGRANGE_JENKINS=ON ` -DLAGRANGE_ALL=ON ` -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -DEMBREE_MAX_ISA=AVX2 ` -B ${{ env.BUILD_DIR }} ` -S . diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index 0d7a3b3e..3afde628 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -86,16 +86,18 @@ if(EMSCRIPTEN) # https://github.com/boostorg/interval/issues/44 list(APPEND BOOST_PATCHES Boost.wasm.patch) endif() +if(WIN32) + # Backport Windows ARM64 assembler support for Boost.Context. + list(APPEND BOOST_PATCHES Boost.winarm.patch) +endif() # Modern CMake target support was added in Boost 1.82.0 # CMake support for boost::numeric_ublas was added in Boost 1.84.0 -# Windows ARM64 support in Boost.Context (formerly carried in Boost.winarm.patch) is upstream as of -# Boost 1.89.0, so no local patch is needed anymore for that platform. include(CPM) CPMAddPackage( NAME Boost - URL https://github.com/boostorg/boost/releases/download/boost-1.91.0-1/boost-1.91.0-1-cmake.tar.xz - URL_HASH SHA256=cc5dc5006ecbdf0051f90979be31b4eee5987d9ae14ae9fb9c03cfa43fa3cdad + URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz + URL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0e EXCLUDE_FROM_ALL ON PATCHES ${BOOST_PATCHES} ) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch new file mode 100644 index 00000000..fc6681aa --- /dev/null +++ b/cmake/recipes/external/Boost.winarm.patch @@ -0,0 +1,132 @@ +Submodule libs/context contains modified content +diff --git i/libs/context/CMakeLists.txt w/libs/context/CMakeLists.txt +index dca5349..bd064b1 100644 +--- i/libs/context/CMakeLists.txt ++++ w/libs/context/CMakeLists.txt +@@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${boost_context_SOURCE_DIR}/cmake) + + ## Binary format + +-if(WIN32) ++if(WIN32 OR CYGWIN) + set(_default_binfmt pe) + elseif(APPLE) + set(_default_binfmt mach-o) +@@ -31,7 +31,7 @@ math(EXPR _bits "${CMAKE_SIZEOF_VOID_P}*8") + + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(_default_abi aapcs) +-elseif(WIN32) ++elseif(WIN32 OR CYGWIN) + set(_default_abi ms) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + if(_bits EQUAL 32) +@@ -60,6 +60,8 @@ elseif(_bits EQUAL 32) + set(_default_arch arm) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(_default_arch mips32) ++ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc32)") ++ set(_default_arch ppc32) + else() + set(_default_arch i386) + endif() +@@ -69,6 +71,8 @@ else() + set(_default_arch arm64) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(_default_arch mips64) ++ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc64)") ++ set(_default_arch ppc64) + else() + set(_default_arch x86_64) + endif() +@@ -89,18 +93,22 @@ if(MSVC) + else() + set(_default_asm masm) + endif() ++elseif(BOOST_CONTEXT_ARCHITECTURE STREQUAL arm64 AND MINGW) ++ set(_default_asm armclang) + else() + set(_default_asm gas) + endif() + +-set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm)") +-set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm) ++set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm, armclang)") ++set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm armclang) + + unset(_default_asm) + + ## Assembler source suffix + +-if(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) ++if(BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) ++ set(_default_ext .S) ++elseif(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) + set(_default_ext .asm) + elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) + set(_default_ext .S) +@@ -133,18 +141,22 @@ message(STATUS "Boost.Context: " + "implementation ${BOOST_CONTEXT_IMPLEMENTATION}") + + # Enable the right assembler +- ++set(ASM_LANGUAGE) + if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") +- if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) ++ if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas OR BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) + if(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") +- enable_language(ASM-ATT) ++ set(ASM_LANGUAGE ASM-ATT) + else() +- enable_language(ASM) ++ set(ASM_LANGUAGE ASM) + endif() + elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) +- enable_language(ASM_ARMASM) ++ if(MSVC) ++ set(ASM_LANGUAGE ASM_MARMASM) ++ else() ++ set(ASM_LANGUAGE ASM_ARMASM) ++ endif() + else() +- enable_language(ASM_MASM) ++ set(ASM_LANGUAGE ASM_MASM) + endif() + endif() + +@@ -170,13 +182,29 @@ if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") + + set(IMPL_SOURCES ${ASM_SOURCES}) + +- if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) +- set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh") +- endif() ++ if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm) + +- if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +- set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") +- endif() ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/nologo") ++ ++ if(MSVC AND NOT(MSVC_VERSION LESS 1936) AND NOT(CMAKE_CXX_SIMULATE_VERSION)) ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/quiet") ++ endif() ++ ++ if(BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/safeseh") ++ endif() ++ ++ # armasm doesn't support most of these options ++ elseif(NOT BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) # masm ++ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") ++ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-Wno-unused-command-line-argument") ++ endif() ++ endif() # masm ++ ++ enable_language(${ASM_LANGUAGE}) ++ set_source_files_properties(${ASM_SOURCES} PROPERTIES LANGUAGE ${ASM_LANGUAGE}) + else() + set(IMPL_SOURCES + src/continuation.cpp From 9265470073dbfe839284992b7cfcaf8473f1c960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 9 Oct 2026 23:06:48 +0000 Subject: [PATCH 76/79] Update Boost to 1.92 and document Windows ARM64 minimum --- cmake/recipes/external/Boost.cmake | 9 +- cmake/recipes/external/Boost.winarm.patch | 132 ---------------------- 2 files changed, 3 insertions(+), 138 deletions(-) delete mode 100644 cmake/recipes/external/Boost.winarm.patch diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index 3afde628..4bf602b5 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -86,18 +86,15 @@ if(EMSCRIPTEN) # https://github.com/boostorg/interval/issues/44 list(APPEND BOOST_PATCHES Boost.wasm.patch) endif() -if(WIN32) - # Backport Windows ARM64 assembler support for Boost.Context. - list(APPEND BOOST_PATCHES Boost.winarm.patch) -endif() # Modern CMake target support was added in Boost 1.82.0 # CMake support for boost::numeric_ublas was added in Boost 1.84.0 +# Windows ARM64 requires Boost 1.89.0 or newer for Boost.Context assembler support. include(CPM) CPMAddPackage( NAME Boost - URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz - URL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0e + URL https://github.com/boostorg/boost/releases/download/boost-1.92.0/boost-1.92.0-cmake.tar.xz + URL_HASH SHA256=9bed76128d4e46755dbe818487788c6fceb6f72b378f4daa49b7e1e600d9088d EXCLUDE_FROM_ALL ON PATCHES ${BOOST_PATCHES} ) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch deleted file mode 100644 index fc6681aa..00000000 --- a/cmake/recipes/external/Boost.winarm.patch +++ /dev/null @@ -1,132 +0,0 @@ -Submodule libs/context contains modified content -diff --git i/libs/context/CMakeLists.txt w/libs/context/CMakeLists.txt -index dca5349..bd064b1 100644 ---- i/libs/context/CMakeLists.txt -+++ w/libs/context/CMakeLists.txt -@@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${boost_context_SOURCE_DIR}/cmake) - - ## Binary format - --if(WIN32) -+if(WIN32 OR CYGWIN) - set(_default_binfmt pe) - elseif(APPLE) - set(_default_binfmt mach-o) -@@ -31,7 +31,7 @@ math(EXPR _bits "${CMAKE_SIZEOF_VOID_P}*8") - - if(CMAKE_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(_default_abi aapcs) --elseif(WIN32) -+elseif(WIN32 OR CYGWIN) - set(_default_abi ms) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") - if(_bits EQUAL 32) -@@ -60,6 +60,8 @@ elseif(_bits EQUAL 32) - set(_default_arch arm) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") - set(_default_arch mips32) -+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc32)") -+ set(_default_arch ppc32) - else() - set(_default_arch i386) - endif() -@@ -69,6 +71,8 @@ else() - set(_default_arch arm64) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") - set(_default_arch mips64) -+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc64)") -+ set(_default_arch ppc64) - else() - set(_default_arch x86_64) - endif() -@@ -89,18 +93,22 @@ if(MSVC) - else() - set(_default_asm masm) - endif() -+elseif(BOOST_CONTEXT_ARCHITECTURE STREQUAL arm64 AND MINGW) -+ set(_default_asm armclang) - else() - set(_default_asm gas) - endif() - --set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm)") --set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm) -+set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm, armclang)") -+set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm armclang) - - unset(_default_asm) - - ## Assembler source suffix - --if(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) -+if(BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) -+ set(_default_ext .S) -+elseif(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) - set(_default_ext .asm) - elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) - set(_default_ext .S) -@@ -133,18 +141,22 @@ message(STATUS "Boost.Context: " - "implementation ${BOOST_CONTEXT_IMPLEMENTATION}") - - # Enable the right assembler -- -+set(ASM_LANGUAGE) - if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") -- if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) -+ if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas OR BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) - if(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") -- enable_language(ASM-ATT) -+ set(ASM_LANGUAGE ASM-ATT) - else() -- enable_language(ASM) -+ set(ASM_LANGUAGE ASM) - endif() - elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) -- enable_language(ASM_ARMASM) -+ if(MSVC) -+ set(ASM_LANGUAGE ASM_MARMASM) -+ else() -+ set(ASM_LANGUAGE ASM_ARMASM) -+ endif() - else() -- enable_language(ASM_MASM) -+ set(ASM_LANGUAGE ASM_MASM) - endif() - endif() - -@@ -170,13 +182,29 @@ if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") - - set(IMPL_SOURCES ${ASM_SOURCES}) - -- if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) -- set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh") -- endif() -+ if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm) - -- if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -- set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") -- endif() -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/nologo") -+ -+ if(MSVC AND NOT(MSVC_VERSION LESS 1936) AND NOT(CMAKE_CXX_SIMULATE_VERSION)) -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/quiet") -+ endif() -+ -+ if(BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/safeseh") -+ endif() -+ -+ # armasm doesn't support most of these options -+ elseif(NOT BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) # masm -+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") -+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") -+ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-Wno-unused-command-line-argument") -+ endif() -+ endif() # masm -+ -+ enable_language(${ASM_LANGUAGE}) -+ set_source_files_properties(${ASM_SOURCES} PROPERTIES LANGUAGE ${ASM_LANGUAGE}) - else() - set(IMPL_SOURCES - src/continuation.cpp From 397409a60dcc12c9676331b15555e1f92fb03cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 9 Oct 2026 23:40:30 +0000 Subject: [PATCH 77/79] =?UTF-8?q?=F0=9F=90=9B=20Explicitly=20include=20Boo?= =?UTF-8?q?st.Coroutine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boost.Asio no longer pulls in Coroutine transitively in Boost 1.92. Select it explicitly so downstream consumers can still use and install the boost_coroutine target. --- cmake/recipes/external/Boost.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index 4bf602b5..738c2778 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -32,6 +32,7 @@ set(BOOST_INCLUDE_LIBRARIES chrono compute container + coroutine crc date_time filesystem From eb3d4e450ca74116b5a6442cafe10c94a8c3b01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 9 Oct 2026 23:50:37 +0000 Subject: [PATCH 78/79] =?UTF-8?q?=F0=9F=94=A5=20Drop=20legacy=20Boost.Coro?= =?UTF-8?q?utine=20selection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boost 1.92 Asio stackful coroutine support uses Boost.Context directly. Remove the unnecessary explicit Coroutine selection and its stale indirect-dependency entry while retaining Context. --- cmake/recipes/external/Boost.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index 738c2778..a6391978 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -32,7 +32,6 @@ set(BOOST_INCLUDE_LIBRARIES chrono compute container - coroutine crc date_time filesystem @@ -125,7 +124,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ${OLD_CMAKE_POSITION_INDEPENDENT_CODE}) # Indirect deps pulled by other boost targets set(Boost_Deps - assert context core coroutine exception random serialization variant2 + assert context core exception random serialization variant2 ) foreach(name IN ITEMS ${BOOST_INCLUDE_LIBRARIES} ${Boost_Deps}) if(TARGET boost_${name}) From 9e761ddf5f8a9c4e88e8a2c15abbd58ef18bc0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 12 Oct 2026 14:44:25 +0000 Subject: [PATCH 79/79] =?UTF-8?q?=F0=9F=90=9B=20Disable=20Boost.UUID=20lib?= =?UTF-8?q?atomic=20linkage=20on=20Emscripten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boost 1.92 defaults BOOST_UUID_LINK_LIBATOMIC to ON for non-Apple Clang, including Emscripten. Emscripten implements atomics in its runtime and has no separate libatomic library. Force the option off only for Emscripten, including stale cached ON values, and leave native toolchains unchanged. Verified the UUID atomic-state smoke test and WASM volume tests. --- cmake/recipes/external/Boost.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index a6391978..1bd16c14 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -81,6 +81,9 @@ option(BOOST_IOSTREAMS_ENABLE_ZSTD "Boost.Iostreams: Enable Zstd support" OFF) set(BOOST_PATCHES) if(EMSCRIPTEN) + # Emscripten provides atomics in its runtime; it has no separate libatomic. + set(BOOST_UUID_LINK_LIBATOMIC OFF CACHE BOOL "Boost.UUID: link Boost::uuid to libatomic" FORCE) + # Wasm doesn't have rounding mode control yet, so we trick Boost::interval into thinking it has. # https://github.com/WebAssembly/rounding-mode-control # https://github.com/boostorg/interval/issues/44