mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
merge bitcoin#20422: mac deployment unification
This commit is contained in:
parent
f2a5b472fd
commit
77539574a7
13
Makefile.am
13
Makefile.am
@ -39,12 +39,9 @@ OSX_TEMP_ISO = $(OSX_DMG:.dmg=).temp.iso
|
|||||||
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/dash.icns
|
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/dash.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/debian/copyright \
|
$(top_srcdir)/contrib/debian/copyright \
|
||||||
@ -64,9 +61,8 @@ WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/dash.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
|
||||||
|
|
||||||
@ -127,7 +123,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 $@
|
||||||
@ -160,11 +156,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/Dash-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
|
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-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 !BUILD_DARWIN
|
endif !BUILD_DARWIN
|
||||||
|
@ -6,10 +6,6 @@ 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 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 `Dash-Qt.dmg`.
|
When complete, it will have produced `Dash-Qt.dmg`.
|
||||||
|
|
||||||
## SDK Extraction
|
## SDK Extraction
|
||||||
@ -110,7 +106,7 @@ broken. Only the compression feature is currently used. Ideally, the creation co
|
|||||||
and `xorrisofs` would no longer be necessary.
|
and `xorrisofs` 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-2015 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:\x00dashcoreuser:\x00Documents:\x00dashcore:\x00dashcore:\x00' + package_name_ns + '.temp.dmg'
|
|
||||||
alias.volume.disk_image_alias.target.posix_path = 'Users/dashcoreuser/Documents/dashcore/dashcore/' + 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['Dash-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>Dash-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 = "Dash-Qt"
|
# for backwards compatibility reasons, this must remain as Dash-Qt
|
||||||
self.binaryPath = os.path.join(path, "Contents", "MacOS", appName)
|
self.binaryPath = os.path.join(path, "Contents", "MacOS", "Dash-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(f"otool failed with return code {otool.returncode}")
|
||||||
raise RuntimeError("otool failed with return code {}".format(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,16 +306,14 @@ 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
|
||||||
if deploymentInfo.qtPath is None and framework.isQtFramework():
|
if deploymentInfo.qtPath is None and framework.isQtFramework():
|
||||||
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
|
||||||
|
|
||||||
# install_name_tool the new id into the binary
|
# install_name_tool the new id into the binary
|
||||||
@ -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,8 +464,7 @@ 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)
|
||||||
destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory)
|
destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory)
|
||||||
@ -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", "Dash-Qt.app")
|
target = os.path.join("dist", "Dash-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,257 +542,154 @@ 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:
|
sys.exit(1)
|
||||||
qt_tr_dir = translations_dir
|
|
||||||
else:
|
print("+ Adding Qt translations +")
|
||||||
if deploymentInfo.qtPath is not None:
|
|
||||||
qt_tr_dir = os.path.join(deploymentInfo.qtPath, "translations")
|
translations = Path(config.translations_dir[0])
|
||||||
else:
|
|
||||||
sys.stderr.write("Error: Could not find Qt translation path\n")
|
regex = re.compile('qt_[a-z]*(.qm|_[A-Z]*.qm)')
|
||||||
sys.exit(1)
|
|
||||||
add_qt_tr = ["qt_{}.qm".format(lng) for lng in config.add_qt_tr[0].split(",")]
|
lang_files = [x for x in translations.iterdir() if regex.match(x.name)]
|
||||||
for lng_file in add_qt_tr:
|
|
||||||
p = os.path.join(qt_tr_dir, lng_file)
|
for file in lang_files:
|
||||||
if verbose >= 3:
|
if verbose:
|
||||||
print("Checking for \"{}\"...".format(p))
|
print(file.as_posix(), "->", os.path.join(applicationBundle.resourcesPath, file.name))
|
||||||
if not os.path.exists(p):
|
shutil.copy2(file.as_posix(), os.path.join(applicationBundle.resourcesPath, file.name))
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not find Qt translation file \"{}\"\n".format(lng_file))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
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['Dash-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:
|
print("+ Preparing .dmg disk image +")
|
||||||
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():
|
if verbose:
|
||||||
hdiutil_args.append("-" + key)
|
print("Determining size of \"dist\"...")
|
||||||
if value is not True:
|
size = 0
|
||||||
hdiutil_args.append(str(value))
|
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)
|
||||||
|
|
||||||
return run(hdiutil_args, universal_newlines=True)
|
if verbose:
|
||||||
if verbose >= 2:
|
print("Creating temp image for modification...")
|
||||||
if fancy is None:
|
|
||||||
print("+ Creating .dmg disk image +")
|
|
||||||
else:
|
|
||||||
print("+ Preparing .dmg disk image +")
|
|
||||||
|
|
||||||
if config.dmg != "":
|
tempname: str = appname + ".temp.dmg"
|
||||||
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:
|
run(["hdiutil", "create", tempname, "-srcfolder", "dist", "-format", "UDRW", "-size", str(size), "-volname", appname], check=True, universal_newlines=True)
|
||||||
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\"...")
|
|
||||||
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 >= 3:
|
if verbose:
|
||||||
print("Creating temp image for modification...")
|
print("Attaching temp image...")
|
||||||
try:
|
output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, universal_newlines=True, stdout=PIPE).stdout
|
||||||
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:
|
m = re.search(r"/Volumes/(.+$)", output)
|
||||||
print("Attaching temp image...")
|
disk_root = m.group(0)
|
||||||
try:
|
|
||||||
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)
|
print("+ Applying fancy settings +")
|
||||||
disk_root = m.group(0)
|
|
||||||
disk_name = m.group(1)
|
|
||||||
|
|
||||||
if verbose >= 2:
|
bg_path = os.path.join(disk_root, ".background", os.path.basename('background.tiff'))
|
||||||
print("+ Applying fancy settings +")
|
os.mkdir(os.path.dirname(bg_path))
|
||||||
|
if verbose:
|
||||||
|
print('background.tiff', "->", bg_path)
|
||||||
|
shutil.copy2('background.tiff', bg_path)
|
||||||
|
|
||||||
if "background_picture" in fancy:
|
os.symlink("/Applications", os.path.join(disk_root, "Applications"))
|
||||||
bg_path = os.path.join(disk_root, ".background", os.path.basename(fancy["background_picture"]))
|
|
||||||
os.mkdir(os.path.dirname(bg_path))
|
|
||||||
if verbose >= 3:
|
|
||||||
print(fancy["background_picture"], "->", bg_path)
|
|
||||||
shutil.copy2(fancy["background_picture"], bg_path)
|
|
||||||
else:
|
|
||||||
bg_path = None
|
|
||||||
|
|
||||||
if fancy.get("applications_symlink", False):
|
print("+ Finalizing .dmg disk image +")
|
||||||
os.symlink("/Applications", os.path.join(disk_root, "Applications"))
|
|
||||||
|
|
||||||
# The Python appscript package broke with OSX 10.8 and isn't being fixed.
|
run(["hdiutil", "detach", f"/Volumes/{appname}"], universal_newlines=True)
|
||||||
# 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}}')
|
run(["hdiutil", "convert", tempname, "-format", "UDZO", "-o", appname, "-imagekey", "zlib-level=9"], check=True, universal_newlines=True)
|
||||||
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 = {
|
os.unlink(tempname)
|
||||||
"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)
|
|
||||||
|
|
||||||
time.sleep(2) # fixes '112:116: execution error: Finder got an error: Can’t get disk "Dash-Core". (-1728)'
|
|
||||||
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 +")
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
try:
|
|
||||||
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")
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
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
|
||||||
|
@ -17,7 +17,6 @@ $(package)_patches+= fix_montery_include.patch
|
|||||||
$(package)_patches += glibc_compatibility.patch
|
$(package)_patches += glibc_compatibility.patch
|
||||||
$(package)_patches+= qtbase-moc-ignore-gcc-macro.patch
|
$(package)_patches+= qtbase-moc-ignore-gcc-macro.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=577b0668a777eb2b451c61e8d026d79285371597ce9df06b6dee6c814164b7c3
|
$(package)_qttranslations_sha256_hash=577b0668a777eb2b451c61e8d026d79285371597ce9df06b6dee6c814164b7c3
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user