miniupnpc Porfile removed; new and improved macdeployqtplus
* My patch for miniupnpc has made it into the latest MacPorts release: https://trac.macports.org/ticket/31354 * Documentation has been changed appropriately * New pure-Python macdeployqt; leverages all problems with the stock macdeployqt
This commit is contained in:
parent
f69b82e78a
commit
f118b5fc5d
@ -21,12 +21,397 @@ import subprocess, sys, re, os, shutil, os.path
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
# This is ported from the original macdeployqt with modifications
|
||||||
|
|
||||||
|
class FrameworkInfo(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.frameworkDirectory = ""
|
||||||
|
self.frameworkName = ""
|
||||||
|
self.frameworkPath = ""
|
||||||
|
self.binaryDirectory = ""
|
||||||
|
self.binaryName = ""
|
||||||
|
self.binaryPath = ""
|
||||||
|
self.version = ""
|
||||||
|
self.installName = ""
|
||||||
|
self.deployedInstallName = ""
|
||||||
|
self.sourceFilePath = ""
|
||||||
|
self.destinationDirectory = ""
|
||||||
|
self.sourceResourcesDirectory = ""
|
||||||
|
self.destinationResourcesDirectory = ""
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if self.__class__ == other.__class__:
|
||||||
|
return self.__dict__ == other.__dict__
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return """ Framework name: %s
|
||||||
|
Framework directory: %s
|
||||||
|
Framework path: %s
|
||||||
|
Binary name: %s
|
||||||
|
Binary directory: %s
|
||||||
|
Binary path: %s
|
||||||
|
Version: %s
|
||||||
|
Install name: %s
|
||||||
|
Deployed install name: %s
|
||||||
|
Source file Path: %s
|
||||||
|
Deployed Directory (relative to bundle): %s
|
||||||
|
""" % (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):
|
||||||
|
return self.frameworkName.endswith(".dylib")
|
||||||
|
|
||||||
|
def isQtFramework(self):
|
||||||
|
if self.isDylib():
|
||||||
|
return self.frameworkName.startswith("libQt")
|
||||||
|
else:
|
||||||
|
return self.frameworkName.startswith("Qt")
|
||||||
|
|
||||||
|
reOLine = re.compile(r'^(.+) \(compatibility version [0-9.]+, current version [0-9.]+\)$')
|
||||||
|
bundleFrameworkDirectory = "Contents/Frameworks"
|
||||||
|
bundleBinaryDirectory = "Contents/MacOS"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromOtoolLibraryLine(cls, line):
|
||||||
|
# Note: line must be trimmed
|
||||||
|
if line == "":
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Don't deploy system libraries (exception for libQtuitools and libQtlucene).
|
||||||
|
if line.startswith("/System/Library/") or line.startswith("@executable_path") or (line.startswith("/usr/lib/") and "libQt" not in line):
|
||||||
|
return None
|
||||||
|
|
||||||
|
m = cls.reOLine.match(line)
|
||||||
|
if m is None:
|
||||||
|
raise RuntimeError("otool line could not be parsed: " + line)
|
||||||
|
|
||||||
|
path = m.group(1)
|
||||||
|
|
||||||
|
info = cls()
|
||||||
|
info.sourceFilePath = path
|
||||||
|
info.installName = path
|
||||||
|
|
||||||
|
if path.endswith(".dylib"):
|
||||||
|
dirname, filename = os.path.split(path)
|
||||||
|
info.frameworkName = filename
|
||||||
|
info.frameworkDirectory = dirname
|
||||||
|
info.frameworkPath = path
|
||||||
|
|
||||||
|
info.binaryDirectory = dirname
|
||||||
|
info.binaryName = filename
|
||||||
|
info.binaryPath = path
|
||||||
|
info.version = "-"
|
||||||
|
|
||||||
|
info.installName = path
|
||||||
|
info.deployedInstallName = "@executable_path/../Frameworks/" + info.binaryName
|
||||||
|
info.sourceFilePath = path
|
||||||
|
info.destinationDirectory = cls.bundleFrameworkDirectory
|
||||||
|
else:
|
||||||
|
parts = path.split("/")
|
||||||
|
i = 0
|
||||||
|
# Search for the .framework directory
|
||||||
|
for part in parts:
|
||||||
|
if part.endswith(".framework"):
|
||||||
|
break
|
||||||
|
i += 1
|
||||||
|
if i == len(parts):
|
||||||
|
raise RuntimeError("Could not find .framework or .dylib in otool line: " + line)
|
||||||
|
|
||||||
|
info.frameworkName = parts[i]
|
||||||
|
info.frameworkDirectory = "/".join(parts[:i])
|
||||||
|
info.frameworkPath = os.path.join(info.frameworkDirectory, info.frameworkName)
|
||||||
|
|
||||||
|
info.binaryName = parts[i+3]
|
||||||
|
info.binaryDirectory = "/".join(parts[i+1:i+3])
|
||||||
|
info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName)
|
||||||
|
info.version = parts[i+2]
|
||||||
|
|
||||||
|
info.deployedInstallName = "@executable_path/../Frameworks/" + os.path.join(info.frameworkName, info.binaryPath)
|
||||||
|
info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory)
|
||||||
|
|
||||||
|
info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources")
|
||||||
|
info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources")
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
class ApplicationBundleInfo(object):
|
||||||
|
def __init__(self, path):
|
||||||
|
self.path = path
|
||||||
|
appName = os.path.splitext(os.path.basename(path))[0]
|
||||||
|
self.binaryPath = os.path.join(path, "Contents", "MacOS", appName)
|
||||||
|
if not os.path.exists(self.binaryPath):
|
||||||
|
raise RuntimeError("Could not find bundle binary for " + path)
|
||||||
|
self.resourcesPath = os.path.join(path, "Contents", "Resources")
|
||||||
|
self.pluginPath = os.path.join(path, "Contents", "PlugIns")
|
||||||
|
|
||||||
|
class DeploymentInfo(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.qtPath = None
|
||||||
|
self.pluginPath = None
|
||||||
|
self.deployedFrameworks = []
|
||||||
|
|
||||||
|
def detectQtPath(self, frameworkDirectory):
|
||||||
|
parentDir = os.path.dirname(frameworkDirectory)
|
||||||
|
if os.path.exists(os.path.join(parentDir, "translations")):
|
||||||
|
# Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x"
|
||||||
|
self.qtPath = parentDir
|
||||||
|
elif os.path.exists(os.path.join(parentDir, "share", "qt4", "translations")):
|
||||||
|
# MacPorts layout, e.g. "/opt/local/share/qt4"
|
||||||
|
self.qtPath = os.path.join(parentDir, "share", "qt4")
|
||||||
|
|
||||||
|
if self.qtPath is not None:
|
||||||
|
pluginPath = os.path.join(self.qtPath, "plugins")
|
||||||
|
if os.path.exists(pluginPath):
|
||||||
|
self.pluginPath = pluginPath
|
||||||
|
|
||||||
|
def usesFramework(self, name):
|
||||||
|
nameDot = "%s." % name
|
||||||
|
libNameDot = "lib%s." % name
|
||||||
|
for framework in self.deployedFrameworks:
|
||||||
|
if framework.endswith(".framework"):
|
||||||
|
if framework.startswith(nameDot):
|
||||||
|
return True
|
||||||
|
elif framework.endswith(".dylib"):
|
||||||
|
if framework.startswith(libNameDot):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getFrameworks(binaryPath, verbose):
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Inspecting with otool: " + binaryPath
|
||||||
|
otool = subprocess.Popen(["otool", "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
o_stdout, o_stderr = otool.communicate()
|
||||||
|
if otool.returncode != 0:
|
||||||
|
if verbose >= 1:
|
||||||
|
sys.stderr.write(o_stderr)
|
||||||
|
sys.stderr.flush()
|
||||||
|
raise RuntimeError("otool failed with return code %d" % otool.returncode)
|
||||||
|
|
||||||
|
otoolLines = o_stdout.split("\n")
|
||||||
|
otoolLines.pop(0) # First line is the inspected binary
|
||||||
|
if ".framework" in binaryPath or binaryPath.endswith(".dylib"):
|
||||||
|
otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency.
|
||||||
|
|
||||||
|
libraries = []
|
||||||
|
for line in otoolLines:
|
||||||
|
info = FrameworkInfo.fromOtoolLibraryLine(line.strip())
|
||||||
|
if info is not None:
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Found framework:"
|
||||||
|
print info
|
||||||
|
libraries.append(info)
|
||||||
|
|
||||||
|
return libraries
|
||||||
|
|
||||||
|
def runInstallNameTool(action, *args):
|
||||||
|
subprocess.check_call(["install_name_tool", "-"+action] + list(args))
|
||||||
|
|
||||||
|
def changeInstallName(oldName, newName, binaryPath, verbose):
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Using install_name_tool:"
|
||||||
|
print " in", binaryPath
|
||||||
|
print " change reference", oldName
|
||||||
|
print " to", newName
|
||||||
|
runInstallNameTool("change", oldName, newName, binaryPath)
|
||||||
|
|
||||||
|
def changeIdentification(id, binaryPath, verbose):
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Using install_name_tool:"
|
||||||
|
print " change identification in", binaryPath
|
||||||
|
print " to", id
|
||||||
|
runInstallNameTool("id", id, binaryPath)
|
||||||
|
|
||||||
|
def runStrip(binaryPath, verbose):
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Using strip:"
|
||||||
|
print " stripped", binaryPath
|
||||||
|
subprocess.check_call(["strip", "-x", binaryPath])
|
||||||
|
|
||||||
|
def copyFramework(framework, path, verbose):
|
||||||
|
fromPath = framework.sourceFilePath
|
||||||
|
toDir = os.path.join(path, framework.destinationDirectory)
|
||||||
|
toPath = os.path.join(toDir, framework.binaryName)
|
||||||
|
|
||||||
|
if not os.path.exists(fromPath):
|
||||||
|
raise RuntimeError("No file at " + fromPath)
|
||||||
|
|
||||||
|
if os.path.exists(toPath):
|
||||||
|
return None # Already there
|
||||||
|
|
||||||
|
if not os.path.exists(toDir):
|
||||||
|
os.makedirs(toDir)
|
||||||
|
|
||||||
|
shutil.copy2(fromPath, toPath)
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Copied:", fromPath
|
||||||
|
print " to:", toPath
|
||||||
|
|
||||||
|
if not framework.isDylib(): # Copy resources for real frameworks
|
||||||
|
fromResourcesDir = framework.sourceResourcesDirectory
|
||||||
|
if os.path.exists(fromResourcesDir):
|
||||||
|
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
|
||||||
|
shutil.copytree(fromResourcesDir, toResourcesDir)
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Copied resources:", fromResourcesDir
|
||||||
|
print " to:", toResourcesDir
|
||||||
|
elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout)
|
||||||
|
qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "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):
|
||||||
|
shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath)
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Copied for libQtGui:", qtMenuNibSourcePath
|
||||||
|
print " to:", qtMenuNibDestinationPath
|
||||||
|
|
||||||
|
return toPath
|
||||||
|
|
||||||
|
def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploymentInfo=None):
|
||||||
|
if deploymentInfo is None:
|
||||||
|
deploymentInfo = DeploymentInfo()
|
||||||
|
|
||||||
|
while len(frameworks) > 0:
|
||||||
|
framework = frameworks.pop(0)
|
||||||
|
deploymentInfo.deployedFrameworks.append(framework.frameworkName)
|
||||||
|
|
||||||
|
if verbose >= 2:
|
||||||
|
print "Processing", framework.frameworkName, "..."
|
||||||
|
|
||||||
|
# Get the Qt path from one of the Qt frameworks
|
||||||
|
if deploymentInfo.qtPath is None and framework.isQtFramework():
|
||||||
|
deploymentInfo.detectQtPath(framework.frameworkDirectory)
|
||||||
|
|
||||||
|
if framework.installName.startswith("@executable_path"):
|
||||||
|
if verbose >= 2:
|
||||||
|
print framework.frameworkName, "already deployed, skipping."
|
||||||
|
continue
|
||||||
|
|
||||||
|
# install_name_tool the new id into the binary
|
||||||
|
changeInstallName(framework.installName, framework.deployedInstallName, binaryPath, verbose)
|
||||||
|
|
||||||
|
# Copy farmework to app bundle.
|
||||||
|
deployedBinaryPath = copyFramework(framework, bundlePath, verbose)
|
||||||
|
# Skip the rest if already was deployed.
|
||||||
|
if deployedBinaryPath is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if strip:
|
||||||
|
runStrip(deployedBinaryPath, verbose)
|
||||||
|
|
||||||
|
# install_name_tool it a new id.
|
||||||
|
changeIdentification(framework.deployedInstallName, deployedBinaryPath, verbose)
|
||||||
|
# Check for framework dependencies
|
||||||
|
dependencies = getFrameworks(deployedBinaryPath, verbose)
|
||||||
|
|
||||||
|
for dependency in dependencies:
|
||||||
|
changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath, verbose)
|
||||||
|
|
||||||
|
# Deploy framework if necessary.
|
||||||
|
if dependency.frameworkName not in deploymentInfo.deployedFrameworks and dependency not in frameworks:
|
||||||
|
frameworks.append(dependency)
|
||||||
|
|
||||||
|
return deploymentInfo
|
||||||
|
|
||||||
|
def deployFrameworksForAppBundle(applicationBundle, strip, verbose):
|
||||||
|
frameworks = getFrameworks(applicationBundle.binaryPath, verbose)
|
||||||
|
if len(frameworks) == 0 and verbose >= 1:
|
||||||
|
print "Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path)
|
||||||
|
return DeploymentInfo()
|
||||||
|
else:
|
||||||
|
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
|
||||||
|
|
||||||
|
def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
|
||||||
|
# Lookup available plugins, exclude unneeded
|
||||||
|
plugins = []
|
||||||
|
for dirpath, dirnames, filenames in os.walk(deploymentInfo.pluginPath):
|
||||||
|
pluginDirectory = os.path.relpath(dirpath, deploymentInfo.pluginPath)
|
||||||
|
if pluginDirectory == "designer":
|
||||||
|
# Skip designer plugins
|
||||||
|
continue
|
||||||
|
elif pluginDirectory == "phonon":
|
||||||
|
# Deploy the phonon plugins only if phonon is in use
|
||||||
|
if not deploymentInfo.usesFramework("phonon"):
|
||||||
|
continue
|
||||||
|
elif pluginDirectory == "sqldrivers":
|
||||||
|
# Deploy the sql plugins only if QtSql is in use
|
||||||
|
if not deploymentInfo.usesFramework("QtSql"):
|
||||||
|
continue
|
||||||
|
elif pluginDirectory == "script":
|
||||||
|
# Deploy the script plugins only if QtScript is in use
|
||||||
|
if not deploymentInfo.usesFramework("QtScript"):
|
||||||
|
continue
|
||||||
|
elif pluginDirectory == "qmltooling":
|
||||||
|
# Deploy the qml plugins only if QtDeclarative is in use
|
||||||
|
if not deploymentInfo.usesFramework("QtDeclarative"):
|
||||||
|
continue
|
||||||
|
elif pluginDirectory == "bearer":
|
||||||
|
# Deploy the bearer plugins only if QtNetwork is in use
|
||||||
|
if not deploymentInfo.usesFramework("QtNetwork"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for pluginName in filenames:
|
||||||
|
pluginPath = os.path.join(pluginDirectory, pluginName)
|
||||||
|
if pluginName.endswith("_debug.dylib"):
|
||||||
|
# Skip debug plugins
|
||||||
|
continue
|
||||||
|
elif pluginPath == "imageformats/libqsvg.dylib" or pluginPath == "iconengines/libqsvgicon.dylib":
|
||||||
|
# Deploy the svg plugins only if QtSvg is in use
|
||||||
|
if not deploymentInfo.usesFramework("QtSvg"):
|
||||||
|
continue
|
||||||
|
elif pluginPath == "accessible/libqtaccessiblecompatwidgets.dylib":
|
||||||
|
# Deploy accessibility for Qt3Support only if the Qt3Support is in use
|
||||||
|
if not deploymentInfo.usesFramework("Qt3Support"):
|
||||||
|
continue
|
||||||
|
elif pluginPath == "graphicssystems/libqglgraphicssystem.dylib":
|
||||||
|
# Deploy the opengl graphicssystem plugin only if QtOpenGL is in use
|
||||||
|
if not deploymentInfo.usesFramework("QtOpenGL"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
plugins.append((pluginDirectory, pluginName))
|
||||||
|
|
||||||
|
for pluginDirectory, pluginName in plugins:
|
||||||
|
if verbose >= 2:
|
||||||
|
print "Processing plugin", os.path.join(pluginDirectory, pluginName), "..."
|
||||||
|
|
||||||
|
sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName)
|
||||||
|
destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory)
|
||||||
|
if not os.path.exists(destinationDirectory):
|
||||||
|
os.makedirs(destinationDirectory)
|
||||||
|
|
||||||
|
destinationPath = os.path.join(destinationDirectory, pluginName)
|
||||||
|
shutil.copy2(sourcePath, destinationPath)
|
||||||
|
if verbose >= 3:
|
||||||
|
print "Copied:", sourcePath
|
||||||
|
print " to:", destinationPath
|
||||||
|
|
||||||
|
if strip:
|
||||||
|
runStrip(destinationPath, verbose)
|
||||||
|
|
||||||
|
dependencies = getFrameworks(destinationPath, verbose)
|
||||||
|
|
||||||
|
for dependency in dependencies:
|
||||||
|
changeInstallName(dependency.installName, dependency.deployedInstallName, destinationPath, verbose)
|
||||||
|
|
||||||
|
# Deploy framework if necessary.
|
||||||
|
if dependency.frameworkName not in deploymentInfo.deployedFrameworks:
|
||||||
|
deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo)
|
||||||
|
|
||||||
qt_conf="""[Paths]
|
qt_conf="""[Paths]
|
||||||
translations=Resources
|
translations=Resources
|
||||||
plugins=PlugIns
|
plugins=PlugIns
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ap = ArgumentParser(description="""Front-end to macdeployqt with some additional functions.
|
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.
|
||||||
@ -69,22 +454,6 @@ for p in config.add_resources:
|
|||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
if len(config.add_qt_tr) == 0:
|
|
||||||
add_qt_tr = []
|
|
||||||
else:
|
|
||||||
qt_tr_dir = os.path.join(os.getenv("QTDIR", ""), "translations")
|
|
||||||
add_qt_tr = ["qt_%s.qm" % 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 \"%s\"..." % p
|
|
||||||
if not os.path.exists(p):
|
|
||||||
if verbose >= 1:
|
|
||||||
sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
|
||||||
|
|
||||||
if len(config.fancy) == 1:
|
if len(config.fancy) == 1:
|
||||||
if verbose >= 3:
|
if verbose >= 3:
|
||||||
print "Fancy: Importing plistlib..."
|
print "Fancy: Importing plistlib..."
|
||||||
@ -160,7 +529,6 @@ if os.path.exists("dist"):
|
|||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
target = os.path.join("dist", app_bundle)
|
target = os.path.join("dist", app_bundle)
|
||||||
target_res = os.path.join(target, "Contents", "Resources")
|
|
||||||
|
|
||||||
if verbose >= 2:
|
if verbose >= 2:
|
||||||
print "+ Copying source bundle +"
|
print "+ Copying source bundle +"
|
||||||
@ -170,27 +538,61 @@ if verbose >= 3:
|
|||||||
os.mkdir("dist")
|
os.mkdir("dist")
|
||||||
shutil.copytree(app_bundle, target)
|
shutil.copytree(app_bundle, target)
|
||||||
|
|
||||||
|
applicationBundle = ApplicationBundleInfo(target)
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
macdeployqt_args = ["macdeployqt", target, "-verbose=%d" % verbose]
|
|
||||||
if not config.plugins:
|
|
||||||
macdeployqt_args.append("-no-plugins")
|
|
||||||
if not config.strip:
|
|
||||||
macdeployqt_args.append("-no-strip")
|
|
||||||
|
|
||||||
if verbose >= 2:
|
if verbose >= 2:
|
||||||
print "+ Running macdeployqt +"
|
print "+ Deploying frameworks +"
|
||||||
|
|
||||||
ret = subprocess.call(macdeployqt_args)
|
try:
|
||||||
if ret != 0:
|
deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose)
|
||||||
|
if deploymentInfo.qtPath is None:
|
||||||
|
deploymentInfo.qtPath = os.getenv("QTDIR", None)
|
||||||
|
if deploymentInfo.qtPath is None:
|
||||||
|
if verbose >= 1:
|
||||||
|
sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n")
|
||||||
|
config.plugins = False
|
||||||
|
except RuntimeError as e:
|
||||||
|
if verbose >= 1:
|
||||||
|
sys.stderr.write("Error: %s\n" % str(e))
|
||||||
sys.exit(ret)
|
sys.exit(ret)
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
|
if config.plugins:
|
||||||
|
if verbose >= 2:
|
||||||
|
print "+ Deploying plugins +"
|
||||||
|
|
||||||
|
try:
|
||||||
|
deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose)
|
||||||
|
except RuntimeError as e:
|
||||||
|
if verbose >= 1:
|
||||||
|
sys.stderr.write("Error: %s\n" % str(e))
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
# ------------------------------------------------
|
||||||
|
|
||||||
|
if len(config.add_qt_tr) == 0:
|
||||||
|
add_qt_tr = []
|
||||||
|
else:
|
||||||
|
qt_tr_dir = os.path.join(deploymentInfo.qtPath, "translations")
|
||||||
|
add_qt_tr = ["qt_%s.qm" % 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 \"%s\"..." % p
|
||||||
|
if not os.path.exists(p):
|
||||||
|
if verbose >= 1:
|
||||||
|
sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# ------------------------------------------------
|
||||||
|
|
||||||
if verbose >= 2:
|
if verbose >= 2:
|
||||||
print "+ Installing qt.conf +"
|
print "+ Installing qt.conf +"
|
||||||
|
|
||||||
f = open(os.path.join(target_res, "qt.conf"), "wb")
|
f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb")
|
||||||
f.write(qt_conf)
|
f.write(qt_conf)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
@ -201,8 +603,8 @@ if len(add_qt_tr) > 0 and verbose >= 2:
|
|||||||
|
|
||||||
for lng_file in add_qt_tr:
|
for lng_file in add_qt_tr:
|
||||||
if verbose >= 3:
|
if verbose >= 3:
|
||||||
print os.path.join(qt_tr_dir, lng_file), "->", os.path.join(target_res, lng_file)
|
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(target_res, lng_file))
|
shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file))
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
|
|
||||||
@ -210,7 +612,7 @@ if len(config.add_resources) > 0 and verbose >= 2:
|
|||||||
print "+ Adding additional resources +"
|
print "+ Adding additional resources +"
|
||||||
|
|
||||||
for p in config.add_resources:
|
for p in config.add_resources:
|
||||||
t = os.path.join(target_res, os.path.basename(p))
|
t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p))
|
||||||
if verbose >= 3:
|
if verbose >= 3:
|
||||||
print p, "->", t
|
print p, "->", t
|
||||||
if os.path.isdir(p):
|
if os.path.isdir(p):
|
||||||
|
@ -6,7 +6,7 @@ You will need the appscript package for the fancy disk image creation to work.
|
|||||||
Install it by invoking "sudo easy_install appscript".
|
Install it by invoking "sudo easy_install appscript".
|
||||||
|
|
||||||
Ths script should be invoked in the target directory like this:
|
Ths script should be invoked in the target directory like this:
|
||||||
$source_dir/contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr de,es,ru -dmg -fancy $source_dir/contrib/macdeploy/fancy.plist
|
$source_dir/contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy $source_dir/contrib/macdeploy/fancy.plist -verbose 2
|
||||||
|
|
||||||
During the process, the disk image window will pop up briefly where the fancy
|
During the process, the disk image window will pop up briefly where the fancy
|
||||||
settings are applied. This is normal, please do not interfere.
|
settings are applied. This is normal, please do not interfere.
|
||||||
@ -19,7 +19,7 @@ Fill in the following.
|
|||||||
Enable custom process step: [x]
|
Enable custom process step: [x]
|
||||||
Command: %{sourceDir}/contrib/macdeploy/macdeployqtplus
|
Command: %{sourceDir}/contrib/macdeploy/macdeployqtplus
|
||||||
Working directory: %{buildDir}
|
Working directory: %{buildDir}
|
||||||
Command arguments: Bitcoin-Qt.app -add-qt-tr de,ru -dmg -fancy %{sourceDir}/contrib/macdeploy/fancy.plist
|
Command arguments: Bitcoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy %{sourceDir}/contrib/macdeploy/fancy.plist -verbose 2
|
||||||
|
|
||||||
After that you can start the deployment process through the menu with
|
After that you can start the deployment process through the menu with
|
||||||
Build -> Deploy Project "bitcoin-qt"
|
Build -> Deploy Project "bitcoin-qt"
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
|
|
||||||
# $Id$
|
|
||||||
|
|
||||||
PortSystem 1.0
|
|
||||||
|
|
||||||
name miniupnpc
|
|
||||||
epoch 2
|
|
||||||
version 1.6
|
|
||||||
revision 2
|
|
||||||
categories net
|
|
||||||
platforms darwin
|
|
||||||
license BSD
|
|
||||||
maintainers singingwolfboy openmaintainer
|
|
||||||
description Lightweight client for UPnP protocol
|
|
||||||
long_description \
|
|
||||||
${description}
|
|
||||||
|
|
||||||
homepage http://miniupnp.free.fr/
|
|
||||||
master_sites http://miniupnp.free.fr/files/download.php?file=${distname}${extract.suffix}&dummy=
|
|
||||||
checksums md5 88055f2d4a061cfd4cfe25a9eae22f67 \
|
|
||||||
sha1 ef8f2edb17f2e7c5b8dc67ee80a65c199d823e0a \
|
|
||||||
rmd160 d86b75b331a3fb5525c71708548f311977c0598f
|
|
||||||
|
|
||||||
use_configure no
|
|
||||||
|
|
||||||
variant universal {}
|
|
||||||
if {[variant_isset universal]} {
|
|
||||||
set archflags ${configure.universal_cflags}
|
|
||||||
} else {
|
|
||||||
set archflags ${configure.cc_archflags}
|
|
||||||
}
|
|
||||||
|
|
||||||
build.args-append CC="${configure.cc} ${archflags}"
|
|
||||||
|
|
||||||
post-patch {
|
|
||||||
reinplace "s|-Wl,-install_name,|-Wl,-install_name,${prefix}/lib/|" ${worksrcpath}/Makefile
|
|
||||||
}
|
|
||||||
|
|
||||||
destroot.destdir PREFIX=${prefix} INSTALLPREFIX=${destroot}${prefix}
|
|
||||||
|
|
||||||
livecheck.type regex
|
|
||||||
livecheck.url http://miniupnp.free.fr/files/
|
|
||||||
livecheck.regex ${name}-(\\d+(\\.\\d{1,4})+)${extract.suffix}
|
|
@ -36,12 +36,7 @@ git clone git@github.com:bitcoin/bitcoin.git bitcoin
|
|||||||
|
|
||||||
3. Install dependencies from MacPorts
|
3. Install dependencies from MacPorts
|
||||||
|
|
||||||
sudo port install boost db48 openssl
|
sudo port install boost db48 openssl miniupnpc
|
||||||
|
|
||||||
Install the right version of miniupnpc:
|
|
||||||
pushd bitcoin/contrib/minipupnpc; sudo port install; popd
|
|
||||||
(this will be unnecessary soon, you will just port install miniupnpc
|
|
||||||
along with the rest of the dependencies).
|
|
||||||
|
|
||||||
Optionally install qrencode (and set USE_QRCODE=1):
|
Optionally install qrencode (and set USE_QRCODE=1):
|
||||||
sudo port install qrencode
|
sudo port install qrencode
|
||||||
|
@ -92,7 +92,7 @@ Mac OS X
|
|||||||
::
|
::
|
||||||
|
|
||||||
sudo port selfupdate
|
sudo port selfupdate
|
||||||
sudo port install boost db48
|
sudo port install boost db48 miniupnpc
|
||||||
|
|
||||||
- Open the .pro file in Qt Creator and build as normal (cmd-B)
|
- Open the .pro file in Qt Creator and build as normal (cmd-B)
|
||||||
|
|
||||||
@ -127,14 +127,6 @@ Set USE_UPNP to a different value to control this:
|
|||||||
| USE_UPNP=1 | build with UPnP support turned on by default at runtime. |
|
| USE_UPNP=1 | build with UPnP support turned on by default at runtime. |
|
||||||
+------------+--------------------------------------------------------------------------+
|
+------------+--------------------------------------------------------------------------+
|
||||||
|
|
||||||
Mac OS X users: miniupnpc is currently outdated on MacPorts. An updated Portfile is provided in contrib/miniupnpc within this project.
|
|
||||||
You can execute the following commands in a terminal to install it:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
cd <location of bitcoin-qt>/contrib/miniupnpc
|
|
||||||
sudo port install
|
|
||||||
|
|
||||||
Notification support for recent (k)ubuntu versions
|
Notification support for recent (k)ubuntu versions
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
|
@ -67,8 +67,9 @@
|
|||||||
rm -rf bitcoin-${VERSION}-win32
|
rm -rf bitcoin-${VERSION}-win32
|
||||||
|
|
||||||
* perform Mac build
|
* perform Mac build
|
||||||
See this blog post for how Gavin set up his build environment and
|
See this blog post for how Gavin set up his build environment to build the OSX
|
||||||
patched macdeployqt to build the OSX release:
|
release; note that a patched version of macdeployqt is not needed anymore, as
|
||||||
|
the required functionality and fixes are implemented directly in macdeployqtplus:
|
||||||
http://gavintech.blogspot.com/2011/11/deploying-bitcoin-qt-on-osx.html
|
http://gavintech.blogspot.com/2011/11/deploying-bitcoin-qt-on-osx.html
|
||||||
qmake USE_SSL=1 USE_UPNP=1 bitcoin-qt.pro
|
qmake USE_SSL=1 USE_UPNP=1 bitcoin-qt.pro
|
||||||
make
|
make
|
||||||
|
Loading…
Reference in New Issue
Block a user