Skip to content

Commit bc488b4

Browse files
committed
feat(generator): discover Qt headers via QLibraryInfo; validate includes
- Prefer `QLibraryInfo::{HeadersPath}` to locate Qt headers; fall back to `$QTDIR/include` when `QLibraryInfo` is unavailable or invalid. - Accept include roots from `PYTHONQT_INCLUDE` and `--include-paths`; warn and skip non-existent paths; normalize with `QDir::cleanPath`. - Probe module subdirs under the Qt include root and append those that exist (QtCore, QtGui, QtNetwork, QtOpenGL, QtXml). - Use `DUI::addIncludePath(...)` instead of pushing to `includePaths`. - Minor cleanups: Use QStringLiteral, add helpers for path joining/dir checks. Remove hardcoded macOS `/Library/Frameworks` header paths from the QTDIR-missing branch anticipating the addition of `getFrameworkDirectories` function.
1 parent 9846c5d commit bc488b4

File tree

1 file changed

+65
-51
lines changed

1 file changed

+65
-51
lines changed

generator/main.cpp

Lines changed: 65 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include <QDir>
5959
#include <QFileInfo>
6060
#include <QFile>
61+
#include <QLibraryInfo>
6162
#include <QTextStream>
6263
#include <QRegularExpression>
6364

@@ -67,67 +68,80 @@ void displayHelp(GeneratorSet *generatorSet);
6768

6869
namespace
6970
{
71+
static const QStringList candidatesQtModules {
72+
QStringLiteral("QtCore"),
73+
QStringLiteral("QtGui"),
74+
QStringLiteral("QtNetwork"),
75+
QStringLiteral("QtOpenGL"),
76+
QStringLiteral("QtXml"),
77+
};
78+
79+
static bool isDir(const QString& p) { return QFileInfo(p).isDir(); }
80+
static QString joinPath(const QString& base, const QString& child) {
81+
return QDir(base).filePath(child);
82+
}
7083

7184
QStringList getIncludeDirectories(const QString &commandLineIncludes)
7285
{
7386
QStringList includes;
74-
includes << QString(".");
75-
76-
QChar pathSplitter = QDir::listSeparator();
87+
includes << QStringLiteral(".");
7788

78-
// Environment PYTHONQT_INCLUDE
79-
QString includePath = getenv("PYTHONQT_INCLUDE");
80-
if (!includePath.isEmpty())
81-
includes += includePath.split(pathSplitter, Qt::SkipEmptyParts);
89+
const QChar pathSplitter = QDir::listSeparator();
8290

83-
// Includes from the command line
84-
if (!commandLineIncludes.isEmpty())
85-
includes += commandLineIncludes.split(pathSplitter, Qt::SkipEmptyParts);
86-
for (auto it = includes.begin(); it != includes.end();)
87-
{
88-
if (!QDir(*it).exists())
89-
{
90-
qWarning() << "Include path " << it->toUtf8() << " does not exist, ignoring it.";
91-
it = includes.erase(it);
91+
// From env var PYTHONQT_INCLUDE
92+
const QString envInclude = qEnvironmentVariable("PYTHONQT_INCLUDE");
93+
if (!envInclude.isEmpty()) {
94+
QStringList envIncludes = envInclude.split(pathSplitter, Qt::SkipEmptyParts);
95+
for(const QString& include: qAsConst(envIncludes)) {
96+
if (isDir(include)) {
97+
includes << include;
98+
}
99+
else {
100+
qWarning() << "Include path" << include << "does not exist, ignoring.";
101+
}
92102
}
93-
else
94-
{
95-
++it;
103+
}
104+
105+
// CLI-provided include paths
106+
if (!commandLineIncludes.isEmpty()) {
107+
const QStringList cliIncludes = commandLineIncludes.split(QDir::listSeparator(), Qt::SkipEmptyParts);
108+
for (const QString& include : cliIncludes) {
109+
if (isDir(include)) {
110+
includes << QDir::cleanPath(include);
111+
}
112+
else {
113+
qWarning() << "Include path" << include << "does not exist, ignoring.";
114+
}
96115
}
97116
}
98117

99-
// Include Qt
100-
QString qtdir = getenv("QTDIR");
101-
if (qtdir.isEmpty() || !QDir(qtdir).exists(qtdir))
102-
{
103-
QString reason = "The QTDIR environment variable " + qtdir.isEmpty() ?
104-
"is not set. " : "points to a non-existing directory. ";
105-
#if defined(Q_OS_MAC)
106-
qWarning() << reason << "Assuming standard binary install using frameworks.";
107-
QString frameworkDir = "/Library/Frameworks";
108-
includes << (frameworkDir + "/QtXml.framework/Headers");
109-
includes << (frameworkDir + "/QtNetwork.framework/Headers");
110-
includes << (frameworkDir + "/QtCore.framework/Headers");
111-
includes << (frameworkDir + "/QtGui.framework/Headers");
112-
includes << (frameworkDir + "/QtOpenGL.framework/Headers");
113-
includes << frameworkDir;
114-
#else
115-
qWarning() << reason << "This may cause problems with finding the necessary include files.";
116-
#endif
118+
// Prefer QLibraryInfo (works without QTDIR)
119+
QString qtInclude = QLibraryInfo::location(QLibraryInfo::HeadersPath);
120+
if (!isDir(qtInclude)) {
121+
// Fallback to QTDIR/include
122+
const QString qtDir = qEnvironmentVariable("QTDIR");
123+
if (qtDir.isEmpty() || !isDir(qtDir)) {
124+
const QString reason = QStringLiteral("The QTDIR environment variable ")
125+
+ (qtDir.isEmpty()
126+
? "is not set."
127+
: "points to a non-existing directory.");
128+
qWarning() << reason << "This may cause problems with finding the necessary include files.";
129+
} else {
130+
qtInclude = joinPath(qtDir, QStringLiteral("include"));
131+
}
117132
}
118-
else
119-
{
120-
std::cout << "-------------------------------------------------------------" << std::endl;
121-
std::cout << "Using QT at: " << qtdir.toLocal8Bit().constData() << std::endl;
122-
std::cout << "-------------------------------------------------------------" << std::endl;
123-
qtdir += "/include";
124-
includes << (qtdir + "/QtXml");
125-
includes << (qtdir + "/QtNetwork");
126-
includes << (qtdir + "/QtCore");
127-
includes << (qtdir + "/QtGui");
128-
includes << (qtdir + "/QtOpenGL");
129-
includes << qtdir;
133+
if (!qtInclude.isEmpty() && isDir(qtInclude)) {
134+
qInfo() << "Using Qt headers at:" << qtInclude;
135+
// Check for <qtInclude>/<Module>
136+
for (const auto& qtModule : std::as_const(candidatesQtModules)) {
137+
const QString qtModuleInclude = joinPath(qtInclude, qtModule);
138+
if (isDir(qtModuleInclude)) {
139+
includes << qtModuleInclude;
140+
}
141+
}
142+
includes << qtInclude;
130143
}
144+
131145
return includes;
132146
}
133147

@@ -136,8 +150,8 @@ namespace
136150
{
137151
simplecpp::DUI dui; // settings
138152

139-
for(QString include : includePaths) {
140-
dui.includePaths.push_back(QDir::toNativeSeparators(include).toStdString());
153+
for(const QString& include : includePaths) {
154+
dui.addIncludePath(QDir::toNativeSeparators(include).toStdString());
141155
}
142156
dui.defines.push_back("__cplusplus=1");
143157
dui.defines.push_back("__STDC__");

0 commit comments

Comments
 (0)