Skip to content

Commit c57983e

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 d9df6e0 commit c57983e

File tree

1 file changed

+70
-51
lines changed

1 file changed

+70
-51
lines changed

generator/main.cpp

Lines changed: 70 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,85 @@ 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+
}
83+
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
84+
QString qEnvironmentVariable(const char *varName){
85+
return QString::fromLocal8Bit(qgetenv(varName));
86+
}
87+
#endif
7088

7189
QStringList getIncludeDirectories(const QString &commandLineIncludes)
7290
{
7391
QStringList includes;
74-
includes << QString(".");
92+
includes << QStringLiteral(".");
7593

76-
QChar pathSplitter = QDir::listSeparator();
94+
const QChar pathSplitter = QDir::listSeparator();
7795

78-
// Environment PYTHONQT_INCLUDE
79-
QString includePath = getenv("PYTHONQT_INCLUDE");
80-
if (!includePath.isEmpty())
81-
includes += includePath.split(pathSplitter, Qt::SkipEmptyParts);
82-
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);
96+
// From env var PYTHONQT_INCLUDE
97+
const QString envInclude = qEnvironmentVariable("PYTHONQT_INCLUDE");
98+
if (!envInclude.isEmpty()) {
99+
QStringList envIncludes = envInclude.split(pathSplitter, Qt::SkipEmptyParts);
100+
for(const QString& include: qAsConst(envIncludes)) {
101+
if (isDir(include)) {
102+
includes << include;
103+
}
104+
else {
105+
qWarning() << "Include path" << include << "does not exist, ignoring.";
106+
}
92107
}
93-
else
94-
{
95-
++it;
108+
}
109+
110+
// CLI-provided include paths
111+
if (!commandLineIncludes.isEmpty()) {
112+
const QStringList cliIncludes = commandLineIncludes.split(QDir::listSeparator(), Qt::SkipEmptyParts);
113+
for (const QString& include : cliIncludes) {
114+
if (isDir(include)) {
115+
includes << QDir::cleanPath(include);
116+
}
117+
else {
118+
qWarning() << "Include path" << include << "does not exist, ignoring.";
119+
}
96120
}
97121
}
98122

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
123+
// Prefer QLibraryInfo (works without QTDIR)
124+
QString qtInclude = QLibraryInfo::location(QLibraryInfo::HeadersPath);
125+
if (!isDir(qtInclude)) {
126+
// Fallback to QTDIR/include
127+
const QString qtDir = qEnvironmentVariable("QTDIR");
128+
if (qtDir.isEmpty() || !isDir(qtDir)) {
129+
const QString reason = QStringLiteral("The QTDIR environment variable ")
130+
+ (qtDir.isEmpty()
131+
? "is not set."
132+
: "points to a non-existing directory.");
133+
qWarning() << reason << "This may cause problems with finding the necessary include files.";
134+
} else {
135+
qtInclude = joinPath(qtDir, QStringLiteral("include"));
136+
}
117137
}
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;
138+
if (!qtInclude.isEmpty() && isDir(qtInclude)) {
139+
qInfo() << "Using Qt headers at:" << qtInclude;
140+
// Check for <qtInclude>/<Module>
141+
for (const auto& qtModule : std::as_const(candidatesQtModules)) {
142+
const QString qtModuleInclude = joinPath(qtInclude, qtModule);
143+
if (isDir(qtModuleInclude)) {
144+
includes << qtModuleInclude;
145+
}
146+
}
147+
includes << qtInclude;
130148
}
149+
131150
return includes;
132151
}
133152

@@ -136,8 +155,8 @@ namespace
136155
{
137156
simplecpp::DUI dui; // settings
138157

139-
for(QString include : includePaths) {
140-
dui.includePaths.push_back(QDir::toNativeSeparators(include).toStdString());
158+
for(const QString& include : includePaths) {
159+
dui.addIncludePath(QDir::toNativeSeparators(include).toStdString());
141160
}
142161
dui.defines.push_back("__cplusplus=1");
143162
dui.defines.push_back("__STDC__");

0 commit comments

Comments
 (0)