Skip to content

Commit 7c966c9

Browse files
PastaPastaPastaogabrielides
authored andcommitted
Merge pull request dashpay#5718 from knst/mac-improvements
backport: bitcoin#24603, bitcoin#26694, bitcoin#24669, bitcoin#22546, bitcoin#22199, bitcoin#25817 (mac build)
1 parent a8573c9 commit 7c966c9

File tree

8 files changed

+161
-212
lines changed

8 files changed

+161
-212
lines changed

Makefile.am

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ OSX_APP=Dash-Qt.app
3636
OSX_VOLNAME = $(subst $(space),-,$(PACKAGE_NAME))
3737
OSX_DMG = $(OSX_VOLNAME).dmg
3838
OSX_TEMP_ISO = $(OSX_DMG:.dmg=).temp.iso
39-
OSX_BACKGROUND_IMAGE=$(top_srcdir)/contrib/macdeploy/background.tiff
4039
OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
4140
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/dash.icns
4241
OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed
@@ -60,7 +59,6 @@ WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/dash.ico \
6059
$(top_srcdir)/doc/README_windows.txt
6160

6261
OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_INSTALLER_ICONS) \
63-
$(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
6462
$(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
6563

6664
COVERAGE_INFO = baseline.info \
@@ -125,28 +123,17 @@ $(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING)
125123
deploydir: $(OSX_DMG)
126124
else !BUILD_DARWIN
127125
APP_DIST_DIR=$(top_builddir)/dist
128-
APP_DIST_EXTRAS=$(APP_DIST_DIR)/.background/background.tiff $(APP_DIST_DIR)/.DS_Store $(APP_DIST_DIR)/Applications
129126

130-
$(APP_DIST_DIR)/Applications:
131-
@rm -f $@
132-
@cd $(@D); $(LN_S) /Applications $(@F)
133-
134-
$(APP_DIST_EXTRAS): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-Qt
135-
136-
$(OSX_TEMP_ISO): $(APP_DIST_EXTRAS)
127+
$(OSX_TEMP_ISO): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-Qt
137128
$(XORRISOFS) -D -l -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -o $@ $(APP_DIST_DIR) -- $(if $(SOURCE_DATE_EPOCH),-volume_date all_file_dates =$(SOURCE_DATE_EPOCH))
138129

139130
$(OSX_DMG): $(OSX_TEMP_ISO)
140131
$(DMG) dmg "$<" "$@"
141132

142-
$(APP_DIST_DIR)/.background/background.tiff:
143-
$(MKDIR_P) $(@D)
144-
cp $(OSX_BACKGROUND_IMAGE) $@
145-
146133
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
147134
INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR)
148135

149-
deploydir: $(APP_DIST_EXTRAS)
136+
deploydir: $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Dash-Qt
150137
endif !BUILD_DARWIN
151138

152139
appbundle: $(OSX_APP_BUILT)

ci/test/00_setup_env_native_qt5.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ export RUN_UNIT_TESTS_SEQUENTIAL="true"
1515
export RUN_UNIT_TESTS="false"
1616
export GOAL="install"
1717
export TEST_PREVIOUS_RELEASES=true
18-
export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.15.0.0 v0.16.1.1 v0.17.0.3 v18.2.2 v19.3.0"
18+
export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.15.0.0 v0.16.1.1 v0.17.0.3 v18.2.2 v19.3.0 v20.0.1"
1919
export BITCOIN_CONFIG="--enable-zmq --enable-reduce-exports --disable-fuzz-binary LDFLAGS=-static-libstdc++"

contrib/guix/libexec/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ mkdir -p "$DISTSRC"
328328
mkdir -p "unsigned-app-${HOST}"
329329
cp --target-directory="unsigned-app-${HOST}" \
330330
osx_volname \
331-
contrib/macdeploy/detached-sig-{apply,create}.sh \
331+
contrib/macdeploy/detached-sig-create.sh \
332332
"${BASEPREFIX}/${HOST}"/native/bin/dmg
333333
mv --target-directory="unsigned-app-${HOST}" dist
334334
(

contrib/macdeploy/detached-sig-apply.sh

Lines changed: 0 additions & 27 deletions
This file was deleted.

contrib/macdeploy/macdeployqtplus

Lines changed: 62 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
#
1818

19-
import plistlib
20-
import sys, re, os, shutil, stat, os.path
19+
import sys, re, os, platform, shutil, stat, subprocess, os.path
2120
from argparse import ArgumentParser
2221
from ds_store import DSStore
2322
from mac_alias import Alias
@@ -53,7 +52,7 @@ class FrameworkInfo(object):
5352
return False
5453

5554
def __str__(self):
56-
return f""" Framework name: {frameworkName}
55+
return f""" Framework name: {self.frameworkName}
5756
Framework directory: {self.frameworkDirectory}
5857
Framework path: {self.frameworkPath}
5958
Binary name: {self.binaryName}
@@ -85,8 +84,8 @@ class FrameworkInfo(object):
8584
if line == "":
8685
return None
8786

88-
# Don't deploy system libraries (exception for libQtuitools and libQtlucene).
89-
if line.startswith("/System/Library/") or line.startswith("@executable_path") or (line.startswith("/usr/lib/") and "libQt" not in line):
87+
# Don't deploy system libraries
88+
if line.startswith("/System/Library/") or line.startswith("@executable_path") or line.startswith("/usr/lib/"):
9089
return None
9190

9291
m = cls.reOLine.match(line)
@@ -246,56 +245,46 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
246245
toDir = os.path.join(path, framework.destinationDirectory)
247246
toPath = os.path.join(toDir, framework.binaryName)
248247

249-
if not os.path.exists(fromPath):
250-
raise RuntimeError(f"No file at {fromPath}")
248+
if framework.isDylib():
249+
if not os.path.exists(fromPath):
250+
raise RuntimeError(f"No file at {fromPath}")
251251

252-
if os.path.exists(toPath):
253-
return None # Already there
252+
if os.path.exists(toPath):
253+
return None # Already there
254254

255-
if not os.path.exists(toDir):
256-
os.makedirs(toDir)
255+
if not os.path.exists(toDir):
256+
os.makedirs(toDir)
257257

258-
shutil.copy2(fromPath, toPath)
259-
if verbose:
260-
print("Copied:", fromPath)
261-
print(" to:", toPath)
258+
shutil.copy2(fromPath, toPath)
259+
if verbose:
260+
print("Copied:", fromPath)
261+
print(" to:", toPath)
262+
else:
263+
to_dir = os.path.join(path, "Contents", "Frameworks", framework.frameworkName)
264+
if os.path.exists(to_dir):
265+
return None # Already there
266+
267+
from_dir = framework.frameworkPath
268+
if not os.path.exists(from_dir):
269+
raise RuntimeError(f"No directory at {from_dir}")
270+
271+
shutil.copytree(from_dir, to_dir, symlinks=True)
272+
if verbose:
273+
print("Copied:", from_dir)
274+
print(" to:", to_dir)
275+
276+
headers_link = os.path.join(to_dir, "Headers")
277+
if os.path.exists(headers_link):
278+
os.unlink(headers_link)
279+
280+
headers_dir = os.path.join(to_dir, framework.binaryDirectory, "Headers")
281+
if os.path.exists(headers_dir):
282+
shutil.rmtree(headers_dir)
262283

263284
permissions = os.stat(toPath)
264285
if not permissions.st_mode & stat.S_IWRITE:
265286
os.chmod(toPath, permissions.st_mode | stat.S_IWRITE)
266287

267-
if not framework.isDylib(): # Copy resources for real frameworks
268-
269-
linkfrom = os.path.join(path, "Contents","Frameworks", framework.frameworkName, "Versions", "Current")
270-
linkto = framework.version
271-
if not os.path.exists(linkfrom):
272-
os.symlink(linkto, linkfrom)
273-
print("Linked:", linkfrom, "->", linkto)
274-
fromResourcesDir = framework.sourceResourcesDirectory
275-
if os.path.exists(fromResourcesDir):
276-
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
277-
shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True)
278-
if verbose:
279-
print("Copied resources:", fromResourcesDir)
280-
print(" to:", toResourcesDir)
281-
fromContentsDir = framework.sourceVersionContentsDirectory
282-
if not os.path.exists(fromContentsDir):
283-
fromContentsDir = framework.sourceContentsDirectory
284-
if os.path.exists(fromContentsDir):
285-
toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory)
286-
shutil.copytree(fromContentsDir, toContentsDir, symlinks=True)
287-
if verbose:
288-
print("Copied Contents:", fromContentsDir)
289-
print(" to:", toContentsDir)
290-
elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout)
291-
qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "Resources", "qt_menu.nib")
292-
qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib")
293-
if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath):
294-
shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True)
295-
if verbose:
296-
print("Copied for libQtGui:", qtMenuNibSourcePath)
297-
print(" to:", qtMenuNibDestinationPath)
298-
299288
return toPath
300289

