mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 09:46:52 -05:00
Merge #20422: build: mac deployment unification
b685f60a08
build: mac_alias 2.1.1 (fanquake)5d2cbdf772
macdeploy: use Python 3.6 (fanquake)a42aa94c54
macdeploy: remove runHDIUtil in favor of directly calling subprocess.run (fanquake)adaa26202b
macdeploy: remove existing Bitcoin-Core.dmg if present (fanquake)ccb0325b1b
macdeploy: move qt_conf to where it's used (fanquake)6390a04862
macdeploy: consolidate .DS_Store generation (fanquake)32347cd56a
macdeploy: assume plistlib is available (fanquake)0ab4018c12
macdeploy: have a single level of logging output (fanquake)827d382aa7
macdeploy: remove add-resources argument (fanquake)464b34d4c3
macdeploy: remove codesigning argument (fanquake)4d70d3d7fe
build: automatically determine macOS translations (fanquake) Pull request description: This consolidates our macOS build code so that `.DS_Store` generation is the same when running `make deploy` for macOS when building on Linux and macOS, rather than maintaining two version of code that essentially do the same thing (just slightly differently). It also removes unused code and any AppleScript usage, automates finding translation files and generally simplifies `macdeployqtplus`. It also gets rid of the annoying "popping up" behaviour during DMG generation, names the created image `Bitcoin-Core.dmg` rather than `Bitcoin-Qt.dmg`. ACKs for top commit: dergoegge: ACKb685f60a08
- Less and cleaner code looks good. I tested this with `make deploy` and everything still works + the popup during DMG generation is gone. Tree-SHA512: dcd38344e2dfcfa7ffbccf6226a71425c4d16b421a4881d5ee37b8e7ef393b3e8077262444c39b11912269d8cf688aba897e6518cba8361eb24a03fdd03b8caf
This commit is contained in:
commit
16b31cc4c5
7 changed files with 173 additions and 489 deletions
13
Makefile.am
13
Makefile.am
|
@ -36,12 +36,9 @@ OSX_DMG = $(OSX_VOLNAME).dmg
|
||||||
OSX_BACKGROUND_SVG=background.svg
|
OSX_BACKGROUND_SVG=background.svg
|
||||||
OSX_BACKGROUND_IMAGE=background.tiff
|
OSX_BACKGROUND_IMAGE=background.tiff
|
||||||
OSX_BACKGROUND_IMAGE_DPIS=36 72
|
OSX_BACKGROUND_IMAGE_DPIS=36 72
|
||||||
OSX_DSSTORE_GEN=$(top_srcdir)/contrib/macdeploy/custom_dsstore.py
|
|
||||||
OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
|
OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
|
||||||
OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist
|
|
||||||
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
|
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
|
||||||
OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed
|
OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed
|
||||||
OSX_QT_TRANSLATIONS = ar,bg,ca,cs,da,de,es,fa,fi,fr,gd,gl,he,hu,it,ja,ko,lt,lv,pl,pt,ru,sk,sl,sv,uk,zh_CN,zh_TW
|
|
||||||
|
|
||||||
DIST_CONTRIB = \
|
DIST_CONTRIB = \
|
||||||
$(top_srcdir)/contrib/linearize/linearize-data.py \
|
$(top_srcdir)/contrib/linearize/linearize-data.py \
|
||||||
|
@ -59,9 +56,8 @@ WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
|
||||||
$(top_srcdir)/share/pixmaps/nsis-wizard.bmp \
|
$(top_srcdir)/share/pixmaps/nsis-wizard.bmp \
|
||||||
$(top_srcdir)/doc/README_windows.txt
|
$(top_srcdir)/doc/README_windows.txt
|
||||||
|
|
||||||
OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \
|
OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_INSTALLER_ICONS) \
|
||||||
$(top_srcdir)/contrib/macdeploy/$(OSX_BACKGROUND_SVG) \
|
$(top_srcdir)/contrib/macdeploy/$(OSX_BACKGROUND_SVG) \
|
||||||
$(OSX_DSSTORE_GEN) \
|
|
||||||
$(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
|
$(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
|
||||||
$(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
|
$(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
|
||||||
|
|
||||||
|
@ -117,7 +113,7 @@ osx_volname:
|
||||||
|
|
||||||
if BUILD_DARWIN
|
if BUILD_DARWIN
|
||||||
$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) $(OSX_BACKGROUND_IMAGE)
|
$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) $(OSX_BACKGROUND_IMAGE)
|
||||||
$(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 -volname $(OSX_VOLNAME)
|
$(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -dmg
|
||||||
|
|
||||||
$(OSX_BACKGROUND_IMAGE).png: contrib/macdeploy/$(OSX_BACKGROUND_SVG)
|
$(OSX_BACKGROUND_IMAGE).png: contrib/macdeploy/$(OSX_BACKGROUND_SVG)
|
||||||
sed 's/PACKAGE_NAME/$(PACKAGE_NAME)/' < "$<" | $(RSVG_CONVERT) -f png -d 36 -p 36 -o $@
|
sed 's/PACKAGE_NAME/$(PACKAGE_NAME)/' < "$<" | $(RSVG_CONVERT) -f png -d 36 -p 36 -o $@
|
||||||
|
@ -147,11 +143,8 @@ $(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE_DPIF
|
||||||
$(MKDIR_P) $(@D)
|
$(MKDIR_P) $(@D)
|
||||||
$(TIFFCP) -c none $(OSX_BACKGROUND_IMAGE_DPIFILES) $@
|
$(TIFFCP) -c none $(OSX_BACKGROUND_IMAGE_DPIFILES) $@
|
||||||
|
|
||||||
$(APP_DIST_DIR)/.DS_Store: $(OSX_DSSTORE_GEN)
|
|
||||||
$(PYTHON) $< "$@" "$(OSX_VOLNAME)"
|
|
||||||
|
|
||||||
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
|
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
|
||||||
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
|
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR)
|
||||||
|
|
||||||
deploydir: $(APP_DIST_EXTRAS)
|
deploydir: $(APP_DIST_EXTRAS)
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -6,11 +6,7 @@ The `macdeployqtplus` script should not be run manually. Instead, after building
|
||||||
make deploy
|
make deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
During the deployment process, the disk image window will pop up briefly
|
When complete, it will have produced `Bitcoin-Core.dmg`.
|
||||||
when the fancy settings are applied. This is normal, please do not interfere,
|
|
||||||
the process will unmount the DMG and cleanup before finishing.
|
|
||||||
|
|
||||||
When complete, it will have produced `Bitcoin-Qt.dmg`.
|
|
||||||
|
|
||||||
## SDK Extraction
|
## SDK Extraction
|
||||||
|
|
||||||
|
@ -111,7 +107,7 @@ broken. Only the compression feature is currently used. Ideally, the creation co
|
||||||
and `genisoimage` would no longer be necessary.
|
and `genisoimage` would no longer be necessary.
|
||||||
|
|
||||||
Background images and other features can be added to DMG files by inserting a
|
Background images and other features can be added to DMG files by inserting a
|
||||||
`.DS_Store` before creation. This is generated by the script `contrib/macdeploy/custom_dsstore.py`.
|
`.DS_Store` during creation.
|
||||||
|
|
||||||
As of OS X 10.9 Mavericks, using an Apple-blessed key to sign binaries is a requirement in
|
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
|
order to satisfy the new Gatekeeper requirements. Because this private key cannot be
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Copyright (c) 2013-2018 The Bitcoin Core developers
|
|
||||||
# Distributed under the MIT software license, see the accompanying
|
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
from ds_store import DSStore
|
|
||||||
from mac_alias import Alias
|
|
||||||
import sys
|
|
||||||
|
|
||||||
output_file = sys.argv[1]
|
|
||||||
package_name_ns = sys.argv[2]
|
|
||||||
|
|
||||||
ds = DSStore.open(output_file, 'w+')
|
|
||||||
ds['.']['bwsp'] = {
|
|
||||||
'ShowStatusBar': False,
|
|
||||||
'WindowBounds': '{{300, 280}, {500, 343}}',
|
|
||||||
'ContainerShowSidebar': False,
|
|
||||||
'SidebarWidth': 0,
|
|
||||||
'ShowTabView': False,
|
|
||||||
'PreviewPaneVisibility': False,
|
|
||||||
'ShowToolbar': False,
|
|
||||||
'ShowSidebar': False,
|
|
||||||
'ShowPathbar': True
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = package_name_ns
|
|
||||||
alias.volume.posix_path = '/Volumes/' + package_name_ns
|
|
||||||
alias.volume.disk_image_alias.target.filename = package_name_ns + '.temp.dmg'
|
|
||||||
alias.volume.disk_image_alias.target.carbon_path = 'Macintosh HD:Users:\x00bitcoinuser:\x00Documents:\x00bitcoin:\x00bitcoin:\x00' + package_name_ns + '.temp.dmg'
|
|
||||||
alias.volume.disk_image_alias.target.posix_path = 'Users/bitcoinuser/Documents/bitcoin/bitcoin/' + package_name_ns + '.temp.dmg'
|
|
||||||
alias.target.carbon_path = package_name_ns + ':.background:\x00background.tiff'
|
|
||||||
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()
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>window_bounds</key>
|
|
||||||
<array>
|
|
||||||
<integer>300</integer>
|
|
||||||
<integer>300</integer>
|
|
||||||
<integer>800</integer>
|
|
||||||
<integer>620</integer>
|
|
||||||
</array>
|
|
||||||
<key>background_picture</key>
|
|
||||||
<string>background.tiff</string>
|
|
||||||
<key>icon_size</key>
|
|
||||||
<integer>96</integer>
|
|
||||||
<key>applications_symlink</key>
|
|
||||||
<true/>
|
|
||||||
<key>items_position</key>
|
|
||||||
<dict>
|
|
||||||
<key>Applications</key>
|
|
||||||
<array>
|
|
||||||
<integer>370</integer>
|
|
||||||
<integer>156</integer>
|
|
||||||
</array>
|
|
||||||
<key>Bitcoin-Qt.app</key>
|
|
||||||
<array>
|
|
||||||
<integer>128</integer>
|
|
||||||
<integer>156</integer>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
|
@ -16,9 +16,13 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
import subprocess, sys, re, os, shutil, stat, os.path, time
|
import plistlib
|
||||||
from string import Template
|
import sys, re, os, shutil, stat, os.path
|
||||||
from argparse import ArgumentParser
|
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
|
from typing import List, Optional
|
||||||
|
|
||||||
# This is ported from the original macdeployqt with modifications
|
# This is ported from the original macdeployqt with modifications
|
||||||
|
@ -49,28 +53,18 @@ class FrameworkInfo(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return """ Framework name: {}
|
return f""" Framework name: {frameworkName}
|
||||||
Framework directory: {}
|
Framework directory: {self.frameworkDirectory}
|
||||||
Framework path: {}
|
Framework path: {self.frameworkPath}
|
||||||
Binary name: {}
|
Binary name: {self.binaryName}
|
||||||
Binary directory: {}
|
Binary directory: {self.binaryDirectory}
|
||||||
Binary path: {}
|
Binary path: {self.binaryPath}
|
||||||
Version: {}
|
Version: {self.version}
|
||||||
Install name: {}
|
Install name: {self.installName}
|
||||||
Deployed install name: {}
|
Deployed install name: {self.deployedInstallName}
|
||||||
Source file Path: {}
|
Source file Path: {self.sourceFilePath}
|
||||||
Deployed Directory (relative to bundle): {}
|
Deployed Directory (relative to bundle): {self.destinationDirectory}
|
||||||
""".format(self.frameworkName,
|
"""
|
||||||
self.frameworkDirectory,
|
|
||||||
self.frameworkPath,
|
|
||||||
self.binaryName,
|
|
||||||
self.binaryDirectory,
|
|
||||||
self.binaryPath,
|
|
||||||
self.version,
|
|
||||||
self.installName,
|
|
||||||
self.deployedInstallName,
|
|
||||||
self.sourceFilePath,
|
|
||||||
self.destinationDirectory)
|
|
||||||
|
|
||||||
def isDylib(self):
|
def isDylib(self):
|
||||||
return self.frameworkName.endswith(".dylib")
|
return self.frameworkName.endswith(".dylib")
|
||||||
|
@ -97,7 +91,7 @@ class FrameworkInfo(object):
|
||||||
|
|
||||||
m = cls.reOLine.match(line)
|
m = cls.reOLine.match(line)
|
||||||
if m is None:
|
if m is None:
|
||||||
raise RuntimeError("otool line could not be parsed: " + line)
|
raise RuntimeError(f"otool line could not be parsed: {line}")
|
||||||
|
|
||||||
path = m.group(1)
|
path = m.group(1)
|
||||||
|
|
||||||
|
@ -117,7 +111,7 @@ class FrameworkInfo(object):
|
||||||
info.version = "-"
|
info.version = "-"
|
||||||
|
|
||||||
info.installName = path
|
info.installName = path
|
||||||
info.deployedInstallName = "@executable_path/../Frameworks/" + info.binaryName
|
info.deployedInstallName = f"@executable_path/../Frameworks/{info.binaryName}"
|
||||||
info.sourceFilePath = path
|
info.sourceFilePath = path
|
||||||
info.destinationDirectory = cls.bundleFrameworkDirectory
|
info.destinationDirectory = cls.bundleFrameworkDirectory
|
||||||
else:
|
else:
|
||||||
|
@ -129,7 +123,7 @@ class FrameworkInfo(object):
|
||||||
break
|
break
|
||||||
i += 1
|
i += 1
|
||||||
if i == len(parts):
|
if i == len(parts):
|
||||||
raise RuntimeError("Could not find .framework or .dylib in otool line: " + line)
|
raise RuntimeError(f"Could not find .framework or .dylib in otool line: {line}")
|
||||||
|
|
||||||
info.frameworkName = parts[i]
|
info.frameworkName = parts[i]
|
||||||
info.frameworkDirectory = "/".join(parts[:i])
|
info.frameworkDirectory = "/".join(parts[:i])
|
||||||
|
@ -140,7 +134,7 @@ class FrameworkInfo(object):
|
||||||
info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName)
|
info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName)
|
||||||
info.version = parts[i+2]
|
info.version = parts[i+2]
|
||||||
|
|
||||||
info.deployedInstallName = "@executable_path/../Frameworks/" + os.path.join(info.frameworkName, info.binaryPath)
|
info.deployedInstallName = f"@executable_path/../Frameworks/{os.path.join(info.frameworkName, info.binaryPath)}"
|
||||||
info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory)
|
info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory)
|
||||||
|
|
||||||
info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources")
|
info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources")
|
||||||
|
@ -154,10 +148,10 @@ class FrameworkInfo(object):
|
||||||
class ApplicationBundleInfo(object):
|
class ApplicationBundleInfo(object):
|
||||||
def __init__(self, path: str):
|
def __init__(self, path: str):
|
||||||
self.path = path
|
self.path = path
|
||||||
appName = "Bitcoin-Qt"
|
# for backwards compatibility reasons, this must remain as Bitcoin-Qt
|
||||||
self.binaryPath = os.path.join(path, "Contents", "MacOS", appName)
|
self.binaryPath = os.path.join(path, "Contents", "MacOS", "Bitcoin-Qt")
|
||||||
if not os.path.exists(self.binaryPath):
|
if not os.path.exists(self.binaryPath):
|
||||||
raise RuntimeError("Could not find bundle binary for " + path)
|
raise RuntimeError(f"Could not find bundle binary for {path}")
|
||||||
self.resourcesPath = os.path.join(path, "Contents", "Resources")
|
self.resourcesPath = os.path.join(path, "Contents", "Resources")
|
||||||
self.pluginPath = os.path.join(path, "Contents", "PlugIns")
|
self.pluginPath = os.path.join(path, "Contents", "PlugIns")
|
||||||
|
|
||||||
|
@ -181,30 +175,26 @@ class DeploymentInfo(object):
|
||||||
self.pluginPath = pluginPath
|
self.pluginPath = pluginPath
|
||||||
|
|
||||||
def usesFramework(self, name: str) -> bool:
|
def usesFramework(self, name: str) -> bool:
|
||||||
nameDot = "{}.".format(name)
|
|
||||||
libNameDot = "lib{}.".format(name)
|
|
||||||
for framework in self.deployedFrameworks:
|
for framework in self.deployedFrameworks:
|
||||||
if framework.endswith(".framework"):
|
if framework.endswith(".framework"):
|
||||||
if framework.startswith(nameDot):
|
if framework.startswith(f"{name}."):
|
||||||
return True
|
return True
|
||||||
elif framework.endswith(".dylib"):
|
elif framework.endswith(".dylib"):
|
||||||
if framework.startswith(libNameDot):
|
if framework.startswith(f"lib{name}."):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
|
def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Inspecting with otool: " + binaryPath)
|
print(f"Inspecting with otool: {binaryPath}")
|
||||||
otoolbin=os.getenv("OTOOL", "otool")
|
otoolbin=os.getenv("OTOOL", "otool")
|
||||||
otool = subprocess.Popen([otoolbin, "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
|
otool = run([otoolbin, "-L", binaryPath], stdout=PIPE, stderr=PIPE, universal_newlines=True)
|
||||||
o_stdout, o_stderr = otool.communicate()
|
|
||||||
if otool.returncode != 0:
|
if otool.returncode != 0:
|
||||||
if verbose >= 1:
|
sys.stderr.write(otool.stderr)
|
||||||
sys.stderr.write(o_stderr)
|
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
raise RuntimeError("otool failed with return code {}".format(otool.returncode))
|
raise RuntimeError(f"otool failed with return code {otool.returncode}")
|
||||||
|
|
||||||
otoolLines = o_stdout.split("\n")
|
otoolLines = otool.stdout.split("\n")
|
||||||
otoolLines.pop(0) # First line is the inspected binary
|
otoolLines.pop(0) # First line is the inspected binary
|
||||||
if ".framework" in binaryPath or binaryPath.endswith(".dylib"):
|
if ".framework" in binaryPath or binaryPath.endswith(".dylib"):
|
||||||
otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency.
|
otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency.
|
||||||
|
@ -214,7 +204,7 @@ def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
|
||||||
line = line.replace("@loader_path", os.path.dirname(binaryPath))
|
line = line.replace("@loader_path", os.path.dirname(binaryPath))
|
||||||
info = FrameworkInfo.fromOtoolLibraryLine(line.strip())
|
info = FrameworkInfo.fromOtoolLibraryLine(line.strip())
|
||||||
if info is not None:
|
if info is not None:
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Found framework:")
|
print("Found framework:")
|
||||||
print(info)
|
print(info)
|
||||||
libraries.append(info)
|
libraries.append(info)
|
||||||
|
@ -223,10 +213,10 @@ def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
|
||||||
|
|
||||||
def runInstallNameTool(action: str, *args):
|
def runInstallNameTool(action: str, *args):
|
||||||
installnametoolbin=os.getenv("INSTALLNAMETOOL", "install_name_tool")
|
installnametoolbin=os.getenv("INSTALLNAMETOOL", "install_name_tool")
|
||||||
subprocess.check_call([installnametoolbin, "-"+action] + list(args))
|
run([installnametoolbin, "-"+action] + list(args), check=True)
|
||||||
|
|
||||||
def changeInstallName(oldName: str, newName: str, binaryPath: str, verbose: int):
|
def changeInstallName(oldName: str, newName: str, binaryPath: str, verbose: int):
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Using install_name_tool:")
|
print("Using install_name_tool:")
|
||||||
print(" in", binaryPath)
|
print(" in", binaryPath)
|
||||||
print(" change reference", oldName)
|
print(" change reference", oldName)
|
||||||
|
@ -234,7 +224,7 @@ def changeInstallName(oldName: str, newName: str, binaryPath: str, verbose: int)
|
||||||
runInstallNameTool("change", oldName, newName, binaryPath)
|
runInstallNameTool("change", oldName, newName, binaryPath)
|
||||||
|
|
||||||
def changeIdentification(id: str, binaryPath: str, verbose: int):
|
def changeIdentification(id: str, binaryPath: str, verbose: int):
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Using install_name_tool:")
|
print("Using install_name_tool:")
|
||||||
print(" change identification in", binaryPath)
|
print(" change identification in", binaryPath)
|
||||||
print(" to", id)
|
print(" to", id)
|
||||||
|
@ -242,22 +232,22 @@ def changeIdentification(id: str, binaryPath: str, verbose: int):
|
||||||
|
|
||||||
def runStrip(binaryPath: str, verbose: int):
|
def runStrip(binaryPath: str, verbose: int):
|
||||||
stripbin=os.getenv("STRIP", "strip")
|
stripbin=os.getenv("STRIP", "strip")
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Using strip:")
|
print("Using strip:")
|
||||||
print(" stripped", binaryPath)
|
print(" stripped", binaryPath)
|
||||||
subprocess.check_call([stripbin, "-x", binaryPath])
|
run([stripbin, "-x", binaryPath], check=True)
|
||||||
|
|
||||||
def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional[str]:
|
def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional[str]:
|
||||||
if framework.sourceFilePath.startswith("Qt"):
|
if framework.sourceFilePath.startswith("Qt"):
|
||||||
#standard place for Nokia Qt installer's frameworks
|
#standard place for Nokia Qt installer's frameworks
|
||||||
fromPath = "/Library/Frameworks/" + framework.sourceFilePath
|
fromPath = f"/Library/Frameworks/{framework.sourceFilePath}"
|
||||||
else:
|
else:
|
||||||
fromPath = framework.sourceFilePath
|
fromPath = framework.sourceFilePath
|
||||||
toDir = os.path.join(path, framework.destinationDirectory)
|
toDir = os.path.join(path, framework.destinationDirectory)
|
||||||
toPath = os.path.join(toDir, framework.binaryName)
|
toPath = os.path.join(toDir, framework.binaryName)
|
||||||
|
|
||||||
if not os.path.exists(fromPath):
|
if not os.path.exists(fromPath):
|
||||||
raise RuntimeError("No file at " + fromPath)
|
raise RuntimeError(f"No file at {fromPath}")
|
||||||
|
|
||||||
if os.path.exists(toPath):
|
if os.path.exists(toPath):
|
||||||
return None # Already there
|
return None # Already there
|
||||||
|
@ -266,7 +256,7 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
|
||||||
os.makedirs(toDir)
|
os.makedirs(toDir)
|
||||||
|
|
||||||
shutil.copy2(fromPath, toPath)
|
shutil.copy2(fromPath, toPath)
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Copied:", fromPath)
|
print("Copied:", fromPath)
|
||||||
print(" to:", toPath)
|
print(" to:", toPath)
|
||||||
|
|
||||||
|
@ -280,13 +270,12 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
|
||||||
linkto = framework.version
|
linkto = framework.version
|
||||||
if not os.path.exists(linkfrom):
|
if not os.path.exists(linkfrom):
|
||||||
os.symlink(linkto, linkfrom)
|
os.symlink(linkto, linkfrom)
|
||||||
if verbose >= 2:
|
|
||||||
print("Linked:", linkfrom, "->", linkto)
|
print("Linked:", linkfrom, "->", linkto)
|
||||||
fromResourcesDir = framework.sourceResourcesDirectory
|
fromResourcesDir = framework.sourceResourcesDirectory
|
||||||
if os.path.exists(fromResourcesDir):
|
if os.path.exists(fromResourcesDir):
|
||||||
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
|
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
|
||||||
shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True)
|
shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True)
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Copied resources:", fromResourcesDir)
|
print("Copied resources:", fromResourcesDir)
|
||||||
print(" to:", toResourcesDir)
|
print(" to:", toResourcesDir)
|
||||||
fromContentsDir = framework.sourceVersionContentsDirectory
|
fromContentsDir = framework.sourceVersionContentsDirectory
|
||||||
|
@ -295,7 +284,7 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
|
||||||
if os.path.exists(fromContentsDir):
|
if os.path.exists(fromContentsDir):
|
||||||
toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory)
|
toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory)
|
||||||
shutil.copytree(fromContentsDir, toContentsDir, symlinks=True)
|
shutil.copytree(fromContentsDir, toContentsDir, symlinks=True)
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Copied Contents:", fromContentsDir)
|
print("Copied Contents:", fromContentsDir)
|
||||||
print(" to:", toContentsDir)
|
print(" to:", toContentsDir)
|
||||||
elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout)
|
elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout)
|
||||||
|
@ -303,7 +292,7 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
|
||||||
qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib")
|
qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib")
|
||||||
if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath):
|
if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath):
|
||||||
shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True)
|
shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True)
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Copied for libQtGui:", qtMenuNibSourcePath)
|
print("Copied for libQtGui:", qtMenuNibSourcePath)
|
||||||
print(" to:", qtMenuNibDestinationPath)
|
print(" to:", qtMenuNibDestinationPath)
|
||||||
|
|
||||||
|
@ -317,7 +306,6 @@ def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPat
|
||||||
framework = frameworks.pop(0)
|
framework = frameworks.pop(0)
|
||||||
deploymentInfo.deployedFrameworks.append(framework.frameworkName)
|
deploymentInfo.deployedFrameworks.append(framework.frameworkName)
|
||||||
|
|
||||||
if verbose >= 2:
|
|
||||||
print("Processing", framework.frameworkName, "...")
|
print("Processing", framework.frameworkName, "...")
|
||||||
|
|
||||||
# Get the Qt path from one of the Qt frameworks
|
# Get the Qt path from one of the Qt frameworks
|
||||||
|
@ -325,7 +313,6 @@ def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPat
|
||||||
deploymentInfo.detectQtPath(framework.frameworkDirectory)
|
deploymentInfo.detectQtPath(framework.frameworkDirectory)
|
||||||
|
|
||||||
if framework.installName.startswith("@executable_path") or framework.installName.startswith(bundlePath):
|
if framework.installName.startswith("@executable_path") or framework.installName.startswith(bundlePath):
|
||||||
if verbose >= 2:
|
|
||||||
print(framework.frameworkName, "already deployed, skipping.")
|
print(framework.frameworkName, "already deployed, skipping.")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -357,8 +344,8 @@ def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPat
|
||||||
|
|
||||||
def deployFrameworksForAppBundle(applicationBundle: ApplicationBundleInfo, strip: bool, verbose: int) -> DeploymentInfo:
|
def deployFrameworksForAppBundle(applicationBundle: ApplicationBundleInfo, strip: bool, verbose: int) -> DeploymentInfo:
|
||||||
frameworks = getFrameworks(applicationBundle.binaryPath, verbose)
|
frameworks = getFrameworks(applicationBundle.binaryPath, verbose)
|
||||||
if len(frameworks) == 0 and verbose >= 1:
|
if len(frameworks) == 0:
|
||||||
print("Warning: Could not find any external frameworks to deploy in {}.".format(applicationBundle.path))
|
print(f"Warning: Could not find any external frameworks to deploy in {applicationBundle.path}.")
|
||||||
return DeploymentInfo()
|
return DeploymentInfo()
|
||||||
else:
|
else:
|
||||||
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
|
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
|
||||||
|
@ -477,7 +464,6 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme
|
||||||
plugins.append((pluginDirectory, pluginName))
|
plugins.append((pluginDirectory, pluginName))
|
||||||
|
|
||||||
for pluginDirectory, pluginName in plugins:
|
for pluginDirectory, pluginName in plugins:
|
||||||
if verbose >= 2:
|
|
||||||
print("Processing plugin", os.path.join(pluginDirectory, pluginName), "...")
|
print("Processing plugin", os.path.join(pluginDirectory, pluginName), "...")
|
||||||
|
|
||||||
sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName)
|
sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName)
|
||||||
|
@ -487,7 +473,7 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme
|
||||||
|
|
||||||
destinationPath = os.path.join(destinationDirectory, pluginName)
|
destinationPath = os.path.join(destinationDirectory, pluginName)
|
||||||
shutil.copy2(sourcePath, destinationPath)
|
shutil.copy2(sourcePath, destinationPath)
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Copied:", sourcePath)
|
print("Copied:", sourcePath)
|
||||||
print(" to:", destinationPath)
|
print(" to:", destinationPath)
|
||||||
|
|
||||||
|
@ -503,147 +489,50 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme
|
||||||
if dependency.frameworkName not in deploymentInfo.deployedFrameworks:
|
if dependency.frameworkName not in deploymentInfo.deployedFrameworks:
|
||||||
deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo)
|
deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo)
|
||||||
|
|
||||||
qt_conf="""[Paths]
|
|
||||||
Translations=Resources
|
|
||||||
Plugins=PlugIns
|
|
||||||
"""
|
|
||||||
|
|
||||||
ap = ArgumentParser(description="""Improved version of macdeployqt.
|
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 .dmg file.
|
||||||
Note, that the "dist" folder will be deleted before deploying on each run.
|
Note, that the "dist" folder will be deleted before deploying on each run.
|
||||||
|
|
||||||
Optionally, Qt translation files (.qm) and additional resources can be added to the bundle.
|
Optionally, Qt translation files (.qm) can be added to the bundle.""")
|
||||||
|
|
||||||
Also optionally signs the .app bundle; set the CODESIGNARGS environment variable to pass arguments
|
|
||||||
to the codesign tool.
|
|
||||||
E.g. CODESIGNARGS='--sign "Developer ID Application: ..." --keychain /encrypted/foo.keychain'""")
|
|
||||||
|
|
||||||
ap.add_argument("app_bundle", nargs=1, metavar="app-bundle", help="application bundle to be deployed")
|
ap.add_argument("app_bundle", nargs=1, metavar="app-bundle", help="application bundle to be deployed")
|
||||||
ap.add_argument("-verbose", type=int, nargs=1, default=[1], metavar="<0-3>", help="0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug")
|
ap.add_argument("appname", nargs=1, metavar="appname", help="name of the app being deployed")
|
||||||
|
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-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("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries")
|
||||||
ap.add_argument("-sign", dest="sign", action="store_true", default=False, help="sign .app bundle with codesign tool")
|
ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image")
|
||||||
ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image; if basename is not specified, a camel-cased version of the app name is used")
|
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("-fancy", nargs=1, metavar="plist", default=[], help="make a fancy looking disk image using the given plist file with instructions; requires -dmg to work")
|
|
||||||
ap.add_argument("-add-qt-tr", nargs=1, metavar="languages", default=[], help="add Qt translation files to the bundle's resources; the language list must be separated with commas, not with whitespace")
|
|
||||||
ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translation files")
|
|
||||||
ap.add_argument("-add-resources", nargs="+", metavar="path", default=[], help="list of additional files or folders to be copied into the bundle's resources; must be the last argument")
|
|
||||||
ap.add_argument("-volname", nargs=1, metavar="volname", default=[], help="custom volume name for dmg")
|
|
||||||
|
|
||||||
config = ap.parse_args()
|
config = ap.parse_args()
|
||||||
|
|
||||||
verbose = config.verbose[0]
|
verbose = config.verbose
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
app_bundle = config.app_bundle[0]
|
app_bundle = config.app_bundle[0]
|
||||||
|
appname = config.appname[0]
|
||||||
|
|
||||||
if not os.path.exists(app_bundle):
|
if not os.path.exists(app_bundle):
|
||||||
if verbose >= 1:
|
sys.stderr.write(f"Error: Could not find app bundle \"{app_bundle}\"\n")
|
||||||
sys.stderr.write("Error: Could not find app bundle \"{}\"\n".format(app_bundle))
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
app_bundle_name = os.path.splitext(os.path.basename(app_bundle))[0]
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
|
||||||
translations_dir = None
|
|
||||||
if config.translations_dir and config.translations_dir[0]:
|
|
||||||
if os.path.exists(config.translations_dir[0]):
|
|
||||||
translations_dir = config.translations_dir[0]
|
|
||||||
else:
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not find translation dir \"{}\"\n".format(translations_dir))
|
|
||||||
sys.exit(1)
|
|
||||||
# ------------------------------------------------
|
|
||||||
|
|
||||||
for p in config.add_resources:
|
|
||||||
if verbose >= 3:
|
|
||||||
print("Checking for \"%s\"..." % p)
|
|
||||||
if not os.path.exists(p):
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not find additional resource file \"{}\"\n".format(p))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
|
||||||
|
|
||||||
if len(config.fancy) == 1:
|
|
||||||
if verbose >= 3:
|
|
||||||
print("Fancy: Importing plistlib...")
|
|
||||||
try:
|
|
||||||
import plistlib
|
|
||||||
except ImportError:
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not import plistlib which is required for fancy disk images.\n")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
p = config.fancy[0]
|
|
||||||
if verbose >= 3:
|
|
||||||
print("Fancy: Loading \"{}\"...".format(p))
|
|
||||||
if not os.path.exists(p):
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not find fancy disk image plist at \"{}\"\n".format(p))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(p, 'rb') as fp:
|
|
||||||
fancy = plistlib.load(fp, fmt=plistlib.FMT_XML)
|
|
||||||
except:
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not parse fancy disk image plist at \"{}\"\n".format(p))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
assert "window_bounds" not in fancy or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4)
|
|
||||||
assert "background_picture" not in fancy or isinstance(fancy["background_picture"], str)
|
|
||||||
assert "icon_size" not in fancy or isinstance(fancy["icon_size"], int)
|
|
||||||
assert "applications_symlink" not in fancy or isinstance(fancy["applications_symlink"], bool)
|
|
||||||
if "items_position" in fancy:
|
|
||||||
assert isinstance(fancy["items_position"], dict)
|
|
||||||
for key, value in fancy["items_position"].items():
|
|
||||||
assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int)
|
|
||||||
except:
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Bad format of fancy disk image plist at \"{}\"\n".format(p))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if "background_picture" in fancy:
|
|
||||||
bp = fancy["background_picture"]
|
|
||||||
if verbose >= 3:
|
|
||||||
print("Fancy: Resolving background picture \"{}\"...".format(bp))
|
|
||||||
if not os.path.exists(bp):
|
|
||||||
bp = os.path.join(os.path.dirname(p), bp)
|
|
||||||
if not os.path.exists(bp):
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not find background picture at \"{}\" or \"{}\"\n".format(fancy["background_picture"], bp))
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
fancy["background_picture"] = bp
|
|
||||||
else:
|
|
||||||
fancy = None
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if os.path.exists("dist"):
|
if os.path.exists("dist"):
|
||||||
if verbose >= 2:
|
print("+ Removing existing dist folder +")
|
||||||
print("+ Removing old dist folder +")
|
|
||||||
|
|
||||||
shutil.rmtree("dist")
|
shutil.rmtree("dist")
|
||||||
|
|
||||||
# ------------------------------------------------
|
if os.path.exists(appname + ".dmg"):
|
||||||
|
print("+ Removing existing DMG +")
|
||||||
if len(config.volname) == 1:
|
os.unlink(appname + ".dmg")
|
||||||
volname = config.volname[0]
|
|
||||||
else:
|
|
||||||
volname = app_bundle_name
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
target = os.path.join("dist", "Bitcoin-Qt.app")
|
target = os.path.join("dist", "Bitcoin-Qt.app")
|
||||||
|
|
||||||
if verbose >= 2:
|
print("+ Copying source bundle +")
|
||||||
print("+ Copying source bundle +")
|
if verbose:
|
||||||
if verbose >= 3:
|
|
||||||
print(app_bundle, "->", target)
|
print(app_bundle, "->", target)
|
||||||
|
|
||||||
os.mkdir("dist")
|
os.mkdir("dist")
|
||||||
|
@ -653,141 +542,113 @@ applicationBundle = ApplicationBundleInfo(target)
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if verbose >= 2:
|
print("+ Deploying frameworks +")
|
||||||
print("+ Deploying frameworks +")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose)
|
deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose)
|
||||||
if deploymentInfo.qtPath is None:
|
if deploymentInfo.qtPath is None:
|
||||||
deploymentInfo.qtPath = os.getenv("QTDIR", None)
|
deploymentInfo.qtPath = os.getenv("QTDIR", None)
|
||||||
if deploymentInfo.qtPath is None:
|
if deploymentInfo.qtPath is None:
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n")
|
sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n")
|
||||||
config.plugins = False
|
config.plugins = False
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
if verbose >= 1:
|
sys.stderr.write(f"Error: {str(e)}\n")
|
||||||
sys.stderr.write("Error: {}\n".format(str(e)))
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if config.plugins:
|
if config.plugins:
|
||||||
if verbose >= 2:
|
|
||||||
print("+ Deploying plugins +")
|
print("+ Deploying plugins +")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose)
|
deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
if verbose >= 1:
|
sys.stderr.write(f"Error: {str(e)}\n")
|
||||||
sys.stderr.write("Error: {}\n".format(str(e)))
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if len(config.add_qt_tr) == 0:
|
if config.translations_dir:
|
||||||
add_qt_tr = []
|
if not Path(config.translations_dir[0]).exists():
|
||||||
else:
|
sys.stderr.write(f"Error: Could not find translation dir \"{config.translations_dir[0]}\"\n")
|
||||||
if translations_dir is not None:
|
|
||||||
qt_tr_dir = translations_dir
|
|
||||||
else:
|
|
||||||
if deploymentInfo.qtPath is not None:
|
|
||||||
qt_tr_dir = os.path.join(deploymentInfo.qtPath, "translations")
|
|
||||||
else:
|
|
||||||
sys.stderr.write("Error: Could not find Qt translation path\n")
|
|
||||||
sys.exit(1)
|
|
||||||
add_qt_tr = ["qt_{}.qm".format(lng) for lng in config.add_qt_tr[0].split(",")]
|
|
||||||
for lng_file in add_qt_tr:
|
|
||||||
p = os.path.join(qt_tr_dir, lng_file)
|
|
||||||
if verbose >= 3:
|
|
||||||
print("Checking for \"{}\"...".format(p))
|
|
||||||
if not os.path.exists(p):
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not find Qt translation file \"{}\"\n".format(lng_file))
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("+ Adding Qt translations +")
|
||||||
|
|
||||||
|
translations = Path(config.translations_dir[0])
|
||||||
|
|
||||||
|
regex = re.compile('qt_[a-z]*(.qm|_[A-Z]*.qm)')
|
||||||
|
|
||||||
|
lang_files = [x for x in translations.iterdir() if regex.match(x.name)]
|
||||||
|
|
||||||
|
for file in lang_files:
|
||||||
|
if verbose:
|
||||||
|
print(file.as_posix(), "->", os.path.join(applicationBundle.resourcesPath, file.name))
|
||||||
|
shutil.copy2(file.as_posix(), os.path.join(applicationBundle.resourcesPath, file.name))
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if verbose >= 2:
|
print("+ Installing qt.conf +")
|
||||||
print("+ Installing qt.conf +")
|
|
||||||
|
qt_conf="""[Paths]
|
||||||
|
Translations=Resources
|
||||||
|
Plugins=PlugIns
|
||||||
|
"""
|
||||||
|
|
||||||
with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f:
|
with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f:
|
||||||
f.write(qt_conf.encode())
|
f.write(qt_conf.encode())
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if len(add_qt_tr) > 0 and verbose >= 2:
|
print("+ Generating .DS_Store +")
|
||||||
print("+ Adding Qt translations +")
|
|
||||||
|
|
||||||
for lng_file in add_qt_tr:
|
output_file = os.path.join("dist", ".DS_Store")
|
||||||
if verbose >= 3:
|
|
||||||
print(os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file))
|
|
||||||
shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file))
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
ds = DSStore.open(output_file, 'w+')
|
||||||
|
|
||||||
if len(config.add_resources) > 0 and verbose >= 2:
|
ds['.']['bwsp'] = {
|
||||||
print("+ Adding additional resources +")
|
'WindowBounds': '{{300, 280}, {500, 343}}',
|
||||||
|
'PreviewPaneVisibility': False,
|
||||||
|
}
|
||||||
|
|
||||||
for p in config.add_resources:
|
icvp = {
|
||||||
t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p))
|
'gridOffsetX': 0.0,
|
||||||
if verbose >= 3:
|
'textSize': 12.0,
|
||||||
print(p, "->", t)
|
'viewOptionsVersion': 1,
|
||||||
if os.path.isdir(p):
|
'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',
|
||||||
shutil.copytree(p, t, symlinks=True)
|
'backgroundColorBlue': 1.0,
|
||||||
else:
|
'iconSize': 96.0,
|
||||||
shutil.copy2(p, t)
|
'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)
|
||||||
|
|
||||||
if config.sign and 'CODESIGNARGS' not in os.environ:
|
ds['Applications']['Iloc'] = (370, 156)
|
||||||
print("You must set the CODESIGNARGS environment variable. Skipping signing.")
|
ds['Bitcoin-Qt.app']['Iloc'] = (128, 156)
|
||||||
elif config.sign:
|
|
||||||
if verbose >= 1:
|
ds.flush()
|
||||||
print("Code-signing app bundle {}".format(target))
|
ds.close()
|
||||||
subprocess.check_call("codesign --force {} {}".format(os.environ['CODESIGNARGS'], target), shell=True)
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if config.dmg is not None:
|
if config.dmg is not None:
|
||||||
|
|
||||||
def runHDIUtil(verb: str, image_basename: str, **kwargs) -> int:
|
|
||||||
hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"]
|
|
||||||
if "capture_stdout" in kwargs:
|
|
||||||
del kwargs["capture_stdout"]
|
|
||||||
run = subprocess.check_output
|
|
||||||
else:
|
|
||||||
if verbose < 2:
|
|
||||||
hdiutil_args.append("-quiet")
|
|
||||||
elif verbose >= 3:
|
|
||||||
hdiutil_args.append("-verbose")
|
|
||||||
run = subprocess.check_call
|
|
||||||
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
hdiutil_args.append("-" + key)
|
|
||||||
if value is not True:
|
|
||||||
hdiutil_args.append(str(value))
|
|
||||||
|
|
||||||
return run(hdiutil_args, universal_newlines=True)
|
|
||||||
|
|
||||||
if verbose >= 2:
|
|
||||||
if fancy is None:
|
|
||||||
print("+ Creating .dmg disk image +")
|
|
||||||
else:
|
|
||||||
print("+ Preparing .dmg disk image +")
|
print("+ Preparing .dmg disk image +")
|
||||||
|
|
||||||
if config.dmg != "":
|
if verbose:
|
||||||
dmg_name = config.dmg
|
|
||||||
else:
|
|
||||||
spl = app_bundle_name.split(" ")
|
|
||||||
dmg_name = spl[0] + "".join(p.capitalize() for p in spl[1:])
|
|
||||||
|
|
||||||
if fancy is None:
|
|
||||||
try:
|
|
||||||
runHDIUtil("create", dmg_name, srcfolder="dist", format="UDBZ", volname=volname, ov=True)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
sys.exit(e.returncode)
|
|
||||||
else:
|
|
||||||
if verbose >= 3:
|
|
||||||
print("Determining size of \"dist\"...")
|
print("Determining size of \"dist\"...")
|
||||||
size = 0
|
size = 0
|
||||||
for path, dirs, files in os.walk("dist"):
|
for path, dirs, files in os.walk("dist"):
|
||||||
|
@ -795,115 +656,40 @@ if config.dmg is not None:
|
||||||
size += os.path.getsize(os.path.join(path, file))
|
size += os.path.getsize(os.path.join(path, file))
|
||||||
size += int(size * 0.15)
|
size += int(size * 0.15)
|
||||||
|
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Creating temp image for modification...")
|
print("Creating temp image for modification...")
|
||||||
try:
|
|
||||||
runHDIUtil("create", dmg_name + ".temp", srcfolder="dist", format="UDRW", size=size, volname=volname, ov=True)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
sys.exit(e.returncode)
|
|
||||||
|
|
||||||
if verbose >= 3:
|
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...")
|
print("Attaching temp image...")
|
||||||
try:
|
output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, universal_newlines=True, stdout=PIPE).stdout
|
||||||
output = runHDIUtil("attach", dmg_name + ".temp", readwrite=True, noverify=True, noautoopen=True, capture_stdout=True)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
sys.exit(e.returncode)
|
|
||||||
|
|
||||||
m = re.search(r"/Volumes/(.+$)", output)
|
m = re.search(r"/Volumes/(.+$)", output)
|
||||||
disk_root = m.group(0)
|
disk_root = m.group(0)
|
||||||
disk_name = m.group(1)
|
|
||||||
|
|
||||||
if verbose >= 2:
|
|
||||||
print("+ Applying fancy settings +")
|
print("+ Applying fancy settings +")
|
||||||
|
|
||||||
if "background_picture" in fancy:
|
bg_path = os.path.join(disk_root, ".background", os.path.basename('background.tiff'))
|
||||||
bg_path = os.path.join(disk_root, ".background", os.path.basename(fancy["background_picture"]))
|
|
||||||
os.mkdir(os.path.dirname(bg_path))
|
os.mkdir(os.path.dirname(bg_path))
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print(fancy["background_picture"], "->", bg_path)
|
print('background.tiff', "->", bg_path)
|
||||||
shutil.copy2(fancy["background_picture"], bg_path)
|
shutil.copy2('background.tiff', bg_path)
|
||||||
else:
|
|
||||||
bg_path = None
|
|
||||||
|
|
||||||
if fancy.get("applications_symlink", False):
|
|
||||||
os.symlink("/Applications", os.path.join(disk_root, "Applications"))
|
os.symlink("/Applications", os.path.join(disk_root, "Applications"))
|
||||||
|
|
||||||
# The Python appscript package broke with OSX 10.8 and isn't being fixed.
|
|
||||||
# So we now build up an AppleScript string and use the osascript command
|
|
||||||
# to make the .dmg file pretty:
|
|
||||||
appscript = Template( """
|
|
||||||
on run argv
|
|
||||||
tell application "Finder"
|
|
||||||
tell disk "$disk"
|
|
||||||
open
|
|
||||||
set current view of container window to icon view
|
|
||||||
set toolbar visible of container window to false
|
|
||||||
set statusbar visible of container window to false
|
|
||||||
set the bounds of container window to {$window_bounds}
|
|
||||||
set theViewOptions to the icon view options of container window
|
|
||||||
set arrangement of theViewOptions to not arranged
|
|
||||||
set icon size of theViewOptions to $icon_size
|
|
||||||
$background_commands
|
|
||||||
$items_positions
|
|
||||||
close -- close/reopen works around a bug...
|
|
||||||
open
|
|
||||||
update without registering applications
|
|
||||||
delay 5
|
|
||||||
eject
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
end run
|
|
||||||
""")
|
|
||||||
|
|
||||||
itemscript = Template('set position of item "${item}" of container window to {${position}}')
|
|
||||||
items_positions = []
|
|
||||||
if "items_position" in fancy:
|
|
||||||
for name, position in fancy["items_position"].items():
|
|
||||||
params = { "item" : name, "position" : ",".join([str(p) for p in position]) }
|
|
||||||
items_positions.append(itemscript.substitute(params))
|
|
||||||
|
|
||||||
params = {
|
|
||||||
"disk" : volname,
|
|
||||||
"window_bounds" : "300,300,800,620",
|
|
||||||
"icon_size" : "96",
|
|
||||||
"background_commands" : "",
|
|
||||||
"items_positions" : "\n ".join(items_positions)
|
|
||||||
}
|
|
||||||
if "window_bounds" in fancy:
|
|
||||||
params["window_bounds"] = ",".join([str(p) for p in fancy["window_bounds"]])
|
|
||||||
if "icon_size" in fancy:
|
|
||||||
params["icon_size"] = str(fancy["icon_size"])
|
|
||||||
if bg_path is not None:
|
|
||||||
# Set background file, then call SetFile to make it invisible.
|
|
||||||
# (note: making it invisible first makes set background picture fail)
|
|
||||||
bgscript = Template("""set background picture of theViewOptions to file ".background:$bgpic"
|
|
||||||
do shell script "SetFile -a V /Volumes/$disk/.background/$bgpic" """)
|
|
||||||
params["background_commands"] = bgscript.substitute({"bgpic" : os.path.basename(bg_path), "disk" : params["disk"]})
|
|
||||||
|
|
||||||
s = appscript.substitute(params)
|
|
||||||
if verbose >= 2:
|
|
||||||
print("Running AppleScript:")
|
|
||||||
print(s)
|
|
||||||
|
|
||||||
p = subprocess.Popen(['osascript', '-'], stdin=subprocess.PIPE)
|
|
||||||
p.communicate(input=s.encode('utf-8'))
|
|
||||||
if p.returncode:
|
|
||||||
print("Error running osascript.")
|
|
||||||
|
|
||||||
if verbose >= 2:
|
|
||||||
print("+ Finalizing .dmg disk image +")
|
print("+ Finalizing .dmg disk image +")
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
try:
|
run(["hdiutil", "detach", f"/Volumes/{appname}"], universal_newlines=True)
|
||||||
runHDIUtil("convert", dmg_name + ".temp", format="UDBZ", o=dmg_name + ".dmg", ov=True)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
sys.exit(e.returncode)
|
|
||||||
|
|
||||||
os.unlink(dmg_name + ".temp.dmg")
|
run(["hdiutil", "convert", tempname, "-format", "UDZO", "-o", appname, "-imagekey", "zlib-level=9"], check=True, universal_newlines=True)
|
||||||
|
|
||||||
|
os.unlink(tempname)
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if verbose >= 2:
|
print("+ Done +")
|
||||||
print("+ Done +")
|
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package=native_mac_alias
|
package=native_mac_alias
|
||||||
$(package)_version=2.0.7
|
$(package)_version=2.1.1
|
||||||
$(package)_download_path=https://github.com/al45tair/mac_alias/archive/
|
$(package)_download_path=https://github.com/al45tair/mac_alias/archive/
|
||||||
$(package)_file_name=v$($(package)_version).tar.gz
|
$(package)_file_name=v$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=6f606d3b6bccd2112aeabf1a063f5b5ece87005a5d7e97c8faca23b916e88838
|
$(package)_sha256_hash=c0ffceee14f7d04a6eb323fb7b8217dc3f373b346198d2ca42300a8362db7efa
|
||||||
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
|
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
|
|
|
@ -14,7 +14,6 @@ $(package)_patches+= fix_android_qmake_conf.patch fix_android_jni_static.patch d
|
||||||
$(package)_patches+= freetype_back_compat.patch drop_lrelease_dependency.patch fix_powerpc_libpng.patch
|
$(package)_patches+= freetype_back_compat.patch drop_lrelease_dependency.patch fix_powerpc_libpng.patch
|
||||||
$(package)_patches+= fix_mingw_cross_compile.patch fix_qpainter_non_determinism.patch
|
$(package)_patches+= fix_mingw_cross_compile.patch fix_qpainter_non_determinism.patch
|
||||||
|
|
||||||
# Update OSX_QT_TRANSLATIONS when this is updated
|
|
||||||
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
|
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
|
||||||
$(package)_qttranslations_sha256_hash=fb5a47799754af73d3bf501fe513342cfe2fc37f64e80df5533f6110e804220c
|
$(package)_qttranslations_sha256_hash=fb5a47799754af73d3bf501fe513342cfe2fc37f64e80df5533f6110e804220c
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue