qt.conf是与QlibraryInfo关联的。与qmake基本没有关系。
qt.conf 用于手动配置 qt程序的环境路径,qt库、translations文件等等,如果想要qt.conf配置文件生效,需要将自定义的qt.conf放入生成的可执行文件同级目录中。
引入qt.conf目的就是方便手动配置QlibraryInfo的各项值,所以必须依赖QlibraryInfo类来使用。下面是QlibraryInfo中预先编译的可能会依赖的路径的名称的枚举,这些名称都对应一个默认的字符串值。
QlibraryInfo有一个全局的static对象,其初始化的默认值是在qconfig.h qconfig 中进行的,如果有为工程添加qt.conf,则会再从qt.conf中获取。
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();
}
![](https://i-blog.csdnimg.cn/blog_migrate/07d5bcab42e5627a928ebbd9c41db884.png)
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的过程可以参考下面文章:
在给qt安装mingw后,出现无法识别qmake的问题,需要在mingw版的qmake.exe的同级文件夹下放入qt.conf,可以从其他版本的qmake对应的文件夹下拷贝去过。
qconfig.h qconfig.cpp_丘上人的博客-CSDN博客
Qt没有被正确的安装, 请运行make install_qt没有被正确安装,请运行make install-CSDN博客