Fix formula - #17
Conversation
…UI), allow using GCC or Clang
|
@raback - I think this PR makes Elmer more accessible on macos (again). If testing is helpful I can also add a GitHub actions to this repo... |
|
Thank you very much for looking into this. 🙏 Maybe, you could take the opportunity and update the stable build to version 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) <noreply@anthropic.com>
|
@mmuetzel I updated it to version 26.2 and confirm both that version and head build on my mac |
mmuetzel
left a comment
There was a problem hiding this comment.
Thanks for updating to the latest release.
Can the parts about Qt5 be dropped with that now?
|
Thanks for reviewing this and offering suggestions. I think I address all the comments and I re-ran the build again locally to confirm everything is in order. |
|
The rules look good to me now. 👍 @raback: Ok to merge? |
Honestly, I'm not certain what the correct convention is. Even after reading the docs, it seems a bit vague. My understanding is that it is compile-time, rather than runtime. The formula is written to link the dependencies to the actual compilation flags. |
PR suggestion Co-authored-by: Markus Mützel <markus.muetzel@gmx.de>
| 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 |
There was a problem hiding this comment.
If adding the flag in the formula works (see other suggestion), you can probably get rid of this patch.
| 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 |
There was a problem hiding this comment.
Oops. Missed a couple of lines further down that should also be removed in that case.
I don't know how to change that now though...
There was a problem hiding this comment.
Thinking about the condition for which the patch is applied: Was it maybe only needed for (very?) old GCC versions?
Does it still fail to build without this patch with more or less recent versions of GCC?
If it fails, which error does that produce?
There was a problem hiding this comment.
In my testing, I found the patch (or your cleaner cxx_flags workaround) is needed even with gcc 16.1.0. That said, I could only get gcc to link against Qt5, not Qt6, which is at least one good reason to keep the Qt5 stuff in the formula around.
There was a problem hiding this comment.
Good point. 👍
Is defining that preprocessor macros only needed for GCC? Or does Qt5 also need it with Clang?
There was a problem hiding this comment.
Never mind.
The build rules here make clear that GCC selects Qt5 and Clang selects Qt6. So, the combination I asked for is never an option for the user.
More basically: Why is there even an option to build ElmerFEM with GCC on macOS? Is that preferable in some ways compared to using their "system" compiler Clang?
- 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.
When compiling ElmerGUI with gcc, it will only link against Qt5, not Qt6, which is at least one good reason to keep the Qt5 stuff in the formula around. |
| 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 |
There was a problem hiding this comment.
Nice! 👍
I didn't know how to correctly build with Apple Accelerate when putting together some build rules for the CI on macOS. Nice to see how it is done. (I hope I'll be able to recall that should it ever come up again.)
If I understand correctly, Apple Accelerate can outperform OpenBLAS on macOS for some workloads.
But I also seem to remember that its interface is somewhat odd (i.e., partly incompatible with gfortran) compared to other implementations of the BLAS/LAPACK libraries. (I seem to recall something about single precision floating point function return arguments being returned as double precision.)
Does the test suite still pass with Apple Accelerate? (Maybe, the affected functions aren't actually being used.)
(It might be worth adding that as a variant to the CI workflows.)
There was a problem hiding this comment.
I ran the "quick" test suite (formula flag --with-testing) and all of those pass when using Accelerate (after adding some extra fortran compatibility flags). I only recently learned it exists and was made aware the Elmer package in macports had it as an option, so I lifted that into this formula as well.
There was a problem hiding this comment.
That ABI incompatibility is tricky indeed.
I have a feeling that you would need to go "all-in" if you deviate from the default Fortran ABI and rebuild all Fortran dependencies using that ABI.
How does MacPorts handle that?
Edit: It looks like it doesn't handle that at all:
https://github.com/macports/macports-ports/blob/578383b5b39697d1002002afdf00af884377782f/science/elmerfem/Portfile#L59-L63
} elseif {[variant_isset accelerate]} {
configure.args-append \
-DBLAS_LIBRARIES="-framework Accelerate" \
-DLAPACK_LIBRARIES="-framework Accelerate"
}
Or are there other newer build rules somewhere else that you were comparing to?
There was a problem hiding this comment.
Alternatively, it might be possible to use a "BLAS shim" library (like FlexiBLAS).
I don't know how well that integrates into Homebrew though.
There was a problem hiding this comment.
Thinking about this, the only more or less "clean" way of using Accelerate given the ABI incompatibility is probably via FlexiBLAS. Homebrew apparently already has a package for it:
https://github.com/Homebrew/homebrew-core/blob/main/Formula/f/flexiblas.rb
Or don't bother with Apple Accelerate for the time being to get this PR over the finish line. A variant with it could also be added in a follow-up change.
There was a problem hiding this comment.
Another (potentially simpler) alternative for the --with-accelerate variant might be linking to vecLibFort instead of using the Accelerate framework directly:
https://formulae.brew.sh/formula/veclibfort
There was a problem hiding this comment.
I went ahead and opened a PR adapting the upstream CI to test with Apple Accelerate using the vecLibFort library as shim: ElmerCSC/elmerfem#841
The essential part is probably this:
${{ matrix.blas == 'accelerate'
&& '-DBLAS_LIBRARIES="${VECLIBFORT_PREFIX}/lib/libvecLibFort.dylib" \
-DLAPACK_LIBRARIES="${VECLIBFORT_PREFIX}/lib/libvecLibFort.dylib"' || '' }} \
It's probably possible to translate that to the Ruby recipe some way (if you'd like to use the same here).
With that, you shouldn't need to switch the Fortran ABI (with -ff2c). It should be working with the default ABI of gfortran.
There was a problem hiding this comment.
don't bother with Apple Accelerate for the time being
I'll drop this change for now and revisit later based on your suggestion for vecLibFort
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.
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.
| # 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" |
There was a problem hiding this comment.
Doesn't that mean that all other dependencies that use Fortran also need to be built using that ABI (e.g., MUMPS)? (Maybe, the same requirement would also hold for OpenMP and MPI.)
Should there be a conflict between --with-accelerate and --with-mumps (and potentially others)?
There was a problem hiding this comment.
Here is what I found when running the quick tests with mumps:
Config (both): --HEAD --with-elmergui --with-accelerate --with-openmp --with-open-mpi --with-mumps --with-testing
Platform: macOS 15.3.1 (arm64), Xcode CLT 16.4 · gfortran-16 · Apple Accelerate · MUMPS 5.3.5 (brewsci/num) · open-mpi 5.0.9
| Compiler | C/C++ | Fortran | GUI toolkit | BLAS/LAPACK | MUMPS | Quick tests | Test time |
|---|---|---|---|---|---|---|---|
| Clang | /usr/bin/clang(++) (libc++) |
gfortran-16 -ff2c |
Qt6 (qtbase) | Accelerate | 6 libs linked | 435 / 435 (100%) | 226.6 s |
| GCC | gcc-16 / g++-16 (libstdc++) | gfortran-16 -ff2c |
Qt5 (qt@5 + qwt-qt5) | Accelerate | 6 libs linked | 435 / 435 (100%) | 239.6 s |
Notes
- 435 tests = 427 base quick suite + 8 MUMPS-specific tests; 0 failures in either config.
-ff2c -fno-second-underscore(auto-applied on the Accelerate path) fixes Apple Accelerate's f2c complex-BLAS calling convention — required for the complex solvers to pass.- GCC path builds ElmerGUI against Qt5 (Qt6 headers don't link under libstdc++); Clang path uses Qt6.
- MUMPS wired via
brewsci/num/brewsci-mumpswithMUMPS_ROOT+SCALAPACK_ROOT+PARMETIS_ROOT+METIS_ROOThints. It also needs to be patched, as documented here - Left installed: Clang + Qt6 GUI + Accelerate + OpenMP + MPI + MUMPS.
Given the patch requirement (and stale brewsci repo), it may be better to error out that config option with a notice of the issue, in case someone wants to compile it manually to be used with Elmer.
There was a problem hiding this comment.
ElmerFEM allows "zmumps" (i.e., complex double-precision floating point) as the "Linear System Direct Method". But apparently, there is no test for it.
I bet, it would fail if you only build ElmerFEM with the f2c Fortran ABI (but not the Mumps libraries).
And even if it wouldn't fail, I still firmly believe that using a shim library for Apple Accelerate (instead of building parts with different Fortran ABIs) is the best way forward.
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.
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple tends to perform better on macOS for some workloads compared OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple tends to perform better on macOS for some workloads compared OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple tends to perform better on macOS for some workloads compared OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple tends to perform better on macOS for some workloads compared OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple tends to perform better on macOS for some workloads compared OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple tends to perform better on macOS for some workloads compared OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple might perform better on macOS for some workloads compared to OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
| # 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)" |
There was a problem hiding this comment.
Not a blocker for this change: It might make sense to fix that upstream in the elmerfem repository.
|
Thanks for your continuous work on this. This looks mostly good to me now (bar the condition for the check for |
|
Mutzel,I’m interest in giving Elmer a try on my Mac. I have Brew as my installer but is there a binary available?SteveSent from Steve's iPhoneM🍑47On Aug 3, 2026, at 2:17 AM, Markus Mützel ***@***.***> wrote:mmuetzel left a comment (ElmerCSC/homebrew-elmerfem#17)
Thanks for your continuous work on this.
This looks mostly good to me now (bar the condition for the check for gfortran).
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Co-authored-by: Markus Mützel <markus.muetzel@gmx.de>
I'm not aware of binary distributions of Elmer for macOS. Maybe, the updated recipe here can serve as a template to try and get a recipe into Homebrew core. @kdunn926: Would you be interested in selecting one of the configuration options of this recipe and upstreaming it to Homebrew? |
I looked into this a bit. I did the first step of running the |
|
Will they need a license for the recipe itself? Or a "field" with the license of the packaged software? I'm not a maintainer of Elmer. I'm just another contributor who is trying to help out here or there if I can. Edit: Replaced link to license in my fork with a link to the upstream repository. |
Add a configuration to the build matrix for the workflow running on macOS that uses Apple Accelerate as the implementation of the BLAS and LAPACK libraries (using the vecLibFort library as a shim for ABI compatibility with gfortran). The implementation from Apple might perform better on macOS for some workloads compared to OpenBLAS. This came up while reviewing the Homebrew recipe for ElmerFEM: ElmerCSC/homebrew-elmerfem#17
|
Maybe, we should move the discussion about potentially upstreaming a variant of this formula to Homebrew to a new issue. |
Refactored to work on modern macOS, ensure
develbranch builds (with ElmerGUI), allow using GCC or ClangAll tests for both
develandrelease-9.0are passing in Clang (default) and GCC builds on Apple Silicon in MacOS 15.3.1.