From 562869d11463837841b0f5ea460744554c0801fb Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 7 Jun 2024 00:05:34 +0000 Subject: [PATCH 1/8] Revert "depends: remove PYTHONPATH from config.site" This reverts commit 3b19100303e70315c31d7aa3a3fd38d58131246f. --- Makefile.am | 2 ++ configure.ac | 2 ++ depends/config.site.in | 1 + 3 files changed, 5 insertions(+) diff --git a/Makefile.am b/Makefile.am index eec498dc0e..1595639d6c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,8 @@ endif .PHONY: deploy FORCE .INTERMEDIATE: $(COVERAGE_INFO) +export PYTHONPATH + if BUILD_BITCOIN_LIBS pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libbitcoinconsensus.pc diff --git a/configure.ac b/configure.ac index 4f71515873..06f748a1b0 100644 --- a/configure.ac +++ b/configure.ac @@ -129,6 +129,8 @@ AC_PATH_TOOL([OBJCOPY], [objcopy]) AC_PATH_PROG([DOXYGEN], [doxygen]) AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"]) +AC_ARG_VAR([PYTHONPATH], [Augments the default search path for python module files]) + AC_ARG_ENABLE([wallet], [AS_HELP_STRING([--disable-wallet], [disable wallet (enabled by default)])], diff --git a/depends/config.site.in b/depends/config.site.in index 29b2a67ed0..04377dd807 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -96,6 +96,7 @@ fi if test -n "@CXX@" -a -z "${CXX}"; then CXX="@CXX@" fi +PYTHONPATH="${depends_prefix}/native/lib/python3/dist-packages${PYTHONPATH:+${PATH_SEPARATOR}}${PYTHONPATH}" if test -n "@AR@"; then AR="@AR@" From 97910b11231e2ffc55a664da7f4b8b1321e6918a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 6 Jun 2024 14:52:14 +0000 Subject: [PATCH 2/8] Revert "ci: remove libz-dev from macOS build deps" This reverts commit 97d53e90badc01224139a4a4356b934f338568d4. --- ci/test/00_setup_env_mac_cross.sh | 2 +- depends/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/test/00_setup_env_mac_cross.sh b/ci/test/00_setup_env_mac_cross.sh index 31c4bff6ae..2a2fd7d48c 100755 --- a/ci/test/00_setup_env_mac_cross.sh +++ b/ci/test/00_setup_env_mac_cross.sh @@ -11,7 +11,7 @@ export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks} export CONTAINER_NAME=ci_macos_cross export CI_IMAGE_NAME_TAG="docker.io/ubuntu:22.04" export HOST=x86_64-apple-darwin -export PACKAGES="zip" +export PACKAGES="libz-dev zip" export XCODE_VERSION=15.0 export XCODE_BUILD_ID=15A240d export RUN_UNIT_TESTS=false diff --git a/depends/README.md b/depends/README.md index a8dfc83e3b..7e8e9c12a8 100644 --- a/depends/README.md +++ b/depends/README.md @@ -48,7 +48,7 @@ The paths are automatically configured and no other options are needed unless ta #### For macOS cross compilation - sudo apt-get install curl bsdmainutils cmake zip + sudo apt-get install curl bsdmainutils cmake libz-dev zip Note: You must obtain the macOS SDK before proceeding with a cross-compile. Under the depends directory, create a subdirectory named `SDKs`. From 4cb87ca5b45257534648f2be7e7d42e0075d445a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 6 Jun 2024 14:53:25 +0000 Subject: [PATCH 3/8] Revert "ci: remove python3-setuptools from mac build deps" This reverts commit 0ffcc5b680b92cf921fc11afb05e4a3607572d41. --- ci/test/00_setup_env_mac_cross.sh | 2 +- depends/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/test/00_setup_env_mac_cross.sh b/ci/test/00_setup_env_mac_cross.sh index 2a2fd7d48c..8b57e7c2f2 100755 --- a/ci/test/00_setup_env_mac_cross.sh +++ b/ci/test/00_setup_env_mac_cross.sh @@ -11,7 +11,7 @@ export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks} export CONTAINER_NAME=ci_macos_cross export CI_IMAGE_NAME_TAG="docker.io/ubuntu:22.04" export HOST=x86_64-apple-darwin -export PACKAGES="libz-dev zip" +export PACKAGES="libz-dev python3-setuptools zip" export XCODE_VERSION=15.0 export XCODE_BUILD_ID=15A240d export RUN_UNIT_TESTS=false diff --git a/depends/README.md b/depends/README.md index 7e8e9c12a8..1b752f7b04 100644 --- a/depends/README.md +++ b/depends/README.md @@ -48,7 +48,7 @@ The paths are automatically configured and no other options are needed unless ta #### For macOS cross compilation - sudo apt-get install curl bsdmainutils cmake libz-dev zip + sudo apt-get install curl bsdmainutils cmake libz-dev python3-setuptools zip Note: You must obtain the macOS SDK before proceeding with a cross-compile. Under the depends directory, create a subdirectory named `SDKs`. From 32f1caee521081e1f21f46ebd4271505f6ab9cb1 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 29 Feb 2024 00:14:07 +0000 Subject: [PATCH 4/8] build: Restore support for macOS `.dmg` creation This partially reverts b5790c35f7e1d48c79b83bded36f3f72c18c9fc1, 33ae0bd1e4756ca0f180ac4b3c32c9eb83b88cfd, and a128111c29ba0c31763ccbcd316268bfa9c029cd. --- Makefile.am | 13 +++- ci/test/00_setup_env_mac_cross.sh | 2 +- configure.ac | 2 + contrib/guix/libexec/build.sh | 2 +- contrib/guix/libexec/codesign.sh | 6 ++ contrib/guix/manifest.scm | 3 +- contrib/macdeploy/README.md | 17 +++-- contrib/macdeploy/background.tiff | 0 contrib/macdeploy/macdeployqtplus | 105 ++++++++++++++++++++++++++- depends/README.md | 2 +- depends/packages/native_ds_store.mk | 15 ++++ depends/packages/native_mac_alias.mk | 15 ++++ depends/packages/packages.mk | 2 +- doc/build-osx.md | 10 ++- 14 files changed, 176 insertions(+), 18 deletions(-) create mode 100644 contrib/macdeploy/background.tiff create mode 100644 depends/packages/native_ds_store.mk create mode 100644 depends/packages/native_mac_alias.mk diff --git a/Makefile.am b/Makefile.am index 1595639d6c..aa80c08c3c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,6 +37,7 @@ space := $(empty) $(empty) OSX_APP=Bitcoin-Qt.app OSX_VOLNAME = $(subst $(space),-,$(PACKAGE_NAME)) +OSX_DMG = $(OSX_VOLNAME).dmg OSX_ZIP = $(OSX_VOLNAME).zip OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns @@ -124,13 +125,19 @@ osx_volname: echo $(OSX_VOLNAME) >$@ if BUILD_DARWIN +$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) + $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -dmg + $(OSX_ZIP): $(OSX_APP_BUILT) $(OSX_PACKAGING) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -zip -deploydir: $(OSX_ZIP) +deploydir: $(OSX_DMG) $(OSX_ZIP) else !BUILD_DARWIN APP_DIST_DIR=$(top_builddir)/dist +$(OSX_DMG): deploydir + $(XORRISOFS) -D -l -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -o $@ $(APP_DIST_DIR) -- $(if $(SOURCE_DATE_EPOCH),-volume_date all_file_dates =$(SOURCE_DATE_EPOCH)) + $(OSX_ZIP): deploydir if [ -n "$(SOURCE_DATE_EPOCH)" ]; then find $(APP_DIST_DIR) -exec touch -d @$(SOURCE_DATE_EPOCH) {} +; fi cd $(APP_DIST_DIR) && find . | sort | $(ZIP) -X@ $@ @@ -141,7 +148,7 @@ $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PAC deploydir: $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt endif !BUILD_DARWIN -deploy: $(OSX_ZIP) +deploy: $(OSX_DMG) $(OSX_ZIP) endif $(BITCOIN_QT_BIN): FORCE @@ -318,7 +325,7 @@ EXTRA_DIST += \ test/util/data/txreplacesingleinput.hex \ test/util/rpcauth-test.py -CLEANFILES = $(OSX_ZIP) $(BITCOIN_WIN_INSTALLER) +CLEANFILES = $(OSX_DMG) $(OSX_ZIP) $(BITCOIN_WIN_INSTALLER) DISTCHECK_CONFIGURE_FLAGS = --enable-man diff --git a/ci/test/00_setup_env_mac_cross.sh b/ci/test/00_setup_env_mac_cross.sh index 8b57e7c2f2..20a2d06c4c 100755 --- a/ci/test/00_setup_env_mac_cross.sh +++ b/ci/test/00_setup_env_mac_cross.sh @@ -11,7 +11,7 @@ export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks} export CONTAINER_NAME=ci_macos_cross export CI_IMAGE_NAME_TAG="docker.io/ubuntu:22.04" export HOST=x86_64-apple-darwin -export PACKAGES="libz-dev python3-setuptools zip" +export PACKAGES="libz-dev python3-setuptools xorriso zip" export XCODE_VERSION=15.0 export XCODE_BUILD_ID=15A240d export RUN_UNIT_TESTS=false diff --git a/configure.ac b/configure.ac index 06f748a1b0..fab23d971b 100644 --- a/configure.ac +++ b/configure.ac @@ -769,6 +769,7 @@ case $host in AC_PATH_TOOL([DSYMUTIL], [dsymutil], [dsymutil]) AC_PATH_TOOL([INSTALL_NAME_TOOL], [install_name_tool], [install_name_tool]) AC_PATH_TOOL([OTOOL], [otool], [otool]) + AC_PATH_PROGS([XORRISOFS], [xorrisofs], [xorrisofs]) AC_PATH_PROG([ZIP], [zip], [zip]) dnl libtool will try to strip the static lib, which is a problem for @@ -1879,6 +1880,7 @@ AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/spl AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])]) AC_CONFIG_LINKS([contrib/devtools/iwyu/bitcoin.core.imp:contrib/devtools/iwyu/bitcoin.core.imp]) AC_CONFIG_LINKS([contrib/filter-lcov.py:contrib/filter-lcov.py]) +AC_CONFIG_LINKS([contrib/macdeploy/background.tiff:contrib/macdeploy/background.tiff]) AC_CONFIG_LINKS([src/.bear-tidy-config:src/.bear-tidy-config]) AC_CONFIG_LINKS([src/.clang-tidy:src/.clang-tidy]) AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py]) diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index b301369ad9..7f7ff0e28f 100755 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -315,7 +315,7 @@ mkdir -p "$DISTSRC" | gzip -9n > "${OUTDIR}/${DISTNAME}-${HOST}-unsigned.tar.gz" \ || ( rm -f "${OUTDIR}/${DISTNAME}-${HOST}-unsigned.tar.gz" && exit 1 ) ) - make deploy ${V:+V=1} OSX_ZIP="${OUTDIR}/${DISTNAME}-${HOST}-unsigned.zip" + make deploy ${V:+V=1} OSX_DMG="${OUTDIR}/${DISTNAME}-${HOST}-unsigned.dmg" OSX_ZIP="${OUTDIR}/${DISTNAME}-${HOST}-unsigned.zip" ;; esac ( diff --git a/contrib/guix/libexec/codesign.sh b/contrib/guix/libexec/codesign.sh index b56d2a2309..9f5c549aa2 100755 --- a/contrib/guix/libexec/codesign.sh +++ b/contrib/guix/libexec/codesign.sh @@ -91,6 +91,12 @@ mkdir -p "$DISTSRC" | xargs -0r touch --no-dereference --date="@${SOURCE_DATE_EPOCH}" find . | sort \ | zip -X@ "${OUTDIR}/${DISTNAME}-${HOST}.zip" + + # Make a DMG from dist/ + xorrisofs -D -l -V "$(< ../osx_volname)" -no-pad -r -dir-mode 0755 \ + -o "${OUTDIR}/${DISTNAME}-${HOST}.dmg" \ + . \ + -- -volume_date all_file_dates ="$SOURCE_DATE_EPOCH" ;; *) exit 1 diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 7335596107..69d1a46228 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -3,6 +3,7 @@ ((gnu packages bash) #:select (bash-minimal)) (gnu packages bison) ((gnu packages certs) #:select (nss-certs)) + ((gnu packages cdrom) #:select (xorriso)) ((gnu packages cmake) #:select (cmake-minimal)) (gnu packages commencement) (gnu packages compression) @@ -525,5 +526,5 @@ inspecting signatures in Mach-O binaries.") ((string-contains target "-linux-") (list (make-bitcoin-cross-toolchain target))) ((string-contains target "darwin") - (list clang-toolchain-17 binutils cmake-minimal python-signapple zip)) + (list clang-toolchain-17 binutils cmake-minimal xorriso python-signapple zip)) (else '()))))) diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md index ea599df3d8..061d685b4f 100644 --- a/contrib/macdeploy/README.md +++ b/contrib/macdeploy/README.md @@ -6,7 +6,7 @@ The `macdeployqtplus` script should not be run manually. Instead, after building make deploy ``` -When complete, it will have produced `Bitcoin-Core.zip`. +When complete, it will have produced `Bitcoin-Core.dmg` and `Bitcoin-Core.zip`. ## SDK Extraction @@ -56,8 +56,8 @@ The `sha256sum` should be `c0c2e7bb92c1fee0c4e9f3a485e4530786732d6c6dd9e9f418c28 ## Deterministic macOS App Notes -macOS Applications are created in Linux by combining a recent `clang` and the Apple -`binutils` (`ld`, `ar`, etc). +Working macOS DMGs are created in Linux by combining a recent `clang`, the Apple +`binutils` (`ld`, `ar`, etc) and DMG authoring tools. Apple uses `clang` extensively for development and has upstreamed the necessary functionality so that a vanilla clang can take advantage. It supports the use of `-F`, @@ -87,15 +87,20 @@ created using these tools. The build process has been designed to avoid includin SDK's files in Guix's outputs. All interim tarballs are fully deterministic and may be freely redistributed. +[`xorrisofs`](https://www.gnu.org/software/xorriso/) is used to create the DMG. + +A background image is added to DMG files by inserting a `.DS_Store` during creation. + As of OS X 10.9 Mavericks, using an Apple-blessed key to sign binaries is a requirement in order to satisfy the new Gatekeeper requirements. Because this private key cannot be shared, we'll have to be a bit creative in order for the build process to remain somewhat deterministic. Here's how it works: -- Builders use Guix to create an unsigned release. This outputs an unsigned ZIP which +- Builders use Guix to create an unsigned release. This outputs an unsigned DMG and ZIP which users may choose to bless and run. It also outputs an unsigned app structure in the form - of a tarball. + of a tarball, which also contains all of the tools that have been previously (deterministically) + built in order to create a final DMG. - The Apple keyholder uses this unsigned app to create a detached signature, using the script that is also included there. Detached signatures are available from this [repository](https://github.com/bitcoin-core/bitcoin-detached-sigs). - Builders feed the unsigned app + detached signature back into Guix. It uses the - pre-built tools to recombine the pieces into a deterministic ZIP. + pre-built tools to recombine the pieces into a deterministic DMG. diff --git a/contrib/macdeploy/background.tiff b/contrib/macdeploy/background.tiff new file mode 100644 index 0000000000..e69de29bb2 diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 4b1d72650d..0cfb46a287 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -18,6 +18,8 @@ import sys, re, os, platform, shutil, stat, subprocess, os.path from argparse import ArgumentParser +from ds_store import DSStore +from mac_alias import Alias from pathlib import Path from subprocess import PIPE, run from typing import Optional @@ -383,7 +385,7 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme ap = ArgumentParser(description="""Improved version of macdeployqt. -Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .zip file. +Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg and/or .zip file. Note, that the "dist" folder will be deleted before deploying on each run. Optionally, Qt translation files (.qm) can be added to the bundle.""") @@ -393,6 +395,7 @@ ap.add_argument("appname", nargs=1, metavar="appname", help="name of the app bei ap.add_argument("-verbose", nargs="?", const=True, help="Output additional debugging information") ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment") ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries") +ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image") ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translations. Base translations will automatically be added to the bundle's resources.") ap.add_argument("-zip", nargs="?", const="", metavar="zip", help="create a .zip containing the app bundle") @@ -415,7 +418,14 @@ if os.path.exists("dist"): print("+ Removing existing dist folder +") shutil.rmtree("dist") -if os.path.exists(appname + ".zip"): +if config.dmg is not None and os.path.exists(appname + ".dmg"): + print("+ Removing existing DMG +") + os.unlink(appname + ".dmg") + +if os.path.exists(appname + ".temp.dmg"): + os.unlink(appname + ".temp.dmg") + +if config.zip is not None and os.path.exists(appname + ".zip"): print("+ Removing existing .zip +") os.unlink(appname + ".zip") @@ -492,9 +502,100 @@ with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f: # ------------------------------------------------ +print("+ Generating .DS_Store +") + +output_file = os.path.join("dist", ".DS_Store") + +ds = DSStore.open(output_file, 'w+') + +ds['.']['bwsp'] = { + 'WindowBounds': '{{300, 280}, {500, 343}}', + 'PreviewPaneVisibility': False, +} + +icvp = { + 'gridOffsetX': 0.0, + 'textSize': 12.0, + 'viewOptionsVersion': 1, + 'backgroundImageAlias': b'\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00', + 'backgroundColorBlue': 1.0, + 'iconSize': 96.0, + 'backgroundColorGreen': 1.0, + 'arrangeBy': 'none', + 'showIconPreview': True, + 'gridSpacing': 100.0, + 'gridOffsetY': 0.0, + 'showItemInfo': False, + 'labelOnBottom': True, + 'backgroundType': 2, + 'backgroundColorRed': 1.0 +} +alias = Alias().from_bytes(icvp['backgroundImageAlias']) +alias.volume.name = appname +alias.volume.posix_path = '/Volumes/' + appname +icvp['backgroundImageAlias'] = alias.to_bytes() +ds['.']['icvp'] = icvp + +ds['.']['vSrn'] = ('long', 1) + +ds['Applications']['Iloc'] = (370, 156) +ds['Bitcoin-Qt.app']['Iloc'] = (128, 156) + +ds.flush() +ds.close() + +# ------------------------------------------------ + if platform.system() == "Darwin": subprocess.check_call(f"codesign --deep --force --sign - {target}", shell=True) +print("+ Installing background.tiff +") + +bg_path = os.path.join('dist', '.background', 'background.tiff') +os.mkdir(os.path.dirname(bg_path)) + +tiff_path = os.path.join('contrib', 'macdeploy', 'background.tiff') +shutil.copy2(tiff_path, bg_path) + +# ------------------------------------------------ + +print("+ Generating symlink for /Applications +") + +os.symlink("/Applications", os.path.join('dist', "Applications")) + +# ------------------------------------------------ + +if config.dmg is not None: + + print("+ Preparing .dmg disk image +") + + if verbose: + print("Determining size of \"dist\"...") + size = 0 + for path, dirs, files in os.walk("dist"): + for file in files: + size += os.path.getsize(os.path.join(path, file)) + size += int(size * 0.15) + + if verbose: + print("Creating temp image for modification...") + + tempname: str = appname + ".temp.dmg" + + run(["hdiutil", "create", tempname, "-srcfolder", "dist", "-format", "UDRW", "-size", str(size), "-volname", appname], check=True, text=True) + + if verbose: + print("Attaching temp image...") + output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, text=True, stdout=PIPE).stdout + + print("+ Finalizing .dmg disk image +") + + run(["hdiutil", "detach", f"/Volumes/{appname}"], text=True) + + run(["hdiutil", "convert", tempname, "-format", "UDZO", "-o", appname, "-imagekey", "zlib-level=9"], check=True, text=True) + + os.unlink(tempname) + # ------------------------------------------------ if config.zip is not None: diff --git a/depends/README.md b/depends/README.md index 1b752f7b04..5e9c0f6668 100644 --- a/depends/README.md +++ b/depends/README.md @@ -48,7 +48,7 @@ The paths are automatically configured and no other options are needed unless ta #### For macOS cross compilation - sudo apt-get install curl bsdmainutils cmake libz-dev python3-setuptools zip + sudo apt-get install curl bsdmainutils cmake libz-dev python3-setuptools xorriso zip Note: You must obtain the macOS SDK before proceeding with a cross-compile. Under the depends directory, create a subdirectory named `SDKs`. diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk new file mode 100644 index 0000000000..51a95f48ef --- /dev/null +++ b/depends/packages/native_ds_store.mk @@ -0,0 +1,15 @@ +package=native_ds_store +$(package)_version=1.3.0 +$(package)_download_path=https://github.com/dmgbuild/ds_store/archive/ +$(package)_file_name=v$($(package)_version).tar.gz +$(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d +$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages + +define $(package)_build_cmds + python3 setup.py build +endef + +define $(package)_stage_cmds + mkdir -p $($(package)_install_libdir) && \ + python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir) +endef diff --git a/depends/packages/native_mac_alias.mk b/depends/packages/native_mac_alias.mk new file mode 100644 index 0000000000..ddd631186e --- /dev/null +++ b/depends/packages/native_mac_alias.mk @@ -0,0 +1,15 @@ +package=native_mac_alias +$(package)_version=2.2.0 +$(package)_download_path=https://github.com/dmgbuild/mac_alias/archive/ +$(package)_file_name=v$($(package)_version).tar.gz +$(package)_sha256_hash=421e6d7586d1f155c7db3e7da01ca0dacc9649a509a253ad7077b70174426499 +$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages + +define $(package)_build_cmds + python3 setup.py build +endef + +define $(package)_stage_cmds + mkdir -p $($(package)_install_libdir) && \ + python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir) +endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index fb52fd4499..86ede3a5a2 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -27,7 +27,7 @@ multiprocess_native_packages = native_libmultiprocess native_capnp usdt_linux_packages=systemtap -darwin_native_packages = +darwin_native_packages = native_ds_store native_mac_alias ifneq ($(build_os),darwin) darwin_native_packages += native_cctools native_libtapi diff --git a/doc/build-osx.md b/doc/build-osx.md index 5c3dc1ac7f..cd78a25426 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -163,9 +163,15 @@ brew install python #### Deploy Dependencies -You can deploy a `.zip` containing the Bitcoin Core application using `make deploy`. +You can deploy a `.dmg` and `.zip` containing the Bitcoin Core application using `make deploy`. It is required that you have `python` installed. +Ensuring that `python` is installed, you can install the deploy dependencies by running the following commands in your terminal: + +``` bash +pip3 install ds_store mac_alias +``` + ## Building Bitcoin Core ### 1. Configuration @@ -223,7 +229,7 @@ make check # Run tests if Python 3 is available ### 3. Deploy (optional) -You can also create a `.zip` containing the `.app` bundle by running the following command: +You can also create a `.dmg` and `.zip` containing the `.app` bundle by running the following command: ``` bash make deploy From 04e5051059d4aa913b5a0c31da34224bf385ea5f Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 29 Feb 2024 00:22:18 +0000 Subject: [PATCH 5/8] build: Create DMG and ZIP together when using macdeployqtplus --- Makefile.am | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index aa80c08c3c..cbf3bfdaec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -125,11 +125,8 @@ osx_volname: echo $(OSX_VOLNAME) >$@ if BUILD_DARWIN -$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) - $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -dmg - -$(OSX_ZIP): $(OSX_APP_BUILT) $(OSX_PACKAGING) - $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -zip +$(OSX_DMG) $(OSX_ZIP): $(OSX_APP_BUILT) $(OSX_PACKAGING) + $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -zip deploydir: $(OSX_DMG) $(OSX_ZIP) else !BUILD_DARWIN From fd41c8ce90d57836037c8c3b9aa4bf7d67ea9384 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 26 Mar 2024 18:23:34 +0000 Subject: [PATCH 6/8] Bugfix: macOS: Open Finder automatically when DMG is mounted --- Makefile.am | 5 ++++- contrib/guix/libexec/codesign.sh | 4 ++++ contrib/macdeploy/make-dmg-open-finder | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100755 contrib/macdeploy/make-dmg-open-finder diff --git a/Makefile.am b/Makefile.am index cbf3bfdaec..558e90f3b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,6 +39,7 @@ OSX_APP=Bitcoin-Qt.app OSX_VOLNAME = $(subst $(space),-,$(PACKAGE_NAME)) OSX_DMG = $(OSX_VOLNAME).dmg OSX_ZIP = $(OSX_VOLNAME).zip +MAKE_DMG_OPEN_FINDER_SCRIPT=$(top_srcdir)/contrib/macdeploy/make-dmg-open-finder OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed @@ -65,6 +66,7 @@ WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \ $(top_srcdir)/doc/README_windows.txt OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_INSTALLER_ICONS) \ + $(MAKE_DMG_OPEN_FINDER_SCRIPT) \ $(top_srcdir)/contrib/macdeploy/detached-sig-create.sh COVERAGE_INFO = $(COV_TOOL_WRAPPER) baseline.info \ @@ -133,7 +135,8 @@ else !BUILD_DARWIN APP_DIST_DIR=$(top_builddir)/dist $(OSX_DMG): deploydir - $(XORRISOFS) -D -l -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -o $@ $(APP_DIST_DIR) -- $(if $(SOURCE_DATE_EPOCH),-volume_date all_file_dates =$(SOURCE_DATE_EPOCH)) + $(XORRISOFS) -D -l -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -hfsplus -o $@ $(APP_DIST_DIR) -- $(if $(SOURCE_DATE_EPOCH),-volume_date all_file_dates =$(SOURCE_DATE_EPOCH)) + $(PYTHON) $(MAKE_DMG_OPEN_FINDER_SCRIPT) $@ $(OSX_ZIP): deploydir if [ -n "$(SOURCE_DATE_EPOCH)" ]; then find $(APP_DIST_DIR) -exec touch -d @$(SOURCE_DATE_EPOCH) {} +; fi diff --git a/contrib/guix/libexec/codesign.sh b/contrib/guix/libexec/codesign.sh index 9f5c549aa2..20e2426f88 100755 --- a/contrib/guix/libexec/codesign.sh +++ b/contrib/guix/libexec/codesign.sh @@ -24,6 +24,8 @@ if [ -n "$V" ]; then export VERBOSE="$V" fi +SRCDIR="$(realpath "$(dirname "$0")")" + # Check that required environment variables are set cat << EOF Required environment variables as seen inside the container: @@ -94,9 +96,11 @@ mkdir -p "$DISTSRC" # Make a DMG from dist/ xorrisofs -D -l -V "$(< ../osx_volname)" -no-pad -r -dir-mode 0755 \ + -hfsplus \ -o "${OUTDIR}/${DISTNAME}-${HOST}.dmg" \ . \ -- -volume_date all_file_dates ="$SOURCE_DATE_EPOCH" + python3 "${SRCDIR}"/../../macdeploy/make-dmg-open-finder "${OUTDIR}/${DISTNAME}-${HOST}.dmg" ;; *) exit 1 diff --git a/contrib/macdeploy/make-dmg-open-finder b/contrib/macdeploy/make-dmg-open-finder new file mode 100755 index 0000000000..1ddae862a2 --- /dev/null +++ b/contrib/macdeploy/make-dmg-open-finder @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +# Copyright (c) 2023 Luke Dashjr +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import sys + +with open(sys.argv[1], "r+b") as dmg: + # Ensure HFS+ header is where we expect it + dmg.seek(0x10400) + assert dmg.read(4) == b'\x48\x2b\0\x04' + + # Set Finder info to open directory ID 2 when mounted + dmg.seek(0x10458) + dmg.write(b'\0\0\0\x02') From 534704fe8344b33dad9ad8db3185786a724ca4de Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 13 Mar 2024 16:27:18 +0000 Subject: [PATCH 7/8] Bugfix: Keep ZIP temp files out of dist dir so DMG can be made in parallel --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 558e90f3b3..5dc33a4587 100644 --- a/Makefile.am +++ b/Makefile.am @@ -140,7 +140,7 @@ $(OSX_DMG): deploydir $(OSX_ZIP): deploydir if [ -n "$(SOURCE_DATE_EPOCH)" ]; then find $(APP_DIST_DIR) -exec touch -d @$(SOURCE_DATE_EPOCH) {} +; fi - cd $(APP_DIST_DIR) && find . | sort | $(ZIP) -X@ $@ + cd $(APP_DIST_DIR) && find . | sort | $(ZIP) --temp-path .. -X@ $@ $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING) INSTALL_NAME_TOOL=$(INSTALL_NAME_TOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) From 526626ce9de6c942943450c50223d46431e215c9 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 7 Jun 2024 19:07:43 +0000 Subject: [PATCH 8/8] macdeployqtplus: Restore Finder background image --- configure.ac | 2 +- contrib/macdeploy/background.tiff | 0 contrib/macdeploy/background.tiff.in | 1 + contrib/macdeploy/macdeployqtplus | 9 +++++++-- 4 files changed, 9 insertions(+), 3 deletions(-) delete mode 100644 contrib/macdeploy/background.tiff create mode 100644 contrib/macdeploy/background.tiff.in diff --git a/configure.ac b/configure.ac index fab23d971b..d7a178620e 100644 --- a/configure.ac +++ b/configure.ac @@ -1880,7 +1880,7 @@ AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/spl AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])]) AC_CONFIG_LINKS([contrib/devtools/iwyu/bitcoin.core.imp:contrib/devtools/iwyu/bitcoin.core.imp]) AC_CONFIG_LINKS([contrib/filter-lcov.py:contrib/filter-lcov.py]) -AC_CONFIG_LINKS([contrib/macdeploy/background.tiff:contrib/macdeploy/background.tiff]) +AC_CONFIG_LINKS([contrib/macdeploy/background.tiff.in:contrib/macdeploy/background.tiff.in]) AC_CONFIG_LINKS([src/.bear-tidy-config:src/.bear-tidy-config]) AC_CONFIG_LINKS([src/.clang-tidy:src/.clang-tidy]) AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py]) diff --git a/contrib/macdeploy/background.tiff b/contrib/macdeploy/background.tiff deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/contrib/macdeploy/background.tiff.in b/contrib/macdeploy/background.tiff.in new file mode 100644 index 0000000000..26812bc530 --- /dev/null +++ b/contrib/macdeploy/background.tiff.in @@ -0,0 +1 @@ +{Wp48S^xk9=GL@E0stWa761SMbT8$j;7A`Tj$HsG;G_T)03$WA1SA$@U8ir`wA%{iC?N~uC|B4-pbzKi?C%LnsO3PoJ6^@@1+y)Kb8i2rpfsQ|H78cOJa;7)^!k*Kd;alsr$^svjxjc2nC~mKs<#J5DUw7I~m)Z_X#i_S&Rw1+t4cc?d$Vn!NPCv7(gK|^OI$>kVvqdBJhFPw5V63<#oK-I`Bb|oySuR(Cr;2(u191Wr62tI_XB{RO$o-5;+SpREcqEVtwW%G4D#%WC^m_(lJNvPz@A3=|+j2|sa)dRnrJUvDL`(_vv8(tBnsxcc03URQ*>$v?@p3$9Rc7`*QW(OUP;d*IRJ|~RJh)+SwF6x7hRkzLuF`B)`NV|Id90L$D}dAAw?fB&el(#(O@JHqJrs4fYQx-()%Fp}e>}g2FfIQsf(kKhaWz)>r0xXCLp5|EY>{A5i_C}uHuLe*;7Z-nW3KqN{}FthcveT0$(^8C&`QX7$+9HOLbY0O?SeUnqJ@b~C`TA&0u@B&sbrXCjx0D%4sKf2atMLcf0n?m_=B>Cs&^#!#3gi8kgjk~TmX*_*qoB|W>!`21`^WA*m>njSkBKa#}=SwePJn3+{PpaaJu?BfCG?ezE>fPm=LpSy0QnXtDKisMY>|OUI>JbMlh}-!Fb=5$hHi=}(qF_5>?6wMM18lscJ{7x9ww;9REm*bAIl?F7eAz4(7L}am$0^Rl$vU!9*;!NYC_e7+)#dl;cS@OrshE0;sXKEiBk1jrL0L&%*nptP$VJpDp5{)L1+ZTN5CwmF6R$nmr6JCf947~$_K%G3KL+uKl7~7A|KfFwH;8w&}yrY=mz(EtQnKp02fmq*q72^fj1m2Yi@nmb<9!*RtQYL*2ZE-?Z-AVgZaE3DS;m1;0yo{Mvu!n@SfHmOag@LFz%~eCDDjr|x26fhjmd(c_3!z>)c7%I5n(yE^@RUTMeyz$=c6=mQhpbsn4H>`*S&`%(PF(rc&zO+h7^E}w!q!ekPq=jFg3^|fF}N=wyOk`d*oC$^$!xYX8@ecc?)K74*b52Qbgi-XUQ^H4tPGE0v`Y~xc&VcrBU7=MknLAfKn*|(z5qqbjhnl^!Ih~gmB_&m@51gD6?*AE*TgCO5Y?{L5R<}O7!Ke8Cvj&gu@WoBBggVR$`|>wFL+@Sb)9_azONSTN_GWO;B|`FP{6R%%kv6f&mW!pjnexmVAouy_iB%bq(`FKxf~MAubTXgKTtB}J_!KFyHSVB1DT1=#dcStlU4fMTNmxfan8E@yJIX5Nh96pJtfJ2UN$owQ7N5^rt1wyg3Xyb;^X){z&E{#rJfWVAjv+62e&cumwdu)E8z(4rm^yR0y#cc04)JEi2Uv-5fBNt@eiI}2FJk!FSqDawwIFn7R?@fz)W;R_Wx<)5TOa5KP0TVVt&%8yXXcw5Ho%2a#cj+16N+U`Lj9tjL*-A$b1&)9QZ`38>H~|jODNsEg7$m3UWrj&+EL6p|S{YLg3oqlr#3Lw3T%q5IfM%2MizusDhOu|Z?oYp!<+@|PD6PB74U;m3t`3-ZN7-E1JG6zH*wdim*1R;3j88Q@E(FD*)eTpnFc?TTdN)t;r-zer6e&tZ^Cj=a}}h2p?~tpI3K=43uTi6!5WsxA;owQqvHqTT@|3e!Ni%4-*?|+h+zXo5f5(6|AD4YyYtu-2jM^6m%;!`RWPS;wLs31L_D2x)~@XPXs?cmDTl`!idNWnYzFicytpCZE7}8Y^l8=j4RT@#k1KO!&$uR)Ah#=CIkAeu2Y;2!$Vc*@kH&(pWdp_#9eCEtW%d)q_3iKpJT$N)FLoY+Hj9}#-N2Tm2ixr!Q7S6^3(_Lk1f#Auqno*0dqohtx@*~>UERm_WOU5xO*CH4fl&n`1=~B|s=$U~KOSC&wiIhcJBWnQY(q<3jL%1?v^8~Ot^g|aUHBe8j5RfhE)V}XvDT?@KZ>XFG~((hYuD$nH6hjp2yGQz0}I?o0IU@wwBl+Y*=*&z;jx9N%E%l@d+@;=LUHWa3bvkr_Vop_E)pmkn(<8v?5a4G#oLN(bve*i#nB7UU`dvhkdE+Dq|`QV#NHs;u$D{%n|v3}DMMZ!M^&q28ayDN_n)j(;bFYX^QstF^FMOT408z;O+eg-;%JV3{}j*B(ZgM^@=Nil;poQD$^Cs~XIHxk#Ko4@{Fy!8IVTVe3aE{^vXz_y;C7QY+74j2bz8WC(!FE;R%~`H`vvcwYpkq%`zG$VCE^XO3IW;G=52b3GDdnT#Qf4d!lvJ&+L`~dByc2TgKZuORMoqeYKsQrXe(hd!O5!*x}7nXjDcYFd%z?a`B2!$Af`=F!)>v$@PrBQu-C3g3Hkoi{lWd3q;0Pq`P5O#~*;5Kjb@H;5RNhHljW{aQLSju^J3A33h|t02#x=i)Y=mS}|y-fU6&n_lsK%f1r<#7qD=v^_nHNNV4vQH8X}FuoRI77x{iHD@@YI216&^0@(Yb50y}a~`@Bluw2b%}LrviouBrCQX=1(GQ@^GA*$xHkd^EKm51E8RvAayhS315w&M9I`0}YE+J&2tTKKTcOIAVxYBu_@u#G>QInhnBF+lz!=z+}NQR!a0RQJQO;(Dvu5PgS)QOuuLl!UguA%P(9dHd=f!sZ=IqY{L=v5mN%GFo=Lw!|tQLkYd7wb_y^u0;bnTtE?es-MZe)e`jWm3PooE7Vs4DYGX->rqYbi6T8h~hmj869{UiI=i^8kEMhmO}AG&;wQG$DVMHh$q8yv$p!1pm>?I-9^2ATCJMU@zbbxv80HsRRlKA2v(F)>bmF}uSO}j@(+J**m(w~(%2hQax8)VmQ*PuK}#V=m{j1i99TlGPwN4fec^FYnXKKG0&Xo8y)iG;Pol`>lCJn&Nnw;p0BeW_+KHtG9ROz3-(@U29Xr00tJtDiqn-spCJ%#m9~cwN9%23#^DUv8{UU7&qE&dl|dDh+ky5k_v1~nThIC(#urJcEQ`4Q2l~Wa;)mF00@xT#`f`WT;CBlIi-N)wPGQ69n*%BXr6dA{p;daHFaQqL(^Ndu3wA@OXo;xSlf;2#U>&HSgA4X@9LK1i0QqYATPAgo+~ZRIu@Oe@f@-Vqnxk|$_vyPaXvmDEVl5A;wJQU6R(xe68pSQU$%}lE>O@jZDKA2fUnq54^D!bf`&m0-7i`#m#lvbH$yGk>kq+zewcEuMxb!8~jcIWT3yI^MXYEtWYP>>5Y%d=T^&AHM=XQ*}&;i=gWi`O;hGJPr)6(Am;PjMo0JhW}sZyHdhlI@AsiYIA=h*;@DyANie>biwD)xPczW2}59tfOlQV3X=ms0X$dV*F8D>chB1gWXdFC?XKQHtsQlVa#T9eS=WD~Dd8s)BQ|$S92a&&2J84|N>NbEyv9y|_!&<0MclJ3i4vu#j4BXAosmkn`d8Z?egPo=y=j$lSh+l1Yj(=`JJnAziVmu@Ru;j8*MRfJ<5}cRWy$kd*OmI%tg(NCxTHXqJ1@Uh&1La!9Ky#ugXVY%~5q(1B7i!#GYUdYQJ5m;VZDq6c;2$qVV(GWJBWTJTUGt3lwh!L7LhSN_Di8C$(F}A3i_9mle9Az5Q`1}Rd4qSXq+kIQ;Tjm&HP1+6V5|k50IUs1%}}8UyPEv+1!IVzy!Ik3SHC6XuPzf`Y_aBg$;-&(xQIL+0hBW~4zMr`jq*s*xS3Om63BYfJal<%Gesy;$gRs+IS#yt6e?5K*Da>!nggxj%Ri8H*z1i!3nP>KNBhp>_H<_vFH*CpTtO(}LfG;=0jK8Y0EURQ>fhI0m|nNks_si>_E5}>f#94OS)-<}GaT{>4O$=Kz4oR1Avgy+nk11*az2b3O8T>v+o2>*$&R(UvZdvk}YnOKYlGx{ZKT(K>h{S98lLoh#ymST|+yEENST|KNT*pGFBVDc{~PXz|oUwm(%v{4)3|pCJ$N>C;GAmn=mc{&pHh1dde!$cG_=TT|+uJaqMwKM9sfjRo6KknlRe_0R{Algb$_{^E9sAW9p6iVZ3xG&=bYrGyi1{!vvHnz3)n}ey==N3Zp^lLf!8F9pbRjc1orC#A5Vfdh*ink#!$1rt}3p+=$oyXRl(ladR%sXC9-31m2-q$T3TgjPl~dJ4CpaO-*LCJGnQJ~JqCAO3NzW`RINPTlKYD{h^$lE1^AHoUN#=kKXrhdk7d^VH+}hQmP?bMm!Ld+qTZ=QzD*LIAh`^elZ(#H><1Y8OT1&(rl(PJ21SDu%VPBe1k;GC57g1=!PH<31m8>j1qXVu(D+gq;jZ3dumqH2w$vV+9xHf3X$iu4vsssp0%(>(k6sFsxS356$8SgjDhR5-rJEum*ok*XGh)I!I8lp!rRhw4(x9*uw9VKoWU5-zGJkx;2)3mt-*6CotMtW>2Szg)Rpgh8NZR{`MG?T4mgIF+j>{Kk~V>GUJ1owQRag!uzdy5AyN>*|3hF1b-h=={zbrXkg>yxW})6!rtIlVwD1YaVH1;pOq<%X1m3};J0wN*n#s1p$!TAqBXDp&Q3Hv?D$>;<2+zpAk+-(Wc|^`QOrF4vCBM%x2QF*Es}y&|Px6duMUpXSU6)yXzZZ{{fiO0f>H632oXn?;>)BQ)9}}X+j|qOQ9Unz%{;HegmI0{mCUh(25Y9J$Eg>H&lr#K{=XFEZDkGd<>XeI~a1VFcGt)q=8GITK!59AMhH_b8KQ$Dog0*h3ZL2aIbgn#`ml^#pIr=Gt>#?Jf7ntf`l9AnRU3%OYH|vSxa@v82)SnJ7XOD*?B-K75zC|<^f;z9$p@IXh{m<-$-^PhJ0b|bDs^ga=VzxK@8g{?9SBtkiSNlhq24#ji|jEv0l}+`EYNW18=aY!zabz=oj=&UT&E;JCevHEiQmbxDW&M$QDw2K4rQ#Tg>#IcFV^W*bv=R;2jd5wZi@&hNw6Xk>nDg9!J^c0g81&aKp{ZU%anz(u3EnFeQ7%(tY$QJ^)iJ(gdB8KE8nQHftI2HL-hrcGkfqFi^0w7ZkW=*5+F6WPaBE+Tea{37J)D@UFL{qQtY~1T9E*j=GO$(==j>Flt~R0gO^cf0ESMHq^QEuYty5c6TSE(l*qMuG@`DbAGRlEEHeV0Z>W*T$G2w)zfQoUr^0rn0w1$fIteL$M)fJJptCo>GAJW{=^~zF%^SOW=`$FmB@sEi#b{sRgM=1!;?=~VC#-1PTK0&ELRcjzY9itEbu>j0vC%l_ectf;Ht$G+vwhj>JQecl`nmK(bUo~{uj0R7{$-Z1=y4J&k}O0<`eZlKpZ>fy#)u;1hoL(m}@M{C3Di5W+ikL@ePTqQSk)Z()fF+4A#9zcU8eUD^2qhY2@(&c0&rlbB`AUl5{Td=B5l&)hR%ArLy93~axtnth{73YqCb8TgVoO6?Pbma{83-E8wF7&;aqHvX&mj3ew&3nT+7D~v}$zoCO9wovBZjXG8E`f)yNnw+G`CZ3C*=bHCArQVnmU_g4oxVB~a+{&4T>;AxRn-LlOSUzrn17bJx1Rr$&Em6$2{A@E(s5bH*vIFKTTjz%p(=cjg&>3(KUr8GwMdi$YpK&0KL+u0F*hpaH_rrW7$&8!QU)af&*<^Dr237*0Wu@EdK2w;>e=w3@G=9V%?o7<)1#K6+5CVqLKGayQp^Kt}&k)I%4DNfSn70WR$F#9v-4&3`DL-RW2kGfA&Zmryl}Wd4JG%51eEMl3L?Z*B5ruomJXe!r{OV*`5)f3NuKZTsGPf>h9&%w9yzUD_3pqX>Si(;|S*BLFz<8hlU^@T=hiu~XC`+_AJS+;=c%jqh|6MO_guv`Ba0=yjYJr#Fjck!L_9{csbHdOF4LZ#m-+Y~Tcl_)@TonfR6t!cl-?vw!r^0#BIXkOR!&2u=z9Ga8n6{chy?c6Wp!6`W5!F?TB$d?b^Q0vJ7LA*d3TeEWy?xv+1C?&)xgMdr#2Dqe{dJ3$0{K)8L=azy+_pP!Y8iYFytY`rZV(iSCp*bq}*+(CoE+16U#C00)yWz2k$_OgW#F2E;vZ5x#J!4iFZyU`n?u%nBy;6yBaC*L^k!Jo9wh*H(wJJrD;I4eaaJ6RqjD0!HcoyEnp2Mj|X{(ksdrJVd=iV{D__;ZvTpVqBg!K#pB-lR^U*AnRn!`aFcFWSgqpom9y({=e6z=A&ju#e;yl<45#16ceyX-DWMbE@O-P7yUyY{(Rf_!GH-#a@~WZa3&^aralmEd}=sB2~D%`>O!XJ{`hLyL6FXc$xC^C2OTL_x&<}++Sxnr)uI{ZWC%P(CPBprx;ld1UiZ(Pi-S}GOP)52!trRL{GWdjs~DimYE5u*CP7Olup$&d}U}qPT)*|54tMT2DEx}Y&lHvd0tS)L9rl{P5*v%OZ~^^eOdodB9{H6t6ll=I7U;9B$N+%Gq7w?jbvX-LN13^tVHxQUWQgz*RH&Oz#?O1N!$u4dD=*~cSrA<61r=>zHaD1Zg%k2RYrbipOh5~$QBJrF^%$NNsXLehi%XA^7I7Sb_b}N0X97~SvTXUuT2Skk5`1uI=$$P%Gos;xfS;8+x1E$^*mU-;=x%kkYC4yMtm<}O*TKJU33VCOFAN5D7^kQ#$vRtYBb&h(|;}D#9J~=gVPxMbU}X)he={!T&U^P4o?{vP2h0GbO%J1ZP;^~e|5ja-1WSx0@f^ziQqRg&8jznfriA?{|{UK&^_fO<^@!WY@cr*lsTOL3)k~@y4;p`bXDokQRZqL_99S?ORIZf;;+LU94FT$fVB#UPEj9{+5C8F3(i6v1A@as|rW@mqP8B5W6i~jrSedb3FZB?vB{T5ululAxWr3x#v#HZr8&0nHhxt9me9kNCe2%DjRYtk;1zx1nsGDSQ{wWNKzH6}?E9T6}wL-5pUDW}eFBHtX{8LhzWmF4-rkK$6KDtdPf=qbWMHR9bux+;PY6=cn5!#?D($%`IX1mPkTQQ$6}uCffNUr>dYhakl3aUhX(Rh?W(pUw~_eV$SSLv(O6-vB^gUsHi*z2)(PrbDh^6Qavf}3zgR!oS?j#VUoQrCb?uO!nvI#7>mf&BFonsrCn{WM|l6Bf)dc9a`nc3^<0jVZ4(Q{Nf5kaO{XXWRlH5GJkiOnen_}X{*5ij-eKPaQj5e8x#(sA4V~J{Jy$uB2)+tQWJx6)@dF3%KQnlga$p40C6~D%CS19en^XzL~AL3`FYw-ui$^(o3hIecwFk)8#4THU>Wej_FbhR?5-(y^%2hWAYx{f#aV#YXe=8N7qWOf9}<1n95-g}YnILeZ8&MlDsKOrOvA!Gc63$du~}HYiht=!%cWLx!eocB*oH9Z&#MVLh%per?>5ZIQaLJpwZ?k9&^BPp$^(IEy6m0)7s3+H9p>u@Xz3TZ6x!GWQ7V#^&AF$eh~#m$zEq}-1EZ|0Kx897yN^p5ulu=3OU#0BhMtk#30kZ0^X&6$!ee5%#}9AUYv+;rdq7zs=Y_%>6sz6gwcWM9H7ahX-Ny8h!L|Bd;e#;$R#5P=fROIfdwOppKImIqP&6P$0MWw;apetZvNUfA`Dy=em!b)#C0kwRzSy-26kSRdBwy+L+&!Ox-!f@S$-ROWf~cyJAqm{Kw6Fk@e_CHUHOQ0o@Rzo#|;qS`lD56(<~!02F}m4Q%ldtKiGx%_`c}j3{RH`dz=TG24L@b0mBNM>&$6lA7FCKy_V9+>CT`bqs)&PKBBb{D-^#|wT-$I23s}jId`F5jbdFpc{Ac&6$yie>uBbc_MpXzaI;K^^w5pbNZQY6C0!46ctFCh`tqdOP76Qi0UTmfC)Z9${EKtij-195Ro&CB~X{@a(OtA0L_SfiB{DQ%1DJ<>TB4}v_b1NzcePKzt3^83)DKB@r>1X3Lh(8vwnlk62?@1=8Airs)!Ga3;*lItq66x=te~|vfl`ov0jX;V}XApz4rk-5aKv@_9IDu==A{ShzlS~E4pT2@v!a356fYMh`%JP0a2fwB$@qh2(WHH^G=xBgbU*#QAW^Zdbj<7fuIOvrq;uKEN7SP#3*S7kX~7{?j3`Y@JAoqQn!qQZdDBj0xcNxq~dk$3Yk=v0<{aI&8Fv7VXtiMNERU%>xW#>GwBb(J@QKL5)9q^?yc#DG=X}!gMgw!aDTJF4c(Z~xCKcZ1j(ciEqkhU^Awt<`uZJ_MYB!rKA!TRC;Jq&1Kc?~6o&yo0i574(W-kt4*K-vX=gZ^nhNR+rjP-5&ZW3Hxnr+<7So+_LgGn(;ivMnXK2pap8|j^Y2g3aD@Cr(LQT_z_cEqZ&j)`iJ00000Hqx;zQt65b00F91ppXFoS~fx=vBYQl0ssI200dcD \ No newline at end of file diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 0cfb46a287..e2f22d32f2 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -16,6 +16,8 @@ # along with this program. If not, see . # +import base64 +import lzma import sys, re, os, platform, shutil, stat, subprocess, os.path from argparse import ArgumentParser from ds_store import DSStore @@ -554,8 +556,11 @@ print("+ Installing background.tiff +") bg_path = os.path.join('dist', '.background', 'background.tiff') os.mkdir(os.path.dirname(bg_path)) -tiff_path = os.path.join('contrib', 'macdeploy', 'background.tiff') -shutil.copy2(tiff_path, bg_path) +tiff_in_path = os.path.join('contrib', 'macdeploy', 'background.tiff.in') + +with open(tiff_in_path, 'r') as tiff_in: + with open(bg_path, 'wb') as bg: + bg.write(lzma.decompress(base64.b85decode(tiff_in.read()))) # ------------------------------------------------