301290
def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPath: str, strip: bool, verbose: int, deploymentInfo: Optional[DeploymentInfo] = None) -> DeploymentInfo:
@@ -351,115 +340,20 @@ def deployFrameworksForAppBundle(applicationBundle: ApplicationBundleInfo, strip
351340
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
352341

353342
def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: DeploymentInfo, strip: bool, verbose: int):
354-
# Lookup available plugins, exclude unneeded
355343
plugins = []
356344
if deploymentInfo.pluginPath is None:
357345
return
358346
for dirpath, dirnames, filenames in os.walk(deploymentInfo.pluginPath):
359347
pluginDirectory = os.path.relpath(dirpath, deploymentInfo.pluginPath)
360-
if pluginDirectory == "designer":
361-
# Skip designer plugins
362-
continue
363-
elif pluginDirectory == "printsupport":
364-
# Skip printsupport plugins
365-
continue
366-
elif pluginDirectory == "imageformats":
367-
# Skip imageformats plugins
348+
349+
if pluginDirectory not in ['styles', 'platforms']:
368350
continue
369-
elif pluginDirectory == "sqldrivers":
370-
# Deploy the sql plugins only if QtSql is in use
371-
if not deploymentInfo.usesFramework("QtSql"):
372-
continue
373-
elif pluginDirectory == "script":
374-
# Deploy the script plugins only if QtScript is in use
375-
if not deploymentInfo.usesFramework("QtScript"):
376-
continue
377-
elif pluginDirectory == "qmltooling" or pluginDirectory == "qml1tooling":
378-
# Deploy the qml plugins only if QtDeclarative is in use
379-
if not deploymentInfo.usesFramework("QtDeclarative"):
380-
continue
381-
elif pluginDirectory == "bearer":
382-
# Deploy the bearer plugins only if QtNetwork is in use
383-
if not deploymentInfo.usesFramework("QtNetwork"):
384-
continue
385-
elif pluginDirectory == "position":
386-
# Deploy the position plugins only if QtPositioning is in use
387-
if not deploymentInfo.usesFramework("QtPositioning"):
388-
continue
389-
elif pluginDirectory == "sensors" or pluginDirectory == "sensorgestures":
390-
# Deploy the sensor plugins only if QtSensors is in use
391-
if not deploymentInfo.usesFramework("QtSensors"):
392-
continue
393-
elif pluginDirectory == "audio" or pluginDirectory == "playlistformats":
394-
# Deploy the audio plugins only if QtMultimedia is in use
395-
if not deploymentInfo.usesFramework("QtMultimedia"):
396-
continue
397-
elif pluginDirectory == "mediaservice":
398-
# Deploy the mediaservice plugins only if QtMultimediaWidgets is in use
399-
if not deploymentInfo.usesFramework("QtMultimediaWidgets"):
400-
continue
401-
elif pluginDirectory == "canbus":
402-
# Deploy the canbus plugins only if QtSerialBus is in use
403-
if not deploymentInfo.usesFramework("QtSerialBus"):
404-
continue
405-
elif pluginDirectory == "webview":
406-
# Deploy the webview plugins only if QtWebView is in use
407-
if not deploymentInfo.usesFramework("QtWebView"):
408-
continue
409-
elif pluginDirectory == "gamepads":
410-
# Deploy the webview plugins only if QtGamepad is in use
411-
if not deploymentInfo.usesFramework("QtGamepad"):
412-
continue
413-
elif pluginDirectory == "geoservices":
414-
# Deploy the webview plugins only if QtLocation is in use
415-
if not deploymentInfo.usesFramework("QtLocation"):
416-
continue
417-
elif pluginDirectory == "texttospeech":
418-
# Deploy the texttospeech plugins only if QtTextToSpeech is in use
419-
if not deploymentInfo.usesFramework("QtTextToSpeech"):
420-
continue
421-
elif pluginDirectory == "virtualkeyboard":
422-
# Deploy the virtualkeyboard plugins only if QtVirtualKeyboard is in use
423-
if not deploymentInfo.usesFramework("QtVirtualKeyboard"):
424-
continue
425-
elif pluginDirectory == "sceneparsers":
426-
# Deploy the virtualkeyboard plugins only if Qt3DCore is in use
427-
if not deploymentInfo.usesFramework("Qt3DCore"):
428-
continue
429-
elif pluginDirectory == "renderplugins":
430-
# Deploy the renderplugins plugins only if Qt3DCore is in use
431-
if not deploymentInfo.usesFramework("Qt3DCore"):
432-
continue
433-
elif pluginDirectory == "geometryloaders":
434-
# Deploy the geometryloaders plugins only if Qt3DCore is in use
435-
if not deploymentInfo.usesFramework("Qt3DCore"):
436-
continue
437351

