Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
944681e
Add macOS CI build and refresh the macOS qmake configuration
Lucassifoni Aug 2, 2026
5197d8a
Use opencv@4 on macOS instead of the OpenCV 5 formula
Lucassifoni Aug 2, 2026
1684755
Point the macOS include path at qwt's framework headers
Lucassifoni Aug 2, 2026
d3b88f6
Let Boost.Stacktrace build on macOS
Lucassifoni Aug 2, 2026
d6daa55
Add the bundle version keys when qmake has not emitted them
Lucassifoni Aug 2, 2026
c418048
Link only the OpenCV modules DFTFringe uses and publish the disk images
Lucassifoni Aug 2, 2026
41ce241
Sign the bundle inside out rather than with codesign --deep
Lucassifoni Aug 2, 2026
03dc54b
Document building and installing DFTFringe on macOS
Lucassifoni Aug 2, 2026
8d37493
Ship the colour maps in Contents/Resources so the bundle can be signed
Lucassifoni Aug 2, 2026
c69cd77
Merge both architectures into one universal disk image
Lucassifoni Aug 3, 2026
e4db87e
Shorten the macOS README sections and add the build badge
Lucassifoni Aug 3, 2026
8446dfe
Rewrites Mac OS Launch section to be clearer
Lucassifoni Aug 3, 2026
66e0741
Merge branch 'githubdoe:master' into macos-build
Lucassifoni Aug 6, 2026
cac0d73
Reorders README sections
Lucassifoni Aug 6, 2026
00f6e68
Cleans up Mac OS build CI
Lucassifoni Aug 6, 2026
ebdecce
Merge branch 'macos-build' of github.com:Lucassifoni/DFTFringe into m…
Lucassifoni Aug 6, 2026
16598c0
Merge branch 'githubdoe:master' into macos-build
Lucassifoni Aug 19, 2026
82df6e3
Removes extraneous comments
Lucassifoni Aug 19, 2026
c6214de
Simplifies README with less detail and sends to the CI workflow for m…
Lucassifoni Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions .github/workflows/build-macos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: build-macos
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
workflow_call:

jobs:
build-macos:
strategy:
fail-fast: false
matrix:
include:
- os: macos-15
arch: arm64
- os: macos-15-intel
arch: x86_64
runs-on: ${{ matrix.os }}
outputs:
workflow-version: ${{ steps.version.outputs.workflow-version }}
steps:
- uses: actions/checkout@v6

- name: Install dependencies
run: brew install qt qwt opencv@4 armadillo

- name: Resolve Homebrew layout
run: |
QT_PREFIX="$(brew --prefix qt)"
if [ ! -x "$QT_PREFIX/bin/qmake" ]; then QT_PREFIX="$(brew --prefix qtbase)"; fi
echo "QT_PREFIX=$QT_PREFIX" >> "$GITHUB_ENV"
echo "PKG_CONFIG_PATH=$(brew --prefix qwt)/lib/pkgconfig:$(brew --prefix opencv@4)/lib/pkgconfig:$(brew --prefix armadillo)/lib/pkgconfig:$(brew --prefix)/lib/pkgconfig" >> "$GITHUB_ENV"

- name: Resolve version strings
id: version
run: |
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
WORKFLOW_VERSION="${{ github.event.pull_request.head.sha }}_${{ github.event.pull_request.base.sha }}"
elif [[ "$GITHUB_REF" == refs/tags/v* ]]; then
WORKFLOW_VERSION="$GITHUB_REF_NAME"
else
WORKFLOW_VERSION="$GITHUB_SHA"
fi
BUNDLE_VERSION="$(printf '%s' "$WORKFLOW_VERSION" | sed -nE 's/^v?([0-9]+\.[0-9]+\.[0-9]+).*$/\1/p')"
echo "WORKFLOW_VERSION=$WORKFLOW_VERSION" >> "$GITHUB_ENV"
echo "BUNDLE_VERSION=${BUNDLE_VERSION:-0.0.0}" >> "$GITHUB_ENV"
echo "workflow-version=$WORKFLOW_VERSION" >> "$GITHUB_OUTPUT"

- name: Find and Replace MY_AUTOMATED_VERSION_STRING
run: sed -i '' "s/MY_AUTOMATED_VERSION_STRING/${WORKFLOW_VERSION}/" DFTFringe.pro

- name: Configure
run: '"$QT_PREFIX/bin/qmake" DFTFringe.pro CONFIG+=release'

- uses: ammaraskar/gcc-problem-matcher@master
- run: echo "::add-matcher::.github/matcher/uic_matcher.json"
- name: Build
run: make -j$(sysctl -n hw.ncpu)
- run: echo "::remove-matcher owner=uic-problem-matcher::"

- name: Bundle dependencies
run: |
"$QT_PREFIX/bin/macdeployqt" build/release/DFTFringe.app -verbose=1
cp -R ColorMaps build/release/DFTFringe.app/Contents/Resources/
PLIST=build/release/DFTFringe.app/Contents/Info.plist
for key in CFBundleShortVersionString CFBundleVersion; do
/usr/libexec/PlistBuddy -c "Set :$key $BUNDLE_VERSION" "$PLIST" 2>/dev/null \
|| /usr/libexec/PlistBuddy -c "Add :$key string $BUNDLE_VERSION" "$PLIST"
done

- name: Verify the bundle is self contained
run: |
if otool -L build/release/DFTFringe.app/Contents/MacOS/DFTFringe \
| tail -n +2 | awk '{print $1}' \
| grep -vE "^(@rpath|@executable_path|/usr/lib|/System)"; then
echo "bundle references the paths above, outside itself"
exit 1
fi

- name: Upload bundle
run: tar czf DFTFringe-${{ matrix.arch }}.tar.gz -C build/release DFTFringe.app
- uses: actions/upload-artifact@v7
with:
name: DFTFringe-macos-${{ matrix.arch }}-bundle
path: DFTFringe-${{ matrix.arch }}.tar.gz
retention-days: 1

universal-dmg:
needs: build-macos
runs-on: macos-15
env:
WORKFLOW_VERSION: ${{ needs.build-macos.outputs.workflow-version }}
steps:
- uses: actions/download-artifact@v8
with:
pattern: DFTFringe-macos-*-bundle
merge-multiple: true

- name: Merge the two architectures
run: |
mkdir arm64 x86_64
tar xzf DFTFringe-arm64.tar.gz -C arm64
tar xzf DFTFringe-x86_64.tar.gz -C x86_64
ARM="$PWD/arm64/DFTFringe.app"
INTEL="$PWD/x86_64/DFTFringe.app"

diff <(cd "$ARM" && find . | sort) <(cd "$INTEL" && find . | sort) \
|| { echo "the two bundles do not contain the same files"; exit 1; }

cp -R "$ARM" DFTFringe.app
UNIVERSAL="$PWD/DFTFringe.app"
find "$UNIVERSAL" -type f | while read -r f; do
rel="${f#$UNIVERSAL/}"
if file -b "$f" | grep -q "Mach-O"; then
lipo -create "$ARM/$rel" "$INTEL/$rel" -output "$f"
fi
done
echo "--- architectures in the merged executable:"
lipo -info "$UNIVERSAL/Contents/MacOS/DFTFringe"

- name: Ad-hoc sign
run: |
APP=DFTFringe.app
find "$APP/Contents/Frameworks" "$APP/Contents/PlugIns" \
\( -name "*.dylib" -o -name "*.so" \) -exec codesign --force --sign - {} +
find "$APP/Contents/Frameworks" -maxdepth 1 -name "*.framework" \
-exec codesign --force --sign - {} +
codesign --force --sign - "$APP"
codesign --verify --deep --strict --verbose=2 "$APP"

- name: Create disk image
run: |
STAGE="$(mktemp -d)/DFTFringe"
mkdir -p "$STAGE"
cp -R DFTFringe.app "$STAGE/"
ln -s /Applications "$STAGE/Applications"
hdiutil create -volname "DFTFringe" -srcfolder "$STAGE" -ov -format UDZO \
"DFTFringe-${WORKFLOW_VERSION}.dmg"

- uses: actions/upload-artifact@v7
with:
name: DFTFringe-macos-build-artifact
path: DFTFringe-${{ env.WORKFLOW_VERSION }}.dmg
11 changes: 10 additions & 1 deletion .github/workflows/make-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ jobs:
call-build-windows:
needs: check-semver
uses: ./.github/workflows/build-windows.yml
call-build-macos:
needs: check-semver
uses: ./.github/workflows/build-macos.yml
# linux build is mainly here to check it builds. We have no acrtifact now.
call-build-linux:
permissions:
Expand All @@ -40,19 +43,24 @@ jobs:

download-and-publish-artifacts:
runs-on: ubuntu-latest
needs: call-build-windows
needs: [call-build-windows, call-build-macos]
steps:
# get artifact uploaded from build workflow
- uses: actions/download-artifact@v8
with:
name: DFTFringe-windows-build-artifact
- uses: actions/download-artifact@v8
with:
name: DFTFringe-macos-build-artifact
# create the GitHub release and upload the artifacts
- name: publish Release
uses: softprops/action-gh-release@v3
with:
body: |
- edit this changelog
- test the installer one last time
- the macOS disk image is not notarised, so the first launch needs
the quarantine flag cleared. See the README for details.
- make the actual release from this draft
# the release will be drafted so it needs to be manually published after release notes editions
draft: true
Expand All @@ -61,3 +69,4 @@ jobs:
files: |
DFTFringeInstaller_${{github.ref_name}}.exe
Z_DFTFringe.exe.debug
DFTFringe-${{github.ref_name}}.dmg
55 changes: 25 additions & 30 deletions DFTFringe.pro
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,8 @@ macx {
CONFIG += app_bundle
CONFIG += sdk_no_version_check
CONFIG += link_pkgconfig
CONFIG += silent

QMAKE_FULL_VERSION=APP_VERSION
QMAKE_MACOSX_DEPLOYMENT_TARGET = 11.0
QMAKE_APPLE_DEVICE_ARCHS = x86_64 arm64
QMAKE_APPLE_DEVICE_ARCHS = $$QMAKE_HOST.arch

CONFIG( debug, debug|release ) { DESTDIR = build/debug }
CONFIG( release, debug|release ) { DESTDIR = build/release }
Expand All @@ -109,32 +106,30 @@ macx {
OBJECTS_DIR = $$DESTDIR/.obj #these change between build and release.
RCC_DIR = $$DESTDIR/.qrc
UI_DIR = $$DESTDIR/.ui
QMAKE_MKDIR = /usr/local/bin/mkdir # This tells QMAKE which mkdir command to use.
QMAKE_PKG_CONFIG = /opt/homebrew/bin/pkg-config # This tells QMAKE which pkg-config executable to use.
PKG_CONFIG_PATH = $$[QT_INSTALL_LIBS]/pkgconfig
INCLUDEPATH += -I$$[QT_INSTALL_PLUGINS]
LIBS += -L$$[QT_INSTALL_PLUGINS]
PKGCONFIG += armadillo opencv Qt5Qwt6

message(........QT_VERSION: $$[QT_VERSION])
message(.QT_INSTALL_PREFIX: $$[QT_INSTALL_PREFIX])
message(QT_INSTALL_HEADERS: $$[QT_INSTALL_HEADERS])
message(...QT_INSTALL_LIBS: $$[QT_INSTALL_LIBS])
message(QT_INSTALL_PLUGINS: $$[QT_INSTALL_PLUGINS])
message(...................)
message(...........DESTDIR: $$DESTDIR)
message(...........MOC_DIR: $$MOC_DIR)
message(.......OBJECTS_DIR: $$OBJECTS_DIR)
message(...........RCC_DIR: $$RCC_DIR)
message(............UI_DIR: $$UI_DIR)
message(...................)
message(.......QMAKE_MKDIR: $$QMAKE_MKDIR)
message(..QMAKE_PKG_CONFIG: $$QMAKE_PKG_CONFIG)
message(...PKG_CONFIG_PATH: $$PKG_CONFIG_PATH)
message(.......INCLUDEPATH: $$INCLUDEPATH)
message(..............LIBS: $$LIBS)
message(.........PKGCONFIG: $$PKGCONFIG)
message(............CONFIG: $$CONFIG)

PKGCONFIG += armadillo Qt6Qwt6

packagesExist(opencv4) {
OPENCV_PACKAGE = opencv4
} else {
OPENCV_PACKAGE = opencv5
}

QMAKE_CXXFLAGS += $$system(pkg-config --cflags-only-I $$OPENCV_PACKAGE)
LIBS += $$system(pkg-config --libs-only-L $$OPENCV_PACKAGE)
LIBS += -lopencv_calib3d
LIBS += -lopencv_core
LIBS += -lopencv_features2d
LIBS += -lopencv_highgui
LIBS += -lopencv_imgcodecs
LIBS += -lopencv_imgproc

QWT_FRAMEWORK_HEADERS = $$system(pkg-config --variable=libdir Qt6Qwt6)/qwt.framework/Headers
exists($$QWT_FRAMEWORK_HEADERS): INCLUDEPATH += $$QWT_FRAMEWORK_HEADERS

LIBS += -lz

DEFINES += BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
}

# Below are the includes for source files and other resources, sorted alphabetically. ##################################
Expand Down
47 changes: 45 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DFTFringe

[![build-windows](https://github.com/githubdoe/DFTFringe/actions/workflows/build-windows.yml/badge.svg?branch=master)](https://github.com/githubdoe/DFTFringe/actions/workflows/build-windows.yml) [![build-linux](https://github.com/githubdoe/DFTFringe/actions/workflows/build-linux.yml/badge.svg?branch=master)](https://github.com/githubdoe/DFTFringe/actions/workflows/build-linux.yml)
[![build-windows](https://github.com/githubdoe/DFTFringe/actions/workflows/build-windows.yml/badge.svg?branch=master)](https://github.com/githubdoe/DFTFringe/actions/workflows/build-windows.yml) [![build-linux](https://github.com/githubdoe/DFTFringe/actions/workflows/build-linux.yml/badge.svg?branch=master)](https://github.com/githubdoe/DFTFringe/actions/workflows/build-linux.yml) [![build-macos](https://github.com/githubdoe/DFTFringe/actions/workflows/build-macos.yml/badge.svg?branch=master)](https://github.com/githubdoe/DFTFringe/actions/workflows/build-macos.yml)


# Introduction
Expand Down Expand Up @@ -31,6 +31,24 @@ Additional information and help is availlable at https://groups.io/g/Interferome
:point_right: Follow the link and use the installer:
[link to latest release](https://github.com/githubdoe/dftfringe/releases/latest).

# How to install DFTFringe on MacOS

Download the disk image from the
[latest release](https://github.com/githubdoe/dftfringe/releases/latest), open it
and drag DFTFringe into Applications. The required OS is MacOS 15 or later.

**The app is not notarised yet**, so macOS refuses to open it the first time and
will just quit without saying anything. To launch it :

Right-click it -> "Open", then open "System Settings", go to "Privacy & Security",
find the DFTFringe security warning, and click "Open Anyway"

Or, from the terminal :

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

# How to build DFTFringe on Linux


Expand All @@ -52,7 +70,32 @@ make -j4

# How to build DFTFringe on MacOS

:building_construction: Under construction :building_construction:
Dependencies come from [Homebrew](https://brew.sh).

```
brew install qt qwt opencv@4 armadillo
```

qmake finds them through pkg-config.
`opencv@4` is keg-only and Qt6 is split across several kegs, so point `PKG_CONFIG_PATH` at them:

```
export PKG_CONFIG_PATH="$(brew --prefix qwt)/lib/pkgconfig:$(brew --prefix opencv@4)/lib/pkgconfig:$(brew --prefix armadillo)/lib/pkgconfig:$(brew --prefix)/lib/pkgconfig"
$(brew --prefix qt)/bin/qmake DFTFringe.pro CONFIG+=release
make -j$(sysctl -n hw.ncpu)
```

This produces `build/release/DFTFringe.app`, linked against Homebrew libraries.
`macdeployqt` copies the libraries in and rewrites their install names. The colour
maps have to be copied in `Contents/Resources`.

```
$(brew --prefix qt)/bin/macdeployqt build/release/DFTFringe.app
cp -R ColorMaps build/release/DFTFringe.app/Contents/Resources/
open build/release/DFTFringe.app
```

To produce an universal build with `lipo` from arm and intel builds, you can take `.github/workflows/build-macos.yml` as reference.

# How to build DFTFringe on Windows

Expand Down
4 changes: 4 additions & 0 deletions colormapviewerdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ colorMapViewerDlg::colorMapViewerDlg(QWidget *parent) :
{
QSettings set;
gpath = qApp->applicationDirPath() + "/ColorMaps";
#ifdef Q_OS_MAC
if (!QDir(gpath).exists())
gpath = qApp->applicationDirPath() + "/../Resources/ColorMaps";
#endif
ui->setupUi(this);
ui->path->setText(gpath);
ui->listWidget->setViewMode(QListWidget::IconMode);
Expand Down
Loading