diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2021-12-03 20:23:35 +0100 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2021-12-07 11:47:34 +0100 |
commit | b0517d5bb2654a02f0ff7debd8da8c9c485c879a (patch) | |
tree | 482712b10c941bb198e03382728845a0f86fe511 /src/qml/qml | |
parent | c77b9bae690053b31c9db110ee5ad6d5741d4511 (diff) |
macOS: Add application bundle's Resources/qml dir as a QML import path
We want to ensure a macOS app bundle can find QML modules from its
build dir without having to run macdeployqt (while developing the app).
If the app is not a macOS bundle and the CMake project follows our
recommended directory layout so that the QML modules are placed in
subdirectories named by their URIs, the app can find user QML
modules using the default 'app directory' QML import path.
If the app is a bundle though, the app dir QML import path resolves
to a subdir in the bundle (build_dir/foo.app/Contents/MacOS).
It doesn't matter if the qmldir files are placed somewhere in
Resources (build_dir/foo.app/Contents/Resources/qml) or in the top
of the build dir (build_dir/My/URI), they still wouldn't be found
by default.
To solve that, both macdeployqt and our new CMake deployment rules
copy user qmldir files to the app bundle's Resources directory at
install time
e.g. foo.app/Contents/Resources/qml/QtQml/qmldir
and delegate to macdeployqt to create a qt.conf file with a custom
QML import path pointing to that dir.
At build time, our new CMake deployment rules copy the qmldir files to
Resources/qml as described above in a POST_BUILD step.
The missing part is the import path.
Instead of creating a qt.conf file or forcing the user to change their
C++ code, augment the QML engine to also consider the bundle
Resources/qml directory as a default import path on macOS.
The implementation is similar to the way we look up regular Qt
plugins in the bundle's PlugIns folder as it was added in qtbase
via fcfe2a5f67f0045e8ed606f60330df5e24cf03b2
Task-number: QTBUG-98545
Change-Id: I4f72832568c2ab8773b463b5f97b4ae060741c62
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index c5f5811755..f51fc6dc22 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -63,6 +63,10 @@ #include <QtQml/private/qqmltype_p_p.h> #include <QtQml/private/qqmlimportresolver_p.h> +#ifdef Q_OS_MACOS +#include "private/qcore_mac_p.h" +#endif + #include <algorithm> #include <functional> @@ -1727,7 +1731,24 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e) for (int ii = paths.count() - 1; ii >= 0; --ii) addPluginPath(paths.at(ii)); } -#endif +#elif defined(Q_OS_MACOS) + // Add the main bundle's Resources/qml directory as an import path, so that QML modules are + // found successfully when running the app from its build dir. + // This is where macdeployqt and our CMake deployment logic puts Qt and user qmldir files. + if (CFBundleRef bundleRef = CFBundleGetMainBundle()) { + if (QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL( + bundleRef, + QCFString(QLatin1String("qml")), 0, 0)) { + if (QCFType<CFURLRef> absoluteUrlRef = CFURLCopyAbsoluteURL(urlRef)) { + if (QCFString path = CFURLCopyFileSystemPath(absoluteUrlRef, kCFURLPOSIXPathStyle)) { + if (QFile::exists(path)) { + addImportPath(QDir(path).canonicalPath()); + } + } + } + } + } +#endif // Q_OS_DARWIN } QQmlImportDatabase::~QQmlImportDatabase() |