438352
for pluginName in filenames:
439353
pluginPath = os.path.join(pluginDirectory, pluginName)
440-
if pluginName.endswith("_debug.dylib"):
441-
# Skip debug plugins
354+
355+
if pluginName.split('.')[0] not in ['libqminimal', 'libqcocoa', 'libqmacstyle']:
442356
continue
443-
elif pluginPath == "imageformats/libqsvg.dylib" or pluginPath == "iconengines/libqsvgicon.dylib":
444-
# Deploy the svg plugins only if QtSvg is in use
445-
if not deploymentInfo.usesFramework("QtSvg"):
446-
continue
447-
elif pluginPath == "accessible/libqtaccessiblecompatwidgets.dylib":
448-
# Deploy accessibility for Qt3Support only if the Qt3Support is in use
449-
if not deploymentInfo.usesFramework("Qt3Support"):
450-
continue
451-
elif pluginPath == "graphicssystems/libqglgraphicssystem.dylib":
452-
# Deploy the opengl graphicssystem plugin only if QtOpenGL is in use
453-
if not deploymentInfo.usesFramework("QtOpenGL"):
454-
continue
455-
elif pluginPath == "accessible/libqtaccessiblequick.dylib":
456-
# Deploy the accessible qtquick plugin only if QtQuick is in use
457-
if not deploymentInfo.usesFramework("QtQuick"):
458-
continue
459-
elif pluginPath == "platforminputcontexts/libqtvirtualkeyboardplugin.dylib":
460-
# Deploy the virtualkeyboardplugin plugin only if QtVirtualKeyboard is in use
461-
if not deploymentInfo.usesFramework("QtVirtualKeyboard"):
462-
continue
463357

