qmake: Normalize paths instead of converting to native separators

Task-number: QTBUG-22738

Change-Id: I40163a883d84beff79f52bff141d61dfe921c129
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
Orgad Shaneh 2011-11-15 10:34:38 +02:00 committed by Qt by Nokia
parent 711f367d8f
commit f9b94a7ee1
6 changed files with 92 additions and 68 deletions

3
dist/changes-5.0.0 vendored
View File

@ -159,6 +159,9 @@ information about a particular change.
- QNetworkConfiguration::bearerName() removed, and bearerTypeName() should be used.
- qmake
* several functions and built-in variables were modified to return normalized paths.
****************************************************************************
* General *

View File

@ -103,8 +103,8 @@ int runQMake(int argc, char **argv)
if(!(oldpwd.length() == 3 && oldpwd[0].isLetter() && oldpwd.endsWith(":/")))
#endif
{
if(oldpwd.right(1) != QString(QChar(QDir::separator())))
oldpwd += QDir::separator();
if(!oldpwd.endsWith(QLatin1Char('/')))
oldpwd += QLatin1Char('/');
}
Option::output_dir = oldpwd; //for now this is the output dir
@ -141,28 +141,33 @@ int runQMake(int argc, char **argv)
for(QStringList::Iterator pfile = files.begin(); pfile != files.end(); pfile++) {
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
QString fn = Option::fixPathToLocalOS((*pfile));
QString fn = Option::normalizePath(*pfile);
if(!QFile::exists(fn)) {
fprintf(stderr, "Cannot find file: %s.\n", fn.toLatin1().constData());
fprintf(stderr, "Cannot find file: %s.\n",
QDir::toNativeSeparators(fn).toLatin1().constData());
exit_val = 2;
continue;
}
//setup pwd properly
debug_msg(1, "Resetting dir to: %s", oldpwd.toLatin1().constData());
debug_msg(1, "Resetting dir to: %s",
QDir::toNativeSeparators(oldpwd).toLatin1().constData());
qmake_setpwd(oldpwd); //reset the old pwd
int di = fn.lastIndexOf(QDir::separator());
int di = fn.lastIndexOf(QLatin1Char('/'));
if(di != -1) {
debug_msg(1, "Changing dir to: %s", fn.left(di).toLatin1().constData());
debug_msg(1, "Changing dir to: %s",
QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
if(!qmake_setpwd(fn.left(di)))
fprintf(stderr, "Cannot find directory: %s\n", fn.left(di).toLatin1().constData());
fprintf(stderr, "Cannot find directory: %s\n",
QDir::toNativeSeparators(fn.left(di)).toLatin1().constData());
fn = fn.right(fn.length() - di - 1);
}
// read project..
if(!project.read(fn)) {
fprintf(stderr, "Error processing project file: %s\n",
fn == "-" ? "(stdin)" : (*pfile).toLatin1().constData());
fn == QLatin1String("-") ?
"(stdin)" : QDir::toNativeSeparators(*pfile).toLatin1().constData());
exit_val = 3;
continue;
}
@ -179,7 +184,8 @@ int runQMake(int argc, char **argv)
if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
fprintf(stderr, "Unable to generate project file.\n");
else
fprintf(stderr, "Unable to generate makefile for: %s\n", (*pfile).toLatin1().constData());
fprintf(stderr, "Unable to generate makefile for: %s\n",
QDir::toNativeSeparators(*pfile).toLatin1().constData());
exit_val = 5;
}
delete mkfile;

View File

@ -75,13 +75,14 @@ QMakeMetaInfo::readLib(QString lib)
meta_type = "libtool";
} else if(meta_file.endsWith(Option::prl_ext)) {
QMakeProject proj;
if(!proj.read(Option::fixPathToLocalOS(meta_file), QMakeProject::ReadProFile))
if(!proj.read(Option::normalizePath(meta_file), QMakeProject::ReadProFile))
return false;
meta_type = "qmake";
vars = proj.variables();
ret = true;
} else {
warn_msg(WarnLogic, "QMakeMetaInfo: unknown file format for %s", meta_file.toLatin1().constData());
warn_msg(WarnLogic, "QMakeMetaInfo: unknown file format for %s",
QDir::toNativeSeparators(meta_file).toLatin1().constData());
}
}
if(ret)
@ -102,8 +103,8 @@ QMakeMetaInfo::findLib(QString lib)
{
if((lib[0] == '\'' || lib[0] == '"') &&
lib[lib.length()-1] == lib[0])
lib = lib.mid(1, lib.length()-2);
lib = Option::fixPathToLocalOS(lib);
lib = lib.mid(1, lib.length()-2);
lib = Option::normalizePath(lib);
QString ret;
QString extns[] = { Option::prl_ext, /*Option::pkgcfg_ext, Option::libtool_ext,*/ QString() };
@ -133,13 +134,14 @@ QMakeMetaInfo::readLibtoolFile(const QString &f)
{
/* I can just run the .la through the .pro parser since they are compatible.. */
QMakeProject proj;
if(!proj.read(Option::fixPathToLocalOS(f), QMakeProject::ReadProFile))
QString nf = Option::normalizePath(f);
if(!proj.read(nf, QMakeProject::ReadProFile))
return false;
QString dirf = Option::fixPathToTargetOS(f).section(Option::dir_sep, 0, -2);
if(dirf == f)
QString dirf = nf.section(QLatin1Char('/'), 0, -2);
if(dirf == nf)
dirf = "";
else if(!dirf.isEmpty() && !dirf.endsWith(Option::output_dir))
dirf += Option::dir_sep;
dirf += QLatin1Char('/');
QHash<QString, QStringList> &v = proj.variables();
for(QHash<QString, QStringList>::Iterator it = v.begin(); it != v.end(); ++it) {
QStringList lst = it.value();
@ -152,18 +154,18 @@ QMakeMetaInfo::readLibtoolFile(const QString &f)
if((dir.startsWith("'") || dir.startsWith("\"")) && dir.endsWith(QString(dir[0])))
dir = dir.mid(1, dir.length() - 2);
dir = dir.trimmed();
if(!dir.isEmpty() && !dir.endsWith(Option::dir_sep))
dir += Option::dir_sep;
if(!dir.isEmpty() && !dir.endsWith(QLatin1Char('/')))
dir += QLatin1Char('/');
if(lst.count() == 1)
lst = lst.first().split(" ");
for(QStringList::Iterator lst_it = lst.begin(); lst_it != lst.end(); ++lst_it) {
bool found = false;
QString dirs[] = { "", dir, dirf, dirf + ".libs" + QDir::separator(), "(term)" };
QString dirs[] = { "", dir, dirf, dirf + ".libs/", "(term)" };
for(int i = 0; !found && dirs[i] != "(term)"; i++) {
if(QFile::exists(dirs[i] + (*lst_it))) {
QString targ = dirs[i] + (*lst_it);
if(QDir::isRelativePath(targ))
targ.prepend(qmake_getpwd() + QDir::separator());
targ.prepend(qmake_getpwd() + QLatin1Char('/'));
vars["QMAKE_PRL_TARGET"] << targ;
found = true;
}

View File

@ -659,9 +659,16 @@ Option::fixString(QString string, uchar flags)
if(string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':'))
string[0] = string[0].toLower();
bool localSep = (flags & Option::FixPathToLocalSeparators) != 0;
bool targetSep = (flags & Option::FixPathToTargetSeparators) != 0;
bool normalSep = (flags & Option::FixPathToNormalSeparators) != 0;
// either none or only one active flag
Q_ASSERT(localSep + targetSep + normalSep <= 1);
//fix separators
Q_ASSERT(!((flags & Option::FixPathToLocalSeparators) && (flags & Option::FixPathToTargetSeparators)));
if(flags & Option::FixPathToLocalSeparators) {
if (flags & Option::FixPathToNormalSeparators) {
string = string.replace('\\', '/');
} else if (flags & Option::FixPathToLocalSeparators) {
#if defined(Q_OS_WIN32)
string = string.replace('/', '\\');
#else

View File

@ -115,7 +115,8 @@ struct Option
FixEnvVars = 0x01,
FixPathCanonicalize = 0x02,
FixPathToLocalSeparators = 0x04,
FixPathToTargetSeparators = 0x08
FixPathToTargetSeparators = 0x08,
FixPathToNormalSeparators = 0x10
};
static QString fixString(QString string, uchar flags);
@ -138,6 +139,15 @@ struct Option
flags |= FixPathCanonicalize;
return fixString(in, flags);
}
inline static QString normalizePath(const QString &in, bool fix_env=true, bool canonical=true)
{
uchar flags = FixPathToNormalSeparators;
if (fix_env)
flags |= FixEnvVars;
if (canonical)
flags |= FixPathCanonicalize;
return fixString(in, flags);
}
inline static bool hasFileExtension(const QString &str, const QStringList &extensions)
{

View File

@ -532,24 +532,24 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0)
{
QStringList concat;
{
const QString base_concat = QDir::separator() + QString("features");
const QString base_concat = QLatin1String("/features");
switch(Option::target_mode) {
case Option::TARG_MACX_MODE: //also a unix
concat << base_concat + QDir::separator() + "mac";
concat << base_concat + QDir::separator() + "macx";
concat << base_concat + QDir::separator() + "unix";
concat << base_concat + QLatin1String("/mac");
concat << base_concat + QLatin1String("/macx");
concat << base_concat + QLatin1String("/unix");
break;
default: // Can't happen, just make the compiler shut up
case Option::TARG_UNIX_MODE:
concat << base_concat + QDir::separator() + "unix";
concat << base_concat + QLatin1String("/unix");
break;
case Option::TARG_WIN_MODE:
concat << base_concat + QDir::separator() + "win32";
concat << base_concat + QLatin1String("/win32");
break;
}
concat << base_concat;
}
const QString mkspecs_concat = QDir::separator() + QString("mkspecs");
const QString mkspecs_concat = QLatin1String("/mkspecs");
QStringList feature_roots;
QByteArray mkspec_path = qgetenv("QMAKEFEATURES");
if(!mkspec_path.isNull())
@ -558,9 +558,9 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0)
feature_roots += splitPathList(prop->value("QMAKEFEATURES"));
if(!Option::mkfile::cachefile.isEmpty()) {
QString path;
int last_slash = Option::mkfile::cachefile.lastIndexOf(QDir::separator());
int last_slash = Option::mkfile::cachefile.lastIndexOf(QLatin1Char('/'));
if(last_slash != -1)
path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash), false);
path = Option::normalizePath(Option::mkfile::cachefile.left(last_slash), false);
for(QStringList::Iterator concat_it = concat.begin();
concat_it != concat.end(); ++concat_it)
feature_roots << (path + (*concat_it));
@ -575,14 +575,14 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0)
}
}
if(!Option::mkfile::qmakespec.isEmpty())
feature_roots << Option::mkfile::qmakespec + QDir::separator() + "features";
feature_roots << Option::mkfile::qmakespec + QLatin1String("/features");
if(!Option::mkfile::qmakespec.isEmpty()) {
QFileInfo specfi(Option::mkfile::qmakespec);
QDir specdir(specfi.absoluteFilePath());
while(!specdir.isRoot()) {
if(!specdir.cdUp() || specdir.isRoot())
break;
if(QFile::exists(specdir.path() + QDir::separator() + "features")) {
if(QFile::exists(specdir.path() + QLatin1String("/features"))) {
for(QStringList::Iterator concat_it = concat.begin();
concat_it != concat.end(); ++concat_it)
feature_roots << (specdir.path() + (*concat_it));
@ -604,7 +604,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0)
QStringList qmake_mkspec_paths()
{
QStringList ret;
const QString concat = QDir::separator() + QString("mkspecs");
const QString concat = QLatin1String("/mkspecs");
QByteArray qmakepath = qgetenv("QMAKEPATH");
if (!qmakepath.isEmpty()) {
const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath));
@ -1232,10 +1232,10 @@ QMakeProject::read(const QString &file, QHash<QString, QStringList> &place)
reset();
const QString oldpwd = qmake_getpwd();
QString filename = Option::fixPathToLocalOS(file, false);
QString filename = Option::normalizePath(file, false);
bool ret = false, using_stdin = false;
QFile qfile;
if(!strcmp(filename.toLatin1(), "-")) {
if(filename == QLatin1String("-")) {
qfile.setFileName("");
ret = qfile.open(stdin, QIODevice::ReadOnly);
using_stdin = true;
@ -1288,10 +1288,10 @@ QMakeProject::read(uchar cmd)
int cache_depth = -1;
QString qmake_cache = Option::mkfile::cachefile;
if(qmake_cache.isEmpty()) { //find it as it has not been specified
QString dir = QDir::toNativeSeparators(Option::output_dir);
while(!QFile::exists((qmake_cache = dir + QDir::separator() + ".qmake.cache"))) {
dir = dir.left(dir.lastIndexOf(QDir::separator()));
if(dir.isEmpty() || dir.indexOf(QDir::separator()) == -1) {
QString dir = Option::output_dir;
while(!QFile::exists((qmake_cache = dir + QLatin1String("/.qmake.cache")))) {
dir = dir.left(dir.lastIndexOf(QLatin1Char('/')));
if(dir.isEmpty() || dir.indexOf(QLatin1Char('/')) == -1) {
qmake_cache = "";
break;
}
@ -1321,7 +1321,7 @@ QMakeProject::read(uchar cmd)
mkspec_roots.join("::").toLatin1().constData());
if(qmakespec.isEmpty()) {
for(QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) {
QString mkspec = (*it) + QDir::separator() + "default";
QString mkspec = (*it) + QLatin1String("/default");
QFileInfo default_info(mkspec);
if(default_info.exists() && default_info.isDir()) {
qmakespec = mkspec;
@ -1343,7 +1343,7 @@ QMakeProject::read(uchar cmd)
} else {
bool found_mkspec = false;
for(QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) {
QString mkspec = (*it) + QDir::separator() + qmakespec;
QString mkspec = (*it) + QLatin1Char('/') + qmakespec;
if(QFile::exists(mkspec)) {
found_mkspec = true;
Option::mkfile::qmakespec = qmakespec = mkspec;
@ -1359,9 +1359,9 @@ QMakeProject::read(uchar cmd)
}
// parse qmake configuration
while(qmakespec.endsWith(QString(QChar(QDir::separator()))))
while(qmakespec.endsWith(QLatin1Char('/')))
qmakespec.truncate(qmakespec.length()-1);
QString spec = qmakespec + QDir::separator() + "qmake.conf";
QString spec = qmakespec + QLatin1String("/qmake.conf");
debug_msg(1, "QMAKESPEC conf: reading %s", spec.toLatin1().constData());
if(!read(spec, base_vars)) {
fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.toLatin1().constData());
@ -1635,7 +1635,7 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash<QString, QString
if(!file.endsWith(Option::prf_ext))
file += Option::prf_ext;
validateModes(); // init dir_sep
if(file.indexOf(Option::dir_sep) == -1 || !QFile::exists(file)) {
if(file.indexOf(QLatin1Char('/')) == -1 || !QFile::exists(file)) {
static QStringList *feature_roots = 0;
if(!feature_roots) {
feature_roots = new QStringList(qmake_feature_paths(prop));
@ -1650,7 +1650,7 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash<QString, QString
currFile = QFileInfo(currFile.canonicalFilePath());
for(int root = 0; root < feature_roots->size(); ++root) {
prfFile = QFileInfo(feature_roots->at(root) +
QDir::separator() + file).canonicalFilePath();
QLatin1Char('/') + file).canonicalFilePath();
if(prfFile == currFile) {
start_root = root+1;
break;
@ -1659,7 +1659,7 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash<QString, QString
}
}
for(int root = start_root; root < feature_roots->size(); ++root) {
QString prf(feature_roots->at(root) + QDir::separator() + file);
QString prf(feature_roots->at(root) + QLatin1Char('/') + file);
if(QFile::exists(prf + Option::js_ext)) {
format = JSFormat;
file = prf + Option::js_ext;
@ -1683,9 +1683,9 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash<QString, QString
include_roots << qmake_getpwd();
include_roots << Option::output_dir;
for(int root = 0; root < include_roots.size(); ++root) {
QString testName = QDir::toNativeSeparators(include_roots[root]);
if (!testName.endsWith(QString(QDir::separator())))
testName += QDir::separator();
QString testName = QDir::fromNativeSeparators(include_roots[root]);
if (!testName.endsWith(QLatin1Char('/')))
testName += QLatin1Char('/');
testName += file;
if(QFile::exists(testName)) {
file = testName;
@ -1711,10 +1711,10 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash<QString, QString
file.toLatin1().constData());
QString orig_file = file;
int di = file.lastIndexOf(QDir::separator());
int di = file.lastIndexOf(QLatin1Char('/'));
QString oldpwd = qmake_getpwd();
if(di != -1) {
if(!qmake_setpwd(file.left(file.lastIndexOf(QDir::separator())))) {
if(!qmake_setpwd(file.left(file.lastIndexOf(QLatin1Char('/'))))) {
fprintf(stderr, "Cannot find directory: %s\n", file.left(di).toLatin1().constData());
return IncludeFailure;
}
@ -1903,8 +1903,7 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list,
fprintf(stderr, "%s:%d: cat(file) requires one argument.\n",
parser.file.toLatin1().constData(), parser.line_no);
} else {
QString file = args[0];
file = Option::fixPathToLocalOS(file);
QString file = Option::normalizePath(args[0]);
bool singleLine = true;
if(args.count() > 1)
@ -1927,8 +1926,7 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list,
fprintf(stderr, "%s:%d: fromfile(file, variable) requires two arguments.\n",
parser.file.toLatin1().constData(), parser.line_no);
} else {
QString file = args[0], seek_var = args[1];
file = Option::fixPathToLocalOS(file);
QString seek_var = args[1], file = Option::normalizePath(args[0]);
QHash<QString, QStringList> tmp;
if(doProjectInclude(file, IncludeFlagNewParser, tmp) == IncludeSuccess) {
@ -2171,8 +2169,8 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list,
if(args.count() == 2)
recursive = (args[1].toLower() == "true" || args[1].toInt());
QStringList dirs;
QString r = Option::fixPathToLocalOS(args[0]);
int slash = r.lastIndexOf(QDir::separator());
QString r = Option::normalizePath(args[0]);
int slash = r.lastIndexOf(QLatin1Char('/'));
if(slash != -1) {
dirs.append(r.left(slash));
r = r.mid(slash+1);
@ -2183,7 +2181,7 @@ QMakeProject::doProjectExpand(QString func, QList<QStringList> args_list,
const QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard);
for(int d = 0; d < dirs.count(); d++) {
QString dir = dirs[d];
if(!dir.isEmpty() && !dir.endsWith(QDir::separator()))
if (!dir.isEmpty() && !dir.endsWith(QLatin1Char('/')))
dir += "/";
QDir qdir(dir);
@ -2411,14 +2409,13 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QHash<QS
parser.line_no);
return false;
}
QString file = args.first();
file = Option::fixPathToLocalOS(file);
QString file = Option::normalizePath(args.first());
if(QFile::exists(file))
return true;
//regular expression I guess
QString dirstr = qmake_getpwd();
int slsh = file.lastIndexOf(QDir::separator());
int slsh = file.lastIndexOf(QLatin1Char('/'));
if(slsh != -1) {
dirstr = file.left(slsh+1);
file = file.right(file.length() - slsh - 1);
@ -2580,7 +2577,7 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QHash<QS
bool ret = false;
QHash<QString, QStringList> tmp;
if(doProjectInclude(Option::fixPathToLocalOS(args[0]), IncludeFlagNewParser, tmp) == IncludeSuccess) {
if(doProjectInclude(Option::normalizePath(args[0]), IncludeFlagNewParser, tmp) == IncludeSuccess) {
if(tmp.contains("QMAKE_INTERNAL_INCLUDED_FILES")) {
QStringList &out = place["QMAKE_INTERNAL_INCLUDED_FILES"];
const QStringList &in = tmp["QMAKE_INTERNAL_INCLUDED_FILES"];
@ -2658,8 +2655,7 @@ QMakeProject::doProjectTest(QString func, QList<QStringList> args_list, QHash<QS
parser.line_no, func_desc.toLatin1().constData());
return false;
}
QString file = args.first();
file = Option::fixPathToLocalOS(file);
QString file = Option::normalizePath(args.first());
uchar flags = IncludeFlagNone;
if(!include_statement)
flags |= IncludeFlagFeature;