qt获取qt.conf 中内容过程 QLibraryInfo

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();
}
qt自带examples plugandpaint项目的编译后的文件结构

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博客

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值