Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@

*.pro.user
build-*
**.o
**/Makefile
macdeployqt/macdeployqt

15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Implementation of macdeployqt utility for Qt5 which fixes problems with application deployment and distribution.

Build:
---
```
cd macdeployqt
qmake macdeployqt.pro
make
sudo make install
```
Usage:
---
```
macdeployqt /path/to/your/app
```
9 changes: 0 additions & 9 deletions README.txt

This file was deleted.

7 changes: 7 additions & 0 deletions macdeployqt/macdeployqt.pro
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ SOURCES += main.cpp \

HEADERS += \
shared.h

CONFIG-=app_bundle

target.path = /usr/local/bin
INSTALLS += target


18 changes: 9 additions & 9 deletions macdeployqt/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,25 +135,25 @@ int main(int argc, char **argv)

DeploymentInfo deploymentInfo = deployQtFrameworks(appBundlePath, additionalExecutables, useDebugLibs);

const QString defaultQmlPath = appBundlePath + "/Contents/Resources/qml/" + QFileInfo(appBundlePath).baseName();
if (qmlDirs.isEmpty() && QDir(defaultQmlPath).exists())
qmlDirs << defaultQmlPath;

if (!qmlDirs.isEmpty()) {
deployQmlImports(appBundlePath, qmlDirs, deploymentInfo);
}

if (plugins) {
if (deploymentInfo.qtPath.isEmpty())
deploymentInfo.pluginPath = "/Developer/Applications/Qt/plugins"; // Assume binary package.
else
deploymentInfo.pluginPath = deploymentInfo.qtPath + "/plugins";

LogNormal();
deployPlugins(appBundlePath, deploymentInfo, useDebugLibs);
deployPlugins(appBundlePath, useDebugLibs, deploymentInfo);
createQtConf(appBundlePath);
}

const QString defaultQmlPath = appBundlePath + "/Contents/Resources/qml/" + QFileInfo(appBundlePath).baseName();
if (qmlDirs.isEmpty() && QDir(defaultQmlPath).exists())
qmlDirs << defaultQmlPath;

if (!qmlDirs.isEmpty()) {
deployQmlImports(appBundlePath, deploymentInfo, qmlDirs);
}

if (dmg) {
LogNormal();
createDiskImage(appBundlePath);
Expand Down
53 changes: 35 additions & 18 deletions macdeployqt/shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ void recursiveCopy(const QString &sourcePath, const QString &destinationPath)
}
}

void recursiveCopyAndDeploy(const QString &appBundlePath, const QString &sourcePath, const QString &destinationPath)
void recursiveCopyAndDeploy(const QString &appBundlePath, const QString &sourcePath, const QString &destinationPath, DeploymentInfo& info)
{
QDir().mkpath(destinationPath);

Expand All @@ -314,7 +314,7 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QString &sourceP
bool useDebugLibs = false;
bool useLoaderPath = false;
QList<FrameworkInfo> frameworks = getQtFrameworks(fileDestinationPath, useDebugLibs);
deployQtFrameworks(frameworks, appBundlePath, QStringList() << fileDestinationPath, useDebugLibs, useLoaderPath);
deployQtFrameworks(frameworks, appBundlePath, QStringList() << fileDestinationPath, useDebugLibs, useLoaderPath, info);
}
} else {
copyFilePrintStatus(fileSourcePath, fileDestinationPath);
Expand All @@ -323,7 +323,7 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QString &sourceP

QStringList subdirs = QDir(sourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot);
foreach (QString dir, subdirs) {
recursiveCopyAndDeploy(appBundlePath, sourcePath + "/" + dir, destinationPath + "/" + dir);
recursiveCopyAndDeploy(appBundlePath, sourcePath + "/" + dir, destinationPath + "/" + dir, info);
}
}

Expand Down Expand Up @@ -445,14 +445,16 @@ void runStrip(const QString &binaryPath)
Returns a DeploymentInfo structure containing the Qt path used and a
a list of actually deployed frameworks.
*/
DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks,
const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs,
bool useLoaderPath)
void deployQtFrameworks(QList<FrameworkInfo> frameworks,
const QString &bundlePath,
const QStringList &binaryPaths,
bool useDebugLibs,
bool useLoaderPath,
DeploymentInfo& deploymentInfo)
{
LogNormal();
LogNormal() << "Deploying Qt frameworks found inside:" << binaryPaths;
QStringList copiedFrameworks;
DeploymentInfo deploymentInfo;
deploymentInfo.useLoaderPath = useLoaderPath;

while (frameworks.isEmpty() == false) {
Expand Down Expand Up @@ -497,8 +499,15 @@ DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks,
}
}
}
deploymentInfo.deployedFrameworks = copiedFrameworks;
return deploymentInfo;

foreach(const QString& copiedFrameworkName, copiedFrameworks)
{
if (!deploymentInfo.deployedFrameworks.contains(copiedFrameworkName))
{
deploymentInfo.deployedFrameworks.append(copiedFrameworkName);
}
}

}

DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs)
Expand All @@ -517,14 +526,17 @@ DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringLis
LogWarning() << "If so, you will need to rebuild" << appBundlePath << "before trying again.";
return DeploymentInfo();
} else {
return deployQtFrameworks(frameworks, applicationBundle.path, allBinaryPaths, useDebugLibs, !additionalExecutables.isEmpty());
DeploymentInfo info;
deployQtFrameworks(frameworks, applicationBundle.path, allBinaryPaths, useDebugLibs, !additionalExecutables.isEmpty(), info);
return info;
}
}

void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pluginSourcePath,
const QString pluginDestinationPath, DeploymentInfo deploymentInfo, bool useDebugLibs)
const QString pluginDestinationPath, DeploymentInfo& deploymentInfo, bool useDebugLibs)
{
LogNormal() << "Deploying plugins from" << pluginSourcePath;
LogNormal() << "Deplyed frameworks:" << deploymentInfo.deployedFrameworks;

if (!pluginSourcePath.contains(deploymentInfo.pluginPath))
return;
Expand Down Expand Up @@ -589,7 +601,12 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
if (copyFilePrintStatus(sourcePath, destinationPath)) {
runStrip(destinationPath);
QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath, useDebugLibs);
deployQtFrameworks(frameworks, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs, deploymentInfo.useLoaderPath);
deployQtFrameworks(frameworks,
appBundleInfo.path,
QStringList() << destinationPath,
useDebugLibs,
deploymentInfo.useLoaderPath,
deploymentInfo);
}
}
}
Expand Down Expand Up @@ -621,7 +638,7 @@ void createQtConf(const QString &appBundlePath)
}
}

void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, bool useDebugLibs)
void deployPlugins(const QString &appBundlePath, bool useDebugLibs, DeploymentInfo& deploymentInfo)
{
ApplicationBundleInfo applicationBundle;
applicationBundle.path = appBundlePath;
Expand Down Expand Up @@ -663,13 +680,13 @@ QStringList findQmlImports(QStringList &qmlDirs)
return importSet.toList();
}

void deployQmlImport(const QString &appBundlePath, DeploymentInfo deploymentInfo, const QString &importPath, const QString &importName)
void deployQmlImport(const QString &appBundlePath, const QString &importPath, const QString &importName, DeploymentInfo& deploymentInfo)
{
recursiveCopyAndDeploy(appBundlePath, importPath, appBundlePath + "/Contents/MacOS/" + importName);
recursiveCopyAndDeploy(appBundlePath, importPath, appBundlePath + "/Contents/MacOS/" + importName, deploymentInfo);
}

// Scan qml files in qmldirs for import statements, deploy used imports from qtbase/imports to Contents/imports.
void deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInfo, QStringList &qmlDirs)
void deployQmlImports(const QString &appBundlePath, QStringList &qmlDirs, DeploymentInfo& deploymentInfo)
{
QStringList imports = findQmlImports(qmlDirs);
QString qtbaseImportsDir = deploymentInfo.qtPath + "/qml";
Expand All @@ -679,10 +696,10 @@ void deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInf
foreach (const QString &availbleImport, availableImports) {
QString importPath = qtbaseImportsDir + "/" + availbleImport;
if (imports.contains(availbleImport)) {
deployQmlImport(appBundlePath, deploymentInfo, importPath, availbleImport);
deployQmlImport(appBundlePath, importPath, availbleImport, deploymentInfo);
} else if (availbleImport.contains("QtQuick.2")) {
// #### figure out versioning
deployQmlImport(appBundlePath, deploymentInfo, importPath, availbleImport);
deployQmlImport(appBundlePath, importPath, availbleImport, deploymentInfo);
}
}
}
Expand Down
11 changes: 8 additions & 3 deletions macdeployqt/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,15 @@ QList<FrameworkInfo> getQtFrameworks(const QString &path, bool useDebugLibs);
QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines, bool useDebugLibs);
QString copyFramework(const FrameworkInfo &framework, const QString path);
DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs);
DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks,const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, bool useLoaderPath);
void deployQtFrameworks(QList<FrameworkInfo> frameworks,
const QString &bundlePath,
const QStringList &binaryPaths,
bool useDebugLibs,
bool useLoaderPath,
DeploymentInfo& deploymentInfo);
void createQtConf(const QString &appBundlePath);
void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, bool useDebugLibs);
void deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInfo, QStringList &qmlDirs);
void deployPlugins(const QString &appBundlePath, bool useDebugLibs, DeploymentInfo& deploymentInfo);
void deployQmlImports(const QString &appBundlePath, QStringList &qmlDirs, DeploymentInfo& deploymentInfo);
void changeIdentification(const QString &id, const QString &binaryPath);
void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath);
void runStrip(const QString &binaryPath);
Expand Down