From aae7a5e09db3d98ce74a523c06b8971a3672b309 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 15 Feb 2016 22:29:01 -0800 Subject: [PATCH] qmake: Add shallow bundle support This is a prerequisite for properly constructed framework bundles. On certain Apple platforms (iOS, tvOS, watchOS), bundles are used in "shallow" format, meaning that the directory structures are flattened compared to the one used in macOS bundles. shallow_bundle allows the difference to be expressed independently of the platform. Note that the term "shallow bundle" is used by Apple in Xcode internals. Change-Id: I1189c52b0ea66843c313783176c11cc2af97ad25 Reviewed-by: Oswald Buddenhagen --- mkspecs/common/uikit.conf | 2 +- mkspecs/features/qt.prf | 4 +- mkspecs/features/qt_functions.prf | 6 +- qmake/generators/mac/pbuilder_pbx.cpp | 6 +- qmake/generators/unix/unixmake.cpp | 9 ++- qmake/generators/unix/unixmake2.cpp | 80 ++++++++++++++++----------- 6 files changed, 64 insertions(+), 43 deletions(-) diff --git a/mkspecs/common/uikit.conf b/mkspecs/common/uikit.conf index edc0eddf00..6ffbe51fce 100644 --- a/mkspecs/common/uikit.conf +++ b/mkspecs/common/uikit.conf @@ -3,7 +3,7 @@ # QMAKE_PLATFORM += uikit -CONFIG += bitcode reduce_exports +CONFIG += bitcode reduce_exports shallow_bundle INCLUDEPATH += $$PWD/uikit DEFINES += DARWIN_NO_CARBON QT_NO_PRINTER QT_NO_PRINTDIALOG diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 0c5f080ec1..7b669b902f 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -244,13 +244,13 @@ contains(qt_module_deps, qml): \ # copy qml files. this part is platform spesific. mac { - osx { + !shallow_bundle { # Note: user can override QMAKE_BUNDLE_QML from pro file to change target bundle path isEmpty(QMAKE_QML_BUNDLE_PATH):QMAKE_QML_BUNDLE_PATH = "Resources/qt_qml" qmlTargetPath = $$OUT_PWD/$${TARGET}.app/Contents/$$QMAKE_QML_BUNDLE_PATH qtconfTargetPath = $$OUT_PWD/$${TARGET}.app/Contents/Resources/qt.conf } else { - # iOS: flat bundle layout (no Contents/Resources) + # shallow bundle layout (no Contents/Resources) isEmpty(QMAKE_QML_BUNDLE_PATH):QMAKE_QML_BUNDLE_PATH = "qt_qml" qmlTargetPath = $CODESIGNING_FOLDER_PATH/$$QMAKE_QML_BUNDLE_PATH qtconfTargetPath = $CODESIGNING_FOLDER_PATH/qt.conf diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 08c7c9f899..e7d73adefb 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -37,11 +37,13 @@ defineReplace(qtRelativeRPathBase) { darwin { if(equals(TEMPLATE, app):app_bundle)|\ if(equals(TEMPLATE, lib):plugin:plugin_bundle) { - ios: return($$target.path/$${TARGET}.app) + shallow_bundle: return($$target.path/$${TARGET}.app) return($$target.path/$${TARGET}.app/Contents/MacOS) } - equals(TEMPLATE, lib):!plugin:lib_bundle: \ + equals(TEMPLATE, lib):!plugin:lib_bundle { + shallow_bundle: return($$target.path/$${TARGET}.framework) return($$target.path/$${TARGET}.framework/Versions/Current) + } } return($$target.path) } diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index bf2e774678..b53b862b87 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1123,9 +1123,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) bundle_resources_files << s; } else { QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]); - if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) { - //### - } + //if (!project->isActiveConfig("shallow_bundle") + // && !project->isEmpty(ProKey(bundle_data[i] + ".version"))) { + //} project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); t << "\t\t" << phase_key << " = {\n" diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index b0f7593fbe..0e29f469ef 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -579,10 +579,13 @@ UnixMakefileGenerator::defaultInstall(const QString &t) plain_targ = escapeFilePath(plain_targ); if (bundle != NoBundle) { QString suffix; - if (project->first("TEMPLATE") == "lib") - suffix = "/Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/$(TARGET)"; - else + if (project->first("TEMPLATE") == "lib") { + if (!project->isActiveConfig("shallow_bundle")) + suffix += "/Versions/" + project->first("QMAKE_FRAMEWORK_VERSION"); + suffix += "/$(TARGET)"; + } else { suffix = "/" + project->first("QMAKE_BUNDLE_LOCATION") + "/$(QMAKE_TARGET)"; + } dst_targ += suffix; if (bundle == SolidBundle) { if (!ret.isEmpty()) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index c53393e268..be476a7806 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -596,9 +596,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << var("QMAKE_LINK_SHLIB_CMD") << "\n\t" << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGETD)`\"", false) << "\n\t" << "-$(MOVE) $(TARGET) $(DESTDIR)$(TARGETD)\n\t" - << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGET0)`\"", false) << "\n\t" - << varGlue("QMAKE_LN_SHLIB", "-", " ", - " Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t"; + << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGET0)`\"", false) << "\n\t"; + if (!project->isActiveConfig("shallow_bundle")) + t << varGlue("QMAKE_LN_SHLIB", "-", " ", + " Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; @@ -778,9 +779,14 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) info_plist = escapeFilePath(fileFixify(info_plist)); } bool isFramework = project->first("TEMPLATE") == "lib" && project->isActiveConfig("lib_bundle"); + bool isShallowBundle = project->isActiveConfig("shallow_bundle"); QString info_plist_out = bundle_dir + - (isFramework ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/Info.plist") - : "Contents/Info.plist"); + (!isShallowBundle + ? (isFramework + ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/") + : "Contents/") + : QString()) + + "Info.plist"; bundledFiles << info_plist_out; alldeps << info_plist_out; QString destdir = info_plist_out.section(Option::dir_sep, 0, -2); @@ -838,7 +844,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "@$(COPY_FILE) " << escapeFilePath(icon) << ' ' << icon_path_f << endl; } } else { - symlinks[bundle_dir + "Resources"] = "Versions/Current/Resources"; + if (!isShallowBundle) + symlinks[bundle_dir + "Resources"] = "Versions/Current/Resources"; t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@sed "; for (const ProString &arg : qAsConst(commonSedArgs)) @@ -857,18 +864,20 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) for(int i = 0; i < bundle_data.count(); i++) { const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files")); QString path = bundle_dir; - const ProKey vkey(bundle_data[i] + ".version"); const ProKey pkey(bundle_data[i] + ".path"); - if (!project->isEmpty(vkey)) { - QString version = project->first(vkey) + "/" + - project->first("QMAKE_FRAMEWORK_VERSION") + "/"; - ProString name = project->first(pkey); - int pos = name.indexOf('/'); - if (pos > 0) - name = name.mid(0, pos); - symlinks[Option::fixPathToTargetOS(path + name)] = - project->first(vkey) + "/Current/" + name; - path += version; + if (!project->isActiveConfig("shallow_bundle")) { + const ProKey vkey(bundle_data[i] + ".version"); + if (!project->isEmpty(vkey)) { + QString version = project->first(vkey) + "/" + + project->first("QMAKE_FRAMEWORK_VERSION") + "/"; + ProString name = project->first(pkey); + int pos = name.indexOf('/'); + if (pos > 0) + name = name.mid(0, pos); + symlinks[Option::fixPathToTargetOS(path + name)] = + project->first(vkey) + "/Current/" + name; + path += version; + } } path += project->first(pkey).toQString(); path = Option::fixPathToTargetOS(path); @@ -906,15 +915,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl; } - QString currentLink = bundle_dir + "Versions/Current"; - QString currentLink_f = escapeDependencyPath(currentLink); - bundledFiles << currentLink; - alldeps << currentLink; - t << currentLink_f << ": $(MAKEFILE)\n\t" - << mkdir_p_asstring(bundle_dir + "Versions") << "\n\t" - << "@-$(DEL_FILE) " << currentLink_f << "\n\t" - << "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION") - << ' ' << currentLink_f << endl; + if (!project->isActiveConfig("shallow_bundle")) { + QString currentLink = bundle_dir + "Versions/Current"; + QString currentLink_f = escapeDependencyPath(currentLink); + bundledFiles << currentLink; + alldeps << currentLink; + t << currentLink_f << ": $(MAKEFILE)\n\t" + << mkdir_p_asstring(bundle_dir + "Versions") << "\n\t" + << "@-$(DEL_FILE) " << currentLink_f << "\n\t" + << "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION") + << ' ' << currentLink_f << endl; + } } } @@ -1157,12 +1168,17 @@ void UnixMakefileGenerator::init2() bundle_loc.prepend("/"); if(!bundle_loc.endsWith("/")) bundle_loc += "/"; - project->values("TARGET_").append(project->first("QMAKE_BUNDLE") + - bundle_loc + project->first("TARGET")); - project->values("TARGET_x.y").append(project->first("QMAKE_BUNDLE") + - "/Versions/" + - project->first("QMAKE_FRAMEWORK_VERSION") + - bundle_loc + project->first("TARGET")); + const QString target = project->first("QMAKE_BUNDLE") + + bundle_loc + project->first("TARGET"); + project->values("TARGET_").append(target); + if (!project->isActiveConfig("shallow_bundle")) { + project->values("TARGET_x.y").append(project->first("QMAKE_BUNDLE") + + "/Versions/" + + project->first("QMAKE_FRAMEWORK_VERSION") + + bundle_loc + project->first("TARGET")); + } else { + project->values("TARGET_x.y").append(target); + } } else if(project->isActiveConfig("plugin")) { QString prefix; if(!project->isActiveConfig("no_plugin_name_prefix"))