From e1baa97a28b98362c33036e3fc3be3d2bd416fe6 Mon Sep 17 00:00:00 2001 From: Anton Simakov Date: Tue, 11 Nov 2014 16:13:51 +0300 Subject: [PATCH] Works with Qt 5.3.2. Fixed dll paths for recursive dependencies --- .gitignore | 3 +++ README.md | 15 +++++++++++ README.txt | 9 ------- macdeployqt/macdeployqt.pro | 7 +++++ macdeployqt/main.cpp | 18 ++++++------- macdeployqt/shared.cpp | 53 ++++++++++++++++++++++++------------- macdeployqt/shared.h | 11 +++++--- 7 files changed, 77 insertions(+), 39 deletions(-) create mode 100644 README.md delete mode 100644 README.txt diff --git a/.gitignore b/.gitignore index fc33856..aa50841 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ *.pro.user build-* +**.o +**/Makefile +macdeployqt/macdeployqt diff --git a/README.md b/README.md new file mode 100644 index 0000000..770540a --- /dev/null +++ b/README.md @@ -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 +``` diff --git a/README.txt b/README.txt deleted file mode 100644 index cd0dbc7..0000000 --- a/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -Implementation of macdeployqt utility for Qt5 which fixes problems with application deployment and distribution. - -Won't work with Qt 5.1.0 - -Usage: -/path/to/macdeployqt.app/Contents/MacOS/macdeployqt /path/to/your/app - -Note: -Added new shell script to fix slashes issues on Qt 5.1.0. Paths are hardcoded. diff --git a/macdeployqt/macdeployqt.pro b/macdeployqt/macdeployqt.pro index f06851e..c2e7098 100644 --- a/macdeployqt/macdeployqt.pro +++ b/macdeployqt/macdeployqt.pro @@ -5,3 +5,10 @@ SOURCES += main.cpp \ HEADERS += \ shared.h + +CONFIG-=app_bundle + +target.path = /usr/local/bin +INSTALLS += target + + diff --git a/macdeployqt/main.cpp b/macdeployqt/main.cpp index 1fc9d84..115dab6 100644 --- a/macdeployqt/main.cpp +++ b/macdeployqt/main.cpp @@ -135,6 +135,14 @@ 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. @@ -142,18 +150,10 @@ int main(int argc, char **argv) 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); diff --git a/macdeployqt/shared.cpp b/macdeployqt/shared.cpp index 0325377..9e523f3 100644 --- a/macdeployqt/shared.cpp +++ b/macdeployqt/shared.cpp @@ -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); @@ -314,7 +314,7 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QString &sourceP bool useDebugLibs = false; bool useLoaderPath = false; QList frameworks = getQtFrameworks(fileDestinationPath, useDebugLibs); - deployQtFrameworks(frameworks, appBundlePath, QStringList() << fileDestinationPath, useDebugLibs, useLoaderPath); + deployQtFrameworks(frameworks, appBundlePath, QStringList() << fileDestinationPath, useDebugLibs, useLoaderPath, info); } } else { copyFilePrintStatus(fileSourcePath, fileDestinationPath); @@ -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); } } @@ -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 frameworks, - const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, - bool useLoaderPath) +void deployQtFrameworks(QList 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) { @@ -497,8 +499,15 @@ DeploymentInfo deployQtFrameworks(QList 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) @@ -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; @@ -589,7 +601,12 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl if (copyFilePrintStatus(sourcePath, destinationPath)) { runStrip(destinationPath); QList frameworks = getQtFrameworks(destinationPath, useDebugLibs); - deployQtFrameworks(frameworks, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs, deploymentInfo.useLoaderPath); + deployQtFrameworks(frameworks, + appBundleInfo.path, + QStringList() << destinationPath, + useDebugLibs, + deploymentInfo.useLoaderPath, + deploymentInfo); } } } @@ -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; @@ -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"; @@ -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); } } } diff --git a/macdeployqt/shared.h b/macdeployqt/shared.h index 52aee54..818c44f 100644 --- a/macdeployqt/shared.h +++ b/macdeployqt/shared.h @@ -100,10 +100,15 @@ QList getQtFrameworks(const QString &path, bool useDebugLibs); QList 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 frameworks,const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, bool useLoaderPath); +void deployQtFrameworks(QList 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);