qt.conf是与QlibraryInfo关联的。与qmake基本没有关系。
qt.conf 用于手动配置 qt程序的环境路径,qt库、translations文件等等。引入qt.conf目的就是方便手动配置QlibraryInfo的各项值,所以必须依赖QlibraryInfo类来使用。下面是QlibraryInfo中预先编译的可能会依赖的路径的名称的枚举,这些名称都对应一个默认的字符串值。
qt.conf 详细介绍的帮助文档路径为:Qt 5.12->Using qt.conf 。
具体文档为:qthelp://org.qt-project.qmake.5120/qtdoc/qt-conf.html
qt.conf所在位置要求如下:
1、:/qt/etc/qt.conf using the resource system
2、on macOS, in the Resource directory inside the application bundle, for example assistant.app/Contents/Resources/qt.conf
3、in the directory containing the application executable, i.e. QCoreApplication::applicationDirPath() + QDir::separator() + "qt.conf"
- //QtInstallDir\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\global\qlibraryinfo.h
- enum LibraryLocation
- {
- PrefixPath = 0,
- DocumentationPath,
- HeadersPath,
- LibrariesPath,
- LibraryExecutablesPath,
- BinariesPath,
- PluginsPath,
- ImportsPath,
- Qml2ImportsPath,
- ArchDataPath,
- DataPath,
- TranslationsPath,
- ExamplesPath,
- TestsPath,
- // Insert new values above this line
- // Please read the comments in qlibraryinfo.cpp before adding
- #ifdef QT_BUILD_QMAKE
- // These are not subject to binary compatibility constraints
- SysrootPath,
- SysrootifyPrefixPath,
- HostBinariesPath,
- HostLibrariesPath,
- HostDataPath,
- TargetSpecPath,
- HostSpecPath,
- HostPrefixPath,
- LastHostPath = HostPrefixPath,
- #endif
- SettingsPath = 100
- };
-
- //QtInstallDir\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\global\qlibraryinfo.cpp
- QString QLibraryInfo::location(LibraryLocation loc)
- {
- .........
- }
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- MainWindow window;
- window.show();
- return app.exec();
- }
而QLibraryInfo调用获取qt.conf的内容的调用栈如下。
下面是QlibraryInfo获取qt.conf中内容的代码入口。可以看到windows下要获取到qt.conf中的内容需要先让QCoreApplication对象初始化,在QCoreApplication对象初始化之前,调用QLibraryInfo会使用默认值。
- //QtInstallDir\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\global\qlibraryinfo.cpp
-
- QSettings *QLibraryInfoPrivate::findConfiguration()
- {
- #ifdef QT_BUILD_QMAKE
- QString qtconfig = qmake_libraryInfoFile();
- if (QFile::exists(qtconfig))
- return new QSettings(qtconfig, QSettings::IniFormat);
- #else
- QString qtconfig = QStringLiteral(":/qt/etc/qt.conf"); //应该是linux下的qt.conf的配置方式之一。linux中qt.conf可以配置在:/qt/etc/下,也可以配置在当前文件下。如果存在,程序会优先使用:/qt/etc/中的qt.conf
- if (QFile::exists(qtconfig))
- return new QSettings(qtconfig, QSettings::IniFormat);
- #ifdef Q_OS_DARWIN
- CFBundleRef bundleRef = CFBundleGetMainBundle();
- if (bundleRef) {
- QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL(bundleRef,
- QCFString(QLatin1String("qt.conf")),
- 0,
- 0);
- if (urlRef) {
- QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
- qtconfig = QDir::cleanPath(path);
- if (QFile::exists(qtconfig))
- return new QSettings(qtconfig, QSettings::IniFormat);
- }
- }
- #endif
- if (QCoreApplication::instance()) {
- QDir pwd(QCoreApplication::applicationDirPath());
- qtconfig = pwd.filePath(QLatin1String("qt.conf")); //发现 qt.conf
- if (QFile::exists(qtconfig))
- return new QSettings(qtconfig, QSettings::IniFormat);
- }
- #endif
- return 0; //no luck
- }
- //QtInstallDir\Qt5.12.0\5.12.0\Src\qtbase\src\gui\kernel\qplatformintegrationfactory.cpp
- Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive)) //(QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive)整体作为QFactoryLoader对象初始化参数,Q_GLOBAL_STATIC_WITH_ARGS作用是通过loader对QFactoryLoader对象进行包装,并加入原子计数功能。
-
-
- //QtInstallDir\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\plugin\qfactoryloader.cpp
- void QFactoryLoader::update()
- {
- #ifdef QT_SHARED
- Q_D(QFactoryLoader);
- QStringList paths = QCoreApplication::libraryPaths();
- for (int i = 0; i < paths.count(); ++i) {//update遍历librarypaths
- const QString &pluginDir = paths.at(i);
- // Already loaded, skip it...
- if (d->loadedPaths.contains(pluginDir))
- continue;
- d->loadedPaths << pluginDir;
-
- QString path = pluginDir + d->suffix;
-
- .....
- }
-
- QFactoryLoader::QFactoryLoader(const char *iid,
- const QString &suffix,
- Qt::CaseSensitivity cs)
- : QObject(*new QFactoryLoaderPrivate)
- {
- moveToThread(QCoreApplicationPrivate::mainThread());
- Q_D(QFactoryLoader);
- d->iid = iid;
- #if QT_CONFIG(library)
- d->cs = cs;
- d->suffix = suffix; //suffix初始化
-
- QMutexLocker locker(qt_factoryloader_mutex());
- update(); //QFactoryLoader初始化调用update
- .....
- }
qt.conf 内容格式为INI文件格式,就是QSetting保存文件的内容的格式。设置Prefix,就不需要拷贝qt的库文件(比如qt5core.dll)到exe的文件夹下了。
- [Paths] //注释
- Prefix=QtInstallDir/Qt5.12.0/5.12.0/msvc2015_64 //prefix是可以是相对路径,相对于QCoreApplication::applicationDirPath(),其他路径都是相对于Prefix的。此处用的是绝对路径,QtInstallDir/Qt5.12.0/5.12.0/msvc2015_64是电脑上qt库的位置。
- Binaries=bin //Binaries、Libraries、include的值与 Prefix的值或当前路径 组装出对应的路径。
- Libraries=lib
- Plugins=plugins
- Doc=deg\\doc //"\"在INI文件中是特殊字符
- Imports=ggt/imports
- Qml2Imports=qml
- Platforms/WindowsArguments = fontengine=freetype //为windows platform设置参数。为qwindows.dll提供参数。
qt.conf等号左边的叫键,右边的叫值,值根据具体开发环境进行设置。有效的固定的键名及其默认值如下(可以发现固定键与enum LibraryLocation中的项名是一一对应的)(注意除了固定键,还可以有不固定的参数键,目前qt只提供platformPluginArguments()来处理传入参数):
- //QtInstallDir\Qt5.12.0\5.12.0\Src\qtbase\src\corelib\global\qlibraryinfo.cpp
- static const struct {
- char key[19], value[13];
- } qtConfEntries[] = {
- { "Prefix", "." },
- { "Documentation", "doc" }, // should be ${Data}/doc
- { "Headers", "include" },
- { "Libraries", "lib" },
- #ifdef Q_OS_WIN
- { "LibraryExecutables", "bin" },
- #else
- { "LibraryExecutables", "libexec" }, // should be ${ArchData}/libexec
- #endif
- { "Binaries", "bin" },
- { "Plugins", "plugins" }, // should be ${ArchData}/plugins,
- { "Imports", "imports" }, // should be ${ArchData}/imports
- { "Qml2Imports", "qml" }, // should be ${ArchData}/qml
- { "ArchData", "." },
- { "Data", "." },
- { "Translations", "translations" }, // should be ${Data}/translations
- { "Examples", "examples" },
- { "Tests", "tests" },
- #ifdef QT_BUILD_QMAKE //这个宏表示下面的键值对在编译qmake的时候会用到。
- { "Sysroot", "" },
- { "SysrootifyPrefix", "" },
- { "HostBinaries", "bin" },
- { "HostLibraries", "lib" },
- { "HostData", "." },
- { "TargetSpec", "" },
- { "HostSpec", "" },
- { "HostPrefix", "" },
- #endif
- };
-
- ......
- static const char platformsSection[] = "Platforms";
- ......
-
- QStringList QLibraryInfo::platformPluginArguments(const QString &platformName)
- {
- #if !defined(QT_BUILD_QMAKE) && !defined(QT_NO_SETTINGS)
- QScopedPointer<const QSettings> settings(QLibraryInfoPrivate::findConfiguration());
- if (!settings.isNull()) {
- const QString key = QLatin1String(platformsSection)
- + QLatin1Char('/')
- + platformName
- + QLatin1String("Arguments");
- return settings->value(key).toStringList();
- }
- #else
- Q_UNUSED(platformName);
- #endif // !QT_BUILD_QMAKE && !QT_NO_SETTINGS
- return QStringList();
- }
All Qt GUI applications require a plugin that implements the Qt Platform Abstraction (QPA) layer in Qt 5. For Windows, the name of the platform plugin is qwindows.dll. This file must be located within a specific subdirectory (by default, platforms) under your distribution directory. Alternatively, it is possible to adjust the search path Qt uses to find its plugins, as described below.
为了保证下面程序运行,需要在该执行程序路径下(我用于调试,所以放在build-plugandpaint-Desktop_Qt_5_12_0_MSVC2015_64bit-Debug下)建立platforms子目录并放入qwindows.dll 或qwindowsd.dll;或者在build-plugandpaint-Desktop_Qt_5_12_0_MSVC2015_64bit-Debug/plugins下建立子目录platforms,并将qwindows.dll或者qwindowsd.dll放入其中。
qt程序设置plugin查找路径的方式:
1、Using qt.conf. This approach is the recommended if you have executables in different places sharing the same plugins.
2、Using QApplication::addLibraryPath() or QApplication::setLibraryPaths(). This approach is recommended if you only have one executable that will use the plugin.
3、Using a third party installation utility to change the hard-coded paths in the QtCore library.
QString QLibraryInfo::location(LibraryLocation loc)获取path的过程可以参考下面文章: