该篇文章内容主要集中Qt Creator HostOsInfo部分代码的分析。从分析插件中的coreplugin中的HostOsInfo模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\utils\utils-lib\下。
从hostosinfo.h引入的头文件看起:
#include "utils_global.h"
#include "osspecificaspects.h"
#include <QString>
utils_global.h内容如下所示,如果定义了UTILS_LIBRARY,则将QTCREATOR_UTILS_EXPORT定义为Q_DECL_EXPORT。如果定义了QTCREATOR_UTILS_STATIC_LIB,则将QTCREATOR_UTILS_EXPORT定义为空(单个文件进行手动测试)。否则,将QTCREATOR_UTILS_EXPORT定义为Q_DECL_IMPORT。只是用于设置编译输出方式的。
#pragma once
#include <qglobal.h>
#if defined(UTILS_LIBRARY)
# define QTCREATOR_UTILS_EXPORT Q_DECL_EXPORT
#elif defined(QTCREATOR_UTILS_STATIC_LIB) // Abuse single files for manual tests
# define QTCREATOR_UTILS_EXPORT
#else
# define QTCREATOR_UTILS_EXPORT Q_DECL_IMPORT
#endif
osspecificaspects.h
因为是windows平台,这里QTC_WIN_EXE_SUFFIX定义为".exe"。Utils命名空间里有代表操作系统类型的枚举类型。
#pragma once
#include <QString>
#include <algorithm>
#define QTC_WIN_EXE_SUFFIX ".exe"
namespace Utils {
// Add more as needed.
enum OsType { OsTypeWindows, OsTypeLinux, OsTypeMac, OsTypeOtherUnix, OsTypeOther };
namespace OsSpecificAspects {
// 如果操作系统类型是Windows,则在形参executable后加上后缀.exe
inline QString withExecutableSuffix(OsType osType, const QString &executable)
{
QString finalName = executable;
if (osType == OsTypeWindows)
finalName += QLatin1String(QTC_WIN_EXE_SUFFIX);
return finalName;
}
// 如果是Windows或者Mac平台则是Qt::CaseInsensitive(大小写不敏感)
inline Qt::CaseSensitivity fileNameCaseSensitivity(OsType osType)
{
return osType == OsTypeWindows || osType == OsTypeMac ? Qt::CaseInsensitive : Qt::CaseSensitive;
}
inline Qt::CaseSensitivity envVarCaseSensitivity(OsType osType)
{
return fileNameCaseSensitivity(osType);
}
// 路径分隔符 windows平台是; 其它平台是:
inline QChar pathListSeparator(OsType osType)
{
return QLatin1Char(osType == OsTypeWindows ? ';' : ':');
}
// 键盘修改器 如果是Mac平台,则是Qt::MetaModifier 其他是Qt::ControlModifier
inline Qt::KeyboardModifier controlModifier(OsType osType)
{
return osType == OsTypeMac ? Qt::MetaModifier : Qt::ControlModifier;
}
// 将Windows下的pathName中的/都替换为\\
inline QString pathWithNativeSeparators(OsType osType, const QString &pathName)
{
if (osType == OsTypeWindows) {
const int pos = pathName.indexOf('/');
if (pos >= 0) {
QString n = pathName;
std::replace(std::begin(n) + pos, std::end(n), '/', '\\');
return n;
}
}
return pathName;
}
} // namespace OsSpecificAspects
} // namespace Utils
HostOsInfo类
HostOsInfo类包含了返回操作系统类型的hostOs函数、返回CPU架构的hostArchitecture函数
namespace Utils {
class QTCREATOR_UTILS_EXPORT HostOsInfo
{
public:
// 这里的OsType就是上面介绍的枚举类型
static constexpr OsType hostOs()
{
#if defined(Q_OS_WIN)
return OsTypeWindows;
#elif defined(Q_OS_LINUX)
return OsTypeLinux;
#elif defined(Q_OS_MAC)
return OsTypeMac;
#elif defined(Q_OS_UNIX)
return OsTypeOtherUnix;
#else
return OsTypeOther;
#endif
}
enum HostArchitecture { HostArchitectureX86, HostArchitectureAMD64, HostArchitectureItanium, HostArchitectureArm, HostArchitectureUnknown };
static HostArchitecture hostArchitecture();
static constexpr bool isWindowsHost() { return hostOs() == OsTypeWindows; }
static constexpr bool isLinuxHost() { return hostOs() == OsTypeLinux; }
static constexpr bool isMacHost() { return hostOs() == OsTypeMac; }
static constexpr bool isAnyUnixHost()
{
#ifdef Q_OS_UNIX
return true;
#else
return false;
#endif
}
static QString withExecutableSuffix(const QString &executable)
{
return OsSpecificAspects::withExecutableSuffix(hostOs(), executable);
}
static void setOverrideFileNameCaseSensitivity(Qt::CaseSensitivity sensitivity);
static void unsetOverrideFileNameCaseSensitivity();
// 文件名大小写敏感检查
static Qt::CaseSensitivity fileNameCaseSensitivity()
{
return m_useOverrideFileNameCaseSensitivity
? m_overrideFileNameCaseSensitivity
: OsSpecificAspects::fileNameCaseSensitivity(hostOs());
}
static QChar pathListSeparator()
{
return OsSpecificAspects::pathListSeparator(hostOs());
}
static Qt::KeyboardModifier controlModifier()
{
return OsSpecificAspects::controlModifier(hostOs());
}
static bool canCreateOpenGLContext(QString *errorMessage);
private:
static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity;
static bool m_useOverrideFileNameCaseSensitivity;
};
} // namespace Utils
#include "hostosinfo.h"
#include <QCoreApplication>
#if !defined(QT_NO_OPENGL) && defined(QT_GUI_LIB)
#include <QOpenGLContext>
#endif
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
using namespace Utils;
//对静态函数进行初始化设置
Qt::CaseSensitivity HostOsInfo::m_overrideFileNameCaseSensitivity = Qt::CaseSensitive;
bool HostOsInfo::m_useOverrideFileNameCaseSensitivity = false;
void HostOsInfo::setOverrideFileNameCaseSensitivity(Qt::CaseSensitivity sensitivity)
{
m_useOverrideFileNameCaseSensitivity = true;
m_overrideFileNameCaseSensitivity = sensitivity;
}
void HostOsInfo::unsetOverrideFileNameCaseSensitivity()
{
m_useOverrideFileNameCaseSensitivity = false;
}
#ifdef Q_OS_WIN
static WORD hostProcessorArchitecture()
{
SYSTEM_INFO info;
GetNativeSystemInfo(&info); // 该函数在C:\Qt\Tools\mingw530_32\i686-w64-mingw32\include的sysinfoapi.h中
return info.wProcessorArchitecture;
}
#endif
HostOsInfo::HostArchitecture HostOsInfo::hostArchitecture()
{
#ifdef Q_OS_WIN
static const WORD processorArchitecture = hostProcessorArchitecture();
switch (processorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64: // 处于winnt.h中
return HostOsInfo::HostArchitectureAMD64;
case PROCESSOR_ARCHITECTURE_INTEL:
return HostOsInfo::HostArchitectureX86;
case PROCESSOR_ARCHITECTURE_IA64:
return HostOsInfo::HostArchitectureItanium;
case PROCESSOR_ARCHITECTURE_ARM:
return HostOsInfo::HostArchitectureArm;
default:
return HostOsInfo::HostArchitectureUnknown;
}
#else
return HostOsInfo::HostArchitectureUnknown;
#endif
}
//检查能否使用OpenGL
bool HostOsInfo::canCreateOpenGLContext(QString *errorMessage)
{
#if defined(QT_NO_OPENGL) || !defined(QT_GUI_LIB)
Q_UNUSED(errorMessage)
return false;
#else
static const bool canCreate = QOpenGLContext().create();
if (!canCreate)
*errorMessage = QCoreApplication::translate("Utils::HostOsInfo", "Cannot create OpenGL context.");
return canCreate;
#endif
}