make sure that installed meta files are always postprocessed

the problem is that there is no sed command on windows ... so build it
into qmake and invoke that from the generated makefiles. cmake does the
same, after all. ^^

Task-number: QTBUG-33794
Change-Id: Ib7077e18acbc5edd79f714c5779a5ed31ea6c093
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
This commit is contained in:
Oswald Buddenhagen 2013-10-11 16:25:01 +02:00 committed by The Qt Project
parent 580096d611
commit 40d4c1b2ed
4 changed files with 132 additions and 2 deletions

View File

@ -14,3 +14,4 @@ QMAKE_SYMBOLIC_LINK = $$QMAKE_COPY
QMAKE_LN_SHLIB = $$QMAKE_SYMBOLIC_LINK
# xcopy copies the contained files if source is a directory. Deal with it.
CONFIG += copy_dir_files
QMAKE_STREAM_EDITOR = $(QMAKE) -install sed

View File

@ -3331,8 +3331,7 @@ QString MakefileGenerator::installMetaFile(const ProKey &replace_rule, const QSt
{
QString ret;
if (project->isEmpty(replace_rule)
|| project->isActiveConfig("no_sed_meta_install")
|| project->isEmpty("QMAKE_STREAM_EDITOR")) {
|| project->isActiveConfig("no_sed_meta_install")) {
ret += "-$(INSTALL_FILE) \"" + src + "\" \"" + dst + "\"";
} else {
ret += "-$(SED)";

View File

@ -301,6 +301,8 @@ void Win32MakefileGenerator::processVars()
project->values("QMAKE_COPY_FILE").append("$(COPY)");
if(project->isEmpty("QMAKE_COPY_DIR"))
project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i");
if (project->isEmpty("QMAKE_STREAM_EDITOR"))
project->values("QMAKE_STREAM_EDITOR").append("$(QMAKE) -install sed");
if(project->isEmpty("QMAKE_INSTALL_FILE"))
project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)");
if(project->isEmpty("QMAKE_INSTALL_PROGRAM"))

View File

@ -57,6 +57,128 @@
QT_BEGIN_NAMESPACE
#ifdef Q_OS_WIN
struct SedSubst {
QRegExp from;
QString to;
};
Q_DECLARE_TYPEINFO(SedSubst, Q_MOVABLE_TYPE);
static int doSed(int argc, char **argv)
{
QVector<SedSubst> substs;
QList<const char *> inFiles;
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], "-e")) {
if (++i == argc) {
fprintf(stderr, "Error: sed option -e requires an argument\n");
return 3;
}
QString cmd = QString::fromLocal8Bit(argv[i]);
for (int j = 0; j < cmd.length(); j++) {
QChar c = cmd.at(j);
if (c.isSpace())
continue;
if (c != QLatin1Char('s')) {
fprintf(stderr, "Error: unrecognized sed command '%c'\n", c.toLatin1());
return 3;
}
QChar sep = ++j < cmd.length() ? cmd.at(j) : QChar();
bool escaped = false;
int phase = 1;
QStringList phases;
QString curr;
while (++j < cmd.length()) {
c = cmd.at(j);
if (!escaped) {
if (c == QLatin1Char(';'))
break;
if (c == QLatin1Char('\\')) {
escaped = true;
continue;
}
if (c == sep) {
phase++;
phases << curr;
curr.clear();
continue;
}
}
if (phase == 1
&& (c == QLatin1Char('+') || c == QLatin1Char('?')
|| c == QLatin1Char('{') || c == QLatin1Char('}')
|| c == QLatin1Char('(') || c == QLatin1Char(')'))) {
// translate sed rx to QRegExp
escaped ^= 1;
}
if (escaped) {
escaped = false;
curr += QLatin1Char('\\');
}
curr += c;
}
if (escaped) {
fprintf(stderr, "Error: unterminated escape sequence in sed s command\n");
return 3;
}
if (phase != 3) {
fprintf(stderr, "Error: sed s command requires three arguments (%d, %c, %s)\n", phase, sep.toLatin1(), qPrintable(curr));
return 3;
}
if (curr != QLatin1String("g")) {
fprintf(stderr, "Error: sed s command must be used with the g option (only)\n");
return 3;
}
SedSubst subst;
subst.from = QRegExp(phases.at(0));
subst.to = phases.at(1);
substs << subst;
}
} else if (argv[i][0] == '-' && argv[i][1] != 0) {
fprintf(stderr, "Error: unrecognized sed option '%s'\n", argv[i]);
return 3;
} else {
inFiles << argv[i];
}
}
if (inFiles.isEmpty())
inFiles << "-";
foreach (const char *inFile, inFiles) {
FILE *f;
if (!strcmp(inFile, "-")) {
f = stdin;
} else if (!(f = fopen(inFile, "r"))) {
perror(inFile);
return 1;
}
QTextStream is(f);
while (!is.atEnd()) {
QString line = is.readLine();
for (int i = 0; i < substs.size(); i++)
line.replace(substs.at(i).from, substs.at(i).to);
puts(qPrintable(line));
}
if (f != stdin)
fclose(f);
}
return 0;
}
static int doInstall(int argc, char **argv)
{
if (!argc) {
fprintf(stderr, "Error: -install requires further arguments\n");
return 3;
}
if (!strcmp(argv[0], "sed"))
return doSed(argc - 1, argv + 1);
fprintf(stderr, "Error: unrecognized -install subcommand '%s'\n", argv[0]);
return 3;
}
#endif // Q_OS_WIN
/* This is to work around lame implementation on Darwin. It has been noted that the getpwd(3) function
is much too slow, and called much too often inside of Qt (every fileFixify). With this we use a locally
cached copy because I can control all the times it is set (because Qt never sets the pwd under me).
@ -85,6 +207,12 @@ int runQMake(int argc, char **argv)
// This is particularly important for things like QtCreator and scripted builds.
setvbuf(stdout, (char *)NULL, _IONBF, 0);
#ifdef Q_OS_WIN
// Workaround for inferior/missing command line tools on Windows: make our own!
if (argc >= 2 && !strcmp(argv[1], "-install"))
return doInstall(argc - 2, argv + 2);
#endif
QMakeVfs vfs;
Option::vfs = &vfs;
QMakeGlobals globals;