Commit a2f40fce authored by Oswald Buddenhagen's avatar Oswald Buddenhagen
Browse files

implement proper vpath handling for qt4 projects

this also removes the bogus special casing of various
filename-containing variables inside the pro parser.
parent edeb93d6
......@@ -107,54 +107,6 @@ QString ProFileReader::value(const QString &variable) const
}
// Construct QFileInfo from path value and base directory
// Truncate trailing slashs and make absolute
static inline QFileInfo infoFromPath(QString path,
const QString &baseDirectory)
{
if (path.size() > 1 && path.endsWith(QLatin1Char('/')))
path.truncate(path.size() - 1);
QFileInfo info(path);
if (info.isAbsolute())
return info;
return QFileInfo(baseDirectory, path);
}
/*!
Returns a list of absolute paths
*/
QStringList ProFileReader::absolutePathValues(const QString &variable,
const QString &baseDirectory,
PathValuesMode mode,
const ProFile *pro) const
{
QStringList rawList;
if (!pro)
rawList = values(variable);
else
rawList = values(variable, pro);
if (rawList.isEmpty())
return QStringList();
// Normalize list of paths, kill trailing slashes,
// remove duplicates while maintaining order
const QChar slash = QLatin1Char('/');
QStringList result;
const QStringList::const_iterator rcend = rawList.constEnd();
for (QStringList::const_iterator it = rawList.constBegin(); it != rcend; ++it) {
const QFileInfo info = infoFromPath(*it, baseDirectory);
if (mode == AllPaths || info.exists()) {
if (mode != ExistingFilePaths || info.isFile()) {
const QString absPath = info.absoluteFilePath();
if (!result.contains(absPath))
result.push_back(absPath);
}
}
}
return result;
}
void ProFileReader::fileMessage(const QString &message)
{
Q_UNUSED(message);
......
......@@ -53,11 +53,6 @@ public:
QString value(const QString &variable) const;
enum PathValuesMode { AllPaths, ExistingPaths, ExistingFilePaths };
QStringList absolutePathValues(const QString &variable,
const QString &baseDirectory,
PathValuesMode mode,
const ProFile *pro = 0) const;
ProFile *proFileFor(const QString &name);
signals:
void errorFound(const QString &error);
......
......@@ -132,14 +132,30 @@ void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader)
<< ProjectExplorer::ResourceType
<< ProjectExplorer::UnknownFileType);
const QString &projectDir = m_qt4ProFileNode->m_projectDir;
QStringList baseVPaths;
baseVPaths += reader->absolutePathValues("VPATH", projectDir);
baseVPaths << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH
baseVPaths += reader->absolutePathValues("DEPENDPATH", projectDir);
baseVPaths.removeDuplicates();
// update files
const QDir projectDir = QFileInfo(m_projectFilePath).dir();
foreach (FileType type, fileTypes) {
const QStringList qmakeVariables = varNames(type);
QStringList newFilePaths;
foreach (const QString &qmakeVariable, qmakeVariables)
newFilePaths += reader->absolutePathValues(qmakeVariable, projectDir.path(), ProFileReader::ExistingFilePaths, includeFile);
foreach (const QString &qmakeVariable, qmakeVariables) {
QStringList vPaths;
if (type == ProjectExplorer::SourceType)
vPaths = reader->absolutePathValues("VPATH_" + qmakeVariable, projectDir);
vPaths += baseVPaths;
if (type == ProjectExplorer::HeaderType)
vPaths += reader->absolutePathValues("INCLUDEPATH", projectDir);
vPaths.removeDuplicates();
newFilePaths += reader->absoluteFileValues(qmakeVariable, projectDir, vPaths, includeFile);
}
newFilePaths.removeDuplicates();
QList<FileNode*> existingFileNodes;
foreach (FileNode *fileNode, fileNodes()) {
......@@ -896,16 +912,16 @@ Qt4ProFileNode *Qt4ProFileNode::createSubProFileNode(const QString &path)
QStringList Qt4ProFileNode::uiDirPaths(ProFileReader *reader) const
{
QStringList candidates = reader->absolutePathValues(QLatin1String("UI_DIR"),
buildDir(),
ProFileReader::ExistingPaths);
buildDir());
candidates.removeDuplicates();
return candidates;
}
QStringList Qt4ProFileNode::mocDirPaths(ProFileReader *reader) const
{
QStringList candidates = reader->absolutePathValues(QLatin1String("MOC_DIR"),
buildDir(),
ProFileReader::ExistingPaths);
buildDir());
candidates.removeDuplicates();
return candidates;
}
......@@ -913,8 +929,7 @@ QStringList Qt4ProFileNode::includePaths(ProFileReader *reader) const
{
QStringList paths;
paths = reader->absolutePathValues(QLatin1String("INCLUDEPATH"),
m_projectDir,
ProFileReader::ExistingPaths);
m_projectDir);
paths << uiDirPaths(reader) << mocDirPaths(reader);
paths.removeDuplicates();
return paths;
......
......@@ -182,9 +182,6 @@ public:
QString propertyValue(const QString &val) const;
bool isActiveConfig(const QString &config, bool regex = false);
QStringList expandPattern(const QString &pattern);
void expandPatternHelper(const QString &relName, const QString &absName,
QStringList &sources_out);
QStringList expandVariableReferences(const QString &value);
void doVariableReplace(QString *str);
QStringList evaluateExpandFunction(const QString &function, const QString &arguments);
......@@ -844,32 +841,6 @@ void ProFileEvaluator::Private::visitProValue(ProValue *value)
m_prevLineNo = m_lineNo;
m_prevProFile = currentProFile();
// The following two blocks fix bug 180128 by making all "interesting"
// file name absolute in each .pro file, not just the top most one
if (varName == QLatin1String("SOURCES")
|| varName == QLatin1String("OBJECTIVE_SOURCES")
|| varName == QLatin1String("HEADERS")
|| varName == QLatin1String("INTERFACES")
|| varName == QLatin1String("FORMS")
|| varName == QLatin1String("FORMS3")
|| varName == QLatin1String("RESOURCES")
|| varName == QLatin1String("LEXSOURCES")
|| varName == QLatin1String("YACCSOURCES")){
// matches only existent files, expand certain(?) patterns
QStringList vv;
for (int i = v.count(); --i >= 0; )
vv << expandPattern(v[i]);
v = vv;
}
if (varName == QLatin1String("TRANSLATIONS")) {
// also matches non-existent files, but does not expand pattern
QString dir = QFileInfo(currentFileName()).absolutePath();
dir += QLatin1Char('/');
for (int i = v.count(); --i >= 0; )
v[i] = QFileInfo(dir, v[i]).absoluteFilePath();
}
switch (m_variableOperator) {
case ProVariable::SetOperator: // =
if (!m_cumulative) {
......@@ -2495,82 +2466,6 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName)
return ok;
}
void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName,
QStringList &sources_out)
{
const QStringList vpaths = values(QLatin1String("VPATH"))
+ values(QLatin1String("QMAKE_ABSOLUTE_SOURCE_PATH"))
+ values(QLatin1String("DEPENDPATH"))
+ values(QLatin1String("VPATH_SOURCES"));
QFileInfo fi(absName);
bool found = fi.exists();
// Search in all vpaths
if (!found) {
foreach (const QString &vpath, vpaths) {
fi.setFile(vpath + QDir::separator() + relName);
if (fi.exists()) {
found = true;
break;
}
}
}
if (found) {
sources_out += fi.absoluteFilePath(); // Not resolving symlinks
} else {
QString val = relName;
QString dir;
QString wildcard = val;
QString real_dir;
if (wildcard.lastIndexOf(QLatin1Char('/')) != -1) {
dir = wildcard.left(wildcard.lastIndexOf(QLatin1Char('/')) + 1);
real_dir = dir;
wildcard = wildcard.right(wildcard.length() - dir.length());
}
if (real_dir.isEmpty() || QFileInfo(real_dir).exists()) {
QStringList files = QDir(real_dir).entryList(QStringList(wildcard));
if (files.isEmpty()) {
q->logMessage(format("Failure to find %1").arg(val));
} else {
QString a;
for (int i = files.count() - 1; i >= 0; --i) {
if (files[i] == QLatin1String(".") || files[i] == QLatin1String(".."))
continue;
a = dir + files[i];
sources_out += a;
}
}
} else {
q->logMessage(format("Cannot match %1/%2, as %3 does not exist.")
.arg(real_dir).arg(wildcard).arg(real_dir));
}
}
}
/*
* Lookup of files are done in this order:
* 1. look in pwd
* 2. look in vpaths
* 3. expand wild card files relative from the profiles folder
**/
// FIXME: This code supports something that I'd consider a flaw in .pro file syntax
// which is not even documented. So arguably this can be ditched completely...
QStringList ProFileEvaluator::Private::expandPattern(const QString& pattern)
{
if (!currentProFile())
return QStringList();
QStringList sources_out;
const QString absName = QDir::cleanPath(QDir::current().absoluteFilePath(pattern));
expandPatternHelper(pattern, absName, sources_out);
return sources_out;
}
QString ProFileEvaluator::Private::format(const char *fmt) const
{
ProFile *pro = currentProFile();
......@@ -2621,6 +2516,59 @@ QStringList ProFileEvaluator::values(const QString &variableName, const ProFile
return fixEnvVariables(d->values(variableName, pro));
}
QStringList ProFileEvaluator::absolutePathValues(
const QString &variable, const QString &baseDirectory) const
{
QStringList result;
foreach (const QString &el, values(variable)) {
const QFileInfo info = QFileInfo(baseDirectory, el);
if (info.isDir())
result << QDir::cleanPath(info.absoluteFilePath());
}
return result;
}
QStringList ProFileEvaluator::absoluteFileValues(
const QString &variable, const QString &baseDirectory, const QStringList &searchDirs,
const ProFile *pro) const
{
QStringList result;
foreach (const QString &el, pro ? values(variable, pro) : values(variable)) {
QFileInfo info(el);
if (info.isAbsolute()) {
if (info.exists()) {
result << QDir::cleanPath(el);
goto next;
}
} else {
foreach (const QString &dir, searchDirs) {
QFileInfo info(dir, el);
if (info.isFile()) {
result << QDir::cleanPath(info.filePath());
goto next;
}
}
if (baseDirectory.isEmpty())
goto next;
info = QFileInfo(baseDirectory, el);
}
{
QFileInfo baseInfo(info.absolutePath());
if (baseInfo.exists()) {
QString wildcard = info.fileName();
if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) {
QDir theDir(QDir::cleanPath(baseInfo.filePath()));
foreach (const QString &fn, theDir.entryList(QStringList(wildcard)))
if (fn != QLatin1String(".") && fn != QLatin1String(".."))
result << theDir.absoluteFilePath(fn);
} // else if (acceptMissing)
}
}
next: ;
}
return result;
}
ProFileEvaluator::TemplateType ProFileEvaluator::templateType()
{
QStringList templ = values(QLatin1String("TEMPLATE"));
......
......@@ -40,7 +40,6 @@
QT_BEGIN_NAMESPACE
class ProFile;
class ProFileEvaluator;
void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap);
......@@ -76,6 +75,10 @@ public:
void addProperties(const QHash<QString, QString> &properties);
QStringList values(const QString &variableName) const;
QStringList values(const QString &variableName, const ProFile *pro) const;
QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const;
QStringList absoluteFileValues(
const QString &variable, const QString &baseDirectory, const QStringList &searchDirs,
const ProFile *pro) const;
QString propertyValue(const QString &val) const;
// for our descendents
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment