Skip to content

Build DFTFringe on macOS and publish DMGs from CI - #348

Open
Lucassifoni wants to merge 12 commits into
githubdoe:masterfrom
Lucassifoni:macos-build
Open

Build DFTFringe on macOS and publish DMGs from CI#348
Lucassifoni wants to merge 12 commits into
githubdoe:masterfrom
Lucassifoni:macos-build

Conversation

@Lucassifoni

Copy link
Copy Markdown
Contributor

Note : this was done by Opus 5, picking up Dan's work in 75d9cc6. I'm happy to work and help as long as needed on it but will be AI-assisted since QT isn't my cup of tea.

---- BEGIN AI-assisted summary ----

Problems since the 2023 Mac build :

  • pkg-config names were opencv (OpenCV 3) and Qt5Qwt6 (qwt built against Qt5), but
    DFTFringe.pro is now the Qt6 project file.
  • -lz was missing, which cnpy.cpp has needed since npz support landed. The link
    could not have succeeded.
  • QMAKE_MKDIR and QMAKE_PKG_CONFIG hard coded two different Homebrew prefixes, one
    Intel and one Apple silicon, so the block could not work on either machine.
  • QMAKE_FULL_VERSION was set to the literal string APP_VERSION.
  • INCLUDEPATH had a stray -I prefix and pointed at the plugins directory.

Everything now comes from pkg-config, so no Homebrew prefix is hard coded and the same project file works on both architectures.

CI

build-macos.yml builds on macos-15 and macos-15-intel and uploads one disk image
per architecture. make-release.yml attaches both to the draft release alongside the
Windows installer.

Not an universal binary. Homebrew ships single-architecture libraries, so a universal
build would mean rebuilding opencv, armadillo and qwt for both architectures and merging
them with lipo.

opencv@4, not opencv. Homebrew's opencv formula is now OpenCV 5. opencv@4
keeps all three platforms on the same major version.

Potential problems

Minimum macOS is 15. macos-13 and macos-14 github runners are retired or deprecated, so the binary
inherits that floor. The 6.2 release required Ventura. Going lower means building the
dependencies from source with an explicit deployment target.

The disk images are not notarised. That needs a paid Apple Developer ID. macOS
refuses to open the app from the Finder, users have to clear the quarantine flag once.
This is documented in the README. The workflow has no signing machinery, so adding notarisation later is purely additive.

The bundle is ad-hoc signed, which is a separate matter: arm64 code must carry at least an ad-hoc signature to execute at all, and macdeployqt invalidates the linker's signature when it rewrites install names.

Single source change

colormapviewerdlg looked for ColorMaps in applicationDirPath(), which inside a
bundle is Contents/MacOS. That directory may hold nothing but code: codesign reports
the .cmp files as unsigned code objects and the whole bundle signature is rejected. The
maps ship in Contents/Resources and the lookup falls back there under Q_OS_MAC. The
6.2 bundle has them in neither location, so the colour map viewer has never worked on
macOS.

Correctness

This branch makes DFTFringe build, it does not produce correct results on its
own without the bool mask PR.

@Lucassifoni

Copy link
Copy Markdown
Contributor Author

Hi,
To me there’s a fair bit of work before merging or moving this one forward. Again, while a developer, this isn’t my ecosystem, but a few things still seem fishy to me.

  • The colour maps dance doesn’t work yet contrary to what is claimed
  • The signing of the package isn’t fully functional either, it needs to be improved
  • The readme has been unnecessarily made verbose

On the choices made, the biggest are that it isn’t an universal intel + arm build but two builds, and that it only produces executables for Mac OS > 15.

I’m willing to put as much time on this as needed.

Best,
Lucas

@atsju atsju left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for this work ! It's really valuable for Mac users.
I see no problem having a different installer between windows and Mac.

Comment thread .github/workflows/build-macos.yml Outdated
Comment thread .github/workflows/build-macos.yml Outdated
arch: x86_64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update to latest version. I'm working on updating the rest of the workflows and will do a PR soon.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread .github/workflows/build-macos.yml Outdated
"DFTFringe-${WORKFLOW_VERSION}-${{ matrix.arch }}.dmg"

- name: Upload Artifact
uses: actions/upload-artifact@v4

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update

Comment thread .github/workflows/make-release.yml Outdated
name: DFTFringe-windows-build-artifact
- uses: actions/download-artifact@v4
with:
pattern: DFTFringe-macos-*-build-artifact

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know nothing about MAC.
AI told me you could do an universal installer : lipo -create arm64_app x86_64_app -output universal_app
I let you judge what is best

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I'm torn on this one. My personal preference is to just grab the ARM build when there is both universal and arch-specific offered, but I don't know what people actually prefer. Maybe we could offer both the fat package with lipo and the two arch-specific builds ? Most software available for Mac does that.

@atsju atsju Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend the universal build. Remember we are developpers but most users prefer something simple over something optimized. They won't see the difference and is will be misleading.

I you want to distribute all 3, it's also possible.

  • Universal build (main download)
  • ARM64 build (alternative)
  • x86_64 build (alternative)

@Lucassifoni

Copy link
Copy Markdown
Contributor Author

@atsju I'll wait for your CI-related PRs to land before rebasing and finishing

Comment thread README.md
Lucassifoni and others added 10 commits August 3, 2026 17:05
The macx block had not been touched since the Qt5 era and no longer
matched the file it lives in:

- pkg-config names were opencv (OpenCV 3) and Qt5Qwt6, but DFTFringe.pro
  is now the Qt6 project file
- zlib was missing from LIBS, which cnpy.cpp needs since npz support landed
- QMAKE_MKDIR and QMAKE_PKG_CONFIG hard coded conflicting Homebrew
  prefixes, one Intel and one Apple silicon
- QMAKE_FULL_VERSION was set to the literal string APP_VERSION
- INCLUDEPATH had an -I prefix and pointed at the plugins directory

The new build-macos workflow builds one disk image per architecture on
macos-15 and macos-15-intel. A universal binary would require rebuilding
every Homebrew dependency for both architectures, so it is left out.

The bundle is ad-hoc signed only; notarisation needs an Apple Developer ID.

Refs githubdoe#24, githubdoe#118

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Homebrew's opencv formula moved to OpenCV 5, whose pkg-config name is
opencv5, so the configure step could not find opencv4. The CI now installs
opencv@4 to stay on the same major version as the Linux and Windows builds.

The project file falls back to opencv5 when opencv4 is absent so that a
local checkout with only the current opencv formula still configures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Homebrew builds qwt as a macOS framework. Its pkg-config file advertises an
include directory that does not hold the headers, so every translation unit
including <qwt_plot.h> failed to compile.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Boost.Stacktrace guards _Unwind_Backtrace behind _GNU_SOURCE, which is a
glibc convention. On macOS the function comes from Apple's libunwind and
needs no such define, so main.cpp was the only translation unit that failed
to compile.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
qmake only templates CFBundleShortVersionString and CFBundleVersion when
VERSION is a dotted number. Untagged builds carry a commit sha, so the keys
are absent rather than wrong and PlistBuddy Set had nothing to act on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
opencv4.pc lists every module, so the bundle carried dnn, gapi and the
OpenVINO stack and weighed 112 MB on arm64 and 141 MB on x86_64. Link the
same six modules as the Linux and Windows builds instead.

make-release now builds macOS alongside Windows and attaches both disk
images to the draft release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Apple deprecates --deep for signing and it can leave nested code invalidly
signed. This bundle nests around twenty frameworks plus the Qt plugins, so
sign those first and the app last, then verify the result.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Covers the Homebrew dependencies, why opencv@4 rather than opencv, the
PKG_CONFIG_PATH needed for the keg-only and split kegs, bundling with
macdeployqt, and the Gatekeeper workaround the unsigned disk images need.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contents/MacOS may hold nothing but code. Copying ColorMaps beside the
executable made codesign report the .cmp files as unsigned code objects and
invalidated the whole bundle signature, which is why macOS killed the app when
it was launched from the Finder while running the binary directly still worked.

colormapviewerdlg falls back to Contents/Resources on macOS, where the maps now
live. The dialog looked next to the executable, which no macOS build has ever
had, so this also makes the colour map viewer work for the first time.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follows the review: a single download is less confusing than asking users to
pick an architecture, and they cannot tell the difference anyway.

The two matrix jobs now build a bundle each and a third job lipos every Mach-O
file in them into one universal application, signs it and wraps it in a disk
image. Signing happens only after the merge, since lipo invalidates it.

The merge refuses to run if the two bundles do not contain the same files.
Homebrew resolves formulae independently on the two runners, so a version bump
landing between the jobs would otherwise silently produce an application built
against two different sets of libraries.

Also updates the action versions to match githubdoe#350 and drops the working branch
from the push trigger.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rewritten with less fluff, and updated for the universal disk image. Drops the
notes about OpenCV module selection and the qwt framework headers, which are
explained where they are done in DFTFringe.pro rather than repeated here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Lucassifoni

Copy link
Copy Markdown
Contributor Author

It looks like the lipo'd DMG will be 169MB. As of today's standards it's okay for me. I'll continue cleaning up and check if I manage to handle the missing color maps.

@Lucassifoni

Copy link
Copy Markdown
Contributor Author

The software won't open unless the user adds a security exception, this is normal unless signed with a valid Apple Developer ID (99$/year). I don't have one as of today. If noone in the team has one, it will have to stay that way. I added shorter instructions in the Readme.

@gr5

gr5 commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

I'm not a MAC person, so no. Possibly @Interferometry has one? He did some work to get DFTF to build on the Mac a few years ago.

@Lucassifoni

Copy link
Copy Markdown
Contributor Author

I re-downloaded their 6.2 build and it looks like it was indeed signed, I don't get a security exemption request.

@gr5

gr5 commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Is it possible/easy to explain how to do this in the installer for mac people who don't know how? Or am I being silly?

As a minimum please explain how to do it here so that I can mention this on the interferometry group when we release this. Or maybe a link to a youtube video on how to do it.

Comment thread README.md
Or, from the terminal :

```
xattr -dr com.apple.quarantine /Applications/DFTFringe.app

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gr5 I already added the instructions here

@Lucassifoni

Lucassifoni commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Another issue to fix before considering the build correct, I did not try to launch it graphically (by double-clicking) before today, and it crashes due to a non-writable root directory issue : #354
It launches fine from a non-root directory launched from the terminal.

Comment thread README.md
make -j4
```

# How to install DFTFringe on MacOS

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's quite strange to have

  • install Win
  • build Linux
  • install Mac
  • build Mac
  • build Win

Maybe reorder to :

  • install Win
  • install Mac
  • build Linux (there is no install)
  • build Mac or Win
  • build Win or Mac

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants