forked from qt-creator/qt-creator
implement proper vpath handling for qt4 projects
this also removes the bogus special casing of various filename-containing variables inside the pro parser.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user