summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2019-08-19 14:29:14 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2019-08-20 12:39:16 +0000
commit6d3f236aab08833bda44e1f1528c8a44db864651 (patch)
tree53d651d85d9873c60ade5746eeb5b13cf624069b
parent30dc401429cb8151a738cf33da587ae49db38d58 (diff)
downloadqt-creator-6d3f236aab08833bda44e1f1528c8a44db864651.tar.gz
Utils::Environment: Use expanded values
The Environment class is supposed to support values with references to other variables, but we failed to actually expand them in most places. Fixes: QTCREATORBUG-22687 Change-Id: I108cb59d3b4571471423455240f6f4f1cf64bf05 Reviewed-by: hjk <hjk@qt.io>
-rw-r--r--src/libs/clangsupport/processcreator.cpp2
-rw-r--r--src/libs/utils/environment.cpp11
-rw-r--r--src/libs/utils/environment.h1
-rw-r--r--src/libs/utils/qtcprocess.cpp8
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.cpp2
-rw-r--r--src/plugins/debugger/cdb/cdbengine.cpp4
-rw-r--r--src/plugins/debugger/debuggerruncontrol.cpp2
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp2
-rw-r--r--src/plugins/projectexplorer/makestep.cpp6
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp2
-rw-r--r--src/plugins/projectexplorer/runconfiguration.cpp2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp2
-rw-r--r--src/plugins/qmljstools/qmljsmodelmanager.cpp2
-rw-r--r--src/plugins/qnx/qnxdeviceprocess.cpp6
-rw-r--r--src/plugins/qnx/qnxtoolchain.cpp2
-rw-r--r--src/plugins/remotelinux/linuxdeviceprocess.cpp2
-rw-r--r--src/plugins/remotelinux/makeinstallstep.cpp2
-rw-r--r--tests/auto/environment/tst_environment.cpp24
19 files changed, 58 insertions, 26 deletions
diff --git a/src/libs/clangsupport/processcreator.cpp b/src/libs/clangsupport/processcreator.cpp
index e0147bda6b..a33d28c9c4 100644
--- a/src/libs/clangsupport/processcreator.cpp
+++ b/src/libs/clangsupport/processcreator.cpp
@@ -175,7 +175,7 @@ QProcessEnvironment ProcessCreator::processEnvironment() const
const Utils::Environment &env = m_environment;
for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
if (env.isEnabled(it))
- processEnvironment.insert(it.key(), env.value(it));
+ processEnvironment.insert(it.key(), env.expandedValueForKey(env.key(it)));
}
return processEnvironment;
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index 02c0329714..156f4b1561 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -46,7 +46,7 @@ QProcessEnvironment Environment::toProcessEnvironment() const
QProcessEnvironment result;
for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it) {
if (it.value().second)
- result.insert(it.key(), it.value().first);
+ result.insert(it.key(), expandedValueForKey(key(it)));
}
return result;
}
@@ -184,7 +184,7 @@ QStringList Environment::appendExeExtensions(const QString &executable) const
// Check all the executable extensions on windows:
// PATHEXT is only used if the executable has no extension
if (fi.suffix().isEmpty()) {
- const QStringList extensions = value("PATHEXT").split(';');
+ const QStringList extensions = expandedValueForKey("PATHEXT").split(';');
for (const QString &ext : extensions)
execs << executable + ext.toLower();
@@ -212,6 +212,11 @@ bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) con
return false;
}
+QString Environment::expandedValueForKey(const QString &key) const
+{
+ return expandVariables(value(key));
+}
+
FilePath Environment::searchInPath(const QString &executable,
const FilePathList &additionalDirs,
const PathFilter &func) const
@@ -297,7 +302,7 @@ FilePathList Environment::path() const
FilePathList Environment::pathListValue(const QString &varName) const
{
- const QStringList pathComponents = value(varName)
+ const QStringList pathComponents = expandedValueForKey(varName)
.split(OsSpecificAspects::pathListSeparator(m_osType), QString::SkipEmptyParts);
return transform(pathComponents, &FilePath::fromUserInput);
}
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index a233435c4a..0f97c2c3a8 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -76,6 +76,7 @@ public:
bool isSameExecutable(const QString &exe1, const QString &exe2) const;
+ QString expandedValueForKey(const QString &key) const;
QString expandVariables(const QString &input) const;
FilePath expandVariables(const FilePath &input) const;
QStringList expandVariables(const QStringList &input) const;
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
index 7080d218a5..557f77fd34 100644
--- a/src/libs/utils/qtcprocess.cpp
+++ b/src/libs/utils/qtcprocess.cpp
@@ -94,7 +94,7 @@ static void envExpandWin(QString &args, const Environment *env, const QString *p
if (prev >= 0) {
const QString var = args.mid(prev + 1, that - prev - 1).toUpper();
const QString val = (var == cdName && pwd && !pwd->isEmpty())
- ? QDir::toNativeSeparators(*pwd) : env->value(var);
+ ? QDir::toNativeSeparators(*pwd) : env->expandedValueForKey(var);
if (!val.isEmpty()) { // Empty values are impossible, so this is an existence check
args.replace(prev, that - prev + 1, val);
off = prev + val.length();
@@ -394,7 +394,7 @@ static QStringList splitArgsUnix(const QString &args, bool abortOnMeta,
if (abortOnMeta)
goto metaerr; // Assume this is a shell builtin
} else {
- cret += env->value(vit);
+ cret += env->expandedValueForKey(env->key(vit));
}
}
if (!braced)
@@ -444,7 +444,7 @@ static QStringList splitArgsUnix(const QString &args, bool abortOnMeta,
if (abortOnMeta)
goto metaerr; // Assume this is a shell builtin
} else {
- val = env->value(vit);
+ val = env->expandedValueForKey(env->key(vit));
}
}
for (int i = 0; i < val.length(); i++) {
@@ -698,7 +698,7 @@ void QtcProcess::start()
qPrintable(m_commandLine.executable().toString()));
env = m_environment;
- QProcess::setEnvironment(env.toStringList());
+ QProcess::setProcessEnvironment(env.toProcessEnvironment());
} else {
env = Environment::systemEnvironment();
}
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
index ecaefda599..45fd574583 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
@@ -192,7 +192,7 @@ bool CMakeBuildStep::init()
pp->setMacroExpander(bc->macroExpander());
Utils::Environment env = bc->environment();
Utils::Environment::setupEnglishOutput(&env);
- if (!env.value("NINJA_STATUS").startsWith(m_ninjaProgressString))
+ if (!env.expandedValueForKey("NINJA_STATUS").startsWith(m_ninjaProgressString))
env.set("NINJA_STATUS", m_ninjaProgressString + "%o/sec] ");
pp->setEnvironment(env);
pp->setWorkingDirectory(bc->buildDirectory());
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 124c97981b..a5554a3aa8 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -395,10 +395,10 @@ void CdbEngine::setupEngine()
debugger.addArgs({"-srcpath", sourcePaths.join(';')});
QStringList symbolPaths = stringListSetting(CdbSymbolPaths);
- QString symbolPath = sp.inferior.environment.value("_NT_ALT_SYMBOL_PATH");
+ QString symbolPath = sp.inferior.environment.expandedValueForKey("_NT_ALT_SYMBOL_PATH");
if (!symbolPath.isEmpty())
symbolPaths += symbolPath;
- symbolPath = sp.inferior.environment.value("_NT_SYMBOL_PATH");
+ symbolPath = sp.inferior.environment.expandedValueForKey("_NT_SYMBOL_PATH");
if (!symbolPath.isEmpty())
symbolPaths += symbolPath;
debugger.addArgs({"-y", symbolPaths.join(';')});
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index fd83b6acc2..ec80b470cf 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -794,7 +794,7 @@ bool DebuggerRunTool::fixupParameters()
for (const auto &var :
QStringList({"DYLD_IMAGE_SUFFIX", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH"}))
if (rp.inferior.environment.hasKey(var))
- rp.debugger.environment.set(var, rp.inferior.environment.value(var));
+ rp.debugger.environment.set(var, rp.inferior.environment.expandedValueForKey(var));
// validate debugger if C++ debugging is enabled
if (rp.isCppDebugging() && !rp.validationErrors.isEmpty()) {
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index c7d0ce24f4..6874b051c7 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -80,7 +80,7 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
expander->registerPrefix(Constants::VAR_CURRENTBUILD_ENV,
tr("Variables in the current build environment"),
- [this](const QString &var) { return environment().value(var); });
+ [this](const QString &var) { return environment().expandedValueForKey(var); });
updateCacheAndEmitEnvironmentChanged();
connect(target, &Target::kitChanged,
diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp
index cfa7a414bf..dece53ad6f 100644
--- a/src/plugins/projectexplorer/makestep.cpp
+++ b/src/plugins/projectexplorer/makestep.cpp
@@ -231,7 +231,7 @@ bool MakeStep::makeflagsJobCountMismatch() const
const Utils::Environment env = environment(buildConfiguration());
if (!env.hasKey(MAKEFLAGS))
return false;
- Utils::optional<int> makeFlagsJobCount = argsJobCount(env.value(MAKEFLAGS));
+ Utils::optional<int> makeFlagsJobCount = argsJobCount(env.expandedValueForKey(MAKEFLAGS));
return makeFlagsJobCount.has_value() && *makeFlagsJobCount != m_userJobCount;
}
@@ -240,7 +240,7 @@ bool MakeStep::makeflagsContainsJobCount() const
const Utils::Environment env = environment(buildConfiguration());
if (!env.hasKey(MAKEFLAGS))
return false;
- return argsJobCount(env.value(MAKEFLAGS)).has_value();
+ return argsJobCount(env.expandedValueForKey(MAKEFLAGS)).has_value();
}
bool MakeStep::userArgsContainsJobCount() const
@@ -258,7 +258,7 @@ Utils::Environment MakeStep::environment(BuildConfiguration *bc) const
const ToolChain *tc = tcs.isEmpty() ? nullptr : tcs.constFirst();
if (tc && tc->targetAbi().os() == Abi::WindowsOS
&& tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor) {
- env.set(MAKEFLAGS, 'L' + env.value(MAKEFLAGS));
+ env.set(MAKEFLAGS, 'L' + env.expandedValueForKey(MAKEFLAGS));
}
}
return env;
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index de97f3f49b..c90799a5e0 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -700,7 +700,7 @@ static QString winExpandDelayedEnvReferences(QString in, const Utils::Environmen
if (nextPos == -1)
break;
const QString var = in.mid(pos + 1, nextPos - pos - 1);
- const QString replacement = env.value(var.toUpper());
+ const QString replacement = env.expandedValueForKey(var.toUpper());
in.replace(pos, nextPos + 1 - pos, replacement);
pos += replacement.size();
}
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 06b31a9c1c..5a73e5c075 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -1686,7 +1686,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
BuildConfiguration::tr("Variables in the current build environment"),
[](const QString &var) {
if (BuildConfiguration *bc = activeBuildConfiguration())
- return bc->environment().value(var);
+ return bc->environment().expandedValueForKey(var);
return QString();
});
diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp
index 285b35c371..457c15cfed 100644
--- a/src/plugins/projectexplorer/runconfiguration.cpp
+++ b/src/plugins/projectexplorer/runconfiguration.cpp
@@ -190,7 +190,7 @@ RunConfiguration::RunConfiguration(Target *target, Core::Id id)
expander->registerPrefix("CurrentRun:Env", tr("Variables in the current run environment"),
[this](const QString &var) {
const auto envAspect = aspect<EnvironmentAspect>();
- return envAspect ? envAspect->environment().value(var) : QString();
+ return envAspect ? envAspect->environment().expandedValueForKey(var) : QString();
});
expander->registerVariable(Constants::VAR_CURRENTRUN_WORKINGDIR,
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index 3473564c92..b0e482a694 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -649,7 +649,7 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile *
Environment::const_iterator eit = env.constBegin(), eend = env.constEnd();
for (; eit != eend; ++eit)
- m_qmakeGlobals->environment.insert(env.key(eit), env.value(eit));
+ m_qmakeGlobals->environment.insert(env.key(eit), env.expandedValueForKey(env.key(eit)));
m_qmakeGlobals->setCommandLineArguments(rootProFile()->buildDir().toString(), qmakeArgs);
diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp
index 2d996f4985..b33846faf9 100644
--- a/src/plugins/qmljstools/qmljsmodelmanager.cpp
+++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp
@@ -111,7 +111,7 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
// Append QML2_IMPORT_PATH if it is defined in build configuration.
// It enables qmlplugindump to correctly dump custom plugins or other dependent
// plugins that are not installed in default Qt qml installation directory.
- projectInfo.qmlDumpEnvironment.appendOrSet("QML2_IMPORT_PATH", bc->environment().value("QML2_IMPORT_PATH"), ":");
+ projectInfo.qmlDumpEnvironment.appendOrSet("QML2_IMPORT_PATH", bc->environment().expandedValueForKey("QML2_IMPORT_PATH"), ":");
}
}
if (!setPreferDump && qtVersion)
diff --git a/src/plugins/qnx/qnxdeviceprocess.cpp b/src/plugins/qnx/qnxdeviceprocess.cpp
index 0fff4b3585..2b6a0c85c4 100644
--- a/src/plugins/qnx/qnxdeviceprocess.cpp
+++ b/src/plugins/qnx/qnxdeviceprocess.cpp
@@ -59,8 +59,10 @@ QString QnxDeviceProcess::fullCommandLine(const Runnable &runnable) const
fullCommandLine += QString::fromLatin1("cd %1 ; ").arg(QtcProcess::quoteArg(runnable.workingDirectory));
const Environment env = runnable.environment;
- for (auto it = env.constBegin(); it != env.constEnd(); ++it)
- fullCommandLine += QString::fromLatin1("%1='%2' ").arg(env.key(it)).arg(env.value(it));
+ for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
+ fullCommandLine += QString::fromLatin1("%1='%2' ")
+ .arg(env.key(it)).arg(env.expandedValueForKey(env.key(it)));
+ }
fullCommandLine += QString::fromLatin1("%1 & echo $! > %2").arg(cmd).arg(m_pidFile);
diff --git a/src/plugins/qnx/qnxtoolchain.cpp b/src/plugins/qnx/qnxtoolchain.cpp
index 6ad191fbea..158d70e494 100644
--- a/src/plugins/qnx/qnxtoolchain.cpp
+++ b/src/plugins/qnx/qnxtoolchain.cpp
@@ -113,7 +113,7 @@ std::unique_ptr<ToolChainConfigWidget> QnxToolChain::createConfigurationWidget()
void QnxToolChain::addToEnvironment(Environment &env) const
{
- if (env.value("QNX_HOST").isEmpty() || env.value("QNX_TARGET").isEmpty())
+ if (env.expandedValueForKey("QNX_HOST").isEmpty() || env.expandedValueForKey("QNX_TARGET").isEmpty())
setQnxEnvironment(env, QnxUtils::qnxEnvironment(m_sdpPath));
GccToolChain::addToEnvironment(env);
diff --git a/src/plugins/remotelinux/linuxdeviceprocess.cpp b/src/plugins/remotelinux/linuxdeviceprocess.cpp
index 3a1e88d19e..c16a12baee 100644
--- a/src/plugins/remotelinux/linuxdeviceprocess.cpp
+++ b/src/plugins/remotelinux/linuxdeviceprocess.cpp
@@ -94,7 +94,7 @@ QString LinuxDeviceProcess::fullCommandLine(const Runnable &runnable) const
const Environment &env = runnable.environment;
for (auto it = env.constBegin(); it != env.constEnd(); ++it)
- cmd.addArgs(env.key(it) + "='" + env.value(it) + '\'', CommandLine::Raw);
+ cmd.addArgs(env.key(it) + "='" + env.expandedValueForKey(env.key(it)) + '\'', CommandLine::Raw);
if (!runInTerminal())
cmd.addArg("exec");
diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp
index 283d9bff4a..e5636c7ea7 100644
--- a/src/plugins/remotelinux/makeinstallstep.cpp
+++ b/src/plugins/remotelinux/makeinstallstep.cpp
@@ -140,7 +140,7 @@ bool MakeInstallStep::init()
Environment env = processParameters()->environment();
for (auto it = cmd.environment.constBegin(); it != cmd.environment.constEnd(); ++it) {
if (cmd.environment.isEnabled(it))
- env.set(it.key(), cmd.environment.value(it));
+ env.set(it.key(), cmd.environment.expandedValueForKey(cmd.environment.key(it)));
}
processParameters()->setEnvironment(env);
}
diff --git a/tests/auto/environment/tst_environment.cpp b/tests/auto/environment/tst_environment.cpp
index 570f43a75c..74177b5edd 100644
--- a/tests/auto/environment/tst_environment.cpp
+++ b/tests/auto/environment/tst_environment.cpp
@@ -57,6 +57,9 @@ private slots:
void environmentUnsetUnknownWindows();
void environmentUnsetUnknownUnix();
+ void expansion_data();
+ void expansion();
+
void find_data();
void find();
@@ -252,6 +255,27 @@ void tst_Environment::environmentUnsetUnknownUnix()
QCOMPARE(env.toStringList(), QStringList({"Foo=bar", "Hi=HO"}));
}
+void tst_Environment::expansion_data()
+{
+ QTest::addColumn<Utils::OsType>("osType");
+ QTest::addColumn<QString>("eu");
+ QTest::addColumn<QString>("ew");
+
+ QTest::newRow("win") << Utils::OsTypeWindows << "${v}" << "blubb";
+ QTest::newRow("lin") << Utils::OsTypeLinux << "blubb" << "%v%";
+}
+
+void tst_Environment::expansion()
+{
+ QFETCH(Utils::OsType, osType);
+ QFETCH(QString, eu);
+ QFETCH(QString, ew);
+
+ const Environment env(QStringList{"eu=${v}", "ew=%v%", "v=blubb"}, osType);
+ QCOMPARE(env.expandedValueForKey("eu"), eu);
+ QCOMPARE(env.expandedValueForKey("ew"), ew);
+}
+
void tst_Environment::find_data()
{
QTest::addColumn<Utils::OsType>("osType");