iOS (OSX): rework how to bundle QML import folders

Before this patch, we would copy "$QTDIR/qml"
directly into the bundle as "qml". This would cause problems
if the user also tried to deploy qml files to a "qml" folder, or
if any other file in the bundle ended up with the name "qml" (which is the
case for QtDeclarative/tools/qml, where the executable is called "qml").

This patch will instead copy the contents of each import folder
into QMAKE_QML_BUNDLE_PATH, which will default to "qt_qml" on iOS
and "Resources/qt_qml" on OSX.

We also change the implementation to use a post script rather
then QMAKE_BUNDLE_DATA for two reasons:
1. Xcode does not like "copy build phases" to copy folders, only
    files (You cannot even create such a phase from Xcode, although
    it is possible to force it the way we create project.pbx. But
    this was error prone)
2. We need to strip away unneeded files from the bundle, like
    archives (which are linked in statically, not dlopened run-time).
    Using rsync lets us copy and strip in one operation.

Change-Id: I7c2117f6cfbe11efdc272dff71adb0b1e619a5ff
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
This commit is contained in:
Richard Moe Gustavsen 2013-10-22 12:56:14 +02:00 committed by The Qt Project
parent 27f2b97155
commit 42e6801843

View File

@ -124,33 +124,37 @@ if(contains(QT, qml)|contains(QT_PRIVATE, qml)): \
QMAKE_CLEAN += $$QML_IMPORT_CPP
# copy qml files. this part is platform spesific.
macx {
# copy to Contents/Resources in the bundle.
QmlImports.path = Contents/Resources/
QmlImports.files *= $$QMLPATHS
QMAKE_BUNDLE_DATA += QmlImports
mac {
osx {
# 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)
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
}
# place qt.conf in Contents/Resources in the app bundle
# set import path in qt.conf to point to the bundeled qml:
QT_CONF_CONTENTS = \
"[Paths]" \
"Imports = Resources/qml" \
"Qml2Imports = Resources/qml"
QT_CONF = "$$OUT_PWD/$${TARGET}.app/Contents/Resources/qt.conf"
write_file($$QT_CONF, QT_CONF_CONTENTS)|error("Aborting.")
} else: ios {
# flat bundle layout (no Contents/Resources)
QmlImports.files *= $$QMLPATHS
QMAKE_BUNDLE_DATA += QmlImports
"Imports = $$QMAKE_QML_BUNDLE_PATH" \
"Qml2Imports = $$QMAKE_QML_BUNDLE_PATH"
write_file("$$OUT_PWD/qt.conf", QT_CONF_CONTENTS)|error("Aborting.")
# write qt.conf to OUT_PWD and make xcode copy it via QMAKE_BUNDLE_DATA
QT_CONF_CONTENTS = \
"[Paths]" \
"Imports = qml" \
"Qml2Imports = qml"
QT_CONF = "$$OUT_PWD/qt.conf"
write_file($$QT_CONF, QT_CONF_CONTENTS)|error("Aborting.")
QtConf.files = $$QT_CONF
QMAKE_BUNDLE_DATA += QtConf
# write qt.conf and copy each qml import dir into the bundle.
# But strip away archives and other files that are not needed:
!isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";"
QMAKE_POST_LINK += \
"cp $$OUT_PWD/qt.conf $$qtconfTargetPath; " \
"test -d $$qmlTargetPath && rm -r $$qmlTargetPath; " \
"mkdir -p $$qmlTargetPath && " \
"for p in $$QMLPATHS; do" \
"rsync -r --exclude='*.a' --exclude='*.prl' --exclude='*.qmltypes' "
macx-xcode: QMAKE_POST_LINK += "$p/ $$qmlTargetPath; done"
else: QMAKE_POST_LINK += "\$\$p/ $$qmlTargetPath; done"
}
}
}