From 7b29a4427b204f29fc530dd5d60d98ce5fb37675 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Thu, 8 Jan 2026 13:27:01 -0700 Subject: [PATCH 01/12] Refactor to work on modern macOS, ensure `devel` branch builds (wit GUI), allow using GCC or Clang --- elmer.rb | 406 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 355 insertions(+), 51 deletions(-) diff --git a/elmer.rb b/elmer.rb index 80f8252..b043133 100644 --- a/elmer.rb +++ b/elmer.rb @@ -1,70 +1,301 @@ class Elmer < Formula - desc """ - Elmer finite element solver + desc "Open source multiphysical simulation software (finite element solver)" + homepage "https://elmerfem.org" - * Requires homebrew/science to be tapped for MUMPS. - * OCC, VTK and QWT (for convergence plot) are not supported - """ - homepage "http://elmerfem.org" - - head "https://github.com/ElmerCSC/elmerfem.git", :branch => "devel" + head "https://github.com/ElmerCSC/elmerfem.git", branch: "devel" stable do - url "https://github.com/ElmerCSC/elmerfem/archive/release-8.2.tar.gz" - sha256 "ed4c87895c76003dd81faa464b6d0f38225d43e584f75290df21df629d0a4ecc" + url "https://github.com/ElmerCSC/elmerfem/archive/refs/tags/release-9.0.tar.gz" + sha256 "08c5bf261e87ff37456c1aa0372db3c83efabe4473ea3ea0b8ec66f5944d1aa0" + + # CMake 3.19 for compatibility with old CHECK_TYPE_SIZE syntax + resource "cmake" do + url "https://github.com/Kitware/CMake/releases/download/v3.19.8/cmake-3.19.8-macos-universal.tar.gz" + sha256 "0976d23d982af05dcbfb3aa34fcb62ead43bea27f0e3bb95222f2a78161423f2" + end + + # Fix Qwt 6.2 deprecation + patch do + url "https://github.com/ElmerCSC/elmerfem/commit/48e9430ccb858ca5bda28b967a0c84b51e2404b2.patch?full_index=1" + sha256 "707032d1f899dacc62ffd7c6f09aff6aaa22d6eaa353b707808bef639d774398" + end + + # Fix Qt5 compile issue + patch do + url "https://github.com/ElmerCSC/elmerfem/commit/e057b0d46a6d1708a0d322bc73d70594a63de447.patch?full_index=1" + sha256 "0abf3d771b720edd3dc27a4b0115f12e325381284b1162568dbbc780c76cf934" + end + + # Fix DCRComplexSolve.F90 issue + patch do + url "https://github.com/ElmerCSC/elmerfem/commit/a28b3521f3c81bd7fe7176555815ffd1d35cf4b2.patch?full_index=1" + sha256 "ae29e1089fa009345c941fdf11ed346bd21a776874b70f9d2bf393b4bd3e1e71" + end + + patch do + url "https://github.com/ElmerCSC/elmerfem/commit/96a33930ee23e785f33bcb257398f1ccca8fdf99.patch?full_index=1" + sha256 "7935cd13ec54afe84de3ac2c3d3b676110f9926092abcfd414f913311920c09b" + end + + patch do + url "https://github.com/ElmerCSC/elmerfem/commit/8f9f2c703b020dc6d21cbaa1cb8b05abbbd7ded1.patch?full_index=1" + sha256 "4372532a4bc792e4d43466c813f1962c6964389abaa62f545a311a49bda76676" + end + + patch do + url "https://github.com/ElmerCSC/elmerfem/commit/54fd87054f687305644b92d0525a3f0cd4423a93.patch?full_index=1" + sha256 "ea8c5e85230d5e6a08dc04cb2e23161bca19940b9f8c092777586dcfa491dedc" + end + + # Comment out hard-coded C/C++ compiler paths + patch :DATA end - option "with-elmerice", "Build ElmerIce" - option "with-elmergui", "Build ElmerGUI" - option "with-openmp", "Enable OpenMP support (experimental)" - option "with-testing", "Run the quick tests" + # ============================================================================= + # Build Options + # ============================================================================= + option "with-elmerice", "Build ElmerIce glaciology module" + option "with-elmergui", "Build ElmerGUI graphical interface" + option "with-gcc", "Use GCC instead of Clang for C/C++ compilation" + option "with-openmp", "Build with OpenMP support" + option "with-testing", "Run the quick tests after build" - depends_on "open-mpi" => [:f90, :recommended] + # ============================================================================= + # Dependencies + # ============================================================================= + # Build dependencies depends_on "cmake" => :build - depends_on "gcc" => ["10", :build] + + # Required: Fortran compiler (always needed regardless of C/C++ compiler choice) + depends_on "gcc" + + # Required: Linear algebra depends_on "openblas" - # depends_on "scalapack" - depends_on "hypre" => :recommended - depends_on "mumps" => :recommended - depends_on "qt5" if build.with? "elmergui" - # depends_on "oce" if build.with? "elmergui" - # depends_on "vtk" => "with-qt" if build.with? "elmergui" - # depends_on "qwt" if build.with? "elmergui" + # Optional: Solver libraries + depends_on "hypre" => :optional + depends_on "mumps" => :optional + + # Optional: Parallelization + depends_on "libomp" => :optional + depends_on "open-mpi" => :optional + + # Optional: GUI dependencies + depends_on "opencascade" => :optional + depends_on "qt" => :optional + depends_on "qwt" => :optional + depends_on "vtk" => :optional def install - cmake_args = %W[-DCMAKE_INSTALL_PREFIX=#{prefix}] - cmake_args << "-DWITH_Hypre:BOOL=TRUE" if build.with? "hypre" - cmake_args << "-DWITH_ElmerIce:BOOL=TRUE" if build.with? "elmerice" - cmake_args << "-DWITH_Mumps:BOOL=TRUE" if build.with? "mumps" - cmake_args << "-DWITH_MPI:BOOL=FALSE" if build.without? "open-mpi" - cmake_args << "-DWITH_MPI:BOOL=TRUE" if build.with? "open-mpi" - cmake_args << "-DWITH_OpenMP:BOOL=TRUE" if build.with? "openmp" - - exten = (OS.mac?) ? "dylib" : "so" - cmake_args << "-DBLAS_LIBRARIES:STRING=#{Formula["openblas"].opt_lib}/libopenblas.#{exten};-lpthread" - cmake_args << "-DLAPACK_LIBRARIES:STRING=#{Formula["openblas"].opt_lib}/libopenblas.#{exten};-lpthread" - - if build.with? "elmergui" - cmake_args << "-DWITH_ELMERGUI:BOOL=TRUE" - # cmake_args << "-DWITH_QWT:BOOL=TRUE" - # cmake_args << "-DWITH_OCC:BOOL=TRUE" - # cmake_args << "-DWITH_VTK:BOOL=TRUE" - cmake_args << "-DQWT_INCLUDE_DIR=#{Formula["qwt"].lib}/qwt.framework/Headers" - cmake_args << "-DWITH_QT5:BOOL=TRUE" + # Determine CMake binary + if build.stable? + resource("cmake").stage do + (buildpath/"local_cmake").install "CMake.app/Contents" + end + cmake_bin = buildpath/"local_cmake/Contents/bin/cmake" + ctest_bin = buildpath/"local_cmake/Contents/bin/ctest" + else + cmake_bin = Formula["cmake"].opt_bin/"cmake" + ctest_bin = Formula["cmake"].opt_bin/"ctest" end - mkdir "build" do - system "cmake -DCMAKE_C_COMPILER=/usr/local/bin/gcc -DCMAKE_CXX_COMPILER=/usr/local/bin/g++", "../", *cmake_args, *std_cmake_args - system "make" - system "make", "install" - system "ctest -L quick" if build.with? "testing" + # Compiler configuration + gcc_formula_str = build.stable? ? "gcc@11" : "gcc" + gcc_formula = Formula[gcc_formula_str] + gcc_version = gcc_formula.version.major + use_gcc = build.with?("gcc") + + # SDK configuration + sdk_path = MacOS.sdk_path + sdk_version = Utils.safe_popen_read("xcrun", "--show-sdk-version").strip + + if build.head? && sdk_version < "15.5" + odie "Homebrew GCC requires macOS SDK 15.5 or newer (found #{sdk_version})" end + + # Build sysroot flags + sys_root = use_gcc ? "--sysroot=#{sdk_path}" : "-isysroot #{sdk_path}" + + # For stable builds with GCC, try to find an older SDK if available + if build.stable? && use_gcc + older_sdk = Dir["/Library/Developer/CommandLineTools/SDKs/MacOSX1[0-4].sdk"].max + if older_sdk + sys_root = "--sysroot=#{older_sdk}" + sdk_path = older_sdk + else + opoo "No older macOS SDK found; GCC build may have compatibility issues" + end + + unless gcc_formula.any_version_installed? + odie "Elmer version requires #{gcc_formula_str}. Run: brew install #{gcc_formula_str}" + end + end + + # Compiler flags + c_flags = "#{sys_root} -Wno-error=implicit-function-declaration -Wno-implicit-function-declaration" + cxx_flags = sys_root + cxx_flags += " -Wno-deprecated-declarations" if build.head? && use_gcc + + # ============================================================================= + # CMake Arguments + # ============================================================================= + cmake_args = std_cmake_args.dup + + # Compiler selection + if use_gcc + cmake_args << "-DCMAKE_C_COMPILER=#{gcc_formula.opt_bin}/gcc-#{gcc_version}" + cmake_args << "-DCMAKE_CXX_COMPILER=#{gcc_formula.opt_bin}/g++-#{gcc_version}" + else + cmake_args << "-DCMAKE_C_COMPILER=/usr/bin/clang" + cmake_args << "-DCMAKE_CXX_COMPILER=/usr/bin/clang++" + end + + # Fortran always uses gfortran + cmake_args << "-DCMAKE_Fortran_COMPILER=#{gcc_formula.opt_bin}/gfortran-#{gcc_version}" + + # Linear algebra + blas_lib = Formula["openblas"].opt_lib/shared_library("libopenblas") + cmake_args << "-DBLAS_LIBRARIES:STRING=#{blas_lib};-lpthread" + cmake_args << "-DLAPACK_LIBRARIES:STRING=#{blas_lib};-lpthread" + + # Optional solver features + cmake_args << "-DWITH_ElmerIce=ON" if build.with?("elmerice") + cmake_args << "-DWITH_Hypre=ON" if build.with?("hypre") + cmake_args << "-DWITH_Mumps=ON" if build.with?("mumps") + cmake_args << "-DWITH_MPI=#{build.with?("open-mpi") ? "ON" : "OFF"}" + + # OpenMP configuration + if build.with?("openmp") + cmake_args << "-DWITH_OpenMP=ON" + cmake_args << "-DWITH_CHOLMOD=ON" + + if use_gcc + # GCC has built-in OpenMP support + %w[C CXX Fortran].each do |lang| + cmake_args << "-DOpenMP_#{lang}_FLAGS=-fopenmp" + end + else + # Clang requires libomp + libomp = Formula["libomp"] + cmake_args << "-DOpenMP_ROOT=#{libomp.opt_prefix}" + ENV.append "LDFLAGS", "-L#{libomp.opt_lib} -lomp" + c_flags += " -I#{libomp.opt_include}" + cxx_flags += " -I#{libomp.opt_include}" + + if build.stable? + cmake_args << "-DOpenMP_C_FLAGS=-Xpreprocessor -fopenmp" + cmake_args << "-DOpenMP_CXX_FLAGS=-Xpreprocessor -fopenmp" + cmake_args << "-DOpenMP_Fortran_FLAGS=-fopenmp" + end + end + end + + # ============================================================================= + # ElmerGUI Configuration + # ============================================================================= + configure_elmergui(cmake_args) if build.with?("elmergui") + + # SDK and flags + cmake_args << "-DCMAKE_OSX_SYSROOT=#{sdk_path}" + cmake_args << "-DCMAKE_C_FLAGS=#{c_flags}" + cmake_args << "-DCMAKE_CXX_FLAGS=#{cxx_flags}" + + # Apply GCC/Qt compatibility patch if needed + if build.head? && use_gcc && build.with?("elmergui") + apply_gcc_qt6_patch + end + + cmake_args << "-DBUILD_TESTING=1" if build.with?("testing") + + # Build and install + system cmake_bin, "-S", ".", "-B", "build", *cmake_args + system cmake_bin, "--build", "build", "--parallel" + system cmake_bin, "--install", "build" + Dir.chdir("build") do + system ctest_bin, ".", "-L", "quick" if build.with?("testing") + end + end + + def configure_elmergui(cmake_args) + cmake_args << "-DWITH_ELMERGUI=ON" + + # Qt version detection + qt_formula = Formula["qt"] + qt_version = qt_formula.version.major.to_i + qwt_dep ="qwt" + + if build.head? && qt_version >= 6 + cmake_args << "-DWITH_QT6=ON" + qt_lib = Formula["qtbase"].opt_lib + cmake_args << "-DQt6_DIR=#{qt_lib}/cmake/Qt6" + %w[Xml PrintSupport OpenGL OpenGLWidgets].each do |mod| + cmake_args << "-DQt6#{mod}_DIR=#{qt_lib}/cmake/Qt6#{mod}" + end + else + # stable build needs Qt5 + qt5_dep = "qt@5" + qwt_dep ="qwt-qt5" + + qt5_installed = Formula[qt5_dep].any_version_installed? + qwt_installed = Formula[qwt_dep].any_version_installed? + + dep_message = ->(p) { "ElmerGUI requires #{p}. To install: brew install #{p}" } + odie dep_message.call(qt5_dep) unless qt5_installed + odie dep_message.call(qwt_dep) unless qwt_installed + + cmake_args << "-DWITH_QT5=ON" + cmake_args << "-DQt5_DIR=#{Formula[qt5_dep].opt_lib}/cmake/Qt5" + end + + # Qwt configuration + qwt_formula = Formula[qwt_dep] + cmake_args << "-DWITH_QWT=ON" + cmake_args << "-DQWT_INCLUDE_DIR=#{qwt_formula.opt_lib}/qwt.framework/Headers" + cmake_args << "-DQWT_LIBRARY=#{qwt_formula.opt_lib}/qwt.framework/qwt" + + # Optional GUI features + cmake_args << "-DWITH_OCC=#{build.with?("opencascade") ? "ON" : "OFF"}" + cmake_args << "-DWITH_VTK=#{build.with?("vtk") ? "ON" : "OFF"}" + end + + def apply_gcc_qt6_patch + patch_content = <<~PATCH + --- ElmerGUI/CMakeLists.txt + +++ ElmerGUI/CMakeLists.txt + @@ -35,6 +35,10 @@ + FOREACH(_pkg ${QT6_PKG_LIST}) + FIND_PACKAGE(${_pkg} PATHS ${QT6_PATH} REQUIRED) + ENDFOREACH() + + + + IF(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D'QT_IGNORE_DEPRECATIONS\\(x\\)=x'") + + ENDIF() + + ADD_DEFINITIONS(-DWITH_QT6) + MESSAGE(STATUS " [ElmerGUI] Qt6: " ${Qt6_FOUND}) + PATCH + + (buildpath/"qt-gcc.patch").write(patch_content) + system "patch", "-p0", "-i", "qt-gcc.patch" + end + + def caveats + return if build.without?("elmergui") || build.stable? + + <<~EOS + If ElmerGUI fails to run with the following error message: + + qt.qpa.plugin: Could not find the Qt platform plugin "cocoa" in "" + This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. + + Try setting the following environment variable (or add the export to ~/.bash_profile): + export QT_QPA_PLATFORM_PLUGIN_PATH=$(brew --prefix qtbase)/share/qt/plugins/platforms + EOS end test do - (testpath / "test.sif").write <<-EOS.undent + (testpath/"test.sif").write <<~EOS Header CHECK KEYWORDS Warn Mesh DB "." "geomstiff" @@ -125,7 +356,7 @@ def install Solver 2 :: Reference Norm Tolerance = Real 1e-3 EOS - (testpath / "geomstiff.grd").write <<-EOS.undent + (testpath/"geomstiff.grd").write <<~EOS ##### ElmerGrid input file for structured grid generation ###### Version = 210903 Coordinate System = Cartesian 2D @@ -152,7 +383,80 @@ def install Element Densities 2 = 1 EOS - system "ElmerGrid", "1", "2", "geomstiff.grd" - system "ElmerSolver", "test.sif" + system bin/"ElmerGrid", "1", "2", "geomstiff.grd" + system bin/"ElmerSolver", "test.sif" end end + +__END__ +--- a/CMakeLists.txt 2020-11-10 19:52:44 ++++ b/CMakeLists.txt 2025-12-31 06:18:57 +@@ -14,9 +14,9 @@ + # message("you need to have gcc-gfrotran installed using HomeBrew") + # set(CMAKE_C_COMPILER "/usr/bin/gcc") + # set(CMAKE_CXX_COMPILER "/usr/bin/g++") +- set(CMAKE_C_COMPILER "/usr/local/bin/gcc-10") +- set(CMAKE_CXX_COMPILER "/usr/local/bin/g++-10") +- set(CMAKE_Fortran_COMPILER "/usr/local/bin/gfortran") ++ # set(CMAKE_C_COMPILER "/usr/local/bin/gcc-10") ++ # set(CMAKE_CXX_COMPILER "/usr/local/bin/g++-10") ++ # set(CMAKE_Fortran_COMPILER "/usr/local/bin/gfortran") + # set(BLA_VENDOR "OpenBLAS") + # option(HUNTER_ENABLED "Enable Hunter package manager support" OFF) + # set (CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE) +@@ -178,13 +178,6 @@ + ENDIF() + + IF(WITH_OpenMP) +- # Advanced properties +- MARK_AS_ADVANCED( +- OpenMP_C_FLAGS +- OpenMP_Fortran_FLAGS +- OpenMP_CXX_FLAGS +- ) +- + # Add OpenMP flags to compilation flags + # if(APPLE) + # if(CMAKE_C_COMPILER_ID STREQUAL "GNU") +@@ -204,12 +197,13 @@ + # set(OpenMP_libiomp5_LIBRARY ${OpenMP_CXX_LIB_NAMES}) + # endif() + # else() +- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") +- SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}") +- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + # endif() + + FIND_PACKAGE(OpenMP REQUIRED) ++ ++ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") ++ SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}") ++ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + + # Test compiler support for OpenMP 4.0 features used + INCLUDE(testOpenMP40) + +--- a/ElmerGUI/CMakeLists.txt 2020-11-10 19:52:44 ++++ b/ElmerGUI/CMakeLists.txt 2026-01-03 06:09:27 +@@ -18,8 +18,8 @@ + + IF(WITH_QT5) + MESSAGE(STATUS "------------------------------------------------") +- IF(WIN32) +- MESSAGE(STATUS "Qt5 Windows packaging") ++ IF(WIN32 OR APPLE) ++ MESSAGE(STATUS "Qt5 Windows/MacOS packaging") + SET(QT5_PKG_LIST Qt5OpenGL Qt5Xml Qt5Script Qt5Gui Qt5Core Qt5Svg Qt5Widgets Qt5PrintSupport) + ELSE() + MESSAGE(STATUS "Qt5 non-Windows packaging") + +--- a/ElmerGUI/Application/CMakeLists.txt 2020-11-10 19:52:44 ++++ b/ElmerGUI/Application/CMakeLists.txt 2026-01-03 06:20:05 +@@ -189,6 +189,7 @@ + ENDIF() + + IF(WITH_QT5) ++ FIND_PACKAGE(Qt5 COMPONENTS Widgets REQUIRED) + QT5_WRAP_UI(UI_HEADERS ${FORMS}) + QT5_ADD_RESOURCES(UI_RESOURCES ElmerGUI.qrc) + ADD_DEFINITIONS(-DWITH_QT5) From e1dac84179c9565b6b575b593ddf24c5559375e9 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Sun, 21 Jun 2026 00:10:48 -0600 Subject: [PATCH 02/12] Update stable to release-26.2 Bump the stable build from release-9.0 to release-26.2: - Update url/sha256 to the release-26.2 tarball. - Drop the six commit-based patches; all are merged upstream into 26.2 (each commit is an ancestor of the tag) and would now fail to apply. - Drop the __END__ DATA patch; its targets no longer exist in 26.2 (the hard-coded /usr/local/bin compiler block is gone and the OpenMP FIND_PACKAGE/SET ordering is already correct upstream). - Use the current "gcc" dependency for stable instead of the release-9.0-era "gcc@11" pin, so the build uses the gfortran that the "gcc" dependency actually provides. Verified: stable (26.2) and HEAD both configure, build, and run (ElmerSolver reports v26.2). Co-Authored-By: Claude Opus 4.8 (1M context) --- elmer.rb | 115 ++----------------------------------------------------- 1 file changed, 3 insertions(+), 112 deletions(-) diff --git a/elmer.rb b/elmer.rb index b043133..09ef287 100644 --- a/elmer.rb +++ b/elmer.rb @@ -5,50 +5,14 @@ class Elmer < Formula head "https://github.com/ElmerCSC/elmerfem.git", branch: "devel" stable do - url "https://github.com/ElmerCSC/elmerfem/archive/refs/tags/release-9.0.tar.gz" - sha256 "08c5bf261e87ff37456c1aa0372db3c83efabe4473ea3ea0b8ec66f5944d1aa0" + url "https://github.com/ElmerCSC/elmerfem/archive/refs/tags/release-26.2.tar.gz" + sha256 "def442937d69234f7e1b36e902a7fcd2a428d671e62f0275bf05aeef7ebbcade" # CMake 3.19 for compatibility with old CHECK_TYPE_SIZE syntax resource "cmake" do url "https://github.com/Kitware/CMake/releases/download/v3.19.8/cmake-3.19.8-macos-universal.tar.gz" sha256 "0976d23d982af05dcbfb3aa34fcb62ead43bea27f0e3bb95222f2a78161423f2" end - - # Fix Qwt 6.2 deprecation - patch do - url "https://github.com/ElmerCSC/elmerfem/commit/48e9430ccb858ca5bda28b967a0c84b51e2404b2.patch?full_index=1" - sha256 "707032d1f899dacc62ffd7c6f09aff6aaa22d6eaa353b707808bef639d774398" - end - - # Fix Qt5 compile issue - patch do - url "https://github.com/ElmerCSC/elmerfem/commit/e057b0d46a6d1708a0d322bc73d70594a63de447.patch?full_index=1" - sha256 "0abf3d771b720edd3dc27a4b0115f12e325381284b1162568dbbc780c76cf934" - end - - # Fix DCRComplexSolve.F90 issue - patch do - url "https://github.com/ElmerCSC/elmerfem/commit/a28b3521f3c81bd7fe7176555815ffd1d35cf4b2.patch?full_index=1" - sha256 "ae29e1089fa009345c941fdf11ed346bd21a776874b70f9d2bf393b4bd3e1e71" - end - - patch do - url "https://github.com/ElmerCSC/elmerfem/commit/96a33930ee23e785f33bcb257398f1ccca8fdf99.patch?full_index=1" - sha256 "7935cd13ec54afe84de3ac2c3d3b676110f9926092abcfd414f913311920c09b" - end - - patch do - url "https://github.com/ElmerCSC/elmerfem/commit/8f9f2c703b020dc6d21cbaa1cb8b05abbbd7ded1.patch?full_index=1" - sha256 "4372532a4bc792e4d43466c813f1962c6964389abaa62f545a311a49bda76676" - end - - patch do - url "https://github.com/ElmerCSC/elmerfem/commit/54fd87054f687305644b92d0525a3f0cd4423a93.patch?full_index=1" - sha256 "ea8c5e85230d5e6a08dc04cb2e23161bca19940b9f8c092777586dcfa491dedc" - end - - # Comment out hard-coded C/C++ compiler paths - patch :DATA end # ============================================================================= @@ -101,7 +65,7 @@ def install end # Compiler configuration - gcc_formula_str = build.stable? ? "gcc@11" : "gcc" + gcc_formula_str = "gcc" gcc_formula = Formula[gcc_formula_str] gcc_version = gcc_formula.version.major use_gcc = build.with?("gcc") @@ -387,76 +351,3 @@ def caveats system bin/"ElmerSolver", "test.sif" end end - -__END__ ---- a/CMakeLists.txt 2020-11-10 19:52:44 -+++ b/CMakeLists.txt 2025-12-31 06:18:57 -@@ -14,9 +14,9 @@ - # message("you need to have gcc-gfrotran installed using HomeBrew") - # set(CMAKE_C_COMPILER "/usr/bin/gcc") - # set(CMAKE_CXX_COMPILER "/usr/bin/g++") -- set(CMAKE_C_COMPILER "/usr/local/bin/gcc-10") -- set(CMAKE_CXX_COMPILER "/usr/local/bin/g++-10") -- set(CMAKE_Fortran_COMPILER "/usr/local/bin/gfortran") -+ # set(CMAKE_C_COMPILER "/usr/local/bin/gcc-10") -+ # set(CMAKE_CXX_COMPILER "/usr/local/bin/g++-10") -+ # set(CMAKE_Fortran_COMPILER "/usr/local/bin/gfortran") - # set(BLA_VENDOR "OpenBLAS") - # option(HUNTER_ENABLED "Enable Hunter package manager support" OFF) - # set (CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE) -@@ -178,13 +178,6 @@ - ENDIF() - - IF(WITH_OpenMP) -- # Advanced properties -- MARK_AS_ADVANCED( -- OpenMP_C_FLAGS -- OpenMP_Fortran_FLAGS -- OpenMP_CXX_FLAGS -- ) -- - # Add OpenMP flags to compilation flags - # if(APPLE) - # if(CMAKE_C_COMPILER_ID STREQUAL "GNU") -@@ -204,12 +197,13 @@ - # set(OpenMP_libiomp5_LIBRARY ${OpenMP_CXX_LIB_NAMES}) - # endif() - # else() -- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") -- SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}") -- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - # endif() - - FIND_PACKAGE(OpenMP REQUIRED) -+ -+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") -+ SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}") -+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - - # Test compiler support for OpenMP 4.0 features used - INCLUDE(testOpenMP40) - ---- a/ElmerGUI/CMakeLists.txt 2020-11-10 19:52:44 -+++ b/ElmerGUI/CMakeLists.txt 2026-01-03 06:09:27 -@@ -18,8 +18,8 @@ - - IF(WITH_QT5) - MESSAGE(STATUS "------------------------------------------------") -- IF(WIN32) -- MESSAGE(STATUS "Qt5 Windows packaging") -+ IF(WIN32 OR APPLE) -+ MESSAGE(STATUS "Qt5 Windows/MacOS packaging") - SET(QT5_PKG_LIST Qt5OpenGL Qt5Xml Qt5Script Qt5Gui Qt5Core Qt5Svg Qt5Widgets Qt5PrintSupport) - ELSE() - MESSAGE(STATUS "Qt5 non-Windows packaging") - ---- a/ElmerGUI/Application/CMakeLists.txt 2020-11-10 19:52:44 -+++ b/ElmerGUI/Application/CMakeLists.txt 2026-01-03 06:20:05 -@@ -189,6 +189,7 @@ - ENDIF() - - IF(WITH_QT5) -+ FIND_PACKAGE(Qt5 COMPONENTS Widgets REQUIRED) - QT5_WRAP_UI(UI_HEADERS ${FORMS}) - QT5_ADD_RESOURCES(UI_RESOURCES ElmerGUI.qrc) - ADD_DEFINITIONS(-DWITH_QT5) From 9d24563f7a6900a24edc50e580e15177512d3cf6 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Wed, 24 Jun 2026 00:37:09 -0600 Subject: [PATCH 03/12] implement suggestions --- elmer.rb | 48 +++++++++--------------------------------------- 1 file changed, 9 insertions(+), 39 deletions(-) diff --git a/elmer.rb b/elmer.rb index 09ef287..fa78831 100644 --- a/elmer.rb +++ b/elmer.rb @@ -7,12 +7,6 @@ class Elmer < Formula stable do url "https://github.com/ElmerCSC/elmerfem/archive/refs/tags/release-26.2.tar.gz" sha256 "def442937d69234f7e1b36e902a7fcd2a428d671e62f0275bf05aeef7ebbcade" - - # CMake 3.19 for compatibility with old CHECK_TYPE_SIZE syntax - resource "cmake" do - url "https://github.com/Kitware/CMake/releases/download/v3.19.8/cmake-3.19.8-macos-universal.tar.gz" - sha256 "0976d23d982af05dcbfb3aa34fcb62ead43bea27f0e3bb95222f2a78161423f2" - end end # ============================================================================= @@ -53,16 +47,8 @@ class Elmer < Formula def install # Determine CMake binary - if build.stable? - resource("cmake").stage do - (buildpath/"local_cmake").install "CMake.app/Contents" - end - cmake_bin = buildpath/"local_cmake/Contents/bin/cmake" - ctest_bin = buildpath/"local_cmake/Contents/bin/ctest" - else - cmake_bin = Formula["cmake"].opt_bin/"cmake" - ctest_bin = Formula["cmake"].opt_bin/"ctest" - end + cmake_bin = Formula["cmake"].opt_bin/"cmake" + ctest_bin = Formula["cmake"].opt_bin/"ctest" # Compiler configuration gcc_formula_str = "gcc" @@ -166,7 +152,7 @@ def install cmake_args << "-DCMAKE_CXX_FLAGS=#{cxx_flags}" # Apply GCC/Qt compatibility patch if needed - if build.head? && use_gcc && build.with?("elmergui") + if use_gcc && build.with?("elmergui") apply_gcc_qt6_patch end @@ -189,27 +175,11 @@ def configure_elmergui(cmake_args) qt_version = qt_formula.version.major.to_i qwt_dep ="qwt" - if build.head? && qt_version >= 6 - cmake_args << "-DWITH_QT6=ON" - qt_lib = Formula["qtbase"].opt_lib - cmake_args << "-DQt6_DIR=#{qt_lib}/cmake/Qt6" - %w[Xml PrintSupport OpenGL OpenGLWidgets].each do |mod| - cmake_args << "-DQt6#{mod}_DIR=#{qt_lib}/cmake/Qt6#{mod}" - end - else - # stable build needs Qt5 - qt5_dep = "qt@5" - qwt_dep ="qwt-qt5" - - qt5_installed = Formula[qt5_dep].any_version_installed? - qwt_installed = Formula[qwt_dep].any_version_installed? - - dep_message = ->(p) { "ElmerGUI requires #{p}. To install: brew install #{p}" } - odie dep_message.call(qt5_dep) unless qt5_installed - odie dep_message.call(qwt_dep) unless qwt_installed - - cmake_args << "-DWITH_QT5=ON" - cmake_args << "-DQt5_DIR=#{Formula[qt5_dep].opt_lib}/cmake/Qt5" + cmake_args << "-DWITH_QT6=ON" + qt_lib = Formula["qtbase"].opt_lib + cmake_args << "-DQt6_DIR=#{qt_lib}/cmake/Qt6" + %w[Xml PrintSupport OpenGL OpenGLWidgets].each do |mod| + cmake_args << "-DQt6#{mod}_DIR=#{qt_lib}/cmake/Qt6#{mod}" end # Qwt configuration @@ -245,7 +215,7 @@ def apply_gcc_qt6_patch end def caveats - return if build.without?("elmergui") || build.stable? + return if build.without?("elmergui") <<~EOS If ElmerGUI fails to run with the following error message: From c60b5a2079b5ca1ef149a3f8d9667a4add96a0f0 Mon Sep 17 00:00:00 2001 From: kdunn926 Date: Thu, 2 Jul 2026 23:32:36 -0600 Subject: [PATCH 04/12] Update elmer.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR suggestion Co-authored-by: Markus Mützel --- elmer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elmer.rb b/elmer.rb index fa78831..8a2e656 100644 --- a/elmer.rb +++ b/elmer.rb @@ -85,7 +85,7 @@ def install # Compiler flags c_flags = "#{sys_root} -Wno-error=implicit-function-declaration -Wno-implicit-function-declaration" cxx_flags = sys_root - cxx_flags += " -Wno-deprecated-declarations" if build.head? && use_gcc + cxx_flags += " -Wno-deprecated-declarations" if use_gcc # ============================================================================= # CMake Arguments From 7794a30f82bdaf3ca327213e8fcdf900c468f264 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Sat, 11 Jul 2026 18:49:42 -0600 Subject: [PATCH 05/12] remove obsolete patches/flags, add accelerate option --- elmer.rb | 44 +++++++++----------------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/elmer.rb b/elmer.rb index 8a2e656..7969ca5 100644 --- a/elmer.rb +++ b/elmer.rb @@ -12,6 +12,7 @@ class Elmer < Formula # ============================================================================= # Build Options # ============================================================================= + option "with-accelerate", "Build with Apple Accelerate support" option "with-elmerice", "Build ElmerIce glaciology module" option "with-elmergui", "Build ElmerGUI graphical interface" option "with-gcc", "Use GCC instead of Clang for C/C++ compilation" @@ -105,9 +106,14 @@ def install cmake_args << "-DCMAKE_Fortran_COMPILER=#{gcc_formula.opt_bin}/gfortran-#{gcc_version}" # Linear algebra - blas_lib = Formula["openblas"].opt_lib/shared_library("libopenblas") - cmake_args << "-DBLAS_LIBRARIES:STRING=#{blas_lib};-lpthread" - cmake_args << "-DLAPACK_LIBRARIES:STRING=#{blas_lib};-lpthread" + if build.with?("accelerate") + cmake_args << "-DBLAS_LIBRARIES:STRING=-framework Accelerate" + cmake_args << "-DLAPACK_LIBRARIES:STRING=-framework Accelerate" + else + blas_lib = Formula["openblas"].opt_lib/shared_library("libopenblas") + cmake_args << "-DBLAS_LIBRARIES:STRING=#{blas_lib};-lpthread" + cmake_args << "-DLAPACK_LIBRARIES:STRING=#{blas_lib};-lpthread" + end # Optional solver features cmake_args << "-DWITH_ElmerIce=ON" if build.with?("elmerice") @@ -132,12 +138,6 @@ def install ENV.append "LDFLAGS", "-L#{libomp.opt_lib} -lomp" c_flags += " -I#{libomp.opt_include}" cxx_flags += " -I#{libomp.opt_include}" - - if build.stable? - cmake_args << "-DOpenMP_C_FLAGS=-Xpreprocessor -fopenmp" - cmake_args << "-DOpenMP_CXX_FLAGS=-Xpreprocessor -fopenmp" - cmake_args << "-DOpenMP_Fortran_FLAGS=-fopenmp" - end end end @@ -151,11 +151,6 @@ def install cmake_args << "-DCMAKE_C_FLAGS=#{c_flags}" cmake_args << "-DCMAKE_CXX_FLAGS=#{cxx_flags}" - # Apply GCC/Qt compatibility patch if needed - if use_gcc && build.with?("elmergui") - apply_gcc_qt6_patch - end - cmake_args << "-DBUILD_TESTING=1" if build.with?("testing") # Build and install @@ -193,27 +188,6 @@ def configure_elmergui(cmake_args) cmake_args << "-DWITH_VTK=#{build.with?("vtk") ? "ON" : "OFF"}" end - def apply_gcc_qt6_patch - patch_content = <<~PATCH - --- ElmerGUI/CMakeLists.txt - +++ ElmerGUI/CMakeLists.txt - @@ -35,6 +35,10 @@ - FOREACH(_pkg ${QT6_PKG_LIST}) - FIND_PACKAGE(${_pkg} PATHS ${QT6_PATH} REQUIRED) - ENDFOREACH() - + - + IF(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D'QT_IGNORE_DEPRECATIONS\\(x\\)=x'") - + ENDIF() - - ADD_DEFINITIONS(-DWITH_QT6) - MESSAGE(STATUS " [ElmerGUI] Qt6: " ${Qt6_FOUND}) - PATCH - - (buildpath/"qt-gcc.patch").write(patch_content) - system "patch", "-p0", "-i", "qt-gcc.patch" - end - def caveats return if build.without?("elmergui") From db09b49539d8249a0ef9b412af24eefd0101abc4 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Sat, 11 Jul 2026 22:51:52 -0600 Subject: [PATCH 06/12] Build ElmerGUI with GCC via Qt5; fix stable+GCC SDK - configure_elmergui: use Qt5 (qt@5/qwt-qt5) for --with-gcc, Qt6 for Clang. Homebrew's Qt6 is Clang/libc++ and exports std::-typed APIs (e.g. QDir::mkdir(std::optional<...>)) only with libc++ mangling, which GCC/libstdc++ can't link; Qt5's API doesn't cross that ABI boundary. - Set each Qt5 component _DIR (qt@5 is keg-only) and add Qt5Widgets to ElmerGUI's macOS Qt5 package list via inreplace. - Drop the forced older-SDK selection for stable+GCC; Homebrew GCC 16 can't parse MacOSX14.sdk headers, so use the current SDK. --- elmer.rb | 59 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/elmer.rb b/elmer.rb index 7969ca5..d28e1e5 100644 --- a/elmer.rb +++ b/elmer.rb @@ -68,16 +68,8 @@ def install # Build sysroot flags sys_root = use_gcc ? "--sysroot=#{sdk_path}" : "-isysroot #{sdk_path}" - # For stable builds with GCC, try to find an older SDK if available + # For stable builds with GCC, ensure the compiler is available if build.stable? && use_gcc - older_sdk = Dir["/Library/Developer/CommandLineTools/SDKs/MacOSX1[0-4].sdk"].max - if older_sdk - sys_root = "--sysroot=#{older_sdk}" - sdk_path = older_sdk - else - opoo "No older macOS SDK found; GCC build may have compatibility issues" - end - unless gcc_formula.any_version_installed? odie "Elmer version requires #{gcc_formula_str}. Run: brew install #{gcc_formula_str}" end @@ -144,7 +136,8 @@ def install # ============================================================================= # ElmerGUI Configuration # ============================================================================= - configure_elmergui(cmake_args) if build.with?("elmergui") + configure_elmergui(cmake_args, use_gcc) if build.with?("elmergui") + # SDK and flags cmake_args << "-DCMAKE_OSX_SYSROOT=#{sdk_path}" @@ -162,22 +155,46 @@ def install end end - def configure_elmergui(cmake_args) + def configure_elmergui(cmake_args, use_gcc) cmake_args << "-DWITH_ELMERGUI=ON" - # Qt version detection - qt_formula = Formula["qt"] - qt_version = qt_formula.version.major.to_i - qwt_dep ="qwt" + if use_gcc + # Homebrew's Qt6 is built with Clang/libc++ and exports APIs taking std:: types + # (e.g. QDir::mkdir(std::optional<...>)) only with libc++ mangling, which + # GCC/libstdc++ never emits -- so a GCC ElmerGUI cannot link against Qt6. Qt5's + # API surface does not cross that std:: ABI boundary, so GCC links Qt5 cleanly. + # This is how the branch built ElmerGUI with GCC prior to the Qt6-everywhere change. + qt5_dep = "qt@5" + qwt_dep = "qwt-qt5" + dep_message = ->(p) { "ElmerGUI with --with-gcc requires #{p}. To install: brew install #{p}" } + odie dep_message.call(qt5_dep) unless Formula[qt5_dep].any_version_installed? + odie dep_message.call(qwt_dep) unless Formula[qwt_dep].any_version_installed? + + cmake_args << "-DWITH_QT5=ON" + qt5_lib = Formula[qt5_dep].opt_lib + cmake_args << "-DQt5_DIR=#{qt5_lib}/cmake/Qt5" + # ElmerGUI FIND_PACKAGEs each Qt5 component; qt@5 is keg-only so point each + # component at its config dir explicitly (mirrors the Qt6 branch below). + %w[Core Gui Widgets OpenGL Xml Svg PrintSupport Script].each do |mod| + cmake_args << "-DQt5#{mod}_DIR=#{qt5_lib}/cmake/Qt5#{mod}" + end - cmake_args << "-DWITH_QT6=ON" - qt_lib = Formula["qtbase"].opt_lib - cmake_args << "-DQt6_DIR=#{qt_lib}/cmake/Qt6" - %w[Xml PrintSupport OpenGL OpenGLWidgets].each do |mod| - cmake_args << "-DQt6#{mod}_DIR=#{qt_lib}/cmake/Qt6#{mod}" + # ElmerGUI's Qt5 package list only includes Qt5Widgets on WIN32; on macOS it is + # omitted, but the Application needs it (QT5_WRAP_UI). Add it to the list. + inreplace "ElmerGUI/CMakeLists.txt", + "SET(QT5_PKG_LIST Qt5OpenGL Qt5Xml Qt5Script Qt5Gui Qt5Core Qt5Svg Qt5PrintSupport)", + "SET(QT5_PKG_LIST Qt5OpenGL Qt5Xml Qt5Script Qt5Gui Qt5Core Qt5Svg Qt5Widgets Qt5PrintSupport)" + else + qwt_dep = "qwt" + cmake_args << "-DWITH_QT6=ON" + qt_lib = Formula["qtbase"].opt_lib + cmake_args << "-DQt6_DIR=#{qt_lib}/cmake/Qt6" + %w[Xml PrintSupport OpenGL OpenGLWidgets].each do |mod| + cmake_args << "-DQt6#{mod}_DIR=#{qt_lib}/cmake/Qt6#{mod}" + end end - # Qwt configuration + # Qwt configuration (qwt for Qt6, qwt-qt5 for Qt5) qwt_formula = Formula[qwt_dep] cmake_args << "-DWITH_QWT=ON" cmake_args << "-DQWT_INCLUDE_DIR=#{qwt_formula.opt_lib}/qwt.framework/Headers" From 0a2db427d6bfb17744d337a516683e939263b735 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Tue, 14 Jul 2026 00:05:34 -0600 Subject: [PATCH 07/12] Make --with-testing non-fatal and add --output-on-failure Run the quick test suite in a begin/rescue so test failures report a warning but do not abort the install; a fully-built keg is always produced. Add --output-on-failure so failing cases are diagnosable in the build log. --- elmer.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/elmer.rb b/elmer.rb index d28e1e5..0b64139 100644 --- a/elmer.rb +++ b/elmer.rb @@ -150,8 +150,20 @@ def install system cmake_bin, "-S", ".", "-B", "build", *cmake_args system cmake_bin, "--build", "build", "--parallel" system cmake_bin, "--install", "build" - Dir.chdir("build") do - system ctest_bin, ".", "-L", "quick" if build.with?("testing") + + # Optionally run the upstream "quick" test suite. Failures are reported but + # do NOT abort the install, so a fully-built keg is always produced. The + # suite drives the build-tree ElmerSolver (via mpiexec when MPI is enabled), + # so a broken host MPI or a single flaky case should not discard the build. + if build.with?("testing") + Dir.chdir("build") do + ohai "Running quick test suite (ctest -L quick)" + begin + system ctest_bin, ".", "-L", "quick", "--output-on-failure" + rescue BuildError + opoo "Some quick tests failed (see output above); installation continues." + end + end end end From ae733887975446373099ad7af409647ad6ef1f39 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Tue, 14 Jul 2026 00:42:32 -0600 Subject: [PATCH 08/12] Fix Accelerate complex-BLAS crashes with -ff2c Apple's legacy Accelerate BLAS returns complex-valued results (ZDOTC, ZDOTU, CDOTC, CDOTU) via a hidden first argument (f2c convention), while gfortran's default ABI returns them in registers. Elmer's complex iterative/harmonic/eigen solvers that call these BLAS functions directly therefore crashed inside libBLAS ZDOTC (e.g. complex BiCGStab(l)) or produced wrong norms, failing 7 of the 427 quick tests under Accelerate. Compile the Fortran sources with -ff2c so gfortran uses the matching convention, paired with -fno-second-underscore to undo the implied -fsecond-underscore (which would rename symbols like zdotc__ and break linking against Accelerate and libgomp). With this, the full quick suite passes 427/427 under Accelerate, matching the OpenBLAS result. --- elmer.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/elmer.rb b/elmer.rb index 0b64139..8a3a207 100644 --- a/elmer.rb +++ b/elmer.rb @@ -79,6 +79,7 @@ def install c_flags = "#{sys_root} -Wno-error=implicit-function-declaration -Wno-implicit-function-declaration" cxx_flags = sys_root cxx_flags += " -Wno-deprecated-declarations" if use_gcc + fortran_flags = "" # ============================================================================= # CMake Arguments @@ -101,6 +102,17 @@ def install if build.with?("accelerate") cmake_args << "-DBLAS_LIBRARIES:STRING=-framework Accelerate" cmake_args << "-DLAPACK_LIBRARIES:STRING=-framework Accelerate" + # Apple's legacy Accelerate BLAS uses the f2c calling convention for + # complex-valued functions: ZDOTC/ZDOTU/CDOTC/CDOTU return their result + # via a hidden first argument rather than in registers. gfortran's default + # ABI returns complex in registers, so Elmer's complex solvers that call + # these directly (e.g. complex BiCGStab(l), harmonic/eigen EM solvers) + # crash inside libBLAS ZDOTC or get wrong results. Building the Fortran + # sources with -ff2c switches gfortran to the matching convention. + # -ff2c implies -fsecond-underscore (which would rename symbols to e.g. + # zdotc__ and break linking against Accelerate and libgomp), so pair it + # with -fno-second-underscore to keep the standard single-underscore names. + fortran_flags += " -ff2c -fno-second-underscore" else blas_lib = Formula["openblas"].opt_lib/shared_library("libopenblas") cmake_args << "-DBLAS_LIBRARIES:STRING=#{blas_lib};-lpthread" @@ -143,6 +155,7 @@ def install cmake_args << "-DCMAKE_OSX_SYSROOT=#{sdk_path}" cmake_args << "-DCMAKE_C_FLAGS=#{c_flags}" cmake_args << "-DCMAKE_CXX_FLAGS=#{cxx_flags}" + cmake_args << "-DCMAKE_Fortran_FLAGS=#{fortran_flags.strip}" unless fortran_flags.strip.empty? cmake_args << "-DBUILD_TESTING=1" if build.with?("testing") From b2f9b39303aa1ba49e95a54326fef5b30060c081 Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Tue, 14 Jul 2026 03:53:03 -0600 Subject: [PATCH 09/12] Wire MUMPS via brewsci/num tap; document HYPRE test limitation MUMPS is no longer in homebrew-core, so --with-mumps now pulls brewsci/num/brewsci-mumps and configure_mumps points Elmer's finders at the MUMPS, ScaLAPACK, ParMetis and Metis kegs (metis.h lives in brewsci-metis). With this, --with-mumps builds and the full quick suite passes 435/435 (8 mumps tests added). HYPRE is left on the default keg. The 3 mgdyn_airgap2 tests (HYPRE BiCGStab + BoomerAMG block preconditioning) abort with MPI_ABORT under both HYPRE 2.33.0 and 3.1.0 and under both Accelerate and OpenBLAS, so that is an upstream Elmer/HYPRE issue rather than a build-configuration one; a version pin does not help and only adds fragility. --- elmer.rb | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/elmer.rb b/elmer.rb index 8a3a207..99c65f0 100644 --- a/elmer.rb +++ b/elmer.rb @@ -16,6 +16,7 @@ class Elmer < Formula option "with-elmerice", "Build ElmerIce glaciology module" option "with-elmergui", "Build ElmerGUI graphical interface" option "with-gcc", "Use GCC instead of Clang for C/C++ compilation" + option "with-mumps", "Build with the MUMPS sparse direct solver (requires the brewsci/num tap)" option "with-openmp", "Build with OpenMP support" option "with-testing", "Run the quick tests after build" @@ -34,7 +35,9 @@ class Elmer < Formula # Optional: Solver libraries depends_on "hypre" => :optional - depends_on "mumps" => :optional + # MUMPS is no longer in homebrew-core; it lives in the brewsci/num tap. Pull it + # in only when requested so the formula still loads without that tap tapped. + depends_on "brewsci/num/brewsci-mumps" if build.with?("mumps") # Optional: Parallelization depends_on "libomp" => :optional @@ -121,8 +124,15 @@ def install # Optional solver features cmake_args << "-DWITH_ElmerIce=ON" if build.with?("elmerice") + + # NOTE: the 3 mgdyn_airgap2 tests (HYPRE BiCGStab + BoomerAMG block + # preconditioning) abort with MPI_ABORT/Errorcode -1. This reproduces with + # both HYPRE 2.33.0 and 3.1.0 and with either Accelerate or OpenBLAS, so it + # is an upstream Elmer/HYPRE issue, not a build-configuration problem. cmake_args << "-DWITH_Hypre=ON" if build.with?("hypre") - cmake_args << "-DWITH_Mumps=ON" if build.with?("mumps") + + configure_mumps(cmake_args) if build.with?("mumps") + cmake_args << "-DWITH_MPI=#{build.with?("open-mpi") ? "ON" : "OFF"}" # OpenMP configuration @@ -180,6 +190,18 @@ def install end end + def configure_mumps(cmake_args) + cmake_args << "-DWITH_Mumps=ON" + cmake_args << "-DMUMPS_ROOT=#{Formula["brewsci/num/brewsci-mumps"].opt_prefix}" + # brewsci-mumps is built with ScaLAPACK ordering plus (Par)Metis, so Elmer's + # FindMumps also requires ScaLAPACK, ParMetis and Metis. Point each finder at + # the right keg through the *_ROOT environment hints they consult. Note metis.h + # lives in brewsci-metis (not brewsci-parmetis), so METIS_ROOT is set separately. + ENV["SCALAPACK_ROOT"] = Formula["scalapack"].opt_prefix.to_s + ENV["PARMETIS_ROOT"] = Formula["brewsci/num/brewsci-parmetis"].opt_prefix.to_s + ENV["METIS_ROOT"] = Formula["brewsci/num/brewsci-metis"].opt_prefix.to_s + end + def configure_elmergui(cmake_args, use_gcc) cmake_args << "-DWITH_ELMERGUI=ON" From b07753ade88e9cbe458de53622b6e705bbc6283b Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Sun, 2 Aug 2026 23:23:13 -0600 Subject: [PATCH 10/12] revert apple accelerate option for now --- elmer.rb | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/elmer.rb b/elmer.rb index 99c65f0..798e21a 100644 --- a/elmer.rb +++ b/elmer.rb @@ -12,7 +12,6 @@ class Elmer < Formula # ============================================================================= # Build Options # ============================================================================= - option "with-accelerate", "Build with Apple Accelerate support" option "with-elmerice", "Build ElmerIce glaciology module" option "with-elmergui", "Build ElmerGUI graphical interface" option "with-gcc", "Use GCC instead of Clang for C/C++ compilation" @@ -102,25 +101,9 @@ def install cmake_args << "-DCMAKE_Fortran_COMPILER=#{gcc_formula.opt_bin}/gfortran-#{gcc_version}" # Linear algebra - if build.with?("accelerate") - cmake_args << "-DBLAS_LIBRARIES:STRING=-framework Accelerate" - cmake_args << "-DLAPACK_LIBRARIES:STRING=-framework Accelerate" - # Apple's legacy Accelerate BLAS uses the f2c calling convention for - # complex-valued functions: ZDOTC/ZDOTU/CDOTC/CDOTU return their result - # via a hidden first argument rather than in registers. gfortran's default - # ABI returns complex in registers, so Elmer's complex solvers that call - # these directly (e.g. complex BiCGStab(l), harmonic/eigen EM solvers) - # crash inside libBLAS ZDOTC or get wrong results. Building the Fortran - # sources with -ff2c switches gfortran to the matching convention. - # -ff2c implies -fsecond-underscore (which would rename symbols to e.g. - # zdotc__ and break linking against Accelerate and libgomp), so pair it - # with -fno-second-underscore to keep the standard single-underscore names. - fortran_flags += " -ff2c -fno-second-underscore" - else - blas_lib = Formula["openblas"].opt_lib/shared_library("libopenblas") - cmake_args << "-DBLAS_LIBRARIES:STRING=#{blas_lib};-lpthread" - cmake_args << "-DLAPACK_LIBRARIES:STRING=#{blas_lib};-lpthread" - end + blas_lib = Formula["openblas"].opt_lib/shared_library("libopenblas") + cmake_args << "-DBLAS_LIBRARIES:STRING=#{blas_lib};-lpthread" + cmake_args << "-DLAPACK_LIBRARIES:STRING=#{blas_lib};-lpthread" # Optional solver features cmake_args << "-DWITH_ElmerIce=ON" if build.with?("elmerice") From 25f2f391c4061021c6803e8db12f71eb6b2aecf8 Mon Sep 17 00:00:00 2001 From: kdunn926 Date: Mon, 3 Aug 2026 16:19:39 -0600 Subject: [PATCH 11/12] Apply suggestion from @mmuetzel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Markus Mützel --- elmer.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/elmer.rb b/elmer.rb index 798e21a..3fe2c6e 100644 --- a/elmer.rb +++ b/elmer.rb @@ -70,11 +70,9 @@ def install # Build sysroot flags sys_root = use_gcc ? "--sysroot=#{sdk_path}" : "-isysroot #{sdk_path}" - # For stable builds with GCC, ensure the compiler is available - if build.stable? && use_gcc - unless gcc_formula.any_version_installed? - odie "Elmer version requires #{gcc_formula_str}. Run: brew install #{gcc_formula_str}" - end + # Ensure the compiler is available + unless gcc_formula.any_version_installed? + odie "Elmer version requires #{gcc_formula_str}. Run: brew install #{gcc_formula_str}" end # Compiler flags From 8b7f19e758b467eabfde1d08401143b29e9dda5c Mon Sep 17 00:00:00 2001 From: Kyle Dunn Date: Fri, 7 Aug 2026 16:57:43 -0600 Subject: [PATCH 12/12] apply `brew audit --strict` fixes --- elmer.rb | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/elmer.rb b/elmer.rb index 3fe2c6e..bd08858 100644 --- a/elmer.rb +++ b/elmer.rb @@ -2,12 +2,10 @@ class Elmer < Formula desc "Open source multiphysical simulation software (finite element solver)" homepage "https://elmerfem.org" - head "https://github.com/ElmerCSC/elmerfem.git", branch: "devel" + url "https://github.com/ElmerCSC/elmerfem/archive/refs/tags/release-26.2.tar.gz" + sha256 "def442937d69234f7e1b36e902a7fcd2a428d671e62f0275bf05aeef7ebbcade" - stable do - url "https://github.com/ElmerCSC/elmerfem/archive/refs/tags/release-26.2.tar.gz" - sha256 "def442937d69234f7e1b36e902a7fcd2a428d671e62f0275bf05aeef7ebbcade" - end + head "https://github.com/ElmerCSC/elmerfem.git", branch: "devel" # ============================================================================= # Build Options @@ -33,10 +31,10 @@ class Elmer < Formula depends_on "openblas" # Optional: Solver libraries - depends_on "hypre" => :optional # MUMPS is no longer in homebrew-core; it lives in the brewsci/num tap. Pull it # in only when requested so the formula still loads without that tap tapped. depends_on "brewsci/num/brewsci-mumps" if build.with?("mumps") + depends_on "hypre" => :optional # Optional: Parallelization depends_on "libomp" => :optional @@ -50,8 +48,8 @@ class Elmer < Formula def install # Determine CMake binary - cmake_bin = Formula["cmake"].opt_bin/"cmake" - ctest_bin = Formula["cmake"].opt_bin/"ctest" + cmake_bin = formula_opt_bin("cmake")/"cmake" + ctest_bin = formula_opt_bin("cmake")/"ctest" # Compiler configuration gcc_formula_str = "gcc" @@ -63,9 +61,7 @@ def install sdk_path = MacOS.sdk_path sdk_version = Utils.safe_popen_read("xcrun", "--show-sdk-version").strip - if build.head? && sdk_version < "15.5" - odie "Homebrew GCC requires macOS SDK 15.5 or newer (found #{sdk_version})" - end + odie "Homebrew GCC requires macOS SDK 15.5 or newer (found #{sdk_version})" if build.head? && sdk_version < "15.5" # Build sysroot flags sys_root = use_gcc ? "--sysroot=#{sdk_path}" : "-isysroot #{sdk_path}" @@ -99,7 +95,7 @@ def install cmake_args << "-DCMAKE_Fortran_COMPILER=#{gcc_formula.opt_bin}/gfortran-#{gcc_version}" # Linear algebra - blas_lib = Formula["openblas"].opt_lib/shared_library("libopenblas") + blas_lib = formula_opt_lib("openblas")/shared_library("libopenblas") cmake_args << "-DBLAS_LIBRARIES:STRING=#{blas_lib};-lpthread" cmake_args << "-DLAPACK_LIBRARIES:STRING=#{blas_lib};-lpthread" @@ -141,7 +137,6 @@ def install # ============================================================================= configure_elmergui(cmake_args, use_gcc) if build.with?("elmergui") - # SDK and flags cmake_args << "-DCMAKE_OSX_SYSROOT=#{sdk_path}" cmake_args << "-DCMAKE_C_FLAGS=#{c_flags}" @@ -173,14 +168,14 @@ def install def configure_mumps(cmake_args) cmake_args << "-DWITH_Mumps=ON" - cmake_args << "-DMUMPS_ROOT=#{Formula["brewsci/num/brewsci-mumps"].opt_prefix}" + cmake_args << "-DMUMPS_ROOT=#{formula_opt_prefix("brewsci/num/brewsci-mumps")}" # brewsci-mumps is built with ScaLAPACK ordering plus (Par)Metis, so Elmer's # FindMumps also requires ScaLAPACK, ParMetis and Metis. Point each finder at # the right keg through the *_ROOT environment hints they consult. Note metis.h # lives in brewsci-metis (not brewsci-parmetis), so METIS_ROOT is set separately. - ENV["SCALAPACK_ROOT"] = Formula["scalapack"].opt_prefix.to_s - ENV["PARMETIS_ROOT"] = Formula["brewsci/num/brewsci-parmetis"].opt_prefix.to_s - ENV["METIS_ROOT"] = Formula["brewsci/num/brewsci-metis"].opt_prefix.to_s + ENV["SCALAPACK_ROOT"] = formula_opt_prefix("scalapack").to_s + ENV["PARMETIS_ROOT"] = formula_opt_prefix("brewsci/num/brewsci-parmetis").to_s + ENV["METIS_ROOT"] = formula_opt_prefix("brewsci/num/brewsci-metis").to_s end def configure_elmergui(cmake_args, use_gcc) @@ -199,7 +194,7 @@ def configure_elmergui(cmake_args, use_gcc) odie dep_message.call(qwt_dep) unless Formula[qwt_dep].any_version_installed? cmake_args << "-DWITH_QT5=ON" - qt5_lib = Formula[qt5_dep].opt_lib + qt5_lib = formula_opt_lib(qt5_dep) cmake_args << "-DQt5_DIR=#{qt5_lib}/cmake/Qt5" # ElmerGUI FIND_PACKAGEs each Qt5 component; qt@5 is keg-only so point each # component at its config dir explicitly (mirrors the Qt6 branch below). @@ -215,7 +210,7 @@ def configure_elmergui(cmake_args, use_gcc) else qwt_dep = "qwt" cmake_args << "-DWITH_QT6=ON" - qt_lib = Formula["qtbase"].opt_lib + qt_lib = formula_opt_lib("qtbase") cmake_args << "-DQt6_DIR=#{qt_lib}/cmake/Qt6" %w[Xml PrintSupport OpenGL OpenGLWidgets].each do |mod| cmake_args << "-DQt6#{mod}_DIR=#{qt_lib}/cmake/Qt6#{mod}"