From df0909d1c8a2243b43c53f67822910b4d45f040b Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Tue, 29 Oct 2024 13:04:58 +0100 Subject: [PATCH] frontend/qt: update to Qt6 on macOS brew's qt@6 would work excpt that it is missing all of the qt@6/libexec folder, which contains the rcc tool we need to bundle the frontend assets. Instead we use `aqtinstall` which installs Qt binaries from official mirrors and includes all we need. We get rid of osx-brew.sh which is only referenced in the BUILD.md and instead inline the instructions, as it is strange to install brew and other unprompted. Devs can follow along the BUILD.md instructions. This commit also introduces universal builds for macOS. They are fat binaries/libraries that include code for both the amd64 and arm64 architectures, so the app can run natively. As a result, the resulting app size is roughly double to before. Alternative considered but dismissed: - Make and distribute two separate BitBox.app outputs per architecture. This reduces the app size, but is a bit more error prone for users and incurs more effort to distribute correctly. Also the AppStore requires universal builds, if we ever want to distbute the app through the AppStore. --- .github/workflows/ci.yml | 12 ++++++++++++ Makefile | 7 ------- README.md | 8 -------- docs/BUILD.md | 21 ++++++++++++++++----- frontends/qt/.gitignore | 4 ++++ frontends/qt/BitBox.pro | 2 ++ frontends/qt/Makefile | 9 ++++++--- frontends/qt/server/Makefile.macosx | 15 +++++++++------ scripts/github-ci.sh | 7 +++---- scripts/osx-brew.sh | 14 -------------- 10 files changed, 52 insertions(+), 47 deletions(-) delete mode 100755 scripts/osx-brew.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8cad161b0..924b998b12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,6 +104,18 @@ jobs: uses: actions/setup-node@v4 with: node-version: '20.x' + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Install Qt + # Qt modules: Not sure why we need qtpositioning - app compilation fails without. Maybe the webengine depends on it. + # qtpositioning depends on qtserialport. + # qtwebechannel is for the JS/backend bridge. + # qtwebengine is for rendering the frontend. + run: | + pip install aqtinstall + aqt install-qt mac desktop 6.2.4 --modules qtpositioning qtserialport qtwebchannel qtwebengine --outputdir ~/Qt - name: Build macOS app run: > ./scripts/github-ci.sh qt-osx; diff --git a/Makefile b/Makefile index 2503dc5cc9..516dd19a65 100644 --- a/Makefile +++ b/Makefile @@ -30,13 +30,6 @@ gomobileinit: # TODO: replace with go install golang.org/x/mobile/cmd/gomobile@latest once https://github.com/golang/mobile/pull/105 is merged. git clone https://github.com/BitBoxSwiss/mobile.git /tmp/mobile && cd /tmp/mobile/cmd/gomobile && go install . gomobile init -# Initializiation on MacOS -# - run make from $GOPATH/src/github.com/BitBoxSwiss/bitbox-wallet-app -# - additional dependencies: Qt 5.15 & Xcode command line tools -# - add to $PATH: /usr/local/opt/go@1.23/bin -osx-init: - ./scripts/osx-brew.sh - $(MAKE) envinit servewallet: go run -mod=vendor ./cmd/servewallet servewallet-mainnet: diff --git a/README.md b/README.md index 38d4bcfbfb..2790cb1fe8 100644 --- a/README.md +++ b/README.md @@ -53,14 +53,6 @@ To build the app or run the development workflow, the following dependencies nee - [Qt5](https://www.qt.io) version 5.15.2 - install Qt for your platform, including the WebEngine component -#### Environment variables - -Make sure the environment variables for qt, go and node are set, see also [docs/BUILD.md](./docs/BUILD.md) for platform specific instructions - -To initialize the build environment and install the required go utilities (linters, ...), call -* `make envinit`, or -* on MacOS `make osx-init` - ## Build the BitBoxApp Clone this repository using `git clone --recursive`. diff --git a/docs/BUILD.md b/docs/BUILD.md index 455227a2ad..2c3fa9618f 100644 --- a/docs/BUILD.md +++ b/docs/BUILD.md @@ -30,17 +30,28 @@ Build artifacts: ## MacOS -Make sure you have `qt@5/bin`, `go@1.23/bin` and `go/bin` in your PATH, i.e. add to your `.zshrc` +Install Go, Qt and create-dmg. Note that qt@6 from homebrew does **not** work as it is missing the +`rcc` tool. + +``` +# Install Go. Can also use the official installer +brew install go@1.23 +brew install create-dmg +# InstalL Qt. Can also use the official installer. +pip install aqtinstall +aqt list-qt mac desktop --arch 6.2.4 +aqt install-qt mac desktop 6.2.4 --modules qtpositioning qtserialport qtwebchannel qtwebengine --outputdir ~/Qt +``` + +Make sure you have `qt@6/bin`, `qt@6/libexec`, `go@1.23/bin` and `go/bin` in your PATH, i.e. add to your `.zshrc`: ```bash -export PATH="$PATH:/usr/local/opt/qt@5/bin" +export PATH="$PATH:~/Qt/6.2.4/macos/bin" +export PATH="$PATH:~/Qt/6.2.4/macos/libexec" export PATH="$PATH:/usr/local/opt/go@1.23/bin" export PATH="$PATH:$HOME/go/bin" ``` -Prepare the MacOS system to have the build environment: -`make osx-init` - Build the QT frontend for MacOS: `make qt-osx` diff --git a/frontends/qt/.gitignore b/frontends/qt/.gitignore index dc87810df5..5476661623 100644 --- a/frontends/qt/.gitignore +++ b/frontends/qt/.gitignore @@ -1,5 +1,9 @@ /build/ /config/ /server/libserver.h +/server/libserver_arm64.h +/server/libserver_amd64.h /server/libserver.so +/server/libserver_arm64.so +/server/libserver_amd64.so .qmake.stash diff --git a/frontends/qt/BitBox.pro b/frontends/qt/BitBox.pro index 9ca064a2bf..41da1e9c32 100644 --- a/frontends/qt/BitBox.pro +++ b/frontends/qt/BitBox.pro @@ -64,6 +64,8 @@ SOURCES += \ HEADERS += libserver.h webclass.h filedialog.h unix:macx { + CONFIG += sdk_no_version_check + QMAKE_APPLE_DEVICE_ARCHS = x86_64 arm64 # Those frameworks are needed for Go's http/net packages. # Waiting for https://github.com/golang/go/issues/11258 to be able to automatically capture link flags. LIBS += -framework CoreFoundation -framework Security diff --git a/frontends/qt/Makefile b/frontends/qt/Makefile index 2164c93c9f..a98b1321f3 100644 --- a/frontends/qt/Makefile +++ b/frontends/qt/Makefile @@ -17,9 +17,6 @@ include ../../env.mk.inc base: mkdir build ./genassets.sh - qmake -set MACOS_MIN_VERSION $(MACOS_MIN_VERSION) - qmake -o build/Makefile - cd build && $(MAKE) clean: -rm -rf build cd server && $(MAKE) clean @@ -27,6 +24,8 @@ linux: $(MAKE) clean cd server && $(MAKE) linux $(MAKE) base + qmake -o build/Makefile + cd build && $(MAKE) mkdir build/linux-tmp build/linux mv build/BitBox build/linux-tmp cp build/assets.rcc build/linux-tmp/ @@ -47,6 +46,10 @@ osx: $(MAKE) clean cd server && $(MAKE) macosx $(MAKE) base + qmake -set MACOS_MIN_VERSION $(MACOS_MIN_VERSION) + # See https://stackoverflow.com/questions/77136519/qmake-failing-with-sdk-14-ventura-13-5-2 + qmake -early QMAKE_DEFAULT_LIBDIRS=$(shell xcrun -show-sdk-path)/usr/lib -o build/Makefile + cd build && $(MAKE) mkdir build/osx mv build/BitBox.app build/osx/ cp resources/MacOS/Info.plist build/osx/BitBox.app/Contents/ diff --git a/frontends/qt/server/Makefile.macosx b/frontends/qt/server/Makefile.macosx index 3a3920be87..e1ba43f455 100644 --- a/frontends/qt/server/Makefile.macosx +++ b/frontends/qt/server/Makefile.macosx @@ -2,7 +2,6 @@ include ../../../hardening.mk.inc include ../../../env.mk.inc CGO=1 BUILDMODE=c-shared -GOARCH=amd64 GOOS=darwin GOTOOLCHAIN=local @@ -10,10 +9,14 @@ darwin: CGO_CFLAGS="-g ${GODARWINSECFLAGS} ${CFLAGS}" \ CGO_LDFLAGS="${GODARWINLDFLAGS} ${LFLAGS}" \ MACOSX_DEPLOYMENT_TARGET=${MACOS_MIN_VERSION} \ - GOARCH=${GOARCH} CGO_ENABLED=${CGO} GOOS=${GOOS} GOTOOLCHAIN=${GOTOOLCHAIN} \ - go build -ldflags='-s' -x -mod=vendor \ - -buildmode="c-shared" -o ${LIBNAME}.so + GOARCH=arm64 CGO_ENABLED=${CGO} GOOS=${GOOS} GOTOOLCHAIN=${GOTOOLCHAIN} go build -ldflags='-s' -x -mod=vendor -buildmode="c-shared" -o ${LIBNAME}_arm64.so + GOARCH=amd64 CGO_ENABLED=${CGO} GOOS=${GOOS} GOTOOLCHAIN=${GOTOOLCHAIN} go build -ldflags='-s' -x -mod=vendor -buildmode="c-shared" -o ${LIBNAME}_amd64.so + lipo -create -output ${LIBNAME}.so ${LIBNAME}_arm64.so ${LIBNAME}_amd64.so + # Without this, the internal names of the two libs are libserver_arm64.so and libserver_amd64.so, and + # will be linked with these names in the final executable (even though the library is fat and its name is libserver.so). + # With this, we fix the internal name which will be used when linking. + install_name_tool -id ${LIBNAME}.so ${LIBNAME}.so clean: - -rm -f ${LIBNAME}.so - -rm -f ${LIBNAME}.h + -rm -f ${LIBNAME}.so ${LIBNAME}_arm64.so ${LIBNAME}_amd64.so + -rm -f ${LIBNAME}_arm64.h {LIBNAME}_amd64.h diff --git a/scripts/github-ci.sh b/scripts/github-ci.sh index f52d33ad64..d1e59d2e8d 100755 --- a/scripts/github-ci.sh +++ b/scripts/github-ci.sh @@ -32,10 +32,9 @@ if [ "$OS_NAME" == "osx" ]; then # GitHub CI installs Go directly in the macos action, before executing # this script. go version - brew install qt@5 - export PATH="/usr/local/opt/qt@5/bin:$PATH" - export LDFLAGS="-L/usr/local/opt/qt@5/lib" - export CPPFLAGS="-I/usr/local/opt/qt@5/include" + export PATH="~/Qt/6.2.4/macos/bin:~/Qt/6.2.4/macos/libexec:$PATH" + export LDFLAGS="-L~/Qt/6.2.4/macos/lib" + export CPPFLAGS="-I~/Qt/6.2.4/macos/include" export GOPATH=~/go export PATH=$PATH:~/go/bin mkdir -p $GOPATH/$(dirname $GO_SRC_DIR) diff --git a/scripts/osx-brew.sh b/scripts/osx-brew.sh deleted file mode 100755 index f09c24446c..0000000000 --- a/scripts/osx-brew.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -if [ $(arch) = "arm64" ]; then - # recent M-based apple machines have an arm64 arch, but we need to install x86_64 deps - arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - /usr/local/Homebrew/bin/brew install go@1.23 - /usr/local/Homebrew/bin/brew install qt@5 - /usr/local/Homebrew/bin/brew install create-dmg -else - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - brew install go@1.23 - brew install qt@5 - brew install create-dmg -fi