add support for returning the command's exit status to $$system()

... and make use of it in qtRunLoggedCommand().

Change-Id: I242dfde344f555800cef1f55d3cb85418a93277f
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Oswald Buddenhagen 2016-07-15 18:09:24 +02:00 committed by Lars Knoll
parent 62838f07d4
commit 0eff800e81
5 changed files with 28 additions and 15 deletions

View File

@ -32,16 +32,13 @@ defineTest(qtLog) {
defineTest(qtRunLoggedCommand) { defineTest(qtRunLoggedCommand) {
qtLog($$1) qtLog($$1)
write_file($${QMAKE_CONFIG_LOG}.part, "")
result = false
system("$$1 > \"$${QMAKE_CONFIG_LOG}.part\" 2>&1"): result = true
output = $$cat($${QMAKE_CONFIG_LOG}.part, blob)
output = $$system("$$1 2>&1", blob, result)
write_file($${QMAKE_CONFIG_LOG}, output, append) write_file($${QMAKE_CONFIG_LOG}, output, append)
$$QMAKE_CONFIG_VERBOSE: log($$output) $$QMAKE_CONFIG_VERBOSE: log($$output)
return($$result) !equals(result, 0): return(false)
return(true)
} }
isEmpty(QMAKE_CONFIG_TESTS_DIR): QMAKE_CONFIG_TESTS_DIR = $$_PRO_FILE_PWD_/config.tests isEmpty(QMAKE_CONFIG_TESTS_DIR): QMAKE_CONFIG_TESTS_DIR = $$_PRO_FILE_PWD_/config.tests

View File

@ -3138,7 +3138,7 @@
See also \l{fn_size}{size()}. See also \l{fn_size}{size()}.
\section2 system(command[, mode]) \section2 system(command[, mode[, stsvar]])
You can use this variant of the \c system function to obtain stdout from the You can use this variant of the \c system function to obtain stdout from the
command and assign it to a variable. command and assign it to a variable.
@ -3147,6 +3147,11 @@
\snippet code/doc_src_qmake-manual.pro 72 \snippet code/doc_src_qmake-manual.pro 72
If you pass \c stsvar, the command's exit status will be stored in that
variable. If the command crashes, the status will be -1, otherwise a
non-negative exit code of the command's choosing. Usually, comparing
the status with zero (success) is sufficient.
See also the test variant of \l{system(command)}{system()}. See also the test variant of \l{system(command)}{system()}.
\section2 system_path(path) \section2 system_path(path)

View File

@ -450,12 +450,13 @@ void QMakeEvaluator::runProcess(QProcess *proc, const QString &command) const
} }
#endif #endif
QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const QByteArray QMakeEvaluator::getCommandOutput(const QString &args, int *exitCode) const
{ {
QByteArray out; QByteArray out;
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
QProcess proc; QProcess proc;
runProcess(&proc, args); runProcess(&proc, args);
*exitCode = (proc.exitStatus() == QProcess::NormalExit) ? proc.exitCode() : -1;
QByteArray errout = proc.readAllStandardError(); QByteArray errout = proc.readAllStandardError();
# ifdef PROEVALUATOR_FULL # ifdef PROEVALUATOR_FULL
// FIXME: Qt really should have the option to set forwarding per channel // FIXME: Qt really should have the option to set forwarding per channel
@ -483,7 +484,12 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const
break; break;
out += QByteArray(buff, read_in); out += QByteArray(buff, read_in);
} }
QT_PCLOSE(proc); int ec = QT_PCLOSE(proc);
# ifdef Q_OS_WIN
*exitCode = ec >= 0 ? ec : -1;
# else
*exitCode = WIFEXITED(ec) ? WEXITSTATUS(ec) : -1;
# endif
} }
# ifdef Q_OS_WIN # ifdef Q_OS_WIN
out.replace("\r\n", "\n"); out.replace("\r\n", "\n");
@ -871,8 +877,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
break; break;
case E_SYSTEM: case E_SYSTEM:
if (!m_skipLevel) { if (!m_skipLevel) {
if (args.count() < 1 || args.count() > 2) { if (args.count() < 1 || args.count() > 3) {
evalError(fL1S("system(execute) requires one or two arguments.")); evalError(fL1S("system(command, [mode], [stsvar]) requires one to three arguments."));
} else { } else {
bool blob = false; bool blob = false;
bool lines = false; bool lines = false;
@ -885,7 +891,12 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive)) else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive))
lines = true; lines = true;
} }
QByteArray bytes = getCommandOutput(args.at(0).toQString(m_tmp2)); int exitCode;
QByteArray bytes = getCommandOutput(args.at(0).toQString(m_tmp2), &exitCode);
if (args.count() > 2 && !args.at(2).isEmpty()) {
m_valuemapStack.top()[args.at(2).toKey()] =
ProStringList(ProString(QString::number(exitCode)));
}
if (lines) { if (lines) {
QTextStream stream(bytes); QTextStream stream(bytes);
while (!stream.atEnd()) while (!stream.atEnd())

View File

@ -240,7 +240,7 @@ public:
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
void runProcess(QProcess *proc, const QString &command) const; void runProcess(QProcess *proc, const QString &command) const;
#endif #endif
QByteArray getCommandOutput(const QString &args) const; QByteArray getCommandOutput(const QString &args, int *exitCode) const;
QMakeEvaluator *m_caller; QMakeEvaluator *m_caller;
#ifdef PROEVALUATOR_CUMULATIVE #ifdef PROEVALUATOR_CUMULATIVE

View File

@ -1326,9 +1326,9 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
<< true; << true;
QTest::newRow("$$system(): bad number of arguments") QTest::newRow("$$system(): bad number of arguments")
<< "VAR = $$system(1, 2, 3)" << "VAR = $$system(1, 2, 3, 4)"
<< "VAR =" << "VAR ="
<< "##:1: system(execute) requires one or two arguments." << "##:1: system(command, [mode], [stsvar]) requires one to three arguments."
<< true; << true;
QTest::newRow("$$unique()") QTest::newRow("$$unique()")