464358
plugins.append((pluginDirectory, pluginName))
465359

@@ -527,6 +421,9 @@ if os.path.exists(appname + ".dmg"):
527421
print("+ Removing existing DMG +")
528422
os.unlink(appname + ".dmg")
529423

424+
if os.path.exists(appname + ".temp.dmg"):
425+
os.unlink(appname + ".temp.dmg")
426+
530427
# ------------------------------------------------
531428

532429
target = os.path.join("dist", "Dash-Qt.app")
@@ -644,6 +541,25 @@ ds.close()
644541

645542
# ------------------------------------------------
646543

544+
if platform.system() == "Darwin":
545+
subprocess.check_call(f"codesign --deep --force --sign - {target}", shell=True)
546+
547+
print("+ Installing background.tiff +")
548+
549+
bg_path = os.path.join('dist', '.background', 'background.tiff')
550+
os.mkdir(os.path.dirname(bg_path))
551+
552+
tiff_path = os.path.join('contrib', 'macdeploy', 'background.tiff')
553+
shutil.copy2(tiff_path, bg_path)
554+
555+
# ------------------------------------------------
556+
557+
print("+ Generating symlink for /Applications +")
558+
559+
os.symlink("/Applications", os.path.join('dist', "Applications"))
560+
561+
# ------------------------------------------------
562+
647563
if config.dmg is not None:
648564

649565
print("+ Preparing .dmg disk image +")
@@ -667,19 +583,6 @@ if config.dmg is not None:
667583
print("Attaching temp image...")
668584
output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, universal_newlines=True, stdout=PIPE).stdout
669585

670-
m = re.search(r"/Volumes/(.+$)", output)
671-
disk_root = m.group(0)
672-
673-
print("+ Applying fancy settings +")
674-
675-
bg_path = os.path.join(disk_root, ".background", os.path.basename('background.tiff'))
676-
os.mkdir(os.path.dirname(bg_path))
677-
if verbose:
678-
print('background.tiff', "->", bg_path)
679-
shutil.copy2('contrib/macdeploy/background.tiff', bg_path)
680-
681-
os.symlink("/Applications", os.path.join(disk_root, "Applications"))
682-
683586
print("+ Finalizing .dmg disk image +")
684587

685588
run(["hdiutil", "detach", f"/Volumes/{appname}"], universal_newlines=True)

depends/packages/qt.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ $(package)_config_opts_darwin += -no-feature-corewlan
134134
$(package)_config_opts_darwin += -no-freetype
135135
$(package)_config_opts_darwin += QMAKE_MACOSX_DEPLOYMENT_TARGET=$(OSX_MIN_VERSION)
136136

137+
# Optimizing using > -O1 causes non-determinism when building across arches.
138+
$(package)_config_opts_aarch64_darwin += "QMAKE_CFLAGS_OPTIMIZE_FULL = -O1"
139+
137140
ifneq ($(build_os),darwin)
138141
$(package)_config_opts_darwin += -xplatform macx-clang-linux
139142
$(package)_config_opts_darwin += -device-option MAC_SDK_PATH=$(OSX_SDK)

0 commit comments

Comments
 (0)