make deploy
```
-When complete, it will have produced `Bitcoin-Core.dmg`.
+When complete, it will have produced `Feather.zip`.
## SDK Extraction
The `sha256sum` of the generated TAR.GZ archive should be `df75d30ecafc429e905134333aeae56ac65fac67cb4182622398fd717df77619`.
-## Deterministic macOS DMG Notes
+## Deterministic macOS App Notes
-Working macOS DMGs are created in Linux by combining a recent `clang`, the Apple
-`binutils` (`ld`, `ar`, etc) and DMG authoring tools.
+macOS Applications are created in Linux by combining a recent `clang` and the Apple
+`binutils` (`ld`, `ar`, etc).
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`,
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 DMG which
+- Builders use Guix to create an unsigned release. This outputs an unsigned ZIP which
users may choose to bless and run. It also outputs an unsigned app structure in the form
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 DMG.
+ pre-built tools to recombine the pieces into a deterministic ZIP.
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 List, Optional
ap = ArgumentParser(description="""Improved version of macdeployqt.
-Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file.
+Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .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.""")
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")
config = ap.parse_args()
print("+ Removing existing dist folder +")
shutil.rmtree("dist")
-if 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 os.path.exists(appname + ".zip"):
+ print("+ Removing existing .zip +")
+ os.unlink(appname + ".zip")
# ------------------------------------------------
# ------------------------------------------------
-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['Feather.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 +")
# ------------------------------------------------
-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, universal_newlines=True)
-
- if verbose:
- print("Attaching temp image...")
- output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, universal_newlines=True, stdout=PIPE).stdout
-
- print("+ Finalizing .dmg disk image +")
-
- run(["hdiutil", "detach", f"/Volumes/{appname}"], universal_newlines=True)
-
- run(["hdiutil", "convert", tempname, "-format", "UDZO", "-o", appname, "-imagekey", "zlib-level=9"], check=True, universal_newlines=True)
-
- os.unlink(tempname)
+if config.zip is not None:
+ shutil.make_archive('{}'.format(appname), format='zip', root_dir='dist', base_dir='Feather.app')
# ------------------------------------------------